匿名管道当然支持异步(重叠)操作。支持异步操作或不支持取决于在调用ZwCreateNamedPipeFile
和ZwOpenFile
时是否使用了FILE_SYNCHRONOUS_IO_[NO]NALERT
,而不是管道的名称(或为空)。CreatePipe
创建具有FILE_SYNCHRONOUS_IO_NONALERT
选项的管道对-仅因为从此API返回的句柄不能用于异步操作。不幸的是,CreatePipe
没有更改此行为的参数,但我们可以自己执行此任务。
从Vista开始,我们可以创建匿名和异步管道对,但是需要使用ndll api。下面的代码与CreatePipe
内部代码几乎相似,只是我创建了异步管道对。
NTSTATUS CreatePipeAnonymousPair(PHANDLE phServerPipe, PHANDLE phClientPipe)
;
NTSTATUS status;
if (0 <= (status = ZwOpenFile(&hFile, SYNCHRONIZE, &oa, &iosb, FILE_SHARE_VALID_FLAGS, 0)))
;
static UNICODE_STRING empty = ;
oa.ObjectName = ∅
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)))
}
ZwClose(hFile);
}
return status;
}
注意,hClientPipe是作为继承创建的 - 因此可以将其传递给子进程。 另外,当你在ConnectNamedPipe中使用hServerPipe时,如果客户端已经连接,则会返回FALSE
和GetLastError() == ERROR_PIPE_CONNECTED
/ 或者如果你使用FSCTL_PIPE_LISTEN
- 你会得到STATUS_PIPE_CONNECTED
- 这真的不是错误而是正常代码。
CreateNamedPipe
时,将指向SECURITY_ATTRIBUTES
结构的指针作为最后一个参数传递。这样可以根据需要精确限制访问权限。通过查看CreateNamedPipe
的文档,这个问题本来很容易解决:lpSecurityAttributes
参数的功能与CreatePipe
相同... - Cody GrayFILE_SYNCHRONOUS_IO_NONALERT
选项创建管道对-只因为从此API返回的句柄不能用于异步操作。不幸的是,CreatePipe没有参数来更改此行为,但我们可以自己完成此任务。 - RbMm