[NTDLL_WINETEST] Sync with Wine Staging 1.7.55. CORE-10536
authorAmine Khaldi <amine.khaldi@reactos.org>
Tue, 24 Nov 2015 15:14:42 +0000 (15:14 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Tue, 24 Nov 2015 15:14:42 +0000 (15:14 +0000)
svn path=/trunk/; revision=70096

rostests/winetests/ntdll/CMakeLists.txt
rostests/winetests/ntdll/directory.c
rostests/winetests/ntdll/env.c
rostests/winetests/ntdll/exception.c
rostests/winetests/ntdll/file.c
rostests/winetests/ntdll/generated.c
rostests/winetests/ntdll/info.c
rostests/winetests/ntdll/om.c
rostests/winetests/ntdll/reg.c
rostests/winetests/ntdll/rtl.c

index 815f3d0..7a843e1 100644 (file)
@@ -34,5 +34,5 @@ add_importlibs(ntdll_winetest user32 msvcrt kernel32 ntdll)
 add_cd_file(TARGET ntdll_winetest DESTINATION reactos/bin FOR all)
 
 if(NOT MSVC)
-    add_target_compile_flags(ntdll_winetest "-Wno-format")
+    add_target_compile_flags(ntdll_winetest "-Wno-format -Wno-error")
 endif()
index b541f0c..89b786d 100644 (file)
@@ -174,7 +174,7 @@ static void test_flags_NtQueryDirectoryFile(OBJECT_ATTRIBUTES *attr, const char
     data_size = mask ? offsetof( FILE_BOTH_DIRECTORY_INFORMATION, FileName[256] ) : sizeof(data);
 
     /* Read the directory and note which files are found */
-    status = pNtOpenFile( &dirh, SYNCHRONIZE | FILE_LIST_DIRECTORY, attr, &io, FILE_OPEN,
+    status = pNtOpenFile( &dirh, SYNCHRONIZE | FILE_LIST_DIRECTORY, attr, &io, FILE_SHARE_READ,
                          FILE_SYNCHRONOUS_IO_NONALERT|FILE_OPEN_FOR_BACKUP_INTENT|FILE_DIRECTORY_FILE);
     ok (status == STATUS_SUCCESS, "failed to open dir '%s', ret 0x%x, error %d\n", testdirA, status, GetLastError());
     if (status != STATUS_SUCCESS) {
@@ -270,6 +270,101 @@ done:
     pRtlFreeUnicodeString(&ntdirname);
 }
 
+static void set_up_case_test(const char *testdir)
+{
+    BOOL ret;
+    char buf[MAX_PATH];
+    HANDLE h;
+
+    ret = CreateDirectoryA(testdir, NULL);
+    ok(ret, "couldn't create dir '%s', error %d\n", testdir, GetLastError());
+
+    sprintf(buf, "%s\\%s", testdir, "TesT");
+    h = CreateFileA(buf, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
+                    FILE_ATTRIBUTE_NORMAL, 0);
+    ok(h != INVALID_HANDLE_VALUE, "failed to create temp file '%s'\n", buf);
+    CloseHandle(h);
+}
+
+static void tear_down_case_test(const char *testdir)
+{
+    int ret;
+    char buf[MAX_PATH];
+
+    sprintf(buf, "%s\\%s", testdir, "TesT");
+    ret = DeleteFileA(buf);
+    ok(ret || (GetLastError() == ERROR_PATH_NOT_FOUND),
+       "Failed to rm %s, error %d\n", buf, GetLastError());
+    RemoveDirectoryA(testdir);
+}
+
+static void test_NtQueryDirectoryFile_case(void)
+{
+    static const char testfile[] = "TesT";
+    static const WCHAR testfile_w[] = {'T','e','s','T'};
+    static int testfile_len = sizeof(testfile) - 1;
+    static WCHAR testmask[] = {'t','e','s','t'};
+    OBJECT_ATTRIBUTES attr;
+    UNICODE_STRING ntdirname;
+    char testdir[MAX_PATH];
+    WCHAR testdir_w[MAX_PATH];
+    HANDLE dirh;
+    UNICODE_STRING mask;
+    IO_STATUS_BLOCK io;
+    UINT data_size, data_len;
+    BYTE data[8192];
+    FILE_BOTH_DIRECTORY_INFORMATION *dir_info = (FILE_BOTH_DIRECTORY_INFORMATION *)data;
+    DWORD status;
+    WCHAR *name;
+    ULONG name_len;
+
+    /* Clean up from prior aborted run, if any, then set up test files */
+    ok(GetTempPathA(MAX_PATH, testdir), "couldn't get temp dir\n");
+    strcat(testdir, "case.tmp");
+    tear_down_case_test(testdir);
+    set_up_case_test(testdir);
+
+    pRtlMultiByteToUnicodeN(testdir_w, sizeof(testdir_w), NULL, testdir, strlen(testdir) + 1);
+    if (!pRtlDosPathNameToNtPathName_U(testdir_w, &ntdirname, NULL, NULL))
+    {
+        ok(0, "RtlDosPathNametoNtPathName_U failed\n");
+        goto done;
+    }
+    InitializeObjectAttributes(&attr, &ntdirname, OBJ_CASE_INSENSITIVE, 0, NULL);
+
+    data_size = offsetof(FILE_BOTH_DIRECTORY_INFORMATION, FileName[256]);
+
+    status = pNtOpenFile(&dirh, SYNCHRONIZE | FILE_LIST_DIRECTORY, &attr, &io, FILE_SHARE_READ,
+                         FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT | FILE_DIRECTORY_FILE);
+    ok (status == STATUS_SUCCESS, "failed to open dir '%s', ret 0x%x, error %d\n", testdir, status, GetLastError());
+    if (status != STATUS_SUCCESS)
+    {
+       skip("can't test if we can't open the directory\n");
+       return;
+    }
+
+    mask.Buffer = testmask;
+    mask.Length = mask.MaximumLength = sizeof(testmask);
+    pNtQueryDirectoryFile(dirh, NULL, NULL, NULL, &io, data, data_size,
+                          FileBothDirectoryInformation, TRUE, &mask, FALSE);
+    ok(U(io).Status == STATUS_SUCCESS, "failed to query directory; status %x\n", U(io).Status);
+    data_len = io.Information;
+    ok(data_len >= sizeof(FILE_BOTH_DIRECTORY_INFORMATION), "not enough data in directory\n");
+
+    name = dir_info->FileName;
+    name_len = dir_info->FileNameLength / sizeof(WCHAR);
+
+    ok(name_len == testfile_len, "unexpected filename length %u\n", name_len);
+    ok(!memcmp(name, testfile_w, testfile_len * sizeof(WCHAR)), "unexpected filename %s\n",
+       wine_dbgstr_wn(name, name_len));
+
+    pNtClose(dirh);
+
+done:
+    tear_down_case_test(testdir);
+    pRtlFreeUnicodeString(&ntdirname);
+}
+
 static void test_redirection(void)
 {
     ULONG old, cur;
@@ -339,5 +434,6 @@ START_TEST(directory)
     pRtlWow64EnableFsRedirectionEx = (void *)GetProcAddress(hntdll,"RtlWow64EnableFsRedirectionEx");
 
     test_NtQueryDirectoryFile();
+    test_NtQueryDirectoryFile_case();
     test_redirection();
 }
index 6bd1530..8989760 100755 (executable)
@@ -111,7 +111,7 @@ static void testQuery(void)
             pRtlMultiByteToUnicodeN( bn, sizeof(bn), NULL, test->val, strlen(test->val)+1 );
             ok( value.Length == strlen(test->val) * sizeof(WCHAR), "Wrong length %d for %s\n",
                 value.Length, test->var );
-            ok((value.Length == strlen(test->val) * sizeof(WCHAR) && memcmp(bv, bn, test->len*sizeof(WCHAR)) == 0) ||
+            ok((value.Length == strlen(test->val) * sizeof(WCHAR) && memcmp(bv, bn, value.Length) == 0) ||
               lstrcmpW(bv, bn) == 0, 
               "Wrong result for %s/%d\n", test->var, test->len);
             ok(bv[test->len] == '@', "Writing too far away in the buffer for %s/%d\n", test->var, test->len);
index 8e7894e..2455e1b 100644 (file)
@@ -973,7 +973,7 @@ static void test_debugger(void)
                                           sizeof(stage), &size_read);
             ok(!status,"NtReadVirtualMemory failed with 0x%x\n", status);
 
-            ok(!de.u.DebugString.fUnicode, "unepxected unicode debug string event\n");
+            ok(!de.u.DebugString.fUnicode, "unexpected unicode debug string event\n");
             ok(de.u.DebugString.nDebugStringLength < sizeof(buffer) - 1, "buffer not large enough to hold %d bytes\n",
                de.u.DebugString.nDebugStringLength);
 
@@ -1838,7 +1838,7 @@ static void test_closehandle(DWORD numexc)
     invalid_handle_exceptions = 0;
     res = CloseHandle((HANDLE)0xdeadbeef);
     ok(!res, "CloseHandle(0xdeadbeef) unexpectedly succeeded\n");
-    ok(GetLastError() == ERROR_INVALID_HANDLE, "wrong error code %d instead of %d",
+    ok(GetLastError() == ERROR_INVALID_HANDLE, "wrong error code %d instead of %d\n",
        GetLastError(), ERROR_INVALID_HANDLE);
     ok(invalid_handle_exceptions == numexc, "CloseHandle generated %d exceptions, expected %d\n",
        invalid_handle_exceptions, numexc);
index 0acc7cf..706984a 100644 (file)
@@ -105,6 +105,8 @@ static NTSTATUS (WINAPI *pNtQueryInformationFile)(HANDLE, PIO_STATUS_BLOCK, PVOI
 static NTSTATUS (WINAPI *pNtQueryDirectoryFile)(HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,
                                                 PVOID,ULONG,FILE_INFORMATION_CLASS,BOOLEAN,PUNICODE_STRING,BOOLEAN);
 static NTSTATUS (WINAPI *pNtQueryVolumeInformationFile)(HANDLE,PIO_STATUS_BLOCK,PVOID,ULONG,FS_INFORMATION_CLASS);
+static NTSTATUS (WINAPI *pNtQueryFullAttributesFile)(const OBJECT_ATTRIBUTES*, FILE_NETWORK_OPEN_INFORMATION*);
+static NTSTATUS (WINAPI *pNtQueryEaFile)(HANDLE,PIO_STATUS_BLOCK,PVOID,ULONG,BOOLEAN,PVOID,ULONG,PULONG,BOOLEAN);
 
 static inline BOOL is_signaled( HANDLE obj )
 {
@@ -200,12 +202,20 @@ static void create_file_test(void)
                                         '\\','f','a','i','l','i','n','g',0};
     static const WCHAR questionmarkInvalidNameW[] = {'a','f','i','l','e','?',0};
     static const WCHAR pipeInvalidNameW[]  = {'a','|','b',0};
+    static const WCHAR pathInvalidNtW[] = {'\\','\\','?','\\',0};
+    static const WCHAR pathInvalidNt2W[] = {'\\','?','?','\\',0};
+    static const WCHAR pathInvalidDosW[] = {'\\','D','o','s','D','e','v','i','c','e','s','\\',0};
+    static const char testdata[] = "Hello World";
+    FILE_NETWORK_OPEN_INFORMATION info;
     NTSTATUS status;
     HANDLE dir, file;
     WCHAR path[MAX_PATH];
     OBJECT_ATTRIBUTES attr;
     IO_STATUS_BLOCK io;
     UNICODE_STRING nameW;
+    LARGE_INTEGER offset;
+    char buf[32];
+    DWORD ret;
 
     GetCurrentDirectoryW( MAX_PATH, path );
     pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
@@ -217,9 +227,35 @@ static void create_file_test(void)
     attr.SecurityQualityOfService = NULL;
 
     /* try various open modes and options on directories */
-    status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
-                            FILE_OPEN, FILE_DIRECTORY_FILE, NULL, 0 );
+    status = pNtCreateFile( &dir, GENERIC_READ|GENERIC_WRITE, &attr, &io, NULL, 0,
+                            FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, FILE_DIRECTORY_FILE, NULL, 0 );
     ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
+
+    U(io).Status = 0xdeadbeef;
+    offset.QuadPart = 0;
+    status = pNtReadFile( dir, NULL, NULL, NULL, &io, buf, sizeof(buf), &offset, NULL );
+    ok( status == STATUS_INVALID_DEVICE_REQUEST || status == STATUS_PENDING, "NtReadFile error %08x\n", status );
+    if (status == STATUS_PENDING)
+    {
+        ret = WaitForSingleObject( dir, 1000 );
+        ok( ret == WAIT_OBJECT_0, "WaitForSingleObject error %u\n", ret );
+        ok( U(io).Status == STATUS_INVALID_DEVICE_REQUEST,
+            "expected STATUS_INVALID_DEVICE_REQUEST, got %08x\n", U(io).Status );
+    }
+
+    U(io).Status = 0xdeadbeef;
+    offset.QuadPart = 0;
+    status = pNtWriteFile( dir, NULL, NULL, NULL, &io, testdata, sizeof(testdata), &offset, NULL);
+    todo_wine
+    ok( status == STATUS_INVALID_DEVICE_REQUEST || status == STATUS_PENDING, "NtWriteFile error %08x\n", status );
+    if (status == STATUS_PENDING)
+    {
+        ret = WaitForSingleObject( dir, 1000 );
+        ok( ret == WAIT_OBJECT_0, "WaitForSingleObject error %u\n", ret );
+        ok( U(io).Status == STATUS_INVALID_DEVICE_REQUEST,
+            "expected STATUS_INVALID_DEVICE_REQUEST, got %08x\n", U(io).Status );
+    }
+
     CloseHandle( dir );
 
     status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
@@ -320,19 +356,55 @@ static void create_file_test(void)
     ok(status == STATUS_OBJECT_NAME_INVALID,
        "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status);
     pRtlFreeUnicodeString(&nameW);
+
+    pRtlInitUnicodeString( &nameW, pathInvalidNtW );
+    status = pNtCreateFile( &dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
+                            FILE_SHARE_READ, FILE_CREATE,
+                            FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
+    ok( status == STATUS_OBJECT_NAME_INVALID,
+        "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
+
+    status = pNtQueryFullAttributesFile( &attr, &info );
+    todo_wine ok( status == STATUS_OBJECT_NAME_INVALID,
+                  "query %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
+
+    pRtlInitUnicodeString( &nameW, pathInvalidNt2W );
+    status = pNtCreateFile( &dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
+                            FILE_SHARE_READ, FILE_CREATE,
+                            FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
+    ok( status == STATUS_OBJECT_NAME_INVALID,
+        "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
+
+    status = pNtQueryFullAttributesFile( &attr, &info );
+    ok( status == STATUS_OBJECT_NAME_INVALID,
+        "query %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
+
+    pRtlInitUnicodeString( &nameW, pathInvalidDosW );
+    status = pNtCreateFile( &dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
+                            FILE_SHARE_READ, FILE_CREATE,
+                            FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
+    ok( status == STATUS_OBJECT_NAME_INVALID,
+        "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
+
+    status = pNtQueryFullAttributesFile( &attr, &info );
+    ok( status == STATUS_OBJECT_NAME_INVALID,
+        "query %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
 }
 
 static void open_file_test(void)
 {
+    static const char testdata[] = "Hello World";
+    static WCHAR fooW[] = {'f','o','o',0};
     NTSTATUS status;
-    HANDLE dir, root, handle;
-    WCHAR path[MAX_PATH];
+    HANDLE dir, root, handle, file;
+    WCHAR path[MAX_PATH], tmpfile[MAX_PATH];
     BYTE data[1024];
     OBJECT_ATTRIBUTES attr;
     IO_STATUS_BLOCK io;
     UNICODE_STRING nameW;
     UINT i, len;
-    BOOL restart = TRUE;
+    BOOL ret, restart = TRUE;
+    DWORD numbytes;
 
     len = GetWindowsDirectoryW( path, MAX_PATH );
     pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
@@ -453,6 +525,74 @@ static void open_file_test(void)
 
     CloseHandle( dir );
     CloseHandle( root );
+
+    GetTempPathW( MAX_PATH, path );
+    GetTempFileNameW( path, fooW, 0, tmpfile );
+    pRtlDosPathNameToNtPathName_U( tmpfile, &nameW, NULL, NULL );
+
+    file = CreateFileW( tmpfile, FILE_WRITE_DATA, 0, NULL, CREATE_ALWAYS, 0, 0 );
+    ok( file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError() );
+    numbytes = 0xdeadbeef;
+    ret = WriteFile( file, testdata, sizeof(testdata) - 1, &numbytes, NULL );
+    ok( ret, "WriteFile failed with error %u\n", GetLastError() );
+    ok( numbytes == sizeof(testdata) - 1, "failed to write all data\n" );
+    CloseHandle( file );
+
+    attr.Length = sizeof(attr);
+    attr.RootDirectory = 0;
+    attr.ObjectName = &nameW;
+    attr.Attributes = OBJ_CASE_INSENSITIVE;
+    attr.SecurityDescriptor = NULL;
+    attr.SecurityQualityOfService = NULL;
+    status = pNtOpenFile( &file, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
+                         FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT );
+    ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
+    pRtlFreeUnicodeString( &nameW );
+
+    numbytes = 0xdeadbeef;
+    memset( data, 0, sizeof(data) );
+    ret = ReadFile( file, data, sizeof(data), &numbytes, NULL );
+    ok( ret, "ReadFile failed with error %u\n", GetLastError() );
+    ok( numbytes == sizeof(testdata) - 1, "failed to read all data\n" );
+    ok( !memcmp( data, testdata, sizeof(testdata) - 1 ), "testdata doesn't match\n" );
+
+    nameW.Length = sizeof(fooW) - sizeof(WCHAR);
+    nameW.Buffer = fooW;
+    attr.RootDirectory = file;
+    attr.ObjectName = &nameW;
+    status = pNtOpenFile( &root, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
+                         FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT );
+    ok( status == STATUS_OBJECT_PATH_NOT_FOUND,
+        "expected STATUS_OBJECT_PATH_NOT_FOUND, got %08x\n", status );
+
+    nameW.Length = 0;
+    nameW.Buffer = NULL;
+    attr.RootDirectory = file;
+    attr.ObjectName = &nameW;
+    status = pNtOpenFile( &root, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
+                          FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT );
+    ok( !status, "open %s failed %x\n", wine_dbgstr_w(tmpfile), status );
+
+    numbytes = SetFilePointer( file, 0, 0, FILE_CURRENT );
+    ok( numbytes == sizeof(testdata) - 1, "SetFilePointer returned %u\n", numbytes );
+    numbytes = SetFilePointer( root, 0, 0, FILE_CURRENT );
+    ok( numbytes == 0, "SetFilePointer returned %u\n", numbytes );
+
+    numbytes = 0xdeadbeef;
+    memset( data, 0, sizeof(data) );
+    ret = ReadFile( root, data, sizeof(data), &numbytes, NULL );
+    ok( ret, "ReadFile failed with error %u\n", GetLastError() );
+    ok( numbytes == sizeof(testdata) - 1, "failed to read all data\n" );
+    ok( !memcmp( data, testdata, sizeof(testdata) - 1 ), "testdata doesn't match\n" );
+
+    numbytes = SetFilePointer( file, 0, 0, FILE_CURRENT );
+    ok( numbytes == sizeof(testdata) - 1, "SetFilePointer returned %u\n", numbytes );
+    numbytes = SetFilePointer( root, 0, 0, FILE_CURRENT );
+    ok( numbytes == sizeof(testdata) - 1, "SetFilePointer returned %u\n", numbytes );
+
+    CloseHandle( file );
+    CloseHandle( root );
+    DeleteFileW( tmpfile );
 }
 
 static void delete_file_test(void)
@@ -1428,6 +1568,1279 @@ static void test_file_all_information(void)
     CloseHandle( h );
 }
 
+static void delete_object( WCHAR *path )
+{
+    BOOL ret = DeleteFileW( path );
+    ok( ret || GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_ACCESS_DENIED,
+        "DeleteFileW failed with %u\n", GetLastError() );
+    if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
+    {
+        ret = RemoveDirectoryW( path );
+        ok( ret, "RemoveDirectoryW failed with %u\n", GetLastError() );
+    }
+}
+
+static void test_file_rename_information(void)
+{
+    static const WCHAR foo_txtW[] = {'\\','f','o','o','.','t','x','t',0};
+    static const WCHAR fooW[] = {'f','o','o',0};
+    WCHAR tmp_path[MAX_PATH], oldpath[MAX_PATH + 16], newpath[MAX_PATH + 16], *filename, *p;
+    FILE_RENAME_INFORMATION *fri;
+    FILE_NAME_INFORMATION *fni;
+    BOOL success, fileDeleted;
+    UNICODE_STRING name_str;
+    HANDLE handle, handle2;
+    IO_STATUS_BLOCK io;
+    NTSTATUS res;
+
+    GetTempPathW( MAX_PATH, tmp_path );
+
+    /* oldpath is a file, newpath doesn't exist */
+    res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
+    ok( res != 0, "failed to create temp file\n" );
+    handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
+    ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
+    ok( res != 0, "failed to create temp file\n" );
+    pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
+    DeleteFileW( newpath );
+    fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
+    fri->Replace = FALSE;
+    fri->RootDir = NULL;
+    fri->FileNameLength = name_str.Length;
+    memcpy( fri->FileName, name_str.Buffer, name_str.Length );
+    pRtlFreeUnicodeString( &name_str );
+
+    U(io).Status = 0xdeadbeef;
+    res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
+    ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
+    ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
+    fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( fileDeleted, "file should not exist\n" );
+    fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+
+    fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
+    res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
+    ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
+    fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
+    ok( !lstrcmpW(fni->FileName, newpath + 2), "FileName expected %s, got %s\n",
+        wine_dbgstr_w(newpath + 2), wine_dbgstr_w(fni->FileName) );
+    HeapFree( GetProcessHeap(), 0, fni );
+
+    CloseHandle( handle );
+    HeapFree( GetProcessHeap(), 0, fri );
+    delete_object( oldpath );
+    delete_object( newpath );
+
+    /* oldpath is a file, newpath is a file, Replace = FALSE */
+    res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
+    ok( res != 0, "failed to create temp file\n" );
+    handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
+    ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
+    ok( res != 0, "failed to create temp file\n" );
+    pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
+    fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
+    fri->Replace = FALSE;
+    fri->RootDir = NULL;
+    fri->FileNameLength = name_str.Length;
+    memcpy( fri->FileName, name_str.Buffer, name_str.Length );
+    pRtlFreeUnicodeString( &name_str );
+
+    U(io).Status = 0xdeadbeef;
+    res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
+    todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
+    ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
+    fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+    fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+
+    CloseHandle( handle );
+    HeapFree( GetProcessHeap(), 0, fri );
+    delete_object( oldpath );
+    delete_object( newpath );
+
+    /* oldpath is a file, newpath is a file, Replace = TRUE */
+    res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
+    ok( res != 0, "failed to create temp file\n" );
+    handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
+    ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
+    ok( res != 0, "failed to create temp file\n" );
+    pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
+    fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
+    fri->Replace = TRUE;
+    fri->RootDir = NULL;
+    fri->FileNameLength = name_str.Length;
+    memcpy( fri->FileName, name_str.Buffer, name_str.Length );
+    pRtlFreeUnicodeString( &name_str );
+
+    U(io).Status = 0xdeadbeef;
+    res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
+    ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
+    ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
+    fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( fileDeleted, "file should not exist\n" );
+    fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+
+    CloseHandle( handle );
+    HeapFree( GetProcessHeap(), 0, fri );
+    delete_object( oldpath );
+    delete_object( newpath );
+
+    /* oldpath is a file, newpath is a file, Replace = FALSE, target file opened */
+    res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
+    ok( res != 0, "failed to create temp file\n" );
+    handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
+    ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
+    ok( res != 0, "failed to create temp file\n" );
+    handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
+    ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
+    fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
+    fri->Replace = FALSE;
+    fri->RootDir = NULL;
+    fri->FileNameLength = name_str.Length;
+    memcpy( fri->FileName, name_str.Buffer, name_str.Length );
+    pRtlFreeUnicodeString( &name_str );
+
+    U(io).Status = 0xdeadbeef;
+    res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
+    todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
+    ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
+    fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+    fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+
+    CloseHandle( handle );
+    CloseHandle( handle2 );
+    HeapFree( GetProcessHeap(), 0, fri );
+    delete_object( oldpath );
+    delete_object( newpath );
+
+    /* oldpath is a file, newpath is a file, Replace = TRUE, target file opened */
+    res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
+    ok( res != 0, "failed to create temp file\n" );
+    handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
+    ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
+    ok( res != 0, "failed to create temp file\n" );
+    handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
+    ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
+    fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
+    fri->Replace = TRUE;
+    fri->RootDir = NULL;
+    fri->FileNameLength = name_str.Length;
+    memcpy( fri->FileName, name_str.Buffer, name_str.Length );
+    pRtlFreeUnicodeString( &name_str );
+
+    U(io).Status = 0xdeadbeef;
+    res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
+    todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
+    ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
+    fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+    fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+
+    CloseHandle( handle );
+    CloseHandle( handle2 );
+    HeapFree( GetProcessHeap(), 0, fri );
+    delete_object( oldpath );
+    delete_object( newpath );
+
+    /* oldpath is a directory, newpath doesn't exist, Replace = FALSE */
+    res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
+    ok( res != 0, "failed to create temp file\n" );
+    DeleteFileW( oldpath );
+    success = CreateDirectoryW( oldpath, NULL );
+    ok( success != 0, "failed to create temp directory\n" );
+    handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
+    ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
+    ok( res != 0, "failed to create temp file\n" );
+    pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
+    DeleteFileW( newpath );
+    fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
+    fri->Replace = FALSE;
+    fri->RootDir = NULL;
+    fri->FileNameLength = name_str.Length;
+    memcpy( fri->FileName, name_str.Buffer, name_str.Length );
+    pRtlFreeUnicodeString( &name_str );
+
+    U(io).Status = 0xdeadbeef;
+    res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
+    ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
+    ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
+    fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( fileDeleted, "file should not exist\n" );
+    fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+
+    fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
+    res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
+    ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
+    fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
+    ok( !lstrcmpW(fni->FileName, newpath + 2), "FileName expected %s, got %s\n",
+        wine_dbgstr_w(newpath + 2), wine_dbgstr_w(fni->FileName) );
+    HeapFree( GetProcessHeap(), 0, fni );
+
+    CloseHandle( handle );
+    HeapFree( GetProcessHeap(), 0, fri );
+    delete_object( oldpath );
+    delete_object( newpath );
+
+    /* oldpath is a directory (but child object opened), newpath doesn't exist, Replace = FALSE */
+    res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
+    ok( res != 0, "failed to create temp file\n" );
+    DeleteFileW( oldpath );
+    success = CreateDirectoryW( oldpath, NULL );
+    ok( success != 0, "failed to create temp directory\n" );
+    handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
+    ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    lstrcpyW( newpath, oldpath );
+    lstrcatW( newpath, foo_txtW );
+    handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0 );
+    ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
+    ok( res != 0, "failed to create temp file\n" );
+    pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
+    DeleteFileW( newpath );
+    fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
+    fri->Replace = FALSE;
+    fri->RootDir = NULL;
+    fri->FileNameLength = name_str.Length;
+    memcpy( fri->FileName, name_str.Buffer, name_str.Length );
+    pRtlFreeUnicodeString( &name_str );
+
+    U(io).Status = 0xdeadbeef;
+    res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
+    todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
+    todo_wine ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
+    fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    todo_wine ok( !fileDeleted, "file should exist\n" );
+    fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    todo_wine ok( fileDeleted, "file should not exist\n" );
+
+    CloseHandle( handle );
+    CloseHandle( handle2 );
+    HeapFree( GetProcessHeap(), 0, fri );
+    delete_object( oldpath );
+    if (res == STATUS_SUCCESS) /* remove when Wine is fixed */
+    {
+        lstrcpyW( oldpath, newpath );
+        lstrcatW( oldpath, foo_txtW );
+        delete_object( oldpath );
+    }
+    delete_object( newpath );
+
+    /* oldpath is a directory, newpath is a file, Replace = FALSE */
+    res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
+    ok( res != 0, "failed to create temp file\n" );
+    DeleteFileW( oldpath );
+    success = CreateDirectoryW( oldpath, NULL );
+    ok( success != 0, "failed to create temp directory\n" );
+    handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
+    ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
+    ok( res != 0, "failed to create temp file\n" );
+    pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
+    fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
+    fri->Replace = FALSE;
+    fri->RootDir = NULL;
+    fri->FileNameLength = name_str.Length;
+    memcpy( fri->FileName, name_str.Buffer, name_str.Length );
+    pRtlFreeUnicodeString( &name_str );
+
+    U(io).Status = 0xdeadbeef;
+    res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
+    todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
+    ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
+    fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+    fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+
+    CloseHandle( handle );
+    HeapFree( GetProcessHeap(), 0, fri );
+    delete_object( oldpath );
+    delete_object( newpath );
+
+    /* oldpath is a directory, newpath is a file, Replace = FALSE, target file opened */
+    res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
+    ok( res != 0, "failed to create temp file\n" );
+    DeleteFileW( oldpath );
+    success = CreateDirectoryW( oldpath, NULL );
+    ok( success != 0, "failed to create temp directory\n" );
+    handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
+    ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
+    ok( res != 0, "failed to create temp file\n" );
+    handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
+    ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
+    fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
+    fri->Replace = FALSE;
+    fri->RootDir = NULL;
+    fri->FileNameLength = name_str.Length;
+    memcpy( fri->FileName, name_str.Buffer, name_str.Length );
+    pRtlFreeUnicodeString( &name_str );
+
+    U(io).Status = 0xdeadbeef;
+    res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
+    todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
+    ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
+    fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+    fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+
+    CloseHandle( handle );
+    CloseHandle( handle2 );
+    HeapFree( GetProcessHeap(), 0, fri );
+    delete_object( oldpath );
+    delete_object( newpath );
+
+    /* oldpath is a directory, newpath is a file, Replace = TRUE */
+    res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
+    ok( res != 0, "failed to create temp file\n" );
+    DeleteFileW( oldpath );
+    success = CreateDirectoryW( oldpath, NULL );
+    ok( success != 0, "failed to create temp directory\n" );
+    handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
+    ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
+    ok( res != 0, "failed to create temp file\n" );
+    pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
+    fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
+    fri->Replace = TRUE;
+    fri->RootDir = NULL;
+    fri->FileNameLength = name_str.Length;
+    memcpy( fri->FileName, name_str.Buffer, name_str.Length );
+    pRtlFreeUnicodeString( &name_str );
+
+    U(io).Status = 0xdeadbeef;
+    res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
+    ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
+    ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
+    fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( fileDeleted, "file should not exist\n" );
+    fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+
+    CloseHandle( handle );
+    HeapFree( GetProcessHeap(), 0, fri );
+    delete_object( oldpath );
+    delete_object( newpath );
+
+    /* oldpath is a directory, newpath is a file, Replace = TRUE, target file opened */
+    res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
+    ok( res != 0, "failed to create temp file\n" );
+    DeleteFileW( oldpath );
+    success = CreateDirectoryW( oldpath, NULL );
+    ok( success != 0, "failed to create temp directory\n" );
+    handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
+    ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
+    ok( res != 0, "failed to create temp file\n" );
+    handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
+    ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
+    fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
+    fri->Replace = TRUE;
+    fri->RootDir = NULL;
+    fri->FileNameLength = name_str.Length;
+    memcpy( fri->FileName, name_str.Buffer, name_str.Length );
+    pRtlFreeUnicodeString( &name_str );
+
+    U(io).Status = 0xdeadbeef;
+    res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
+    todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
+    ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
+    fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+    fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+
+    CloseHandle( handle );
+    CloseHandle( handle2 );
+    HeapFree( GetProcessHeap(), 0, fri );
+    delete_object( oldpath );
+    delete_object( newpath );
+
+    /* oldpath is a directory, newpath is a directory, Replace = FALSE */
+    res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
+    ok( res != 0, "failed to create temp file\n" );
+    DeleteFileW( oldpath );
+    success = CreateDirectoryW( oldpath, NULL );
+    ok( success != 0, "failed to create temp directory\n" );
+    handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
+    ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
+    ok( res != 0, "failed to create temp file\n" );
+    DeleteFileW( newpath );
+    success = CreateDirectoryW( newpath, NULL );
+    ok( success != 0, "failed to create temp directory\n" );
+    pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
+    fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
+    fri->Replace = FALSE;
+    fri->RootDir = NULL;
+    fri->FileNameLength = name_str.Length;
+    memcpy( fri->FileName, name_str.Buffer, name_str.Length );
+    pRtlFreeUnicodeString( &name_str );
+
+    U(io).Status = 0xdeadbeef;
+    res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
+    todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
+    ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
+    fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+    fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+
+    CloseHandle( handle );
+    HeapFree( GetProcessHeap(), 0, fri );
+    delete_object( oldpath );
+    delete_object( newpath );
+
+    /* oldpath is a directory, newpath is a directory, Replace = TRUE */
+    res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
+    ok( res != 0, "failed to create temp file\n" );
+    DeleteFileW( oldpath );
+    success = CreateDirectoryW( oldpath, NULL );
+    ok( success != 0, "failed to create temp directory\n" );
+    handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
+    ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
+    ok( res != 0, "failed to create temp file\n" );
+    DeleteFileW( newpath );
+    success = CreateDirectoryW( newpath, NULL );
+    ok( success != 0, "failed to create temp directory\n" );
+    pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
+    fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
+    fri->Replace = TRUE;
+    fri->RootDir = NULL;
+    fri->FileNameLength = name_str.Length;
+    memcpy( fri->FileName, name_str.Buffer, name_str.Length );
+    pRtlFreeUnicodeString( &name_str );
+
+    U(io).Status = 0xdeadbeef;
+    res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
+    todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
+    ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
+    fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+    fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+
+    CloseHandle( handle );
+    HeapFree( GetProcessHeap(), 0, fri );
+    delete_object( oldpath );
+    delete_object( newpath );
+
+    /* oldpath is a directory, newpath is a directory, Replace = TRUE, target file opened */
+    res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
+    ok( res != 0, "failed to create temp file\n" );
+    DeleteFileW( oldpath );
+    success = CreateDirectoryW( oldpath, NULL );
+    ok( success != 0, "failed to create temp directory\n" );
+    handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
+    ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
+    ok( res != 0, "failed to create temp file\n" );
+    DeleteFileW( newpath );
+    success = CreateDirectoryW( newpath, NULL );
+    ok( success != 0, "failed to create temp directory\n" );
+    handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
+    ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
+    fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
+    fri->Replace = TRUE;
+    fri->RootDir = NULL;
+    fri->FileNameLength = name_str.Length;
+    memcpy( fri->FileName, name_str.Buffer, name_str.Length );
+    pRtlFreeUnicodeString( &name_str );
+
+    U(io).Status = 0xdeadbeef;
+    res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
+    todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
+    ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
+    fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+    fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+
+    CloseHandle( handle );
+    CloseHandle( handle2 );
+    HeapFree( GetProcessHeap(), 0, fri );
+    delete_object( oldpath );
+    delete_object( newpath );
+
+    /* oldpath is a file, newpath is a directory, Replace = FALSE */
+    res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
+    ok( res != 0, "failed to create temp file\n" );
+    handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
+    ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
+    ok( res != 0, "failed to create temp file\n" );
+    DeleteFileW( newpath );
+    success = CreateDirectoryW( newpath, NULL );
+    ok( success != 0, "failed to create temp directory\n" );
+    pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
+    fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
+    fri->Replace = FALSE;
+    fri->RootDir = NULL;
+    fri->FileNameLength = name_str.Length;
+    memcpy( fri->FileName, name_str.Buffer, name_str.Length );
+    pRtlFreeUnicodeString( &name_str );
+
+    U(io).Status = 0xdeadbeef;
+    res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
+    todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
+    ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
+    fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+    fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+
+    CloseHandle( handle );
+    HeapFree( GetProcessHeap(), 0, fri );
+    delete_object( oldpath );
+    delete_object( newpath );
+
+    /* oldpath is a file, newpath is a directory, Replace = TRUE */
+    res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
+    ok( res != 0, "failed to create temp file\n" );
+    handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
+    ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
+    ok( res != 0, "failed to create temp file\n" );
+    DeleteFileW( newpath );
+    success = CreateDirectoryW( newpath, NULL );
+    ok( success != 0, "failed to create temp directory\n" );
+    pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
+    fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
+    fri->Replace = TRUE;
+    fri->RootDir = NULL;
+    fri->FileNameLength = name_str.Length;
+    memcpy( fri->FileName, name_str.Buffer, name_str.Length );
+    pRtlFreeUnicodeString( &name_str );
+
+    U(io).Status = 0xdeadbeef;
+    res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
+    todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
+    ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
+    fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+    fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+
+    CloseHandle( handle );
+    HeapFree( GetProcessHeap(), 0, fri );
+    delete_object( oldpath );
+    delete_object( newpath );
+
+    /* oldpath is a file, newpath doesn't exist, test with RootDir != NULL */
+    res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
+    ok( res != 0, "failed to create temp file\n" );
+    handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
+    ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
+    ok( res != 0, "failed to create temp file\n" );
+    DeleteFileW( newpath );
+    for (filename = newpath, p = newpath; *p; p++)
+        if (*p == '\\') filename = p + 1;
+    handle2 = CreateFileW( tmp_path, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
+    ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + lstrlenW(filename) * sizeof(WCHAR) );
+    fri->Replace = FALSE;
+    fri->RootDir = handle2;
+    fri->FileNameLength = lstrlenW(filename) * sizeof(WCHAR);
+    memcpy( fri->FileName, filename, fri->FileNameLength );
+
+    U(io).Status = 0xdeadbeef;
+    res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
+    ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
+    ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
+    fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( fileDeleted, "file should not exist\n" );
+    fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+
+    fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
+    res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
+    ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
+    fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
+    ok( !lstrcmpW(fni->FileName, newpath + 2), "FileName expected %s, got %s\n",
+        wine_dbgstr_w(newpath + 2), wine_dbgstr_w(fni->FileName) );
+    HeapFree( GetProcessHeap(), 0, fni );
+
+    CloseHandle( handle );
+    CloseHandle( handle2 );
+    HeapFree( GetProcessHeap(), 0, fri );
+    delete_object( oldpath );
+    delete_object( newpath );
+}
+
+static void test_file_link_information(void)
+{
+    static const WCHAR foo_txtW[] = {'\\','f','o','o','.','t','x','t',0};
+    static const WCHAR fooW[] = {'f','o','o',0};
+    WCHAR tmp_path[MAX_PATH], oldpath[MAX_PATH + 16], newpath[MAX_PATH + 16], *filename, *p;
+    FILE_LINK_INFORMATION *fli;
+    FILE_NAME_INFORMATION *fni;
+    BOOL success, fileDeleted;
+    UNICODE_STRING name_str;
+    HANDLE handle, handle2;
+    IO_STATUS_BLOCK io;
+    NTSTATUS res;
+
+    GetTempPathW( MAX_PATH, tmp_path );
+
+    /* oldpath is a file, newpath doesn't exist */
+    res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
+    ok( res != 0, "failed to create temp file\n" );
+    handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
+    ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
+    ok( res != 0, "failed to create temp file\n" );
+    pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
+    DeleteFileW( newpath );
+    fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
+    fli->ReplaceIfExists = FALSE;
+    fli->RootDirectory = NULL;
+    fli->FileNameLength = name_str.Length;
+    memcpy( fli->FileName, name_str.Buffer, name_str.Length );
+    pRtlFreeUnicodeString( &name_str );
+
+    U(io).Status = 0xdeadbeef;
+    res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
+    ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
+    ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
+    fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+    fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+
+    fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
+    res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
+    ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
+    fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
+    ok( !lstrcmpW(fni->FileName, oldpath + 2), "FileName expected %s, got %s\n",
+        wine_dbgstr_w(oldpath + 2), wine_dbgstr_w(fni->FileName) );
+    HeapFree( GetProcessHeap(), 0, fni );
+
+    CloseHandle( handle );
+    HeapFree( GetProcessHeap(), 0, fli );
+    delete_object( oldpath );
+    delete_object( newpath );
+
+    /* oldpath is a file, newpath is a file, ReplaceIfExists = FALSE */
+    res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
+    ok( res != 0, "failed to create temp file\n" );
+    handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
+    ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
+    ok( res != 0, "failed to create temp file\n" );
+    pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
+    fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
+    fli->ReplaceIfExists = FALSE;
+    fli->RootDirectory = NULL;
+    fli->FileNameLength = name_str.Length;
+    memcpy( fli->FileName, name_str.Buffer, name_str.Length );
+    pRtlFreeUnicodeString( &name_str );
+
+    U(io).Status = 0xdeadbeef;
+    res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
+    todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
+    ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
+    fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+    fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+
+    CloseHandle( handle );
+    HeapFree( GetProcessHeap(), 0, fli );
+    delete_object( oldpath );
+    delete_object( newpath );
+
+    /* oldpath is a file, newpath is a file, ReplaceIfExists = TRUE */
+    res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
+    ok( res != 0, "failed to create temp file\n" );
+    handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
+    ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
+    ok( res != 0, "failed to create temp file\n" );
+    pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
+    fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
+    fli->ReplaceIfExists = TRUE;
+    fli->RootDirectory = NULL;
+    fli->FileNameLength = name_str.Length;
+    memcpy( fli->FileName, name_str.Buffer, name_str.Length );
+    pRtlFreeUnicodeString( &name_str );
+
+    U(io).Status = 0xdeadbeef;
+    res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
+    ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
+    ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
+    fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+    fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+
+    CloseHandle( handle );
+    HeapFree( GetProcessHeap(), 0, fli );
+    delete_object( oldpath );
+    delete_object( newpath );
+
+    /* oldpath is a file, newpath is a file, ReplaceIfExists = FALSE, target file opened */
+    res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
+    ok( res != 0, "failed to create temp file\n" );
+    handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
+    ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
+    ok( res != 0, "failed to create temp file\n" );
+    handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
+    ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
+    fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
+    fli->ReplaceIfExists = FALSE;
+    fli->RootDirectory = NULL;
+    fli->FileNameLength = name_str.Length;
+    memcpy( fli->FileName, name_str.Buffer, name_str.Length );
+    pRtlFreeUnicodeString( &name_str );
+
+    U(io).Status = 0xdeadbeef;
+    res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
+    todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
+    ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
+    fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+    fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+
+    CloseHandle( handle );
+    CloseHandle( handle2 );
+    HeapFree( GetProcessHeap(), 0, fli );
+    delete_object( oldpath );
+    delete_object( newpath );
+
+    /* oldpath is a file, newpath is a file, ReplaceIfExists = TRUE, target file opened */
+    res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
+    ok( res != 0, "failed to create temp file\n" );
+    handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
+    ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
+    ok( res != 0, "failed to create temp file\n" );
+    handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
+    ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
+    fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
+    fli->ReplaceIfExists = TRUE;
+    fli->RootDirectory = NULL;
+    fli->FileNameLength = name_str.Length;
+    memcpy( fli->FileName, name_str.Buffer, name_str.Length );
+    pRtlFreeUnicodeString( &name_str );
+
+    U(io).Status = 0xdeadbeef;
+    res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
+    todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
+    ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
+    fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+    fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+
+    CloseHandle( handle );
+    CloseHandle( handle2 );
+    HeapFree( GetProcessHeap(), 0, fli );
+    delete_object( oldpath );
+    delete_object( newpath );
+
+    /* oldpath is a directory, newpath doesn't exist, ReplaceIfExists = FALSE */
+    res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
+    ok( res != 0, "failed to create temp file\n" );
+    DeleteFileW( oldpath );
+    success = CreateDirectoryW( oldpath, NULL );
+    ok( success != 0, "failed to create temp directory\n" );
+    handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
+    ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
+    ok( res != 0, "failed to create temp file\n" );
+    pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
+    DeleteFileW( newpath );
+    fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
+    fli->ReplaceIfExists = FALSE;
+    fli->RootDirectory = NULL;
+    fli->FileNameLength = name_str.Length;
+    memcpy( fli->FileName, name_str.Buffer, name_str.Length );
+    pRtlFreeUnicodeString( &name_str );
+
+    U(io).Status = 0xdeadbeef;
+    res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
+    todo_wine ok( U(io).Status == 0xdeadbeef , "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
+    ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
+    fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+    fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( fileDeleted, "file should not exist\n" );
+
+    fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
+    res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
+    ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
+    fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
+    ok( !lstrcmpW(fni->FileName, oldpath + 2), "FileName expected %s, got %s\n",
+        wine_dbgstr_w(oldpath + 2), wine_dbgstr_w(fni->FileName) );
+    HeapFree( GetProcessHeap(), 0, fni );
+
+    CloseHandle( handle );
+    HeapFree( GetProcessHeap(), 0, fli );
+    delete_object( oldpath );
+    delete_object( newpath );
+
+    /* oldpath is a directory (but child object opened), newpath doesn't exist, ReplaceIfExists = FALSE */
+    res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
+    ok( res != 0, "failed to create temp file\n" );
+    DeleteFileW( oldpath );
+    success = CreateDirectoryW( oldpath, NULL );
+    ok( success != 0, "failed to create temp directory\n" );
+    handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
+    ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    lstrcpyW( newpath, oldpath );
+    lstrcatW( newpath, foo_txtW );
+    handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0 );
+    ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
+    ok( res != 0, "failed to create temp file\n" );
+    pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
+    DeleteFileW( newpath );
+    fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
+    fli->ReplaceIfExists = FALSE;
+    fli->RootDirectory = NULL;
+    fli->FileNameLength = name_str.Length;
+    memcpy( fli->FileName, name_str.Buffer, name_str.Length );
+    pRtlFreeUnicodeString( &name_str );
+
+    U(io).Status = 0xdeadbeef;
+    res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
+    todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
+    ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
+    fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+    fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( fileDeleted, "file should not exist\n" );
+
+    CloseHandle( handle );
+    CloseHandle( handle2 );
+    HeapFree( GetProcessHeap(), 0, fli );
+    delete_object( oldpath );
+    delete_object( newpath );
+
+    /* oldpath is a directory, newpath is a file, ReplaceIfExists = FALSE */
+    res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
+    ok( res != 0, "failed to create temp file\n" );
+    DeleteFileW( oldpath );
+    success = CreateDirectoryW( oldpath, NULL );
+    ok( success != 0, "failed to create temp directory\n" );
+    handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
+    ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
+    ok( res != 0, "failed to create temp file\n" );
+    pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
+    fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
+    fli->ReplaceIfExists = FALSE;
+    fli->RootDirectory = NULL;
+    fli->FileNameLength = name_str.Length;
+    memcpy( fli->FileName, name_str.Buffer, name_str.Length );
+    pRtlFreeUnicodeString( &name_str );
+
+    U(io).Status = 0xdeadbeef;
+    res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
+    todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
+    ok( res == STATUS_OBJECT_NAME_COLLISION || res == STATUS_FILE_IS_A_DIRECTORY /* > Win XP */,
+        "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
+    fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+    fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+
+    CloseHandle( handle );
+    HeapFree( GetProcessHeap(), 0, fli );
+    delete_object( oldpath );
+    delete_object( newpath );
+
+    /* oldpath is a directory, newpath is a file, ReplaceIfExists = FALSE, target file opened */
+    res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
+    ok( res != 0, "failed to create temp file\n" );
+    DeleteFileW( oldpath );
+    success = CreateDirectoryW( oldpath, NULL );
+    ok( success != 0, "failed to create temp directory\n" );
+    handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
+    ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
+    ok( res != 0, "failed to create temp file\n" );
+    handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
+    ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
+    fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
+    fli->ReplaceIfExists = FALSE;
+    fli->RootDirectory = NULL;
+    fli->FileNameLength = name_str.Length;
+    memcpy( fli->FileName, name_str.Buffer, name_str.Length );
+    pRtlFreeUnicodeString( &name_str );
+
+    U(io).Status = 0xdeadbeef;
+    res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
+    todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
+    ok( res == STATUS_OBJECT_NAME_COLLISION || res == STATUS_FILE_IS_A_DIRECTORY /* > Win XP */,
+        "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
+    fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+    fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+
+    CloseHandle( handle );
+    CloseHandle( handle2 );
+    HeapFree( GetProcessHeap(), 0, fli );
+    delete_object( oldpath );
+    delete_object( newpath );
+
+    /* oldpath is a directory, newpath is a file, ReplaceIfExists = TRUE */
+    res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
+    ok( res != 0, "failed to create temp file\n" );
+    DeleteFileW( oldpath );
+    success = CreateDirectoryW( oldpath, NULL );
+    ok( success != 0, "failed to create temp directory\n" );
+    handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
+    ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
+    ok( res != 0, "failed to create temp file\n" );
+    pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
+    fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
+    fli->ReplaceIfExists = TRUE;
+    fli->RootDirectory = NULL;
+    fli->FileNameLength = name_str.Length;
+    memcpy( fli->FileName, name_str.Buffer, name_str.Length );
+    pRtlFreeUnicodeString( &name_str );
+
+    U(io).Status = 0xdeadbeef;
+    res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
+    todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
+    ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
+    fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+    fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+
+    CloseHandle( handle );
+    HeapFree( GetProcessHeap(), 0, fli );
+    delete_object( oldpath );
+    delete_object( newpath );
+
+    /* oldpath is a directory, newpath is a file, ReplaceIfExists = TRUE, target file opened */
+    res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
+    ok( res != 0, "failed to create temp file\n" );
+    DeleteFileW( oldpath );
+    success = CreateDirectoryW( oldpath, NULL );
+    ok( success != 0, "failed to create temp directory\n" );
+    handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
+    ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
+    ok( res != 0, "failed to create temp file\n" );
+    handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
+    ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
+    fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
+    fli->ReplaceIfExists = TRUE;
+    fli->RootDirectory = NULL;
+    fli->FileNameLength = name_str.Length;
+    memcpy( fli->FileName, name_str.Buffer, name_str.Length );
+    pRtlFreeUnicodeString( &name_str );
+
+    U(io).Status = 0xdeadbeef;
+    res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
+    todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
+    ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
+    fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+    fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+
+    CloseHandle( handle );
+    CloseHandle( handle2 );
+    HeapFree( GetProcessHeap(), 0, fli );
+    delete_object( oldpath );
+    delete_object( newpath );
+
+    /* oldpath is a directory, newpath is a directory, ReplaceIfExists = FALSE */
+    res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
+    ok( res != 0, "failed to create temp file\n" );
+    DeleteFileW( oldpath );
+    success = CreateDirectoryW( oldpath, NULL );
+    ok( success != 0, "failed to create temp directory\n" );
+    handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
+    ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
+    ok( res != 0, "failed to create temp file\n" );
+    DeleteFileW( newpath );
+    success = CreateDirectoryW( newpath, NULL );
+    ok( success != 0, "failed to create temp directory\n" );
+    pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
+    fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
+    fli->ReplaceIfExists = FALSE;
+    fli->RootDirectory = NULL;
+    fli->FileNameLength = name_str.Length;
+    memcpy( fli->FileName, name_str.Buffer, name_str.Length );
+    pRtlFreeUnicodeString( &name_str );
+
+    U(io).Status = 0xdeadbeef;
+    res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
+    todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
+    ok( res == STATUS_OBJECT_NAME_COLLISION || res == STATUS_FILE_IS_A_DIRECTORY /* > Win XP */,
+        "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
+    fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+    fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+
+    CloseHandle( handle );
+    HeapFree( GetProcessHeap(), 0, fli );
+    delete_object( oldpath );
+    delete_object( newpath );
+
+    /* oldpath is a directory, newpath is a directory, ReplaceIfExists = TRUE */
+    res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
+    ok( res != 0, "failed to create temp file\n" );
+    DeleteFileW( oldpath );
+    success = CreateDirectoryW( oldpath, NULL );
+    ok( success != 0, "failed to create temp directory\n" );
+    handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
+    ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
+    ok( res != 0, "failed to create temp file\n" );
+    DeleteFileW( newpath );
+    success = CreateDirectoryW( newpath, NULL );
+    ok( success != 0, "failed to create temp directory\n" );
+    pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
+    fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
+    fli->ReplaceIfExists = TRUE;
+    fli->RootDirectory = NULL;
+    fli->FileNameLength = name_str.Length;
+    memcpy( fli->FileName, name_str.Buffer, name_str.Length );
+    pRtlFreeUnicodeString( &name_str );
+
+    U(io).Status = 0xdeadbeef;
+    res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
+    todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
+    ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
+    fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+    fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+
+    CloseHandle( handle );
+    HeapFree( GetProcessHeap(), 0, fli );
+    delete_object( oldpath );
+    delete_object( newpath );
+
+    /* oldpath is a directory, newpath is a directory, ReplaceIfExists = TRUE, target file opened */
+    res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
+    ok( res != 0, "failed to create temp file\n" );
+    DeleteFileW( oldpath );
+    success = CreateDirectoryW( oldpath, NULL );
+    ok( success != 0, "failed to create temp directory\n" );
+    handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
+    ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
+    ok( res != 0, "failed to create temp file\n" );
+    DeleteFileW( newpath );
+    success = CreateDirectoryW( newpath, NULL );
+    ok( success != 0, "failed to create temp directory\n" );
+    handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
+    ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
+    fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
+    fli->ReplaceIfExists = TRUE;
+    fli->RootDirectory = NULL;
+    fli->FileNameLength = name_str.Length;
+    memcpy( fli->FileName, name_str.Buffer, name_str.Length );
+    pRtlFreeUnicodeString( &name_str );
+
+    U(io).Status = 0xdeadbeef;
+    res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
+    todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
+    ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
+    fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+    fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+
+    CloseHandle( handle );
+    CloseHandle( handle2 );
+    HeapFree( GetProcessHeap(), 0, fli );
+    delete_object( oldpath );
+    delete_object( newpath );
+
+    /* oldpath is a file, newpath is a directory, ReplaceIfExists = FALSE */
+    res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
+    ok( res != 0, "failed to create temp file\n" );
+    handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
+    ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
+    ok( res != 0, "failed to create temp file\n" );
+    DeleteFileW( newpath );
+    success = CreateDirectoryW( newpath, NULL );
+    ok( success != 0, "failed to create temp directory\n" );
+    pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
+    fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
+    fli->ReplaceIfExists = FALSE;
+    fli->RootDirectory = NULL;
+    fli->FileNameLength = name_str.Length;
+    memcpy( fli->FileName, name_str.Buffer, name_str.Length );
+    pRtlFreeUnicodeString( &name_str );
+
+    U(io).Status = 0xdeadbeef;
+    res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
+    todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
+    ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
+    fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+    fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+
+    CloseHandle( handle );
+    HeapFree( GetProcessHeap(), 0, fli );
+    delete_object( oldpath );
+    delete_object( newpath );
+
+    /* oldpath is a file, newpath is a directory, ReplaceIfExists = TRUE */
+    res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
+    ok( res != 0, "failed to create temp file\n" );
+    handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
+    ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
+    ok( res != 0, "failed to create temp file\n" );
+    DeleteFileW( newpath );
+    success = CreateDirectoryW( newpath, NULL );
+    ok( success != 0, "failed to create temp directory\n" );
+    pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
+    fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
+    fli->ReplaceIfExists = TRUE;
+    fli->RootDirectory = NULL;
+    fli->FileNameLength = name_str.Length;
+    memcpy( fli->FileName, name_str.Buffer, name_str.Length );
+    pRtlFreeUnicodeString( &name_str );
+
+    U(io).Status = 0xdeadbeef;
+    res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
+    todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
+    ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
+    fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+    fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+
+    CloseHandle( handle );
+    HeapFree( GetProcessHeap(), 0, fli );
+    delete_object( oldpath );
+    delete_object( newpath );
+
+    /* oldpath is a file, newpath doesn't exist, test with RootDirectory != NULL */
+    res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
+    ok( res != 0, "failed to create temp file\n" );
+    handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
+    ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
+    ok( res != 0, "failed to create temp file\n" );
+    DeleteFileW( newpath );
+    for (filename = newpath, p = newpath; *p; p++)
+        if (*p == '\\') filename = p + 1;
+    handle2 = CreateFileW( tmp_path, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
+    ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+    fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + lstrlenW(filename) * sizeof(WCHAR) );
+    fli->ReplaceIfExists = FALSE;
+    fli->RootDirectory = handle2;
+    fli->FileNameLength = lstrlenW(filename) * sizeof(WCHAR);
+    memcpy( fli->FileName, filename, fli->FileNameLength );
+
+    U(io).Status = 0xdeadbeef;
+    res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
+    ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
+    ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
+    fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+    fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "file should exist\n" );
+
+    fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
+    res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
+    ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
+    fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
+    ok( !lstrcmpW(fni->FileName, oldpath + 2), "FileName expected %s, got %s\n",
+        wine_dbgstr_w(oldpath + 2), wine_dbgstr_w(fni->FileName) );
+    HeapFree( GetProcessHeap(), 0, fni );
+
+    CloseHandle( handle );
+    CloseHandle( handle2 );
+    HeapFree( GetProcessHeap(), 0, fli );
+    delete_object( oldpath );
+    delete_object( newpath );
+}
+
 static void test_file_both_information(void)
 {
     IO_STATUS_BLOCK io;
@@ -1453,10 +2866,26 @@ static void test_file_disposition_information(void)
     IO_STATUS_BLOCK io;
     FILE_DISPOSITION_INFORMATION fdi;
     BOOL fileDeleted;
+    DWORD fdi2;
     void *ptr;
 
     GetTempPathA( MAX_PATH, tmp_path );
 
+    /* tests for info struct size */
+    GetTempFileNameA( tmp_path, "dis", 0, buffer );
+    handle = CreateFileA( buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
+    ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
+    res = pNtSetInformationFile( handle, &io, &fdi, 0, FileDispositionInformation );
+    todo_wine
+    ok( res == STATUS_INFO_LENGTH_MISMATCH, "expected STATUS_INFO_LENGTH_MISMATCH, got %x\n", res );
+    fdi2 = 0x100;
+    res = pNtSetInformationFile( handle, &io, &fdi2, sizeof(fdi2), FileDispositionInformation );
+    ok( res == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %x\n", res );
+    CloseHandle( handle );
+    fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    ok( !fileDeleted, "File shouldn't have been deleted\n" );
+    DeleteFileA( buffer );
+
     /* cannot set disposition on file not opened with delete access */
     GetTempFileNameA( tmp_path, "dis", 0, buffer );
     handle = CreateFileA(buffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
@@ -1512,20 +2941,6 @@ static void test_file_disposition_information(void)
     SetFileAttributesA( buffer, FILE_ATTRIBUTE_NORMAL );
     DeleteFileA( buffer );
 
-    /* cannot set disposition on readonly file */
-    GetTempFileNameA( tmp_path, "dis", 0, buffer );
-    DeleteFileA( buffer );
-    handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0);
-    ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
-    fdi.DoDeleteFile = TRUE;
-    res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
-    ok( res == STATUS_CANNOT_DELETE, "unexpected FileDispositionInformation result (expected STATUS_CANNOT_DELETE, got %x)\n", res );
-    CloseHandle( handle );
-    fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
-    ok( !fileDeleted, "File shouldn't have been deleted\n" );
-    SetFileAttributesA( buffer, FILE_ATTRIBUTE_NORMAL );
-    DeleteFileA( buffer );
-
     /* can set disposition on file and then reset it */
     GetTempFileNameA( tmp_path, "dis", 0, buffer );
     handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
@@ -2000,11 +3415,11 @@ static void test_query_volume_information_file(void)
 
     ffvi = (FILE_FS_VOLUME_INFORMATION *)buf;
 
-todo_wine
-{
     ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %d\n", status);
     ok(U(io).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %d\n", U(io).Status);
 
+todo_wine
+{
     ok(io.Information == (FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel) + ffvi->VolumeLabelLength),
     "expected %d, got %lu\n", (FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel) + ffvi->VolumeLabelLength),
      io.Information);
@@ -2153,6 +3568,83 @@ static void test_NtCreateFile(void)
     DeleteFileW( path );
 }
 
+static void test_readonly(void)
+{
+    static const WCHAR fooW[] = {'f','o','o',0};
+    NTSTATUS status;
+    HANDLE handle;
+    WCHAR path[MAX_PATH];
+    OBJECT_ATTRIBUTES attr;
+    IO_STATUS_BLOCK io;
+    UNICODE_STRING nameW;
+
+    GetTempPathW(MAX_PATH, path);
+    GetTempFileNameW(path, fooW, 0, path);
+    DeleteFileW(path);
+    pRtlDosPathNameToNtPathName_U(path, &nameW, NULL, NULL);
+
+    attr.Length = sizeof(attr);
+    attr.RootDirectory = NULL;
+    attr.ObjectName = &nameW;
+    attr.Attributes = OBJ_CASE_INSENSITIVE;
+    attr.SecurityDescriptor = NULL;
+    attr.SecurityQualityOfService = NULL;
+
+    status = pNtCreateFile(&handle, GENERIC_READ, &attr, &io, NULL, FILE_ATTRIBUTE_READONLY,
+                           FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_CREATE, 0, NULL, 0);
+    ok(status == STATUS_SUCCESS, "got %#x\n", status);
+    CloseHandle(handle);
+
+    status = pNtOpenFile(&handle, GENERIC_WRITE,  &attr, &io,
+                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN_FOR_BACKUP_INTENT);
+    ok(status == STATUS_ACCESS_DENIED, "got %#x\n", status);
+    CloseHandle(handle);
+
+    status = pNtOpenFile(&handle, GENERIC_READ,  &attr, &io,
+                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN_FOR_BACKUP_INTENT);
+    ok(status == STATUS_SUCCESS, "got %#x\n", status);
+    CloseHandle(handle);
+
+    status = pNtOpenFile(&handle, FILE_READ_ATTRIBUTES,  &attr, &io,
+                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN_FOR_BACKUP_INTENT);
+    ok(status == STATUS_SUCCESS, "got %#x\n", status);
+    CloseHandle(handle);
+
+    status = pNtOpenFile(&handle, FILE_WRITE_ATTRIBUTES,  &attr, &io,
+                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN_FOR_BACKUP_INTENT);
+    ok(status == STATUS_SUCCESS, "got %#x\n", status);
+    CloseHandle(handle);
+
+    status = pNtOpenFile(&handle, DELETE,  &attr, &io,
+                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN_FOR_BACKUP_INTENT);
+    ok(status == STATUS_SUCCESS, "got %#x\n", status);
+    CloseHandle(handle);
+
+    status = pNtOpenFile(&handle, READ_CONTROL,  &attr, &io,
+                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN_FOR_BACKUP_INTENT);
+    ok(status == STATUS_SUCCESS, "got %#x\n", status);
+    CloseHandle(handle);
+
+    status = pNtOpenFile(&handle, WRITE_DAC,  &attr, &io,
+                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN_FOR_BACKUP_INTENT);
+    ok(status == STATUS_SUCCESS, "got %#x\n", status);
+    CloseHandle(handle);
+
+    status = pNtOpenFile(&handle, WRITE_OWNER,  &attr, &io,
+                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN_FOR_BACKUP_INTENT);
+    ok(status == STATUS_SUCCESS, "got %#x\n", status);
+    CloseHandle(handle);
+
+    status = pNtOpenFile(&handle, SYNCHRONIZE,  &attr, &io,
+                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN_FOR_BACKUP_INTENT);
+    ok(status == STATUS_SUCCESS, "got %#x\n", status);
+    CloseHandle( handle );
+
+    pRtlFreeUnicodeString(&nameW);
+    SetFileAttributesW(path, FILE_ATTRIBUTE_ARCHIVE);
+    DeleteFileW(path);
+}
+
 static void test_read_write(void)
 {
     static const char contents[14] = "1234567890abcd";
@@ -2865,6 +4357,86 @@ static void test_read_write(void)
     CloseHandle(hfile);
 }
 
+static void test_query_ea(void)
+{
+    #define EA_BUFFER_SIZE 4097
+    unsigned char data[EA_BUFFER_SIZE + 8];
+    unsigned char *buffer = (void *)(((DWORD_PTR)data + 7) & ~7);
+    DWORD buffer_len, i;
+    IO_STATUS_BLOCK io;
+    NTSTATUS status;
+    HANDLE handle;
+
+    if (!(handle = create_temp_file(0))) return;
+
+    /* test with INVALID_HANDLE_VALUE */
+    U(io).Status = 0xdeadbeef;
+    io.Information = 0xdeadbeef;
+    memset(buffer, 0xcc, EA_BUFFER_SIZE);
+    buffer_len = EA_BUFFER_SIZE - 1;
+    status = pNtQueryEaFile(INVALID_HANDLE_VALUE, &io, buffer, buffer_len, TRUE, NULL, 0, NULL, FALSE);
+    ok(status == STATUS_OBJECT_TYPE_MISMATCH, "expected STATUS_OBJECT_TYPE_MISMATCH, got %x\n", status);
+    ok(U(io).Status == 0xdeadbeef, "expected 0xdeadbeef, got %x\n", U(io).Status);
+    ok(io.Information == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", io.Information);
+    ok(buffer[0] == 0xcc, "data at position 0 overwritten\n");
+
+    /* test with 0xdeadbeef */
+    U(io).Status = 0xdeadbeef;
+    io.Information = 0xdeadbeef;
+    memset(buffer, 0xcc, EA_BUFFER_SIZE);
+    buffer_len = EA_BUFFER_SIZE - 1;
+    status = pNtQueryEaFile((void *)0xdeadbeef, &io, buffer, buffer_len, TRUE, NULL, 0, NULL, FALSE);
+    ok(status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %x\n", status);
+    ok(U(io).Status == 0xdeadbeef, "expected 0xdeadbeef, got %x\n", U(io).Status);
+    ok(io.Information == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", io.Information);
+    ok(buffer[0] == 0xcc, "data at position 0 overwritten\n");
+
+    /* test without buffer */
+    U(io).Status = 0xdeadbeef;
+    io.Information = 0xdeadbeef;
+    status = pNtQueryEaFile(handle, &io, NULL, 0, TRUE, NULL, 0, NULL, FALSE);
+    ok(status == STATUS_NO_EAS_ON_FILE, "expected STATUS_NO_EAS_ON_FILE, got %x\n", status);
+    ok(U(io).Status == 0xdeadbeef, "expected 0xdeadbeef, got %x\n", U(io).Status);
+    ok(io.Information == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", io.Information);
+
+    /* test with zero buffer */
+    U(io).Status = 0xdeadbeef;
+    io.Information = 0xdeadbeef;
+    status = pNtQueryEaFile(handle, &io, buffer, 0, TRUE, NULL, 0, NULL, FALSE);
+    ok(status == STATUS_NO_EAS_ON_FILE, "expected STATUS_NO_EAS_ON_FILE, got %x\n", status);
+    ok(U(io).Status == 0xdeadbeef, "expected 0xdeadbeef, got %x\n", U(io).Status);
+    ok(io.Information == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", io.Information);
+
+    /* test with very small buffer */
+    U(io).Status = 0xdeadbeef;
+    io.Information = 0xdeadbeef;
+    memset(buffer, 0xcc, EA_BUFFER_SIZE);
+    buffer_len = 4;
+    status = pNtQueryEaFile(handle, &io, buffer, buffer_len, TRUE, NULL, 0, NULL, FALSE);
+    ok(status == STATUS_NO_EAS_ON_FILE, "expected STATUS_NO_EAS_ON_FILE, got %x\n", status);
+    ok(U(io).Status == 0xdeadbeef, "expected 0xdeadbeef, got %x\n", U(io).Status);
+    ok(io.Information == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", io.Information);
+    for (i = 0; i < buffer_len && !buffer[i]; i++);
+    ok(i == buffer_len,  "expected %u bytes filled with 0x00, got %u bytes\n", buffer_len, i);
+    ok(buffer[i] == 0xcc, "data at position %u overwritten\n", buffer[i]);
+
+    /* test with very big buffer */
+    U(io).Status = 0xdeadbeef;
+    io.Information = 0xdeadbeef;
+    memset(buffer, 0xcc, EA_BUFFER_SIZE);
+    buffer_len = EA_BUFFER_SIZE - 1;
+    status = pNtQueryEaFile(handle, &io, buffer, buffer_len, TRUE, NULL, 0, NULL, FALSE);
+    ok(status == STATUS_NO_EAS_ON_FILE, "expected STATUS_NO_EAS_ON_FILE, got %x\n", status);
+    ok(U(io).Status == 0xdeadbeef, "expected 0xdeadbeef, got %x\n", U(io).Status);
+    ok(io.Information == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", io.Information);
+    for (i = 0; i < buffer_len && !buffer[i]; i++);
+    ok(i == buffer_len,  "expected %u bytes filled with 0x00, got %u bytes\n", buffer_len, i);
+    ok(buffer[i] == 0xcc, "data at position %u overwritten\n", buffer[i]);
+
+    CloseHandle(handle);
+    #undef EA_BUFFER_SIZE
+}
+
 static INT build_reparse_buffer(WCHAR *filename, REPARSE_DATA_BUFFER **pbuffer)
 {
     REPARSE_DATA_BUFFER *buffer;
@@ -3072,9 +4644,12 @@ START_TEST(file)
     pNtQueryInformationFile = (void *)GetProcAddress(hntdll, "NtQueryInformationFile");
     pNtQueryDirectoryFile   = (void *)GetProcAddress(hntdll, "NtQueryDirectoryFile");
     pNtQueryVolumeInformationFile = (void *)GetProcAddress(hntdll, "NtQueryVolumeInformationFile");
+    pNtQueryFullAttributesFile = (void *)GetProcAddress(hntdll, "NtQueryFullAttributesFile");
+    pNtQueryEaFile          = (void *)GetProcAddress(hntdll, "NtQueryEaFile");
 
     test_read_write();
     test_NtCreateFile();
+    test_readonly();
     create_file_test();
     open_file_test();
     delete_file_test();
@@ -3088,8 +4663,11 @@ START_TEST(file)
     test_file_name_information();
     test_file_full_size_information();
     test_file_all_name_information();
+    test_file_rename_information();
+    test_file_link_information();
     test_file_disposition_information();
     test_query_volume_information_file();
     test_query_attribute_information_file();
+    test_query_ea();
     test_junction_points();
 }
index f8ef346..b099a5c 100755 (executable)
@@ -839,72 +839,142 @@ static void test_pack_IMAGE_LINENUMBER(void)
 static void test_pack_IMAGE_LOAD_CONFIG_DIRECTORY(void)
 {
     /* IMAGE_LOAD_CONFIG_DIRECTORY */
-#ifndef __REACTOS__
-    TEST_TYPE_SIZE   (IMAGE_LOAD_CONFIG_DIRECTORY, 88)
-#endif
+    TEST_TYPE_SIZE   (IMAGE_LOAD_CONFIG_DIRECTORY, 112)
     TEST_TYPE_ALIGN  (IMAGE_LOAD_CONFIG_DIRECTORY, 8)
-    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY, Size, 4)
-    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY, Size, 4)
-    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, Size, 0)
-    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY, TimeDateStamp, 4)
-    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY, TimeDateStamp, 4)
-    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, TimeDateStamp, 4)
-    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY, MajorVersion, 2)
-    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY, MajorVersion, 2)
-    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, MajorVersion, 8)
-    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY, MinorVersion, 2)
-    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY, MinorVersion, 2)
-    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, MinorVersion, 10)
-    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY, GlobalFlagsClear, 4)
-    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY, GlobalFlagsClear, 4)
-    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, GlobalFlagsClear, 12)
-    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY, GlobalFlagsSet, 4)
-    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY, GlobalFlagsSet, 4)
-    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, GlobalFlagsSet, 16)
-    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY, CriticalSectionDefaultTimeout, 4)
-    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY, CriticalSectionDefaultTimeout, 4)
-    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, CriticalSectionDefaultTimeout, 20)
-#ifndef __REACTOS__  // wine headers are broken
-    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY, DeCommitFreeBlockThreshold, 4)
-    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY, DeCommitFreeBlockThreshold, 4)
-    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, DeCommitFreeBlockThreshold, 24)
-    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY, DeCommitTotalFreeThreshold, 4)
-    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY, DeCommitTotalFreeThreshold, 4)
-    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, DeCommitTotalFreeThreshold, 28)
-    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY, LockPrefixTable, 8)
-    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY, LockPrefixTable, 8)
-    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, LockPrefixTable, 32)
-    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY, MaximumAllocationSize, 4)
-    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY, MaximumAllocationSize, 4)
-    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, MaximumAllocationSize, 40)
-    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY, VirtualMemoryThreshold, 4)
-    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY, VirtualMemoryThreshold, 4)
-    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, VirtualMemoryThreshold, 44)
-    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY, ProcessHeapFlags, 4)
-    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY, ProcessHeapFlags, 4)
-    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, ProcessHeapFlags, 48)
-    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY, ProcessAffinityMask, 4)
-    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY, ProcessAffinityMask, 4)
-    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, ProcessAffinityMask, 52)
-    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY, CSDVersion, 2)
-    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY, CSDVersion, 2)
-    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, CSDVersion, 56)
-    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY, Reserved1, 2)
-    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY, Reserved1, 2)
-    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, Reserved1, 58)
-    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY, EditList, 8)
-    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY, EditList, 8)
-    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, EditList, 64)
-    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY, SecurityCookie, 4)
-    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY, SecurityCookie, 4)
-    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, SecurityCookie, 72)
-    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY, SEHandlerTable, 4)
-    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY, SEHandlerTable, 4)
-    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, SEHandlerTable, 76)
-    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY, SEHandlerCount, 4)
-    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY, SEHandlerCount, 4)
-    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, SEHandlerCount, 80)
-#endif
+}
+
+static void test_pack_IMAGE_LOAD_CONFIG_DIRECTORY32(void)
+{
+    /* IMAGE_LOAD_CONFIG_DIRECTORY32 */
+    TEST_TYPE_SIZE   (IMAGE_LOAD_CONFIG_DIRECTORY32, 88)
+    TEST_TYPE_ALIGN  (IMAGE_LOAD_CONFIG_DIRECTORY32, 8)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY32, Size, 4)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY32, Size, 4)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY32, Size, 0)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY32, TimeDateStamp, 4)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY32, TimeDateStamp, 4)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY32, TimeDateStamp, 4)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY32, MajorVersion, 2)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY32, MajorVersion, 2)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY32, MajorVersion, 8)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY32, MinorVersion, 2)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY32, MinorVersion, 2)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY32, MinorVersion, 10)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY32, GlobalFlagsClear, 4)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY32, GlobalFlagsClear, 4)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY32, GlobalFlagsClear, 12)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY32, GlobalFlagsSet, 4)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY32, GlobalFlagsSet, 4)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY32, GlobalFlagsSet, 16)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY32, CriticalSectionDefaultTimeout, 4)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY32, CriticalSectionDefaultTimeout, 4)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY32, CriticalSectionDefaultTimeout, 20)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY32, DeCommitFreeBlockThreshold, 4)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY32, DeCommitFreeBlockThreshold, 4)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY32, DeCommitFreeBlockThreshold, 24)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY32, DeCommitTotalFreeThreshold, 4)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY32, DeCommitTotalFreeThreshold, 4)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY32, DeCommitTotalFreeThreshold, 28)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY32, LockPrefixTable, 8)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY32, LockPrefixTable, 8)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY32, LockPrefixTable, 32)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY32, MaximumAllocationSize, 4)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY32, MaximumAllocationSize, 4)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY32, MaximumAllocationSize, 40)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY32, VirtualMemoryThreshold, 4)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY32, VirtualMemoryThreshold, 4)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY32, VirtualMemoryThreshold, 44)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY32, ProcessHeapFlags, 4)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY32, ProcessHeapFlags, 4)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY32, ProcessHeapFlags, 48)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY32, ProcessAffinityMask, 4)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY32, ProcessAffinityMask, 4)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY32, ProcessAffinityMask, 52)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY32, CSDVersion, 2)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY32, CSDVersion, 2)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY32, CSDVersion, 56)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY32, Reserved1, 2)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY32, Reserved1, 2)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY32, Reserved1, 58)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY32, EditList, 8)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY32, EditList, 8)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY32, EditList, 64)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY32, SecurityCookie, 4)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY32, SecurityCookie, 4)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY32, SecurityCookie, 72)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY32, SEHandlerTable, 4)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY32, SEHandlerTable, 4)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY32, SEHandlerTable, 76)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY32, SEHandlerCount, 4)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY32, SEHandlerCount, 4)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY32, SEHandlerCount, 80)
+}
+
+static void test_pack_IMAGE_LOAD_CONFIG_DIRECTORY64(void)
+{
+    /* IMAGE_LOAD_CONFIG_DIRECTORY64 */
+    TEST_TYPE_SIZE   (IMAGE_LOAD_CONFIG_DIRECTORY64, 112)
+    TEST_TYPE_ALIGN  (IMAGE_LOAD_CONFIG_DIRECTORY64, 8)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY64, Size, 4)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY64, Size, 4)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY64, Size, 0)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY64, TimeDateStamp, 4)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY64, TimeDateStamp, 4)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY64, TimeDateStamp, 4)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY64, MajorVersion, 2)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY64, MajorVersion, 2)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY64, MajorVersion, 8)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY64, MinorVersion, 2)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY64, MinorVersion, 2)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY64, MinorVersion, 10)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY64, GlobalFlagsClear, 4)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY64, GlobalFlagsClear, 4)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY64, GlobalFlagsClear, 12)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY64, GlobalFlagsSet, 4)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY64, GlobalFlagsSet, 4)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY64, GlobalFlagsSet, 16)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY64, CriticalSectionDefaultTimeout, 4)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY64, CriticalSectionDefaultTimeout, 4)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY64, CriticalSectionDefaultTimeout, 20)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY64, DeCommitFreeBlockThreshold, 8)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY64, DeCommitFreeBlockThreshold, 8)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY64, DeCommitFreeBlockThreshold, 24)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY64, DeCommitTotalFreeThreshold, 8)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY64, DeCommitTotalFreeThreshold, 8)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY64, DeCommitTotalFreeThreshold, 32)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY64, LockPrefixTable, 8)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY64, LockPrefixTable, 8)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY64, LockPrefixTable, 40)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY64, MaximumAllocationSize, 8)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY64, MaximumAllocationSize, 8)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY64, MaximumAllocationSize, 48)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY64, VirtualMemoryThreshold, 8)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY64, VirtualMemoryThreshold, 8)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY64, VirtualMemoryThreshold, 56)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY64, ProcessAffinityMask, 8)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY64, ProcessAffinityMask, 8)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY64, ProcessAffinityMask, 64)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY64, ProcessHeapFlags, 4)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY64, ProcessHeapFlags, 4)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY64, ProcessHeapFlags, 72)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY64, CSDVersion, 2)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY64, CSDVersion, 2)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY64, CSDVersion, 76)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY64, Reserved1, 2)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY64, Reserved1, 2)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY64, Reserved1, 78)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY64, EditList, 8)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY64, EditList, 8)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY64, EditList, 80)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY64, SecurityCookie, 8)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY64, SecurityCookie, 8)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY64, SecurityCookie, 88)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY64, SEHandlerTable, 8)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY64, SEHandlerTable, 8)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY64, SEHandlerTable, 96)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY64, SEHandlerCount, 8)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY64, SEHandlerCount, 8)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY64, SEHandlerCount, 104)
 }
 
 static void test_pack_IMAGE_NT_HEADERS(void)
@@ -2109,10 +2179,6 @@ static void test_pack_PIMAGE_LOAD_CONFIG_DIRECTORY(void)
     /* PIMAGE_LOAD_CONFIG_DIRECTORY */
     TEST_TYPE_SIZE   (PIMAGE_LOAD_CONFIG_DIRECTORY, 8)
     TEST_TYPE_ALIGN  (PIMAGE_LOAD_CONFIG_DIRECTORY, 8)
-#ifndef __REACTOS__ // wine headers are broken
-    TEST_TARGET_SIZE (PIMAGE_LOAD_CONFIG_DIRECTORY, 88)
-#endif
-    TEST_TARGET_ALIGN(PIMAGE_LOAD_CONFIG_DIRECTORY, 8)
 }
 
 static void test_pack_PIMAGE_NT_HEADERS(void)
@@ -4192,66 +4258,140 @@ static void test_pack_IMAGE_LOAD_CONFIG_DIRECTORY(void)
     /* IMAGE_LOAD_CONFIG_DIRECTORY */
     TEST_TYPE_SIZE   (IMAGE_LOAD_CONFIG_DIRECTORY, 72)
     TEST_TYPE_ALIGN  (IMAGE_LOAD_CONFIG_DIRECTORY, 4)
-    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY, Size, 4)
-    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY, Size, 4)
-    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, Size, 0)
-    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY, TimeDateStamp, 4)
-    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY, TimeDateStamp, 4)
-    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, TimeDateStamp, 4)
-    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY, MajorVersion, 2)
-    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY, MajorVersion, 2)
-    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, MajorVersion, 8)
-    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY, MinorVersion, 2)
-    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY, MinorVersion, 2)
-    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, MinorVersion, 10)
-    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY, GlobalFlagsClear, 4)
-    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY, GlobalFlagsClear, 4)
-    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, GlobalFlagsClear, 12)
-    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY, GlobalFlagsSet, 4)
-    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY, GlobalFlagsSet, 4)
-    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, GlobalFlagsSet, 16)
-    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY, CriticalSectionDefaultTimeout, 4)
-    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY, CriticalSectionDefaultTimeout, 4)
-    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, CriticalSectionDefaultTimeout, 20)
-    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY, DeCommitFreeBlockThreshold, 4)
-    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY, DeCommitFreeBlockThreshold, 4)
-    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, DeCommitFreeBlockThreshold, 24)
-    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY, DeCommitTotalFreeThreshold, 4)
-    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY, DeCommitTotalFreeThreshold, 4)
-    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, DeCommitTotalFreeThreshold, 28)
-    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY, LockPrefixTable, 4)
-    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY, LockPrefixTable, 4)
-    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, LockPrefixTable, 32)
-    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY, MaximumAllocationSize, 4)
-    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY, MaximumAllocationSize, 4)
-    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, MaximumAllocationSize, 36)
-    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY, VirtualMemoryThreshold, 4)
-    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY, VirtualMemoryThreshold, 4)
-    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, VirtualMemoryThreshold, 40)
-    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY, ProcessHeapFlags, 4)
-    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY, ProcessHeapFlags, 4)
-    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, ProcessHeapFlags, 44)
-    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY, ProcessAffinityMask, 4)
-    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY, ProcessAffinityMask, 4)
-    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, ProcessAffinityMask, 48)
-    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY, CSDVersion, 2)
-    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY, CSDVersion, 2)
-    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, CSDVersion, 52)
-    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY, Reserved1, 2)
-    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY, Reserved1, 2)
-    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, Reserved1, 54)
-    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY, EditList, 4)
-    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY, EditList, 4)
-    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, EditList, 56)
-    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY, SecurityCookie, 4)
-    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY, SecurityCookie, 4)
-    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, SecurityCookie, 60)
-    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY, SEHandlerTable, 4)
-    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY, SEHandlerTable, 4)
-    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, SEHandlerTable, 64)
-    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY, SEHandlerCount, 4)
-    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY, SEHandlerCount, 4)
-    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, SEHandlerCount, 68)
+}
+
+static void test_pack_IMAGE_LOAD_CONFIG_DIRECTORY32(void)
+{
+    /* IMAGE_LOAD_CONFIG_DIRECTORY32 */
+    TEST_TYPE_SIZE   (IMAGE_LOAD_CONFIG_DIRECTORY32, 72)
+    TEST_TYPE_ALIGN  (IMAGE_LOAD_CONFIG_DIRECTORY32, 4)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY32, Size, 4)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY32, Size, 4)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY32, Size, 0)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY32, TimeDateStamp, 4)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY32, TimeDateStamp, 4)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY32, TimeDateStamp, 4)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY32, MajorVersion, 2)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY32, MajorVersion, 2)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY32, MajorVersion, 8)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY32, MinorVersion, 2)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY32, MinorVersion, 2)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY32, MinorVersion, 10)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY32, GlobalFlagsClear, 4)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY32, GlobalFlagsClear, 4)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY32, GlobalFlagsClear, 12)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY32, GlobalFlagsSet, 4)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY32, GlobalFlagsSet, 4)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY32, GlobalFlagsSet, 16)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY32, CriticalSectionDefaultTimeout, 4)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY32, CriticalSectionDefaultTimeout, 4)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY32, CriticalSectionDefaultTimeout, 20)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY32, DeCommitFreeBlockThreshold, 4)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY32, DeCommitFreeBlockThreshold, 4)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY32, DeCommitFreeBlockThreshold, 24)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY32, DeCommitTotalFreeThreshold, 4)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY32, DeCommitTotalFreeThreshold, 4)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY32, DeCommitTotalFreeThreshold, 28)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY32, LockPrefixTable, 4)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY32, LockPrefixTable, 4)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY32, LockPrefixTable, 32)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY32, MaximumAllocationSize, 4)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY32, MaximumAllocationSize, 4)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY32, MaximumAllocationSize, 36)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY32, VirtualMemoryThreshold, 4)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY32, VirtualMemoryThreshold, 4)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY32, VirtualMemoryThreshold, 40)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY32, ProcessHeapFlags, 4)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY32, ProcessHeapFlags, 4)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY32, ProcessHeapFlags, 44)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY32, ProcessAffinityMask, 4)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY32, ProcessAffinityMask, 4)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY32, ProcessAffinityMask, 48)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY32, CSDVersion, 2)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY32, CSDVersion, 2)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY32, CSDVersion, 52)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY32, Reserved1, 2)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY32, Reserved1, 2)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY32, Reserved1, 54)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY32, EditList, 4)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY32, EditList, 4)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY32, EditList, 56)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY32, SecurityCookie, 4)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY32, SecurityCookie, 4)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY32, SecurityCookie, 60)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY32, SEHandlerTable, 4)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY32, SEHandlerTable, 4)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY32, SEHandlerTable, 64)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY32, SEHandlerCount, 4)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY32, SEHandlerCount, 4)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY32, SEHandlerCount, 68)
+}
+
+static void test_pack_IMAGE_LOAD_CONFIG_DIRECTORY64(void)
+{
+    /* IMAGE_LOAD_CONFIG_DIRECTORY64 */
+    TEST_TYPE_SIZE   (IMAGE_LOAD_CONFIG_DIRECTORY64, 112)
+    TEST_TYPE_ALIGN  (IMAGE_LOAD_CONFIG_DIRECTORY64, 8)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY64, Size, 4)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY64, Size, 4)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY64, Size, 0)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY64, TimeDateStamp, 4)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY64, TimeDateStamp, 4)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY64, TimeDateStamp, 4)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY64, MajorVersion, 2)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY64, MajorVersion, 2)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY64, MajorVersion, 8)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY64, MinorVersion, 2)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY64, MinorVersion, 2)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY64, MinorVersion, 10)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY64, GlobalFlagsClear, 4)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY64, GlobalFlagsClear, 4)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY64, GlobalFlagsClear, 12)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY64, GlobalFlagsSet, 4)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY64, GlobalFlagsSet, 4)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY64, GlobalFlagsSet, 16)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY64, CriticalSectionDefaultTimeout, 4)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY64, CriticalSectionDefaultTimeout, 4)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY64, CriticalSectionDefaultTimeout, 20)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY64, DeCommitFreeBlockThreshold, 8)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY64, DeCommitFreeBlockThreshold, 8)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY64, DeCommitFreeBlockThreshold, 24)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY64, DeCommitTotalFreeThreshold, 8)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY64, DeCommitTotalFreeThreshold, 8)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY64, DeCommitTotalFreeThreshold, 32)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY64, LockPrefixTable, 8)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY64, LockPrefixTable, 8)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY64, LockPrefixTable, 40)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY64, MaximumAllocationSize, 8)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY64, MaximumAllocationSize, 8)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY64, MaximumAllocationSize, 48)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY64, VirtualMemoryThreshold, 8)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY64, VirtualMemoryThreshold, 8)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY64, VirtualMemoryThreshold, 56)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY64, ProcessAffinityMask, 8)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY64, ProcessAffinityMask, 8)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY64, ProcessAffinityMask, 64)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY64, ProcessHeapFlags, 4)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY64, ProcessHeapFlags, 4)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY64, ProcessHeapFlags, 72)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY64, CSDVersion, 2)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY64, CSDVersion, 2)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY64, CSDVersion, 76)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY64, Reserved1, 2)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY64, Reserved1, 2)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY64, Reserved1, 78)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY64, EditList, 8)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY64, EditList, 8)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY64, EditList, 80)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY64, SecurityCookie, 8)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY64, SecurityCookie, 8)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY64, SecurityCookie, 88)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY64, SEHandlerTable, 8)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY64, SEHandlerTable, 8)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY64, SEHandlerTable, 96)
+    TEST_FIELD_SIZE  (IMAGE_LOAD_CONFIG_DIRECTORY64, SEHandlerCount, 8)
+    TEST_FIELD_ALIGN (IMAGE_LOAD_CONFIG_DIRECTORY64, SEHandlerCount, 8)
+    TEST_FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY64, SEHandlerCount, 104)
 }
 
 static void test_pack_IMAGE_NT_HEADERS(void)
@@ -5456,8 +5596,6 @@ static void test_pack_PIMAGE_LOAD_CONFIG_DIRECTORY(void)
     /* PIMAGE_LOAD_CONFIG_DIRECTORY */
     TEST_TYPE_SIZE   (PIMAGE_LOAD_CONFIG_DIRECTORY, 4)
     TEST_TYPE_ALIGN  (PIMAGE_LOAD_CONFIG_DIRECTORY, 4)
-    TEST_TARGET_SIZE (PIMAGE_LOAD_CONFIG_DIRECTORY, 72)
-    TEST_TARGET_ALIGN(PIMAGE_LOAD_CONFIG_DIRECTORY, 4)
 }
 
 static void test_pack_PIMAGE_NT_HEADERS(void)
@@ -6828,6 +6966,8 @@ static void test_pack(void)
     test_pack_IMAGE_IMPORT_DESCRIPTOR();
     test_pack_IMAGE_LINENUMBER();
     test_pack_IMAGE_LOAD_CONFIG_DIRECTORY();
+    test_pack_IMAGE_LOAD_CONFIG_DIRECTORY32();
+    test_pack_IMAGE_LOAD_CONFIG_DIRECTORY64();
     test_pack_IMAGE_NT_HEADERS();
     test_pack_IMAGE_NT_HEADERS32();
     test_pack_IMAGE_NT_HEADERS64();
index 5fff490..c0e2b1a 100755 (executable)
@@ -477,27 +477,47 @@ static void test_query_handle(void)
     ULONG ReturnLength;
     ULONG SystemInformationLength = sizeof(SYSTEM_HANDLE_INFORMATION);
     SYSTEM_HANDLE_INFORMATION* shi = HeapAlloc(GetProcessHeap(), 0, SystemInformationLength);
+    HANDLE event_handle;
+
+    event_handle = CreateEventA(NULL, FALSE, FALSE, NULL);
+    ok( event_handle != NULL, "CreateEventA failed %u\n", GetLastError() );
 
     /* Request the needed length : a SystemInformationLength greater than one struct sets ReturnLength */
+    ReturnLength = 0xdeadbeef;
     status = pNtQuerySystemInformation(SystemHandleInformation, shi, SystemInformationLength, &ReturnLength);
-    todo_wine ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
+    ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
+    ok( ReturnLength != 0xdeadbeef, "Expected valid ReturnLength\n" );
 
     SystemInformationLength = ReturnLength;
     shi = HeapReAlloc(GetProcessHeap(), 0, shi , SystemInformationLength);
+
+    ReturnLength = 0xdeadbeef;
     status = pNtQuerySystemInformation(SystemHandleInformation, shi, SystemInformationLength, &ReturnLength);
     if (status != STATUS_INFO_LENGTH_MISMATCH) /* vista */
     {
-        ok( status == STATUS_SUCCESS,
-            "Expected STATUS_SUCCESS, got %08x\n", status);
-
-        /* Check if we have some return values */
-        trace("Number of Handles : %d\n", shi->Count);
-        todo_wine
+        ULONG ExpectedLength = FIELD_OFFSET(SYSTEM_HANDLE_INFORMATION, Handle[shi->Count]);
+        unsigned int i;
+        BOOL found = FALSE;
+
+        ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status );
+        ok( ReturnLength == ExpectedLength, "Expected length %u, got %u\n", ExpectedLength, ReturnLength );
+        ok( shi->Count > 1, "Expected more than 1 handles, got %u\n", shi->Count );
+        for (i = 0; i < shi->Count; i++)
         {
-            /* our implementation is a stub for now */
-            ok( shi->Count > 1, "Expected more than 1 handles, got (%d)\n", shi->Count);
+            if (shi->Handle[i].OwnerPid == GetCurrentProcessId() &&
+                (HANDLE)(ULONG_PTR)shi->Handle[i].HandleValue == event_handle)
+            {
+                found = TRUE;
+                break;
+            }
         }
+        ok( found, "Expected to find event handle in handle list\n" );
     }
+
+    status = pNtQuerySystemInformation(SystemHandleInformation, NULL, SystemInformationLength, &ReturnLength);
+    ok( status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got %08x\n", status );
+
+    CloseHandle(event_handle);
     HeapFree( GetProcessHeap(), 0, shi);
 }
 
@@ -1442,6 +1462,8 @@ static void test_mapprotection(void)
     *(unsigned char*)addr = 0xc3;       /* lret ... in both i386 and x86_64 */
 #elif defined(__arm__)
     *(unsigned long*)addr = 0xe12fff1e; /* bx lr */
+#elif defined(__aarch64__)
+    *(unsigned long*)addr = 0xd65f03c0; /* ret */
 #else
     ok(0, "Add a return opcode for your architecture or expect a crash in this test\n");
 #endif
@@ -1695,6 +1717,69 @@ static void test_NtGetCurrentProcessorNumber(void)
     ok(status == STATUS_SUCCESS, "got 0x%x (expected STATUS_SUCCESS)\n", status);
 }
 
+static DWORD WINAPI start_address_thread(void *arg)
+{
+    PRTL_THREAD_START_ROUTINE entry;
+    NTSTATUS status;
+    DWORD ret;
+
+    entry = NULL;
+    ret = 0xdeadbeef;
+    status = pNtQueryInformationThread(GetCurrentThread(), ThreadQuerySetWin32StartAddress,
+                                       &entry, sizeof(entry), &ret);
+    ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
+    ok(ret == sizeof(entry), "NtQueryInformationThread returned %u bytes\n", ret);
+    ok(entry == (void *)start_address_thread, "expected %p, got %p\n", start_address_thread, entry);
+    return 0;
+}
+
+static void test_thread_start_address(void)
+{
+    PRTL_THREAD_START_ROUTINE entry, expected_entry;
+    IMAGE_NT_HEADERS *nt;
+    NTSTATUS status;
+    HANDLE thread;
+    void *module;
+    DWORD ret;
+
+    module = GetModuleHandleA(0);
+    ok(module != NULL, "expected non-NULL address for module\n");
+    nt = RtlImageNtHeader(module);
+    ok(nt != NULL, "expected non-NULL address for NT header\n");
+
+    entry = NULL;
+    ret = 0xdeadbeef;
+    status = pNtQueryInformationThread(GetCurrentThread(), ThreadQuerySetWin32StartAddress,
+                                       &entry, sizeof(entry), &ret);
+    ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
+    ok(ret == sizeof(entry), "NtQueryInformationThread returned %u bytes\n", ret);
+    expected_entry = (void *)((char *)module + nt->OptionalHeader.AddressOfEntryPoint);
+    ok(entry == expected_entry, "expected %p, got %p\n", expected_entry, entry);
+
+    entry = (void *)0xdeadbeef;
+    status = pNtSetInformationThread(GetCurrentThread(), ThreadQuerySetWin32StartAddress,
+                                     &entry, sizeof(entry));
+    ok(status == STATUS_SUCCESS || status == STATUS_INVALID_PARAMETER, /* >= Vista */
+       "expected STATUS_SUCCESS or STATUS_INVALID_PARAMETER, got %08x\n", status);
+
+    if (status == STATUS_SUCCESS)
+    {
+        entry = NULL;
+        ret = 0xdeadbeef;
+        status = pNtQueryInformationThread(GetCurrentThread(), ThreadQuerySetWin32StartAddress,
+                                           &entry, sizeof(entry), &ret);
+        ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
+        ok(ret == sizeof(entry), "NtQueryInformationThread returned %u bytes\n", ret);
+        ok(entry == (void *)0xdeadbeef, "expected 0xdeadbeef, got %p\n", entry);
+    }
+
+    thread = CreateThread(NULL, 0, start_address_thread, NULL, 0, NULL);
+    ok(thread != INVALID_HANDLE_VALUE, "CreateThread failed with %d\n", GetLastError());
+    ret = WaitForSingleObject(thread, 1000);
+    ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", ret);
+    CloseHandle(thread);
+}
+
 START_TEST(info)
 {
     char **argv;
@@ -1820,5 +1905,10 @@ START_TEST(info)
 
     trace("Starting test_affinity()\n");
     test_affinity();
+
+    trace("Starting test_NtGetCurrentProcessorNumber()\n");
     test_NtGetCurrentProcessorNumber();
+
+    trace("Starting test_thread_start_address()\n");
+    test_thread_start_address();
 }
index 83b63d8..65e9260 100644 (file)
@@ -54,6 +54,7 @@ static NTSTATUS (WINAPI *pNtCreateKeyedEvent)( HANDLE *, ACCESS_MASK, const OBJE
 static NTSTATUS (WINAPI *pNtOpenKeyedEvent)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES * );
 static NTSTATUS (WINAPI *pNtWaitForKeyedEvent)( HANDLE, const void *, BOOLEAN, const LARGE_INTEGER * );
 static NTSTATUS (WINAPI *pNtReleaseKeyedEvent)( HANDLE, const void *, BOOLEAN, const LARGE_INTEGER * );
+static NTSTATUS (WINAPI *pNtCreateIoCompletion)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, ULONG);
 
 #define KEYEDEVENT_WAIT       0x0001
 #define KEYEDEVENT_WAKE       0x0002
@@ -150,7 +151,7 @@ static void test_namespace_pipe(void)
 
     pRtlInitUnicodeString(&str, buffer3);
     InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
-    status = pNtOpenFile(&h, GENERIC_READ, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN);
+    status = pNtOpenFile(&h, GENERIC_READ, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, 0);
     ok(status == STATUS_OBJECT_PATH_NOT_FOUND ||
        status == STATUS_PIPE_NOT_AVAILABLE ||
        status == STATUS_OBJECT_NAME_INVALID || /* vista */
@@ -159,7 +160,7 @@ static void test_namespace_pipe(void)
 
     pRtlInitUnicodeString(&str, buffer4);
     InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
-    status = pNtOpenFile(&h, GENERIC_READ, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN);
+    status = pNtOpenFile(&h, GENERIC_READ, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, 0);
     ok(status == STATUS_OBJECT_NAME_NOT_FOUND ||
        status == STATUS_OBJECT_NAME_INVALID, /* vista */
         "NtOpenFile should have failed with STATUS_OBJECT_NAME_NOT_FOUND got(%08x)\n", status);
@@ -657,8 +658,10 @@ static void test_symboliclink(void)
     pRtlFreeUnicodeString(&target);
 
     pRtlCreateUnicodeStringFromAsciiz(&str, "test-link\\NUL");
-    status = pNtOpenFile(&h, GENERIC_READ, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN);
-    todo_wine ok(status == STATUS_SUCCESS, "Failed to open NUL device(%08x)\n", status);
+    status = pNtOpenFile(&h, GENERIC_READ, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, 0);
+    ok(status == STATUS_SUCCESS, "Failed to open NUL device(%08x)\n", status);
+    status = pNtOpenFile(&h, GENERIC_READ, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE);
+    ok(status == STATUS_SUCCESS, "Failed to open NUL device(%08x)\n", status);
     pRtlFreeUnicodeString(&str);
 
     pNtClose(h);
@@ -672,12 +675,16 @@ static void test_query_object(void)
                                  '\\','t','e','s','t','_','e','v','e','n','t'};
     static const WCHAR type_event[] = {'E','v','e','n','t'};
     static const WCHAR type_file[] = {'F','i','l','e'};
+    static const WCHAR type_iocompletion[] = {'I','o','C','o','m','p','l','e','t','i','o','n'};
+    static const WCHAR type_directory[] = {'D','i','r','e','c','t','o','r','y'};
+    static const WCHAR type_section[] = {'S','e','c','t','i','o','n'};
     HANDLE handle;
     char buffer[1024];
     NTSTATUS status;
     ULONG len, expected_len;
     UNICODE_STRING *str;
-    char dir[MAX_PATH];
+    char dir[MAX_PATH], tmp_path[MAX_PATH], file1[MAX_PATH + 16];
+    LARGE_INTEGER size;
 
     handle = CreateEventA( NULL, FALSE, FALSE, "test_event" );
 
@@ -784,6 +791,66 @@ static void test_query_object(void)
                   "wrong/bad type name %s (%p)\n", wine_dbgstr_w(str->Buffer), str->Buffer );
 
     pNtClose( handle );
+
+    GetTempPathA(MAX_PATH, tmp_path);
+    GetTempFileNameA(tmp_path, "foo", 0, file1);
+    handle = CreateFileA(file1, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
+    len = 0;
+    memset( buffer, 0, sizeof(buffer) );
+    status = pNtQueryObject( handle, ObjectTypeInformation, buffer, sizeof(buffer), &len );
+    ok( status == STATUS_SUCCESS, "NtQueryObject failed %x\n", status );
+    ok( len > sizeof(OBJECT_TYPE_INFORMATION), "unexpected len %u\n", len );
+    str = (UNICODE_STRING *)buffer;
+    expected_len = sizeof(OBJECT_TYPE_INFORMATION) + str->Length + sizeof(WCHAR);
+    ok( len >= expected_len, "unexpected len %u\n", len );
+    ok( str->Buffer && !memcmp( str->Buffer, type_file, sizeof(type_file) ),
+                  "wrong/bad type name %s (%p)\n", wine_dbgstr_w(str->Buffer), str->Buffer );
+    DeleteFileA( file1 );
+    pNtClose( handle );
+
+    status = pNtCreateIoCompletion( &handle, IO_COMPLETION_ALL_ACCESS, NULL, 0 );
+    ok( status == STATUS_SUCCESS, "NtCreateIoCompletion failed %x\n", status);
+    len = 0;
+    memset( buffer, 0, sizeof(buffer) );
+    status = pNtQueryObject( handle, ObjectTypeInformation, buffer, sizeof(buffer), &len );
+    ok( status == STATUS_SUCCESS, "NtQueryObject failed %x\n", status );
+    ok( len > sizeof(OBJECT_TYPE_INFORMATION), "unexpected len %u\n", len );
+    str = (UNICODE_STRING *)buffer;
+    expected_len = sizeof(OBJECT_TYPE_INFORMATION) + str->Length + sizeof(WCHAR);
+    ok( len >= expected_len, "unexpected len %u\n", len );
+    ok( str->Buffer && !memcmp( str->Buffer, type_iocompletion, sizeof(type_iocompletion) ),
+                  "wrong/bad type name %s (%p)\n", wine_dbgstr_w(str->Buffer), str->Buffer );
+    pNtClose( handle );
+
+    status = pNtCreateDirectoryObject( &handle, DIRECTORY_QUERY, NULL );
+    ok(status == STATUS_SUCCESS, "Failed to create Directory %08x\n", status);
+    len = 0;
+    memset( buffer, 0, sizeof(buffer) );
+    status = pNtQueryObject( handle, ObjectTypeInformation, buffer, sizeof(buffer), &len );
+    ok( status == STATUS_SUCCESS, "NtQueryObject failed %x\n", status );
+    ok( len > sizeof(OBJECT_TYPE_INFORMATION), "unexpected len %u\n", len );
+    str = (UNICODE_STRING *)buffer;
+    expected_len = sizeof(OBJECT_TYPE_INFORMATION) + str->Length + sizeof(WCHAR);
+    ok( len >= expected_len, "unexpected len %u\n", len );
+    ok( str->Buffer && !memcmp( str->Buffer, type_directory, sizeof(type_directory) ),
+                  "wrong/bad type name %s (%p)\n", wine_dbgstr_w(str->Buffer), str->Buffer );
+    pNtClose( handle );
+
+    size.u.LowPart = 256;
+    size.u.HighPart = 0;
+    status = pNtCreateSection( &handle, SECTION_MAP_WRITE, NULL, &size, PAGE_READWRITE, SEC_COMMIT, 0 );
+    ok( status == STATUS_SUCCESS , "NtCreateSection returned %x\n", status );
+    len = 0;
+    memset( buffer, 0, sizeof(buffer) );
+    status = pNtQueryObject( handle, ObjectTypeInformation, buffer, sizeof(buffer), &len );
+    ok( status == STATUS_SUCCESS, "NtQueryObject failed %x\n", status );
+    ok( len > sizeof(OBJECT_TYPE_INFORMATION), "unexpected len %u\n", len );
+    str = (UNICODE_STRING *)buffer;
+    expected_len = sizeof(OBJECT_TYPE_INFORMATION) + str->Length + sizeof(WCHAR);
+    ok( len >= expected_len, "unexpected len %u\n", len );
+    ok( str->Buffer && !memcmp( str->Buffer, type_section, sizeof(type_section) ),
+                  "wrong/bad type name %s (%p)\n", wine_dbgstr_w(str->Buffer), str->Buffer );
+    pNtClose( handle );
 }
 
 static void test_type_mismatch(void)
@@ -1055,23 +1122,19 @@ static void test_null_device(void)
        "expected STATUS_OBJECT_TYPE_MISMATCH, got %08x\n", status);
 
     status = pNtOpenFile(&null, GENERIC_READ | GENERIC_WRITE, &attr, &iosb,
-                         FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN);
+                         FILE_SHARE_READ | FILE_SHARE_WRITE, 0);
     ok(status == STATUS_SUCCESS,
        "expected STATUS_SUCCESS, got %08x\n", status);
 
     SetLastError(0xdeadbeef);
     ret = WriteFile(null, buf, sizeof(buf), &num_bytes, NULL);
-    todo_wine
     ok(!ret, "WriteFile unexpectedly succeeded\n");
-    todo_wine
     ok(GetLastError() == ERROR_INVALID_PARAMETER,
        "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
 
     SetLastError(0xdeadbeef);
     ret = ReadFile(null, buf, sizeof(buf), &num_bytes, NULL);
-    todo_wine
     ok(!ret, "ReadFile unexpectedly succeeded\n");
-    todo_wine
     ok(GetLastError() == ERROR_INVALID_PARAMETER,
        "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
 
@@ -1166,6 +1229,7 @@ START_TEST(om)
     pNtOpenKeyedEvent       =  (void *)GetProcAddress(hntdll, "NtOpenKeyedEvent");
     pNtWaitForKeyedEvent    =  (void *)GetProcAddress(hntdll, "NtWaitForKeyedEvent");
     pNtReleaseKeyedEvent    =  (void *)GetProcAddress(hntdll, "NtReleaseKeyedEvent");
+    pNtCreateIoCompletion   =  (void *)GetProcAddress(hntdll, "NtCreateIoCompletion");
 
     test_case_sensitive();
     test_namespace_pipe();
index 5fc86b5..8984e24 100755 (executable)
@@ -123,6 +123,7 @@ static NTSTATUS (WINAPI * pRtlQueryRegistryValues)(IN ULONG, IN PCWSTR,IN PRTL_Q
 static NTSTATUS (WINAPI * pRtlCheckRegistryKey)(IN ULONG,IN PWSTR);
 static NTSTATUS (WINAPI * pRtlOpenCurrentUser)(IN ACCESS_MASK, PHANDLE);
 static NTSTATUS (WINAPI * pNtOpenKey)(PHANDLE, IN ACCESS_MASK, IN POBJECT_ATTRIBUTES);
+static NTSTATUS (WINAPI * pNtOpenKeyEx)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, ULONG);
 static NTSTATUS (WINAPI * pNtClose)(IN HANDLE);
 static NTSTATUS (WINAPI * pNtFlushKey)(HANDLE);
 static NTSTATUS (WINAPI * pNtDeleteKey)(HANDLE);
@@ -145,6 +146,10 @@ static NTSTATUS (WINAPI * pRtlFreeHeap)(PVOID, ULONG, PVOID);
 static LPVOID   (WINAPI * pRtlAllocateHeap)(PVOID,ULONG,ULONG);
 static NTSTATUS (WINAPI * pRtlZeroMemory)(PVOID, ULONG);
 static NTSTATUS (WINAPI * pRtlpNtQueryValueKey)(HANDLE,ULONG*,PBYTE,DWORD*,void *);
+static NTSTATUS (WINAPI * pNtNotifyChangeKey)(HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,ULONG,BOOLEAN,PVOID,ULONG,BOOLEAN);
+static NTSTATUS (WINAPI * pNtNotifyChangeMultipleKeys)(HANDLE,ULONG,OBJECT_ATTRIBUTES*,HANDLE,PIO_APC_ROUTINE,
+                                                       void*,IO_STATUS_BLOCK*,ULONG,BOOLEAN,void*,ULONG,BOOLEAN);
+static NTSTATUS (WINAPI * pNtWaitForSingleObject)(HANDLE,BOOLEAN,const LARGE_INTEGER*);
 
 static HMODULE hntdll = 0;
 static int CurrentTest = 0;
@@ -182,6 +187,7 @@ static BOOL InitFunctionPtrs(void)
     NTDLL_GET_PROC(NtQueryInformationProcess)
     NTDLL_GET_PROC(NtSetValueKey)
     NTDLL_GET_PROC(NtOpenKey)
+    NTDLL_GET_PROC(NtNotifyChangeKey)
     NTDLL_GET_PROC(RtlFormatCurrentUserKeyPath)
     NTDLL_GET_PROC(RtlCompareUnicodeString)
     NTDLL_GET_PROC(RtlReAllocateHeap)
@@ -192,9 +198,12 @@ static BOOL InitFunctionPtrs(void)
     NTDLL_GET_PROC(RtlZeroMemory)
     NTDLL_GET_PROC(RtlpNtQueryValueKey)
     NTDLL_GET_PROC(RtlOpenCurrentUser)
+    NTDLL_GET_PROC(NtWaitForSingleObject)
 
     /* optional functions */
     pNtQueryLicenseValue = (void *)GetProcAddress(hntdll, "NtQueryLicenseValue");
+    pNtOpenKeyEx = (void *)GetProcAddress(hntdll, "NtOpenKeyEx");
+    pNtNotifyChangeMultipleKeys = (void *)GetProcAddress(hntdll, "NtNotifyChangeMultipleKeys");
 
     return TRUE;
 }
@@ -351,6 +360,18 @@ static void test_NtOpenKey(void)
     attr.Length *= 2;
     status = pNtOpenKey(&key, am, &attr);
     ok(status == STATUS_INVALID_PARAMETER, "Expected STATUS_INVALID_PARAMETER, got: 0x%08x\n", status);
+
+    if (!pNtOpenKeyEx)
+    {
+        win_skip("NtOpenKeyEx not available\n");
+        return;
+    }
+
+    InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
+    status = pNtOpenKeyEx(&key, KEY_WRITE|KEY_READ, &attr, 0);
+    ok(status == STATUS_SUCCESS, "NtOpenKeyEx Failed: 0x%08x\n", status);
+
+    pNtClose(key);
 }
 
 static void test_NtCreateKey(void)
@@ -509,14 +530,14 @@ static void test_NtQueryValueKey(void)
     OBJECT_ATTRIBUTES attr;
     UNICODE_STRING ValName;
     KEY_VALUE_BASIC_INFORMATION *basic_info;
-    KEY_VALUE_PARTIAL_INFORMATION *partial_info;
+    KEY_VALUE_PARTIAL_INFORMATION *partial_info, pi;
     KEY_VALUE_FULL_INFORMATION *full_info;
     DWORD len, expected;
 
     pRtlCreateUnicodeStringFromAsciiz(&ValName, "deletetest");
 
     InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
-    status = pNtOpenKey(&key, KEY_READ, &attr);
+    status = pNtOpenKey(&key, KEY_READ|KEY_SET_VALUE, &attr);
     ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08x\n", status);
 
     len = FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[0]);
@@ -611,8 +632,18 @@ static void test_NtQueryValueKey(void)
     ok(len == expected, "NtQueryValueKey wrong len %u\n", len);
 
     HeapFree(GetProcessHeap(), 0, partial_info);
+    pRtlFreeUnicodeString(&ValName);
 
+    pRtlCreateUnicodeStringFromAsciiz(&ValName, "custtest");
+    status = pNtSetValueKey(key, &ValName, 0, 0xff00ff00, NULL, 0);
+    ok(status == STATUS_SUCCESS, "NtSetValueKey Failed: 0x%08x\n", status);
+
+    status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, &pi, sizeof(pi), &len);
+    ok(status == STATUS_SUCCESS, "NtQueryValueKey should have returned STATUS_BUFFER_TOO_SMALL instead of 0x%08x\n", status);
+    ok(pi.Type == 0xff00ff00, "Type=%x\n", pi.Type);
+    ok(pi.DataLength == 0, "DataLength=%u\n", pi.DataLength);
     pRtlFreeUnicodeString(&ValName);
+
     pNtClose(key);
 }
 
@@ -1445,12 +1476,14 @@ static void test_long_value_name(void)
 
 static void test_NtQueryKey(void)
 {
-    HANDLE key;
+    HANDLE key, subkey, subkey2;
     NTSTATUS status;
     OBJECT_ATTRIBUTES attr;
     ULONG length, len;
     KEY_NAME_INFORMATION *info = NULL;
+    KEY_CACHED_INFORMATION cached_info;
     UNICODE_STRING str;
+    DWORD dw;
 
     InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
     status = pNtOpenKey(&key, KEY_READ, &attr);
@@ -1485,9 +1518,171 @@ static void test_NtQueryKey(void)
        wine_dbgstr_wn(winetestpath.Buffer, winetestpath.Length/sizeof(WCHAR)));
 
     HeapFree(GetProcessHeap(), 0, info);
+
+    attr.RootDirectory = key;
+    attr.ObjectName = &str;
+    pRtlCreateUnicodeStringFromAsciiz(&str, "test_subkey");
+    status = pNtCreateKey(&subkey, GENERIC_ALL, &attr, 0, 0, 0, 0);
+    ok(status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status);
+
+    status = pNtQueryKey(subkey, KeyCachedInformation, &cached_info, sizeof(cached_info), &len);
+    ok(status == STATUS_SUCCESS, "NtQueryKey Failed: 0x%08x\n", status);
+
+    if (status == STATUS_SUCCESS)
+    {
+        ok(len == sizeof(cached_info), "got unexpected length %d\n", len);
+        ok(cached_info.SubKeys == 0, "cached_info.SubKeys = %u\n", cached_info.SubKeys);
+        ok(cached_info.MaxNameLen == 0, "cached_info.MaxNameLen = %u\n", cached_info.MaxNameLen);
+        ok(cached_info.Values == 0, "cached_info.Values = %u\n", cached_info.Values);
+        ok(cached_info.MaxValueNameLen == 0, "cached_info.MaxValueNameLen = %u\n", cached_info.MaxValueNameLen);
+        ok(cached_info.MaxValueDataLen == 0, "cached_info.MaxValueDataLen = %u\n", cached_info.MaxValueDataLen);
+        ok(cached_info.NameLength == 22, "cached_info.NameLength = %u\n", cached_info.NameLength);
+    }
+
+    attr.RootDirectory = subkey;
+    attr.ObjectName = &str;
+    pRtlCreateUnicodeStringFromAsciiz(&str, "test_subkey2");
+    status = pNtCreateKey(&subkey2, GENERIC_ALL, &attr, 0, 0, 0, 0);
+    ok(status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status);
+
+    pRtlCreateUnicodeStringFromAsciiz(&str, "val");
+    dw = 64;
+    status = pNtSetValueKey( subkey, &str, 0, REG_DWORD, &dw, sizeof(dw) );
+    ok( status == STATUS_SUCCESS, "NtSetValueKey failed: 0x%08x\n", status );
+
+    if (!winetest_interactive)
+        skip("ROSTESTS-198: Causes an assert in Cm.\n");
+    else
+    {
+        status = pNtQueryKey(subkey, KeyCachedInformation, &cached_info, sizeof(cached_info), &len);
+        ok(status == STATUS_SUCCESS, "NtQueryKey Failed: 0x%08x\n", status);
+
+        if (status == STATUS_SUCCESS)
+        {
+            ok(len == sizeof(cached_info), "got unexpected length %d\n", len);
+            ok(cached_info.SubKeys == 1, "cached_info.SubKeys = %u\n", cached_info.SubKeys);
+            ok(cached_info.MaxNameLen == 24, "cached_info.MaxNameLen = %u\n", cached_info.MaxNameLen);
+            ok(cached_info.Values == 1, "cached_info.Values = %u\n", cached_info.Values);
+            ok(cached_info.MaxValueNameLen == 6, "cached_info.MaxValueNameLen = %u\n", cached_info.MaxValueNameLen);
+            ok(cached_info.MaxValueDataLen == 4, "cached_info.MaxValueDataLen = %u\n", cached_info.MaxValueDataLen);
+            ok(cached_info.NameLength == 22, "cached_info.NameLength = %u\n", cached_info.NameLength);
+        }
+    }
+
+    status = pNtDeleteKey(subkey2);
+    ok(status == STATUS_SUCCESS, "NtDeleteSubkey failed: %x\n", status);
+    status = pNtDeleteKey(subkey);
+    ok(status == STATUS_SUCCESS, "NtDeleteSubkey failed: %x\n", status);
+
+    pNtClose(subkey2);
+    pNtClose(subkey);
     pNtClose(key);
 }
 
+static void test_notify(void)
+{
+    OBJECT_ATTRIBUTES attr;
+    LARGE_INTEGER timeout;
+    IO_STATUS_BLOCK iosb;
+    UNICODE_STRING str;
+    HANDLE key, events[2], subkey;
+    NTSTATUS status;
+
+    InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
+    status = pNtOpenKey(&key, KEY_ALL_ACCESS, &attr);
+    ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08x\n", status);
+
+    events[0] = CreateEventW(NULL, FALSE, TRUE, NULL);
+    ok(events[0] != NULL, "CreateEvent failed: %u\n", GetLastError());
+    events[1] = CreateEventW(NULL, FALSE, TRUE, NULL);
+    ok(events[1] != NULL, "CreateEvent failed: %u\n", GetLastError());
+
+    status = pNtNotifyChangeKey(key, events[0], NULL, NULL, &iosb, REG_NOTIFY_CHANGE_NAME, FALSE, NULL, 0, TRUE);
+    ok(status == STATUS_PENDING, "NtNotifyChangeKey returned %x\n", status);
+    status = pNtNotifyChangeKey(key, events[1], NULL, NULL, &iosb, REG_NOTIFY_CHANGE_NAME, FALSE, NULL, 0, TRUE);
+    ok(status == STATUS_PENDING, "NtNotifyChangeKey returned %x\n", status);
+
+    timeout.QuadPart = 0;
+    status = pNtWaitForSingleObject(events[0], FALSE, &timeout);
+    ok(status == STATUS_TIMEOUT, "NtWaitForSingleObject returned %x\n", status);
+    status = pNtWaitForSingleObject(events[1], FALSE, &timeout);
+    ok(status == STATUS_TIMEOUT, "NtWaitForSingleObject returned %x\n", status);
+
+    attr.RootDirectory = key;
+    attr.ObjectName = &str;
+
+    pRtlCreateUnicodeStringFromAsciiz(&str, "test_subkey");
+    status = pNtCreateKey(&subkey, GENERIC_ALL, &attr, 0, 0, 0, 0);
+    ok(status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status);
+
+    status = pNtWaitForSingleObject(events[0], FALSE, &timeout);
+    ok(status == STATUS_SUCCESS, "NtWaitForSingleObject returned %x\n", status);
+    status = pNtWaitForSingleObject(events[1], FALSE, &timeout);
+    ok(status == STATUS_SUCCESS, "NtWaitForSingleObject returned %x\n", status);
+
+    status = pNtNotifyChangeKey(key, events[0], NULL, NULL, &iosb, 0, FALSE, NULL, 0, TRUE);
+    ok(status == STATUS_PENDING, "NtNotifyChangeKey returned %x\n", status);
+    status = pNtNotifyChangeKey(key, events[1], NULL, NULL, &iosb, 0, FALSE, NULL, 0, TRUE);
+    ok(status == STATUS_PENDING, "NtNotifyChangeKey returned %x\n", status);
+
+    status = pNtDeleteKey(subkey);
+    ok(status == STATUS_SUCCESS, "NtDeleteSubkey failed: %x\n", status);
+
+    status = pNtWaitForSingleObject(events[0], FALSE, &timeout);
+    ok(status == STATUS_SUCCESS, "NtWaitForSingleObject returned %x\n", status);
+    status = pNtWaitForSingleObject(events[1], FALSE, &timeout);
+    ok(status == STATUS_SUCCESS, "NtWaitForSingleObject returned %x\n", status);
+
+    pNtClose(subkey);
+
+    status = pNtNotifyChangeKey(key, events[0], NULL, NULL, &iosb, 0, FALSE, NULL, 0, TRUE);
+    ok(status == STATUS_PENDING, "NtNotifyChangeKey returned %x\n", status);
+    status = pNtNotifyChangeKey(key, events[1], NULL, NULL, &iosb, 0, FALSE, NULL, 0, TRUE);
+    ok(status == STATUS_PENDING, "NtNotifyChangeKey returned %x\n", status);
+
+    pNtClose(key);
+
+    status = pNtWaitForSingleObject(events[0], FALSE, &timeout);
+    ok(status == STATUS_SUCCESS, "NtWaitForSingleObject returned %x\n", status);
+    status = pNtWaitForSingleObject(events[1], FALSE, &timeout);
+    ok(status == STATUS_SUCCESS, "NtWaitForSingleObject returned %x\n", status);
+
+    if (pNtNotifyChangeMultipleKeys)
+    {
+        InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
+        status = pNtOpenKey(&key, KEY_ALL_ACCESS, &attr);
+        ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08x\n", status);
+
+        status = pNtNotifyChangeMultipleKeys(key, 0, NULL, events[0], NULL, NULL, &iosb, REG_NOTIFY_CHANGE_NAME, FALSE, NULL, 0, TRUE);
+        ok(status == STATUS_PENDING, "NtNotifyChangeKey returned %x\n", status);
+
+        timeout.QuadPart = 0;
+        status = pNtWaitForSingleObject(events[0], FALSE, &timeout);
+        ok(status == STATUS_TIMEOUT, "NtWaitForSingleObject returned %x\n", status);
+
+        attr.RootDirectory = key;
+        attr.ObjectName = &str;
+        pRtlCreateUnicodeStringFromAsciiz(&str, "test_subkey");
+        status = pNtCreateKey(&subkey, GENERIC_ALL, &attr, 0, 0, 0, 0);
+        ok(status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status);
+
+        status = pNtWaitForSingleObject(events[0], FALSE, &timeout);
+        ok(status == STATUS_SUCCESS, "NtWaitForSingleObject returned %x\n", status);
+
+        status = pNtDeleteKey(subkey);
+        ok(status == STATUS_SUCCESS, "NtDeleteSubkey failed: %x\n", status);
+        pNtClose(subkey);
+        pNtClose(key);
+    }
+    else
+    {
+        win_skip("NtNotifyChangeMultipleKeys not available\n");
+    }
+
+    pNtClose(events[0]);
+    pNtClose(events[1]);
+}
+
 START_TEST(reg)
 {
     static const WCHAR winetest[] = {'\\','W','i','n','e','T','e','s','t',0};
@@ -1512,6 +1707,7 @@ START_TEST(reg)
     test_NtQueryLicenseKey();
     test_NtQueryValueKey();
     test_long_value_name();
+    test_notify();
     test_NtDeleteKey();
     test_symlinks();
     test_redirection();
index bf2c22e..90b9323 100755 (executable)
@@ -108,6 +108,8 @@ static NTSTATUS  (WINAPI *pRtlGetCompressionWorkSpaceSize)(USHORT, PULONG, PULON
 static NTSTATUS  (WINAPI *pRtlDecompressBuffer)(USHORT, PUCHAR, ULONG, const UCHAR*, ULONG, PULONG);
 static NTSTATUS  (WINAPI *pRtlDecompressFragment)(USHORT, PUCHAR, ULONG, const UCHAR*, ULONG, ULONG, PULONG, PVOID);
 static NTSTATUS  (WINAPI *pRtlCompressBuffer)(USHORT, const UCHAR*, ULONG, PUCHAR, ULONG, ULONG, PULONG, PVOID);
+static BOOL      (WINAPI *pRtlIsCriticalSectionLocked)(RTL_CRITICAL_SECTION *);
+static BOOL      (WINAPI *pRtlIsCriticalSectionLockedByThread)(RTL_CRITICAL_SECTION *);
 
 static HMODULE hkernel32 = 0;
 static BOOL      (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
@@ -170,6 +172,8 @@ static void InitFunctionPtrs(void)
         pRtlDecompressBuffer = (void *)GetProcAddress(hntdll, "RtlDecompressBuffer");
         pRtlDecompressFragment = (void *)GetProcAddress(hntdll, "RtlDecompressFragment");
         pRtlCompressBuffer = (void *)GetProcAddress(hntdll, "RtlCompressBuffer");
+        pRtlIsCriticalSectionLocked = (void *)GetProcAddress(hntdll, "RtlIsCriticalSectionLocked");
+        pRtlIsCriticalSectionLockedByThread = (void *)GetProcAddress(hntdll, "RtlIsCriticalSectionLockedByThread");
     }
     hkernel32 = LoadLibraryA("kernel32.dll");
     ok(hkernel32 != 0, "LoadLibrary failed\n");
@@ -722,46 +726,11 @@ static void test_RtlUniform(void)
 }
 
 
-static ULONG my_RtlRandom(PULONG seed)
-{
-    static ULONG saved_value[128] =
-    { /*   0 */ 0x4c8bc0aa, 0x4c022957, 0x2232827a, 0x2f1e7626, 0x7f8bdafb, 0x5c37d02a, 0x0ab48f72, 0x2f0c4ffa,
-      /*   8 */ 0x290e1954, 0x6b635f23, 0x5d3885c0, 0x74b49ff8, 0x5155fa54, 0x6214ad3f, 0x111e9c29, 0x242a3a09,
-      /*  16 */ 0x75932ae1, 0x40ac432e, 0x54f7ba7a, 0x585ccbd5, 0x6df5c727, 0x0374dad1, 0x7112b3f1, 0x735fc311,
-      /*  24 */ 0x404331a9, 0x74d97781, 0x64495118, 0x323e04be, 0x5974b425, 0x4862e393, 0x62389c1d, 0x28a68b82,
-      /*  32 */ 0x0f95da37, 0x7a50bbc6, 0x09b0091c, 0x22cdb7b4, 0x4faaed26, 0x66417ccd, 0x189e4bfa, 0x1ce4e8dd,
-      /*  40 */ 0x5274c742, 0x3bdcf4dc, 0x2d94e907, 0x32eac016, 0x26d33ca3, 0x60415a8a, 0x31f57880, 0x68c8aa52,
-      /*  48 */ 0x23eb16da, 0x6204f4a1, 0x373927c1, 0x0d24eb7c, 0x06dd7379, 0x2b3be507, 0x0f9c55b1, 0x2c7925eb,
-      /*  56 */ 0x36d67c9a, 0x42f831d9, 0x5e3961cb, 0x65d637a8, 0x24bb3820, 0x4d08e33d, 0x2188754f, 0x147e409e,
-      /*  64 */ 0x6a9620a0, 0x62e26657, 0x7bd8ce81, 0x11da0abb, 0x5f9e7b50, 0x23e444b6, 0x25920c78, 0x5fc894f0,
-      /*  72 */ 0x5e338cbb, 0x404237fd, 0x1d60f80f, 0x320a1743, 0x76013d2b, 0x070294ee, 0x695e243b, 0x56b177fd,
-      /*  80 */ 0x752492e1, 0x6decd52f, 0x125f5219, 0x139d2e78, 0x1898d11e, 0x2f7ee785, 0x4db405d8, 0x1a028a35,
-      /*  88 */ 0x63f6f323, 0x1f6d0078, 0x307cfd67, 0x3f32a78a, 0x6980796c, 0x462b3d83, 0x34b639f2, 0x53fce379,
-      /*  96 */ 0x74ba50f4, 0x1abc2c4b, 0x5eeaeb8d, 0x335a7a0d, 0x3973dd20, 0x0462d66b, 0x159813ff, 0x1e4643fd,
-      /* 104 */ 0x06bc5c62, 0x3115e3fc, 0x09101613, 0x47af2515, 0x4f11ec54, 0x78b99911, 0x3db8dd44, 0x1ec10b9b,
-      /* 112 */ 0x5b5506ca, 0x773ce092, 0x567be81a, 0x5475b975, 0x7a2cde1a, 0x494536f5, 0x34737bb4, 0x76d9750b,
-      /* 120 */ 0x2a1f6232, 0x2e49644d, 0x7dddcbe7, 0x500cebdb, 0x619dab9e, 0x48c626fe, 0x1cda3193, 0x52dabe9d };
-    ULONG rand;
-    int pos;
-    ULONG result;
-
-    rand = (*seed * 0x7fffffed + 0x7fffffc3) % 0x7fffffff;
-    *seed = (rand * 0x7fffffed + 0x7fffffc3) % 0x7fffffff;
-    pos = *seed & 0x7f;
-    result = saved_value[pos];
-    saved_value[pos] = rand;
-    return(result);
-}
-
-
 static void test_RtlRandom(void)
 {
-    ULONGLONG num;
+    int i, j;
     ULONG seed;
-    ULONG seed_bak;
-    ULONG seed_expected;
-    ULONG result;
-    ULONG result_expected;
+    ULONG res[512];
 
     if (!pRtlRandom)
     {
@@ -769,185 +738,14 @@ static void test_RtlRandom(void)
         return;
     }
 
-/*
- * Unlike RtlUniform, RtlRandom is not documented. We guess that for
- * RtlRandom D.H. Lehmer's 1948 algorithm is used like stated in
- * the documentation of the RtlUniform function. This algorithm is:
- *
- * seed = (seed * const_1 + const_2) % const_3;
- *
- * According to the RtlUniform documentation the random number is
- * distributed over [0..MAXLONG], but in reality it is distributed
- * over [0..MAXLONG-1]. Therefore const_3 might be MAXLONG + 1 or
- * MAXLONG:
- *
- * seed = (seed * const_1 + const_2) % (MAXLONG + 1);
- *
- * or
- *
- * seed = (seed * const_1 + const_2) % MAXLONG;
- *
- * To find out const_2 we just call RtlRandom with seed set to 0:
- */
     seed = 0;
-    result_expected = 0x320a1743;
-    seed_expected =0x44b;
-    result = pRtlRandom(&seed);
-
-/*
- * Windows Vista uses different algorithms, so skip the rest of the tests
- * until that is figured out. Trace output for the failures is about 10.5 MB!
- */
-
-    if (seed == 0x3fc) {
-        skip("Most likely running on Windows Vista which uses a different algorithm\n");
-        return;
+    for (i = 0; i < sizeof(res) / sizeof(res[0]); i++)
+    {
+        res[i] = pRtlRandom(&seed);
+        ok(seed != res[i], "%i: seed is same as res %x\n", i, seed);
+        for (j = 0; j < i; j++)
+            ok(res[i] != res[j], "res[%i] (%x) is same as res[%i] (%x)\n", j, res[j], i, res[i]);
     }
-
-    ok(result == result_expected,
-        "pRtlRandom(&seed (seed == 0)) returns %x, expected %x\n",
-        result, result_expected);
-    ok(seed == seed_expected,
-        "pRtlRandom(&seed (seed == 0)) sets seed to %x, expected %x\n",
-        seed, seed_expected);
-/*
- * Seed is not equal to result as with RtlUniform. To see more we
- * call RtlRandom again with seed set to 0:
- */
-    seed = 0;
-    result_expected = 0x7fffffc3;
-    seed_expected =0x44b;
-    result = pRtlRandom(&seed);
-    ok(result == result_expected,
-        "RtlRandom(&seed (seed == 0)) returns %x, expected %x\n",
-        result, result_expected);
-    ok(seed == seed_expected,
-        "RtlRandom(&seed (seed == 0)) sets seed to %x, expected %x\n",
-        seed, seed_expected);
-/*
- * Seed is set to the same value as before but the result is different.
- * To see more we call RtlRandom again with seed set to 0:
- */
-    seed = 0;
-    result_expected = 0x7fffffc3;
-    seed_expected =0x44b;
-    result = pRtlRandom(&seed);
-    ok(result == result_expected,
-        "RtlRandom(&seed (seed == 0)) returns %x, expected %x\n",
-        result, result_expected);
-    ok(seed == seed_expected,
-        "RtlRandom(&seed (seed == 0)) sets seed to %x, expected %x\n",
-        seed, seed_expected);
-/*
- * Seed is again set to the same value as before. This time we also
- * have the same result as before. Interestingly the value of the
- * result is 0x7fffffc3 which is the same value used in RtlUniform
- * as const_2. If we do
- *
- * seed = 0;
- * result = RtlUniform(&seed);
- *
- * we get the same result (0x7fffffc3) as with
- *
- * seed = 0;
- * RtlRandom(&seed);
- * seed = 0;
- * result = RtlRandom(&seed);
- *
- * And there is another interesting thing. If we do
- *
- * seed = 0;
- * RtlUniform(&seed);
- * RtlUniform(&seed);
- *
- * seed is set to the value 0x44b which ist the same value that
- *
- * seed = 0;
- * RtlRandom(&seed);
- *
- * assigns to seed. Putting these two findings together leads to
- * the conclusion that RtlRandom saves the value in some variable,
- * like in the following algorithm:
- *
- * result = saved_value;
- * saved_value = RtlUniform(&seed);
- * RtlUniform(&seed);
- * return(result);
- *
- * Now we do further tests with seed set to 1:
- */
-    seed = 1;
-    result_expected = 0x7a50bbc6;
-    seed_expected =0x5a1;
-    result = pRtlRandom(&seed);
-    ok(result == result_expected,
-        "RtlRandom(&seed (seed == 1)) returns %x, expected %x\n",
-        result, result_expected);
-    ok(seed == seed_expected,
-        "RtlRandom(&seed (seed == 1)) sets seed to %x, expected %x\n",
-        seed, seed_expected);
-/*
- * If there is just one saved_value the result now would be
- * 0x7fffffc3. From this test we can see that there is more than
- * one saved_value, like with this algorithm:
- *
- * result = saved_value[pos];
- * saved_value[pos] = RtlUniform(&seed);
- * RtlUniform(&seed);
- * return(result);
- *
- * But how is the value of pos determined? The calls to RtlUniform
- * create a sequence of random numbers. Every second random number
- * is put into the saved_value array and is used in some later call
- * of RtlRandom as result. The only reasonable source to determine
- * pos are the random numbers generated by RtlUniform which are not
- * put into the saved_value array. This are the values of seed
- * between the two calls of RtlUniform as in this algorithm:
- *
- * rand = RtlUniform(&seed);
- * RtlUniform(&seed);
- * pos = position(seed);
- * result = saved_value[pos];
- * saved_value[pos] = rand;
- * return(result);
- *
- * What remains to be determined is: The size of the saved_value array,
- * the initial values of the saved_value array and the function
- * position(seed). These tests are not shown here. 
- * The result of these tests is: The size of the saved_value array
- * is 128, the initial values can be seen in the my_RtlRandom
- * function and the position(seed) function is (seed & 0x7f).
- *
- * For a full test of RtlRandom use one of the following loop heads:
- *
- *  for (num = 0; num <= 0xffffffff; num++) {
- *      seed = num;
- *      ...
- *
- *  seed = 0;
- *  for (num = 0; num <= 0xffffffff; num++) {
- *      ...
- */
-    seed = 0;
-    for (num = 0; num <= 100000; num++) {
-        seed_bak = seed;
-       seed_expected = seed;
-        result_expected = my_RtlRandom(&seed_expected);
-       /* The following corrections are necessary because the */
-       /* previous tests changed the saved_value array */
-       if (num == 0) {
-           result_expected = 0x7fffffc3;
-        } else if (num == 81) {
-           result_expected = 0x7fffffb1;
-       } /* if */
-        result = pRtlRandom(&seed);
-        ok(result == result_expected,
-                "test: 0x%x%08x RtlUniform(&seed (seed == %x)) returns %x, expected %x\n",
-                (DWORD)(num >> 32), (DWORD)num, seed_bak, result, result_expected);
-        ok(seed == seed_expected,
-                "test: 0x%x%08x RtlUniform(&seed (seed == %x)) sets seed to %x, expected %x\n",
-                (DWORD)(num >> 32), (DWORD)num, seed_bak, result, seed_expected);
-    } /* for */
 }
 
 
@@ -2716,6 +2514,79 @@ static void test_LdrLockLoaderLock(void)
     pLdrUnlockLoaderLock(0, magic);
 }
 
+static void test_RtlCompressBuffer(void)
+{
+    ULONG compress_workspace, decompress_workspace;
+    static const UCHAR test_buffer[] = "WineWineWine";
+    static UCHAR buf1[0x1000], buf2[0x1000];
+    ULONG final_size, buf_size;
+    UCHAR *workspace = NULL;
+    NTSTATUS status;
+
+    if (!pRtlCompressBuffer || !pRtlDecompressBuffer || !pRtlGetCompressionWorkSpaceSize)
+    {
+        win_skip("skipping RtlCompressBuffer tests, required functions not available\n");
+        return;
+    }
+
+    compress_workspace = decompress_workspace = 0xdeadbeef;
+    status = pRtlGetCompressionWorkSpaceSize(COMPRESSION_FORMAT_LZNT1, &compress_workspace,
+                                             &decompress_workspace);
+    ok(status == STATUS_SUCCESS, "got wrong status 0x%08x\n", status);
+    ok(compress_workspace != 0, "got wrong compress_workspace %u\n", compress_workspace);
+    workspace = HeapAlloc(GetProcessHeap(), 0, compress_workspace);
+    ok(workspace != NULL, "HeapAlloc failed %d\n", GetLastError());
+
+    /* test compression format / engine */
+    final_size = 0xdeadbeef;
+    status = pRtlCompressBuffer(COMPRESSION_FORMAT_NONE, test_buffer, sizeof(test_buffer),
+                                buf1, sizeof(buf1) - 1, 4096, &final_size, workspace);
+    ok(status == STATUS_INVALID_PARAMETER, "got wrong status 0x%08x\n", status);
+    ok(final_size == 0xdeadbeef, "got wrong final_size %u\n", final_size);
+
+    final_size = 0xdeadbeef;
+    status = pRtlCompressBuffer(COMPRESSION_FORMAT_DEFAULT, test_buffer, sizeof(test_buffer),
+                                buf1, sizeof(buf1) - 1, 4096, &final_size, workspace);
+    ok(status == STATUS_INVALID_PARAMETER, "got wrong status 0x%08x\n", status);
+    ok(final_size == 0xdeadbeef, "got wrong final_size %u\n", final_size);
+
+    final_size = 0xdeadbeef;
+    status = pRtlCompressBuffer(0xFF, test_buffer, sizeof(test_buffer),
+                                buf1, sizeof(buf1) - 1, 4096, &final_size, workspace);
+    ok(status == STATUS_UNSUPPORTED_COMPRESSION, "got wrong status 0x%08x\n", status);
+    ok(final_size == 0xdeadbeef, "got wrong final_size %u\n", final_size);
+
+    /* test compression */
+    final_size = 0xdeadbeef;
+    memset(buf1, 0x11, sizeof(buf1));
+    status = pRtlCompressBuffer(COMPRESSION_FORMAT_LZNT1, test_buffer, sizeof(test_buffer),
+                                buf1, sizeof(buf1), 4096, &final_size, workspace);
+    ok(status == STATUS_SUCCESS, "got wrong status 0x%08x\n", status);
+    ok((*(WORD *)buf1 & 0x7000) == 0x3000, "no chunk signature found %04x\n", *(WORD *)buf1);
+    todo_wine
+    ok(final_size < sizeof(test_buffer), "got wrong final_size %u\n", final_size);
+
+    /* test decompression */
+    buf_size = final_size;
+    final_size = 0xdeadbeef;
+    memset(buf2, 0x11, sizeof(buf2));
+    status = pRtlDecompressBuffer(COMPRESSION_FORMAT_LZNT1, buf2, sizeof(buf2),
+                                  buf1, buf_size, &final_size);
+    ok(status == STATUS_SUCCESS, "got wrong status 0x%08x\n", status);
+    ok(final_size == sizeof(test_buffer), "got wrong final_size %u\n", final_size);
+    ok(!memcmp(buf2, test_buffer, sizeof(test_buffer)), "got wrong decoded data\n");
+    ok(buf2[sizeof(test_buffer)] == 0x11, "too many bytes written\n");
+
+    /* buffer too small */
+    final_size = 0xdeadbeef;
+    memset(buf1, 0x11, sizeof(buf1));
+    status = pRtlCompressBuffer(COMPRESSION_FORMAT_LZNT1, test_buffer, sizeof(test_buffer),
+                                buf1, 4, 4096, &final_size, workspace);
+    ok(status == STATUS_BUFFER_TOO_SMALL, "got wrong status 0x%08x\n", status);
+
+    HeapFree(GetProcessHeap(), 0, workspace);
+}
+
 static void test_RtlGetCompressionWorkSpaceSize(void)
 {
     ULONG compress_workspace, decompress_workspace;
@@ -2727,6 +2598,7 @@ static void test_RtlGetCompressionWorkSpaceSize(void)
         return;
     }
 
+    /* test invalid format / engine */
     status = pRtlGetCompressionWorkSpaceSize(COMPRESSION_FORMAT_NONE, &compress_workspace,
                                              &decompress_workspace);
     ok(status == STATUS_INVALID_PARAMETER, "got wrong status 0x%08x\n", status);
@@ -2738,27 +2610,30 @@ static void test_RtlGetCompressionWorkSpaceSize(void)
     status = pRtlGetCompressionWorkSpaceSize(0xFF, &compress_workspace, &decompress_workspace);
     ok(status == STATUS_UNSUPPORTED_COMPRESSION, "got wrong status 0x%08x\n", status);
 
+    /* test LZNT1 with normal and maximum compression */
     compress_workspace = decompress_workspace = 0xdeadbeef;
     status = pRtlGetCompressionWorkSpaceSize(COMPRESSION_FORMAT_LZNT1, &compress_workspace,
                                              &decompress_workspace);
     ok(status == STATUS_SUCCESS, "got wrong status 0x%08x\n", status);
-    ok(compress_workspace != 0, "got wrong compress_workspace %d\n", compress_workspace);
-    ok(decompress_workspace == 0x1000, "got wrong decompress_workspace %d\n", decompress_workspace);
+    ok(compress_workspace != 0, "got wrong compress_workspace %u\n", compress_workspace);
+    ok(decompress_workspace == 0x1000, "got wrong decompress_workspace %u\n", decompress_workspace);
 
     compress_workspace = decompress_workspace = 0xdeadbeef;
     status = pRtlGetCompressionWorkSpaceSize(COMPRESSION_FORMAT_LZNT1 | COMPRESSION_ENGINE_MAXIMUM,
                                              &compress_workspace, &decompress_workspace);
     ok(status == STATUS_SUCCESS, "got wrong status 0x%08x\n", status);
-    ok(compress_workspace != 0, "got wrong compress_workspace %d\n", compress_workspace);
-    ok(decompress_workspace == 0x1000, "got wrong decompress_workspace %d\n", decompress_workspace);
+    ok(compress_workspace != 0, "got wrong compress_workspace %u\n", compress_workspace);
+    ok(decompress_workspace == 0x1000, "got wrong decompress_workspace %u\n", decompress_workspace);
 }
 
 /* helper for test_RtlDecompressBuffer, checks if a chunk is incomplete */
 static BOOL is_incomplete_chunk(const UCHAR *compressed, ULONG compressed_size, BOOL check_all)
 {
     ULONG chunk_size;
+
     if (compressed_size <= sizeof(WORD))
         return TRUE;
+
     while (compressed_size >= sizeof(WORD))
     {
         chunk_size = (*(WORD *)compressed & 0xFFF) + 1;
@@ -2769,16 +2644,15 @@ static BOOL is_incomplete_chunk(const UCHAR *compressed, ULONG compressed_size,
         compressed      += sizeof(WORD) + chunk_size;
         compressed_size -= sizeof(WORD) + chunk_size;
     }
+
     return FALSE;
 }
 
-#define DECOMPRESS_BROKEN_TRUNCATED    1
-#define DECOMPRESS_BROKEN_FRAGMENT     2
+#define DECOMPRESS_BROKEN_FRAGMENT     1 /* < Win 7 */
+#define DECOMPRESS_BROKEN_TRUNCATED    2 /* broken on all machines */
 
 static void test_RtlDecompressBuffer(void)
 {
-    static const UCHAR test_multiple_chunks[] = {0x03, 0x30, 'W', 'i', 'n', 'e',
-                                                 0x03, 0x30, 'W', 'i', 'n', 'e'};
     static const struct
     {
         UCHAR compressed[32];
@@ -2994,28 +2868,28 @@ static void test_RtlDecompressBuffer(void)
 
     /* test compression format / engine */
     final_size = 0xdeadbeef;
-    status = pRtlDecompressBuffer(COMPRESSION_FORMAT_NONE, buf, sizeof(buf) - 1, test_lznt[0].compressed,
+    status = pRtlDecompressBuffer(COMPRESSION_FORMAT_NONE, buf, sizeof(buf), test_lznt[0].compressed,
                                   test_lznt[0].compressed_size, &final_size);
     ok(status == STATUS_INVALID_PARAMETER, "got wrong status 0x%08x\n", status);
-    ok(final_size == 0xdeadbeef, "got wrong final_size %d\n", final_size);
+    ok(final_size == 0xdeadbeef, "got wrong final_size %u\n", final_size);
 
     final_size = 0xdeadbeef;
-    status = pRtlDecompressBuffer(COMPRESSION_FORMAT_DEFAULT, buf, sizeof(buf) - 1, test_lznt[0].compressed,
+    status = pRtlDecompressBuffer(COMPRESSION_FORMAT_DEFAULT, buf, sizeof(buf), test_lznt[0].compressed,
                                   test_lznt[0].compressed_size, &final_size);
     ok(status == STATUS_INVALID_PARAMETER, "got wrong status 0x%08x\n", status);
-    ok(final_size == 0xdeadbeef, "got wrong final_size %d\n", final_size);
+    ok(final_size == 0xdeadbeef, "got wrong final_size %u\n", final_size);
 
     final_size = 0xdeadbeef;
-    status = pRtlDecompressBuffer(0xFF, buf, sizeof(buf) - 1, test_lznt[0].compressed,
+    status = pRtlDecompressBuffer(0xFF, buf, sizeof(buf), test_lznt[0].compressed,
                                   test_lznt[0].compressed_size, &final_size);
     ok(status == STATUS_UNSUPPORTED_COMPRESSION, "got wrong status 0x%08x\n", status);
-    ok(final_size == 0xdeadbeef, "got wrong final_size %d\n", final_size);
+    ok(final_size == 0xdeadbeef, "got wrong final_size %u\n", final_size);
 
     /* regular tests for RtlDecompressBuffer */
     for (i = 0; i < sizeof(test_lznt) / sizeof(test_lznt[0]); i++)
     {
-        trace("Running test %d (compressed_size=%d, compressed_size=%d, status=%d)\n",
-              i, test_lznt[i].compressed_size, test_lznt[i].compressed_size, test_lznt[i].status);
+        trace("Running test %d (compressed_size=%u, uncompressed_size=%u, status=0x%08x)\n",
+              i, test_lznt[i].compressed_size, test_lznt[i].uncompressed_size, test_lznt[i].status);
 
         /* test with very big buffer */
         final_size = 0xdeadbeef;
@@ -3027,11 +2901,11 @@ static void test_RtlDecompressBuffer(void)
         if (!status)
         {
             ok(final_size == test_lznt[i].uncompressed_size,
-               "%d: got wrong final_size %d\n", i, final_size);
+               "%d: got wrong final_size %u\n", i, final_size);
             ok(!memcmp(buf, test_lznt[i].uncompressed, test_lznt[i].uncompressed_size),
                "%d: got wrong decoded data\n", i);
             ok(buf[test_lznt[i].uncompressed_size] == 0x11,
-               "%d: buf[%d] overwritten\n", i, test_lznt[i].uncompressed_size);
+               "%d: buf[%u] was modified\n", i, test_lznt[i].uncompressed_size);
         }
 
         /* test that modifier for compression engine is ignored */
@@ -3044,11 +2918,11 @@ static void test_RtlDecompressBuffer(void)
         if (!status)
         {
             ok(final_size == test_lznt[i].uncompressed_size,
-               "%d: got wrong final_size %d\n", i, final_size);
+               "%d: got wrong final_size %u\n", i, final_size);
             ok(!memcmp(buf, test_lznt[i].uncompressed, test_lznt[i].uncompressed_size),
                "%d: got wrong decoded data\n", i);
             ok(buf[test_lznt[i].uncompressed_size] == 0x11,
-               "%d: buf[%d] overwritten\n", i, test_lznt[i].uncompressed_size);
+               "%d: buf[%u] was modified\n", i, test_lznt[i].uncompressed_size);
         }
 
         /* test with expected output size */
@@ -3062,11 +2936,11 @@ static void test_RtlDecompressBuffer(void)
             if (!status)
             {
                 ok(final_size == test_lznt[i].uncompressed_size,
-                   "%d: got wrong final_size %d\n", i, final_size);
+                   "%d: got wrong final_size %u\n", i, final_size);
                 ok(!memcmp(buf, test_lznt[i].uncompressed, test_lznt[i].uncompressed_size),
                    "%d: got wrong decoded data\n", i);
                 ok(buf[test_lznt[i].uncompressed_size] == 0x11,
-                   "%d: buf[%d] overwritten\n", i, test_lznt[i].uncompressed_size);
+                   "%d: buf[%u] was modified\n", i, test_lznt[i].uncompressed_size);
             }
         }
 
@@ -3077,16 +2951,19 @@ static void test_RtlDecompressBuffer(void)
             memset(buf, 0x11, sizeof(buf));
             status = pRtlDecompressBuffer(COMPRESSION_FORMAT_LZNT1, buf, test_lznt[i].uncompressed_size - 1,
                                           test_lznt[i].compressed, test_lznt[i].compressed_size, &final_size);
-            ok(status == test_lznt[i].status || broken(status == STATUS_BAD_COMPRESSION_BUFFER &&
-               (test_lznt[i].broken_flags & DECOMPRESS_BROKEN_TRUNCATED)), "%d: got wrong status 0x%08x\n", i, status);
+            if (test_lznt[i].broken_flags & DECOMPRESS_BROKEN_TRUNCATED)
+                todo_wine
+                ok(status == STATUS_BAD_COMPRESSION_BUFFER, "%d: got wrong status 0x%08x\n", i, status);
+            else
+                ok(status == test_lznt[i].status, "%d: got wrong status 0x%08x\n", i, status);
             if (!status)
             {
                 ok(final_size == test_lznt[i].uncompressed_size - 1,
-                   "%d: got wrong final_size %d\n", i, final_size);
+                   "%d: got wrong final_size %u\n", i, final_size);
                 ok(!memcmp(buf, test_lznt[i].uncompressed, test_lznt[i].uncompressed_size - 1),
                    "%d: got wrong decoded data\n", i);
                 ok(buf[test_lznt[i].uncompressed_size - 1] == 0x11,
-                   "%d: buf[%d] overwritten\n", i, test_lznt[i].uncompressed_size - 1);
+                   "%d: buf[%u] was modified\n", i, test_lznt[i].uncompressed_size - 1);
             }
         }
 
@@ -3096,82 +2973,84 @@ static void test_RtlDecompressBuffer(void)
         status = pRtlDecompressBuffer(COMPRESSION_FORMAT_LZNT1, buf, 0, test_lznt[i].compressed,
                                       test_lznt[i].compressed_size, &final_size);
         if (is_incomplete_chunk(test_lznt[i].compressed, test_lznt[i].compressed_size, FALSE))
-        {
             ok(status == STATUS_BAD_COMPRESSION_BUFFER, "%d: got wrong status 0x%08x\n", i, status);
-        }
         else
         {
             ok(status == STATUS_SUCCESS, "%d: got wrong status 0x%08x\n", i, status);
-            ok(final_size == 0, "%d: got wrong final_size %d\n", i, final_size);
-            ok(buf[0] == 0x11, "%d: buf[%d] overwritten\n", i, test_lznt[i].uncompressed_size);
+            ok(final_size == 0, "%d: got wrong final_size %u\n", i, final_size);
+            ok(buf[0] == 0x11, "%d: buf[0] was modified\n", i);
         }
 
-        /* test RtlDecompressBuffer with offset = 0 */
+        /* test RtlDecompressFragment with offset = 0 */
         final_size = 0xdeadbeef;
         memset(buf, 0x11, sizeof(buf));
         status = pRtlDecompressFragment(COMPRESSION_FORMAT_LZNT1, buf, sizeof(buf), test_lznt[i].compressed,
                                         test_lznt[i].compressed_size, 0, &final_size, workspace);
-        ok(status == test_lznt[i].status || broken(status == STATUS_BAD_COMPRESSION_BUFFER &&
-           (test_lznt[i].broken_flags & DECOMPRESS_BROKEN_FRAGMENT)), "%d: got wrong status 0x%08x\n", i, status);
+        if (test_lznt[i].broken_flags & DECOMPRESS_BROKEN_FRAGMENT)
+            todo_wine
+            ok(status == STATUS_BAD_COMPRESSION_BUFFER, "%d: got wrong status 0x%08x\n", i, status);
+        else
+            ok(status == test_lznt[i].status, "%d: got wrong status 0x%08x\n", i, status);
         if (!status)
         {
             ok(final_size == test_lznt[i].uncompressed_size,
-               "%d: got wrong final_size %d\n", i, final_size);
+               "%d: got wrong final_size %u\n", i, final_size);
             ok(!memcmp(buf, test_lznt[i].uncompressed, test_lznt[i].uncompressed_size),
                "%d: got wrong decoded data\n", i);
             ok(buf[test_lznt[i].uncompressed_size] == 0x11,
-               "%d: buf[%d] overwritten\n", i, test_lznt[i].uncompressed_size);
+               "%d: buf[%u] was modified\n", i, test_lznt[i].uncompressed_size);
         }
 
-        /* test RtlDecompressBuffer with offset = 1 */
+        /* test RtlDecompressFragment with offset = 1 */
         final_size = 0xdeadbeef;
         memset(buf, 0x11, sizeof(buf));
         status = pRtlDecompressFragment(COMPRESSION_FORMAT_LZNT1, buf, sizeof(buf), test_lznt[i].compressed,
                                         test_lznt[i].compressed_size, 1, &final_size, workspace);
-        ok(status == test_lznt[i].status || broken(status == STATUS_BAD_COMPRESSION_BUFFER &&
-           (test_lznt[i].broken_flags & DECOMPRESS_BROKEN_FRAGMENT)), "%d: got wrong status 0x%08x\n", i, status);
+        if (test_lznt[i].broken_flags & DECOMPRESS_BROKEN_FRAGMENT)
+            todo_wine
+            ok(status == STATUS_BAD_COMPRESSION_BUFFER, "%d: got wrong status 0x%08x\n", i, status);
+        else
+            ok(status == test_lznt[i].status, "%d: got wrong status 0x%08x\n", i, status);
         if (!status)
         {
             if (test_lznt[i].uncompressed_size == 0)
             {
                 todo_wine
-                ok(final_size == 4095,
-                   "%d: got wrong final size %d\n", i, final_size);
+                ok(final_size == 4095, "%d: got wrong final_size %u\n", i, final_size);
                 /* Buffer doesn't contain any useful value on Windows */
-                ok(buf[4095] == 0x11,
-                   "%d: buf[4095] overwritten\n", i);
+                ok(buf[4095] == 0x11, "%d: buf[4095] was modified\n", i);
             }
             else
             {
                 ok(final_size == test_lznt[i].uncompressed_size - 1,
-                   "%d: got wrong final_size %d\n", i, final_size);
+                   "%d: got wrong final_size %u\n", i, final_size);
                 ok(!memcmp(buf, test_lznt[i].uncompressed + 1, test_lznt[i].uncompressed_size - 1),
                    "%d: got wrong decoded data\n", i);
                 ok(buf[test_lznt[i].uncompressed_size - 1] == 0x11,
-                   "%d: buf[%d] overwritten\n", i, test_lznt[i].uncompressed_size - 1);
+                   "%d: buf[%u] was modified\n", i, test_lznt[i].uncompressed_size - 1);
             }
         }
 
-        /* test RtlDecompressBuffer with offset = 4095 */
+        /* test RtlDecompressFragment with offset = 4095 */
         final_size = 0xdeadbeef;
         memset(buf, 0x11, sizeof(buf));
         status = pRtlDecompressFragment(COMPRESSION_FORMAT_LZNT1, buf, sizeof(buf), test_lznt[i].compressed,
                                         test_lznt[i].compressed_size, 4095, &final_size, workspace);
-        ok(status == test_lznt[i].status || broken(status == STATUS_BAD_COMPRESSION_BUFFER &&
-           (test_lznt[i].broken_flags & DECOMPRESS_BROKEN_FRAGMENT)), "%d: got wrong status 0x%08x\n", i, status);
+        if (test_lznt[i].broken_flags & DECOMPRESS_BROKEN_FRAGMENT)
+            todo_wine
+            ok(status == STATUS_BAD_COMPRESSION_BUFFER, "%d: got wrong status 0x%08x\n", i, status);
+        else
+            ok(status == test_lznt[i].status, "%d: got wrong status 0x%08x\n", i, status);
         if (!status)
         {
             todo_wine
-            ok(final_size == 1,
-               "%d: got wrong final size %d\n", i, final_size);
+            ok(final_size == 1, "%d: got wrong final_size %u\n", i, final_size);
             todo_wine
-            ok(buf[0] == 0,
-               "%d: padding is not zero\n", i);
-            ok(buf[1] == 0x11,
-               "%d: buf[1] overwritten\n", i);
+            ok(buf[0] == 0, "%d: padding is not zero\n", i);
+            ok(buf[1] == 0x11, "%d: buf[1] was modified\n", i);
         }
 
-        /* test RtlDecompressBuffer with offset = 4096 */
+        /* test RtlDecompressFragment with offset = 4096 */
         final_size = 0xdeadbeef;
         memset(buf, 0x11, sizeof(buf));
         status = pRtlDecompressFragment(COMPRESSION_FORMAT_LZNT1, buf, sizeof(buf), test_lznt[i].compressed,
@@ -3181,263 +3060,109 @@ static void test_RtlDecompressBuffer(void)
         ok(status == expected_status, "%d: got wrong status 0x%08x, expected 0x%08x\n", i, status, expected_status);
         if (!status)
         {
-            ok(final_size == 0,
-               "%d: got wrong final size %d\n", i, final_size);
-            ok(buf[0] == 0x11,
-               "%d: buf[4096] overwritten\n", i);
+            ok(final_size == 0, "%d: got wrong final_size %u\n", i, final_size);
+            ok(buf[0] == 0x11, "%d: buf[4096] was modified\n", i);
         }
     }
+}
 
-    /* test decoding of multiple chunks with pRtlDecompressBuffer */
-    final_size = 0xdeadbeef;
-    memset(buf, 0x11, sizeof(buf));
-    status = pRtlDecompressBuffer(COMPRESSION_FORMAT_LZNT1, buf, sizeof(buf), test_multiple_chunks,
-                                  sizeof(test_multiple_chunks), &final_size);
-    ok(status == STATUS_SUCCESS || broken(status == STATUS_BAD_COMPRESSION_BUFFER),
-       "got wrong status 0x%08x\n", status);
-    if (!status)
-    {
-        ok(final_size == 4100, "got wrong final_size %d\n", final_size);
-        ok(!memcmp(buf, "Wine", 4), "got wrong decoded data at offset 0\n");
-        ok(buf[4] == 0 && buf[4095] == 0, "padding is not zero\n");
-        ok(!memcmp(buf + 4096, "Wine", 4), "got wrong decoded data at offset 4096\n");
-        ok(buf[4100] == 0x11, "buf[4100] overwritten\n");
-    }
-
-    final_size = 0xdeadbeef;
-    memset(buf, 0x11, sizeof(buf));
-    status = pRtlDecompressBuffer(COMPRESSION_FORMAT_LZNT1, buf, 4097, test_multiple_chunks,
-                                  sizeof(test_multiple_chunks), &final_size);
-    ok(status == STATUS_SUCCESS || broken(status == STATUS_BAD_COMPRESSION_BUFFER),
-       "got wrong status 0x%08x\n", status);
-    if (!status)
-    {
-        ok(final_size == 4097, "got wrong final_size %d\n", final_size);
-        ok(!memcmp(buf, "Wine", 4), "got wrong decoded data at offset 0\n");
-        ok(buf[4] == 0 && buf[4095] == 0, "padding is not zero\n");
-        ok(buf[4096], "got wrong decoded data at offset 4096\n");
-        ok(buf[4097] == 0x11, "buf[4097] overwritten\n");
-    }
-
-    final_size = 0xdeadbeef;
-    memset(buf, 0x11, sizeof(buf));
-    status = pRtlDecompressBuffer(COMPRESSION_FORMAT_LZNT1, buf, 4096, test_multiple_chunks,
-                                  sizeof(test_multiple_chunks), &final_size);
-    ok(status == STATUS_SUCCESS || broken(status == STATUS_BAD_COMPRESSION_BUFFER),
-       "got wrong status 0x%08x\n", status);
-    if (!status)
-    {
-        ok(final_size == 4, "got wrong final_size %d\n", final_size);
-        ok(!memcmp(buf, "Wine", 4), "got wrong decoded data at offset 0\n");
-        ok(buf[4] == 0x11, "buf[4] overwritten\n");
-    }
-
-    final_size = 0xdeadbeef;
-    memset(buf, 0x11, sizeof(buf));
-    status = pRtlDecompressBuffer(COMPRESSION_FORMAT_LZNT1, buf, 4, test_multiple_chunks,
-                                  sizeof(test_multiple_chunks), &final_size);
-    ok(status == STATUS_SUCCESS, "got wrong status 0x%08x\n", status);
-    if (!status)
-    {
-        ok(final_size == 4, "got wrong final_size %d\n", final_size);
-        ok(!memcmp(buf, "Wine", 4), "got wrong decoded data at offset 0\n");
-        ok(buf[4] == 0x11, "buf[4] overwritten\n");
-    }
-
-    final_size = 0xdeadbeef;
-    memset(buf, 0x11, sizeof(buf));
-    status = pRtlDecompressBuffer(COMPRESSION_FORMAT_LZNT1, buf, 3, test_multiple_chunks,
-                                  sizeof(test_multiple_chunks), &final_size);
-    ok(status == STATUS_SUCCESS, "got wrong status 0x%08x\n", status);
-    if (!status)
-    {
-        ok(final_size == 3, "got wrong final_size %d\n", final_size);
-        ok(!memcmp(buf, "Wine", 3), "got wrong decoded data at offset 0\n");
-        ok(buf[3] == 0x11, "buf[3] overwritten\n");
-    }
+#undef DECOMPRESS_BROKEN_FRAGMENT
+#undef DECOMPRESS_BROKEN_TRUNCATED
 
-    final_size = 0xdeadbeef;
-    memset(buf, 0x11, sizeof(buf));
-    status = pRtlDecompressBuffer(COMPRESSION_FORMAT_LZNT1, buf, 0, test_multiple_chunks,
-                                  sizeof(test_multiple_chunks), &final_size);
-    ok(status == STATUS_SUCCESS, "got wrong status 0x%08x\n", status);
-    if (!status)
-    {
-        ok(final_size == 0, "got wrong final_size %d\n", final_size);
-        ok(buf[0] == 0x11, "buf[0] overwritten\n");
-    }
+struct critsect_locked_info
+{
+    CRITICAL_SECTION crit;
+    HANDLE semaphores[2];
+};
 
-    /* test multiple chunks in combination with RtlDecompressBuffer and offset=1 */
-    final_size = 0xdeadbeef;
-    memset(buf, 0x11, sizeof(buf));
-    status = pRtlDecompressFragment(COMPRESSION_FORMAT_LZNT1, buf, sizeof(buf), test_multiple_chunks,
-                                    sizeof(test_multiple_chunks), 1, &final_size, workspace);
-    ok(status == STATUS_SUCCESS || broken(status == STATUS_BAD_COMPRESSION_BUFFER),
-       "got wrong status 0x%08x\n", status);
-    if (!status)
-    {
-        ok(final_size == 4099, "got wrong final_size %d\n", final_size);
-        ok(!memcmp(buf, "ine", 3), "got wrong decoded data at offset 0\n");
-        ok(buf[3] == 0 && buf[4094] == 0, "padding is not zero\n");
-        ok(!memcmp(buf + 4095, "Wine", 4), "got wrong decoded data at offset 4095\n");
-        ok(buf[4099] == 0x11, "buf[4099] overwritten\n");
-    }
+static DWORD WINAPI critsect_locked_thread(void *param)
+{
+    struct critsect_locked_info *info = param;
+    DWORD ret;
 
-    final_size = 0xdeadbeef;
-    memset(buf, 0x11, sizeof(buf));
-    status = pRtlDecompressFragment(COMPRESSION_FORMAT_LZNT1, buf, 4096, test_multiple_chunks,
-                                    sizeof(test_multiple_chunks), 1, &final_size, workspace);
-    ok(status == STATUS_SUCCESS || broken(status == STATUS_BAD_COMPRESSION_BUFFER),
-       "got wrong status 0x%08x\n", status);
-    if (!status)
-    {
-        ok(final_size == 4096, "got wrong final_size %d\n", final_size);
-        ok(!memcmp(buf, "ine", 3), "got wrong decoded data at offset 0\n");
-        ok(buf[3] == 0 && buf[4094] == 0, "padding is not zero\n");
-        ok(buf[4095] == 'W', "got wrong decoded data at offset 4095\n");
-        ok(buf[4096] == 0x11, "buf[4096] overwritten\n");
-    }
+    ret = pRtlIsCriticalSectionLocked(&info->crit);
+    ok(ret == TRUE, "expected TRUE, got %u\n", ret);
+    ret = pRtlIsCriticalSectionLockedByThread(&info->crit);
+    ok(ret == FALSE, "expected FALSE, got %u\n", ret);
 
-    final_size = 0xdeadbeef;
-    memset(buf, 0x11, sizeof(buf));
-    status = pRtlDecompressFragment(COMPRESSION_FORMAT_LZNT1, buf, 4095, test_multiple_chunks,
-                                    sizeof(test_multiple_chunks), 1, &final_size, workspace);
-    ok(status == STATUS_SUCCESS || broken(status == STATUS_BAD_COMPRESSION_BUFFER),
-       "got wrong status 0x%08x\n", status);
-    if (!status)
-    {
-        ok(final_size == 3, "got wrong final_size %d\n", final_size);
-        ok(!memcmp(buf, "ine", 3), "got wrong decoded data at offset 0\n");
-        ok(buf[4] == 0x11, "buf[4] overwritten\n");
-    }
+    ReleaseSemaphore(info->semaphores[0], 1, NULL);
+    ret = WaitForSingleObject(info->semaphores[1], 1000);
+    ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", ret);
 
-    final_size = 0xdeadbeef;
-    memset(buf, 0x11, sizeof(buf));
-    status = pRtlDecompressFragment(COMPRESSION_FORMAT_LZNT1, buf, 3, test_multiple_chunks,
-                                    sizeof(test_multiple_chunks), 1, &final_size, workspace);
-    ok(status == STATUS_SUCCESS, "got wrong status 0x%08x\n", status);
-    if (!status)
-    {
-        ok(final_size == 3, "got wrong final_size %d\n", final_size);
-        ok(!memcmp(buf, "ine", 3), "got wrong decoded data at offset 0\n");
-        ok(buf[3] == 0x11, "buf[3] overwritten\n");
-    }
+    ret = pRtlIsCriticalSectionLocked(&info->crit);
+    ok(ret == FALSE, "expected FALSE, got %u\n", ret);
+    ret = pRtlIsCriticalSectionLockedByThread(&info->crit);
+    ok(ret == FALSE, "expected FALSE, got %u\n", ret);
 
-    /* test multiple chunks in combination with RtlDecompressBuffer and offset=4 */
-    final_size = 0xdeadbeef;
-    memset(buf, 0x11, sizeof(buf));
-    status = pRtlDecompressFragment(COMPRESSION_FORMAT_LZNT1, buf, sizeof(buf), test_multiple_chunks,
-                                    sizeof(test_multiple_chunks), 4, &final_size, workspace);
-    ok(status == STATUS_SUCCESS || broken(status == STATUS_BAD_COMPRESSION_BUFFER),
-       "got wrong status 0x%08x\n", status);
-    if (!status)
-    {
-        ok(final_size == 4096, "got wrong final_size %d\n", final_size);
-        ok(buf[0] == 0 && buf[4091] == 0, "padding is not zero\n");
-        ok(!memcmp(buf + 4092, "Wine", 4), "got wrong decoded data at offset 4092\n");
-        ok(buf[4096] == 0x11, "buf[4096] overwritten\n");
-    }
+    EnterCriticalSection(&info->crit);
 
-    final_size = 0xdeadbeef;
-    memset(buf, 0x11, sizeof(buf));
-    status = pRtlDecompressFragment(COMPRESSION_FORMAT_LZNT1, buf, sizeof(buf), test_multiple_chunks,
-                                    sizeof(test_multiple_chunks), 4095, &final_size, workspace);
-    ok(status == STATUS_SUCCESS || broken(status == STATUS_BAD_COMPRESSION_BUFFER),
-       "got wrong status 0x%08x\n", status);
-    if (!status)
-    {
-        ok(final_size == 5, "got wrong final_size %d\n", final_size);
-        ok(buf[0] == 0, "padding is not zero\n");
-        ok(!memcmp(buf + 1, "Wine", 4), "got wrong decoded data at offset 1\n");
-        ok(buf[5] == 0x11, "buf[5] overwritten\n");
-    }
+    ret = pRtlIsCriticalSectionLocked(&info->crit);
+    ok(ret == TRUE, "expected TRUE, got %u\n", ret);
+    ret = pRtlIsCriticalSectionLockedByThread(&info->crit);
+    ok(ret == TRUE, "expected TRUE, got %u\n", ret);
 
-    final_size = 0xdeadbeef;
-    memset(buf, 0x11, sizeof(buf));
-    status = pRtlDecompressFragment(COMPRESSION_FORMAT_LZNT1, buf, sizeof(buf), test_multiple_chunks,
-                                    sizeof(test_multiple_chunks), 4096, &final_size, workspace);
-    ok(status == STATUS_SUCCESS || broken(status == STATUS_BAD_COMPRESSION_BUFFER),
-       "got wrong status 0x%08x\n", status);
-    if (!status)
-    {
-        ok(final_size == 4, "got wrong final_size %d\n", final_size);
-        ok(!memcmp(buf, "Wine", 4), "got wrong decoded data at offset 0\n");
-        ok(buf[4] == 0x11, "buf[4] overwritten\n");
-    }
+    ReleaseSemaphore(info->semaphores[0], 1, NULL);
+    ret = WaitForSingleObject(info->semaphores[1], 1000);
+    ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", ret);
 
+    LeaveCriticalSection(&info->crit);
+    return 0;
 }
 
-static void test_RtlCompressBuffer(void)
+static void test_RtlIsCriticalSectionLocked(void)
 {
-    ULONG compress_workspace, decompress_workspace;
-    static const UCHAR test_buffer[] = "WineWineWine";
-    static UCHAR buf1[0x1000], buf2[0x1000], *workspace;
-    ULONG final_size, buf_size;
-    NTSTATUS status;
+    struct critsect_locked_info info;
+    HANDLE thread;
+    BOOL ret;
 
-    if (!pRtlCompressBuffer || !pRtlGetCompressionWorkSpaceSize)
+    if (!pRtlIsCriticalSectionLocked || !pRtlIsCriticalSectionLockedByThread)
     {
-        win_skip("RtlCompressBuffer or RtlGetCompressionWorkSpaceSize is not available\n");
+        win_skip("skipping RtlIsCriticalSectionLocked tests, required functions not available\n");
         return;
     }
 
-    compress_workspace = decompress_workspace = 0xdeadbeef;
-    status = pRtlGetCompressionWorkSpaceSize(COMPRESSION_FORMAT_LZNT1, &compress_workspace,
-                                             &decompress_workspace);
-    ok(status == STATUS_SUCCESS, "got wrong status 0x%08x\n", status);
-    ok(compress_workspace != 0, "got wrong compress_workspace %d\n", compress_workspace);
+    InitializeCriticalSection(&info.crit);
+    info.semaphores[0] = CreateSemaphoreW(NULL, 0, 1, NULL);
+    ok(info.semaphores[0] != NULL, "CreateSemaphore failed with %u\n", GetLastError());
+    info.semaphores[1] = CreateSemaphoreW(NULL, 0, 1, NULL);
+    ok(info.semaphores[1] != NULL, "CreateSemaphore failed with %u\n", GetLastError());
 
-    workspace = HeapAlloc( GetProcessHeap(), 0, compress_workspace );
-    ok(workspace != NULL, "HeapAlloc failed %x\n", GetLastError());
+    ret = pRtlIsCriticalSectionLocked(&info.crit);
+    ok(ret == FALSE, "expected FALSE, got %u\n", ret);
+    ret = pRtlIsCriticalSectionLockedByThread(&info.crit);
+    ok(ret == FALSE, "expected FALSE, got %u\n", ret);
 
-    /* test compression format / engine */
-    final_size = 0xdeadbeef;
-    status = pRtlCompressBuffer(COMPRESSION_FORMAT_NONE, test_buffer, sizeof(test_buffer),
-                                buf1, sizeof(buf1) - 1, 4096, &final_size, workspace);
-    ok(status == STATUS_INVALID_PARAMETER, "got wrong status 0x%08x\n", status);
-    ok(final_size == 0xdeadbeef, "got wrong final_size %d\n", final_size);
+    EnterCriticalSection(&info.crit);
 
-    final_size = 0xdeadbeef;
-    status = pRtlCompressBuffer(COMPRESSION_FORMAT_DEFAULT, test_buffer, sizeof(test_buffer),
-                                buf1, sizeof(buf1) - 1, 4096, &final_size, workspace);
-    ok(status == STATUS_INVALID_PARAMETER, "got wrong status 0x%08x\n", status);
-    ok(final_size == 0xdeadbeef, "got wrong final_size %d\n", final_size);
+    ret = pRtlIsCriticalSectionLocked(&info.crit);
+    ok(ret == TRUE, "expected TRUE, got %u\n", ret);
+    ret = pRtlIsCriticalSectionLockedByThread(&info.crit);
+    ok(ret == TRUE, "expected TRUE, got %u\n", ret);
 
-    final_size = 0xdeadbeef;
-    status = pRtlCompressBuffer(0xFF, test_buffer, sizeof(test_buffer),
-                                buf1, sizeof(buf1) - 1, 4096, &final_size, workspace);
-    ok(status == STATUS_UNSUPPORTED_COMPRESSION, "got wrong status 0x%08x\n", status);
-    ok(final_size == 0xdeadbeef, "got wrong final_size %d\n", final_size);
+    thread = CreateThread(NULL, 0, critsect_locked_thread, &info, 0, NULL);
+    ok(thread != NULL, "CreateThread failed with %u\n", GetLastError());
+    ret = WaitForSingleObject(info.semaphores[0], 1000);
+    ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", ret);
 
-    /* test compression */
-    final_size = 0xdeadbeef;
-    memset(buf1, 0x11, sizeof(buf1));
-    status = pRtlCompressBuffer(COMPRESSION_FORMAT_LZNT1, test_buffer, sizeof(test_buffer),
-                                buf1, sizeof(buf1), 4096, &final_size, workspace);
-    ok(status == STATUS_SUCCESS, "got wrong status 0x%08x\n", status);
-    ok((*(WORD *)buf1 & 0x7000) == 0x3000, "no chunk signature found %04x\n", *(WORD *)buf1);
-    buf_size = final_size;
-    todo_wine
-    ok(final_size < sizeof(test_buffer), "got wrong final_size %d\n", final_size);
+    LeaveCriticalSection(&info.crit);
 
-    /* test decompression */
-    final_size = 0xdeadbeef;
-    memset(buf2, 0x11, sizeof(buf2));
-    status = pRtlDecompressBuffer(COMPRESSION_FORMAT_LZNT1, buf2, sizeof(buf2),
-                                  buf1, buf_size, &final_size);
-    ok(status == STATUS_SUCCESS, "got wrong status 0x%08x\n", status);
-    ok(final_size == sizeof(test_buffer), "got wrong final_size %d\n", final_size);
-    ok(!memcmp(buf2, test_buffer, sizeof(test_buffer)), "got wrong decoded data\n");
-    ok(buf2[sizeof(test_buffer)] == 0x11, "buf[%u] overwritten\n", (DWORD)sizeof(test_buffer));
+    ReleaseSemaphore(info.semaphores[1], 1, NULL);
+    ret = WaitForSingleObject(info.semaphores[0], 1000);
+    ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", ret);
 
-    /* buffer too small */
-    final_size = 0xdeadbeef;
-    memset(buf1, 0x11, sizeof(buf1));
-    status = pRtlCompressBuffer(COMPRESSION_FORMAT_LZNT1, test_buffer, sizeof(test_buffer),
-                                buf1, 4, 4096, &final_size, workspace);
-    ok(status == STATUS_BUFFER_TOO_SMALL, "got wrong status 0x%08x\n", status);
+    ret = pRtlIsCriticalSectionLocked(&info.crit);
+    ok(ret == TRUE, "expected TRUE, got %u\n", ret);
+    ret = pRtlIsCriticalSectionLockedByThread(&info.crit);
+    ok(ret == FALSE, "expected FALSE, got %u\n", ret);
 
-    HeapFree(GetProcessHeap(), 0, workspace);
+    ReleaseSemaphore(info.semaphores[1], 1, NULL);
+    ret = WaitForSingleObject(thread, 1000);
+    ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", ret);
+
+    CloseHandle(thread);
+    CloseHandle(info.semaphores[0]);
+    CloseHandle(info.semaphores[1]);
+    DeleteCriticalSection(&info.crit);
 }
 
 START_TEST(rtl)
@@ -3477,7 +3202,8 @@ START_TEST(rtl)
     test_RtlIpv6StringToAddressEx();
     test_LdrAddRefDll();
     test_LdrLockLoaderLock();
+    test_RtlCompressBuffer();
     test_RtlGetCompressionWorkSpaceSize();
     test_RtlDecompressBuffer();
-    test_RtlCompressBuffer();
+    test_RtlIsCriticalSectionLocked();
 }