【发布时间】:2014-11-19 01:54:33
【问题描述】:
我正在开发一个开源 .NET 程序集 (WinSCP .NET assembly),它会生成一个原生 (C++) 应用程序并通过事件和文件映射对象与其通信。
程序集使用Process 类生成应用程序,没有特殊设置。程序集创建少量事件(使用EventWaitHandle)和文件映射(使用PInvoked CreateFileMapping),应用程序使用OpenEvent 和OpenFileMapping“打开”这些事件。
在大多数情况下都可以正常工作。但现在我有一个用户在 Windows Server 2008 R2 64 位上使用 ASPX 应用程序的程序集。
在他的情况下,OpenEvent 和 OpenFileMapping 返回 NULL,GetLastError 返回 ERROR_ACCESS_DENIED。
我已尝试通过显式授予当前用户对事件对象的必要权限和应用程序代码来改进汇编代码,以根据Microsoft Docs example 仅需要真正需要的访问权限(而不是原始EVENT_ALL_ACCESS)。它没有帮助。所以我什至没有费心为文件映射对象尝试同样的方法。
创建事件的 C# 代码是:
EventWaitHandleSecurity security = new EventWaitHandleSecurity();
string user = Environment.UserDomainName + "\\" + Environment.UserName;
EventWaitHandleAccessRule rule;
rule =
new EventWaitHandleAccessRule(
user, EventWaitHandleRights.Synchronize | EventWaitHandleRights.Modify,
AccessControlType.Allow);
security.AddAccessRule(rule);
rule =
new EventWaitHandleAccessRule(
user, EventWaitHandleRights.ChangePermissions, AccessControlType.Deny);
security.AddAccessRule(rule);
new EventWaitHandle(
false, EventResetMode.AutoReset, name, out createdNew, security);
“打开”事件的 C++ 代码是:
OpenEvent(EVENT_MODIFY_STATE, false, name);
(对于其他事件,访问级别为SYNCHRONIZE,取决于需要)。
我还尝试在对象名称中添加Global\ 前缀。不出所料,这并没有解决问题。
有谁知道是什么导致OpenEvent(或CreateFileMapping)中的“访问被拒绝”错误?
【问题讨论】:
-
怀疑你修复了,ASP.NET 应用程序默认使用有限的用户帐户运行。一些background here.
-
抱歉,我没有正确理解这个场景。问题可能是您在受限制的令牌下运行,即进程可以以不具有运行的用户帐户的完整访问权限的方式运行。您可能需要检查安全令牌以找出启用了哪些 SID 以便适当地设置对象的权限;抱歉,我不确定如何在 .NET 中执行此操作。另一种方法是安排子进程继承现有的对象句柄,而不是打开新的句柄;再说一次,不知道你会如何在 .NET 中做到这一点。
-
如果事件和映射文件是使用不允许所有人访问的 ACL 创建的,则像 ASP.NET 这样的受限上下文可能无法打开它。我首先建议为运行 ASP.NET 进程的用户打开具有明确权限的事件和映射文件。
-
@MartinPrikryl create... 有关创建安全属性结构的安全描述符的示例(所有人),请参见 msdn.microsoft.com/en-us/library/windows/desktop/…。
-
@PeterRitchie:您是否知道是否为使用受限令牌运行的 ASPX 应用程序启用了所有人 SID?我相当确定用户帐户的 SID 不会。最好的选择是登录 SID,但我不太确定您将如何从令牌中提取该 SID。
标签: c# c++ winapi synchronization memory-mapped-files