Sync to trunk (r44789)
[reactos.git] / rostests / winetests / kernel32 / path.c
index dfe889f..6acb740 100755 (executable)
@@ -952,14 +952,133 @@ static void test_GetTempPath(void)
     SetEnvironmentVariableA("TMP", save_TMP);
 }
 
+static void test_GetLongPathNameA(void)
+{
+    DWORD length, explength, hostsize;
+    char tempfile[MAX_PATH];
+    char longpath[MAX_PATH];
+    char unc_prefix[MAX_PATH];
+    char unc_short[MAX_PATH], unc_long[MAX_PATH];
+    char temppath[MAX_PATH], temppath2[MAX_PATH];
+    HANDLE file;
+
+    if (!pGetLongPathNameA)
+        return;
+
+    GetTempPathA(MAX_PATH, tempfile);
+    lstrcatA(tempfile, "longfilename.longext");
+
+    file = CreateFileA(tempfile, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+    CloseHandle(file);
+
+    /* Test a normal path with a small buffer size */
+    memset(temppath, 0, MAX_PATH);
+    length = pGetLongPathNameA(tempfile, temppath, 4);
+    /* We have a failure so length should be the minumum plus the terminating '0'  */
+    ok(length >= lstrlen(tempfile) + 1, "Wrong length\n");
+    ok(temppath[0] == 0, "Buffer should not have been touched\n");
+
+    /* Some UNC syntax tests */
+
+    memset(temppath, 0, MAX_PATH);
+    memset(temppath2, 0, MAX_PATH);
+    lstrcpyA(temppath2, "\\\\?\\");
+    lstrcatA(temppath2, tempfile);
+    explength = length + 4;
+
+    SetLastError(0xdeadbeef);
+    length = pGetLongPathNameA(temppath2, NULL, 0);
+    if (length == 0 && GetLastError() == ERROR_BAD_NET_NAME)
+    {
+        win_skip("UNC syntax tests don't work on Win98/WinMe\n");
+        DeleteFileA(tempfile);
+        return;
+    }
+    ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
+
+    length = pGetLongPathNameA(temppath2, NULL, MAX_PATH);
+    ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
+
+    length = pGetLongPathNameA(temppath2, temppath, 4);
+    ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
+    ok(temppath[0] == 0, "Buffer should not have been touched\n");
+
+    /* Now an UNC path with the computername */
+    lstrcpyA(unc_prefix, "\\\\");
+    hostsize = sizeof(unc_prefix) - 2;
+    GetComputerName(unc_prefix + 2, &hostsize);
+    lstrcatA(unc_prefix, "\\");
+
+    /* Create a short syntax for the whole unc path */
+    memset(unc_short, 0, MAX_PATH);
+    GetShortPathNameA(tempfile, temppath, MAX_PATH);
+    lstrcpyA(unc_short, unc_prefix);
+    unc_short[lstrlenA(unc_short)] = temppath[0];
+    lstrcatA(unc_short, "$\\");
+    lstrcatA(unc_short, strchr(temppath, '\\') + 1);
+
+    /* Create a long syntax for reference */
+    memset(longpath, 0, MAX_PATH);
+    pGetLongPathNameA(tempfile, temppath, MAX_PATH);
+    lstrcpyA(longpath, unc_prefix);
+    longpath[lstrlenA(longpath)] = temppath[0];
+    lstrcatA(longpath, "$\\");
+    lstrcatA(longpath, strchr(temppath, '\\') + 1);
+
+    /* NULL test */
+    SetLastError(0xdeadbeef);
+    length = pGetLongPathNameA(unc_short, NULL, 0);
+    if (length == 0 && GetLastError() == ERROR_BAD_NETPATH)
+    {
+        /* Seen on Window XP Home */
+        win_skip("UNC with computername is not supported\n");
+        DeleteFileA(tempfile);
+        return;
+    }
+    explength = lstrlenA(longpath) + 1;
+    todo_wine
+    ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
+
+    length = pGetLongPathNameA(unc_short, NULL, MAX_PATH);
+    todo_wine
+    ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
+
+    memset(unc_long, 0, MAX_PATH);
+    length = pGetLongPathNameA(unc_short, unc_long, lstrlenA(unc_short));
+    /* length will include terminating '0' on failure */
+    todo_wine
+    ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
+    ok(unc_long[0] == 0, "Buffer should not have been touched\n");
+
+    memset(unc_long, 0, MAX_PATH);
+    length = pGetLongPathNameA(unc_short, unc_long, length);
+    /* length doesn't include terminating '0' on success */
+    explength--;
+    todo_wine
+    {
+    ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
+    ok(!lstrcmpiA(unc_long, longpath), "Expected (%s), got (%s)\n", longpath, unc_long);
+    }
+
+    DeleteFileA(tempfile);
+}
+
 static void test_GetLongPathNameW(void)
 {
-    DWORD length; 
+    DWORD length, expanded;
+    BOOL ret;
+    HANDLE file;
     WCHAR empty[MAX_PATH];
+    WCHAR tempdir[MAX_PATH], name[200];
+    WCHAR dirpath[4 + MAX_PATH + 200]; /* To ease removal */
+    WCHAR shortpath[4 + MAX_PATH + 200 + 1 + 200];
+    static const WCHAR prefix[] = { '\\','\\','?','\\', 0};
+    static const WCHAR backslash[] = { '\\', 0};
+    static const WCHAR letterX[] = { 'X', 0};
+
+    if (!pGetLongPathNameW)
+        return;
 
-    /* Not present in all windows versions */
-    if(pGetLongPathNameW) 
-    {
     SetLastError(0xdeadbeef); 
     length = pGetLongPathNameW(NULL,NULL,0);
     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
@@ -975,7 +1094,73 @@ static void test_GetLongPathNameW(void)
     length = pGetLongPathNameW(empty,NULL,0);
     ok(0==length,"GetLongPathNameW returned %d but expected 0\n",length);
     ok(GetLastError()==ERROR_PATH_NOT_FOUND,"GetLastError returned %d but expected ERROR_PATH_NOT_FOUND\n",GetLastError());
+
+    /* Create a long path name. The path needs to exist for these tests to
+     * succeed so we need the "\\?\" prefix when creating directories and
+     * files.
+     */
+    name[0] = 0;
+    while (lstrlenW(name) < (sizeof(name)/sizeof(WCHAR) - 1))
+        lstrcatW(name, letterX);
+
+    GetTempPathW(MAX_PATH, tempdir);
+
+    lstrcpyW(shortpath, prefix);
+    lstrcatW(shortpath, tempdir);
+    lstrcatW(shortpath, name);
+    lstrcpyW(dirpath, shortpath);
+    ret = CreateDirectoryW(shortpath, NULL);
+    ok(ret, "Could not create the temporary directory : %d\n", GetLastError());
+    lstrcatW(shortpath, backslash);
+    lstrcatW(shortpath, name);
+
+    /* Path does not exist yet and we know it overruns MAX_PATH */
+
+    /* No prefix */
+    SetLastError(0xdeadbeef);
+    length = pGetLongPathNameW(shortpath + 4, NULL, 0);
+    ok(length == 0, "Expected 0, got %d\n", length);
+    todo_wine
+    ok(GetLastError() == ERROR_PATH_NOT_FOUND,
+       "Expected ERROR_PATH_NOT_FOUND, got %d\n", GetLastError());
+    /* With prefix */
+    SetLastError(0xdeadbeef);
+    length = pGetLongPathNameW(shortpath, NULL, 0);
+    todo_wine
+    {
+    ok(length == 0, "Expected 0, got %d\n", length);
+    ok(GetLastError() == ERROR_FILE_NOT_FOUND,
+       "Expected ERROR_PATH_NOT_FOUND, got %d\n", GetLastError());
     }
+
+    file = CreateFileW(shortpath, GENERIC_READ|GENERIC_WRITE, 0, NULL,
+                       CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+    ok(file != INVALID_HANDLE_VALUE,
+       "Could not create the temporary file : %d.\n", GetLastError());
+    CloseHandle(file);
+
+    /* Path exists */
+
+    /* No prefix */
+    SetLastError(0xdeadbeef);
+    length = pGetLongPathNameW(shortpath + 4, NULL, 0);
+    todo_wine
+    {
+    ok(length == 0, "Expected 0, got %d\n", length);
+    ok(GetLastError() == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %d\n", GetLastError());
+    }
+    /* With prefix */
+    expanded = 4 + (pGetLongPathNameW(tempdir, NULL, 0) - 1) + lstrlenW(name) + 1 + lstrlenW(name) + 1;
+    SetLastError(0xdeadbeef);
+    length = pGetLongPathNameW(shortpath, NULL, 0);
+    ok(length == expanded, "Expected %d, got %d\n", expanded, length);
+
+    /* NULL buffer with length crashes on Windows */
+    if (0)
+    length = pGetLongPathNameW(shortpath, NULL, 20);
+
+    ok(DeleteFileW(shortpath), "Could not delete temporary file\n");
+    ok(RemoveDirectoryW(dirpath), "Could not delete temporary directory\n");
 }
 
 static void test_GetShortPathNameW(void)
@@ -1273,11 +1458,18 @@ START_TEST(path)
         (void*)GetProcAddress( GetModuleHandleA("kernel32.dll"),
                                "NeedCurrentDirectoryForExePathW" );
 
+    /* Report only once */
+    if (!pGetLongPathNameA)
+        win_skip("GetLongPathNameA is not available\n");
+    if (!pGetLongPathNameW)
+        win_skip("GetLongPathNameW is not available\n");
+
     test_InitPathA(curdir, &curDrive, &otherDrive);
     test_CurrentDirectoryA(origdir,curdir);
     test_PathNameA(curdir, curDrive, otherDrive);
     test_CleanupPathA(origdir,curdir);
     test_GetTempPath();
+    test_GetLongPathNameA();
     test_GetLongPathNameW();
     test_GetShortPathNameW();
     test_GetSystemDirectory();