Signed-off-by: YeshunYe yeyeshun@uniontech.com Change-Id: I2a8099278fae6dcc45bc92fb1f1f606407fba000
Although MSDN does not mention that CreateFile can be used to create folders, it is actually supported. Verified on WinXP, Win7, and Win10.
From: YeshunYe yeyeshun@uniontech.com
Signed-off-by: YeshunYe yeyeshun@uniontech.com Change-Id: I2a8099278fae6dcc45bc92fb1f1f606407fba000 --- dlls/kernel32/tests/file.c | 37 ++++++++++++++++++++++++++++++++++++- dlls/kernelbase/file.c | 10 +++++++--- 2 files changed, 43 insertions(+), 4 deletions(-)
diff --git a/dlls/kernel32/tests/file.c b/dlls/kernel32/tests/file.c index cf0c40d5cd6..c3a899e6865 100644 --- a/dlls/kernel32/tests/file.c +++ b/dlls/kernel32/tests/file.c @@ -1415,6 +1415,42 @@ static void test_CreateFileA(void) ok(ret, "RemoveDirectoryA: error %ld\n", GetLastError()); SetCurrentDirectoryW(curdir);
+ /* test creating directory as a directory */ + hFile = CreateFileA( dirname, 0, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + CREATE_NEW, + FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS | FILE_ATTRIBUTE_DIRECTORY, + NULL ); + ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA did not work, last error %lu on dir <%s>\n", GetLastError(), dirname ); + if (hFile != INVALID_HANDLE_VALUE) + { + ret = GetFileInformationByHandle( hFile, &Finfo ); + CloseHandle( hFile ); + ok(ret, "GetFileInformationByHandle error %ld\n", GetLastError()); + if (ret) + { + ok(Finfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY, + "CreateFileA probably did not create directory %s correctly\n file information does not include FILE_ATTRIBUTE_DIRECTORY, actual=0x%08lx\n", + dirname, Finfo.dwFileAttributes); + if (Finfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + ret = RemoveDirectoryA(dirname); + ok(ret, "RemoveDirectoryA: error %ld\n", GetLastError()); + } + else + { + ret = DeleteFileA(dirname); + ok(ret, "DeleteFile error %ld\n", GetLastError()); + } + } + else + { + DeleteFileA(dirname); + RemoveDirectoryA(dirname); + } + } + /* test opening directory as a directory */ hFile = CreateFileA( temp_path, GENERIC_READ, FILE_SHARE_READ, @@ -1442,7 +1478,6 @@ static void test_CreateFileA(void) else skip("Probable Win9x, got ERROR_PATH_NOT_FOUND w/ FILE_FLAG_BACKUP_SEMANTICS or %s\n", temp_path);
- /* *** Test opening volumes/devices using drive letter *** */
/* test using drive letter in non-rewrite format without trailing \ */ diff --git a/dlls/kernelbase/file.c b/dlls/kernelbase/file.c index 7d8b6844456..539632a0115 100644 --- a/dlls/kernelbase/file.c +++ b/dlls/kernelbase/file.c @@ -758,12 +758,16 @@ HANDLE WINAPI DECLSPEC_HOTPATCH CreateFileA( LPCSTR name, DWORD access, DWORD sh return CreateFileW( nameW, access, sharing, sa, creation, attributes, template ); }
-static UINT get_nt_file_options( DWORD attributes ) +static UINT get_nt_file_options( DWORD attributes, BOOL bCreateNew ) { UINT options = 0;
if (attributes & FILE_FLAG_BACKUP_SEMANTICS) + { options |= FILE_OPEN_FOR_BACKUP_INTENT; + if (bCreateNew && (attributes & FILE_FLAG_POSIX_SEMANTICS) && (attributes & FILE_ATTRIBUTE_DIRECTORY)) + options |= FILE_DIRECTORY_FILE; + } else options |= FILE_NON_DIRECTORY_FILE; if (attributes & FILE_FLAG_DELETE_ON_CLOSE) @@ -864,7 +868,7 @@ HANDLE WINAPI DECLSPEC_HOTPATCH CreateFileW( LPCWSTR filename, DWORD access, DWO status = NtCreateFile( &ret, access | SYNCHRONIZE | FILE_READ_ATTRIBUTES, &attr, &io, NULL, attributes & FILE_ATTRIBUTE_VALID_FLAGS, sharing, nt_disposition[creation - CREATE_NEW], - get_nt_file_options( attributes ), NULL, 0 ); + get_nt_file_options( attributes, creation == CREATE_NEW ), NULL, 0 ); if (status) { if (vxd_name && vxd_name[0]) @@ -3379,7 +3383,7 @@ HANDLE WINAPI DECLSPEC_HOTPATCH ReOpenFile( HANDLE handle, DWORD access, DWORD s }
status = NtCreateFile( &file, access | SYNCHRONIZE | FILE_READ_ATTRIBUTES, &attr, &io, NULL, - 0, sharing, FILE_OPEN, get_nt_file_options( attributes ), NULL, 0 ); + 0, sharing, FILE_OPEN, get_nt_file_options( attributes, FALSE ), NULL, 0 ); if (!set_ntstatus( status )) return INVALID_HANDLE_VALUE; return file;