/* Unit test suite for Path functions * * Copyright 2002 Matthew Mastracci * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include #include #include #include "wine/test.h" #include "windef.h" #include "winbase.h" #include "winreg.h" #include "shlwapi.h" #include "wininet.h" static HMODULE hShlwapi; static HRESULT (WINAPI *pPathIsValidCharA)(char,DWORD); static HRESULT (WINAPI *pPathIsValidCharW)(WCHAR,DWORD); static LPWSTR (WINAPI *pPathCombineW)(LPWSTR, LPCWSTR, LPCWSTR); /* ################ */ struct { const char *url; const char *path; DWORD ret; } TEST_PATHFROMURL[] = { {"file:///c:/foo/ba%5Cr", "c:\\foo\\ba\\r", S_OK}, {"file:///c:/foo/../ba%5Cr", "c:\\foo\\..\\ba\\r", S_OK}, {"file:///host/c:/foo/bar", "\\host\\c:\\foo\\bar", S_OK}, {"file://host/c:/foo/bar", "\\\\hostc:\\foo\\bar", S_OK}, {"file://host/c:/foo/bar", "\\\\hostc:\\foo\\bar", S_OK}, {"file:\\\\host\\c:\\foo\\bar", "\\\\hostc:\\foo\\bar", S_OK}, {"file:\\\\host\\ca\\foo\\bar", "\\\\host\\ca\\foo\\bar", S_OK}, {"file:\\\\host\\c|\\foo\\bar", "\\\\hostc|\\foo\\bar", S_OK}, {"file:\\%5Chost\\c:\\foo\\bar", "\\\\host\\c:\\foo\\bar", S_OK}, {"file:\\\\host\\cx:\\foo\\bar", "\\\\host\\cx:\\foo\\bar", S_OK}, {"file://c:/foo/bar", "c:\\foo\\bar", S_OK}, {"file://c:/d:/foo/bar", "c:\\d:\\foo\\bar", S_OK}, {"file://c|/d|/foo/bar", "c:\\d|\\foo\\bar", S_OK}, {"file://host/foo/bar", "\\\\host\\foo\\bar", S_OK}, {"file:/foo/bar", "\\foo\\bar", S_OK}, {"file:/foo/bar/", "\\foo\\bar\\", S_OK}, {"file:foo/bar", "foo\\bar", S_OK}, {"file:c:/foo/bar", "c:\\foo\\bar", S_OK}, {"file:c|/foo/bar", "c:\\foo\\bar", S_OK}, {"file:cx|/foo/bar", "cx|\\foo\\bar", S_OK}, {"file:////c:/foo/bar", "c:\\foo\\bar", S_OK}, /* {"file:////c:/foo/foo%20bar", "c:\\foo\\foo%20bar", S_OK},*/ {"c:\\foo\\bar", NULL, E_INVALIDARG}, {"foo/bar", NULL, E_INVALIDARG}, {"http://foo/bar", NULL, E_INVALIDARG}, }; static struct { const char *path; BOOL expect; } TEST_PATH_IS_URL[] = { {"http://foo/bar", TRUE}, {"c:\\foo\\bar", FALSE}, {"c:/foo/bar", FALSE}, {"foo://foo/bar", TRUE}, {"foo\\bar", FALSE}, {"foo.bar", FALSE}, {"bogusscheme:", TRUE}, {"http:partial", TRUE}, {"www.winehq.org", FALSE}, /* More examples that the user might enter as the browser start page */ {"winehq.org", FALSE}, {"ftp.winehq.org", FALSE}, {"http://winehq.org", TRUE}, {"http://www.winehq.org", TRUE}, {"https://winehq.org", TRUE}, {"https://www.winehq.org", TRUE}, {"ftp://winehq.org", TRUE}, {"ftp://ftp.winehq.org", TRUE}, {"file://does_not_exist.txt", TRUE}, {"about:blank", TRUE}, {"about:home", TRUE}, {"about:mozilla", TRUE}, /* scheme is case independent */ {"HTTP://www.winehq.org", TRUE}, /* a space at the start is not allowed */ {" http://www.winehq.org", FALSE}, {"", FALSE}, {NULL, FALSE} }; struct { const char *path; const char *result; } TEST_PATH_UNQUOTE_SPACES[] = { { "abcdef", "abcdef" }, { "\"abcdef\"", "abcdef" }, { "\"abcdef", "\"abcdef" }, { "abcdef\"", "abcdef\"" }, { "\"\"abcdef\"\"", "\"abcdef\"" }, { "abc\"def", "abc\"def" }, { "\"abc\"def", "\"abc\"def" }, { "\"abc\"def\"", "abc\"def" }, { "\'abcdef\'", "\'abcdef\'" }, { "\"\"", "" }, { "\"", "" } }; /* ################ */ static LPWSTR GetWideString(const char* szString) { LPWSTR wszString = HeapAlloc(GetProcessHeap(), 0, (2*INTERNET_MAX_URL_LENGTH) * sizeof(WCHAR)); MultiByteToWideChar(0, 0, szString, -1, wszString, INTERNET_MAX_URL_LENGTH); return wszString; } static void FreeWideString(LPWSTR wszString) { HeapFree(GetProcessHeap(), 0, wszString); } static LPSTR strdupA(LPCSTR p) { LPSTR ret; DWORD len = (strlen(p) + 1); ret = HeapAlloc(GetProcessHeap(), 0, len); memcpy(ret, p, len); return ret; } /* ################ */ static void test_PathSearchAndQualify(void) { WCHAR path1[] = {'c',':','\\','f','o','o',0}; WCHAR expect1[] = {'c',':','\\','f','o','o',0}; WCHAR path2[] = {'c',':','f','o','o',0}; WCHAR c_drive[] = {'c',':',0}; WCHAR foo[] = {'f','o','o',0}; WCHAR path3[] = {'\\','f','o','o',0}; WCHAR winini[] = {'w','i','n','.','i','n','i',0}; WCHAR out[MAX_PATH]; WCHAR cur_dir[MAX_PATH]; WCHAR dot[] = {'.',0}; /* c:\foo */ ok(PathSearchAndQualifyW(path1, out, MAX_PATH) != 0, "PathSearchAndQualify rets 0\n"); ok(!lstrcmpiW(out, expect1), "strings don't match\n"); /* c:foo */ ok(PathSearchAndQualifyW(path2, out, MAX_PATH) != 0, "PathSearchAndQualify rets 0\n"); GetFullPathNameW(c_drive, MAX_PATH, cur_dir, NULL); PathAddBackslashW(cur_dir); lstrcatW(cur_dir, foo); ok(!lstrcmpiW(out, cur_dir), "strings don't match\n"); /* foo */ ok(PathSearchAndQualifyW(foo, out, MAX_PATH) != 0, "PathSearchAndQualify rets 0\n"); GetFullPathNameW(dot, MAX_PATH, cur_dir, NULL); PathAddBackslashW(cur_dir); lstrcatW(cur_dir, foo); ok(!lstrcmpiW(out, cur_dir), "strings don't match\n"); /* \foo */ ok(PathSearchAndQualifyW(path3, out, MAX_PATH) != 0, "PathSearchAndQualify rets 0\n"); GetFullPathNameW(dot, MAX_PATH, cur_dir, NULL); lstrcpyW(cur_dir + 2, path3); ok(!lstrcmpiW(out, cur_dir), "strings don't match\n"); /* win.ini */ ok(PathSearchAndQualifyW(winini, out, MAX_PATH) != 0, "PathSearchAndQualify rets 0\n"); if(!SearchPathW(NULL, winini, NULL, MAX_PATH, cur_dir, NULL)) GetFullPathNameW(winini, MAX_PATH, cur_dir, NULL); ok(!lstrcmpiW(out, cur_dir), "strings don't match\n"); } static void test_PathCreateFromUrl(void) { size_t i; char ret_path[INTERNET_MAX_URL_LENGTH]; DWORD len, ret; WCHAR ret_pathW[INTERNET_MAX_URL_LENGTH]; WCHAR *pathW, *urlW; static const char url[] = "http://www.winehq.org"; /* Check ret_path = NULL */ len = sizeof(url); ret = PathCreateFromUrlA(url, NULL, &len, 0); ok ( ret == E_INVALIDARG, "got 0x%08x expected E_INVALIDARG\n", ret); for(i = 0; i < sizeof(TEST_PATHFROMURL) / sizeof(TEST_PATHFROMURL[0]); i++) { len = INTERNET_MAX_URL_LENGTH; ret = PathCreateFromUrlA(TEST_PATHFROMURL[i].url, ret_path, &len, 0); ok(ret == TEST_PATHFROMURL[i].ret, "ret %08x from url %s\n", ret, TEST_PATHFROMURL[i].url); if(TEST_PATHFROMURL[i].path) { ok(!lstrcmpi(ret_path, TEST_PATHFROMURL[i].path), "got %s expected %s from url %s\n", ret_path, TEST_PATHFROMURL[i].path, TEST_PATHFROMURL[i].url); ok(len == strlen(ret_path), "ret len %d from url %s\n", len, TEST_PATHFROMURL[i].url); } len = INTERNET_MAX_URL_LENGTH; pathW = GetWideString(TEST_PATHFROMURL[i].path); urlW = GetWideString(TEST_PATHFROMURL[i].url); ret = PathCreateFromUrlW(urlW, ret_pathW, &len, 0); WideCharToMultiByte(CP_ACP, 0, ret_pathW, -1, ret_path, sizeof(ret_path),0,0); ok(ret == TEST_PATHFROMURL[i].ret, "ret %08x from url L\"%s\"\n", ret, TEST_PATHFROMURL[i].url); if(TEST_PATHFROMURL[i].path) { ok(!lstrcmpiW(ret_pathW, pathW), "got %s expected %s from url L\"%s\"\n", ret_path, TEST_PATHFROMURL[i].path, TEST_PATHFROMURL[i].url); ok(len == lstrlenW(ret_pathW), "ret len %d from url L\"%s\"\n", len, TEST_PATHFROMURL[i].url); } FreeWideString(urlW); FreeWideString(pathW); } } static void test_PathIsUrl(void) { size_t i; BOOL ret; for(i = 0; i < sizeof(TEST_PATH_IS_URL)/sizeof(TEST_PATH_IS_URL[0]); i++) { ret = PathIsURLA(TEST_PATH_IS_URL[i].path); ok(ret == TEST_PATH_IS_URL[i].expect, "returned %d from path %s, expected %d\n", ret, TEST_PATH_IS_URL[i].path, TEST_PATH_IS_URL[i].expect); } } static const DWORD SHELL_charclass[] = { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000080, 0x00000100, 0x00000200, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000002, 0x00000100, 0x00000040, 0x00000100, 0x00000004, 0x00000000, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000010, 0x00000020, 0x00000000, 0x00000100, 0x00000000, 0x00000001, 0x00000100, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000100, 0x00000008, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000100, 0x00000000, 0x00000100, 0x00000100 }; static void test_PathIsValidCharA(void) { BOOL ret; unsigned int c; for (c = 0; c < 0x7f; c++) { ret = pPathIsValidCharA( c, ~0U ); ok ( ret || !SHELL_charclass[c], "PathIsValidCharA failed: 0x%02x got 0x%08x\n", c, ret ); } for (c = 0x7f; c <= 0xff; c++) { ret = pPathIsValidCharA( c, ~0U ); ok ( ret, "PathIsValidCharA failed: 0x%02x got 0x%08x\n", c, ret ); } } static void test_PathIsValidCharW(void) { BOOL ret; unsigned int c; for (c = 0; c < 0x7f; c++) { ret = pPathIsValidCharW( c, ~0U ); ok ( ret || !SHELL_charclass[c], "PathIsValidCharW failed: 0x%02x got 0x%08x\n", c, ret ); } for (c = 0x007f; c <= 0xffff; c++) { ret = pPathIsValidCharW( c, ~0U ); ok ( ret, "PathIsValidCharW failed: 0x%02x got 0x%08x\n", c, ret ); } } static void test_PathMakePretty(void) { char buff[MAX_PATH]; ok (PathMakePrettyA(NULL) == FALSE, "PathMakePretty: NULL path succeeded\n"); buff[0] = '\0'; ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Empty path failed\n"); strcpy(buff, "C:\\A LONG FILE NAME WITH \\SPACES.TXT"); ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Long UC name failed\n"); ok (strcmp(buff, "C:\\a long file name with \\spaces.txt") == 0, "PathMakePretty: Long UC name not changed\n"); strcpy(buff, "C:\\A LONG FILE NAME WITH \\MixedCase.TXT"); ok (PathMakePrettyA(buff) == FALSE, "PathMakePretty: Long MC name succeeded\n"); ok (strcmp(buff, "C:\\A LONG FILE NAME WITH \\MixedCase.TXT") == 0, "PathMakePretty: Failed but modified path\n"); strcpy(buff, "TEST"); ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Short name failed\n"); ok (strcmp(buff, "Test") == 0, "PathMakePretty: 1st char lowercased %s\n", buff); } static void test_PathMatchSpec(void) { static const char file[] = "c:\\foo\\bar\\filename.ext"; static const char spec1[] = ".ext"; static const char spec2[] = "*.ext"; static const char spec3[] = "*.ext "; static const char spec4[] = " *.ext"; static const char spec5[] = "* .ext"; static const char spec6[] = "*. ext"; static const char spec7[] = "* . ext"; static const char spec8[] = "*.e?t"; static const char spec9[] = "filename.ext"; static const char spec10[] = "*bar\\filename.ext"; static const char spec11[] = " foo; *.ext"; static const char spec12[] = "*.ext;*.bar"; static const char spec13[] = "*bar*"; ok (PathMatchSpecA(file, spec1) == FALSE, "PathMatchSpec: Spec1 failed\n"); ok (PathMatchSpecA(file, spec2) == TRUE, "PathMatchSpec: Spec2 failed\n"); ok (PathMatchSpecA(file, spec3) == FALSE, "PathMatchSpec: Spec3 failed\n"); ok (PathMatchSpecA(file, spec4) == TRUE, "PathMatchSpec: Spec4 failed\n"); todo_wine ok (PathMatchSpecA(file, spec5) == TRUE, "PathMatchSpec: Spec5 failed\n"); todo_wine ok (PathMatchSpecA(file, spec6) == TRUE, "PathMatchSpec: Spec6 failed\n"); ok (PathMatchSpecA(file, spec7) == FALSE, "PathMatchSpec: Spec7 failed\n"); ok (PathMatchSpecA(file, spec8) == TRUE, "PathMatchSpec: Spec8 failed\n"); ok (PathMatchSpecA(file, spec9) == FALSE, "PathMatchSpec: Spec9 failed\n"); ok (PathMatchSpecA(file, spec10) == TRUE, "PathMatchSpec: Spec10 failed\n"); ok (PathMatchSpecA(file, spec11) == TRUE, "PathMatchSpec: Spec11 failed\n"); ok (PathMatchSpecA(file, spec12) == TRUE, "PathMatchSpec: Spec12 failed\n"); ok (PathMatchSpecA(file, spec13) == TRUE, "PathMatchSpec: Spec13 failed\n"); } static void test_PathCombineW(void) { LPWSTR wszString, wszString2; WCHAR wbuf[MAX_PATH+1], wstr1[MAX_PATH] = {'C',':','\\',0}, wstr2[MAX_PATH]; static const WCHAR expout[] = {'C',':','\\','A','A',0}; int i; wszString2 = HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR)); /* NULL test */ wszString = pPathCombineW(NULL, NULL, NULL); ok (wszString == NULL, "Expected a NULL return\n"); /* Some NULL */ wszString2[0] = 'a'; wszString = pPathCombineW(wszString2, NULL, NULL); ok (wszString == NULL || broken(wszString[0] == 'a'), /* Win95 and some W2K */ "Expected a NULL return\n"); ok (wszString2[0] == 0 || broken(wszString2[0] == 'a'), /* Win95 and some W2K */ "Destination string not empty\n"); HeapFree(GetProcessHeap(), 0, wszString2); /* overflow test */ wstr2[0] = wstr2[1] = wstr2[2] = 'A'; for (i=3; i