Windows 创建一个目录并通过发出一个IRP来获取句柄

Windows 创建一个目录并通过发出一个IRP来获取句柄,windows,winapi,file-io,filesystems,ntfs,Windows,Winapi,File Io,Filesystems,Ntfs,当我们通过CreateFile创建一个文件时,该文件将被创建并获得句柄。 但是CreateDirectory不返回目录的句柄 我还希望在创建目录时获得句柄。 我想通过只发出一个I/O请求包来处理这个问题 所以,“先创建目录,然后创建具有文件\u标志\u备份\u语义的文件。”不会是答案。 它将向文件系统发出两个IRP 是否有一个Api可以在用户模式下使用(Win32 Api)?NT可以这样做,但Win32不公开它。您需要为此使用NT API,明确地它应该遵循相同的参数 下面是一个说明性的例子(在一

当我们通过CreateFile创建一个文件时,该文件将被创建并获得句柄。
但是CreateDirectory不返回目录的句柄

我还希望在创建目录时获得句柄。
我想通过只发出一个I/O请求包来处理这个问题

所以,“先创建目录,然后创建具有文件\u标志\u备份\u语义的文件。”不会是答案。
它将向文件系统发出两个IRP


是否有一个Api可以在用户模式下使用(Win32 Api)?

NT可以这样做,但Win32不公开它。您需要为此使用NT API,明确地它应该遵循相同的参数

下面是一个说明性的例子(在一个web表单——YMMV中被匆忙破解):

有些事情需要注意

  • NT路径的约定与Win32路径略有不同。。。您可能需要清理路径

  • 当谈到
    HANDLE
    s时,NT API通常处理
    NULL
    ,而不是
    INVALID\u HANDLE\u VALUE

  • 我在这里没有这样做,但是通过更改
    InitializeObjectAttributes
    调用,您可以做一些有趣的事情,比如相对于另一个目录句柄创建。当然,我放在这里的所有标志,你可能也想要改变。查阅文档和/或网络以获得最佳结果


+1这是正确的方法,但请注意:作为,此功能“可能会从一个版本的Windows更改到下一个版本,甚至可能在每个版本的service Pack之间进行更改”。至少,您应该始终通过动态运行时链接访问这些功能,如果它已被更改或删除。
CreateFile
实际上可以创建一个目录。将配置设置为
CREATE\u NEW
,将标志设置为
FILE\u FLAG\u BACKUP\u SEMANTICS\FILE\u FLAG\u POSIX\u SEMANTICS\124; FILE\u ATTRIBUTE\u DIRECTORY
。因为这没有文档记录,所以它可能没有在ReactOS和Wine中实现。请注意,如果您在Python之类的脚本环境中,请确保使用标题(0x01000000)中的
FILE\u FLAG\u POSIX\u SEMANTICS
的正确值。MSDN上列出的值总是错误的。对于NTFS,您还可以创建
$INDEX\u分配
属性。下面是命令提示符下的一个愚蠢版本的
mkdir dirname
type num>dirname::$INDEX\u ALLOCATION
。当然,它在FAT32驱动器上不起作用。
HANDLE
CreateDirectoryAndGetHandle(PWSTR pszFileName)
{
    NTSTATUS Status;
    UNICODE_STRING FileName;
    HANDLE DirectoryHandle;
    IO_STATUS_BLOCK IoStatus;
    OBJECT_ATTRIBUTES ObjectAttributes;

    RtlInitUnicodeString(&FileName, pszFileName);
    InitializeObjectAttributes(&ObjectAtributes, &FileName, 0, NULL, NULL);

    Status = NtCreateFile(&DirectoryHandle,
                          GENERIC_READ | GENERIC_WRITE,
                          &ObjectAttributes,
                          &IoStatus,
                          FILE_ATTRIBUTE_NORMAL,
                          FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
                          FILE_CREATE,
                          FILE_DIRECTORY_FILE,
                          NULL,
                          0);

    if (NT_SUCCESS(Status))
    {
       return DirectoryHandle;
    }
    else
    {
       SetLastError(RtlNtStatusToDosError(Status));
       return INVALID_HANDLE_VALUE;
    }
}