Instead of just attributes.
Otherwise we may miss important flags like FILE_FLAG_OVERLAPPED and open the file for synchronous I/O, causing a deadlock in Flight Simulator.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/kernel32/tests/file.c | 48 +++++++++++++++++++++++++++++++------- dlls/kernelbase/file.c | 30 ++++++++++++++++++++++-- 2 files changed, 68 insertions(+), 10 deletions(-)
diff --git a/dlls/kernel32/tests/file.c b/dlls/kernel32/tests/file.c index 0f2c00d75ad..ec0e923706c 100644 --- a/dlls/kernel32/tests/file.c +++ b/dlls/kernel32/tests/file.c @@ -1675,14 +1675,14 @@ static void test_CreateFileW(void)
static void test_CreateFile2(void) { - HANDLE hFile; + HANDLE hFile, iocp; WCHAR temp_path[MAX_PATH]; WCHAR filename[MAX_PATH]; CREATEFILE2_EXTENDED_PARAMETERS exparams; static const WCHAR emptyW[]={'\0'}; static const WCHAR prefix[] = {'p','f','x',0}; static const WCHAR bogus[] = { '\', '\', '.', '\', 'B', 'O', 'G', 'U', 'S', 0 }; - DWORD ret; + DWORD i, ret;
if (!pCreateFile2) { @@ -1699,8 +1699,8 @@ static void test_CreateFile2(void)
SetLastError(0xdeadbeef); exparams.dwSize = sizeof(exparams); - exparams.dwFileAttributes = FILE_FLAG_RANDOM_ACCESS; - exparams.dwFileFlags = 0; + exparams.dwFileAttributes = 0; + exparams.dwFileFlags = FILE_FLAG_RANDOM_ACCESS; exparams.dwSecurityQosFlags = 0; exparams.lpSecurityAttributes = NULL; exparams.hTemplateFile = 0; @@ -1744,14 +1744,46 @@ static void test_CreateFile2(void)
ret = CreateDirectoryW(filename, NULL); ok(ret == TRUE, "couldn't create temporary directory\n"); - exparams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS; + exparams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL; + exparams.dwFileFlags = FILE_FLAG_BACKUP_SEMANTICS; + SetLastError(0xdeadbeef); hFile = pCreateFile2(filename, GENERIC_READ | GENERIC_WRITE, 0, OPEN_ALWAYS, &exparams); - todo_wine - ok(hFile == INVALID_HANDLE_VALUE, - "expected CreateFile2 to fail on existing directory, error: %d\n", GetLastError()); + ok(hFile != INVALID_HANDLE_VALUE, + "CreateFile2 failed with FILE_FLAG_BACKUP_SEMANTICS on existing directory, error: %d\n", GetLastError()); CloseHandle(hFile); ret = RemoveDirectoryW(filename); ok(ret, "DeleteFileW: error %d\n", GetLastError()); + + for (i = 0; i < 2; ++i) + { + memset(&exparams, 0, sizeof(exparams)); + exparams.dwSize = sizeof(exparams); + if (i == 0) + { + exparams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL; + exparams.dwFileFlags = FILE_FLAG_OVERLAPPED | FILE_FLAG_DELETE_ON_CLOSE; + } + else + { + exparams.dwFileFlags = FILE_ATTRIBUTE_NORMAL; + exparams.dwFileAttributes = FILE_FLAG_OVERLAPPED | FILE_FLAG_DELETE_ON_CLOSE; + } + + SetLastError(0xdeadbeef); + hFile = pCreateFile2(filename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, CREATE_ALWAYS, &exparams); + ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == 0, "%d: hFile %p, last error %u\n", i, hFile, GetLastError()); + + iocp = CreateIoCompletionPort(hFile, NULL, 0, 2); + if (i == 1) ok(iocp == NULL && GetLastError() == ERROR_INVALID_PARAMETER, "%d: CreateIoCompletionPort returned %p, error %u\n", i, iocp, GetLastError()); + else ok(iocp != INVALID_HANDLE_VALUE && GetLastError() == 0, "%d: CreateIoCompletionPort returned %p, error %u\n", i, iocp, GetLastError()); + + CloseHandle(iocp); + CloseHandle(hFile); + + ret = DeleteFileW(filename); + if (i == 1) ok(ret, "%d: unexpected DeleteFileW failure, error %u\n", i, GetLastError()); + else ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND, "%d: unexpected DeleteFileW result, ret %d error %u\n", i, ret, GetLastError()); + } }
static void test_GetTempFileNameA(void) diff --git a/dlls/kernelbase/file.c b/dlls/kernelbase/file.c index d9b34408692..b265866ac54 100644 --- a/dlls/kernelbase/file.c +++ b/dlls/kernelbase/file.c @@ -655,13 +655,39 @@ BOOL WINAPI DECLSPEC_HOTPATCH CreateDirectoryExW( LPCWSTR template, LPCWSTR path HANDLE WINAPI DECLSPEC_HOTPATCH CreateFile2( LPCWSTR name, DWORD access, DWORD sharing, DWORD creation, CREATEFILE2_EXTENDED_PARAMETERS *params ) { + static const DWORD attributes_mask = FILE_ATTRIBUTE_READONLY | + FILE_ATTRIBUTE_HIDDEN | + FILE_ATTRIBUTE_SYSTEM | + FILE_ATTRIBUTE_ARCHIVE | + FILE_ATTRIBUTE_NORMAL | + FILE_ATTRIBUTE_TEMPORARY | + FILE_ATTRIBUTE_OFFLINE | + FILE_ATTRIBUTE_ENCRYPTED | + FILE_ATTRIBUTE_INTEGRITY_STREAM; + static const DWORD flags_mask = FILE_FLAG_BACKUP_SEMANTICS | + FILE_FLAG_DELETE_ON_CLOSE | + FILE_FLAG_NO_BUFFERING | + FILE_FLAG_OPEN_NO_RECALL | + FILE_FLAG_OPEN_REPARSE_POINT | + FILE_FLAG_OVERLAPPED | + FILE_FLAG_POSIX_SEMANTICS | + FILE_FLAG_RANDOM_ACCESS | + FILE_FLAG_SEQUENTIAL_SCAN | + FILE_FLAG_WRITE_THROUGH; + LPSECURITY_ATTRIBUTES sa = params ? params->lpSecurityAttributes : NULL; - DWORD attributes = params ? params->dwFileAttributes : 0; HANDLE template = params ? params->hTemplateFile : NULL; + DWORD attributes = params ? params->dwFileAttributes : 0; + DWORD flags = params ? params->dwFileFlags : 0;
FIXME( "(%s %x %x %x %p), partial stub\n", debugstr_w(name), access, sharing, creation, params );
- return CreateFileW( name, access, sharing, sa, creation, attributes, template ); + if (attributes & ~attributes_mask) FIXME( "unsupported attributes %#x\n", attributes ); + if (flags & ~flags_mask) FIXME( "unsupported flags %#x\n", flags ); + attributes &= attributes_mask; + flags &= flags_mask; + + return CreateFileW( name, access, sharing, sa, creation, flags | attributes, template ); }