[PATCH] kernelbase: Also pass CreateFile2 dwFileFlags to CreateFileW.

Rémi Bernon rbernon at codeweavers.com
Wed Sep 9 13:38:44 CDT 2020


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 at 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 );
 }
 
 
-- 
2.28.0




More information about the wine-devel mailing list