Search code examples
windowswinapifile-iofilesystemsntfs

Create a directory and get the handle by issuing one IRP


When we create a file by CreateFile, the file created and we get the handle.
But CreateDirectory doesn't return directory's handle.

I'd like to also get the handle when I create a directory.
I want to handle this by issuing only one I/O request packet.

So, 'Do CreateDirectory, then CreateFile with FILE_FLAG_BACKUP_SEMANTICS.' won't be an answer.
It will issue two Irps to file system.

Is there an Api I can use in Usermode(Win32 Api)?


Solution

  • NT can do this, but Win32 doesn't expose it. You need to use NT APIs for this. NtCreateFile, specifically. It should follow the same parameters of ZwCreateFile.

    Here's an illustrative example (hacked up in a hurry inside a web form -- YMMV):

    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;
        }
    }
    

    Some things to note...

    • NT paths have slightly different conventions than Win32 paths... You might have to sanitize the path.

    • When talking about HANDLEs, NT APIs generally deal with NULL rather than INVALID_HANDLE_VALUE.

    • I didn't do it here, but by changing the InitializeObjectAttributes call you can do interesting things, like do a create relative to another directory handle. Of course all the flags I've put in here you might also want to change. Consult documentation and/or the web for best results.