简体   繁体   English

服务和用户模式进程之间的共享全局事件不起作用

[英]Shared global event between a service & user-mode processes doesn't work

I'm trying to create a named global event that could be shared among my service and user process(-es). 我正在尝试创建一个可以在我的服务和用户进程(-es)之间共享的命名全局事件。 The user process may run under credentials of any low privileged logged in Windows user (even a built-in guest.) There's also no way of knowing which process will create this event first, ie service or a user process. 用户进程可以在任何低权限登录Windows用户(甚至是内置guest虚拟机)的凭据下运行。也无法知道哪个进程将首先创建此事件,即服务或用户进程。

So from both the service & user-mode process the event is created/opened as such: 因此,从服务和用户模式过程中,事件都是这样创建/打开的:

//Event name is made up using special/shared file path, and basically becomes something like this
strEventName = L"Global\\sa_evt_C:_Users_Name_C++_Mod0110_debug_TmLog0";

//Create descriptor for "ALL access"
PSECURITY_DESCRIPTOR psdAll;
if(::ConvertStringSecurityDescriptorToSecurityDescriptor(
    isWindowsVistaOrLater ? L"D:(A;;GA;;;WD)(A;;GA;;;AN)S:(ML;;;;;S-1-16-0)" : L"D:(A;;GA;;;WD)(A;;GA;;;AN)",
    SDDL_REVISION_1, &psdAll, NULL))
{
    SECURITY_ATTRIBUTES sa;
    sa.nLength = sizeof(sa);
    sa.bInheritHandle = FALSE;
    sa.lpSecurityDescriptor = psdAll;

    hEvent = ::CreateEvent(&sa, TRUE, FALSE, strEventName);

    LocalFree(psdAll);
}

The issue I'm experiencing is that the event is created by both the service and user mode process(-es) but it's almost like if they each create their own (non-shared) copies of the event, ie when I signal it the other module does not see it (via WaitForSingleObject API.) 我遇到的问题是事件是由服务和用户模式进程(-es)创建的,但它几乎就像是他们每个人创建自己的(非共享)事件副本,即当我发出信号时其他模块没有看到它(通过WaitForSingleObject API。)

I also ran it through the debugger and, say, after this event is created in the service, I would expect the CreateEvent() API in the user process to succeed and return GetLastError as ERROR_ALREADY_EXISTS , but it returns NO_ERROR . 我也通过调试器运行它,比如说,在服务中创建此事件之后,我希望用户进程中的CreateEvent()API成功并将GetLastError作为ERROR_ALREADY_EXISTS返回,但它返回NO_ERROR

Any idea what am I doing wrong here and how to make it work? 知道我在这里做错了什么以及如何使它工作?

So from both the service & user-mode process the event is created/opened as such 因此,从服务和用户模式过程中,事件都是这样创建/打开的

There is an easier way to create a security descriptor that allows unrestricted access to the event: 有一种更简单的方法来创建允许不受限制地访问事件的安全描述符:

SECURITY_DESCRIPTOR sd;
InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);

SECURITY_ATTRIBUTES sa = {0};
sa.nLength = sizeof(sa);
sa.bInheritHandle = FALSE;
sa.lpSecurityDescriptor = &sd;

hEvent = ::CreateEvent(&sa, TRUE, FALSE, strEventName);

There's also no way of knowing which process will create this event first, ie service or a user process. 也无法知道哪个进程将首先创建此事件,即服务或用户进程。

You could require the user processes to use OpenEvent() instead of CreateEvent() . 您可以要求用户进程使用OpenEvent()而不是CreateEvent() If the service is not running yet, the event would not be available to the processes. 如果服务尚未运行,则该进程将无法使用该事件。 Non-admin/elevated processes should not be creating objects in the Global\\ namespace, only consuming them, as they do not have the SeCreateGlobalPrivilege permission by default. 非管理员/提升的进程不应该在Global\\ namespace中创建对象,只是消耗它们,因为默认情况下它们没有SeCreateGlobalPrivilege权限。

Fixed it. 固定它。 Silly mistake. 愚蠢的错误。 Forgot that those kernel object names are case sensitive. 忘记那些内核对象名称区分大小写。 What I should've done is called CharLower () on the part of the name that follows Global\\ to make it all lower case, and then it would've worked just fine. 我应该做的是在Global\\之后的名称上调用CharLower (),使其全部小写,然后它就可以正常工作了。

As for the length of the kernel object name and characters allowed in it, there're basically two restrictions that I know of: 至于内核对象名称的长度和允许的字符,我基本上有两个限制:

  1. The part of the name that follows Global\\ (or Local\\ , or Session\\ ) may contain any characters, except slashes, ie \\ or / . Global\\ (或Local\\Session\\ )后面的名称部分可能包含除斜杠之外的任何字符,即\\/

  2. And the full object name itself cannot exceed MAX_PATH characters (which is 260.) So it can be quite long. 完整的对象名称本身不能超过MAX_PATH字符(即260)。因此它可能会很长。

InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);

Which I used to sync between IE activeX and native app, but it again failed. 我曾经在IE activeX和本机应用程序之间进行同步,但它再次失败了。 then i switched to ConvertStringSecurityDescriptorToSecurityDescriptor , it works well. 然后我切换到ConvertStringSecurityDescriptorToSecurityDescriptor ,它运作良好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM