如何在进程之间共享内核对象
2010-07-16 22:13
399 查看
本文说明如何构造安全描述符,以授予给定组对内核对象的访问权限,使该对象能够在以不同用户帐户运行的进程之间共享。
回到顶端
本文中的示例代码非常特定,因为它授予经过身份验证的用户 组对互斥体的访问权限。这段代码使用了大量的安全 API 来构造互斥体的安全描述符。有关这些安全函数的完整文档,请参阅 MSDN Library 中 Platform SDK 文档的“Access Control”(访问控制)部分:http://msdn.microsoft.com/library/en-us/security/hh/winbase/accctrl_2hf0.asp您必须完全了解这些调用(通常情况下还包括访问控制技术),以便针对其他用户、组和内核对象改编代码。
回到顶端
出于说明目的,此示例代码使用了通用访问权限。这些通用权限利用了可用于所有内核对象的通用映射。在实际的应用程序中,创建对象时最好使用对象特定的访问权限。
给定的资源管理器在映射到对象特定的访问权限时,可能会解释给定的通用权限集,以包括其他标准访问权限。例如,为互斥体指定 GENERIC_READ、GENERIC_WRITE 和 GENERIC_EXECUTE 权限相当于指定对象特定的权限 MUTEX_MODIFY_STATE 和 SYNCHRONIZE。因此,其他线程要想获得互斥体的句柄,只能通过在 OpenMutex() 中为 dwDesiredAccess 参数指定 MUTEX_MODIFY_STATE 和/或 SYNCHRONIZE。使用 MUTEX_ALL_ACCESS 打开互斥体的尝试将失败,并显示错误代码 5 (ERROR_ACCESS_DENIED)。
回到顶端
更多信息
有时,服务必须创建可由运行在不同用户帐户下的进程访问的内核对象。要允许以这种方式共享对象,服务必须使用明确授权用户对象访问权限的安全描述符来创建对象。或者,安全描述符可以授予对整个用户组的访问权限。本文中的示例代码非常特定,因为它授予经过身份验证的用户 组对互斥体的访问权限。这段代码使用了大量的安全 API 来构造互斥体的安全描述符。有关这些安全函数的完整文档,请参阅 MSDN Library 中 Platform SDK 文档的“Access Control”(访问控制)部分:http://msdn.microsoft.com/library/en-us/security/hh/winbase/accctrl_2hf0.asp您必须完全了解这些调用(通常情况下还包括访问控制技术),以便针对其他用户、组和内核对象改编代码。
回到顶端
示例代码
以下示例代码说明了如何构造安全描述符,以授予经过身份验证的用户 组 GENERIC_READ、GENERIC_WRITE 和 GENERIC_EXECUTE 权限。新构造的安全描述符随即应用于互斥体。出于说明目的,此示例代码使用了通用访问权限。这些通用权限利用了可用于所有内核对象的通用映射。在实际的应用程序中,创建对象时最好使用对象特定的访问权限。
给定的资源管理器在映射到对象特定的访问权限时,可能会解释给定的通用权限集,以包括其他标准访问权限。例如,为互斥体指定 GENERIC_READ、GENERIC_WRITE 和 GENERIC_EXECUTE 权限相当于指定对象特定的权限 MUTEX_MODIFY_STATE 和 SYNCHRONIZE。因此,其他线程要想获得互斥体的句柄,只能通过在 OpenMutex() 中为 dwDesiredAccess 参数指定 MUTEX_MODIFY_STATE 和/或 SYNCHRONIZE。使用 MUTEX_ALL_ACCESS 打开互斥体的尝试将失败,并显示错误代码 5 (ERROR_ACCESS_DENIED)。
#include <windows.h> #include <stdio.h> // The following function initializes the supplied security descriptor // with a DACL that grants the Authenticated Users group GENERIC_READ, // GENERIC_WRITE, and GENERIC_EXECUTE access. // // The function returns NULL if any of the access control APIs fail. // Otherwise, it returns a PVOID pointer that should be freed by calling // FreeRestrictedSD() after the security descriptor has been used to // create the object. PVOID BuildRestrictedSD(PSECURITY_DESCRIPTOR pSD) { DWORD dwAclLength; PSID pAuthenticatedUsersSID = NULL; PACL pDACL = NULL; BOOL bResult = FALSE; PACCESS_ALLOWED_ACE pACE = NULL; SID_IDENTIFIER_AUTHORITY siaNT = SECURITY_NT_AUTHORITY; SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION; __try { // initialize the security descriptor if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) { printf("InitializeSecurityDescriptor() failed with error %d\n", GetLastError()); __leave; } // obtain a sid for the Authenticated Users Group if (!AllocateAndInitializeSid(&siaNT, 1, SECURITY_AUTHENTICATED_USER_RID, 0, 0, 0, 0, 0, 0, 0, &pAuthenticatedUsersSID)) { printf("AllocateAndInitializeSid() failed with error %d\n", GetLastError()); __leave; } // NOTE: // // The Authenticated Users group includes all user accounts that // have been successfully authenticated by the system. If access // must be restricted to a specific user or group other than // Authenticated Users, the SID can be constructed using the // LookupAccountSid() API based on a user or group name. // calculate the DACL length dwAclLength = sizeof(ACL) // add space for Authenticated Users group ACE + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(pAuthenticatedUsersSID); // allocate memory for the DACL pDACL = (PACL) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwAclLength); if (!pDACL) { printf("HeapAlloc() failed with error %d\n", GetLastError()); __leave; } // initialize the DACL if (!InitializeAcl(pDACL, dwAclLength, ACL_REVISION)) { printf("InitializeAcl() failed with error %d\n", GetLastError()); __leave; } // add the Authenticated Users group ACE to the DACL with // GENERIC_READ, GENERIC_WRITE, and GENERIC_EXECUTE access if (!AddAccessAllowedAce(pDACL, ACL_REVISION, GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE, pAuthenticatedUsersSID)) { printf("AddAccessAllowedAce() failed with error %d\n", GetLastError()); __leave; } // set the DACL in the security descriptor if (!SetSecurityDescriptorDacl(pSD, TRUE, pDACL, FALSE)) { printf("SetSecurityDescriptorDacl() failed with error %d\n", GetLastError()); __leave; } bResult = TRUE; } __finally { if (pAuthenticatedUsersSID) FreeSid(pAuthenticatedUsersSID); } if (bResult == FALSE) { if (pDACL) HeapFree(GetProcessHeap(), 0, pDACL); pDACL = NULL; } return (PVOID) pDACL; } // The following function frees memory allocated in the // BuildRestrictedSD() function VOID FreeRestrictedSD(PVOID ptr) { if (ptr) HeapFree(GetProcessHeap(), 0, ptr); return; } void main(void) { SECURITY_ATTRIBUTES sa; SECURITY_DESCRIPTOR sd; PVOID ptr; HANDLE hMutex; // build a restricted security descriptor ptr = BuildRestrictedSD(&sd); if (!ptr) { printf("BuildRestrictedSD() failed\n"); return; } // create a mutex using the security descriptor sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = &sd; sa.bInheritHandle = FALSE; hMutex = CreateMutex(&sa, FALSE, "RestrictedMutex"); if (!hMutex) printf("CreateMutex() failed with error %d\n", GetLastError()); // free the memory allocated by BuildRestrictedSD FreeRestrictedSD(ptr); // use the mutex ... printf("Press the return key to close the mutex handle...\n"); getchar(); // close the mutex handle CloseHandle(hMutex); }
相关文章推荐
- 如何在进程之间共享内核对象
- Windows进程共享内核对象的3种方法
- -跨越进程边界共享内核对象【对象句柄的继承性】
- 进程间共享内核对象句柄[继承方式]
- windows笔记-跨越进程边界共享内核对象【对象句柄的继承性】
- Windows进程共享内核对象的3种方法
- windows笔记-跨越进程边界共享内核对象【对象句柄的继承性】
- windows笔记-跨越进程边界共享内核对象【复制对象句柄】
- 3.3 跨越进程边界共享内核对象
- 跨进程边界共享内核对象
- 跨进程共享内核对象方法:命名对象
- 多进程共享内核对象的方法
- 如何创建一个在任何进程任何帐户任何会话都能存取的内核对象
- 共享跨越进程边界内核对象的方法?
- 内核对象 复制对象句柄 DuplicateHandle 跨进程边界共享内核对象
- C++ const对象如何在多文件之间共享
- windows笔记-跨越进程边界共享内核对象【对象句柄的继承性】
- windows笔记-跨越进程边界共享内核对象【命名对象】
- 请教:如何在WebService和调用方之间共享对象定义
- Chapter03-跨进程共享内核对象