Windows 命名管道访问控制

gua*_*hen 6 windows ipc nonblocking named-pipes

我的进程(服务器)创建了一个子进程(客户端),CreateProcess并且我在这些进程之间进行 IPC。我从匿名管道开始,但很快我发现它不支持重叠操作,如此处所述

所以,命名管道是我的第二选择。我的困惑是:如果我创建一个命名管道,是否可以将该管道的访问限制为仅由先前调用创建的子进程CreateProcess?因此,即使另一个进程获得了管道的名称,它仍然无法读取或写入管道。

我的IPC使用仅限于本地机器和单一平台(Windows)。

顺便说一句,我可以更改这些过程的两个代码。

RbM*_*bMm 0

当然,匿名管道完全支持异步(重叠)操作。支持或不支持异步操作 - 仅取决于FILE_SYNCHRONOUS_IO_[NO]NALERT在 callZwCreateNamedPipeFile和中使用 from ZwOpenFile,但不取决于来自哪个名称(或空)有管道。CreatePipe使用选项创建管道对FILE_SYNCHRONOUS_IO_NONALERT- 只是因为从此 api 返回的句柄不能在异步操作中使用。不幸的CreatePipe是没有参数可以改变这种行为,但我们可以自己完成这个任务

从 vista 开始,我们可以创建匿名(未命名)和异步管道对,但为此您需要使用 ndll api。下一个代码几乎是类似的CreatePipe内部代码,除了我创建异步管道对。

NTSTATUS CreatePipeAnonymousPair(PHANDLE phServerPipe, PHANDLE phClientPipe)
{
    HANDLE hFile;

    IO_STATUS_BLOCK iosb;

    static UNICODE_STRING NamedPipe = RTL_CONSTANT_STRING(L"\\Device\\NamedPipe\\");

    OBJECT_ATTRIBUTES oa = { sizeof(oa), 0, &NamedPipe, OBJ_CASE_INSENSITIVE };

    NTSTATUS status;

    if (0 <= (status = ZwOpenFile(&hFile, SYNCHRONIZE, &oa, &iosb, FILE_SHARE_VALID_FLAGS, 0)))
    {
        oa.RootDirectory = hFile;

        static LARGE_INTEGER timeout = { 0, MINLONG };
        static UNICODE_STRING empty = {};

        oa.ObjectName = &empty;

        if (0 <= (status = ZwCreateNamedPipeFile(phServerPipe,
            FILE_READ_ATTRIBUTES|FILE_READ_DATA|
            FILE_WRITE_ATTRIBUTES|FILE_WRITE_DATA|
            FILE_CREATE_PIPE_INSTANCE, 
            &oa, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE,
            FILE_CREATE, 0, FILE_PIPE_BYTE_STREAM_TYPE, FILE_PIPE_BYTE_STREAM_MODE,
            FILE_PIPE_QUEUE_OPERATION, 1, 0, 0, &timeout)))
        {

            oa.RootDirectory = *phServerPipe;
            oa.Attributes = OBJ_CASE_INSENSITIVE|OBJ_INHERIT;

            if (0 > (status = ZwOpenFile(phClientPipe, FILE_READ_ATTRIBUTES|FILE_READ_DATA|
                FILE_WRITE_ATTRIBUTES|FILE_WRITE_DATA, &oa, &iosb, FILE_SHARE_VALID_FLAGS, 0)))
            {
                ZwClose(oa.RootDirectory);
                *phServerPipe = 0;
            }
        }

        ZwClose(hFile);
    }

    return status;
}
Run Code Online (Sandbox Code Playgroud)

请注意,hClientPipe 创建为继承 - 因此可以将其传递给子进程。另外,当您将在ConnectNamedPipe中使用 hServerPipe 时FALSEGetLastError() == ERROR_PIPE_CONNECTED因为客户端已连接)/或者如果您将使用-FSCTL_PIPE_LISTEN您得到了STATUS_PIPE_CONNECTED- 这实际上不是错误,而是好的代码