Better would be to derive from WaitHandle but following class could give you
a head start :
[StructLayout(La youtKind.Sequen tial)]
internal struct SECURITY_DESCRI PTOR
{
public byte Revision;
public byte Sbz1;
public ushort Control;
public uint Owner;
public uint Group;
public uint Sacl;
public uint Dacl;
}
[StructLayout(La youtKind.Sequen tial)]
public struct SECURITY_ATTRIB UTES
{
internal int nLength;
internal IntPtr pSecurityDescri ptor;
internal bool bInheritHandle;
}
class Win32NamedMutex : IDisposable
{
[DllImport("kern el32", SetLastError=tr ue),
SuppressUnmanag edCodeSecurityA ttribute]
static extern IntPtr CreateMutex(
ref SECURITY_ATTRIB UTES pSecurityAttrib utes, // pointer to sa
bool bInitialOwner,
string lpName
);
[DllImport("kern el32", SetLastError=tr ue),
SuppressUnmanag edCodeSecurityA ttribute]
static extern bool ReleaseMutex(
IntPtr handle
);
[DllImport("adva pi32", SetLastError=tr ue),
SuppressUnmanag edCodeSecurityA ttribute]
static extern bool InitializeSecur ityDescriptor(
IntPtr pSecurityDescri ptor, // pointer to sd
int dwRevision // revision must be SECURITY_DESCRI PTOR_REVISION (1)
);
[DllImport("adva pi32", SetLastError=tr ue),
SuppressUnmanag edCodeSecurityA ttribute]
static extern bool SetSecurityDesc riptorDacl(
IntPtr pSecurityDescri ptor, // pointer to sd
bool bDaclPresent,
IntPtr pDacl,
bool bDaclDefaulted
);
[DllImport("adva pi32", SetLastError=tr ue),
SuppressUnmanag edCodeSecurityA ttribute]
static extern bool IsValidSecurity Descriptor(IntP tr pSecurityDescri ptor);
// pointer to sd
SECURITY_ATTRIB UTES sa;
SECURITY_DESCRI PTOR sd;
IntPtr pSd;
IntPtr handle;
private bool disposed = false;
public IntPtr CreateNamedMute x(string name, ref bool initialOwner)
{
handle = IntPtr.Zero;
if (CreateSaWithNu llDaclSd())
{
handle = CreateMutex(ref sa, initialOwner, name);
if (handle == IntPtr.Zero)
{
Console.WriteLi ne("{0}", Marshal.GetLast Win32Error());
}
else {
if(Marshal.GetL astWin32Error() == 183) //ERROR_ALREADY_E XISTS
initialOwner = false;
}
}
return handle;
}
private bool CreateSdWithNul lDacl()
{
bool ret = false;
sd = new SECURITY_DESCRI PTOR();
pSd = Marshal.AllocHG lobal( Marshal.SizeOf( sd) );
Marshal.Structu reToPtr(sd, pSd, true);
// Initialize SD with revision level 1 (mandatory)
if(InitializeSe curityDescripto r(pSd, 1))
{
// set NULL DACL in SD, this sets "everyone" access privileges
if (SetSecurityDes criptorDacl(pSd , true, IntPtr.Zero, true))
{
ret = IsValidSecurity Descriptor(pSd) ; // set ret = true if valid SD
}
else {ret = false;}
}
return ret;
}
private bool CreateSaWithNul lDaclSd()
{
if (CreateSdWithNu llDacl())
{
sa = new SECURITY_ATTRIB UTES();
sa.pSecurityDes criptor = pSd;
sa.bInheritHand le = false;
sa.nLength = Marshal.SizeOf( sa);
return true;
}
return false;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFina lize(this);
}
protected virtual void Dispose(bool disposing)
{
if(!this.dispos ed)
{
// Release unmanaged Mutex.
ReleaseMutex(th is.handle);
handle = IntPtr.Zero;
}
disposed = true;
}
~Win32NamedMute x()
{
Dispose(false);
// BUG BUG, finalizer should never be called. Object should be Disposed
by client.
// Failed to call dispose, will throw in debug build
#if DEBUG
throw new Exception("Fina lizer called on disposable object");
#endif
}
}
Use case:
IntPtr handle;
bool owner = true;
using(Win32Name dMutex ws = new Win32NamedMutex ())
{
handle = ws.CreateNamedM utex("Global\\m yMutex", ref owner);
if (owner != true)
{
// already owned wait until handle signaled
AutoResetEvent wh = new AutoResetEvent( false);
wh.Handle = handle;
wh.WaitOne();
}
else
{
.....// Do some work while owning Mutex
}
} // release mutex resources
.....
Willy.
"Chris B." <ch********@hot mail.com> wrote in message
news:uM******** *****@TK2MSFTNG P12.phx.gbl...
If anyone can figure out how to implement the following C++ function in C#
using interop, I'd be very appreciative.
I have not been successful in getting it to work correctly using interop
(without using unsafe code) because of the pointer issues of the
structure.
Thanks,
Chris
//------------------------------------------------------------
HANDLE __stdcall CreateAllAccess Mutex(BOOL bInitialOwner, const wchar_t
*pszName)
{
HANDLE rc = NULL;
SECURITY_DESCRI PTOR sd;
SECURITY_ATTRIB UTES sa;
// A security descriptor with a NULL DACL must be used because this
function can be initially called
// by an application running as a service which will create the mutex
with
a default security
// descriptor that does not allow user-mode applications to open the
mutex
by name with CreateMutex.
if (InitializeSecu rityDescriptor( &sd, SECURITY_DESCRI PTOR_REVISION)) //
initialize the security descriptor
{
if (SetSecurityDes criptorDacl(&sd , TRUE, NULL, FALSE)) // add a NULL
DACL to the security descriptor
{
sa.nLength = sizeof(sa);
sa.lpSecurityDe scriptor = &sd;
sa.bInheritHand le = FALSE;
rc = CreateMutexW(&s a, bInitialOwner, pszName);
}
}
return rc;
}