最简单的方法是让您的服务创建共享内存,并在CreateFileMapping中指定一个DACL,以授予常规用户读取共享内存的权限。
普通用户没有创建全局特权,但服务可以具有此特权。如果您必须让您的用户创建共享内存,然后让服务对其进行探测,则可以使用IPC方案,您的用户代码将消息发送到包含文件映射句柄的服务,然后该服务将调用DuplicateHandle以获取参考它。这将需要您的服务以调试权限运行。
创建DACL的最简单方法是使用ConvertStringSecurityDescriptorToSecurityDescriptor,该字符串采用名为SDDL的格式指定ACL。
Writing Secure Code包含了一个关于使用SDDL创建DACL的精彩篇章。
// Error handling removed for brevity
SECURITY_ATTRIBUTES security;
ZeroMemory(&security, sizeof(security));
security.nLength = sizeof(security);
ConvertStringSecurityDescriptorToSecurityDescriptor(
L"D:P(A;OICI;GA;;;SY)(A;OICI;GA;;;BA)(A;OICI;GR;;;IU)",
SDDL_REVISION_1,
&security.lpSecurityDescriptor,
NULL);
CreateFileMapping(INVALID_HANDLE_VALUE, &security,
PAGE_READWRITE, sizeHigh, sizeLow, L"Global\\MyObject");
LocalFree(securityDescriptor.lpSecurityDescriptor);
“d:P(A; OICI; GA ;;; SY)(A; OICI; GA ;;; BA)(A; OICI; GR ;;; IU)” 指定DACL。 D:P表示这是一个DACL(而不是SACL,你很少使用SACL),接下来是几个控制谁可以访问的ACE字符串。每个是A(允许)并允许对象并包含继承(OICI)。首先授予系统(SY)和管理员(BA,内置管理员)的所有访问权限(GA - 全部授予)。最后的授予读取(GR)给交互式用户(IU),这是实际登录到会话的用户。
完成此操作后,普通用户应该能够调用OpenFileMapping获取共享映射的句柄,并能够将其映射到其进程中。由于普通用户对该对象的权限有限,因此他们必须确保将其打开并将其映射为只读访问。
如果用户需要write-acccess,则可以将GR替换为GWGR。请注意,这是不安全的 - 当您的服务正在阅读并尝试解析信息时,受限用户将能够修改共享内存,从而导致服务崩溃。
不幸的是,普通用户也必须有写权限 – Clay 2009-05-22 16:55:46