[SHLWAPI_WINETEST]: Sync to Wine 1.5.13.

CORE-6415

svn path=/trunk/; revision=57428
This commit is contained in:
Amine Khaldi 2012-09-29 13:14:50 +00:00
parent 25d97f0bd9
commit d28c6f3c65
10 changed files with 1630 additions and 248 deletions

View file

@ -1,7 +1,5 @@
add_definitions(
-D__ROS_LONG64__
-D_DLL -D__USE_CRTIMP)
add_definitions(-D__ROS_LONG64__)
remove_definitions(-DWINVER=0x502 -D_WIN32_IE=0x600 -D_WIN32_WINNT=0x502)
@ -15,9 +13,9 @@ list(APPEND SOURCE
path.c
shreg.c
string.c
thread.c
url.c
testlist.c
thread.c)
testlist.c)
add_executable(shlwapi_winetest ${SOURCE})
target_link_libraries(shlwapi_winetest wine uuid)

View file

@ -212,10 +212,16 @@ static HRESULT (WINAPI *pSHLWAPI_213)(_IDummyStream*);
static HRESULT (WINAPI *pSHLWAPI_214)(_IDummyStream*,ULARGE_INTEGER*);
static void InitFunctionPtrs(void)
static BOOL InitFunctionPtrs(void)
{
SHLWAPI_hshlwapi = GetModuleHandleA("shlwapi.dll");
/* SHCreateStreamOnFileEx was introduced in shlwapi v6.0 */
if(!GetProcAddress(SHLWAPI_hshlwapi, "SHCreateStreamOnFileEx")){
win_skip("Too old shlwapi version\n");
return FALSE;
}
pSHLWAPI_17 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)17);
ok(pSHLWAPI_17 != 0, "No Ordinal 17\n");
pSHLWAPI_18 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)18);
@ -238,6 +244,8 @@ static void InitFunctionPtrs(void)
ok(pSHLWAPI_213 != 0, "No Ordinal 213\n");
pSHLWAPI_214 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)214);
ok(pSHLWAPI_214 != 0, "No Ordinal 214\n");
return TRUE;
}
static void InitDummyStream(_IDummyStream* iface)
@ -363,26 +371,22 @@ static void test_CList(void)
inserted = (LPSHLWAPI_CLIST)buff;
inserted->ulSize = sizeof(SHLWAPI_CLIST) -1;
inserted->ulId = 33;
hRet = pSHLWAPI_20(&list, inserted);
/* The call succeeds but the item is not inserted, except on some early
* versions which return failure. Wine behaves like later versions.
*/
if (0)
{
ok(hRet == S_OK, "failed bad element size\n");
}
pSHLWAPI_20(&list, inserted);
inserted = pSHLWAPI_22(list, 33);
ok(inserted == NULL, "inserted bad element size\n");
inserted = (LPSHLWAPI_CLIST)buff;
inserted->ulSize = 44;
inserted->ulId = ~0U;
hRet = pSHLWAPI_20(&list, inserted);
/* See comment above, some early versions fail this call */
if (0)
{
ok(hRet == S_OK, "failed adding a container\n");
}
pSHLWAPI_20(&list, inserted);
item = SHLWAPI_CLIST_items;
/* Look for nonexistent item in populated list */
@ -623,7 +627,8 @@ static void test_SHLWAPI_214(void)
START_TEST(clist)
{
InitFunctionPtrs();
if(!InitFunctionPtrs())
return;
test_CList();

View file

@ -40,7 +40,7 @@ static BOOL (WINAPI *pSHLWAPI_269)(LPCSTR, CLSID *) = 0;
static DWORD (WINAPI *pSHLWAPI_23)(REFGUID, LPSTR, INT) = 0;
/* GUIDs to test */
const GUID * TEST_guids[] = {
static const GUID * TEST_guids[] = {
&CLSID_ShellDesktop,
&CLSID_ShellLink,
&CATID_BrowsableShellExt,
@ -96,7 +96,7 @@ const GUID * TEST_guids[] = {
NULL
};
DEFINE_GUID(IID_Endianess, 0x01020304, 0x0506, 0x0708, 0x09, 0x0A, 0x0B,
DEFINE_GUID(IID_Endianness, 0x01020304, 0x0506, 0x0708, 0x09, 0x0A, 0x0B,
0x0C, 0x0D, 0x0E, 0x0F, 0x0A);
static void test_ClassIDs(void)
@ -128,26 +128,26 @@ static void test_ClassIDs(void)
i++;
}
/* Test endianess */
dwLen = pSHLWAPI_23(&IID_Endianess, szBuff, 256);
ok(dwLen == (is_vista ? S_OK : 39), "wrong size %u for IID_Endianess\n", dwLen);
/* Test endianness */
dwLen = pSHLWAPI_23(&IID_Endianness, szBuff, 256);
ok(dwLen == (is_vista ? S_OK : 39), "wrong size %u for IID_Endianness\n", dwLen);
ok(!strcmp(szBuff, "{01020304-0506-0708-090A-0B0C0D0E0F0A}"),
"Endianess Broken, got '%s'\n", szBuff);
"Endianness Broken, got '%s'\n", szBuff);
/* test lengths */
szBuff[0] = ':';
dwLen = pSHLWAPI_23(&IID_Endianess, szBuff, 0);
dwLen = pSHLWAPI_23(&IID_Endianness, szBuff, 0);
ok(dwLen == (is_vista ? E_FAIL : 0), "accepted bad length\n");
ok(szBuff[0] == ':', "wrote to buffer with no length\n");
szBuff[0] = ':';
dwLen = pSHLWAPI_23(&IID_Endianess, szBuff, 38);
dwLen = pSHLWAPI_23(&IID_Endianness, szBuff, 38);
ok(dwLen == (is_vista ? E_FAIL : 0), "accepted bad length\n");
ok(szBuff[0] == ':', "wrote to buffer with no length\n");
szBuff[0] = ':';
dwLen = pSHLWAPI_23(&IID_Endianess, szBuff, 39);
dwLen = pSHLWAPI_23(&IID_Endianness, szBuff, 39);
ok(dwLen == (is_vista ? S_OK : 39), "rejected ok length\n");
ok(szBuff[0] == '{', "Didn't write to buffer with ok length\n");
@ -156,7 +156,7 @@ static void test_ClassIDs(void)
bRet = pSHLWAPI_269(szBuff, &guid);
ok(bRet == FALSE, "accepted invalid string\n");
dwLen = pSHLWAPI_23(&IID_Endianess, szBuff, 39);
dwLen = pSHLWAPI_23(&IID_Endianness, szBuff, 39);
ok(dwLen == (is_vista ? S_OK : 39), "rejected ok length\n");
ok(szBuff[0] == '{', "Didn't write to buffer with ok length\n");
}
@ -185,6 +185,13 @@ static void test_CLSIDFromProgIDWrap(void)
START_TEST(clsid)
{
hShlwapi = GetModuleHandleA("shlwapi.dll");
/* SHCreateStreamOnFileEx was introduced in shlwapi v6.0 */
if(!GetProcAddress(hShlwapi, "SHCreateStreamOnFileEx")){
win_skip("Too old shlwapi version\n");
return;
}
pSHLWAPI_269 = (void*)GetProcAddress(hShlwapi, (LPSTR)269);
pSHLWAPI_23 = (void*)GetProcAddress(hShlwapi, (LPSTR)23);

View file

@ -281,12 +281,15 @@ static void test_SHCreateStreamOnFileA(DWORD mode, DWORD stgm)
ok(stream != NULL, "SHCreateStreamOnFileA: expected a valid IStream object, got NULL\n");
if (stream) {
BOOL delret;
test_IStream_invalid_operations(stream, mode);
refcount = IStream_Release(stream);
ok(refcount == 0, "SHCreateStreamOnFileA: expected 0, got %d\n", refcount);
ok(DeleteFileA(test_file), "SHCreateStreamOnFileA: could not delete file '%s', got error %d\n", test_file, GetLastError());
delret = DeleteFileA(test_file);
ok(delret, "SHCreateStreamOnFileA: could not delete file '%s', got error %d\n",
test_file, GetLastError());
}
}
@ -388,14 +391,15 @@ static void test_SHCreateStreamOnFileW(DWORD mode, DWORD stgm)
ok(stream != NULL, "SHCreateStreamOnFileW: expected a valid IStream object, got NULL\n");
if (stream) {
BOOL delret;
test_IStream_invalid_operations(stream, mode);
refcount = IStream_Release(stream);
ok(refcount == 0, "SHCreateStreamOnFileW: expected 0, got %d\n", refcount);
ok(DeleteFileA(test_fileA),
"SHCreateStreamOnFileW: could not delete the test file, got error %d\n",
GetLastError());
delret = DeleteFileA(test_fileA);
ok(delret, "SHCreateStreamOnFileW: could not delete the test file, got error %d\n",
GetLastError());
}
}
@ -409,6 +413,7 @@ static void test_SHCreateStreamOnFileEx(DWORD mode, DWORD stgm)
WCHAR test_file[MAX_PATH];
CHAR test_fileA[MAX_PATH];
static const CHAR testEx_txt[] = "\\testEx.txt";
BOOL delret;
trace("SHCreateStreamOnFileEx: testing mode %d, STGM flags %08x\n", mode, stgm);
@ -489,9 +494,9 @@ static void test_SHCreateStreamOnFileEx(DWORD mode, DWORD stgm)
refcount = IStream_Release(stream);
ok(refcount == 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount);
ok(DeleteFileA(test_fileA),
"SHCreateStreamOnFileEx: could not delete the test file, got error %d\n",
GetLastError());
delret = DeleteFileA(test_fileA);
ok(delret, "SHCreateStreamOnFileEx: could not delete the test file, got error %d\n",
GetLastError());
}
stream = NULL;
@ -510,9 +515,9 @@ static void test_SHCreateStreamOnFileEx(DWORD mode, DWORD stgm)
refcount = IStream_Release(stream);
ok(refcount == 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount);
ok(DeleteFileA(test_fileA),
"SHCreateStreamOnFileEx: could not delete the test file, got error %d\n",
GetLastError());
delret = DeleteFileA(test_fileA);
ok(delret, "SHCreateStreamOnFileEx: could not delete the test file, got error %d\n",
GetLastError());
}
stream = NULL;
@ -577,9 +582,9 @@ static void test_SHCreateStreamOnFileEx(DWORD mode, DWORD stgm)
ok(refcount == 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount);
}
ok(DeleteFileA(test_fileA),
"SHCreateStreamOnFileEx: could not delete the test file, got error %d\n",
GetLastError());
delret = DeleteFileA(test_fileA);
ok(delret, "SHCreateStreamOnFileEx: could not delete the test file, got error %d\n",
GetLastError());
}

File diff suppressed because it is too large Load diff

View file

@ -17,7 +17,6 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
@ -37,7 +36,7 @@ static BOOL (WINAPI *pPathAppendA)(LPSTR, LPCSTR);
/* ################ */
struct {
static const struct {
const char *url;
const char *path;
DWORD ret;
@ -106,7 +105,7 @@ static struct {
{NULL, FALSE}
};
struct {
static const struct {
const char *path;
const char *result;
} TEST_PATH_UNQUOTE_SPACES[] = {
@ -1362,6 +1361,12 @@ START_TEST(path)
{
HMODULE hShlwapi = GetModuleHandleA("shlwapi.dll");
/* SHCreateStreamOnFileEx was introduced in shlwapi v6.0 */
if(!GetProcAddress(hShlwapi, "SHCreateStreamOnFileEx")){
win_skip("Too old shlwapi version\n");
return;
}
pPathCreateFromUrlA = (void*)GetProcAddress(hShlwapi, "PathCreateFromUrlA");
pPathCreateFromUrlW = (void*)GetProcAddress(hShlwapi, "PathCreateFromUrlW");
pPathCombineW = (void*)GetProcAddress(hShlwapi, "PathCombineW");

View file

@ -17,7 +17,6 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
@ -34,12 +33,11 @@
#define REG_CURRENT_VERSION "Software\\Microsoft\\Windows\\CurrentVersion\\explorer"
static HMODULE hshlwapi;
typedef DWORD (WINAPI *SHCopyKeyA_func)(HKEY,LPCSTR,HKEY,DWORD);
static SHCopyKeyA_func pSHCopyKeyA;
typedef DWORD (WINAPI *SHRegGetPathA_func)(HKEY,LPCSTR,LPCSTR,LPSTR,DWORD);
static SHRegGetPathA_func pSHRegGetPathA;
typedef LSTATUS (WINAPI *SHRegGetValueA_func)(HKEY,LPCSTR,LPCSTR,SRRF,LPDWORD,LPVOID,LPDWORD);
static SHRegGetValueA_func pSHRegGetValueA;
static DWORD (WINAPI *pSHCopyKeyA)(HKEY,LPCSTR,HKEY,DWORD);
static DWORD (WINAPI *pSHRegGetPathA)(HKEY,LPCSTR,LPCSTR,LPSTR,DWORD);
static LSTATUS (WINAPI *pSHRegGetValueA)(HKEY,LPCSTR,LPCSTR,SRRF,LPDWORD,LPVOID,LPDWORD);
static LSTATUS (WINAPI *pSHRegCreateUSKeyW)(LPCWSTR,REGSAM,HUSKEY,PHUSKEY,DWORD);
static char sTestpath1[] = "%LONGSYSTEMVAR%\\subdir1";
static char sTestpath2[] = "%FOO%\\subdir1";
@ -192,7 +190,7 @@ static void test_SHGetRegPath(void)
ok( 0 == strcmp(sExpTestpath1, buf) , "Comparing (%s) with (%s) failed\n", buf, sExpTestpath1);
}
static void test_SHQUeryValueEx(void)
static void test_SHQueryValueEx(void)
{
HKEY hKey;
DWORD dwSize;
@ -445,21 +443,47 @@ static void test_SHDeleteKey(void)
ok( 0, "Could not set up SHDeleteKey test\n");
}
static void test_SHRegCreateUSKeyW(void)
{
static const WCHAR subkeyW[] = {'s','u','b','k','e','y',0};
LONG ret;
if (!pSHRegCreateUSKeyW)
{
win_skip("SHRegCreateUSKeyW not available\n");
return;
}
ret = pSHRegCreateUSKeyW(subkeyW, KEY_ALL_ACCESS, NULL, NULL, SHREGSET_FORCE_HKCU);
ok(ret == ERROR_INVALID_PARAMETER, "got %d\n", ret);
}
START_TEST(shreg)
{
HKEY hkey = create_test_entries();
HKEY hkey = create_test_entries();
if (!hkey) return;
if (!hkey) return;
hshlwapi = GetModuleHandleA("shlwapi.dll");
pSHCopyKeyA=(SHCopyKeyA_func)GetProcAddress(hshlwapi,"SHCopyKeyA");
pSHRegGetPathA=(SHRegGetPathA_func)GetProcAddress(hshlwapi,"SHRegGetPathA");
pSHRegGetValueA=(SHRegGetValueA_func)GetProcAddress(hshlwapi,"SHRegGetValueA");
test_SHGetValue();
test_SHRegGetValue();
test_SHQUeryValueEx();
test_SHGetRegPath();
test_SHCopyKey();
test_SHDeleteKey();
delete_key( hkey, "Software\\Wine", "Test" );
hshlwapi = GetModuleHandleA("shlwapi.dll");
/* SHCreateStreamOnFileEx was introduced in shlwapi v6.0 */
if(!GetProcAddress(hshlwapi, "SHCreateStreamOnFileEx")){
win_skip("Too old shlwapi version\n");
return;
}
pSHCopyKeyA = (void*)GetProcAddress(hshlwapi,"SHCopyKeyA");
pSHRegGetPathA = (void*)GetProcAddress(hshlwapi,"SHRegGetPathA");
pSHRegGetValueA = (void*)GetProcAddress(hshlwapi,"SHRegGetValueA");
pSHRegCreateUSKeyW = (void*)GetProcAddress(hshlwapi, "SHRegCreateUSKeyW");
test_SHGetValue();
test_SHRegGetValue();
test_SHQueryValueEx();
test_SHGetRegPath();
test_SHCopyKey();
test_SHDeleteKey();
test_SHRegCreateUSKeyW();
delete_key( hkey, "Software\\Wine", "Test" );
}

View file

@ -55,12 +55,18 @@ static LPSTR (WINAPI *pStrFormatKBSizeA)(LONGLONG,LPSTR,UINT);
static LPWSTR (WINAPI *pStrFormatKBSizeW)(LONGLONG,LPWSTR,UINT);
static BOOL (WINAPI *pStrIsIntlEqualA)(BOOL,LPCSTR,LPCSTR,int);
static BOOL (WINAPI *pStrIsIntlEqualW)(BOOL,LPCWSTR,LPCWSTR,int);
static HRESULT (WINAPI *pStrRetToBSTR)(STRRET*,void*,BSTR*);
static LPWSTR (WINAPI *pStrPBrkW)(LPCWSTR,LPCWSTR);
static LPSTR (WINAPI *pStrRChrA)(LPCSTR,LPCSTR,WORD);
static HRESULT (WINAPI *pStrRetToBSTR)(STRRET*,LPCITEMIDLIST,BSTR*);
static HRESULT (WINAPI *pStrRetToBufA)(STRRET*,LPCITEMIDLIST,LPSTR,UINT);
static HRESULT (WINAPI *pStrRetToBufW)(STRRET*,LPCITEMIDLIST,LPWSTR,UINT);
static LPWSTR (WINAPI *pStrStrNW)(LPCWSTR,LPCWSTR,UINT);
static LPWSTR (WINAPI *pStrStrNIW)(LPCWSTR,LPCWSTR,UINT);
static INT (WINAPIV *pwnsprintfA)(LPSTR,INT,LPCSTR, ...);
static INT (WINAPIV *pwnsprintfW)(LPWSTR,INT,LPCWSTR, ...);
static LPWSTR (WINAPI *pStrChrNW)(LPWSTR,WCHAR,UINT);
static BOOL (WINAPI *pStrToInt64ExA)(LPCSTR,DWORD,LONGLONG*);
static BOOL (WINAPI *pStrToInt64ExW)(LPCWSTR,DWORD,LONGLONG*);
static int strcmpW(const WCHAR *str1, const WCHAR *str2)
{
@ -73,17 +79,19 @@ typedef struct tagStrToIntResult
{
const char* string;
int str_to_int;
int str_to_int_ex;
int str_to_int_hex;
LONGLONG str_to_int64_ex;
LONGLONG str_to_int64_hex;
} StrToIntResult;
static const StrToIntResult StrToInt_results[] = {
{ "1099", 1099, 1099, 1099 },
{ "4294967319", 23, ((LONGLONG)1 << 32) | 23, ((LONGLONG)1 << 32) | 23 },
{ "+88987", 0, 88987, 88987 },
{ "012", 12, 12, 12 },
{ "-55", -55, -55, -55 },
{ "-0", 0, 0, 0 },
{ "0x44ff", 0, 0, 0x44ff },
{ "0x2bdc546291f4b1", 0, 0, ((LONGLONG)0x2bdc54 << 32) | 0x6291f4b1 },
{ "+0x44f4", 0, 0, 0x44f4 },
{ "-0x44fd", 0, 0, 0x44fd },
{ "+ 88987", 0, 0, 0 },
@ -107,6 +115,8 @@ typedef struct tagStrFormatSizeResult
LONGLONG value;
const char* byte_size_64;
const char* kb_size;
int kb_size_broken;
const char* kb_size2;
} StrFormatSizeResult;
@ -117,19 +127,19 @@ static const StrFormatSizeResult StrFormatSize_results[] = {
{ 10191, "9.95 KB", "10 KB"},
{ 100353, "98.0 KB", "99 KB"},
{ 1022286, "998 KB", "999 KB"},
{ 1046862, "0.99 MB", "1,023 KB"},
{ 1048574619, "999 MB", "1,023,999 KB"},
{ 1073741775, "0.99 GB", "1,048,576 KB"},
{ ((LONGLONG)0x000000f9 << 32) | 0xfffff94e, "999 GB", "1,048,575,999 KB"},
{ ((LONGLONG)0x000000ff << 32) | 0xfffffa9b, "0.99 TB", "1,073,741,823 KB"},
{ ((LONGLONG)0x0003e7ff << 32) | 0xfffffa9b, "999 TB", "1,073,741,823,999 KB"},
{ ((LONGLONG)0x0003ffff << 32) | 0xfffffbe8, "0.99 PB", "1,099,511,627,775 KB"},
{ ((LONGLONG)0x0f9fffff << 32) | 0xfffffd35, "999 PB", "1,099,511,627,776,000 KB"},
{ ((LONGLONG)0x0fffffff << 32) | 0xfffffa9b, "0.99 EB", "1,125,899,906,842,623 KB"},
{ 1046862, "0.99 MB", "1,023 KB", 1, "1023 KB"},
{ 1048574619, "999 MB", "1,023,999 KB", 1, "1023999 KB"},
{ 1073741775, "0.99 GB", "1,048,576 KB", 1, "1048576 KB"},
{ ((LONGLONG)0x000000f9 << 32) | 0xfffff94e, "999 GB", "1,048,575,999 KB", 1, "1048575999 KB"},
{ ((LONGLONG)0x000000ff << 32) | 0xfffffa9b, "0.99 TB", "1,073,741,823 KB", 1, "1073741823 KB"},
{ ((LONGLONG)0x0003e7ff << 32) | 0xfffffa9b, "999 TB", "1,073,741,823,999 KB", 1, "4294967295 KB"},
{ ((LONGLONG)0x0003ffff << 32) | 0xfffffbe8, "0.99 PB", "1,099,511,627,775 KB", 1, "4294967295 KB"},
{ ((LONGLONG)0x0f9fffff << 32) | 0xfffffd35, "999 PB", "1,099,511,627,776,000 KB", 1, "0 KB"},
{ ((LONGLONG)0x0fffffff << 32) | 0xfffffa9b, "0.99 EB", "1,125,899,906,842,623 KB", 1, "4294967295 KB"},
{ 0, NULL, NULL }
};
/* StrFormatByteSize64/StrFormatKBSize results */
/* StrFromTimeIntervalA/StrFromTimeIntervalW results */
typedef struct tagStrFromTimeIntervalResult
{
DWORD ms;
@ -191,6 +201,39 @@ static const StrFromTimeIntervalResult StrFromTimeInterval_results[] = {
{ 0, 0, NULL }
};
/* Returns true if the user interface is in English. Note that this does not
* presume of the formatting of dates, numbers, etc.
*/
static BOOL is_lang_english(void)
{
static HMODULE hkernel32 = NULL;
static LANGID (WINAPI *pGetThreadUILanguage)(void) = NULL;
static LANGID (WINAPI *pGetUserDefaultUILanguage)(void) = NULL;
if (!hkernel32)
{
hkernel32 = GetModuleHandleA("kernel32.dll");
pGetThreadUILanguage = (void*)GetProcAddress(hkernel32, "GetThreadUILanguage");
pGetUserDefaultUILanguage = (void*)GetProcAddress(hkernel32, "GetUserDefaultUILanguage");
}
if (pGetThreadUILanguage)
return PRIMARYLANGID(pGetThreadUILanguage()) == LANG_ENGLISH;
if (pGetUserDefaultUILanguage)
return PRIMARYLANGID(pGetUserDefaultUILanguage()) == LANG_ENGLISH;
return PRIMARYLANGID(GetUserDefaultLangID()) == LANG_ENGLISH;
}
/* Returns true if the dates, numbers, etc. are formatted using English
* conventions.
*/
static BOOL is_locale_english(void)
{
/* Surprisingly GetThreadLocale() is irrelevant here */
return PRIMARYLANGID(GetUserDefaultLangID()) == LANG_ENGLISH;
}
static void test_StrChrA(void)
{
char string[129];
@ -364,16 +407,28 @@ static void test_StrCpyW(void)
WCHAR szSrc[256];
WCHAR szBuff[256];
const StrFormatSizeResult* result = StrFormatSize_results;
LPWSTR lpRes;
while(result->value)
{
MultiByteToWideChar(0,0,result->byte_size_64,-1,szSrc,sizeof(szSrc)/sizeof(WCHAR));
StrCpyW(szBuff, szSrc);
ok(!StrCmpW(szSrc, szBuff), "Copied string %s wrong\n", result->byte_size_64);
lpRes = StrCpyW(szBuff, szSrc);
ok(!StrCmpW(szSrc, szBuff) && lpRes == szBuff, "Copied string %s wrong\n", result->byte_size_64);
result++;
}
/* this test crashes on win2k SP4 */
/*lpRes = StrCpyW(szBuff, NULL);*/
/*ok(lpRes == szBuff, "Wrong return value: got %p expected %p\n", lpRes, szBuff);*/
/* this test crashes on win2k SP4 */
/*lpRes = StrCpyW(NULL, szSrc);*/
/*ok(lpRes == NULL, "Wrong return value: got %p expected NULL\n", lpRes);*/
/* this test crashes on win2k SP4 */
/*lpRes = StrCpyW(NULL, NULL);*/
/*ok(lpRes == NULL, "Wrong return value: got %p expected NULL\n", lpRes);*/
}
static void test_StrChrNW(void)
@ -441,7 +496,7 @@ static void test_StrToIntExA(void)
ok(!bRet || return_val != -1, "No result returned from '%s'\n",
result->string);
if (bRet)
ok(return_val == result->str_to_int_ex, "converted '%s' wrong (%d)\n",
ok(return_val == (int)result->str_to_int64_ex, "converted '%s' wrong (%d)\n",
result->string, return_val);
result++;
}
@ -454,7 +509,7 @@ static void test_StrToIntExA(void)
ok(!bRet || return_val != -1, "No result returned from '%s'\n",
result->string);
if (bRet)
ok(return_val == result->str_to_int_hex, "converted '%s' wrong (%d)\n",
ok(return_val == (int)result->str_to_int64_hex, "converted '%s' wrong (%d)\n",
result->string, return_val);
result++;
}
@ -475,7 +530,7 @@ static void test_StrToIntExW(void)
ok(!bRet || return_val != -1, "No result returned from '%s'\n",
result->string);
if (bRet)
ok(return_val == result->str_to_int_ex, "converted '%s' wrong (%d)\n",
ok(return_val == (int)result->str_to_int64_ex, "converted '%s' wrong (%d)\n",
result->string, return_val);
result++;
}
@ -489,12 +544,91 @@ static void test_StrToIntExW(void)
ok(!bRet || return_val != -1, "No result returned from '%s'\n",
result->string);
if (bRet)
ok(return_val == result->str_to_int_hex, "converted '%s' wrong (%d)\n",
ok(return_val == (int)result->str_to_int64_hex, "converted '%s' wrong (%d)\n",
result->string, return_val);
result++;
}
}
static void test_StrToInt64ExA(void)
{
const StrToIntResult *result = StrToInt_results;
LONGLONG return_val;
BOOL bRet;
if (!pStrToInt64ExA)
{
win_skip("StrToInt64ExA() is not available\n");
return;
}
while (result->string)
{
return_val = -1;
bRet = pStrToInt64ExA(result->string,0,&return_val);
ok(!bRet || return_val != -1, "No result returned from '%s'\n",
result->string);
if (bRet)
ok(return_val == result->str_to_int64_ex, "converted '%s' wrong (%08x%08x)\n",
result->string, (DWORD)(return_val >> 32), (DWORD)return_val);
result++;
}
result = StrToInt_results;
while (result->string)
{
return_val = -1;
bRet = pStrToInt64ExA(result->string,STIF_SUPPORT_HEX,&return_val);
ok(!bRet || return_val != -1, "No result returned from '%s'\n",
result->string);
if (bRet)
ok(return_val == result->str_to_int64_hex, "converted '%s' wrong (%08x%08x)\n",
result->string, (DWORD)(return_val >> 32), (DWORD)return_val);
result++;
}
}
static void test_StrToInt64ExW(void)
{
WCHAR szBuff[256];
const StrToIntResult *result = StrToInt_results;
LONGLONG return_val;
BOOL bRet;
if (!pStrToInt64ExW)
{
win_skip("StrToInt64ExW() is not available\n");
return;
}
while (result->string)
{
return_val = -1;
MultiByteToWideChar(0,0,result->string,-1,szBuff,sizeof(szBuff)/sizeof(WCHAR));
bRet = pStrToInt64ExW(szBuff, 0, &return_val);
ok(!bRet || return_val != -1, "No result returned from '%s'\n",
result->string);
if (bRet)
ok(return_val == result->str_to_int64_ex, "converted '%s' wrong (%08x%08x)\n",
result->string, (DWORD)(return_val >> 32), (DWORD)return_val);
result++;
}
result = StrToInt_results;
while (result->string)
{
return_val = -1;
MultiByteToWideChar(0,0,result->string,-1,szBuff,sizeof(szBuff)/sizeof(WCHAR));
bRet = pStrToInt64ExW(szBuff, STIF_SUPPORT_HEX, &return_val);
ok(!bRet || return_val != -1, "No result returned from '%s'\n",
result->string);
if (bRet)
ok(return_val == result->str_to_int64_hex, "converted '%s' wrong (%08x%08x)\n",
result->string, (DWORD)(return_val >> 32), (DWORD)return_val);
result++;
}
}
static void test_StrDupA(void)
{
LPSTR lpszStr;
@ -560,8 +694,8 @@ static void test_StrFormatKBSizeW(void)
{
pStrFormatKBSizeW(result->value, szBuffW, 256);
WideCharToMultiByte(0,0,szBuffW,-1,szBuff,sizeof(szBuff)/sizeof(WCHAR),0,0);
ok(!strcmp(result->kb_size, szBuff),
"Formatted %x%08x wrong: got %s, expected %s\n",
ok(!strcmp(result->kb_size, szBuff), "Formatted %x%08x wrong: got %s, expected %s\n",
(LONG)(result->value >> 32), (LONG)result->value, szBuff, result->kb_size);
result++;
}
@ -582,7 +716,10 @@ static void test_StrFormatKBSizeA(void)
{
pStrFormatKBSizeA(result->value, szBuff, 256);
ok(!strcmp(result->kb_size, szBuff),
/* shlwapi on Win98 SE does not appear to apply delimiters to the output
* and does not correctly handle extremely large values. */
ok(!strcmp(result->kb_size, szBuff) ||
(result->kb_size_broken && !strcmp(result->kb_size2, szBuff)),
"Formatted %x%08x wrong: got %s, expected %s\n",
(LONG)(result->value >> 32), (LONG)result->value, szBuff, result->kb_size);
result++;
@ -598,8 +735,8 @@ static void test_StrFromTimeIntervalA(void)
{
StrFromTimeIntervalA(szBuff, 256, result->ms, result->digits);
ok(!strcmp(result->time_interval, szBuff), "Formatted %d %d wrong\n",
result->ms, result->digits);
ok(!strcmp(result->time_interval, szBuff), "Formatted %d %d wrong: %s\n",
result->ms, result->digits, szBuff);
result++;
}
}
@ -772,7 +909,7 @@ static void test_StrRStrI(void)
static const WCHAR wszPattern4[] = {'a','b',0};
LPWSTR retW;
LPSTR retA;
check_strrstri(A, szTest, 4, "A", szTest+1);
check_strrstri(A, szTest, 4, "aX", szTest+1);
check_strrstri(A, szTest, 4, "Ay", NULL);
@ -804,6 +941,12 @@ static void test_SHAnsiToAnsi(void)
return;
}
if (pSHAnsiToAnsi == (void *)pStrPBrkW)
{
win_skip("Ordinal 345 corresponds to StrPBrkW, skipping SHAnsiToAnsi tests\n");
return;
}
memset(dest, '\n', sizeof(dest));
dwRet = pSHAnsiToAnsi("hello", dest, sizeof(dest)/sizeof(dest[0]));
ok(dwRet == 6 && !memcmp(dest, "hello\0\n\n", sizeof(dest)),
@ -825,6 +968,12 @@ static void test_SHUnicodeToUnicode(void)
return;
}
if (pSHUnicodeToUnicode == (void *)pStrRChrA)
{
win_skip("Ordinal 346 corresponds to StrRChrA, skipping SHUnicodeToUnicode tests\n");
return;
}
memcpy(dest, lpInit, sizeof(lpInit));
dwRet = pSHUnicodeToUnicode(lpSrc, dest, sizeof(dest)/sizeof(dest[0]));
ok(dwRet == 6 && !memcmp(dest, lpRes, sizeof(dest)),
@ -932,7 +1081,7 @@ if (0)
{
memset(buf, 0xbf, sizeof(buf));
ret = pwnsprintfA(buf, 10, "%s", str1);
ok(broken(ret == 9) || ret == -1 /* Vista */, "Unexpected wsnprintfA return %d, expected 9 or -1\n", ret);
ok(broken(ret == 9) || ret == -1 /* Vista */, "Unexpected wnsprintfA return %d, expected 9 or -1\n", ret);
expect_eq(buf[9], 0, CHAR, "%x");
expect_eq(buf[10], (CHAR)0xbf, CHAR, "%x");
}
@ -943,7 +1092,7 @@ if (0)
{
memset(wbuf, 0xbf, sizeof(wbuf));
ret = pwnsprintfW(wbuf, 10, fmt, wstr1);
ok(broken(ret == 9) || ret == -1 /* Vista */, "Unexpected wsnprintfW return %d, expected 9 or -1\n", ret);
ok(broken(ret == 9) || ret == -1 /* Vista */, "Unexpected wnsprintfW return %d, expected 9 or -1\n", ret);
expect_eq(wbuf[9], 0, WCHAR, "%x");
expect_eq(wbuf[10], (WCHAR)0xbfbf, WCHAR, "%x");
}
@ -951,6 +1100,387 @@ if (0)
win_skip("wnsprintfW() is not available\n");
}
static void test_StrStrA(void)
{
static const char *deadbeefA = "DeAdBeEf";
const struct
{
const char *search;
const char *expect;
} StrStrA_cases[] =
{
{"", NULL},
{"DeAd", deadbeefA},
{"dead", NULL},
{"AdBe", deadbeefA + 2},
{"adbe", NULL},
{"BeEf", deadbeefA + 4},
{"beef", NULL},
};
LPSTR ret;
int i;
/* Tests crash on Win2k */
if (0)
{
ret = StrStrA(NULL, NULL);
ok(!ret, "Expected StrStrA to return NULL, got %p\n", ret);
ret = StrStrA(NULL, "");
ok(!ret, "Expected StrStrA to return NULL, got %p\n", ret);
ret = StrStrA("", NULL);
ok(!ret, "Expected StrStrA to return NULL, got %p\n", ret);
}
ret = StrStrA("", "");
ok(!ret, "Expected StrStrA to return NULL, got %p\n", ret);
for (i = 0; i < sizeof(StrStrA_cases)/sizeof(StrStrA_cases[0]); i++)
{
ret = StrStrA(deadbeefA, StrStrA_cases[i].search);
ok(ret == StrStrA_cases[i].expect,
"[%d] Expected StrStrA to return %p, got %p\n",
i, StrStrA_cases[i].expect, ret);
}
}
static void test_StrStrW(void)
{
static const WCHAR emptyW[] = {0};
static const WCHAR deadbeefW[] = {'D','e','A','d','B','e','E','f',0};
static const WCHAR deadW[] = {'D','e','A','d',0};
static const WCHAR dead_lowerW[] = {'d','e','a','d',0};
static const WCHAR adbeW[] = {'A','d','B','e',0};
static const WCHAR adbe_lowerW[] = {'a','d','b','e',0};
static const WCHAR beefW[] = {'B','e','E','f',0};
static const WCHAR beef_lowerW[] = {'b','e','e','f',0};
const struct
{
const WCHAR *search;
const WCHAR *expect;
} StrStrW_cases[] =
{
{emptyW, NULL},
{deadW, deadbeefW},
{dead_lowerW, NULL},
{adbeW, deadbeefW + 2},
{adbe_lowerW, NULL},
{beefW, deadbeefW + 4},
{beef_lowerW, NULL},
};
LPWSTR ret;
int i;
/* Tests crash on Win2k */
if (0)
{
ret = StrStrW(NULL, NULL);
ok(!ret, "Expected StrStrW to return NULL, got %p\n", ret);
ret = StrStrW(NULL, emptyW);
ok(!ret, "Expected StrStrW to return NULL, got %p\n", ret);
ret = StrStrW(emptyW, NULL);
ok(!ret, "Expected StrStrW to return NULL, got %p\n", ret);
}
ret = StrStrW(emptyW, emptyW);
ok(!ret, "Expected StrStrW to return NULL, got %p\n", ret);
for (i = 0; i < sizeof(StrStrW_cases)/sizeof(StrStrW_cases[0]); i++)
{
ret = StrStrW(deadbeefW, StrStrW_cases[i].search);
ok(ret == StrStrW_cases[i].expect,
"[%d] Expected StrStrW to return %p, got %p\n",
i, StrStrW_cases[i].expect, ret);
}
}
static void test_StrStrIA(void)
{
static const char *deadbeefA = "DeAdBeEf";
const struct
{
const char *search;
const char *expect;
} StrStrIA_cases[] =
{
{"", NULL},
{"DeAd", deadbeefA},
{"dead", deadbeefA},
{"AdBe", deadbeefA + 2},
{"adbe", deadbeefA + 2},
{"BeEf", deadbeefA + 4},
{"beef", deadbeefA + 4},
{"cafe", NULL},
};
LPSTR ret;
int i;
/* Tests crash on Win2k */
if (0)
{
ret = StrStrIA(NULL, NULL);
ok(!ret, "Expected StrStrIA to return NULL, got %p\n", ret);
ret = StrStrIA(NULL, "");
ok(!ret, "Expected StrStrIA to return NULL, got %p\n", ret);
ret = StrStrIA("", NULL);
ok(!ret, "Expected StrStrIA to return NULL, got %p\n", ret);
}
ret = StrStrIA("", "");
ok(!ret, "Expected StrStrIA to return NULL, got %p\n", ret);
for (i = 0; i < sizeof(StrStrIA_cases)/sizeof(StrStrIA_cases[0]); i++)
{
ret = StrStrIA(deadbeefA, StrStrIA_cases[i].search);
ok(ret == StrStrIA_cases[i].expect,
"[%d] Expected StrStrIA to return %p, got %p\n",
i, StrStrIA_cases[i].expect, ret);
}
}
static void test_StrStrIW(void)
{
static const WCHAR emptyW[] = {0};
static const WCHAR deadbeefW[] = {'D','e','A','d','B','e','E','f',0};
static const WCHAR deadW[] = {'D','e','A','d',0};
static const WCHAR dead_lowerW[] = {'d','e','a','d',0};
static const WCHAR adbeW[] = {'A','d','B','e',0};
static const WCHAR adbe_lowerW[] = {'a','d','b','e',0};
static const WCHAR beefW[] = {'B','e','E','f',0};
static const WCHAR beef_lowerW[] = {'b','e','e','f',0};
static const WCHAR cafeW[] = {'c','a','f','e',0};
const struct
{
const WCHAR *search;
const WCHAR *expect;
} StrStrIW_cases[] =
{
{emptyW, NULL},
{deadW, deadbeefW},
{dead_lowerW, deadbeefW},
{adbeW, deadbeefW + 2},
{adbe_lowerW, deadbeefW + 2},
{beefW, deadbeefW + 4},
{beef_lowerW, deadbeefW + 4},
{cafeW, NULL},
};
LPWSTR ret;
int i;
/* Tests crash on Win2k */
if (0)
{
ret = StrStrIW(NULL, NULL);
ok(!ret, "Expected StrStrIW to return NULL, got %p\n", ret);
ret = StrStrIW(NULL, emptyW);
ok(!ret, "Expected StrStrIW to return NULL, got %p\n", ret);
ret = StrStrIW(emptyW, NULL);
ok(!ret, "Expected StrStrIW to return NULL, got %p\n", ret);
}
ret = StrStrIW(emptyW, emptyW);
ok(!ret, "Expected StrStrIW to return NULL, got %p\n", ret);
for (i = 0; i < sizeof(StrStrIW_cases)/sizeof(StrStrIW_cases[0]); i++)
{
ret = StrStrIW(deadbeefW, StrStrIW_cases[i].search);
ok(ret == StrStrIW_cases[i].expect,
"[%d] Expected StrStrIW to return %p, got %p\n",
i, StrStrIW_cases[i].expect, ret);
}
}
static void test_StrStrNW(void)
{
static const WCHAR emptyW[] = {0};
static const WCHAR deadbeefW[] = {'D','e','A','d','B','e','E','f',0};
static const WCHAR deadW[] = {'D','e','A','d',0};
static const WCHAR dead_lowerW[] = {'d','e','a','d',0};
static const WCHAR adbeW[] = {'A','d','B','e',0};
static const WCHAR adbe_lowerW[] = {'a','d','b','e',0};
static const WCHAR beefW[] = {'B','e','E','f',0};
static const WCHAR beef_lowerW[] = {'b','e','e','f',0};
const struct
{
const WCHAR *search;
const UINT count;
const WCHAR *expect;
} StrStrNW_cases[] =
{
{emptyW, sizeof(deadbeefW)/sizeof(WCHAR), NULL},
{deadW, sizeof(deadbeefW)/sizeof(WCHAR), deadbeefW},
{dead_lowerW, sizeof(deadbeefW)/sizeof(WCHAR), NULL},
{adbeW, sizeof(deadbeefW)/sizeof(WCHAR), deadbeefW + 2},
{adbe_lowerW, sizeof(deadbeefW)/sizeof(WCHAR), NULL},
{beefW, sizeof(deadbeefW)/sizeof(WCHAR), deadbeefW + 4},
{beef_lowerW, sizeof(deadbeefW)/sizeof(WCHAR), NULL},
{beefW, 0, NULL},
{beefW, 1, NULL},
{beefW, 2, NULL},
{beefW, 3, NULL},
{beefW, 4, NULL},
{beefW, 5, deadbeefW + 4},
{beefW, 6, deadbeefW + 4},
{beefW, 7, deadbeefW + 4},
{beefW, 8, deadbeefW + 4},
{beefW, 9, deadbeefW + 4},
};
LPWSTR ret;
UINT i;
if (!pStrStrNW)
{
win_skip("StrStrNW() is not available\n");
return;
}
ret = pStrStrNW(NULL, NULL, 0);
ok(!ret, "Expected StrStrNW to return NULL, got %p\n", ret);
ret = pStrStrNW(NULL, NULL, 10);
ok(!ret, "Expected StrStrNW to return NULL, got %p\n", ret);
ret = pStrStrNW(NULL, emptyW, 10);
ok(!ret, "Expected StrStrNW to return NULL, got %p\n", ret);
ret = pStrStrNW(emptyW, NULL, 10);
ok(!ret, "Expected StrStrNW to return NULL, got %p\n", ret);
ret = pStrStrNW(emptyW, emptyW, 10);
ok(!ret, "Expected StrStrNW to return NULL, got %p\n", ret);
for (i = 0; i < sizeof(StrStrNW_cases)/sizeof(StrStrNW_cases[0]); i++)
{
ret = pStrStrNW(deadbeefW, StrStrNW_cases[i].search, StrStrNW_cases[i].count);
ok(ret == StrStrNW_cases[i].expect,
"[%d] Expected StrStrNW to return %p, got %p\n",
i, StrStrNW_cases[i].expect, ret);
}
/* StrStrNW accepts counts larger than the search string length but rejects
* counts larger than around 2G. The limit seems to change based on the
* caller executable itself. */
ret = pStrStrNW(deadbeefW, beefW, 100);
ok(ret == deadbeefW + 4, "Expected StrStrNW to return deadbeefW + 4, got %p\n", ret);
if (0)
{
ret = pStrStrNW(deadbeefW, beefW, ~0U);
ok(!ret, "Expected StrStrNW to return NULL, got %p\n", ret);
}
}
static void test_StrStrNIW(void)
{
static const WCHAR emptyW[] = {0};
static const WCHAR deadbeefW[] = {'D','e','A','d','B','e','E','f',0};
static const WCHAR deadW[] = {'D','e','A','d',0};
static const WCHAR dead_lowerW[] = {'d','e','a','d',0};
static const WCHAR adbeW[] = {'A','d','B','e',0};
static const WCHAR adbe_lowerW[] = {'a','d','b','e',0};
static const WCHAR beefW[] = {'B','e','E','f',0};
static const WCHAR beef_lowerW[] = {'b','e','e','f',0};
static const WCHAR cafeW[] = {'c','a','f','e',0};
const struct
{
const WCHAR *search;
const UINT count;
const WCHAR *expect;
} StrStrNIW_cases[] =
{
{emptyW, sizeof(deadbeefW)/sizeof(WCHAR), NULL},
{deadW, sizeof(deadbeefW)/sizeof(WCHAR), deadbeefW},
{dead_lowerW, sizeof(deadbeefW)/sizeof(WCHAR), deadbeefW},
{adbeW, sizeof(deadbeefW)/sizeof(WCHAR), deadbeefW + 2},
{adbe_lowerW, sizeof(deadbeefW)/sizeof(WCHAR), deadbeefW + 2},
{beefW, sizeof(deadbeefW)/sizeof(WCHAR), deadbeefW + 4},
{beef_lowerW, sizeof(deadbeefW)/sizeof(WCHAR), deadbeefW + 4},
{cafeW, sizeof(deadbeefW)/sizeof(WCHAR), NULL},
{beefW, 0, NULL},
{beefW, 1, NULL},
{beefW, 2, NULL},
{beefW, 3, NULL},
{beefW, 4, NULL},
{beefW, 5, deadbeefW + 4},
{beefW, 6, deadbeefW + 4},
{beefW, 7, deadbeefW + 4},
{beefW, 8, deadbeefW + 4},
{beefW, 9, deadbeefW + 4},
{beef_lowerW, 0, NULL},
{beef_lowerW, 1, NULL},
{beef_lowerW, 2, NULL},
{beef_lowerW, 3, NULL},
{beef_lowerW, 4, NULL},
{beef_lowerW, 5, deadbeefW + 4},
{beef_lowerW, 6, deadbeefW + 4},
{beef_lowerW, 7, deadbeefW + 4},
{beef_lowerW, 8, deadbeefW + 4},
{beef_lowerW, 9, deadbeefW + 4},
};
LPWSTR ret;
UINT i;
if (!pStrStrNIW)
{
win_skip("StrStrNIW() is not available\n");
return;
}
ret = pStrStrNIW(NULL, NULL, 0);
ok(!ret, "Expected StrStrNIW to return NULL, got %p\n", ret);
ret = pStrStrNIW(NULL, NULL, 10);
ok(!ret, "Expected StrStrNIW to return NULL, got %p\n", ret);
ret = pStrStrNIW(NULL, emptyW, 10);
ok(!ret, "Expected StrStrNIW to return NULL, got %p\n", ret);
ret = pStrStrNIW(emptyW, NULL, 10);
ok(!ret, "Expected StrStrNIW to return NULL, got %p\n", ret);
ret = pStrStrNIW(emptyW, emptyW, 10);
ok(!ret, "Expected StrStrNIW to return NULL, got %p\n", ret);
for (i = 0; i < sizeof(StrStrNIW_cases)/sizeof(StrStrNIW_cases[0]); i++)
{
ret = pStrStrNIW(deadbeefW, StrStrNIW_cases[i].search, StrStrNIW_cases[i].count);
ok(ret == StrStrNIW_cases[i].expect,
"[%d] Expected StrStrNIW to return %p, got %p\n",
i, StrStrNIW_cases[i].expect, ret);
}
/* StrStrNIW accepts counts larger than the search string length but rejects
* counts larger than around 2G. The limit seems to change based on the
* caller executable itself. */
ret = pStrStrNIW(deadbeefW, beefW, 100);
ok(ret == deadbeefW + 4, "Expected StrStrNIW to return deadbeefW + 4, got %p\n", ret);
if (0)
{
ret = pStrStrNIW(deadbeefW, beefW, ~0U);
ok(!ret, "Expected StrStrNIW to return NULL, got %p\n", ret);
}
}
START_TEST(string)
{
HMODULE hShlwapi;
@ -978,11 +1508,17 @@ START_TEST(string)
pStrFormatKBSizeW = (void *)GetProcAddress(hShlwapi, "StrFormatKBSizeW");
pStrIsIntlEqualA = (void *)GetProcAddress(hShlwapi, "StrIsIntlEqualA");
pStrIsIntlEqualW = (void *)GetProcAddress(hShlwapi, "StrIsIntlEqualW");
pStrPBrkW = (void *)GetProcAddress(hShlwapi, "StrPBrkW");
pStrRChrA = (void *)GetProcAddress(hShlwapi, "StrRChrA");
pStrRetToBSTR = (void *)GetProcAddress(hShlwapi, "StrRetToBSTR");
pStrRetToBufA = (void *)GetProcAddress(hShlwapi, "StrRetToBufA");
pStrRetToBufW = (void *)GetProcAddress(hShlwapi, "StrRetToBufW");
pStrStrNW = (void *)GetProcAddress(hShlwapi, "StrStrNW");
pStrStrNIW = (void *)GetProcAddress(hShlwapi, "StrStrNIW");
pwnsprintfA = (void *)GetProcAddress(hShlwapi, "wnsprintfA");
pwnsprintfW = (void *)GetProcAddress(hShlwapi, "wnsprintfW");
pStrToInt64ExA = (void *)GetProcAddress(hShlwapi, "StrToInt64ExA");
pStrToInt64ExW = (void *)GetProcAddress(hShlwapi, "StrToInt64ExW");
test_StrChrA();
test_StrChrW();
@ -996,20 +1532,23 @@ START_TEST(string)
test_StrToIntW();
test_StrToIntExA();
test_StrToIntExW();
test_StrToInt64ExA();
test_StrToInt64ExW();
test_StrDupA();
if (lstrcmp(thousandDelim, ",")==0 && lstrcmp(decimalDelim, ".")==0)
/* language-dependent test */
if (is_lang_english() && is_locale_english())
{
/* these tests are locale-dependent */
test_StrFormatByteSize64A();
test_StrFormatKBSizeA();
test_StrFormatKBSizeW();
}
/* language-dependent test */
if (PRIMARYLANGID(GetUserDefaultLangID()) != LANG_ENGLISH)
trace("Skipping StrFromTimeInterval test for non English language\n");
else
skip("An English UI and locale is required for the StrFormat*Size tests\n");
if (is_lang_english())
test_StrFromTimeIntervalA();
else
skip("An English UI is required for the StrFromTimeInterval tests\n");
test_StrCmpA();
test_StrCmpW();
@ -1020,6 +1559,12 @@ START_TEST(string)
test_SHAnsiToAnsi();
test_SHUnicodeToUnicode();
test_StrXXX_overflows();
test_StrStrA();
test_StrStrW();
test_StrStrIA();
test_StrStrIW();
test_StrStrNW();
test_StrStrNIW();
CoUninitialize();
}

View file

@ -21,6 +21,8 @@
#include <stdarg.h>
#define COBJMACROS
#define CONST_VTABLE
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
@ -37,13 +39,18 @@ static DWORD AddRef_called;
typedef struct
{
const IUnknownVtbl* lpVtbl;
IUnknown IUnknown_iface;
LONG *ref;
} threadref;
static inline threadref *impl_from_IUnknown(IUnknown *iface)
{
return CONTAINING_RECORD(iface, threadref, IUnknown_iface);
}
static HRESULT WINAPI threadref_QueryInterface(IUnknown *iface, REFIID riid, LPVOID *ppvObj)
{
threadref * This = (threadref *)iface;
threadref * This = impl_from_IUnknown(iface);
trace("unexpected QueryInterface(%p, %p, %p) called\n", This, riid, ppvObj);
*ppvObj = NULL;
@ -52,7 +59,7 @@ static HRESULT WINAPI threadref_QueryInterface(IUnknown *iface, REFIID riid, LPV
static ULONG WINAPI threadref_AddRef(IUnknown *iface)
{
threadref * This = (threadref *)iface;
threadref * This = impl_from_IUnknown(iface);
AddRef_called++;
return InterlockedIncrement(This->ref);
@ -60,7 +67,7 @@ static ULONG WINAPI threadref_AddRef(IUnknown *iface)
static ULONG WINAPI threadref_Release(IUnknown *iface)
{
threadref * This = (threadref *)iface;
threadref * This = impl_from_IUnknown(iface);
trace("unexpected Release(%p) called\n", This);
return InterlockedDecrement(This->ref);
@ -76,7 +83,7 @@ static const IUnknownVtbl threadref_vt =
static void init_threadref(threadref* iface, LONG *refcount)
{
iface->lpVtbl = &threadref_vt;
iface->IUnknown_iface.lpVtbl = &threadref_vt;
iface->ref = refcount;
}
@ -184,7 +191,7 @@ static void test_SHGetThreadRef(void)
if (0) {
/* this crash on Windows */
hr = pSHGetThreadRef(NULL);
pSHGetThreadRef(NULL);
}
}
@ -209,7 +216,7 @@ static void test_SHSetThreadRef(void)
init_threadref(&ref, &refcount);
AddRef_called = 0;
refcount = 1;
hr = pSHSetThreadRef( (IUnknown *)&ref);
hr = pSHSetThreadRef(&ref.IUnknown_iface);
ok( (hr == S_OK) && (refcount == 1) && (!AddRef_called),
"got 0x%x with %d, %d (expected S_OK with 1, 0)\n",
hr, refcount, AddRef_called);
@ -219,7 +226,7 @@ static void test_SHSetThreadRef(void)
refcount = 1;
punk = NULL;
hr = pSHGetThreadRef(&punk);
ok( (hr == S_OK) && (punk == (IUnknown *)&ref) && (refcount == 2) && (AddRef_called == 1),
ok( (hr == S_OK) && (punk == &ref.IUnknown_iface) && (refcount == 2) && (AddRef_called == 1),
"got 0x%x and %p with %d, %d (expected S_OK and %p with 2, 1)\n",
hr, punk, refcount, AddRef_called, &ref);

View file

@ -56,6 +56,8 @@ static HRESULT (WINAPI *pHashData)(LPBYTE, DWORD, LPBYTE, DWORD);
static const char* TEST_URL_1 = "http://www.winehq.org/tests?date=10/10/1923";
static const char* TEST_URL_2 = "http://localhost:8080/tests%2e.html?date=Mon%2010/10/1923";
static const char* TEST_URL_3 = "http://foo:bar@localhost:21/internal.php?query=x&return=y";
static const char* TEST_URL_4 = "http://foo:bar@google.*.com:21/internal.php?query=x&return=y";
static const WCHAR winehqW[] = {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.','o','r','g','/',0};
static const CHAR winehqA[] = {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.','o','r','g','/',0};
@ -83,9 +85,18 @@ static const TEST_URL_APPLY TEST_APPLY[] = {
{"winehq.org", URL_APPLY_GUESSSCHEME | URL_APPLY_DEFAULT, S_OK, 17, "http://winehq.org"},
{"winehq.org", URL_APPLY_GUESSSCHEME, S_FALSE, TEST_APPLY_MAX_LENGTH, untouchedA},
{"winehq.org", URL_APPLY_DEFAULT, S_OK, 17, "http://winehq.org"},
{"http://www.winehq.org", URL_APPLY_GUESSSCHEME , S_FALSE, TEST_APPLY_MAX_LENGTH, untouchedA},
{"http://www.winehq.org", URL_APPLY_GUESSSCHEME | URL_APPLY_FORCEAPPLY, S_FALSE, TEST_APPLY_MAX_LENGTH, untouchedA},
{"http://www.winehq.org", URL_APPLY_GUESSSCHEME | URL_APPLY_FORCEAPPLY | URL_APPLY_DEFAULT, S_OK, 28, "http://http://www.winehq.org"},
{"http://www.winehq.org", URL_APPLY_GUESSSCHEME | URL_APPLY_DEFAULT, S_FALSE, TEST_APPLY_MAX_LENGTH, untouchedA},
{"", URL_APPLY_GUESSSCHEME | URL_APPLY_DEFAULT, S_OK, 7, "http://"},
{"", URL_APPLY_GUESSSCHEME, S_FALSE, TEST_APPLY_MAX_LENGTH, untouchedA},
{"", URL_APPLY_DEFAULT, S_OK, 7, "http://"}
{"", URL_APPLY_DEFAULT, S_OK, 7, "http://"},
{"u:\\windows", URL_APPLY_GUESSFILE | URL_APPLY_DEFAULT, S_OK, 18, "file:///u:/windows"},
{"u:\\windows", URL_APPLY_GUESSFILE, S_OK, 18, "file:///u:/windows"},
{"u:\\windows", URL_APPLY_DEFAULT, S_OK, 17, "http://u:\\windows"},
{"file:///c:/windows", URL_APPLY_GUESSFILE , S_FALSE, TEST_APPLY_MAX_LENGTH, untouchedA},
{"aa:\\windows", URL_APPLY_GUESSFILE , S_FALSE, TEST_APPLY_MAX_LENGTH, untouchedA},
};
/* ################ */
@ -100,6 +111,8 @@ typedef struct _TEST_URL_CANONICALIZE {
static const TEST_URL_CANONICALIZE TEST_CANONICALIZE[] = {
{"http://www.winehq.org/tests/../tests/../..", 0, S_OK, "http://www.winehq.org/", TRUE},
{"http://www.winehq.org/..", 0, S_OK, "http://www.winehq.org/..", FALSE},
{"http://www.winehq.org/tests/tests2/../../tests", 0, S_OK, "http://www.winehq.org/tests", FALSE},
{"http://www.winehq.org/tests/../tests", 0, S_OK, "http://www.winehq.org/tests", FALSE},
{"http://www.winehq.org/tests\n", URL_WININET_COMPATIBILITY|URL_ESCAPE_SPACES_ONLY|URL_ESCAPE_UNSAFE, S_OK, "http://www.winehq.org/tests", FALSE},
{"http://www.winehq.org/tests\r", URL_WININET_COMPATIBILITY|URL_ESCAPE_SPACES_ONLY|URL_ESCAPE_UNSAFE, S_OK, "http://www.winehq.org/tests", FALSE},
@ -112,6 +125,7 @@ static const TEST_URL_CANONICALIZE TEST_CANONICALIZE[] = {
{"http://www.winehq.org/tests/../", 0, S_OK, "http://www.winehq.org/", FALSE},
{"http://www.winehq.org/tests/..?query=x&return=y", 0, S_OK, "http://www.winehq.org/?query=x&return=y", FALSE},
{"http://www.winehq.org/tests/../?query=x&return=y", 0, S_OK, "http://www.winehq.org/?query=x&return=y", FALSE},
{"\tht\ttp\t://www\t.w\tineh\t\tq.or\tg\t/\ttests/..\t?\tquer\ty=x\t\t&re\tturn=y\t\t", 0, S_OK, "http://www.winehq.org/?query=x&return=y", FALSE},
{"http://www.winehq.org/tests/..#example", 0, S_OK, "http://www.winehq.org/#example", FALSE},
{"http://www.winehq.org/tests/../#example", 0, S_OK, "http://www.winehq.org/#example", FALSE},
{"http://www.winehq.org/tests\\../#example", 0, S_OK, "http://www.winehq.org/#example", FALSE},
@ -120,6 +134,9 @@ static const TEST_URL_CANONICALIZE TEST_CANONICALIZE[] = {
{"http://www.winehq.org/tests/../#example", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests/../#example", FALSE},
{"http://www.winehq.org/tests/foo bar", URL_ESCAPE_SPACES_ONLY| URL_DONT_ESCAPE_EXTRA_INFO , S_OK, "http://www.winehq.org/tests/foo%20bar", FALSE},
{"http://www.winehq.org/tests/foo%20bar", URL_UNESCAPE , S_OK, "http://www.winehq.org/tests/foo bar", FALSE},
{"http://www.winehq.org", 0, S_OK, "http://www.winehq.org/", FALSE},
{"http:///www.winehq.org", 0, S_OK, "http:///www.winehq.org", FALSE},
{"http:////www.winehq.org", 0, S_OK, "http:////www.winehq.org", FALSE},
{"file:///c:/tests/foo%20bar", URL_UNESCAPE , S_OK, "file:///c:/tests/foo bar", FALSE},
{"file:///c:/tests\\foo%20bar", URL_UNESCAPE , S_OK, "file:///c:/tests/foo bar", FALSE},
{"file:///c:/tests/foo%20bar", 0, S_OK, "file:///c:/tests/foo%20bar", FALSE},
@ -134,6 +151,24 @@ static const TEST_URL_CANONICALIZE TEST_CANONICALIZE[] = {
{"file:///c://tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\\\tests\\foo bar", FALSE},
{"file:///c:\\tests\\foo bar", 0, S_OK, "file:///c:/tests/foo bar", FALSE},
{"file:///c:\\tests\\foo bar", URL_DONT_SIMPLIFY, S_OK, "file:///c:/tests/foo bar", FALSE},
{"file:///c:\\tests\\foobar", 0, S_OK, "file:///c:/tests/foobar", FALSE},
{"file:///c:\\tests\\foobar", URL_WININET_COMPATIBILITY, S_OK, "file://c:\\tests\\foobar", FALSE},
{"file://home/user/file", 0, S_OK, "file://home/user/file", FALSE},
{"file:///home/user/file", 0, S_OK, "file:///home/user/file", FALSE},
{"file:////home/user/file", 0, S_OK, "file://home/user/file", FALSE},
{"file://home/user/file", URL_WININET_COMPATIBILITY, S_OK, "file://\\\\home\\user\\file", FALSE},
{"file:///home/user/file", URL_WININET_COMPATIBILITY, S_OK, "file://\\home\\user\\file", FALSE},
{"file:////home/user/file", URL_WININET_COMPATIBILITY, S_OK, "file://\\\\home\\user\\file", FALSE},
{"file://///home/user/file", URL_WININET_COMPATIBILITY, S_OK, "file://\\\\home\\user\\file", FALSE},
{"file://C:/user/file", 0, S_OK, "file:///C:/user/file", FALSE},
{"file://C:/user/file/../asdf", 0, S_OK, "file:///C:/user/asdf", FALSE},
{"file:///C:/user/file", 0, S_OK, "file:///C:/user/file", FALSE},
{"file:////C:/user/file", 0, S_OK, "file:///C:/user/file", FALSE},
{"file://C:/user/file", URL_WININET_COMPATIBILITY, S_OK, "file://C:\\user\\file", FALSE},
{"file:///C:/user/file", URL_WININET_COMPATIBILITY, S_OK, "file://C:\\user\\file", FALSE},
{"file:////C:/user/file", URL_WININET_COMPATIBILITY, S_OK, "file://C:\\user\\file", FALSE},
{"http:///www.winehq.org", 0, S_OK, "http:///www.winehq.org", FALSE},
{"http:///www.winehq.org", URL_WININET_COMPATIBILITY, S_OK, "http:///www.winehq.org", FALSE},
{"http://www.winehq.org/site/about", URL_FILE_USE_PATHURL, S_OK, "http://www.winehq.org/site/about", FALSE},
{"file_://www.winehq.org/site/about", URL_FILE_USE_PATHURL, S_OK, "file_://www.winehq.org/site/about", FALSE},
{"c:\\dir\\file", 0, S_OK, "file:///c:/dir/file", FALSE},
@ -141,6 +176,7 @@ static const TEST_URL_CANONICALIZE TEST_CANONICALIZE[] = {
{"c:dir\\file", 0, S_OK, "file:///c:dir/file", FALSE},
{"c:\\tests\\foo bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar", FALSE},
{"c:\\tests\\foo bar", 0, S_OK, "file:///c:/tests/foo%20bar", FALSE},
{"c\t:\t\\te\tsts\\fo\to \tbar\t", 0, S_OK, "file:///c:/tests/foo%20bar", FALSE},
{"res://file", 0, S_OK, "res://file/", FALSE},
{"res://file", URL_FILE_USE_PATHURL, S_OK, "res://file/", FALSE},
{"res:///c:/tests/foo%20bar", URL_UNESCAPE , S_OK, "res:///c:/tests/foo bar", FALSE},
@ -158,11 +194,19 @@ static const TEST_URL_CANONICALIZE TEST_CANONICALIZE[] = {
{"res://c:\\tests/res\\foo%20bar/strange\\sth", URL_FILE_USE_PATHURL, S_OK, "res://c:\\tests/res\\foo%20bar/strange\\sth", FALSE},
{"res://c:\\tests/res\\foo%20bar/strange\\sth", URL_UNESCAPE, S_OK, "res://c:\\tests/res\\foo bar/strange\\sth", FALSE},
{"A", 0, S_OK, "A", FALSE},
{"../A", 0, S_OK, "../A", FALSE},
{"A/../B", 0, S_OK, "B", TRUE},
{"/uri-res/N2R?urn:sha1:B3K", URL_DONT_ESCAPE_EXTRA_INFO | URL_WININET_COMPATIBILITY /*0x82000000*/, S_OK, "/uri-res/N2R?urn:sha1:B3K", FALSE} /*LimeWire online installer calls this*/,
{"http:www.winehq.org/dir/../index.html", 0, S_OK, "http:www.winehq.org/index.html"},
{"http://localhost/test.html", URL_FILE_USE_PATHURL, S_OK, "http://localhost/test.html"},
{"http://localhost/te%20st.html", URL_FILE_USE_PATHURL, S_OK, "http://localhost/te%20st.html"},
{"http://www.winehq.org/%E6%A1%9C.html", URL_FILE_USE_PATHURL, S_OK, "http://www.winehq.org/%E6%A1%9C.html"}
{"http://www.winehq.org/%E6%A1%9C.html", URL_FILE_USE_PATHURL, S_OK, "http://www.winehq.org/%E6%A1%9C.html"},
{"mk:@MSITStore:C:\\Program Files/AutoCAD 2008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm", 0, S_OK, "mk:@MSITStore:C:\\Program Files/AutoCAD 2008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm"},
{"ftp:@MSITStore:C:\\Program Files/AutoCAD 2008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm", 0, S_OK, "ftp:@MSITStore:C:\\Program Files/AutoCAD 2008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm"},
{"file:@MSITStore:C:\\Program Files/AutoCAD 2008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm", 0, S_OK, "file:@MSITStore:C:/Program Files/AutoCAD 2008/Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm"},
{"http:@MSITStore:C:\\Program Files/AutoCAD 2008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm", 0, S_OK, "http:@MSITStore:C:/Program Files/AutoCAD 2008/Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm"},
{"http:@MSITStore:C:\\Program Files/AutoCAD 2008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm", URL_FILE_USE_PATHURL, S_OK, "http:@MSITStore:C:/Program Files/AutoCAD 2008/Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm"},
{"mk:@MSITStore:C:\\Program Files/AutoCAD 2008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm", URL_FILE_USE_PATHURL, S_OK, "mk:@MSITStore:C:\\Program Files/AutoCAD 2008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm"},
};
/* ################ */
@ -280,6 +324,9 @@ static const TEST_URL_COMBINE TEST_COMBINE[] = {
{"http://www.winehq.org/tests/#example", "tests9", 0, S_OK, "http://www.winehq.org/tests/tests9"},
{"http://www.winehq.org/tests/../tests/", "/tests10/..", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests10/.."},
{"http://www.winehq.org/tests/../", "tests11", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests/../tests11"},
{"http://www.winehq.org/test12", "#", 0, S_OK, "http://www.winehq.org/test12#"},
{"http://www.winehq.org/test13#aaa", "#bbb", 0, S_OK, "http://www.winehq.org/test13#bbb"},
{"http://www.winehq.org/test14#aaa/bbb#ccc", "#", 0, S_OK, "http://www.winehq.org/test14#"},
{"file:///C:\\dir\\file.txt", "test.txt", 0, S_OK, "file:///C:/dir/test.txt"},
{"file:///C:\\dir\\file.txt#hash\\hash", "test.txt", 0, S_OK, "file:///C:/dir/file.txt#hash/test.txt"},
{"file:///C:\\dir\\file.html#hash\\hash", "test.html", 0, S_OK, "file:///C:/dir/test.html"},
@ -296,7 +343,7 @@ static const TEST_URL_COMBINE TEST_COMBINE[] = {
{"foo:today", "foo:calendar", 0, S_OK, "foo:calendar"},
{"foo:today", "bar:calendar", 0, S_OK, "bar:calendar"},
{"foo:/today", "foo:calendar", 0, S_OK, "foo:/calendar"},
{"foo:/today/", "foo:calendar", 0, S_OK, "foo:/today/calendar"},
{"Foo:/today/", "fOo:calendar", 0, S_OK, "foo:/today/calendar"},
{"mk:@MSITStore:dir/test.chm::dir/index.html", "image.jpg", 0, S_OK, "mk:@MSITStore:dir/test.chm::dir/image.jpg"},
{"mk:@MSITStore:dir/test.chm::dir/dir2/index.html", "../image.jpg", 0, S_OK, "mk:@MSITStore:dir/test.chm::dir/image.jpg"},
/* UrlCombine case 2 tests. Schemes do not match */
@ -318,7 +365,7 @@ static const TEST_URL_COMBINE TEST_COMBINE[] = {
{"outbind://xxxxxxxxx/","http:wine16/dir",0, S_OK,"http:wine16/dir"},
{"http://xxxxxxxxx","outbind:wine17/dir",URL_PLUGGABLE_PROTOCOL, S_OK,"outbind:wine17/dir"},
{"xxx://xxxxxxxxx","ftp:wine18/dir",URL_PLUGGABLE_PROTOCOL, S_OK,"ftp:wine18/dir"},
{"ftp://xxxxxxxxx/","xxx:wine19/dir",URL_PLUGGABLE_PROTOCOL, S_OK,"xxx:wine19/dir"},
{"ftp://xxxxxxxxx/","xXx:wine19/dir",URL_PLUGGABLE_PROTOCOL, S_OK,"xxx:wine19/dir"},
{"outbind://xxxxxxxxx/","http:wine20/dir",URL_PLUGGABLE_PROTOCOL, S_OK,"http:wine20/dir"},
{"file:///c:/dir/file.txt","index.html?test=c:/abc",URL_ESCAPE_SPACES_ONLY|URL_DONT_ESCAPE_EXTRA_INFO,S_OK,"file:///c:/dir/index.html?test=c:/abc"}
};
@ -337,6 +384,7 @@ static const struct {
{"c:foo\\bar", "file:///c:foo/bar", S_OK},
{"c:\\foo/b a%r", "file:///c:/foo/b%20a%25r", S_OK},
{"c:\\foo\\foo bar", "file:///c:/foo/foo%20bar", S_OK},
{"file:///c:/foo/bar", "file:///c:/foo/bar", S_FALSE},
#if 0
/* The following test fails on native shlwapi as distributed with Win95/98.
* Wine matches the behaviour of later versions.
@ -587,6 +635,9 @@ static void test_UrlGetPart(void)
const char* http_url = "http://user:pass 123@www.wine hq.org";
const char* res_url = "res://some.dll/find.dlg";
const char* about_url = "about:blank";
const char* excid_url = "x-excid://36C00000/guid:{048B4E89-2E92-496F-A837-33BA02FF6D32}/Message.htm";
const char* foo_url = "foo://bar-url/test";
const char* short_url = "ascheme:";
CHAR szPart[INTERNET_MAX_URL_LENGTH];
DWORD dwSize;
@ -623,6 +674,20 @@ static void test_UrlGetPart(void)
ok(szPart[0]==0, "UrlGetPartA(\"hi\") return \"%s\" instead of \"\"\n", szPart);
ok(dwSize == 0, "dwSize = %d\n", dwSize);
if(pUrlGetPartW)
{
const WCHAR hiW[] = {'h','i',0};
WCHAR bufW[5];
/* UrlGetPartW returns S_OK instead of S_FALSE */
dwSize = sizeof szPart;
bufW[0]='x'; bufW[1]=0;
res = pUrlGetPartW(hiW, bufW, &dwSize, URL_PART_SCHEME, 0);
todo_wine ok(res==S_OK, "UrlGetPartW(\"hi\") returned %08X\n", res);
ok(bufW[0] == 0, "UrlGetPartW(\"hi\") return \"%c\"\n", bufW[0]);
ok(dwSize == 0, "dwSize = %d\n", dwSize);
}
dwSize = sizeof szPart;
szPart[0]='x'; szPart[1]=0;
res = pUrlGetPartA("hi", szPart, &dwSize, URL_PART_QUERY, 0);
@ -637,6 +702,8 @@ static void test_UrlGetPart(void)
test_url_part(TEST_URL_3, URL_PART_SCHEME, 0, "http");
test_url_part(TEST_URL_3, URL_PART_QUERY, 0, "?query=x&return=y");
test_url_part(TEST_URL_4, URL_PART_HOSTNAME, 0, "google.*.com");
test_url_part(file_url, URL_PART_HOSTNAME, 0, "h o s t");
test_url_part(http_url, URL_PART_HOSTNAME, 0, "www.wine hq.org");
@ -644,6 +711,10 @@ static void test_UrlGetPart(void)
test_url_part(about_url, URL_PART_SCHEME, 0, "about");
test_url_part(excid_url, URL_PART_SCHEME, 0, "x-excid");
test_url_part(foo_url, URL_PART_SCHEME, 0, "foo");
test_url_part(short_url, URL_PART_SCHEME, 0, "ascheme");
dwSize = sizeof(szPart);
res = pUrlGetPartA(about_url, szPart, &dwSize, URL_PART_HOSTNAME, 0);
ok(res==E_FAIL, "returned %08x\n", res);
@ -674,6 +745,34 @@ static void test_UrlGetPart(void)
szPart[0] = 'x'; szPart[1] = '\0';
res = pUrlGetPartA("index.htm", szPart, &dwSize, URL_PART_HOSTNAME, 0);
ok(res==E_FAIL, "returned %08x\n", res);
dwSize = sizeof(szPart);
szPart[0] = 'x'; szPart[1] = '\0';
res = pUrlGetPartA(excid_url, szPart, &dwSize, URL_PART_HOSTNAME, 0);
ok(res==E_FAIL, "returned %08x\n", res);
ok(szPart[0] == 'x', "szPart[0] = %c\n", szPart[0]);
ok(dwSize == sizeof(szPart), "dwSize = %d\n", dwSize);
dwSize = sizeof(szPart);
szPart[0] = 'x'; szPart[1] = '\0';
res = pUrlGetPartA(excid_url, szPart, &dwSize, URL_PART_QUERY, 0);
ok(res==S_FALSE, "returned %08x\n", res);
ok(szPart[0] == 0, "szPart[0] = %c\n", szPart[0]);
ok(dwSize == 0, "dwSize = %d\n", dwSize);
dwSize = sizeof(szPart);
szPart[0] = 'x'; szPart[1] = '\0';
res = pUrlGetPartA(foo_url, szPart, &dwSize, URL_PART_HOSTNAME, 0);
ok(res==E_FAIL, "returned %08x\n", res);
ok(szPart[0] == 'x', "szPart[0] = %c\n", szPart[0]);
ok(dwSize == sizeof(szPart), "dwSize = %d\n", dwSize);
dwSize = sizeof(szPart);
szPart[0] = 'x'; szPart[1] = '\0';
res = pUrlGetPartA(foo_url, szPart, &dwSize, URL_PART_QUERY, 0);
ok(res==S_FALSE, "returned %08x\n", res);
ok(szPart[0] == 0, "szPart[0] = %c\n", szPart[0]);
ok(dwSize == 0, "dwSize = %d\n", dwSize);
}
/* ########################### */
@ -750,10 +849,13 @@ static void test_url_canonicalize(int index, const char *szUrl, DWORD dwFlags, H
static void test_UrlEscape(void)
{
static const WCHAR out[] = { 'f','o','o','%','2','0','b','a','r',0 };
DWORD size = 0;
HRESULT ret;
unsigned int i;
char empty_string[] = "";
WCHAR overwrite[] = { 'f','o','o',' ','b','a','r',0,0,0 };
if (!pUrlEscapeA) {
win_skip("UrlEscapeA noz found\n");
@ -780,9 +882,28 @@ static void test_UrlEscape(void)
ok(size == 1, "got %d, expected %d\n", size, 1);
size = 1;
empty_string[0] = 127;
ret = pUrlEscapeA("/woningplan/woonkamer basis.swf", empty_string, &size, URL_ESCAPE_SPACES_ONLY);
ok(ret == E_POINTER, "got %x, expected %x\n", ret, E_POINTER);
ok(size == 34, "got %d, expected %d\n", size, 34);
ok(empty_string[0] == 127, "String has changed, empty_string[0] = %d\n", empty_string[0]);
if(pUrlEscapeW) {
WCHAR wc;
size = sizeof(overwrite)/sizeof(WCHAR);
ret = pUrlEscapeW(overwrite, overwrite, &size, URL_ESCAPE_SPACES_ONLY);
ok(ret == S_OK, "got %x, expected S_OK\n", ret);
ok(size == 9, "got %d, expected 9\n", size);
ok(!lstrcmpW(overwrite, out), "got %s, expected %s\n", wine_dbgstr_w(overwrite), wine_dbgstr_w(out));
size = 1;
wc = 127;
ret = pUrlEscapeW(overwrite, &wc, &size, URL_ESCAPE_SPACES_ONLY);
ok(ret == E_POINTER, "got %x, expected %x\n", ret, E_POINTER);
ok(size == 10, "got %d, expected 10\n", size);
ok(wc == 127, "String has changed, wc = %d\n", wc);
}
for(i=0; i<sizeof(TEST_ESCAPE)/sizeof(TEST_ESCAPE[0]); i++) {
test_url_escape(TEST_ESCAPE[i].url, TEST_ESCAPE[i].flags,
@ -1385,8 +1506,17 @@ static void test_HashData(void)
START_TEST(url)
{
char *pFunc;
hShlwapi = GetModuleHandleA("shlwapi.dll");
/* SHCreateStreamOnFileEx was introduced in shlwapi v6.0 */
pFunc = (void*)GetProcAddress(hShlwapi, "SHCreateStreamOnFileEx");
if(!pFunc){
win_skip("Too old shlwapi version\n");
return;
}
pUrlUnescapeA = (void *) GetProcAddress(hShlwapi, "UrlUnescapeA");
pUrlUnescapeW = (void *) GetProcAddress(hShlwapi, "UrlUnescapeW");
pUrlIsA = (void *) GetProcAddress(hShlwapi, "UrlIsA");