[KERNEL32_WINETEST]
authorAmine Khaldi <amine.khaldi@reactos.org>
Sat, 12 May 2012 19:33:11 +0000 (19:33 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Sat, 12 May 2012 19:33:11 +0000 (19:33 +0000)
* Sync to Wine 1.5.4. I excluded loader and virtual tests from the sync until bug #7071 is fixed.
See issue #7070 for more details.

svn path=/trunk/; revision=56567

15 files changed:
rostests/winetests/kernel32/actctx.c
rostests/winetests/kernel32/atom.c
rostests/winetests/kernel32/change.c
rostests/winetests/kernel32/codepage.c
rostests/winetests/kernel32/comm.c
rostests/winetests/kernel32/console.c
rostests/winetests/kernel32/file.c
rostests/winetests/kernel32/format_msg.c
rostests/winetests/kernel32/locale.c
rostests/winetests/kernel32/module.c
rostests/winetests/kernel32/pipe.c
rostests/winetests/kernel32/process.c
rostests/winetests/kernel32/profile.c
rostests/winetests/kernel32/sync.c
rostests/winetests/kernel32/volume.c

index b7f3010..3af6e63 100644 (file)
@@ -591,7 +591,7 @@ static HANDLE test_create(const char *file, const char *manifest)
     ok(handle != INVALID_HANDLE_VALUE, "handle == INVALID_HANDLE_VALUE, error %u\n", GetLastError());
 
     ok(actctx.cbSize == sizeof(actctx), "actctx.cbSize=%d\n", actctx.cbSize);
-    ok(actctx.dwFlags == 0, "actctx.=%d\n", actctx.dwFlags);
+    ok(actctx.dwFlags == 0, "actctx.dwFlags=%d\n", actctx.dwFlags);
     ok(actctx.lpSource == path, "actctx.lpSource=%p\n", actctx.lpSource);
     ok(actctx.wProcessorArchitecture == 0,
        "actctx.wProcessorArchitecture=%d\n", actctx.wProcessorArchitecture);
@@ -599,7 +599,7 @@ static HANDLE test_create(const char *file, const char *manifest)
     ok(actctx.lpAssemblyDirectory == NULL,
        "actctx.lpAssemblyDirectory=%p\n", actctx.lpAssemblyDirectory);
     ok(actctx.lpResourceName == NULL, "actctx.lpResourceName=%p\n", actctx.lpResourceName);
-    ok(actctx.lpApplicationName == NULL, "actctx.lpApplocationName=%p\n",
+    ok(actctx.lpApplicationName == NULL, "actctx.lpApplicationName=%p\n",
        actctx.lpApplicationName);
     ok(actctx.hModule == NULL, "actctx.hModule=%p\n", actctx.hModule);
 
index 15ef04c..0c17408 100755 (executable)
@@ -168,11 +168,11 @@ static void test_get_atom_name(void)
 
     if (unicode_OS)
     {
-        static const WCHAR sampleW[10] = {'.','.','.','.','.','.','.','.','.','.'};
+        static const WCHAR sampleW[] = {'.','.','.','.','.','.','.','.','.','.'};
 
         for (i = 0; i < 10; i++) bufW[i] = '.';
         ok( !GlobalGetAtomNameW( atom, bufW, 0 ), "succeeded\n" );
-        ok( !memcmp( bufW, sampleW, 10 * sizeof(WCHAR) ), "should not touch buffer\n" );
+        ok( !memcmp( bufW, sampleW, sizeof(sampleW) ), "should not touch buffer\n" );
     }
 
     /* Test integer atoms */
@@ -266,7 +266,7 @@ static void test_get_atom_name(void)
             {
                 /* len == 0 with ERROR_MORE_DATA is on NT3.51 */
                 ok(len == 1 || (len == 0 && GetLastError() == ERROR_MORE_DATA),
-                         "0x%04x: got %u with %d (excepted '1' or '0' with "
+                         "0x%04x: got %u with %d (expected '1' or '0' with "
                          "ERROR_MORE_DATA)\n", i, len, GetLastError());
                 ok(outW[1] == DOUBLE('.'), "buffer overwrite\n");
             }
@@ -442,11 +442,11 @@ static void test_local_get_atom_name(void)
 
     if (unicode_OS)
     {
-        static const WCHAR sampleW[10] = {'.','.','.','.','.','.','.','.','.','.'};
+        static const WCHAR sampleW[] = {'.','.','.','.','.','.','.','.','.','.'};
 
         for (i = 0; i < 10; i++) bufW[i] = '.';
         ok( !GetAtomNameW( atom, bufW, 0 ), "succeeded\n" );
-        ok( !memcmp( bufW, sampleW, 10 * sizeof(WCHAR) ), "should not touch buffer\n" );
+        ok( !memcmp( bufW, sampleW, sizeof(sampleW) ), "should not touch buffer\n" );
     }
 
     /* Test integer atoms */
index 4d0bc1c..6142e43 100755 (executable)
@@ -858,7 +858,7 @@ static void test_readdirectorychanges_cr(void)
     ok(fni->FileNameLength == lstrlenW(szFile)*sizeof(WCHAR),
             "FileNameLength = %d\n", fni->FileNameLength);
     ok(!memcmp(fni->FileName, szFile, lstrlenW(szFile)*sizeof(WCHAR)),
-            "FileName = %s\n", wine_dbgstr_w(fni->FileName));
+            "FileName = %s\n", wine_dbgstr_wn(fni->FileName, fni->FileNameLength/sizeof(WCHAR)));
 
     r = pReadDirectoryChangesW(hdir, fni, sizeof(fni), FALSE,
             FILE_NOTIFY_CHANGE_FILE_NAME, NULL, &ov, readdirectorychanges_cr);
@@ -878,7 +878,7 @@ static void test_readdirectorychanges_cr(void)
     ok(fni->FileNameLength == lstrlenW(szFile)*sizeof(WCHAR),
             "FileNameLength = %d\n", fni->FileNameLength);
     ok(!memcmp(fni->FileName, szFile, lstrlenW(szFile)*sizeof(WCHAR)),
-            "FileName = %s\n", wine_dbgstr_w(fni->FileName));
+            "FileName = %s\n", wine_dbgstr_wn(fni->FileName, fni->FileNameLength/sizeof(WCHAR)));
 
     r = pReadDirectoryChangesW(hdir, fni, sizeof(fni), FALSE,
             FILE_NOTIFY_CHANGE_FILE_NAME, NULL, &ov, readdirectorychanges_cr);
@@ -894,7 +894,7 @@ static void test_readdirectorychanges_cr(void)
     ok(fni->FileNameLength == lstrlenW(szFile)*sizeof(WCHAR),
             "FileNameLength = %d\n", fni->FileNameLength);
     ok(!memcmp(fni->FileName, szFile, lstrlenW(szFile)*sizeof(WCHAR)),
-            "FileName = %s\n", wine_dbgstr_w(fni->FileName));
+            "FileName = %s\n", wine_dbgstr_wn(fni->FileName, fni->FileNameLength/sizeof(WCHAR)));
 
     r = pReadDirectoryChangesW(hdir, fni, sizeof(fni), FALSE,
             FILE_NOTIFY_CHANGE_FILE_NAME, NULL, &ov, readdirectorychanges_cr);
@@ -910,7 +910,7 @@ static void test_readdirectorychanges_cr(void)
     ok(fni->FileNameLength == lstrlenW(szFile)*sizeof(WCHAR),
             "FileNameLength = %d\n", fni->FileNameLength);
     ok(!memcmp(fni->FileName, szFile, lstrlenW(szFile)*sizeof(WCHAR)),
-            "FileName = %s\n", wine_dbgstr_w(fni->FileName));
+            "FileName = %s\n", wine_dbgstr_wn(fni->FileName, fni->FileNameLength/sizeof(WCHAR)));
 
     CloseHandle(hdir);
 
@@ -934,7 +934,7 @@ static void test_readdirectorychanges_cr(void)
         ok(fni->FileNameLength == lstrlenW(szDir)*sizeof(WCHAR),
                 "FileNameLength = %d\n", fni->FileNameLength);
         ok(!memcmp(fni->FileName, szDir, lstrlenW(szDir)*sizeof(WCHAR)),
-                "FileName = %s\n", wine_dbgstr_w(fni->FileName));
+                "FileName = %s\n", wine_dbgstr_wn(fni->FileName, fni->FileNameLength/sizeof(WCHAR)));
         ok(fni->NextEntryOffset != 0, "no next entry in movement event\n");
         fni_next = (FILE_NOTIFY_INFORMATION*)((char*)fni+fni->NextEntryOffset);
         ok(fni_next->NextEntryOffset == 0, "there should be no more events in buffer\n");
@@ -942,7 +942,7 @@ static void test_readdirectorychanges_cr(void)
         ok(fni_next->FileNameLength == lstrlenW(szFile)*sizeof(WCHAR),
                 "FileNameLength = %d\n", fni_next->FileNameLength);
         ok(!memcmp(fni_next->FileName, szFile, lstrlenW(szFile)*sizeof(WCHAR)),
-                "FileName = %s\n", wine_dbgstr_w(fni_next->FileName));
+                "FileName = %s\n", wine_dbgstr_wn(fni_next->FileName, fni_next->FileNameLength/sizeof(WCHAR)));
     }
     else
     {
@@ -975,7 +975,7 @@ static void test_readdirectorychanges_cr(void)
     ok(fni->FileNameLength == lstrlenW(szDir)*sizeof(WCHAR),
             "FileNameLength = %d\n", fni->FileNameLength);
     ok(!memcmp(fni->FileName, szDir, lstrlenW(szDir)*sizeof(WCHAR)),
-            "FileName = %s\n", wine_dbgstr_w(fni->FileName));
+            "FileName = %s\n", wine_dbgstr_wn(fni->FileName, fni->FileNameLength/sizeof(WCHAR)));
     if (fni->NextEntryOffset)
         fni_next = (FILE_NOTIFY_INFORMATION*)((char*)fni+fni->NextEntryOffset);
     else
@@ -993,7 +993,7 @@ static void test_readdirectorychanges_cr(void)
     ok(fni_next->FileNameLength == lstrlenW(szDir)*sizeof(WCHAR),
             "FileNameLength = %d\n", fni_next->FileNameLength);
     ok(!memcmp(fni_next->FileName, szDir, lstrlenW(szDir)*sizeof(WCHAR)),
-            "FileName = %s\n", wine_dbgstr_w(fni_next->FileName));
+            "FileName = %s\n", wine_dbgstr_wn(fni_next->FileName, fni_next->FileNameLength/sizeof(WCHAR)));
 
     CloseHandle(hdir);
     RemoveDirectoryW(file);
index 8f9c4e1..61bcf54 100755 (executable)
@@ -211,8 +211,8 @@ static void test_string_conversion(LPBOOL bUsedDefaultChar)
     int ret;
     WCHAR wc1 = 228;                           /* Western Windows-1252 character */
     WCHAR wc2 = 1088;                          /* Russian Windows-1251 character not displayable for Windows-1252 */
-    WCHAR wcs[5] = {'T', 'h', 1088, 'i', 0};   /* String with ASCII characters and a Russian character */
-    WCHAR dbwcs[3] = {28953, 25152, 0};        /* String with Chinese (codepage 950) characters */
+    static const WCHAR wcs[] = {'T', 'h', 1088, 'i', 0}; /* String with ASCII characters and a Russian character */
+    static const WCHAR dbwcs[] = {28953, 25152, 0}; /* String with Chinese (codepage 950) characters */
 
     SetLastError(0xdeadbeef);
     ret = WideCharToMultiByte(1252, 0, &wc1, 1, &mbc, 1, NULL, bUsedDefaultChar);
index b08174f..895a9ab 100755 (executable)
@@ -1115,9 +1115,8 @@ static void  test_WaitRx(HANDLE hcom)
     ZeroMemory( &overlapped, sizeof(overlapped));
     overlapped.hEvent = hComPortEvent;
 
-    ok((hComWriteEvent =  CreateEvent( NULL, TRUE, FALSE, NULL )) !=0,
-       "CreateEvent res %d\n",
-       GetLastError());
+    hComWriteEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
+    ok(hComWriteEvent != NULL, "CreateEvent res %d\n", GetLastError());
     ZeroMemory( &overlapped_w, sizeof(overlapped_w));
     overlapped_w.hEvent = hComWriteEvent;
 
index f248666..d0c58f8 100755 (executable)
@@ -780,6 +780,28 @@ static void testScreenBuffer(HANDLE hConOut)
        "GetLastError: expecting %u got %u\n",
        ERROR_INVALID_HANDLE, GetLastError());
 
+    /* trying to write non-console handle */
+    SetLastError(0xdeadbeef);
+    ok(!WriteConsoleA(hFileOutRW, test_str1, lstrlenA(test_str1), &len, NULL),
+        "Shouldn't succeed\n");
+    ok(GetLastError() == ERROR_INVALID_HANDLE,
+       "GetLastError: expecting %u got %u\n",
+       ERROR_INVALID_HANDLE, GetLastError());
+
+    SetLastError(0xdeadbeef);
+    ok(!WriteConsoleA(hFileOutRO, test_str1, lstrlenA(test_str1), &len, NULL),
+        "Shouldn't succeed\n");
+    ok(GetLastError() == ERROR_INVALID_HANDLE,
+       "GetLastError: expecting %u got %u\n",
+       ERROR_INVALID_HANDLE, GetLastError());
+
+    SetLastError(0xdeadbeef);
+    ok(!WriteConsoleA(hFileOutWT, test_str1, lstrlenA(test_str1), &len, NULL),
+        "Shouldn't succeed\n");
+    todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE,
+       "GetLastError: expecting %u got %u\n",
+       ERROR_INVALID_HANDLE, GetLastError());
+
     CloseHandle(hFileOutRW);
     CloseHandle(hFileOutRO);
     CloseHandle(hFileOutWT);
@@ -1116,6 +1138,68 @@ static void test_OpenConsoleW(void)
         CloseHandle(ret);
 }
 
+static void test_CreateFileW(void)
+{
+    static const WCHAR coninW[] = {'C','O','N','I','N','$',0};
+    static const WCHAR conoutW[] = {'C','O','N','O','U','T','$',0};
+
+    static const struct
+    {
+        LPCWSTR name;
+        DWORD access;
+        BOOL inherit;
+        DWORD creation;
+        DWORD gle;
+        BOOL is_broken;
+    } cf_table[] = {
+        {coninW,   0,                            FALSE,      0,                 ERROR_INVALID_PARAMETER,        TRUE},
+        {coninW,   0,                            FALSE,      OPEN_ALWAYS,       0,                              FALSE},
+        {coninW,   GENERIC_READ | GENERIC_WRITE, FALSE,      0,                 ERROR_INVALID_PARAMETER,        TRUE},
+        {coninW,   GENERIC_READ | GENERIC_WRITE, FALSE,      CREATE_NEW,        0,                              FALSE},
+        {coninW,   GENERIC_READ | GENERIC_WRITE, FALSE,      CREATE_ALWAYS,     0,                              FALSE},
+        {coninW,   GENERIC_READ | GENERIC_WRITE, FALSE,      OPEN_ALWAYS,       0,                              FALSE},
+        {coninW,   GENERIC_READ | GENERIC_WRITE, FALSE,      TRUNCATE_EXISTING, 0,                              FALSE},
+        {conoutW,  0,                            FALSE,      0,                 ERROR_INVALID_PARAMETER,        TRUE},
+        {conoutW,  0,                            FALSE,      OPEN_ALWAYS,       0,                              FALSE},
+        {conoutW,  GENERIC_READ | GENERIC_WRITE, FALSE,      0,                 ERROR_INVALID_PARAMETER,        TRUE},
+        {conoutW,  GENERIC_READ | GENERIC_WRITE, FALSE,      CREATE_NEW,        0,                              FALSE},
+        {conoutW,  GENERIC_READ | GENERIC_WRITE, FALSE,      CREATE_ALWAYS,     0,                              FALSE},
+        {conoutW,  GENERIC_READ | GENERIC_WRITE, FALSE,      OPEN_ALWAYS,       0,                              FALSE},
+        {conoutW,  GENERIC_READ | GENERIC_WRITE, FALSE,      TRUNCATE_EXISTING, 0,                              FALSE},
+    };
+
+    int index;
+    HANDLE ret;
+    SECURITY_ATTRIBUTES sa;
+
+    for (index = 0; index < sizeof(cf_table)/sizeof(cf_table[0]); index++)
+    {
+        SetLastError(0xdeadbeef);
+
+        sa.nLength = sizeof(sa);
+        sa.lpSecurityDescriptor = NULL;
+        sa.bInheritHandle = cf_table[index].inherit;
+
+        ret = CreateFileW(cf_table[index].name, cf_table[index].access,
+                          FILE_SHARE_READ|FILE_SHARE_WRITE, &sa,
+                          cf_table[index].creation, FILE_ATTRIBUTE_NORMAL, NULL);
+        if (ret == INVALID_HANDLE_VALUE)
+        {
+            ok(cf_table[index].gle,
+               "Expected CreateFileW not to return INVALID_HANDLE_VALUE for index %d\n", index);
+            ok(GetLastError() == cf_table[index].gle,
+                "Expected GetLastError() to return %u for index %d, got %u\n",
+                cf_table[index].gle, index, GetLastError());
+        }
+        else
+        {
+            ok(!cf_table[index].gle || broken(cf_table[index].is_broken) /* Win7 */,
+               "Expected CreateFileW to succeed for index %d\n", index);
+            CloseHandle(ret);
+        }
+    }
+}
+
 static void test_VerifyConsoleIoHandle( HANDLE handle )
 {
     BOOL ret;
@@ -2546,6 +2630,7 @@ START_TEST(console)
 
     test_GetConsoleProcessList();
     test_OpenConsoleW();
+    test_CreateFileW();
     test_OpenCON();
     test_VerifyConsoleIoHandle(hConOut);
     test_GetSetStdHandle();
index bc423d7..9cfb664 100755 (executable)
@@ -1591,7 +1591,7 @@ static void test_offset_in_overlapped_structure(void)
 
 static void test_LockFile(void)
 {
-    HANDLE handle;
+    HANDLE handle, handle2;
     DWORD written;
     OVERLAPPED overlapped;
     int limited_LockFile;
@@ -1606,6 +1606,14 @@ static void test_LockFile(void)
         ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
         return;
     }
+    handle2 = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE,
+                           FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+                           OPEN_EXISTING, 0, 0 );
+    if (handle2 == INVALID_HANDLE_VALUE)
+    {
+        ok( 0, "couldn't open file \"%s\" (err=%d)\n", filename, GetLastError() );
+        goto cleanup;
+    }
     ok( WriteFile( handle, sillytext, strlen(sillytext), &written, NULL ), "write failed\n" );
 
     ok( LockFile( handle, 0, 0, 0, 0 ), "LockFile failed\n" );
@@ -1656,6 +1664,22 @@ static void test_LockFile(void)
             "UnlockFileEx 150,100 again succeeded\n" );
     }
 
+    /* shared lock can overlap exclusive if handles are equal */
+    S(U(overlapped)).Offset = 300;
+    ok( LockFileEx( handle, LOCKFILE_EXCLUSIVE_LOCK, 0, 100, 0, &overlapped ),
+        "LockFileEx exclusive 300,100 failed\n" );
+    ok( !LockFileEx( handle2, LOCKFILE_FAIL_IMMEDIATELY, 0, 100, 0, &overlapped ),
+        "LockFileEx handle2 300,100 succeeded\n" );
+    ret = LockFileEx( handle, LOCKFILE_FAIL_IMMEDIATELY, 0, 100, 0, &overlapped );
+    ok( ret, "LockFileEx 300,100 failed\n" );
+    ok( UnlockFileEx( handle, 0, 100, 0, &overlapped ), "UnlockFileEx 300,100 failed\n" );
+    /* exclusive lock is removed first */
+    ok( LockFileEx( handle2, LOCKFILE_FAIL_IMMEDIATELY, 0, 100, 0, &overlapped ),
+        "LockFileEx handle2 300,100 failed\n" );
+    ok( UnlockFileEx( handle2, 0, 100, 0, &overlapped ), "UnlockFileEx 300,100 failed\n" );
+    if (ret)
+        ok( UnlockFileEx( handle, 0, 100, 0, &overlapped ), "UnlockFileEx 300,100 failed\n" );
+
     ret = LockFile( handle, 0, 0x10000000, 0, 0xf0000000 );
     if (ret)
     {
@@ -1689,6 +1713,8 @@ static void test_LockFile(void)
 
     ok( UnlockFile( handle, 100, 0, 0, 0 ), "UnlockFile 100,0 failed\n" );
 
+    CloseHandle( handle2 );
+cleanup:
     CloseHandle( handle );
     DeleteFileA( filename );
 }
@@ -1732,12 +1758,12 @@ static BOOL create_fake_dll( LPCSTR filename )
 #elif defined __sparc__
     nt->FileHeader.Machine = IMAGE_FILE_MACHINE_SPARC;
 #elif defined __arm__
-    nt->FileHeader.Machine = IMAGE_FILE_MACHINE_ARM;
+    nt->FileHeader.Machine = IMAGE_FILE_MACHINE_ARMV7;
 #else
 # error You must specify the machine type
 #endif
     nt->FileHeader.NumberOfSections = 1;
-    nt->FileHeader.SizeOfOptionalHeader = IMAGE_SIZEOF_NT_OPTIONAL_HEADER;
+    nt->FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER);
     nt->FileHeader.Characteristics = IMAGE_FILE_DLL | IMAGE_FILE_EXECUTABLE_IMAGE;
     nt->OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR_MAGIC;
     nt->OptionalHeader.MajorLinkerVersion = 1;
@@ -2393,7 +2419,8 @@ static void test_read_write(void)
     user_apc_ran = FALSE;
     if (pQueueUserAPC) {
         trace("Queueing an user APC\n"); /* verify the file is non alerable */
-        ok(pQueueUserAPC(&user_apc, GetCurrentThread(), 0), "QueueUserAPC failed: %d\n", GetLastError());
+        ret = pQueueUserAPC(&user_apc, GetCurrentThread(), 0);
+        ok(ret, "QueueUserAPC failed: %d\n", GetLastError());
     }
 
     SetLastError(12345678);
@@ -3124,6 +3151,92 @@ static void test_ReplaceFileW(void)
     }
 }
 
+static void test_CreatFile(void)
+{
+    static const struct test_data
+    {
+        DWORD disposition, access, error, clean_up;
+    } td[] =
+    {
+    /* 0 */ { 0, 0, ERROR_INVALID_PARAMETER, 0 },
+    /* 1 */ { 0, GENERIC_READ, ERROR_INVALID_PARAMETER, 0 },
+    /* 2 */ { 0, GENERIC_READ|GENERIC_WRITE, ERROR_INVALID_PARAMETER, 0 },
+    /* 3 */ { CREATE_NEW, 0, ERROR_FILE_EXISTS, 1 },
+    /* 4 */ { CREATE_NEW, 0, 0, 1 },
+    /* 5 */ { CREATE_NEW, GENERIC_READ, 0, 1 },
+    /* 6 */ { CREATE_NEW, GENERIC_WRITE, 0, 1 },
+    /* 7 */ { CREATE_NEW, GENERIC_READ|GENERIC_WRITE, 0, 0 },
+    /* 8 */ { CREATE_ALWAYS, 0, 0, 0 },
+    /* 9 */ { CREATE_ALWAYS, GENERIC_READ, 0, 0 },
+    /* 10*/ { CREATE_ALWAYS, GENERIC_WRITE, 0, 0 },
+    /* 11*/ { CREATE_ALWAYS, GENERIC_READ|GENERIC_WRITE, 0, 1 },
+    /* 12*/ { OPEN_EXISTING, 0, ERROR_FILE_NOT_FOUND, 0 },
+    /* 13*/ { CREATE_ALWAYS, 0, 0, 0 },
+    /* 14*/ { OPEN_EXISTING, 0, 0, 0 },
+    /* 15*/ { OPEN_EXISTING, GENERIC_READ, 0, 0 },
+    /* 16*/ { OPEN_EXISTING, GENERIC_WRITE, 0, 0 },
+    /* 17*/ { OPEN_EXISTING, GENERIC_READ|GENERIC_WRITE, 0, 1 },
+    /* 18*/ { OPEN_ALWAYS, 0, 0, 0 },
+    /* 19*/ { OPEN_ALWAYS, GENERIC_READ, 0, 0 },
+    /* 20*/ { OPEN_ALWAYS, GENERIC_WRITE, 0, 0 },
+    /* 21*/ { OPEN_ALWAYS, GENERIC_READ|GENERIC_WRITE, 0, 0 },
+    /* 22*/ { TRUNCATE_EXISTING, 0, ERROR_INVALID_PARAMETER, 0 },
+    /* 23*/ { TRUNCATE_EXISTING, GENERIC_READ, ERROR_INVALID_PARAMETER, 0 },
+    /* 24*/ { TRUNCATE_EXISTING, GENERIC_WRITE, 0, 0 },
+    /* 25*/ { TRUNCATE_EXISTING, GENERIC_READ|GENERIC_WRITE, 0, 0 }
+    };
+    char temp_path[MAX_PATH];
+    char file_name[MAX_PATH];
+    DWORD i, ret, written;
+    HANDLE hfile;
+
+    GetTempPath(MAX_PATH, temp_path);
+    GetTempFileName(temp_path, "tmp", 0, file_name);
+
+    for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
+    {
+        SetLastError(0xdeadbeef);
+        hfile = CreateFile(file_name, td[i].access, 0, NULL, td[i].disposition, 0, 0);
+        if (!td[i].error)
+        {
+            ok(hfile != INVALID_HANDLE_VALUE, "%d: CreateFile error %d\n", i, GetLastError());
+            written = 0xdeadbeef;
+            SetLastError(0xdeadbeef);
+            ret = WriteFile(hfile, &td[i].error, sizeof(td[i].error), &written, NULL);
+            if (td[i].access & GENERIC_WRITE)
+            ok(ret, "%d: WriteFile error %d\n", i, GetLastError());
+            else
+            {
+                ok(!ret, "%d: WriteFile should fail\n", i);
+                ok(GetLastError() == ERROR_ACCESS_DENIED, "%d: expected ERROR_ACCESS_DENIED, got %d\n", i, GetLastError());
+            }
+            CloseHandle(hfile);
+        }
+        else
+        {
+            /* FIXME: remove the condition below once Wine is fixed */
+            if (td[i].disposition == TRUNCATE_EXISTING && !(td[i].access & GENERIC_WRITE))
+            {
+                todo_wine
+                {
+                ok(hfile == INVALID_HANDLE_VALUE, "%d: CreateFile should fail\n", i);
+                ok(GetLastError() == td[i].error, "%d: expected %d, got %d\n", i, td[i].error, GetLastError());
+                }
+                CloseHandle(hfile);
+            }
+            else
+            {
+            ok(hfile == INVALID_HANDLE_VALUE, "%d: CreateFile should fail\n", i);
+            ok(GetLastError() == td[i].error, "%d: expected %d, got %d\n", i, td[i].error, GetLastError());
+            }
+        }
+
+        if (td[i].clean_up) DeleteFile(file_name);
+    }
+
+    DeleteFile(file_name);
+}
+
 START_TEST(file)
 {
     InitFunctionPointers();
@@ -3139,6 +3252,7 @@ START_TEST(file)
     test_GetTempFileNameA();
     test_CopyFileA();
     test_CopyFileW();
+    test_CreatFile();
     test_CreateFileA();
     test_CreateFileW();
     test_DeleteFileA();
index 37ea3e9..1f56440 100755 (executable)
@@ -125,6 +125,7 @@ static void test_message_from_string_wide(void)
     static const WCHAR s_sp002sp001[] = {' ',' ','0','0','0','2',',',' ',' ','0','0','1',0};
     static const WCHAR s_sp002sp003[] = {' ',' ','0','0','0','2',',',' ','0','0','0','0','3',0};
     static const WCHAR s_sp001004[]   = {' ',' ','0','0','1',',','0','0','0','0','0','4',0};
+    static const WCHAR s_null[]       = {'(','n','u','l','l',')',0};
 
     static const WCHAR init_buf[] = {'x', 'x', 'x', 'x', 'x', 'x'};
     static const WCHAR broken_buf[] = {'t','e','s','t','x','x'};
@@ -381,6 +382,12 @@ static void test_message_from_string_wide(void)
     ok(!lstrcmpW(s_crlfcrlf, out), "failed out=%s\n", wine_dbgstr_w(out));
     ok(r==4,"failed: r=%d\n", r);
 
+    /* null string as argument */
+    r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_1, 0,
+        0, out, sizeof(out)/sizeof(WCHAR), NULL);
+    ok(!lstrcmpW(s_null, out),"failed out=[%s]\n", wine_dbgstr_w(out));
+    ok(r==6,"failed: r=%d\n",r);
+
     /* precision and width */
 
     r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_13s,
@@ -700,6 +707,12 @@ static void test_message_from_string(void)
     ok(!strcmp("\r\n\r\n", out),"failed out=[%s]\n",out);
     ok(r==4,"failed: r=%d\n",r);
 
+    /* null string as argument */
+    r = doit(FORMAT_MESSAGE_FROM_STRING, "%1", 0,
+        0, out, sizeof(out)/sizeof(CHAR), NULL);
+    ok(!strcmp("(null)", out),"failed out=[%s]\n",out);
+    ok(r==6,"failed: r=%d\n",r);
+
     /* precision and width */
 
     r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!3s!",
index e13247e..1cc6610 100755 (executable)
@@ -30,6 +30,9 @@
 #include <stdarg.h>
 #include <stdio.h>
 
+#undef WINVER
+#define WINVER 0x0600
+
 #include "wine/test.h"
 #include "windef.h"
 #include "winbase.h"
@@ -71,20 +74,30 @@ static BOOL (WINAPI *pEnumSystemLanguageGroupsA)(LANGUAGEGROUP_ENUMPROC, DWORD,
 static BOOL (WINAPI *pEnumLanguageGroupLocalesA)(LANGGROUPLOCALE_ENUMPROC, LGRPID, DWORD, LONG_PTR);
 static BOOL (WINAPI *pEnumUILanguagesA)(UILANGUAGE_ENUMPROC, DWORD, LONG_PTR);
 static BOOL (WINAPI *pEnumSystemLocalesEx)(LOCALE_ENUMPROCEX, DWORD, LPARAM, LPVOID);
+static LCID (WINAPI *pLocaleNameToLCID)(LPCWSTR, DWORD);
+static INT  (WINAPI *pLCIDToLocaleName)(LCID, LPWSTR, INT, DWORD);
 static INT (WINAPI *pFoldStringA)(DWORD, LPCSTR, INT, LPSTR, INT);
 static INT (WINAPI *pFoldStringW)(DWORD, LPCWSTR, INT, LPWSTR, INT);
 static BOOL (WINAPI *pIsValidLanguageGroup)(LGRPID, DWORD);
+static INT (WINAPI *pIdnToNameprepUnicode)(DWORD, LPCWSTR, INT, LPWSTR, INT);
+static INT (WINAPI *pIdnToAscii)(DWORD, LPCWSTR, INT, LPWSTR, INT);
+static INT (WINAPI *pIdnToUnicode)(DWORD, LPCWSTR, INT, LPWSTR, INT);
 
 static void InitFunctionPointers(void)
 {
   hKernel32 = GetModuleHandleA("kernel32");
   pEnumSystemLanguageGroupsA = (void*)GetProcAddress(hKernel32, "EnumSystemLanguageGroupsA");
   pEnumLanguageGroupLocalesA = (void*)GetProcAddress(hKernel32, "EnumLanguageGroupLocalesA");
+  pLocaleNameToLCID = (void*)GetProcAddress(hKernel32, "LocaleNameToLCID");
+  pLCIDToLocaleName = (void*)GetProcAddress(hKernel32, "LCIDToLocaleName");
   pFoldStringA = (void*)GetProcAddress(hKernel32, "FoldStringA");
   pFoldStringW = (void*)GetProcAddress(hKernel32, "FoldStringW");
   pIsValidLanguageGroup = (void*)GetProcAddress(hKernel32, "IsValidLanguageGroup");
   pEnumUILanguagesA = (void*)GetProcAddress(hKernel32, "EnumUILanguagesA");
   pEnumSystemLocalesEx = (void*)GetProcAddress(hKernel32, "EnumSystemLocalesEx");
+  pIdnToNameprepUnicode = (void*)GetProcAddress(hKernel32, "IdnToNameprepUnicode");
+  pIdnToAscii = (void*)GetProcAddress(hKernel32, "IdnToAscii");
+  pIdnToUnicode = (void*)GetProcAddress(hKernel32, "IdnToUnicode");
 }
 
 #define eq(received, expected, label, type) \
@@ -1135,12 +1148,63 @@ static void test_GetNumberFormatA(void)
   }
 }
 
+struct comparestringa_entry {
+  LCID lcid;
+  DWORD flags;
+  const char *first;
+  int first_len;
+  const char *second;
+  int second_len;
+  int ret;
+};
+
+static const struct comparestringa_entry comparestringa_data[] = {
+  { LOCALE_SYSTEM_DEFAULT, 0, "EndDialog", -1, "_Property", -1, CSTR_GREATER_THAN },
+  { LOCALE_SYSTEM_DEFAULT, 0, "osp_vba.sreg0070", -1, "_IEWWBrowserComp", -1, CSTR_GREATER_THAN },
+  { LOCALE_SYSTEM_DEFAULT, 0, "r", -1, "\\", -1, CSTR_GREATER_THAN },
+  { LOCALE_SYSTEM_DEFAULT, 0, "osp_vba.sreg0031", -1, "OriginalDatabase", -1, CSTR_GREATER_THAN },
+  { LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aaa", -1, CSTR_GREATER_THAN },
+  { LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aab", -1, CSTR_LESS_THAN },
+  { LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "Aab", -1, CSTR_LESS_THAN },
+  { LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "Aab", -1, CSTR_LESS_THAN },
+  { LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "A.ab", -1, CSTR_LESS_THAN },
+  { LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "AB", -1, CSTR_LESS_THAN },
+  { LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "Aab", -1, CSTR_LESS_THAN },
+  { LOCALE_SYSTEM_DEFAULT, 0, "aB", -1, "Aab", -1, CSTR_GREATER_THAN },
+  { LOCALE_SYSTEM_DEFAULT, 0, "Ba", -1, "bab", -1, CSTR_LESS_THAN },
+  { LOCALE_SYSTEM_DEFAULT, 0, "{100}{83}{71}{71}{71}", -1, "Global_DataAccess_JRO", -1, CSTR_LESS_THAN },
+  { LOCALE_SYSTEM_DEFAULT, 0, "a", -1, "{", -1, CSTR_GREATER_THAN },
+  { LOCALE_SYSTEM_DEFAULT, 0, "A", -1, "{", -1, CSTR_GREATER_THAN },
+  { LOCALE_SYSTEM_DEFAULT, 0, "3.5", 0, "4.0", -1, CSTR_LESS_THAN },
+  { LOCALE_SYSTEM_DEFAULT, 0, "3.5", -1, "4.0", -1, CSTR_LESS_THAN },
+  { LOCALE_SYSTEM_DEFAULT, 0, "3.520.4403.2", -1, "4.0.2927.10", -1, CSTR_LESS_THAN },
+  /* hyphen and apostrophe are treated differently depending on whether SORT_STRINGSORT specified or not */
+  { LOCALE_SYSTEM_DEFAULT, 0, "-o", -1, "/m", -1, CSTR_GREATER_THAN },
+  { LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "-o", -1, CSTR_LESS_THAN },
+  { LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-o", -1, "/m", -1, CSTR_LESS_THAN },
+  { LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "-o", -1, CSTR_GREATER_THAN },
+  { LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "/m", -1, CSTR_GREATER_THAN },
+  { LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "'o", -1, CSTR_LESS_THAN },
+  { LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "/m", -1, CSTR_LESS_THAN },
+  { LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "'o", -1, CSTR_GREATER_THAN },
+  { LOCALE_SYSTEM_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ", 9, CSTR_EQUAL },
+  { LOCALE_SYSTEM_DEFAULT, 0, "aLuZkUtZ", 7, "aLuZkUtZ\0A", 10, CSTR_LESS_THAN }
+};
 
 static void test_CompareStringA(void)
 {
-  int ret;
+  int ret, i;
   LCID lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
 
+  for (i = 0; i < sizeof(comparestringa_data)/sizeof(struct comparestringa_entry); i++)
+  {
+      const struct comparestringa_entry *entry = &comparestringa_data[i];
+
+      ret = CompareStringA(entry->lcid, entry->flags, entry->first, entry->first_len,
+          entry->second, entry->second_len);
+      ok(ret == entry->ret, "%d: got %d, expected %d\n", i, ret, entry->ret);
+  }
+
   ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "Salute", -1);
   ok (ret== 1, "(Salut/Salute) Expected 1, got %d\n", ret);
 
@@ -1189,89 +1253,6 @@ static void test_CompareStringA(void)
     ret = lstrcmpA(NULL, "");
     ok (ret == -1 || broken(ret == -2) /* win9x */, "lstrcmpA(NULL, \"\") should return -1, got %d\n", ret);
  
-    ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"EndDialog",-1,"_Property",-1);
-    ok( ret == 3, "EndDialog vs _Property ... expected 3, got %d\n", ret);
-
-    ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0070",-1,"_IEWWBrowserComp",-1);
-    ok( ret == 3, "osp_vba.sreg0070 vs _IEWWBrowserComp ... expected 3, got %d\n", ret);
-
-    ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"r",-1,"\\",-1); 
-    ok( ret == 3, "r vs \\ ... expected 3, got %d\n", ret);
-
-    ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0031", -1, "OriginalDatabase", -1 );
-    ok( ret == 3, "osp_vba.sreg0031 vs OriginalDatabase ... expected 3, got %d\n", ret);
-
-    ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aaa", -1 );
-    ok( ret == 3, "AAA vs aaa expected 3, got %d\n", ret);
-
-    ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aab", -1 );
-    ok( ret == 1, "AAA vs aab expected 1, got %d\n", ret);
-
-    ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "Aab", -1 );
-    ok( ret == 1, "AAA vs Aab expected 1, got %d\n", ret);
-
-    ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "Aab", -1 );
-    ok( ret == 1, ".AAA vs Aab expected 1, got %d\n", ret);
-
-    ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "A.ab", -1 );
-    ok( ret == 1, ".AAA vs A.ab expected 1, got %d\n", ret);
-
-    ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "AB", -1 );
-    ok( ret == 1, "aa vs AB expected 1, got %d\n", ret);
-
-    ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "Aab", -1 );
-    ok( ret == 1, "aa vs Aab expected 1, got %d\n", ret);
-
-    ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aB", -1, "Aab", -1 );
-    ok( ret == 3, "aB vs Aab expected 3, got %d\n", ret);
-
-    ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "Ba", -1, "bab", -1 );
-    ok( ret == 1, "Ba vs bab expected 1, got %d\n", ret);
-
-    ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "{100}{83}{71}{71}{71}", -1, "Global_DataAccess_JRO", -1 );
-    ok( ret == 1, "{100}{83}{71}{71}{71} vs Global_DataAccess_JRO expected 1, got %d\n", ret);
-
-    ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "a", -1, "{", -1 );
-    ok( ret == 3, "a vs { expected 3, got %d\n", ret);
-
-    ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "A", -1, "{", -1 );
-    ok( ret == 3, "A vs { expected 3, got %d\n", ret);
-
-    ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", 0, "4.0", -1 );
-    ok(ret == 1, "3.5/0 vs 4.0/-1 expected 1, got %d\n", ret);
-
-    ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", -1, "4.0", -1 );
-    ok(ret == 1, "3.5 vs 4.0 expected 1, got %d\n", ret);
-
-    ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.520.4403.2", -1, "4.0.2927.10", -1 );
-    ok(ret == 1, "3.520.4403.2 vs 4.0.2927.10 expected 1, got %d\n", ret);
-
-   /* hyphen and apostrophe are treated differently depending on
-    * whether SORT_STRINGSORT specified or not
-    */
-    ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-o", -1, "/m", -1 );
-    ok(ret == 3, "-o vs /m expected 3, got %d\n", ret);
-
-    ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "-o", -1 );
-    ok(ret == 1, "/m vs -o expected 1, got %d\n", ret);
-
-    ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-o", -1, "/m", -1 );
-    ok(ret == 1, "-o vs /m expected 1, got %d\n", ret);
-
-    ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "-o", -1 );
-    ok(ret == 3, "/m vs -o expected 3, got %d\n", ret);
-
-    ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "/m", -1 );
-    ok(ret == 3, "'o vs /m expected 3, got %d\n", ret);
-
-    ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "'o", -1 );
-    ok(ret == 1, "/m vs 'o expected 1, got %d\n", ret);
-
-    ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "/m", -1 );
-    ok(ret == 1, "'o vs /m expected 1, got %d\n", ret);
-
-    ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "'o", -1 );
-    ok(ret == 3, "/m vs 'o expected 3, got %d\n", ret);
 
     if (0) { /* this requires collation table patch to make it MS compatible */
     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "-o", -1 );
@@ -1311,11 +1292,6 @@ static void test_CompareStringA(void)
     ok(ret == 1, "-m vs `o expected 1, got %d\n", ret);
     }
 
-    ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ", 9);
-    ok(ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0 expected 2, got %d\n", ret);
-
-    ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 7, "aLuZkUtZ\0A", 10);
-    ok(ret == 1, "aLuZkUtZ vs aLuZkUtZ\\0A expected 1, got %d\n", ret);
 
     /* WinXP handles embedded NULLs differently than earlier versions */
     ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ\0A", 10);
@@ -1674,6 +1650,43 @@ static void test_LCMapStringW(void)
        "unexpected error code %d\n", GetLastError());
 }
 
+static void test_LocaleNames(void)
+{
+    LCID lcid;
+    INT ret;
+    WCHAR buffer[LOCALE_NAME_MAX_LENGTH];
+
+    if (!pLocaleNameToLCID)
+    {
+        win_skip( "LocaleNameToLCID not available\n" );
+        return;
+    }
+
+    /* special cases */
+    buffer[0] = 0;
+    lcid = pLocaleNameToLCID(LOCALE_NAME_USER_DEFAULT, 0);
+    ok(lcid == GetUserDefaultLCID() || broken(GetLastError() == ERROR_INVALID_PARAMETER /* Vista */),
+       "Expected lcid == %08x, got %08x, error %d\n", lcid, GetUserDefaultLCID(), GetLastError());
+    ret = pLCIDToLocaleName(lcid, buffer, LOCALE_NAME_MAX_LENGTH, 0);
+    ok(ret > 0, "Expected ret > 0, got %d, error %d\n", ret, GetLastError());
+    trace("%08x, %s\n", lcid, wine_dbgstr_w(buffer));
+
+    buffer[0] = 0;
+    lcid = pLocaleNameToLCID(LOCALE_NAME_SYSTEM_DEFAULT, 0);
+    todo_wine ok(!lcid && GetLastError() == ERROR_INVALID_PARAMETER,
+                 "Expected lcid != 0, got %08x, error %d\n", lcid, GetLastError());
+    ret = pLCIDToLocaleName(lcid, buffer, LOCALE_NAME_MAX_LENGTH, 0);
+    ok(ret > 0, "Expected ret > 0, got %d, error %d\n", ret, GetLastError());
+    trace("%08x, %s\n", lcid, wine_dbgstr_w(buffer));
+
+    buffer[0] = 0;
+    lcid = pLocaleNameToLCID(LOCALE_NAME_INVARIANT, 0);
+    todo_wine ok(lcid == 0x7F, "Expected lcid = 0x7F, got %08x, error %d\n", lcid, GetLastError());
+    ret = pLCIDToLocaleName(lcid, buffer, LOCALE_NAME_MAX_LENGTH, 0);
+    ok(ret > 0, "Expected ret > 0, got %d, error %d\n", ret, GetLastError());
+    trace("%08x, %s\n", lcid, wine_dbgstr_w(buffer));
+}
+
 /* this requires collation table patch to make it MS compatible */
 static const char * const strings_sorted[] =
 {
@@ -2098,6 +2111,18 @@ static void test_FoldStringW(void)
   {
     'W','i','n','e',0x0348,0x0551,0x1323,0x280d,'W','i','n','e','\0'
   };
+  static const WCHAR foldczone_todo_src[] =
+  {
+      0x3c5,0x308,0x6a,0x30c,0xa0,0xaa,0
+  };
+  static const WCHAR foldczone_todo_dst[] =
+  {
+      0x3cb,0x1f0,' ','a',0
+  };
+  static const WCHAR foldczone_todo_broken_dst[] =
+  {
+      0x3cb,0x1f0,0xa0,0xaa,0
+  };
   static const WCHAR ligatures_src[] =
   {
     'W',    'i',    'n',    'e',    0x03a6, 0x03b9, 0x03bd, 0x03b5,
@@ -2242,6 +2267,13 @@ static void test_FoldStringW(void)
   ok(!memcmp(dst, foldczone_dst, sizeof(foldczone_dst)),
      "MAP_FOLDCZONE: Expanded incorrectly\n");
 
+  ret = pFoldStringW(MAP_FOLDCZONE|MAP_PRECOMPOSED, foldczone_todo_src, -1, dst, 256);
+  todo_wine ok(ret == sizeof(foldczone_todo_dst)/sizeof(foldczone_todo_dst[0]),
+          "Got %d, error %d\n", ret, GetLastError());
+  todo_wine ok(!memcmp(dst, foldczone_todo_dst, sizeof(foldczone_todo_dst))
+          || broken(!memcmp(dst, foldczone_todo_broken_dst, sizeof(foldczone_todo_broken_dst))),
+          "MAP_FOLDCZONE: Expanded incorrectly (%s)\n", wine_dbgstr_w(dst));
+
   /* MAP_EXPAND_LIGATURES */
   SetLastError(0);
   ret = pFoldStringW(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
@@ -2803,6 +2835,311 @@ static void test_GetStringTypeW(void)
         ok(types[i] & C1_SPACE || broken(types[i] == C1_CNTRL) || broken(types[i] == 0), "incorrect types returned for %x -> (%x does not have %x)\n",space_special[i], types[i], C1_SPACE );
 }
 
+static void test_IdnToNameprepUnicode(void)
+{
+    struct {
+        DWORD in_len;
+        const WCHAR in[64];
+        DWORD ret;
+        const WCHAR out[64];
+        DWORD flags;
+        DWORD err;
+        DWORD todo;
+    } test_data[] = {
+        {
+            5, {'t','e','s','t',0},
+            5, {'t','e','s','t',0},
+            0, 0xdeadbeef
+        },
+        {
+            3, {'a',0xe111,'b'},
+            0, {0},
+            0, ERROR_INVALID_NAME
+        },
+        {
+            4, {'t',0,'e',0},
+            0, {0},
+            0, ERROR_INVALID_NAME
+        },
+        {
+            1, {'T',0},
+            1, {'T',0},
+            0, 0xdeadbeef
+        },
+        {
+            1, {0},
+            0, {0},
+            0, ERROR_INVALID_NAME
+        },
+        {
+            6, {' ','-','/','[',']',0},
+            6, {' ','-','/','[',']',0},
+            0, 0xdeadbeef
+        },
+        {
+            3, {'a','-','a'},
+            3, {'a','-','a'},
+            IDN_USE_STD3_ASCII_RULES, 0xdeadbeef
+        },
+        {
+            3, {'a','a','-'},
+            0, {0},
+            IDN_USE_STD3_ASCII_RULES, ERROR_INVALID_NAME
+        },
+        { /* FoldString is not working as expected when MAP_FOLDCZONE is specified (composition+compatibility) */
+            10, {'T',0xdf,0x130,0x143,0x37a,0x6a,0x30c,' ',0xaa,0},
+            12, {'t','s','s','i',0x307,0x144,' ',0x3b9,0x1f0,' ','a',0},
+            0, 0xdeadbeef, TRUE
+        },
+        {
+            11, {'t',0xad,0x34f,0x1806,0x180b,0x180c,0x180d,0x200b,0x200c,0x200d,0},
+            2, {'t',0},
+            0, 0xdeadbeef
+        },
+        { /* Another example of incorrectly working FoldString (composition) */
+            2, {0x3b0, 0},
+            2, {0x3b0, 0},
+            0, 0xdeadbeef, TRUE
+        },
+        {
+            2, {0x221, 0},
+            0, {0},
+            0, ERROR_NO_UNICODE_TRANSLATION
+        },
+        {
+            2, {0x221, 0},
+            2, {0x221, 0},
+            IDN_ALLOW_UNASSIGNED, 0xdeadbeef
+        },
+        {
+            5, {'a','.','.','a',0},
+            0, {0},
+            0, ERROR_INVALID_NAME
+        },
+        {
+            3, {'a','.',0},
+            3, {'a','.',0},
+            0, 0xdeadbeef
+        },
+    };
+
+    WCHAR buf[1024];
+    DWORD i, ret, err;
+
+    if (!pIdnToNameprepUnicode)
+    {
+        win_skip("IdnToNameprepUnicode is not available\n");
+        return;
+    }
+
+    ret = pIdnToNameprepUnicode(0, test_data[0].in,
+            test_data[0].in_len, NULL, 0);
+    ok(ret == test_data[0].ret, "ret = %d\n", ret);
+
+    SetLastError(0xdeadbeef);
+    ret = pIdnToNameprepUnicode(0, test_data[1].in,
+            test_data[1].in_len, NULL, 0);
+    err = GetLastError();
+    ok(ret == test_data[1].ret, "ret = %d\n", ret);
+    ok(err == test_data[1].err, "err = %d\n", err);
+
+    SetLastError(0xdeadbeef);
+    ret = pIdnToNameprepUnicode(0, test_data[0].in, -1,
+            buf, sizeof(buf)/sizeof(WCHAR));
+    err = GetLastError();
+    ok(ret == test_data[0].ret, "ret = %d\n", ret);
+    ok(err == 0xdeadbeef, "err = %d\n", err);
+
+    SetLastError(0xdeadbeef);
+    ret = pIdnToNameprepUnicode(0, test_data[0].in, -2,
+            buf, sizeof(buf)/sizeof(WCHAR));
+    err = GetLastError();
+    ok(ret == 0, "ret = %d\n", ret);
+    ok(err == ERROR_INVALID_PARAMETER, "err = %d\n", err);
+
+    SetLastError(0xdeadbeef);
+    ret = pIdnToNameprepUnicode(0, test_data[0].in, 0,
+            buf, sizeof(buf)/sizeof(WCHAR));
+    err = GetLastError();
+    ok(ret == 0, "ret = %d\n", ret);
+    ok(err == ERROR_INVALID_NAME, "err = %d\n", err);
+
+    ret = pIdnToNameprepUnicode(IDN_ALLOW_UNASSIGNED|IDN_USE_STD3_ASCII_RULES,
+            test_data[0].in, -1, buf, sizeof(buf)/sizeof(WCHAR));
+    ok(ret == test_data[0].ret, "ret = %d\n", ret);
+
+    SetLastError(0xdeadbeef);
+    ret = pIdnToNameprepUnicode(0, NULL, 0, NULL, 0);
+    err = GetLastError();
+    ok(ret == 0, "ret = %d\n", ret);
+    ok(err == ERROR_INVALID_PARAMETER, "err = %d\n", err);
+
+    SetLastError(0xdeadbeef);
+    ret = pIdnToNameprepUnicode(4, NULL, 0, NULL, 0);
+    err = GetLastError();
+    ok(ret == 0, "ret = %d\n", ret);
+    ok(err == ERROR_INVALID_FLAGS, "err = %d\n", err);
+
+    for (i=0; i<sizeof(test_data)/sizeof(*test_data); i++)
+    {
+        SetLastError(0xdeadbeef);
+        ret = pIdnToNameprepUnicode(test_data[i].flags, test_data[i].in,
+                test_data[i].in_len, buf, sizeof(buf)/sizeof(WCHAR));
+        err = GetLastError();
+        if(!test_data[i].todo) {
+            ok(ret == test_data[i].ret, "%d) ret = %d\n", i, ret);
+            ok(err == test_data[i].err, "%d) err = %d\n", i, err);
+            ok(!memcmp(test_data[i].out, buf, ret*sizeof(WCHAR)),
+                    "%d) buf = %s\n", i, wine_dbgstr_wn(buf, ret));
+        }else {
+            todo_wine ok(!memcmp(test_data[i].out, buf, ret*sizeof(WCHAR)),
+                    "%d) buf = %s\n", i, wine_dbgstr_wn(buf, ret));
+        }
+    }
+}
+
+static void test_IdnToAscii(void)
+{
+    struct {
+        DWORD in_len;
+        const WCHAR in[64];
+        DWORD ret;
+        const WCHAR out[64];
+        DWORD flags;
+        DWORD err;
+    } test_data[] = {
+        {
+            5, {'T','e','s','t',0},
+            5, {'T','e','s','t',0},
+            0, 0xdeadbeef
+        },
+        {
+            5, {'T','e',0x017c,'s','t',0},
+            12, {'x','n','-','-','t','e','s','t','-','c','b','b',0},
+            0, 0xdeadbeef
+        },
+        {
+            12, {'t','e',0x0105,'s','t','.','t','e',0x017c,'s','t',0},
+            26, {'x','n','-','-','t','e','s','t','-','c','t','a','.','x','n','-','-','t','e','s','t','-','c','b','b',0},
+            0, 0xdeadbeef
+        },
+        {
+            3, {0x0105,'.',0},
+            9, {'x','n','-','-','2','d','a','.',0},
+            0, 0xdeadbeef
+        },
+        {
+            10, {'h','t','t','p',':','/','/','t',0x0106,0},
+            17, {'x','n','-','-','h','t','t','p',':','/','/','t','-','7','8','a',0},
+            0, 0xdeadbeef
+        },
+        {
+            10, {0x4e3a,0x8bf4,0x4e0d,0x4ed6,0x5011,0x10d,0x11b,0x305c,0x306a,0},
+            35, {'x','n','-','-','b','e','a','2','a','1','6','3','1','a','v','b','a',
+                'v','4','4','t','y','h','a','3','2','b','9','1','e','g','s','2','t',0},
+            0, 0xdeadbeef
+        },
+        {
+            2, {0x221,0},
+            8, {'x','n','-','-','6','l','a',0},
+            IDN_ALLOW_UNASSIGNED, 0xdeadbeef
+        },
+    };
+
+    WCHAR buf[1024];
+    DWORD i, ret, err;
+
+    if (!pIdnToAscii)
+    {
+        win_skip("IdnToAscii is not available\n");
+        return;
+    }
+
+    for (i=0; i<sizeof(test_data)/sizeof(*test_data); i++)
+    {
+        SetLastError(0xdeadbeef);
+        ret = pIdnToAscii(test_data[i].flags, test_data[i].in,
+                test_data[i].in_len, buf, sizeof(buf));
+        err = GetLastError();
+        ok(ret == test_data[i].ret, "%d) ret = %d\n", i, ret);
+        ok(err == test_data[i].err, "%d) err = %d\n", i, err);
+        ok(!memcmp(test_data[i].out, buf, ret*sizeof(WCHAR)),
+                "%d) buf = %s\n", i, wine_dbgstr_wn(buf, ret));
+    }
+}
+
+static void test_IdnToUnicode(void)
+{
+    struct {
+        DWORD in_len;
+        const WCHAR in[64];
+        DWORD ret;
+        const WCHAR out[64];
+        DWORD flags;
+        DWORD err;
+    } test_data[] = {
+        {
+            5, {'T','e','s','.',0},
+            5, {'T','e','s','.',0},
+            0, 0xdeadbeef
+        },
+        {
+            2, {0x105,0},
+            0, {0},
+            0, ERROR_INVALID_NAME
+        },
+        {
+            33, {'x','n','-','-','4','d','b','c','a','g','d','a','h','y','m','b',
+                'x','e','k','h','e','h','6','e','0','a','7','f','e','i','0','b',0},
+            23, {0x05dc,0x05de,0x05d4,0x05d4,0x05dd,0x05e4,0x05e9,0x05d5,0x05d8,
+                0x05dc,0x05d0,0x05de,0x05d3,0x05d1,0x05e8,0x05d9,0x05dd,0x05e2,
+                0x05d1,0x05e8,0x05d9,0x05ea,0},
+            0, 0xdeadbeef
+        },
+        {
+            34, {'t','e','s','t','.','x','n','-','-','k','d','a','9','a','g','5','e',
+                '9','j','n','f','s','j','.','x','n','-','-','p','d','-','f','n','a'},
+            16, {'t','e','s','t','.',0x0105,0x0119,0x015b,0x0107,
+                0x0142,0x00f3,0x017c,'.','p',0x0119,'d'},
+            0, 0xdeadbeef
+        },
+        {
+            64, {'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
+                'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
+                'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
+                'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a'},
+            0, {0},
+            0, ERROR_INVALID_NAME
+        },
+        {
+            8, {'x','n','-','-','6','l','a',0},
+            2, {0x221,0},
+            IDN_ALLOW_UNASSIGNED, 0xdeadbeef
+        },
+    };
+
+    WCHAR buf[1024];
+    DWORD i, ret, err;
+
+    if (!pIdnToUnicode)
+    {
+        win_skip("IdnToUnicode is not available\n");
+        return;
+    }
+
+    for (i=0; i<sizeof(test_data)/sizeof(*test_data); i++)
+    {
+        SetLastError(0xdeadbeef);
+        ret = pIdnToUnicode(test_data[i].flags, test_data[i].in,
+                test_data[i].in_len, buf, sizeof(buf));
+        err = GetLastError();
+        ok(ret == test_data[i].ret, "%d) ret = %d\n", i, ret);
+        ok(err == test_data[i].err, "%d) err = %d\n", i, err);
+        ok(!memcmp(test_data[i].out, buf, ret*sizeof(WCHAR)),
+                "%d) buf = %s\n", i, wine_dbgstr_wn(buf, ret));
+    }
+}
+
 START_TEST(locale)
 {
   InitFunctionPointers();
@@ -2819,6 +3156,7 @@ START_TEST(locale)
   test_CompareStringA();
   test_LCMapStringA();
   test_LCMapStringW();
+  test_LocaleNames();
   test_FoldStringA();
   test_FoldStringW();
   test_ConvertDefaultLocale();
@@ -2829,6 +3167,9 @@ START_TEST(locale)
   test_EnumUILanguageA();
   test_GetCPInfo();
   test_GetStringTypeW();
+  test_IdnToNameprepUnicode();
+  test_IdnToAscii();
+  test_IdnToUnicode();
   /* this requires collation table patch to make it MS compatible */
   if (0) test_sorting();
 }
index 01fa448..f88c8cb 100755 (executable)
 #include "wine/test.h"
 #include <windows.h>
 
+static DWORD (WINAPI *pGetDllDirectoryA)(DWORD,LPSTR);
+static DWORD (WINAPI *pGetDllDirectoryW)(DWORD,LPWSTR);
+static BOOL (WINAPI *pSetDllDirectoryA)(LPCSTR);
+static BOOL (WINAPI *pGetModuleHandleExA)(DWORD,LPCSTR,HMODULE*);
+static BOOL (WINAPI *pGetModuleHandleExW)(DWORD,LPCWSTR,HMODULE*);
+
 static BOOL is_unicode_enabled = TRUE;
 
 static BOOL cmpStrAW(const char* a, const WCHAR* b, DWORD lenA, DWORD lenB)
@@ -44,13 +50,21 @@ static void testGetModuleFileName(const char* name)
 
     /* first test, with enough space in buffer */
     memset(bufA, '-', sizeof(bufA));
+    SetLastError(0xdeadbeef);
     len1A = GetModuleFileNameA(hMod, bufA, sizeof(bufA));
+    ok(GetLastError() == ERROR_SUCCESS ||
+       broken(GetLastError() == 0xdeadbeef), /* <= XP SP3 */
+       "LastError was not reset: %u\n", GetLastError());
     ok(len1A > 0, "Getting module filename for handle %p\n", hMod);
 
     if (is_unicode_enabled)
     {
         memset(bufW, '-', sizeof(bufW));
+        SetLastError(0xdeadbeef);
         len1W = GetModuleFileNameW(hMod, bufW, sizeof(bufW) / sizeof(WCHAR));
+        ok(GetLastError() == ERROR_SUCCESS ||
+           broken(GetLastError() == 0xdeadbeef), /* <= XP SP3 */
+           "LastError was not reset: %u\n", GetLastError());
         ok(len1W > 0, "Getting module filename for handle %p\n", hMod);
     }
 
@@ -378,6 +392,294 @@ static void testLoadLibraryEx(void)
 
 }
 
+static void testGetDllDirectory(void)
+{
+    CHAR bufferA[MAX_PATH];
+    WCHAR bufferW[MAX_PATH];
+    DWORD length, ret;
+    int i;
+    static const char *dll_directories[] =
+    {
+        "",
+        "C:\\Some\\Path",
+        "C:\\Some\\Path\\",
+        "Q:\\A\\Long\\Path with spaces that\\probably\\doesn't exist!",
+    };
+    const int test_count = sizeof(dll_directories) / sizeof(dll_directories[0]);
+
+    if (!pGetDllDirectoryA || !pGetDllDirectoryW)
+    {
+        win_skip("GetDllDirectory not available\n");
+        return;
+    }
+    if (!pSetDllDirectoryA)
+    {
+        win_skip("SetDllDirectoryA not available\n");
+        return;
+    }
+
+    for (i = 0; i < test_count; i++)
+    {
+        length = strlen(dll_directories[i]);
+        if (!pSetDllDirectoryA(dll_directories[i]))
+        {
+            skip("i=%d, SetDllDirectoryA failed\n", i);
+            continue;
+        }
+
+        /* no buffer, determine length */
+        ret = pGetDllDirectoryA(0, NULL);
+        ok(ret == length + 1, "Expected %u, got %u\n", length + 1, ret);
+
+        ret = pGetDllDirectoryW(0, NULL);
+        ok(ret == length + 1, "Expected %u, got %u\n", length + 1, ret);
+
+        /* buffer of exactly the right size */
+        bufferA[length] = 'A';
+        bufferA[length + 1] = 'A';
+        ret = pGetDllDirectoryA(length + 1, bufferA);
+        ok(ret == length, "i=%d, Expected %u, got %u\n", i, length, ret);
+        ok(bufferA[length + 1] == 'A', "i=%d, Buffer overflow\n", i);
+        ok(strcmp(bufferA, dll_directories[i]) == 0, "i=%d, Wrong path returned: '%s'\n", i, bufferA);
+
+        bufferW[length] = 'A';
+        bufferW[length + 1] = 'A';
+        ret = pGetDllDirectoryW(length + 1, bufferW);
+        ok(ret == length, "i=%d, Expected %u, got %u\n", i, length, ret);
+        ok(bufferW[length + 1] == 'A', "i=%d, Buffer overflow\n", i);
+        ok(cmpStrAW(dll_directories[i], bufferW, length, length),
+           "i=%d, Wrong path returned: %s\n", i, wine_dbgstr_w(bufferW));
+
+        /* zero size buffer
+         * the A version always null-terminates the buffer,
+         * the W version doesn't do it on some platforms */
+        bufferA[0] = 'A';
+        ret = pGetDllDirectoryA(0, bufferA);
+        ok(ret == length + 1, "i=%d, Expected %u, got %u\n", i, length + 1, ret);
+        ok(bufferA[0] == 0, "i=%d, Buffer not null terminated\n", i);
+
+        bufferW[0] = 'A';
+        ret = pGetDllDirectoryW(0, bufferW);
+        ok(ret == length + 1, "i=%d, Expected %u, got %u\n", i, length + 1, ret);
+        ok(bufferW[0] == 0 || /* XP, 2003 */
+           broken(bufferW[0] == 'A'), "i=%d, Buffer overflow\n", i);
+
+        /* buffer just one too short */
+        bufferA[0] = 'A';
+        ret = pGetDllDirectoryA(length, bufferA);
+        ok(ret == length + 1, "i=%d, Expected %u, got %u\n", i, length + 1, ret);
+        ok(bufferA[0] == 0, "i=%d, Buffer not null terminated\n", i);
+
+        bufferW[0] = 'A';
+        ret = pGetDllDirectoryW(length, bufferW);
+        ok(ret == length + 1, "i=%d, Expected %u, got %u\n", i, length + 1, ret);
+        ok(bufferW[0] == 0 || /* XP, 2003 */
+           broken(bufferW[0] == 'A'), "i=%d, Buffer overflow\n", i);
+
+        /* no buffer, but too short length */
+        ret = pGetDllDirectoryA(length, NULL);
+        ok(ret == length + 1, "i=%d, Expected %u, got %u\n", i, length + 1, ret);
+
+        ret = pGetDllDirectoryW(length, NULL);
+        ok(ret == length + 1, "i=%d, Expected %u, got %u\n", i, length + 1, ret);
+    }
+
+    /* unset whatever we did so following tests won't be affected */
+    pSetDllDirectoryA(NULL);
+}
+
+static void init_pointers(void)
+{
+    HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
+
+#define MAKEFUNC(f) (p##f = (void*)GetProcAddress(hKernel32, #f))
+    MAKEFUNC(GetDllDirectoryA);
+    MAKEFUNC(GetDllDirectoryW);
+    MAKEFUNC(SetDllDirectoryA);
+    MAKEFUNC(GetModuleHandleExA);
+    MAKEFUNC(GetModuleHandleExW);
+#undef MAKEFUNC
+}
+
+static void testGetModuleHandleEx(void)
+{
+    static const WCHAR kernel32W[] = {'k','e','r','n','e','l','3','2',0};
+    static const WCHAR nosuchmodW[] = {'n','o','s','u','c','h','m','o','d',0};
+    BOOL ret;
+    DWORD error;
+    HMODULE mod, mod_kernel32;
+
+    if (!pGetModuleHandleExA || !pGetModuleHandleExW)
+    {
+        win_skip( "GetModuleHandleEx not available\n" );
+        return;
+    }
+
+    SetLastError( 0xdeadbeef );
+    ret = pGetModuleHandleExA( 0, NULL, NULL );
+    error = GetLastError();
+    ok( !ret, "unexpected success\n" );
+    ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
+
+    SetLastError( 0xdeadbeef );
+    ret = pGetModuleHandleExA( 0, "kernel32", NULL );
+    error = GetLastError();
+    ok( !ret, "unexpected success\n" );
+    ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
+
+    SetLastError( 0xdeadbeef );
+    mod = (HMODULE)0xdeadbeef;
+    ret = pGetModuleHandleExA( 0, "kernel32", &mod );
+    ok( ret, "unexpected failure %u\n", GetLastError() );
+    ok( mod != (HMODULE)0xdeadbeef, "got %p\n", mod );
+    FreeLibrary( mod );
+
+    SetLastError( 0xdeadbeef );
+    mod = (HMODULE)0xdeadbeef;
+    ret = pGetModuleHandleExA( 0, "nosuchmod", &mod );
+    error = GetLastError();
+    ok( !ret, "unexpected success\n" );
+    ok( error == ERROR_MOD_NOT_FOUND, "got %u\n", error );
+    ok( mod == NULL, "got %p\n", mod );
+
+    SetLastError( 0xdeadbeef );
+    ret = pGetModuleHandleExW( 0, NULL, NULL );
+    error = GetLastError();
+    ok( !ret, "unexpected success\n" );
+    ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
+
+    SetLastError( 0xdeadbeef );
+    ret = pGetModuleHandleExW( 0, kernel32W, NULL );
+    error = GetLastError();
+    ok( !ret, "unexpected success\n" );
+    ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
+
+    SetLastError( 0xdeadbeef );
+    mod = (HMODULE)0xdeadbeef;
+    ret = pGetModuleHandleExW( 0, kernel32W, &mod );
+    ok( ret, "unexpected failure %u\n", GetLastError() );
+    ok( mod != (HMODULE)0xdeadbeef, "got %p\n", mod );
+    FreeLibrary( mod );
+
+    SetLastError( 0xdeadbeef );
+    mod = (HMODULE)0xdeadbeef;
+    ret = pGetModuleHandleExW( 0, nosuchmodW, &mod );
+    error = GetLastError();
+    ok( !ret, "unexpected success\n" );
+    ok( error == ERROR_MOD_NOT_FOUND, "got %u\n", error );
+    ok( mod == NULL, "got %p\n", mod );
+
+    SetLastError( 0xdeadbeef );
+    ret = pGetModuleHandleExA( GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, NULL, NULL );
+    error = GetLastError();
+    ok( !ret, "unexpected success\n" );
+    ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
+
+    SetLastError( 0xdeadbeef );
+    ret = pGetModuleHandleExA( GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, "kernel32", NULL );
+    error = GetLastError();
+    ok( !ret, "unexpected success\n" );
+    ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
+
+    SetLastError( 0xdeadbeef );
+    mod = (HMODULE)0xdeadbeef;
+    ret = pGetModuleHandleExA( GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, "kernel32", &mod );
+    ok( ret, "unexpected failure %u\n", GetLastError() );
+    ok( mod != (HMODULE)0xdeadbeef, "got %p\n", mod );
+
+    SetLastError( 0xdeadbeef );
+    mod = (HMODULE)0xdeadbeef;
+    ret = pGetModuleHandleExA( GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, "nosuchmod", &mod );
+    error = GetLastError();
+    ok( !ret, "unexpected success\n" );
+    ok( error == ERROR_MOD_NOT_FOUND, "got %u\n", error );
+    ok( mod == NULL, "got %p\n", mod );
+
+    SetLastError( 0xdeadbeef );
+    ret = pGetModuleHandleExW( GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, NULL, NULL );
+    error = GetLastError();
+    ok( !ret, "unexpected success\n" );
+    ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
+
+    SetLastError( 0xdeadbeef );
+    ret = pGetModuleHandleExW( GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, kernel32W, NULL );
+    error = GetLastError();
+    ok( !ret, "unexpected success\n" );
+    ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
+
+    SetLastError( 0xdeadbeef );
+    mod = (HMODULE)0xdeadbeef;
+    ret = pGetModuleHandleExW( GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, kernel32W, &mod );
+    ok( ret, "unexpected failure %u\n", GetLastError() );
+    ok( mod != (HMODULE)0xdeadbeef, "got %p\n", mod );
+
+    SetLastError( 0xdeadbeef );
+    mod = (HMODULE)0xdeadbeef;
+    ret = pGetModuleHandleExW( GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, nosuchmodW, &mod );
+    error = GetLastError();
+    ok( !ret, "unexpected success\n" );
+    ok( error == ERROR_MOD_NOT_FOUND, "got %u\n", error );
+    ok( mod == NULL, "got %p\n", mod );
+
+    mod_kernel32 = LoadLibraryA( "kernel32" );
+
+    SetLastError( 0xdeadbeef );
+    ret = pGetModuleHandleExA( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, NULL, NULL );
+    error = GetLastError();
+    ok( !ret, "unexpected success\n" );
+    ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
+
+    SetLastError( 0xdeadbeef );
+    ret = pGetModuleHandleExA( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCSTR)mod_kernel32, NULL );
+    error = GetLastError();
+    ok( !ret, "unexpected success\n" );
+    ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
+
+    SetLastError( 0xdeadbeef );
+    mod = (HMODULE)0xdeadbeef;
+    ret = pGetModuleHandleExA( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCSTR)mod_kernel32, &mod );
+    ok( ret, "unexpected failure %u\n", GetLastError() );
+    ok( mod == mod_kernel32, "got %p\n", mod );
+    FreeLibrary( mod );
+
+    SetLastError( 0xdeadbeef );
+    mod = (HMODULE)0xdeadbeef;
+    ret = pGetModuleHandleExA( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCSTR)0xbeefdead, &mod );
+    error = GetLastError();
+    ok( !ret, "unexpected success\n" );
+    ok( error == ERROR_MOD_NOT_FOUND, "got %u\n", error );
+    ok( mod == NULL, "got %p\n", mod );
+
+    SetLastError( 0xdeadbeef );
+    ret = pGetModuleHandleExW( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, NULL, NULL );
+    error = GetLastError();
+    ok( !ret, "unexpected success\n" );
+    ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
+
+    SetLastError( 0xdeadbeef );
+    ret = pGetModuleHandleExW( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCWSTR)mod_kernel32, NULL );
+    error = GetLastError();
+    ok( !ret, "unexpected success\n" );
+    ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
+
+    SetLastError( 0xdeadbeef );
+    mod = (HMODULE)0xdeadbeef;
+    ret = pGetModuleHandleExW( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCWSTR)mod_kernel32, &mod );
+    ok( ret, "unexpected failure %u\n", GetLastError() );
+    ok( mod == mod_kernel32, "got %p\n", mod );
+    FreeLibrary( mod );
+
+    SetLastError( 0xdeadbeef );
+    mod = (HMODULE)0xdeadbeef;
+    ret = pGetModuleHandleExW( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCWSTR)0xbeefdead, &mod );
+    error = GetLastError();
+    ok( !ret, "unexpected success\n" );
+    ok( error == ERROR_MOD_NOT_FOUND, "got %u\n", error );
+    ok( mod == NULL, "got %p\n", mod );
+
+    FreeLibrary( mod_kernel32 );
+}
+
 START_TEST(module)
 {
     WCHAR filenameW[MAX_PATH];
@@ -392,13 +694,18 @@ START_TEST(module)
         is_unicode_enabled = FALSE;
     }
 
+    init_pointers();
+
     testGetModuleFileName(NULL);
     testGetModuleFileName("kernel32.dll");
     testGetModuleFileName_Wrong();
 
+    testGetDllDirectory();
+
     testLoadLibraryA();
     testNestedLoadLibraryA();
     testLoadLibraryA_Wrong();
     testGetProcAddress_Wrong();
     testLoadLibraryEx();
+    testGetModuleHandleEx();
 }
index ed78794..3484c62 100755 (executable)
@@ -18,7 +18,6 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#include <assert.h>
 #include <stdarg.h>
 #include <stdio.h>
 
@@ -72,6 +71,19 @@ static void test_CreateNamedPipe(int pipemode)
     ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_NAME,
         "CreateNamedPipe should fail if name doesn't start with \\\\.\\pipe\n");
 
+    if (pipemode == PIPE_TYPE_BYTE)
+    {
+        /* Bad parameter checks */
+        hnp = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_MESSAGE,
+            /* nMaxInstances */ 1,
+            /* nOutBufSize */ 1024,
+            /* nInBufSize */ 1024,
+            /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
+            /* lpSecurityAttrib */ NULL);
+        ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_PARAMETER,
+            "CreateNamedPipe should fail with PIPE_TYPE_BYTE | PIPE_READMODE_MESSAGE\n");
+    }
+
     hnp = CreateNamedPipe(NULL,
         PIPE_ACCESS_DUPLEX, pipemode | PIPE_WAIT,
         1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
@@ -375,7 +387,7 @@ static void test_CreateNamedPipe_instances_must_match(void)
     ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
 
     hnp2 = CreateNamedPipe(PIPENAME, PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE | PIPE_WAIT,
-        /* nMaxInstances */ 1,
+        /* nMaxInstances */ 2,
         /* nOutBufSize */ 1024,
         /* nInBufSize */ 1024,
         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
@@ -385,7 +397,25 @@ static void test_CreateNamedPipe_instances_must_match(void)
 
     ok(CloseHandle(hnp), "CloseHandle\n");
 
-    /* etc, etc */
+    /* check everything else */
+    hnp = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
+        /* nMaxInstances */ 4,
+        /* nOutBufSize */ 1024,
+        /* nInBufSize */ 1024,
+        /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
+        /* lpSecurityAttrib */ NULL);
+    ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
+
+    hnp2 = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE,
+        /* nMaxInstances */ 3,
+        /* nOutBufSize */ 102,
+        /* nInBufSize */ 24,
+        /* nDefaultWait */ 1234,
+        /* lpSecurityAttrib */ NULL);
+    ok(hnp2 != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
+
+    ok(CloseHandle(hnp), "CloseHandle\n");
+    ok(CloseHandle(hnp2), "CloseHandle\n");
 }
 
 /** implementation of alarm() */
@@ -480,7 +510,8 @@ static DWORD CALLBACK serverThreadMain2(LPVOID arg)
         user_apc_ran = FALSE;
         if (i == 0 && pQueueUserAPC) {
             trace("Queueing an user APC\n"); /* verify the pipe is non alerable */
-            ok(pQueueUserAPC(&user_apc, GetCurrentThread(), 0), "QueueUserAPC failed: %d\n", GetLastError());
+            success = pQueueUserAPC(&user_apc, GetCurrentThread(), 0);
+            ok(success, "QueueUserAPC failed: %d\n", GetLastError());
         }
 
         /* Wait for client to connect */
index b3b8d18..8aadf2a 100755 (executable)
@@ -62,6 +62,7 @@ static LPVOID (WINAPI *pVirtualAllocEx)(HANDLE, LPVOID, SIZE_T, DWORD, DWORD);
 static BOOL   (WINAPI *pVirtualFreeEx)(HANDLE, LPVOID, SIZE_T, DWORD);
 static BOOL   (WINAPI *pQueryFullProcessImageNameA)(HANDLE hProcess, DWORD dwFlags, LPSTR lpExeName, PDWORD lpdwSize);
 static BOOL   (WINAPI *pQueryFullProcessImageNameW)(HANDLE hProcess, DWORD dwFlags, LPWSTR lpExeName, PDWORD lpdwSize);
+static DWORD  (WINAPI *pK32GetProcessImageFileNameA)(HANDLE,LPSTR,DWORD);
 
 /* ############################### */
 static char     base[MAX_PATH];
@@ -204,6 +205,7 @@ static int     init(void)
     pVirtualFreeEx = (void *) GetProcAddress(hkernel32, "VirtualFreeEx");
     pQueryFullProcessImageNameA = (void *) GetProcAddress(hkernel32, "QueryFullProcessImageNameA");
     pQueryFullProcessImageNameW = (void *) GetProcAddress(hkernel32, "QueryFullProcessImageNameW");
+    pK32GetProcessImageFileNameA = (void *) GetProcAddress(hkernel32, "K32GetProcessImageFileNameA");
     return 1;
 }
 
@@ -1638,21 +1640,70 @@ static void test_GetProcessVersion(void)
     CloseHandle(pi.hThread);
 }
 
-static void test_ProcessNameA(void)
+static void test_GetProcessImageFileNameA(void)
+{
+    DWORD rc;
+    CHAR process[MAX_PATH];
+    static const char harddisk[] = "\\Device\\HarddiskVolume";
+
+    if (!pK32GetProcessImageFileNameA)
+    {
+        win_skip("K32GetProcessImageFileNameA is unavailable\n");
+        return;
+    }
+
+    /* callers must guess the buffer size */
+    SetLastError(0xdeadbeef);
+    rc = pK32GetProcessImageFileNameA(GetCurrentProcess(), NULL, 0);
+    ok(!rc && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+       "K32GetProcessImageFileNameA(no buffer): returned %u, le=%u\n", rc, GetLastError());
+
+    *process = '\0';
+    rc = pK32GetProcessImageFileNameA(GetCurrentProcess(), process, sizeof(process));
+    expect_eq_d(rc, lstrlenA(process));
+    if (strncmp(process, harddisk, lstrlenA(harddisk)))
+    {
+        todo_wine win_skip("%s is probably on a network share, skipping tests\n", process);
+        return;
+    }
+
+    if (!pQueryFullProcessImageNameA)
+        win_skip("QueryFullProcessImageNameA unavailable (added in Windows Vista)\n");
+    else
+    {
+        CHAR image[MAX_PATH];
+        DWORD length;
+
+        length = sizeof(image);
+        expect_eq_d(TRUE, pQueryFullProcessImageNameA(GetCurrentProcess(), PROCESS_NAME_NATIVE, image, &length));
+        expect_eq_d(length, lstrlenA(image));
+        ok(lstrcmpi(process, image) == 0, "expected '%s' to be equal to '%s'\n", process, image);
+    }
+}
+
+static void test_QueryFullProcessImageNameA(void)
 {
 #define INIT_STR "Just some words"
     DWORD length, size;
-    CHAR buf[1024];
+    CHAR buf[MAX_PATH], module[MAX_PATH];
 
     if (!pQueryFullProcessImageNameA)
     {
         win_skip("QueryFullProcessImageNameA unavailable (added in Windows Vista)\n");
         return;
     }
+
+    *module = '\0';
+    SetLastError(0); /* old Windows don't reset it on success */
+    size = GetModuleFileNameA(NULL, module, sizeof(module));
+    ok(size && GetLastError() != ERROR_INSUFFICIENT_BUFFER, "GetModuleFileName failed: %u le=%u\n", size, GetLastError());
+
     /* get the buffer length without \0 terminator */
-    length = 1024;
+    length = sizeof(buf);
     expect_eq_d(TRUE, pQueryFullProcessImageNameA(GetCurrentProcess(), 0, buf, &length));
     expect_eq_d(length, lstrlenA(buf));
+    ok((buf[0] == '\\' && buf[1] == '\\') ||
+       lstrcmpi(buf, module) == 0, "expected %s to match %s\n", buf, module);
 
     /*  when the buffer is too small
      *  - function fail with error ERROR_INSUFFICIENT_BUFFER
@@ -1676,8 +1727,8 @@ static void test_ProcessNameA(void)
     expect_eq_s(INIT_STR, buf);
 
     /* this is a difference between the ascii and the unicode version
-     * the unicode version crashes when the size is big enough to hold the result
-     * ascii version through an error
+     * the unicode version crashes when the size is big enough to hold
+     * the result while the ascii version throws an error
      */
     size = 1024;
     expect_eq_d(FALSE, pQueryFullProcessImageNameA(GetCurrentProcess(), 0, NULL, &size));
@@ -1685,13 +1736,13 @@ static void test_ProcessNameA(void)
     expect_eq_d(ERROR_INVALID_PARAMETER, GetLastError());
 }
 
-static void test_ProcessName(void)
+static void test_QueryFullProcessImageNameW(void)
 {
     HANDLE hSelf;
-    WCHAR module_name[1024];
+    WCHAR module_name[1024], device[1024];
     WCHAR deviceW[] = {'\\','D', 'e','v','i','c','e',0};
     WCHAR buf[1024];
-    DWORD size;
+    DWORD size, len;
 
     if (!pQueryFullProcessImageNameW)
     {
@@ -1736,13 +1787,6 @@ static void test_ProcessName(void)
     expect_eq_d(0, size);
     expect_eq_d(ERROR_INSUFFICIENT_BUFFER, GetLastError());
 
-    /* native path */
-    size = sizeof(buf) / sizeof(buf[0]);
-    expect_eq_d(TRUE, pQueryFullProcessImageNameW(hSelf, PROCESS_NAME_NATIVE, buf, &size));
-    expect_eq_d(lstrlenW(buf), size);
-    ok(buf[0] == '\\', "NT path should begin with '\\'\n");
-    todo_wine ok(memcmp(buf, deviceW, sizeof(WCHAR)*lstrlenW(deviceW)) == 0, "NT path should begin with \\Device\n");
-
     /* Buffer too small */
     size = lstrlenW(module_name)/2;
     SetLastError(0xdeadbeef);
@@ -1752,6 +1796,33 @@ static void test_ProcessName(void)
     expect_eq_d(ERROR_INSUFFICIENT_BUFFER, GetLastError());
     expect_eq_ws_i(module_name, buf);  /* buffer not changed */
 
+
+    /* native path */
+    size = sizeof(buf) / sizeof(buf[0]);
+    expect_eq_d(TRUE, pQueryFullProcessImageNameW(hSelf, PROCESS_NAME_NATIVE, buf, &size));
+    expect_eq_d(lstrlenW(buf), size);
+    ok(buf[0] == '\\', "NT path should begin with '\\'\n");
+    ok(memcmp(buf, deviceW, sizeof(WCHAR)*lstrlenW(deviceW)) == 0, "NT path should begin with \\Device\n");
+
+    module_name[2] = '\0';
+    *device = '\0';
+    size = QueryDosDeviceW(module_name, device, sizeof(device)/sizeof(device[0]));
+    ok(size, "QueryDosDeviceW failed: le=%u\n", GetLastError());
+    len = lstrlenW(device);
+    ok(size >= len+2, "expected %d to be greater than %d+2 = strlen(%s)\n", size, len, wine_dbgstr_w(device));
+
+    if (size >= lstrlenW(buf))
+    {
+        ok(0, "expected %s\\ to match the start of %s\n", wine_dbgstr_w(device), wine_dbgstr_w(buf));
+    }
+    else
+    {
+        ok(buf[len] == '\\', "expected '%c' to be a '\\' in %s\n", buf[len], wine_dbgstr_w(module_name));
+        buf[len] = '\0';
+        ok(lstrcmpiW(device, buf) == 0, "expected %s to match %s\n", wine_dbgstr_w(device), wine_dbgstr_w(buf));
+        ok(lstrcmpiW(module_name+3, buf+len+1) == 0, "expected '%s' to match '%s'\n", wine_dbgstr_w(module_name+3), wine_dbgstr_w(buf+len+1));
+    }
+
     CloseHandle(hSelf);
 }
 
@@ -1888,8 +1959,9 @@ START_TEST(process)
     test_ExitCode();
     test_OpenProcess();
     test_GetProcessVersion();
-    test_ProcessNameA();
-    test_ProcessName();
+    test_GetProcessImageFileNameA();
+    test_QueryFullProcessImageNameA();
+    test_QueryFullProcessImageNameW();
     test_Handles();
     test_SystemInfo();
     test_RegistryQuota();
index 07b351c..211d0c6 100755 (executable)
@@ -448,8 +448,8 @@ static void test_profile_delete_on_close(void)
 
     h = CreateFile(testfile, GENERIC_WRITE, FILE_SHARE_READ, NULL,
                     CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL);
-    ok( WriteFile( h, contents, sizeof contents - 1, &size, NULL ),
-                    "Cannot write test file: %x\n", GetLastError() );
+    res = WriteFile( h, contents, sizeof contents - 1, &size, NULL );
+    ok( res, "Cannot write test file: %x\n", GetLastError() );
     ok( size == sizeof contents - 1, "Test file: partial write\n");
 
     SetLastError(0xdeadbeef);
@@ -472,8 +472,8 @@ static void test_profile_refresh(void)
 
     h = CreateFile(testfile, GENERIC_WRITE, FILE_SHARE_READ, NULL,
                     CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL);
-    ok( WriteFile( h, contents1, sizeof contents1 - 1, &size, NULL ),
-                    "Cannot write test file: %x\n", GetLastError() );
+    res = WriteFile( h, contents1, sizeof contents1 - 1, &size, NULL );
+    ok( res, "Cannot write test file: %x\n", GetLastError() );
     ok( size == sizeof contents1 - 1, "Test file: partial write\n");
 
     SetLastError(0xdeadbeef);
@@ -488,8 +488,8 @@ static void test_profile_refresh(void)
 
     h = CreateFile(testfile, GENERIC_WRITE, FILE_SHARE_READ, NULL,
                     CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL);
-    ok( WriteFile( h, contents2, sizeof contents2 - 1, &size, NULL ),
-                    "Cannot write test file: %x\n", GetLastError() );
+    res = WriteFile( h, contents2, sizeof contents2 - 1, &size, NULL );
+    ok( res, "Cannot write test file: %x\n", GetLastError() );
     ok( size == sizeof contents2 - 1, "Test file: partial write\n");
 
     SetLastError(0xdeadbeef);
@@ -500,6 +500,13 @@ static void test_profile_refresh(void)
 
     /* This also deletes the file */
     CloseHandle(h);
+
+    /* Cache must be invalidated if file no longer exists and default must be returned */
+    SetLastError(0xdeadbeef);
+    res = GetPrivateProfileInt(SECTION, KEY, 421, testfile);
+    ok( res == 421 ||
+        broken(res == 0 && GetLastError() == 0xdeadbeef), /* Win9x, WinME */
+        "Got %d instead of 421\n", res);
 }
 
 static void create_test_file(LPCSTR name, LPCSTR data, DWORD size)
index 98d996f..e875c79 100755 (executable)
@@ -18,7 +18,7 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#define _WIN32_WINNT 0x500
+#define _WIN32_WINNT 0x502
 #include <stdarg.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -35,6 +35,8 @@ static HANDLE (WINAPI *pCreateWaitableTimerA)(SECURITY_ATTRIBUTES*,BOOL,LPCSTR);
 static BOOL   (WINAPI *pDeleteTimerQueueEx)(HANDLE, HANDLE);
 static BOOL   (WINAPI *pDeleteTimerQueueTimer)(HANDLE, HANDLE, HANDLE);
 static HANDLE (WINAPI *pOpenWaitableTimerA)(DWORD,BOOL,LPCSTR);
+static HANDLE (WINAPI *pCreateMemoryResourceNotification)(MEMORY_RESOURCE_NOTIFICATION_TYPE);
+static BOOL   (WINAPI *pQueryMemoryResourceNotification)(HANDLE, PBOOL);
 
 static void test_signalandwait(void)
 {
@@ -131,12 +133,23 @@ static void test_mutex(void)
     int i;
     DWORD failed = 0;
 
+    SetLastError(0xdeadbeef);
+    hOpened = OpenMutex(0, FALSE, "WineTestMutex");
+    ok(hOpened == NULL, "OpenMutex succeeded\n");
+    ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
+
+    SetLastError(0xdeadbeef);
     hCreated = CreateMutex(NULL, FALSE, "WineTestMutex");
     ok(hCreated != NULL, "CreateMutex failed with error %d\n", GetLastError());
 
+    SetLastError(0xdeadbeef);
     hOpened = OpenMutex(0, FALSE, "WineTestMutex");
-    ok(hOpened == NULL, "OpenMutex succeded\n");
+todo_wine
+    ok(hOpened == NULL, "OpenMutex succeeded\n");
+todo_wine
+    ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u\n", GetLastError());
 
+    SetLastError(0xdeadbeef);
     hOpened = OpenMutex(GENERIC_EXECUTE, FALSE, "WineTestMutex");
     ok(hOpened != NULL, "OpenMutex failed with error %d\n", GetLastError());
     wait_ret = WaitForSingleObject(hOpened, INFINITE);
@@ -149,6 +162,7 @@ static void test_mutex(void)
         ok(wait_ret == WAIT_OBJECT_0, "WaitForSingleObject failed with error 0x%08x\n", wait_ret);
     }
 
+    SetLastError(0xdeadbeef);
     hOpened = OpenMutex(GENERIC_READ | GENERIC_WRITE, FALSE, "WineTestMutex");
     ok(hOpened != NULL, "OpenMutex failed with error %d\n", GetLastError());
     wait_ret = WaitForSingleObject(hOpened, INFINITE);
@@ -157,22 +171,30 @@ static void test_mutex(void)
 
     for (i = 0; i < 32; i++)
     {
+        SetLastError(0xdeadbeef);
         hOpened = OpenMutex(0x1 << i, FALSE, "WineTestMutex");
         if(hOpened != NULL)
         {
+            SetLastError(0xdeadbeef);
             ret = ReleaseMutex(hOpened);
             ok(ret, "ReleaseMutex failed with error %d, access %x\n", GetLastError(), 1 << i);
             CloseHandle(hOpened);
         }
         else
         {
+            if ((1 << i) == ACCESS_SYSTEM_SECURITY)
+                todo_wine ok(GetLastError() == ERROR_PRIVILEGE_NOT_HELD, "wrong error %u, access %x\n", GetLastError(), 1 << i);
+            else
+                todo_wine ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u, , access %x\n", GetLastError(), 1 << i);
             ReleaseMutex(hCreated);
             failed |=0x1 << i;
         }
     }
 
-    ok( failed == 0x0de0fffe, "open succeded when it shouldn't: %x\n", failed);
+todo_wine
+    ok( failed == 0x0de0fffe, "open succeeded when it shouldn't: %x\n", failed);
 
+    SetLastError(0xdeadbeef);
     ret = ReleaseMutex(hCreated);
     ok(!ret && (GetLastError() == ERROR_NOT_OWNER),
         "ReleaseMutex should have failed with ERROR_NOT_OWNER instead of %d\n", GetLastError());
@@ -300,6 +322,8 @@ static void test_event(void)
     SECURITY_ATTRIBUTES sa;
     SECURITY_DESCRIPTOR sd;
     ACL acl;
+    DWORD ret;
+    BOOL val;
 
     /* no sd */
     handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
@@ -360,6 +384,39 @@ static void test_event(void)
     ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
 
     CloseHandle( handle );
+
+    /* resource notifications are events too */
+
+    if (!pCreateMemoryResourceNotification || !pQueryMemoryResourceNotification)
+    {
+        trace( "memory resource notifications not supported\n" );
+        return;
+    }
+    handle = pCreateMemoryResourceNotification( HighMemoryResourceNotification + 1 );
+    ok( !handle, "CreateMemoryResourceNotification succeeded\n" );
+    ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
+    ret = pQueryMemoryResourceNotification( handle, &val );
+    ok( !ret, "QueryMemoryResourceNotification succeeded\n" );
+    ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
+
+    handle = pCreateMemoryResourceNotification( LowMemoryResourceNotification );
+    ok( handle != 0, "CreateMemoryResourceNotification failed err %u\n", GetLastError() );
+    ret = WaitForSingleObject( handle, 10 );
+    ok( ret == WAIT_OBJECT_0 || ret == WAIT_TIMEOUT, "WaitForSingleObject wrong ret %u\n", ret );
+
+    val = ~0;
+    ret = pQueryMemoryResourceNotification( handle, &val );
+    ok( ret, "QueryMemoryResourceNotification failed err %u\n", GetLastError() );
+    ok( val == FALSE || val == TRUE, "wrong value %u\n", val );
+    ret = CloseHandle( handle );
+    ok( ret, "CloseHandle failed err %u\n", GetLastError() );
+
+    handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
+    val = ~0;
+    ret = pQueryMemoryResourceNotification( handle, &val );
+    ok( ret, "QueryMemoryResourceNotification failed err %u\n", GetLastError() );
+    ok( val == FALSE || val == TRUE, "wrong value %u\n", val );
+    CloseHandle( handle );
 }
 
 static void test_semaphore(void)
@@ -1074,6 +1131,8 @@ START_TEST(sync)
     pDeleteTimerQueueEx = (void*)GetProcAddress(hdll, "DeleteTimerQueueEx");
     pDeleteTimerQueueTimer = (void*)GetProcAddress(hdll, "DeleteTimerQueueTimer");
     pOpenWaitableTimerA = (void*)GetProcAddress(hdll, "OpenWaitableTimerA");
+    pCreateMemoryResourceNotification = (void *)GetProcAddress(hdll, "CreateMemoryResourceNotification");
+    pQueryMemoryResourceNotification = (void *)GetProcAddress(hdll, "QueryMemoryResourceNotification");
 
     test_signalandwait();
     test_mutex();
index f4a0f14..1d02782 100644 (file)
@@ -44,6 +44,12 @@ static void test_query_dos_deviceA(void)
     DWORD ret, ret2, buflen=32768;
     BOOL found = FALSE;
 
+    /* callers must guess the buffer size */
+    SetLastError(0xdeadbeef);
+    ret = QueryDosDeviceA( NULL, NULL, 0 );
+    ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+       "QueryDosDeviceA(no buffer): returned %u, le=%u\n", ret, GetLastError());
+
     buffer = HeapAlloc( GetProcessHeap(), 0, buflen );
     SetLastError(0xdeadbeef);
     ret = QueryDosDeviceA( NULL, buffer, buflen );