ID: Q193073
The information in this article applies to:
- Microsoft Windows NT 4.0
To share objects (mutex, event, and so forth) that you create under another security context, you can do one of the following:
If you have access to the source code, the easiest method is to place a NULL DACL in the security descriptor when the object is created. For additional information about how to use a NULL DACL, please see the following article in the Microsoft Knowledge Base:
ARTICLE-ID: Q106387
TITLE : HOWTO: Share Objects with a Service
Alternatively, you can add an access-allowed ACE to the object so that it
can be appropriately shared. For additional information about how to add an
access-allowed ACE to a file object, please see the following article in
the Microsoft Knowledge Base:
ARTICLE-ID: Q102102
TITLE : HOWTO: Add an Access-Allowed ACE to a File
However, if you don't have access to the source code, and the object was
created to use the default DACL (that is, passing a NULL pointer for the
security descriptor parameter), you may not be able to access the object.
For example, you have a third-party DLL that you use in your service
program and this DLL makes the following API call:
hMutex = CreateMutex(NULL, FALSE, "ThirdPartyDLLMutex");
If the service is installed under the Local System account, the mutex
should be successfully created with the default DACL of the Local System
account when the service starts.
Now, suppose you also use this DLL in one of your interactive process. In this scenario, the CreateMutex() call listed above will fail with error code 5 (ERROR_ACCESS_DENIED) and the third-party DLL might or might not be able to continue. The problem is that the first parameter has been hard coded as NULL, which means that the mutex will be created with the Default DACL. The default DACL only allows access to Local System account and the Owner.
To work around this problem, you can modify the default DACL to grant access to the desired individuals or groups so that the default DACL already contains the desired access permissions when you use it to create any object.
If the DLL is implicitly linked to your service program, this work around will not entirely solve the DLL problem mentioned above because the DLL might make the CreateMutex() call before you have a chance to modify the default DACL. In this case, you can do one of the following:
// Somewhere in your service program.
...
...
...
SECURITY_ATTRIBUTES sa;
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&sa, sizeof(sa));
sa.nLength = sizeof(sa);
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
if (!CreateProcess(NULL, "MyProg.exe", &sa, &sa, TRUE, CREATE_SUSPENDED,
NULL, NULL, &si, &pi))
{
return GetLastError();
}
else
{
ModifyDefaultDacl(pi.hProcess);
ResumeThread(pi.hThread);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
// Continue processing.
...
...
...
/*++
Function : ModifyDefaultDacl
Synopsis : Add EVERYONE ACE to the process token DACL.
Parameter: hProcess - Handle to process to modify the DACL.
Return : 0 if successful, otherwise error code.
--*/
DWORD ModifyDefaultDacl(HANDLE hProcess)
{
int i;
ACL_SIZE_INFORMATION asi;
ACCESS_ALLOWED_ACE *pace;
DWORD dwNewAclSize;
DWORD dwSize = 0;
DWORD dwTokenInfoLength = 0;
DWORD dwResult = 0;
HANDLE hToken = NULL;
PACL pacl = NULL;
PSID psidEveryone = NULL;
SID_IDENTIFIER_AUTHORITY siaWorld = SECURITY_WORLD_SID_AUTHORITY;
TOKEN_DEFAULT_DACL tddNew;
TOKEN_DEFAULT_DACL *ptdd = NULL;
TOKEN_INFORMATION_CLASS tic = TokenDefaultDacl;
__try
{
//
// Obtain an access token.
//
if (!OpenProcessToken(hProcess, TOKEN_QUERY |
TOKEN_ADJUST_DEFAULT, &hToken))
{
dwResult = GetLastError();
__leave;
}
//
// Obtain buffer size for DACL information.
//
if (!GetTokenInformation(hToken, tic, (LPVOID)NULL,
dwTokenInfoLength, &dwSize))
{
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
ptdd = (TOKEN_DEFAULT_DACL *) LocalAlloc(LPTR, dwSize);
if (ptdd == NULL)
{
dwResult = GetLastError();
__leave;
}
if (!GetTokenInformation(hToken, tic, (LPVOID)ptdd, dwSize,
&dwSize))
{
dwResult = GetLastError();
__leave;
}
}
else
{
dwResult = GetLastError();
__leave;
}
}
//
// Obtain ACL information.
//
if (!GetAclInformation(ptdd->DefaultDacl, (LPVOID)&asi,
(DWORD)sizeof(ACL_SIZE_INFORMATION),
AclSizeInformation))
{
dwResult = GetLastError();
__leave;
}
//
// Create SID for the Everyone group.
//
if (!AllocateAndInitializeSid(&siaWorld, 1, SECURITY_WORLD_RID, 0,
0, 0, 0, 0, 0, 0, &psidEveryone))
{
dwResult = GetLastError();
__leave;
}
//
// Compute the size of the new ACL.
//
dwNewAclSize = asi.AclBytesInUse + sizeof(ACCESS_ALLOWED_ACE) +
GetLengthSid(psidEveryone) - sizeof(DWORD);
//
// Allocate buffer for the new ACL.
//
pacl = (PACL) LocalAlloc(LPTR, dwNewAclSize);
if (pacl == NULL)
{
dwResult = GetLastError();
__leave;
}
//
// Intialize the ACL.
//
if (!InitializeAcl(pacl, dwNewAclSize, ACL_REVISION))
{
dwResult = GetLastError();
__leave;
}
//
// Loop through all the ACEs.
//
for (i = 0; i < (int) asi.AceCount; i++)
{
//
// Get current ACE.
//
if (!GetAce(ptdd->DefaultDacl, i, (LPVOID *)&pace))
{
dwResult = GetLastError();
__leave;
}
//
// Build the new ACL.
//
if (!AddAce(pacl, ACL_REVISION, MAXDWORD, pace,
((PACE_HEADER)pace)->AceSize))
{
dwResult = GetLastError();
__leave;
}
}
//
// Add the new ACE.
//
if (!AddAccessAllowedAce(pacl, ACL_REVISION, GENERIC_ALL,
psidEveryone))
{
dwResult = GetLastError();
__leave;
}
//
// Set the new Default DACL.
//
tddNew.DefaultDacl = pacl;
if (!SetTokenInformation(hToken, tic, (LPVOID)&tddNew,
dwNewAclSize))
{
dwResult = GetLastError();
__leave;
}
}
__finally
{
//
// Free the buffer for the sid.
//
if (psidEveryone)
{
FreeSid(psidEveryone);
}
//
// Free the buffers.
//
if (pacl)
{
LocalFree((HLOCAL)pacl);
}
if (ptdd)
{
LocalFree((HLOCAL)ptdd);
}
//
// Close the access token.
//
if (hToken)
{
CloseHandle(hToken);
}
}
return dwResult;
}
For additional information, please see the following article in the Microsoft Knowledge Base:
ARTICLE-ID: Q106387
TITLE : HOWTO: Share Objects with a Service
ARTICLE-ID: Q102102
TITLE : HOWTO: Add an Access-Allowed ACE to a File
Additional query words:
Keywords : kbAccCtrl kbAPI kbSDKPlatform kbSDKWin32 kbSecurity kbCodeSam kbfaq
Issue type : kbhowto
Last Reviewed: September 27, 1998