add some of the shlwapi tests

svn path=/trunk/; revision=17126
This commit is contained in:
Steven Edwards 2005-08-06 23:58:36 +00:00
parent bf046096f1
commit d8de9b24fb
10 changed files with 3280 additions and 0 deletions

View file

@ -0,0 +1,9 @@
Makefile
clist.ok
clsid.ok
generated.ok
ordinal.ok
path.ok
shreg.ok
string.ok
testlist.c

View file

@ -0,0 +1,643 @@
/* Unit test suite for SHLWAPI Compact List and IStream ordinal functions
*
* Copyright 2002 Jon Griffiths
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdarg.h>
#include "wine/test.h"
#include "windef.h"
#include "winbase.h"
#include "objbase.h"
typedef struct tagSHLWAPI_CLIST
{
ULONG ulSize;
ULONG ulId;
} SHLWAPI_CLIST, *LPSHLWAPI_CLIST;
typedef const SHLWAPI_CLIST* LPCSHLWAPI_CLIST;
/* Items to add */
static const SHLWAPI_CLIST SHLWAPI_CLIST_items[] =
{
{4, 1},
{8, 3},
{12, 2},
{16, 8},
{20, 9},
{3, 11},
{9, 82},
{33, 16},
{32, 55},
{24, 100},
{39, 116},
{ 0, 0}
};
/* Dummy IStream object for testing calls */
typedef struct
{
void* lpVtbl;
LONG ref;
int readcalls;
BOOL failreadcall;
BOOL failreadsize;
BOOL readbeyondend;
BOOL readreturnlarge;
int writecalls;
BOOL failwritecall;
BOOL failwritesize;
int seekcalls;
int statcalls;
BOOL failstatcall;
LPCSHLWAPI_CLIST item;
ULARGE_INTEGER pos;
} _IDummyStream;
static
HRESULT WINAPI QueryInterface(_IDummyStream *This,REFIID riid, LPVOID *ppvObj)
{
return S_OK;
}
static ULONG WINAPI AddRef(_IDummyStream *This)
{
return InterlockedIncrement(&This->ref);
}
static ULONG WINAPI Release(_IDummyStream *This)
{
return InterlockedDecrement(&This->ref);
}
static HRESULT WINAPI Read(_IDummyStream* This, LPVOID lpMem, ULONG ulSize,
PULONG lpRead)
{
HRESULT hRet = S_OK;
++This->readcalls;
if (This->failreadcall)
{
return STG_E_ACCESSDENIED;
}
else if (This->failreadsize)
{
*lpRead = ulSize + 8;
return S_OK;
}
else if (This->readreturnlarge)
{
*((ULONG*)lpMem) = 0xffff01;
*lpRead = ulSize;
This->readreturnlarge = FALSE;
return S_OK;
}
if (ulSize == sizeof(ULONG))
{
/* Read size of item */
*((ULONG*)lpMem) = This->item->ulSize ? This->item->ulSize + sizeof(SHLWAPI_CLIST) : 0;
*lpRead = ulSize;
}
else
{
unsigned int i;
char* buff = (char*)lpMem;
/* Read item data */
if (!This->item->ulSize)
{
This->readbeyondend = TRUE;
*lpRead = 0;
return E_FAIL; /* Should never happen */
}
*((ULONG*)lpMem) = This->item->ulId;
*lpRead = ulSize;
for (i = 0; i < This->item->ulSize; i++)
buff[4+i] = i*2;
This->item++;
}
return hRet;
}
static HRESULT WINAPI Write(_IDummyStream* This, LPVOID lpMem, ULONG ulSize,
PULONG lpWritten)
{
HRESULT hRet = S_OK;
++This->writecalls;
if (This->failwritecall)
{
return STG_E_ACCESSDENIED;
}
else if (This->failwritesize)
{
*lpWritten = 0;
}
else
*lpWritten = ulSize;
return hRet;
}
static HRESULT WINAPI Seek(_IDummyStream* This, LARGE_INTEGER dlibMove,
DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition)
{
++This->seekcalls;
This->pos.QuadPart = dlibMove.QuadPart;
if (plibNewPosition)
plibNewPosition->QuadPart = dlibMove.QuadPart;
return S_OK;
}
static HRESULT WINAPI Stat(_IDummyStream* This, STATSTG* pstatstg,
DWORD grfStatFlag)
{
++This->statcalls;
if (This->failstatcall)
return E_FAIL;
if (pstatstg)
pstatstg->cbSize.QuadPart = This->pos.QuadPart;
return S_OK;
}
/* VTable */
static void* iclvt[] =
{
QueryInterface,
AddRef,
Release,
Read,
Write,
Seek,
NULL, /* SetSize */
NULL, /* CopyTo */
NULL, /* Commit */
NULL, /* Revert */
NULL, /* LockRegion */
NULL, /* UnlockRegion */
Stat,
NULL /* Clone */
};
/* Function ptrs for ordinal calls */
static HMODULE SHLWAPI_hshlwapi = 0;
static VOID (WINAPI *pSHLWAPI_19)(LPSHLWAPI_CLIST);
static HRESULT (WINAPI *pSHLWAPI_20)(LPSHLWAPI_CLIST*,LPCSHLWAPI_CLIST);
static BOOL (WINAPI *pSHLWAPI_21)(LPSHLWAPI_CLIST*,ULONG);
static LPSHLWAPI_CLIST (WINAPI *pSHLWAPI_22)(LPSHLWAPI_CLIST,ULONG);
static HRESULT (WINAPI *pSHLWAPI_17)(_IDummyStream*,LPSHLWAPI_CLIST);
static HRESULT (WINAPI *pSHLWAPI_18)(_IDummyStream*,LPSHLWAPI_CLIST*);
static BOOL (WINAPI *pSHLWAPI_166)(_IDummyStream*);
static HRESULT (WINAPI *pSHLWAPI_184)(_IDummyStream*,LPVOID,ULONG);
static HRESULT (WINAPI *pSHLWAPI_212)(_IDummyStream*,LPCVOID,ULONG);
static HRESULT (WINAPI *pSHLWAPI_213)(_IDummyStream*);
static HRESULT (WINAPI *pSHLWAPI_214)(_IDummyStream*,ULARGE_INTEGER*);
static void InitFunctionPtrs(void)
{
SHLWAPI_hshlwapi = LoadLibraryA("shlwapi.dll");
ok(SHLWAPI_hshlwapi != 0, "LoadLibrary failed\n");
if (SHLWAPI_hshlwapi)
{
pSHLWAPI_17 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)17);
ok(pSHLWAPI_17 != 0, "No Ordinal 17\n");
pSHLWAPI_18 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)18);
ok(pSHLWAPI_18 != 0, "No Ordinal 18\n");
pSHLWAPI_19 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)19);
ok(pSHLWAPI_19 != 0, "No Ordinal 19\n");
pSHLWAPI_20 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)20);
ok(pSHLWAPI_20 != 0, "No Ordinal 20\n");
pSHLWAPI_21 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)21);
ok(pSHLWAPI_21 != 0, "No Ordinal 21\n");
pSHLWAPI_22 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)22);
ok(pSHLWAPI_22 != 0, "No Ordinal 22\n");
pSHLWAPI_166 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)166);
ok(pSHLWAPI_166 != 0, "No Ordinal 166\n");
pSHLWAPI_184 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)184);
ok(pSHLWAPI_184 != 0, "No Ordinal 184\n");
pSHLWAPI_212 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)212);
ok(pSHLWAPI_212 != 0, "No Ordinal 212\n");
pSHLWAPI_213 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)213);
ok(pSHLWAPI_213 != 0, "No Ordinal 213\n");
pSHLWAPI_214 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)214);
ok(pSHLWAPI_214 != 0, "No Ordinal 214\n");
}
}
static void InitDummyStream(_IDummyStream* iface)
{
iface->lpVtbl = (void*)iclvt;
iface->ref = 1;
iface->readcalls = 0;
iface->failreadcall = FALSE;
iface->failreadsize = FALSE;
iface->readbeyondend = FALSE;
iface->readreturnlarge = FALSE;
iface->writecalls = 0;
iface->failwritecall = FALSE;
iface->failwritesize = FALSE;
iface->seekcalls = 0;
iface->statcalls = 0;
iface->failstatcall = FALSE;
iface->item = SHLWAPI_CLIST_items;
iface->pos.QuadPart = 0;
}
static void test_CList(void)
{
_IDummyStream streamobj;
LPSHLWAPI_CLIST list = NULL;
LPCSHLWAPI_CLIST item = SHLWAPI_CLIST_items;
HRESULT hRet;
LPSHLWAPI_CLIST inserted;
BYTE buff[64];
unsigned int i;
if (!pSHLWAPI_17 || !pSHLWAPI_18 || !pSHLWAPI_19 || !pSHLWAPI_20 ||
!pSHLWAPI_21 || !pSHLWAPI_22)
return;
/* Populate a list and test the items are added correctly */
while (item->ulSize)
{
/* Create item and fill with data */
inserted = (LPSHLWAPI_CLIST)buff;
inserted->ulSize = item->ulSize + sizeof(SHLWAPI_CLIST);
inserted->ulId = item->ulId;
for (i = 0; i < item->ulSize; i++)
buff[sizeof(SHLWAPI_CLIST)+i] = i*2;
/* Add it */
hRet = pSHLWAPI_20(&list, inserted);
ok(hRet > S_OK, "failed list add\n");
if (hRet > S_OK)
{
ok(list && list->ulSize, "item not added\n");
/* Find it */
inserted = pSHLWAPI_22(list, item->ulId);
ok(inserted != NULL, "lost after adding\n");
ok(!inserted || inserted->ulId != ~0UL, "find returned a container\n");
/* Check size */
if (inserted && inserted->ulSize & 0x3)
{
/* Contained */
ok(inserted[-1].ulId == ~0UL, "invalid size is not countained\n");
ok(inserted[-1].ulSize > inserted->ulSize+sizeof(SHLWAPI_CLIST),
"container too small\n");
}
else if (inserted)
{
ok(inserted->ulSize==item->ulSize+sizeof(SHLWAPI_CLIST),
"id %ld size wrong (%ld!=%ld)\n", inserted->ulId, inserted->ulSize,
item->ulSize+sizeof(SHLWAPI_CLIST));
}
if (inserted)
{
BOOL bDataOK = TRUE;
LPBYTE bufftest = (LPBYTE)inserted;
for (i = 0; i < inserted->ulSize - sizeof(SHLWAPI_CLIST); i++)
if (bufftest[sizeof(SHLWAPI_CLIST)+i] != i*2)
bDataOK = FALSE;
ok(bDataOK == TRUE, "data corrupted on insert\n");
}
ok(!inserted || inserted->ulId==item->ulId, "find got wrong item\n");
}
item++;
}
/* Write the list */
InitDummyStream(&streamobj);
hRet = pSHLWAPI_17(&streamobj, list);
ok(hRet == S_OK, "write failed\n");
if (hRet == S_OK)
{
/* 1 call for each element, + 1 for OK (use our null element for this) */
ok(streamobj.writecalls == sizeof(SHLWAPI_CLIST_items)/sizeof(SHLWAPI_CLIST),
"wrong call count\n");
ok(streamobj.readcalls == 0,"called Read() in write\n");
ok(streamobj.seekcalls == 0,"called Seek() in write\n");
}
/* Failure cases for writing */
InitDummyStream(&streamobj);
streamobj.failwritecall = TRUE;
hRet = pSHLWAPI_17(&streamobj, list);
ok(hRet == STG_E_ACCESSDENIED, "changed object failure return\n");
ok(streamobj.writecalls == 1, "called object after failure\n");
ok(streamobj.readcalls == 0,"called Read() after failure\n");
ok(streamobj.seekcalls == 0,"called Seek() after failure\n");
InitDummyStream(&streamobj);
streamobj.failwritesize = TRUE;
hRet = pSHLWAPI_17(&streamobj, list);
ok(hRet == STG_E_MEDIUMFULL, "changed size failure return\n");
ok(streamobj.writecalls == 1, "called object after size failure\n");
ok(streamobj.readcalls == 0,"called Read() after failure\n");
ok(streamobj.seekcalls == 0,"called Seek() after failure\n");
/* Invalid inputs for adding */
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");
#endif
inserted = pSHLWAPI_22(list, 33);
ok(inserted == NULL, "inserted bad element size\n");
inserted = (LPSHLWAPI_CLIST)buff;
inserted->ulSize = 44;
inserted->ulId = ~0UL;
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");
#endif
item = SHLWAPI_CLIST_items;
/* Look for nonexistent item in populated list */
inserted = pSHLWAPI_22(list, 99999999);
ok(inserted == NULL, "found a nonexistent item\n");
while (item->ulSize)
{
/* Delete items */
BOOL bRet = pSHLWAPI_21(&list, item->ulId);
ok(bRet == TRUE, "couldn't find item to delete\n");
item++;
}
/* Look for nonexistent item in empty list */
inserted = pSHLWAPI_22(list, 99999999);
ok(inserted == NULL, "found an item in empty list\n");
/* Create a list by reading in data */
InitDummyStream(&streamobj);
hRet = pSHLWAPI_18(&streamobj, &list);
ok(hRet == S_OK, "failed create from Read()\n");
if (hRet == S_OK)
{
ok(streamobj.readbeyondend == FALSE, "read beyond end\n");
/* 2 calls per item, but only 1 for the terminator */
ok(streamobj.readcalls == sizeof(SHLWAPI_CLIST_items)/sizeof(SHLWAPI_CLIST)*2-1,
"wrong call count\n");
ok(streamobj.writecalls == 0, "called Write() from create\n");
ok(streamobj.seekcalls == 0,"called Seek() from create\n");
item = SHLWAPI_CLIST_items;
/* Check the items were added correctly */
while (item->ulSize)
{
inserted = pSHLWAPI_22(list, item->ulId);
ok(inserted != NULL, "lost after adding\n");
ok(!inserted || inserted->ulId != ~0UL, "find returned a container\n");
/* Check size */
if (inserted && inserted->ulSize & 0x3)
{
/* Contained */
ok(inserted[-1].ulId == ~0UL, "invalid size is not countained\n");
ok(inserted[-1].ulSize > inserted->ulSize+sizeof(SHLWAPI_CLIST),
"container too small\n");
}
else if (inserted)
{
ok(inserted->ulSize==item->ulSize+sizeof(SHLWAPI_CLIST),
"id %ld size wrong (%ld!=%ld)\n", inserted->ulId, inserted->ulSize,
item->ulSize+sizeof(SHLWAPI_CLIST));
}
ok(!inserted || inserted->ulId==item->ulId, "find got wrong item\n");
if (inserted)
{
BOOL bDataOK = TRUE;
LPBYTE bufftest = (LPBYTE)inserted;
for (i = 0; i < inserted->ulSize - sizeof(SHLWAPI_CLIST); i++)
if (bufftest[sizeof(SHLWAPI_CLIST)+i] != i*2)
bDataOK = FALSE;
ok(bDataOK == TRUE, "data corrupted on insert\n");
}
item++;
}
}
/* Failure cases for reading */
InitDummyStream(&streamobj);
streamobj.failreadcall = TRUE;
hRet = pSHLWAPI_18(&streamobj, &list);
ok(hRet == STG_E_ACCESSDENIED, "changed object failure return\n");
ok(streamobj.readbeyondend == FALSE, "read beyond end\n");
ok(streamobj.readcalls == 1, "called object after read failure\n");
ok(streamobj.writecalls == 0,"called Write() after read failure\n");
ok(streamobj.seekcalls == 0,"called Seek() after read failure\n");
/* Read returns large object */
InitDummyStream(&streamobj);
streamobj.readreturnlarge = TRUE;
hRet = pSHLWAPI_18(&streamobj, &list);
ok(hRet == S_OK, "failed create from Read() with large item\n");
ok(streamobj.readbeyondend == FALSE, "read beyond end\n");
ok(streamobj.readcalls == 1,"wrong call count\n");
ok(streamobj.writecalls == 0,"called Write() after read failure\n");
ok(streamobj.seekcalls == 2,"wrong Seek() call count (%d)\n", streamobj.seekcalls);
pSHLWAPI_19(list);
}
static BOOL test_SHLWAPI_166(void)
{
_IDummyStream streamobj;
BOOL bRet;
if (!pSHLWAPI_166)
return FALSE;
InitDummyStream(&streamobj);
bRet = pSHLWAPI_166(&streamobj);
if (bRet != TRUE)
return FALSE; /* This version doesn't support stream ops on clists */
ok(streamobj.readcalls == 0, "called Read()\n");
ok(streamobj.writecalls == 0, "called Write()\n");
ok(streamobj.seekcalls == 0, "called Seek()\n");
ok(streamobj.statcalls == 1, "wrong call count\n");
streamobj.statcalls = 0;
streamobj.pos.QuadPart = 50001;
bRet = pSHLWAPI_166(&streamobj);
ok(bRet == FALSE, "failed after seek adjusted\n");
ok(streamobj.readcalls == 0, "called Read()\n");
ok(streamobj.writecalls == 0, "called Write()\n");
ok(streamobj.seekcalls == 0, "called Seek()\n");
ok(streamobj.statcalls == 1, "wrong call count\n");
/* Failure cases */
InitDummyStream(&streamobj);
streamobj.pos.QuadPart = 50001;
streamobj.failstatcall = TRUE; /* 1: Stat() Bad, Read() OK */
bRet = pSHLWAPI_166(&streamobj);
ok(bRet == FALSE, "should be FALSE after read is OK\n");
ok(streamobj.readcalls == 1, "wrong call count\n");
ok(streamobj.writecalls == 0, "called Write()\n");
ok(streamobj.seekcalls == 1, "wrong call count\n");
ok(streamobj.statcalls == 1, "wrong call count\n");
ok(streamobj.pos.QuadPart == 0, "Didn't seek to start\n");
InitDummyStream(&streamobj);
streamobj.pos.QuadPart = 50001;
streamobj.failstatcall = TRUE;
streamobj.failreadcall = TRUE; /* 2: Stat() Bad, Read() Bad Also */
bRet = pSHLWAPI_166(&streamobj);
ok(bRet == TRUE, "Should be true after read fails\n");
ok(streamobj.readcalls == 1, "wrong call count\n");
ok(streamobj.writecalls == 0, "called Write()\n");
ok(streamobj.seekcalls == 0, "Called Seek()\n");
ok(streamobj.statcalls == 1, "wrong call count\n");
ok(streamobj.pos.QuadPart == 50001, "called Seek() after read failed\n");
return TRUE;
}
static void test_SHLWAPI_184(void)
{
_IDummyStream streamobj;
char buff[256];
HRESULT hRet;
if (!pSHLWAPI_184)
return;
InitDummyStream(&streamobj);
hRet = pSHLWAPI_184(&streamobj, buff, sizeof(buff));
ok(hRet == S_OK, "failed Read()\n");
ok(streamobj.readcalls == 1, "wrong call count\n");
ok(streamobj.writecalls == 0, "called Write()\n");
ok(streamobj.seekcalls == 0, "called Seek()\n");
}
static void test_SHLWAPI_212(void)
{
_IDummyStream streamobj;
char buff[256];
HRESULT hRet;
if (!pSHLWAPI_212)
return;
InitDummyStream(&streamobj);
hRet = pSHLWAPI_212(&streamobj, buff, sizeof(buff));
ok(hRet == S_OK, "failed Write()\n");
ok(streamobj.readcalls == 0, "called Read()\n");
ok(streamobj.writecalls == 1, "wrong call count\n");
ok(streamobj.seekcalls == 0, "called Seek()\n");
}
static void test_SHLWAPI_213(void)
{
_IDummyStream streamobj;
ULARGE_INTEGER ul;
LARGE_INTEGER ll;
HRESULT hRet;
if (!pSHLWAPI_213 || !pSHLWAPI_214)
return;
InitDummyStream(&streamobj);
ll.QuadPart = 5000l;
Seek(&streamobj, ll, 0, NULL); /* Seek to 5000l */
streamobj.seekcalls = 0;
pSHLWAPI_213(&streamobj); /* Should rewind */
ok(streamobj.statcalls == 0, "called Stat()\n");
ok(streamobj.readcalls == 0, "called Read()\n");
ok(streamobj.writecalls == 0, "called Write()\n");
ok(streamobj.seekcalls == 1, "wrong call count\n");
ul.QuadPart = 50001;
hRet = pSHLWAPI_214(&streamobj, &ul);
ok(hRet == S_OK, "failed Stat()\n");
ok(ul.QuadPart == 0, "213 didn't rewind stream\n");
}
static void test_SHLWAPI_214(void)
{
_IDummyStream streamobj;
ULARGE_INTEGER ul;
LARGE_INTEGER ll;
HRESULT hRet;
if (!pSHLWAPI_214)
return;
InitDummyStream(&streamobj);
ll.QuadPart = 5000l;
Seek(&streamobj, ll, 0, NULL);
ul.QuadPart = 0;
streamobj.seekcalls = 0;
hRet = pSHLWAPI_214(&streamobj, &ul);
ok(hRet == S_OK, "failed Stat()\n");
ok(streamobj.statcalls == 1, "wrong call count\n");
ok(streamobj.readcalls == 0, "called Read()\n");
ok(streamobj.writecalls == 0, "called Write()\n");
ok(streamobj.seekcalls == 0, "called Seek()\n");
ok(ul.QuadPart == 5000l, "Stat gave wrong size\n");
}
START_TEST(clist)
{
InitFunctionPtrs();
test_CList();
/* Test streaming if this version supports it */
if (test_SHLWAPI_166())
{
test_SHLWAPI_184();
test_SHLWAPI_212();
test_SHLWAPI_213();
test_SHLWAPI_214();
}
if (SHLWAPI_hshlwapi)
FreeLibrary(SHLWAPI_hshlwapi);
}

View file

@ -0,0 +1,171 @@
/* Unit test suite for SHLWAPI Class ID functions
*
* Copyright 2003 Jon Griffiths
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
#define INITGUID
#include "wine/test.h"
#include "winbase.h"
#include "winerror.h"
#include "winnls.h"
#include "winuser.h"
#include "shlguid.h"
#include "wine/shobjidl.h"
/* Function ptrs for ordinal calls */
static HMODULE hShlwapi = 0;
static BOOL (WINAPI *pSHLWAPI_269)(LPCSTR, CLSID *) = 0;
static DWORD (WINAPI *pSHLWAPI_23)(REFGUID, LPSTR, INT) = 0;
/* GUIDs to test */
const GUID * TEST_guids[] = {
&CLSID_ShellDesktop,
&CLSID_ShellLink,
&CATID_BrowsableShellExt,
&CATID_BrowseInPlace,
&CATID_DeskBand,
&CATID_InfoBand,
&CATID_CommBand,
&FMTID_Intshcut,
&FMTID_InternetSite,
&CGID_Explorer,
&CGID_ShellDocView,
&CGID_ShellServiceObject,
&CGID_ExplorerBarDoc,
&IID_INewShortcutHookA,
&IID_IShellIcon,
&IID_IShellFolder,
&IID_IShellExtInit,
&IID_IShellPropSheetExt,
&IID_IPersistFolder,
&IID_IExtractIconA,
&IID_IShellDetails,
&IID_IDelayedRelease,
&IID_IShellLinkA,
&IID_IShellCopyHookA,
&IID_IFileViewerA,
&IID_ICommDlgBrowser,
&IID_IEnumIDList,
&IID_IFileViewerSite,
&IID_IContextMenu2,
&IID_IShellExecuteHookA,
&IID_IPropSheetPage,
&IID_INewShortcutHookW,
&IID_IFileViewerW,
&IID_IShellLinkW,
&IID_IExtractIconW,
&IID_IShellExecuteHookW,
&IID_IShellCopyHookW,
&IID_IRemoteComputer,
&IID_IQueryInfo,
&IID_IDockingWindow,
&IID_IDockingWindowSite,
&CLSID_NetworkPlaces,
&CLSID_NetworkDomain,
&CLSID_NetworkServer,
&CLSID_NetworkShare,
&CLSID_MyComputer,
&CLSID_Internet,
&CLSID_ShellFSFolder,
&CLSID_RecycleBin,
&CLSID_ControlPanel,
&CLSID_Printers,
&CLSID_MyDocuments,
NULL
};
DEFINE_GUID(IID_Endianess, 0x01020304, 0x0506, 0x0708, 0x09, 0x0A, 0x0B,
0x0C, 0x0D, 0x0E, 0x0F, 0x0A);
static void test_ClassIDs(void)
{
const GUID **guids = TEST_guids;
char szBuff[256];
GUID guid;
DWORD dwLen;
BOOL bRet;
int i = 0;
if (!pSHLWAPI_269 || !pSHLWAPI_23)
return;
while (*guids)
{
dwLen = pSHLWAPI_23(*guids, szBuff, 256);
ok(dwLen == 39, "wrong size for id %d\n", i);
bRet = pSHLWAPI_269(szBuff, &guid);
ok(bRet != FALSE, "created invalid string '%s'\n", szBuff);
if (bRet)
ok(IsEqualGUID(*guids, &guid), "GUID created wrong %d\n", i);
guids++;
i++;
}
/* Test endianess */
dwLen = pSHLWAPI_23(&IID_Endianess, szBuff, 256);
ok(dwLen == 39, "wrong size for IID_Endianess\n");
ok(!strcmp(szBuff, "{01020304-0506-0708-090A-0B0C0D0E0F0A}"),
"Endianess Broken, got '%s'\n", szBuff);
/* test lengths */
szBuff[0] = ':';
dwLen = pSHLWAPI_23(&IID_Endianess, szBuff, 0);
ok(dwLen == 0, "accepted bad length\n");
ok(szBuff[0] == ':', "wrote to buffer with no length\n");
szBuff[0] = ':';
dwLen = pSHLWAPI_23(&IID_Endianess, szBuff, 38);
ok(dwLen == 0, "accepted bad length\n");
ok(szBuff[0] == ':', "wrote to buffer with no length\n");
szBuff[0] = ':';
dwLen = pSHLWAPI_23(&IID_Endianess, szBuff, 39);
ok(dwLen == 39, "rejected ok length\n");
ok(szBuff[0] == '{', "Didn't write to buffer with ok length\n");
/* Test string */
strcpy(szBuff, "{xxx-");
bRet = pSHLWAPI_269(szBuff, &guid);
ok(bRet == FALSE, "accepted invalid string\n");
dwLen = pSHLWAPI_23(&IID_Endianess, szBuff, 39);
ok(dwLen == 39, "rejected ok length\n");
ok(szBuff[0] == '{', "Didn't write to buffer with ok length\n");
}
START_TEST(clsid)
{
hShlwapi = LoadLibraryA("shlwapi.dll");
ok(hShlwapi != 0, "LoadLibraryA failed\n");
if (hShlwapi)
{
pSHLWAPI_269 = (void*)GetProcAddress(hShlwapi, (LPSTR)269);
pSHLWAPI_23 = (void*)GetProcAddress(hShlwapi, (LPSTR)23);
}
test_ClassIDs();
if (hShlwapi)
FreeLibrary(hShlwapi);
}

View file

@ -0,0 +1,186 @@
/* File generated automatically from tools/winapi/test.dat; do not edit! */
/* This file can be copied, modified and distributed without restriction. */
/*
* Unit tests for data structure packing
*/
#define WINVER 0x0501
#define _WIN32_IE 0x0501
#define _WIN32_WINNT 0x0501
#define WINE_NOWINSOCK
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "wtypes.h"
#include "winreg.h"
#include "shlwapi.h"
#include "wine/test.h"
/***********************************************************************
* Compability macros
*/
#define DWORD_PTR UINT_PTR
#define LONG_PTR INT_PTR
#define ULONG_PTR UINT_PTR
/***********************************************************************
* Windows API extension
*/
#if defined(_MSC_VER) && (_MSC_VER >= 1300) && defined(__cplusplus)
# define FIELD_ALIGNMENT(type, field) __alignof(((type*)0)->field)
#elif defined(__GNUC__)
# define FIELD_ALIGNMENT(type, field) __alignof__(((type*)0)->field)
#else
/* FIXME: Not sure if is possible to do without compiler extension */
#endif
#if defined(_MSC_VER) && (_MSC_VER >= 1300) && defined(__cplusplus)
# define _TYPE_ALIGNMENT(type) __alignof(type)
#elif defined(__GNUC__)
# define _TYPE_ALIGNMENT(type) __alignof__(type)
#else
/*
* FIXME: Not sure if is possible to do without compiler extension
* (if type is not just a name that is, if so the normal)
* TYPE_ALIGNMENT can be used)
*/
#endif
#if defined(TYPE_ALIGNMENT) && defined(_MSC_VER) && _MSC_VER >= 800 && !defined(__cplusplus)
#pragma warning(disable:4116)
#endif
#if !defined(TYPE_ALIGNMENT) && defined(_TYPE_ALIGNMENT)
# define TYPE_ALIGNMENT _TYPE_ALIGNMENT
#endif
/***********************************************************************
* Test helper macros
*/
#ifdef FIELD_ALIGNMENT
# define TEST_FIELD_ALIGNMENT(type, field, align) \
ok(FIELD_ALIGNMENT(type, field) == align, \
"FIELD_ALIGNMENT(" #type ", " #field ") == %d (expected " #align ")\n", \
(int)FIELD_ALIGNMENT(type, field))
#else
# define TEST_FIELD_ALIGNMENT(type, field, align) do { } while (0)
#endif
#define TEST_FIELD_OFFSET(type, field, offset) \
ok(FIELD_OFFSET(type, field) == offset, \
"FIELD_OFFSET(" #type ", " #field ") == %ld (expected " #offset ")\n", \
(long int)FIELD_OFFSET(type, field))
#ifdef _TYPE_ALIGNMENT
#define TEST__TYPE_ALIGNMENT(type, align) \
ok(_TYPE_ALIGNMENT(type) == align, "TYPE_ALIGNMENT(" #type ") == %d (expected " #align ")\n", (int)_TYPE_ALIGNMENT(type))
#else
# define TEST__TYPE_ALIGNMENT(type, align) do { } while (0)
#endif
#ifdef TYPE_ALIGNMENT
#define TEST_TYPE_ALIGNMENT(type, align) \
ok(TYPE_ALIGNMENT(type) == align, "TYPE_ALIGNMENT(" #type ") == %d (expected " #align ")\n", (int)TYPE_ALIGNMENT(type))
#else
# define TEST_TYPE_ALIGNMENT(type, align) do { } while (0)
#endif
#define TEST_TYPE_SIZE(type, size) \
ok(sizeof(type) == size, "sizeof(" #type ") == %d (expected " #size ")\n", ((int) sizeof(type)))
/***********************************************************************
* Test macros
*/
#define TEST_FIELD(type, field_type, field_name, field_offset, field_size, field_align) \
TEST_TYPE_SIZE(field_type, field_size); \
TEST_FIELD_ALIGNMENT(type, field_name, field_align); \
TEST_FIELD_OFFSET(type, field_name, field_offset); \
#define TEST_TYPE(type, size, align) \
TEST_TYPE_ALIGNMENT(type, align); \
TEST_TYPE_SIZE(type, size)
#define TEST_TYPE_POINTER(type, size, align) \
TEST__TYPE_ALIGNMENT(*(type)0, align); \
TEST_TYPE_SIZE(*(type)0, size)
#define TEST_TYPE_SIGNED(type) \
ok((type) -1 < 0, "(" #type ") -1 < 0\n");
#define TEST_TYPE_UNSIGNED(type) \
ok((type) -1 > 0, "(" #type ") -1 > 0\n");
static void test_pack_ASSOCF(void)
{
/* ASSOCF */
TEST_TYPE(ASSOCF, 4, 4);
TEST_TYPE_UNSIGNED(ASSOCF);
}
static void test_pack_DLLGETVERSIONPROC(void)
{
/* DLLGETVERSIONPROC */
TEST_TYPE(DLLGETVERSIONPROC, 4, 4);
}
static void test_pack_DLLVERSIONINFO(void)
{
/* DLLVERSIONINFO (pack 8) */
TEST_TYPE(DLLVERSIONINFO, 20, 4);
TEST_FIELD(DLLVERSIONINFO, DWORD, cbSize, 0, 4, 4);
TEST_FIELD(DLLVERSIONINFO, DWORD, dwMajorVersion, 4, 4, 4);
TEST_FIELD(DLLVERSIONINFO, DWORD, dwMinorVersion, 8, 4, 4);
TEST_FIELD(DLLVERSIONINFO, DWORD, dwBuildNumber, 12, 4, 4);
TEST_FIELD(DLLVERSIONINFO, DWORD, dwPlatformID, 16, 4, 4);
}
static void test_pack_DLLVERSIONINFO2(void)
{
/* DLLVERSIONINFO2 (pack 8) */
TEST_TYPE(DLLVERSIONINFO2, 32, 8);
TEST_FIELD(DLLVERSIONINFO2, DLLVERSIONINFO, info1, 0, 20, 4);
TEST_FIELD(DLLVERSIONINFO2, DWORD, dwFlags, 20, 4, 4);
TEST_FIELD(DLLVERSIONINFO2, ULONGLONG, ullVersion, 24, 8, 8);
}
static void test_pack_HUSKEY(void)
{
/* HUSKEY */
TEST_TYPE(HUSKEY, 4, 4);
}
static void test_pack_IQueryAssociations(void)
{
/* IQueryAssociations */
}
static void test_pack_PHUSKEY(void)
{
/* PHUSKEY */
TEST_TYPE(PHUSKEY, 4, 4);
TEST_TYPE_POINTER(PHUSKEY, 4, 4);
}
static void test_pack(void)
{
test_pack_ASSOCF();
test_pack_DLLGETVERSIONPROC();
test_pack_DLLVERSIONINFO();
test_pack_DLLVERSIONINFO2();
test_pack_HUSKEY();
test_pack_IQueryAssociations();
test_pack_PHUSKEY();
}
START_TEST(generated)
{
test_pack();
}

View file

@ -0,0 +1,248 @@
/* Unit test suite for SHLWAPI ordinal functions
*
* Copyright 2004 Jon Griffiths
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
#include "wine/test.h"
#include "winbase.h"
#include "winerror.h"
#include "winuser.h"
/* Function ptrs for ordinal calls */
static HMODULE hShlwapi;
static int (WINAPI *pSHSearchMapInt)(const int*,const int*,int,int);
static HRESULT (WINAPI *pGetAcceptLanguagesA)(LPSTR,LPDWORD);
static HANDLE (WINAPI *pSHAllocShared)(LPCVOID,DWORD,DWORD);
static LPVOID (WINAPI *pSHLockShared)(HANDLE,DWORD);
static BOOL (WINAPI *pSHUnlockShared)(LPVOID);
static BOOL (WINAPI *pSHFreeShared)(HANDLE,DWORD);
static void test_GetAcceptLanguagesA(void)
{ HRESULT retval;
DWORD buffersize, buffersize2, exactsize;
char buffer[100];
if (!pGetAcceptLanguagesA)
return;
buffersize = sizeof(buffer);
memset(buffer, 0, sizeof(buffer));
SetLastError(ERROR_SUCCESS);
retval = pGetAcceptLanguagesA( buffer, &buffersize);
trace("GetAcceptLanguagesA: retval %08lx, size %08lx, buffer (%s),"
" last error %ld\n", retval, buffersize, buffer, GetLastError());
if(retval != S_OK) {
trace("GetAcceptLanguagesA: skipping tests\n");
return;
}
ok( (ERROR_NO_IMPERSONATION_TOKEN == GetLastError()) ||
(ERROR_CLASS_DOES_NOT_EXIST == GetLastError()) ||
(ERROR_PROC_NOT_FOUND == GetLastError()) ||
(ERROR_CALL_NOT_IMPLEMENTED == GetLastError()) ||
(ERROR_SUCCESS == GetLastError()), "last error set to %ld\n", GetLastError());
exactsize = strlen(buffer);
SetLastError(ERROR_SUCCESS);
retval = pGetAcceptLanguagesA( NULL, NULL);
ok(retval == E_FAIL,
"function result wrong: got %08lx; expected E_FAIL\n", retval);
ok(ERROR_SUCCESS == GetLastError(), "last error set to %ld\n", GetLastError());
buffersize = sizeof(buffer);
SetLastError(ERROR_SUCCESS);
retval = pGetAcceptLanguagesA( NULL, &buffersize);
ok(retval == E_FAIL,
"function result wrong: got %08lx; expected E_FAIL\n", retval);
ok(buffersize == sizeof(buffer),
"buffersize was changed (2nd parameter; not on Win2k)\n");
ok(ERROR_SUCCESS == GetLastError(), "last error set to %ld\n", GetLastError());
SetLastError(ERROR_SUCCESS);
retval = pGetAcceptLanguagesA( buffer, NULL);
ok(retval == E_FAIL,
"function result wrong: got %08lx; expected E_FAIL\n", retval);
ok(ERROR_SUCCESS == GetLastError(), "last error set to %ld\n", GetLastError());
buffersize = 0;
memset(buffer, 0, sizeof(buffer));
SetLastError(ERROR_SUCCESS);
retval = pGetAcceptLanguagesA( buffer, &buffersize);
ok(retval == E_FAIL,
"function result wrong: got %08lx; expected E_FAIL\n", retval);
ok(buffersize == 0,
"buffersize wrong(changed) got %08lx; expected 0 (2nd parameter; not on Win2k)\n", buffersize);
ok(ERROR_SUCCESS == GetLastError(), "last error set to %ld\n", GetLastError());
buffersize = buffersize2 = 1;
memset(buffer, 0, sizeof(buffer));
SetLastError(ERROR_SUCCESS);
retval = pGetAcceptLanguagesA( buffer, &buffersize);
switch(retval) {
case 0L:
if(buffersize == exactsize) {
ok( (ERROR_SUCCESS == GetLastError()) || (ERROR_CALL_NOT_IMPLEMENTED == GetLastError()) ||
(ERROR_PROC_NOT_FOUND == GetLastError()) || (ERROR_NO_IMPERSONATION_TOKEN == GetLastError()),
"last error wrong: got %08lx; expected ERROR_SUCCESS(NT4)/ERROR_CALL_NOT_IMPLEMENTED(98/ME)/"
"ERROR_PROC_NOT_FOUND(NT4)/ERROR_NO_IMPERSONATION_TOKEN(XP)\n", GetLastError());
ok(exactsize == strlen(buffer),
"buffer content (length) wrong: got %08x, expected %08lx \n", strlen(buffer), exactsize);
} else if((buffersize +1) == buffersize2) {
ok(ERROR_SUCCESS == GetLastError(),
"last error wrong: got %08lx; expected ERROR_SUCCESS\n", GetLastError());
ok(buffersize == strlen(buffer),
"buffer content (length) wrong: got %08x, expected %08lx \n", strlen(buffer), buffersize);
} else
ok( 0, "retval %08lx, size %08lx, buffer (%s), last error %ld\n",
retval, buffersize, buffer, GetLastError());
break;
case E_INVALIDARG:
ok(buffersize == 0,
"buffersize wrong: got %08lx, expected 0 (2nd parameter;Win2k)\n", buffersize);
ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(),
"last error wrong: got %08lx; expected ERROR_INSUFFICIENT_BUFFER\n", GetLastError());
ok(buffersize2 == strlen(buffer),
"buffer content (length) wrong: got %08x, expected %08lx \n", strlen(buffer), buffersize2);
break;
default:
ok( 0, "retval %08lx, size %08lx, buffer (%s), last error %ld\n",
retval, buffersize, buffer, GetLastError());
break;
}
buffersize = buffersize2 = exactsize;
memset(buffer, 0, sizeof(buffer));
SetLastError(ERROR_SUCCESS);
retval = pGetAcceptLanguagesA( buffer, &buffersize);
switch(retval) {
case 0L:
ok(ERROR_SUCCESS == GetLastError(),
"last error wrong: got %08lx; expected ERROR_SUCCESS\n", GetLastError());
if((buffersize == exactsize) /* XP */ ||
((buffersize +1)== exactsize) /* 98 */)
ok(buffersize == strlen(buffer),
"buffer content (length) wrong: got %08x, expected %08lx \n", strlen(buffer), buffersize);
else
ok( 0, "retval %08lx, size %08lx, buffer (%s), last error %ld\n",
retval, buffersize, buffer, GetLastError());
break;
case E_INVALIDARG:
ok(buffersize == 0,
"buffersize wrong: got %08lx, expected 0 (2nd parameter;Win2k)\n", buffersize);
ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(),
"last error wrong: got %08lx; expected ERROR_INSUFFICIENT_BUFFER\n", GetLastError());
ok(buffersize2 == strlen(buffer),
"buffer content (length) wrong: got %08x, expected %08lx \n", strlen(buffer), buffersize2);
break;
default:
ok( 0, "retval %08lx, size %08lx, buffer (%s), last error %ld\n",
retval, buffersize, buffer, GetLastError());
break;
}
}
static void test_SHSearchMapInt(void)
{
int keys[8], values[8];
int i = 0;
if (!pSHSearchMapInt)
return;
memset(keys, 0, sizeof(keys));
memset(values, 0, sizeof(values));
keys[0] = 99; values[0] = 101;
/* NULL key/value lists crash native, so skip testing them */
/* 1 element */
i = pSHSearchMapInt(keys, values, 1, keys[0]);
ok(i == values[0], "Len 1, expected %d, got %d\n", values[0], i);
/* Key doesn't exist */
i = pSHSearchMapInt(keys, values, 1, 100);
ok(i == -1, "Len 1 - bad key, expected -1, got %d\n", i);
/* Len = 0 => not found */
i = pSHSearchMapInt(keys, values, 0, keys[0]);
ok(i == -1, "Len 1 - passed len 0, expected -1, got %d\n", i);
/* 2 elements, len = 1 */
keys[1] = 98; values[1] = 102;
i = pSHSearchMapInt(keys, values, 1, keys[1]);
ok(i == -1, "Len 1 - array len 2, expected -1, got %d\n", i);
/* 2 elements, len = 2 */
i = pSHSearchMapInt(keys, values, 2, keys[1]);
ok(i == values[1], "Len 2, expected %d, got %d\n", values[1], i);
/* Searches forward */
keys[2] = 99; values[2] = 103;
i = pSHSearchMapInt(keys, values, 3, keys[0]);
ok(i == values[0], "Len 3, expected %d, got %d\n", values[0], i);
}
static void test_alloc_shared(void)
{
DWORD procid;
HANDLE hmem;
int val;
int* p;
BOOL ret;
procid=GetCurrentProcessId();
hmem=pSHAllocShared(NULL,10,procid);
ok(hmem!=NULL,"SHAllocShared(NULL...) failed: %ld\n", GetLastError());
ret = pSHFreeShared(hmem, procid);
ok( ret, "SHFreeShared failed: %ld\n", GetLastError());
val=0x12345678;
hmem=pSHAllocShared(&val,4,procid);
ok(hmem!=NULL,"SHAllocShared(NULL...) failed: %ld\n", GetLastError());
p=(int*)pSHLockShared(hmem,procid);
ok(p!=NULL,"SHLockShared failed: %ld\n", GetLastError());
if (p!=NULL)
ok(*p==val,"Wrong value in shared memory: %d instead of %d\n",*p,val);
ret = pSHUnlockShared(p);
ok( ret, "SHUnlockShared failed: %ld\n", GetLastError());
ret = pSHFreeShared(hmem, procid);
ok( ret, "SHFreeShared failed: %ld\n", GetLastError());
}
START_TEST(ordinal)
{
hShlwapi = LoadLibraryA("shlwapi.dll");
ok(hShlwapi != 0, "LoadLibraryA failed\n");
if (!hShlwapi)
return;
pGetAcceptLanguagesA = (void*)GetProcAddress(hShlwapi, (LPSTR)14);
pSHSearchMapInt = (void*)GetProcAddress(hShlwapi, (LPSTR)198);
pSHAllocShared=(void*)GetProcAddress(hShlwapi,(char*)7);
pSHLockShared=(void*)GetProcAddress(hShlwapi,(char*)8);
pSHUnlockShared=(void*)GetProcAddress(hShlwapi,(char*)9);
pSHFreeShared=(void*)GetProcAddress(hShlwapi,(char*)10);
test_GetAcceptLanguagesA();
test_SHSearchMapInt();
test_alloc_shared();
FreeLibrary(hShlwapi);
}

View file

@ -0,0 +1,833 @@
/* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include "wine/test.h"
#include "windef.h"
#include "winbase.h"
#include "wine/unicode.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);
const char* TEST_URL_1 = "http://www.winehq.org/tests?date=10/10/1923";
const char* TEST_URL_2 = "http://localhost:8080/tests%2e.html?date=Mon%2010/10/1923";
const char* TEST_URL_3 = "http://foo:bar@localhost:21/internal.php?query=x&return=y";
typedef struct _TEST_URL_CANONICALIZE {
const char *url;
DWORD flags;
HRESULT expectret;
const char *expecturl;
} TEST_URL_CANONICALIZE;
const TEST_URL_CANONICALIZE TEST_CANONICALIZE[] = {
/*FIXME {"http://www.winehq.org/tests/../tests/../..", 0, S_OK, "http://www.winehq.org/"},*/
{"http://www.winehq.org/tests/../tests", 0, S_OK, "http://www.winehq.org/tests"},
{"http://www.winehq.org/tests\n", URL_WININET_COMPATIBILITY|URL_ESCAPE_SPACES_ONLY|URL_ESCAPE_UNSAFE, S_OK, "http://www.winehq.org/tests"},
{"http://www.winehq.org/tests\r", URL_WININET_COMPATIBILITY|URL_ESCAPE_SPACES_ONLY|URL_ESCAPE_UNSAFE, S_OK, "http://www.winehq.org/tests"},
{"http://www.winehq.org/tests\r", 0, S_OK, "http://www.winehq.org/tests"},
{"http://www.winehq.org/tests\r", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests"},
{"http://www.winehq.org/tests/../tests/", 0, S_OK, "http://www.winehq.org/tests/"},
{"http://www.winehq.org/tests/../tests/..", 0, S_OK, "http://www.winehq.org/"},
{"http://www.winehq.org/tests/../tests/../", 0, S_OK, "http://www.winehq.org/"},
{"http://www.winehq.org/tests/..", 0, S_OK, "http://www.winehq.org/"},
{"http://www.winehq.org/tests/../", 0, S_OK, "http://www.winehq.org/"},
{"http://www.winehq.org/tests/..?query=x&return=y", 0, S_OK, "http://www.winehq.org/?query=x&return=y"},
{"http://www.winehq.org/tests/../?query=x&return=y", 0, S_OK, "http://www.winehq.org/?query=x&return=y"},
{"http://www.winehq.org/tests/..#example", 0, S_OK, "http://www.winehq.org/#example"},
{"http://www.winehq.org/tests/../#example", 0, S_OK, "http://www.winehq.org/#example"},
{"http://www.winehq.org/tests/../#example", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests/../#example"},
{"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"},
{"http://www.winehq.org/tests/foo%20bar", URL_UNESCAPE , S_OK, "http://www.winehq.org/tests/foo bar"},
{"file:///c:/tests/foo%20bar", URL_UNESCAPE , S_OK, "file:///c:/tests/foo bar"},
};
typedef struct _TEST_URL_ESCAPE {
const char *url;
DWORD flags;
DWORD expectescaped;
HRESULT expectret;
const char *expecturl;
} TEST_URL_ESCAPE;
const TEST_URL_ESCAPE TEST_ESCAPE[] = {
{"http://www.winehq.org/tests0", 0, 0, S_OK, "http://www.winehq.org/tests0"},
{"http://www.winehq.org/tests1\n", 0, 0, S_OK, "http://www.winehq.org/tests1%0A"},
{"http://www.winehq.org/tests2\r", 0, 0, S_OK, "http://www.winehq.org/tests2%0D"},
{"http://www.winehq.org/tests3\r", URL_ESCAPE_SPACES_ONLY|URL_ESCAPE_UNSAFE, 0, S_OK, "http://www.winehq.org/tests3\r"},
{"http://www.winehq.org/tests4\r", URL_ESCAPE_SPACES_ONLY, 0, S_OK, "http://www.winehq.org/tests4\r"},
{"http://www.winehq.org/tests5\r", URL_WININET_COMPATIBILITY|URL_ESCAPE_SPACES_ONLY, 0, S_OK, "http://www.winehq.org/tests5\r"},
{"/direct/swhelp/series6/6.2i_latestservicepack.dat\r", URL_ESCAPE_SPACES_ONLY, 0, S_OK, "/direct/swhelp/series6/6.2i_latestservicepack.dat\r"},
{"file://////foo/bar\\baz", 0, 0, S_OK, "file://foo/bar/baz"},
{"file://///foo/bar\\baz", 0, 0, S_OK, "file://foo/bar/baz"},
{"file:////foo/bar\\baz", 0, 0, S_OK, "file://foo/bar/baz"},
{"file:///localhost/foo/bar\\baz", 0, 0, S_OK, "file:///localhost/foo/bar/baz"},
{"file:///foo/bar\\baz", 0, 0, S_OK, "file:///foo/bar/baz"},
{"file://loCalHost/foo/bar\\baz", 0, 0, S_OK, "file:///foo/bar/baz"},
{"file://foo/bar\\baz", 0, 0, S_OK, "file://foo/bar/baz"},
{"file:/localhost/foo/bar\\baz", 0, 0, S_OK, "file:///localhost/foo/bar/baz"},
{"file:/foo/bar\\baz", 0, 0, S_OK, "file:///foo/bar/baz"},
{"file:foo/bar\\baz", 0, 0, S_OK, "file:foo/bar/baz"},
{"file:\\foo/bar\\baz", 0, 0, S_OK, "file:///foo/bar/baz"},
{"file:\\\\foo/bar\\baz", 0, 0, S_OK, "file://foo/bar/baz"},
{"file:\\\\\\foo/bar\\baz", 0, 0, S_OK, "file:///foo/bar/baz"},
{"file:\\\\localhost\\foo/bar\\baz", 0, 0, S_OK, "file:///foo/bar/baz"},
{"file:///f oo/b?a r\\baz", 0, 0, S_OK, "file:///f%20oo/b?a r\\baz"},
{"file:///foo/b#a r\\baz", 0, 0, S_OK, "file:///foo/b%23a%20r/baz"},
{"file:///f o^&`{}|][\"<>\\%o/b#a r\\baz", 0, 0, S_OK, "file:///f%20o%5E%26%60%7B%7D%7C%5D%5B%22%3C%3E/%o/b%23a%20r/baz"},
{"file:///f o%o/b?a r\\b%az", URL_ESCAPE_PERCENT, 0, S_OK, "file:///f%20o%25o/b?a r\\b%az"},
{"file:/foo/bar\\baz", URL_ESCAPE_SEGMENT_ONLY, 0, S_OK, "file:%2Ffoo%2Fbar%5Cbaz"},
{"foo/b%ar\\ba?z\\", URL_ESCAPE_SEGMENT_ONLY, 0, S_OK, "foo%2Fb%ar%5Cba%3Fz%5C"},
{"foo/b%ar\\ba?z\\", URL_ESCAPE_PERCENT | URL_ESCAPE_SEGMENT_ONLY, 0, S_OK, "foo%2Fb%25ar%5Cba%3Fz%5C"},
{"foo/bar\\ba?z\\", 0, 0, S_OK, "foo/bar%5Cba?z\\"},
{"/foo/bar\\ba?z\\", 0, 0, S_OK, "/foo/bar%5Cba?z\\"},
{"/foo/bar\\ba#z\\", 0, 0, S_OK, "/foo/bar%5Cba#z\\"},
{"/foo/%5C", 0, 0, S_OK, "/foo/%5C"},
{"/foo/%5C", URL_ESCAPE_PERCENT, 0, S_OK, "/foo/%255C"},
{"http://////foo/bar\\baz", 0, 0, S_OK, "http://////foo/bar/baz"},
{"http://///foo/bar\\baz", 0, 0, S_OK, "http://///foo/bar/baz"},
{"http:////foo/bar\\baz", 0, 0, S_OK, "http:////foo/bar/baz"},
{"http:///foo/bar\\baz", 0, 0, S_OK, "http:///foo/bar/baz"},
{"http://localhost/foo/bar\\baz", 0, 0, S_OK, "http://localhost/foo/bar/baz"},
{"http://foo/bar\\baz", 0, 0, S_OK, "http://foo/bar/baz"},
{"http:/foo/bar\\baz", 0, 0, S_OK, "http:/foo/bar/baz"},
{"http:foo/bar\\ba?z\\", 0, 0, S_OK, "http:foo%2Fbar%2Fba?z\\"},
{"http:foo/bar\\ba#z\\", 0, 0, S_OK, "http:foo%2Fbar%2Fba#z\\"},
{"http:\\foo/bar\\baz", 0, 0, S_OK, "http:/foo/bar/baz"},
{"http:\\\\foo/bar\\baz", 0, 0, S_OK, "http://foo/bar/baz"},
{"http:\\\\\\foo/bar\\baz", 0, 0, S_OK, "http:///foo/bar/baz"},
{"http:\\\\\\\\foo/bar\\baz", 0, 0, S_OK, "http:////foo/bar/baz"},
{"http:/fo ?o/b ar\\baz", 0, 0, S_OK, "http:/fo%20?o/b ar\\baz"},
{"http:fo ?o/b ar\\baz", 0, 0, S_OK, "http:fo%20?o/b ar\\baz"},
{"http:/foo/bar\\baz", URL_ESCAPE_SEGMENT_ONLY, 0, S_OK, "http:%2Ffoo%2Fbar%5Cbaz"},
{"https://foo/bar\\baz", 0, 0, S_OK, "https://foo/bar/baz"},
{"https:/foo/bar\\baz", 0, 0, S_OK, "https:/foo/bar/baz"},
{"https:\\foo/bar\\baz", 0, 0, S_OK, "https:/foo/bar/baz"},
{"foo:////foo/bar\\baz", 0, 0, S_OK, "foo:////foo/bar%5Cbaz"},
{"foo:///foo/bar\\baz", 0, 0, S_OK, "foo:///foo/bar%5Cbaz"},
{"foo://localhost/foo/bar\\baz", 0, 0, S_OK, "foo://localhost/foo/bar%5Cbaz"},
{"foo://foo/bar\\baz", 0, 0, S_OK, "foo://foo/bar%5Cbaz"},
{"foo:/foo/bar\\baz", 0, 0, S_OK, "foo:/foo/bar%5Cbaz"},
{"foo:foo/bar\\baz", 0, 0, S_OK, "foo:foo%2Fbar%5Cbaz"},
{"foo:\\foo/bar\\baz", 0, 0, S_OK, "foo:%5Cfoo%2Fbar%5Cbaz"},
{"foo:/foo/bar\\ba?\\z", 0, 0, S_OK, "foo:/foo/bar%5Cba?\\z"},
{"foo:/foo/bar\\ba#\\z", 0, 0, S_OK, "foo:/foo/bar%5Cba#\\z"},
{"mailto:/fo/o@b\\%a?\\r.b#\\az", 0, 0, S_OK, "mailto:%2Ffo%2Fo@b%5C%a%3F%5Cr.b%23%5Caz"},
{"mailto:fo/o@b\\%a?\\r.b#\\az", 0, 0, S_OK, "mailto:fo%2Fo@b%5C%a%3F%5Cr.b%23%5Caz"},
{"mailto:fo/o@b\\%a?\\r.b#\\az", URL_ESCAPE_PERCENT, 0, S_OK, "mailto:fo%2Fo@b%5C%25a%3F%5Cr.b%23%5Caz"},
{"ftp:fo/o@bar.baz/foo/bar", 0, 0, S_OK, "ftp:fo%2Fo@bar.baz%2Ffoo%2Fbar"},
{"ftp:/fo/o@bar.baz/foo/bar", 0, 0, S_OK, "ftp:/fo/o@bar.baz/foo/bar"},
{"ftp://fo/o@bar.baz/fo?o\\bar", 0, 0, S_OK, "ftp://fo/o@bar.baz/fo?o\\bar"},
{"ftp://fo/o@bar.baz/fo#o\\bar", 0, 0, S_OK, "ftp://fo/o@bar.baz/fo#o\\bar"},
{"ftp://localhost/o@bar.baz/fo#o\\bar", 0, 0, S_OK, "ftp://localhost/o@bar.baz/fo#o\\bar"},
{"ftp:///fo/o@bar.baz/foo/bar", 0, 0, S_OK, "ftp:///fo/o@bar.baz/foo/bar"},
{"ftp:////fo/o@bar.baz/foo/bar", 0, 0, S_OK, "ftp:////fo/o@bar.baz/foo/bar"}
};
typedef struct _TEST_URL_COMBINE {
const char *url1;
const char *url2;
DWORD flags;
HRESULT expectret;
const char *expecturl;
} TEST_URL_COMBINE;
const TEST_URL_COMBINE TEST_COMBINE[] = {
{"http://www.winehq.org/tests", "tests1", 0, S_OK, "http://www.winehq.org/tests1"},
/*FIXME {"http://www.winehq.org/tests", "../tests2", 0, S_OK, "http://www.winehq.org/tests2"},*/
{"http://www.winehq.org/tests/", "../tests3", 0, S_OK, "http://www.winehq.org/tests3"},
{"http://www.winehq.org/tests/../tests", "tests4", 0, S_OK, "http://www.winehq.org/tests4"},
{"http://www.winehq.org/tests/../tests/", "tests5", 0, S_OK, "http://www.winehq.org/tests/tests5"},
{"http://www.winehq.org/tests/../tests/", "/tests6/..", 0, S_OK, "http://www.winehq.org/"},
{"http://www.winehq.org/tests/../tests/..", "tests7/..", 0, S_OK, "http://www.winehq.org/"},
{"http://www.winehq.org/tests/?query=x&return=y", "tests8", 0, S_OK, "http://www.winehq.org/tests/tests8"},
{"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"},
};
struct {
const char *path;
const char *url;
DWORD ret;
} TEST_URLFROMPATH [] = {
{"foo", "file:foo", S_OK},
{"foo\\bar", "file:foo/bar", S_OK},
{"\\foo\\bar", "file:///foo/bar", S_OK},
{"c:\\foo\\bar", "file:///c:/foo/bar", S_OK},
{"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},
#if 0
/* The following test fails on native shlwapi as distributed with Win95/98.
* Wine matches the behaviour of later versions.
*/
{"xx:c:\\foo\\bar", "xx:c:\\foo\\bar", S_FALSE}
#endif
};
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},
};
struct {
char url[30];
const char *expect;
} TEST_URL_UNESCAPE[] = {
{"file://foo/bar", "file://foo/bar"},
{"file://fo%20o%5Ca/bar", "file://fo o\\a/bar"}
};
struct {
const char *path;
BOOL expect;
} TEST_PATH_IS_URL[] = {
{"http://foo/bar", TRUE},
{"c:\\foo\\bar", FALSE},
{"foo://foo/bar", TRUE},
{"foo\\bar", FALSE},
{"foo.bar", FALSE},
{"bogusscheme:", TRUE},
{"http:partial", TRUE}
};
struct {
const char *url;
BOOL expectOpaque;
BOOL expectFile;
} TEST_URLIS_ATTRIBS[] = {
{ "ftp:", FALSE, FALSE },
{ "http:", FALSE, FALSE },
{ "gopher:", FALSE, FALSE },
{ "mailto:", TRUE, FALSE },
{ "news:", FALSE, FALSE },
{ "nntp:", FALSE, FALSE },
{ "telnet:", FALSE, FALSE },
{ "wais:", FALSE, FALSE },
{ "file:", FALSE, TRUE },
{ "mk:", FALSE, FALSE },
{ "https:", FALSE, FALSE },
{ "shell:", TRUE, FALSE },
{ "https:", FALSE, FALSE },
{ "snews:", FALSE, FALSE },
{ "local:", FALSE, FALSE },
{ "javascript:", TRUE, FALSE },
{ "vbscript:", TRUE, FALSE },
{ "about:", TRUE, FALSE },
{ "res:", FALSE, FALSE },
{ "bogusscheme:", FALSE, FALSE },
{ "file:\\\\e:\\b\\c", FALSE, TRUE },
{ "file://e:/b/c", FALSE, TRUE },
{ "http:partial", FALSE, FALSE },
{ "mailto://www.winehq.org/test.html", TRUE, FALSE },
{ "file:partial", FALSE, TRUE }
};
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 void hash_url(const char* szUrl)
{
LPCSTR szTestUrl = szUrl;
LPWSTR wszTestUrl = GetWideString(szTestUrl);
DWORD cbSize = sizeof(DWORD);
DWORD dwHash1, dwHash2;
ok(UrlHashA(szTestUrl, (LPBYTE)&dwHash1, cbSize) == S_OK, "UrlHashA didn't return S_OK\n");
ok(UrlHashW(wszTestUrl, (LPBYTE)&dwHash2, cbSize) == S_OK, "UrlHashW didn't return S_OK\n");
FreeWideString(wszTestUrl);
ok(dwHash1 == dwHash2, "Hashes didn't compare\n");
}
static void test_UrlHash(void)
{
hash_url(TEST_URL_1);
hash_url(TEST_URL_2);
hash_url(TEST_URL_3);
}
static void test_url_part(const char* szUrl, DWORD dwPart, DWORD dwFlags, const char* szExpected)
{
CHAR szPart[INTERNET_MAX_URL_LENGTH];
WCHAR wszPart[INTERNET_MAX_URL_LENGTH];
LPWSTR wszUrl = GetWideString(szUrl);
LPWSTR wszConvertedPart;
DWORD dwSize;
dwSize = INTERNET_MAX_URL_LENGTH;
ok( UrlGetPartA(szUrl, szPart, &dwSize, dwPart, dwFlags) == S_OK, "UrlGetPartA for \"%s\" part 0x%08lx didn't return S_OK but \"%s\"\n", szUrl, dwPart, szPart);
dwSize = INTERNET_MAX_URL_LENGTH;
ok( UrlGetPartW(wszUrl, wszPart, &dwSize, dwPart, dwFlags) == S_OK, "UrlGetPartW didn't return S_OK\n" );
wszConvertedPart = GetWideString(szPart);
ok(strcmpW(wszPart,wszConvertedPart)==0, "Strings didn't match between ascii and unicode UrlGetPart!\n");
FreeWideString(wszUrl);
FreeWideString(wszConvertedPart);
/* Note that v6.0 and later don't return '?' with the query */
ok(strcmp(szPart,szExpected)==0 ||
(*szExpected=='?' && !strcmp(szPart,szExpected+1)),
"Expected %s, but got %s\n", szExpected, szPart);
}
static void test_UrlGetPart(void)
{
test_url_part(TEST_URL_3, URL_PART_HOSTNAME, 0, "localhost");
test_url_part(TEST_URL_3, URL_PART_PORT, 0, "21");
test_url_part(TEST_URL_3, URL_PART_USERNAME, 0, "foo");
test_url_part(TEST_URL_3, URL_PART_PASSWORD, 0, "bar");
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");
}
static void test_url_escape(const char *szUrl, DWORD dwFlags, HRESULT dwExpectReturn, const char *szExpectUrl)
{
CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
DWORD dwEscaped;
WCHAR ret_urlW[INTERNET_MAX_URL_LENGTH];
WCHAR *urlW, *expected_urlW;
dwEscaped=INTERNET_MAX_URL_LENGTH;
ok(UrlEscapeA(szUrl, szReturnUrl, &dwEscaped, dwFlags) == dwExpectReturn, "UrlEscapeA didn't return 0x%08lx from \"%s\"\n", dwExpectReturn, szUrl);
ok(strcmp(szReturnUrl,szExpectUrl)==0, "Expected \"%s\", but got \"%s\" from \"%s\"\n", szExpectUrl, szReturnUrl, szUrl);
dwEscaped = INTERNET_MAX_URL_LENGTH;
urlW = GetWideString(szUrl);
expected_urlW = GetWideString(szExpectUrl);
ok(UrlEscapeW(urlW, ret_urlW, &dwEscaped, dwFlags) == dwExpectReturn, "UrlEscapeW didn't return 0x%08lx from \"%s\"\n", dwExpectReturn, szUrl);
WideCharToMultiByte(CP_ACP,0,ret_urlW,-1,szReturnUrl,INTERNET_MAX_URL_LENGTH,0,0);
ok(strcmpW(ret_urlW, expected_urlW)==0, "Expected \"%s\", but got \"%s\" from \"%s\" flags %08lx\n", szExpectUrl, szReturnUrl, szUrl, dwFlags);
FreeWideString(urlW);
FreeWideString(expected_urlW);
}
static void test_url_canonicalize(const char *szUrl, DWORD dwFlags, HRESULT dwExpectReturn, const char *szExpectUrl)
{
CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
WCHAR wszReturnUrl[INTERNET_MAX_URL_LENGTH];
LPWSTR wszUrl = GetWideString(szUrl);
LPWSTR wszExpectUrl = GetWideString(szExpectUrl);
LPWSTR wszConvertedUrl;
DWORD dwSize;
dwSize = INTERNET_MAX_URL_LENGTH;
ok(UrlCanonicalizeA(szUrl, NULL, &dwSize, dwFlags) != dwExpectReturn, "Unexpected return for NULL buffer\n");
ok(UrlCanonicalizeA(szUrl, szReturnUrl, &dwSize, dwFlags) == dwExpectReturn, "UrlCanonicalizeA didn't return 0x%08lx\n", dwExpectReturn);
ok(strcmp(szReturnUrl,szExpectUrl)==0, "UrlCanonicalizeA dwFlags 0x%08lx Expected %s, but got %s\n", dwFlags, szExpectUrl, szReturnUrl);
dwSize = INTERNET_MAX_URL_LENGTH;
ok(UrlCanonicalizeW(wszUrl, NULL, &dwSize, dwFlags) != dwExpectReturn, "Unexpected return for NULL buffer\n");
ok(UrlCanonicalizeW(wszUrl, wszReturnUrl, &dwSize, dwFlags) == dwExpectReturn, "UrlCanonicalizeW didn't return 0x%08lx\n", dwExpectReturn);
wszConvertedUrl = GetWideString(szReturnUrl);
ok(strcmpW(wszReturnUrl, wszConvertedUrl)==0, "Strings didn't match between ascii and unicode UrlCanonicalize!\n");
FreeWideString(wszConvertedUrl);
FreeWideString(wszUrl);
FreeWideString(wszExpectUrl);
}
static void test_UrlEscape(void)
{
unsigned int i;
for(i=0; i<sizeof(TEST_ESCAPE)/sizeof(TEST_ESCAPE[0]); i++) {
test_url_escape(TEST_ESCAPE[i].url, TEST_ESCAPE[i].flags,
TEST_ESCAPE[i].expectret, TEST_ESCAPE[i].expecturl);
}
}
static void test_UrlCanonicalize(void)
{
unsigned int i;
for(i=0; i<sizeof(TEST_CANONICALIZE)/sizeof(TEST_CANONICALIZE[0]); i++) {
test_url_canonicalize(TEST_CANONICALIZE[i].url, TEST_CANONICALIZE[i].flags,
TEST_CANONICALIZE[i].expectret, TEST_CANONICALIZE[i].expecturl);
}
}
static void test_url_combine(const char *szUrl1, const char *szUrl2, DWORD dwFlags, HRESULT dwExpectReturn, const char *szExpectUrl)
{
HRESULT hr;
CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
WCHAR wszReturnUrl[INTERNET_MAX_URL_LENGTH];
LPWSTR wszUrl1 = GetWideString(szUrl1);
LPWSTR wszUrl2 = GetWideString(szUrl2);
LPWSTR wszExpectUrl = GetWideString(szExpectUrl);
LPWSTR wszConvertedUrl;
DWORD dwSize;
DWORD dwExpectLen = lstrlen(szExpectUrl);
hr = UrlCombineA(szUrl1, szUrl2, NULL, NULL, dwFlags);
ok(hr == E_INVALIDARG, "UrlCombineA returned 0x%08lx, expected 0x%08lx\n", hr, E_INVALIDARG);
dwSize = 0;
hr = UrlCombineA(szUrl1, szUrl2, NULL, &dwSize, dwFlags);
ok(hr == E_POINTER, "Checking length of string, return was 0x%08lx, expected 0x%08lx\n", hr, E_POINTER);
ok(dwSize == dwExpectLen+1, "Got length %ld, expected %ld\n", dwSize, dwExpectLen+1);
dwSize--;
hr = UrlCombineA(szUrl1, szUrl2, szReturnUrl, &dwSize, dwFlags);
ok(hr == E_POINTER, "UrlCombineA returned 0x%08lx, expected 0x%08lx\n", hr, E_POINTER);
ok(dwSize == dwExpectLen+1, "Got length %ld, expected %ld\n", dwSize, dwExpectLen+1);
hr = UrlCombineA(szUrl1, szUrl2, szReturnUrl, &dwSize, dwFlags);
ok(hr == dwExpectReturn, "UrlCombineA returned 0x%08lx, expected 0x%08lx\n", hr, dwExpectReturn);
ok(dwSize == dwExpectLen, "Got length %ld, expected %ld\n", dwSize, dwExpectLen);
if(SUCCEEDED(hr)) {
ok(strcmp(szReturnUrl,szExpectUrl)==0, "Expected %s, but got %s\n", szExpectUrl, szReturnUrl);
}
dwSize = 0;
hr = UrlCombineW(wszUrl1, wszUrl2, NULL, &dwSize, dwFlags);
ok(hr == E_POINTER, "Checking length of string, return was 0x%08lx, expected 0x%08lx\n", hr, E_POINTER);
ok(dwSize == dwExpectLen+1, "Got length %ld, expected %ld\n", dwSize, dwExpectLen+1);
dwSize--;
hr = UrlCombineW(wszUrl1, wszUrl2, wszReturnUrl, &dwSize, dwFlags);
ok(hr == E_POINTER, "UrlCombineA returned 0x%08lx, expected 0x%08lx\n", hr, E_POINTER);
ok(dwSize == dwExpectLen+1, "Got length %ld, expected %ld\n", dwSize, dwExpectLen+1);
hr = UrlCombineW(wszUrl1, wszUrl2, wszReturnUrl, &dwSize, dwFlags);
ok(hr == dwExpectReturn, "UrlCombineW returned 0x%08lx, expected 0x%08lx\n", hr, dwExpectReturn);
ok(dwSize == dwExpectLen, "Got length %ld, expected %ld\n", dwSize, dwExpectLen);
if(SUCCEEDED(hr)) {
wszConvertedUrl = GetWideString(szReturnUrl);
ok(strcmpW(wszReturnUrl, wszConvertedUrl)==0, "Strings didn't match between ascii and unicode UrlCombine!\n");
FreeWideString(wszConvertedUrl);
}
FreeWideString(wszUrl1);
FreeWideString(wszUrl2);
FreeWideString(wszExpectUrl);
}
static void test_UrlCombine(void)
{
unsigned int i;
for(i=0; i<sizeof(TEST_COMBINE)/sizeof(TEST_COMBINE[0]); i++) {
test_url_combine(TEST_COMBINE[i].url1, TEST_COMBINE[i].url2, TEST_COMBINE[i].flags,
TEST_COMBINE[i].expectret, TEST_COMBINE[i].expecturl);
}
}
static void test_UrlCreateFromPath(void)
{
size_t i;
char ret_url[INTERNET_MAX_URL_LENGTH];
DWORD len, ret;
WCHAR ret_urlW[INTERNET_MAX_URL_LENGTH];
WCHAR *pathW, *urlW;
for(i = 0; i < sizeof(TEST_URLFROMPATH) / sizeof(TEST_URLFROMPATH[0]); i++) {
len = INTERNET_MAX_URL_LENGTH;
ret = UrlCreateFromPathA(TEST_URLFROMPATH[i].path, ret_url, &len, 0);
ok(ret == TEST_URLFROMPATH[i].ret, "ret %08lx from path %s\n", ret, TEST_URLFROMPATH[i].path);
ok(!lstrcmpi(ret_url, TEST_URLFROMPATH[i].url), "url %s from path %s\n", ret_url, TEST_URLFROMPATH[i].path);
ok(len == strlen(ret_url), "ret len %ld from path %s\n", len, TEST_URLFROMPATH[i].path);
len = INTERNET_MAX_URL_LENGTH;
pathW = GetWideString(TEST_URLFROMPATH[i].path);
urlW = GetWideString(TEST_URLFROMPATH[i].url);
ret = UrlCreateFromPathW(pathW, ret_urlW, &len, 0);
WideCharToMultiByte(CP_ACP, 0, ret_urlW, -1, ret_url, sizeof(ret_url),0,0);
ok(ret == TEST_URLFROMPATH[i].ret, "ret %08lx from path L\"%s\", expected %08lx\n",
ret, TEST_URLFROMPATH[i].path, TEST_URLFROMPATH[i].ret);
ok(!lstrcmpiW(ret_urlW, urlW), "got %s expected %s from path L\"%s\"\n", ret_url, TEST_URLFROMPATH[i].url, TEST_URLFROMPATH[i].path);
ok(len == strlenW(ret_urlW), "ret len %ld from path L\"%s\"\n", len, TEST_URLFROMPATH[i].path);
FreeWideString(urlW);
FreeWideString(pathW);
}
}
static void test_UrlIs(void)
{
BOOL ret;
size_t i;
WCHAR wurl[80];
for(i = 0; i < sizeof(TEST_PATH_IS_URL) / sizeof(TEST_PATH_IS_URL[0]); i++) {
MultiByteToWideChar(CP_ACP, 0, TEST_PATH_IS_URL[i].path, -1, wurl, 80);
ret = UrlIsA( TEST_PATH_IS_URL[i].path, URLIS_URL );
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 );
ret = UrlIsW( wurl, URLIS_URL );
ok( ret == TEST_PATH_IS_URL[i].expect,
"returned %d from path (UrlIsW) %s, expected %d\n", ret, TEST_PATH_IS_URL[i].path,
TEST_PATH_IS_URL[i].expect );
}
for(i = 0; i < sizeof(TEST_URLIS_ATTRIBS) / sizeof(TEST_URLIS_ATTRIBS[0]); i++) {
MultiByteToWideChar(CP_ACP, 0, TEST_URLIS_ATTRIBS[i].url, -1, wurl, 80);
ret = UrlIsA( TEST_URLIS_ATTRIBS[i].url, URLIS_OPAQUE);
ok( ret == TEST_URLIS_ATTRIBS[i].expectOpaque,
"returned %d for URLIS_OPAQUE, url \"%s\", expected %d\n", ret, TEST_URLIS_ATTRIBS[i].url,
TEST_URLIS_ATTRIBS[i].expectOpaque );
ret = UrlIsA( TEST_URLIS_ATTRIBS[i].url, URLIS_FILEURL);
ok( ret == TEST_URLIS_ATTRIBS[i].expectFile,
"returned %d for URLIS_FILEURL, url \"%s\", expected %d\n", ret, TEST_URLIS_ATTRIBS[i].url,
TEST_URLIS_ATTRIBS[i].expectFile );
ret = UrlIsW( wurl, URLIS_OPAQUE);
ok( ret == TEST_URLIS_ATTRIBS[i].expectOpaque,
"returned %d for URLIS_OPAQUE (UrlIsW), url \"%s\", expected %d\n", ret, TEST_URLIS_ATTRIBS[i].url,
TEST_URLIS_ATTRIBS[i].expectOpaque );
ret = UrlIsW( wurl, URLIS_FILEURL);
ok( ret == TEST_URLIS_ATTRIBS[i].expectFile,
"returned %d for URLIS_FILEURL (UrlIsW), url \"%s\", expected %d\n", ret, TEST_URLIS_ATTRIBS[i].url,
TEST_URLIS_ATTRIBS[i].expectFile );
}
}
static void test_UrlUnescape(void)
{
CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
WCHAR ret_urlW[INTERNET_MAX_URL_LENGTH];
WCHAR *urlW, *expected_urlW;
DWORD dwEscaped;
size_t i;
for(i=0; i<sizeof(TEST_URL_UNESCAPE)/sizeof(TEST_URL_UNESCAPE[0]); i++) {
dwEscaped=INTERNET_MAX_URL_LENGTH;
ok(UrlUnescapeA(TEST_URL_UNESCAPE[i].url, szReturnUrl, &dwEscaped, 0) == S_OK, "UrlEscapeA didn't return 0x%08lx from \"%s\"\n", S_OK, TEST_URL_UNESCAPE[i].url);
ok(strcmp(szReturnUrl,TEST_URL_UNESCAPE[i].expect)==0, "Expected \"%s\", but got \"%s\" from \"%s\"\n", TEST_URL_UNESCAPE[i].expect, szReturnUrl, TEST_URL_UNESCAPE[i].url);
dwEscaped = INTERNET_MAX_URL_LENGTH;
urlW = GetWideString(TEST_URL_UNESCAPE[i].url);
expected_urlW = GetWideString(TEST_URL_UNESCAPE[i].expect);
ok(UrlUnescapeW(urlW, ret_urlW, &dwEscaped, 0) == S_OK, "UrlEscapeW didn't return 0x%08lx from \"%s\"\n", S_OK, TEST_URL_UNESCAPE[i].url);
WideCharToMultiByte(CP_ACP,0,ret_urlW,-1,szReturnUrl,INTERNET_MAX_URL_LENGTH,0,0);
ok(strcmpW(ret_urlW, expected_urlW)==0, "Expected \"%s\", but got \"%s\" from \"%s\" flags %08lx\n", TEST_URL_UNESCAPE[i].expect, szReturnUrl, TEST_URL_UNESCAPE[i].url, 0L);
FreeWideString(urlW);
FreeWideString(expected_urlW);
}
}
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);
strcatW(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);
strcatW(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);
strcpyW(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;
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 %08lx 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 %ld 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 %08lx 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 == strlenW(ret_pathW), "ret len %ld 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;
ret = pPathIsValidCharA( 0x7f, 0 );
ok ( !ret, "PathIsValidCharA succeeded: 0x%08lx\n", (DWORD)ret );
ret = pPathIsValidCharA( 0x7f, 1 );
ok ( !ret, "PathIsValidCharA succeeded: 0x%08lx\n", (DWORD)ret );
for (c = 0; c < 0x7f; c++)
{
ret = pPathIsValidCharA( c, ~0U );
ok ( ret == SHELL_charclass[c] || (ret == 1 && SHELL_charclass[c] == 0xffffffff),
"PathIsValidCharA failed: 0x%02x got 0x%08lx expected 0x%08lx\n",
c, (DWORD)ret, SHELL_charclass[c] );
}
for (c = 0x7f; c <= 0xff; c++)
{
ret = pPathIsValidCharA( c, ~0U );
ok ( ret == 0x00000100,
"PathIsValidCharA failed: 0x%02x got 0x%08lx expected 0x00000100\n",
c, (DWORD)ret );
}
}
static void test_PathIsValidCharW(void)
{
BOOL ret;
unsigned int c;
ret = pPathIsValidCharW( 0x7f, 0 );
ok ( !ret, "PathIsValidCharW succeeded: 0x%08lx\n", (DWORD)ret );
ret = pPathIsValidCharW( 0x7f, 1 );
ok ( !ret, "PathIsValidCharW succeeded: 0x%08lx\n", (DWORD)ret );
for (c = 0; c < 0x7f; c++)
{
ret = pPathIsValidCharW( c, ~0U );
ok ( ret == SHELL_charclass[c] || (ret == 1 && SHELL_charclass[c] == 0xffffffff),
"PathIsValidCharW failed: 0x%02x got 0x%08lx expected 0x%08lx\n",
c, (DWORD)ret, SHELL_charclass[c] );
}
for (c = 0x007f; c <= 0xffff; c++)
{
ret = pPathIsValidCharW( c, ~0U );
ok ( ret == 0x00000100,
"PathIsValidCharW failed: 0x%02x got 0x%08lx expected 0x00000100\n",
c, (DWORD)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);
}
START_TEST(path)
{
hShlwapi = LoadLibraryA("shlwapi.dll");
if (!hShlwapi) return;
test_UrlHash();
test_UrlGetPart();
test_UrlCanonicalize();
test_UrlEscape();
test_UrlCombine();
test_UrlCreateFromPath();
test_UrlIs();
test_UrlUnescape();
test_PathSearchAndQualify();
test_PathCreateFromUrl();
test_PathIsUrl();
test_PathMakePretty();
/* For whatever reason, PathIsValidCharA and PathAppendA share the same
* ordinal number in some native versions. Check this to prevent a crash.
*/
pPathIsValidCharA = (void*)GetProcAddress(hShlwapi, (LPSTR)455);
if (pPathIsValidCharA && pPathIsValidCharA != (void*)GetProcAddress(hShlwapi, "PathAppendA"))
{
test_PathIsValidCharA();
pPathIsValidCharW = (void*)GetProcAddress(hShlwapi, (LPSTR)456);
if (pPathIsValidCharW) test_PathIsValidCharW();
}
}

View file

@ -0,0 +1,13 @@
<module name="shlwapi_test" type="win32cui" installbase="bin" installname="shlwapi_test.exe" warnings="true">
<include base="shlwapi_test">.</include>
<define name="__USE_W32API" />
<library>ntdll</library>
<library>shlwapi</library>
<library>ole32</library>
<library>oleaut32</library>
<file>clist.c</file>
<file>ordinal.c</file>
<file>shreg.c</file>
<file>string.c</file>
<file>testlist.c</file>
</module>

View file

@ -0,0 +1,385 @@
/* Unit test suite for SHReg* functions
*
* Copyright 2002 Juergen Schmied
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include "wine/test.h"
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "winreg.h"
#include "winuser.h"
#include "shlwapi.h"
/* Keys used for testing */
#define REG_TEST_KEY "Software\\Wine\\Test"
#define REG_CURRENT_VERSION "Software\\Microsoft\\Windows\\CurrentVersion"
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;
static const char * sTestpath1 = "%LONGSYSTEMVAR%\\subdir1";
static const char * sTestpath2 = "%FOO%\\subdir1";
static const char * sEnvvar1 = "bar";
static const char * sEnvvar2 = "ImARatherLongButIndeedNeededString";
static char sExpTestpath1[MAX_PATH];
static char sExpTestpath2[MAX_PATH];
static unsigned sExpLen1;
static unsigned sExpLen2;
static const char * sEmptyBuffer ="0123456789";
/* delete key and all its subkeys */
static DWORD delete_key( HKEY hkey, LPSTR parent, LPSTR keyname )
{
HKEY parentKey;
DWORD ret;
RegCloseKey(hkey);
/* open the parent of the key to close */
ret = RegOpenKeyExA( HKEY_CURRENT_USER, parent, 0, KEY_ALL_ACCESS, &parentKey);
if (ret != ERROR_SUCCESS)
return ret;
ret = SHDeleteKeyA( parentKey, keyname );
RegCloseKey(parentKey);
return ret;
}
static HKEY create_test_entries(void)
{
HKEY hKey;
DWORD ret;
SetEnvironmentVariableA("LONGSYSTEMVAR", sEnvvar1);
SetEnvironmentVariableA("FOO", sEnvvar2);
ret = RegCreateKeyA(HKEY_CURRENT_USER, REG_TEST_KEY, &hKey);
ok( ERROR_SUCCESS == ret, "RegCreateKeyA failed, ret=%lu\n", ret);
if (hKey)
{
ok(!RegSetValueExA(hKey,"Test1",0,REG_EXPAND_SZ, (LPBYTE) sTestpath1, strlen(sTestpath1)+1), "RegSetValueExA failed\n");
ok(!RegSetValueExA(hKey,"Test2",0,REG_SZ, (LPBYTE) sTestpath1, strlen(sTestpath1)+1), "RegSetValueExA failed\n");
ok(!RegSetValueExA(hKey,"Test3",0,REG_EXPAND_SZ, (LPBYTE) sTestpath2, strlen(sTestpath2)+1), "RegSetValueExA failed\n");
}
sExpLen1 = ExpandEnvironmentStringsA(sTestpath1, sExpTestpath1, sizeof(sExpTestpath1));
sExpLen2 = ExpandEnvironmentStringsA(sTestpath2, sExpTestpath2, sizeof(sExpTestpath2));
ok(sExpLen1 > 0, "Couldn't expand %s\n", sTestpath1);
trace("sExplen1 = (%d)\n", sExpLen1);
ok(sExpLen2 > 0, "Couldn't expand %s\n", sTestpath2);
trace("sExplen2 = (%d)\n", sExpLen2);
return hKey;
}
static void test_SHGetValue(void)
{
DWORD dwSize;
DWORD dwType;
DWORD dwRet;
char buf[MAX_PATH];
strcpy(buf, sEmptyBuffer);
dwSize = MAX_PATH;
dwType = -1;
dwRet = SHGetValueA(HKEY_CURRENT_USER, REG_TEST_KEY, "Test1", &dwType, buf, &dwSize);
ok( ERROR_SUCCESS == dwRet, "SHGetValueA failed, ret=%lu\n", dwRet);
ok( 0 == strcmp(sExpTestpath1, buf), "Comparing of (%s) with (%s) failed\n", buf, sExpTestpath1);
ok( REG_SZ == dwType, "Expected REG_SZ, got (%lu)\n", dwType);
strcpy(buf, sEmptyBuffer);
dwSize = MAX_PATH;
dwType = -1;
dwRet = SHGetValueA(HKEY_CURRENT_USER, REG_TEST_KEY, "Test2", &dwType, buf, &dwSize);
ok( ERROR_SUCCESS == dwRet, "SHGetValueA failed, ret=%lu\n", dwRet);
ok( 0 == strcmp(sTestpath1, buf) , "Comparing of (%s) with (%s) failed\n", buf, sTestpath1);
ok( REG_SZ == dwType , "Expected REG_SZ, got (%lu)\n", dwType);
}
static void test_SHGetRegPath(void)
{
char buf[MAX_PATH];
DWORD dwRet;
if (!pSHRegGetPathA)
return;
strcpy(buf, sEmptyBuffer);
dwRet = (*pSHRegGetPathA)(HKEY_CURRENT_USER, REG_TEST_KEY, "Test1", buf, 0);
ok( ERROR_SUCCESS == dwRet, "SHRegGetPathA failed, ret=%lu\n", dwRet);
ok( 0 == strcmp(sExpTestpath1, buf) , "Comparing (%s) with (%s) failed\n", buf, sExpTestpath1);
}
static void test_SHQUeryValueEx(void)
{
HKEY hKey;
DWORD dwSize;
DWORD dwType;
char buf[MAX_PATH];
DWORD dwRet;
const char * sTestedFunction = "";
DWORD nUsedBuffer1,nUsedBuffer2;
sTestedFunction = "RegOpenKeyExA";
dwRet = RegOpenKeyExA(HKEY_CURRENT_USER, REG_TEST_KEY, 0, KEY_QUERY_VALUE, &hKey);
ok( ERROR_SUCCESS == dwRet, "%s failed, ret=%lu\n", sTestedFunction, dwRet);
/****** SHQueryValueExA ******/
sTestedFunction = "SHQueryValueExA";
nUsedBuffer1 = max(strlen(sExpTestpath1)+1, strlen(sTestpath1)+1);
nUsedBuffer2 = max(strlen(sExpTestpath2)+1, strlen(sTestpath2)+1);
/*
* Case 1.1 All arguments are NULL
*/
dwRet = SHQueryValueExA( hKey, "Test1", NULL, NULL, NULL, NULL);
ok( ERROR_SUCCESS == dwRet, "%s failed, ret=%lu\n", sTestedFunction, dwRet);
/*
* Case 1.2 dwType is set
*/
dwType = -1;
dwRet = SHQueryValueExA( hKey, "Test1", NULL, &dwType, NULL, NULL);
ok( ERROR_SUCCESS == dwRet, "%s failed, ret=%lu\n", sTestedFunction, dwRet);
ok( REG_SZ == dwType , "Expected REG_SZ, got (%lu)\n", dwType);
/*
* dwSize is set
* dwExpanded < dwUnExpanded
*/
dwSize = 6;
dwRet = SHQueryValueExA( hKey, "Test1", NULL, NULL, NULL, &dwSize);
ok( ERROR_SUCCESS == dwRet, "%s failed, ret=%lu\n", sTestedFunction, dwRet);
ok( dwSize == nUsedBuffer1, "Buffer sizes (%lu) and (%lu) are not equal\n", dwSize, nUsedBuffer1);
/*
* dwExpanded > dwUnExpanded
*/
dwSize = 6;
dwRet = SHQueryValueExA( hKey, "Test3", NULL, NULL, NULL, &dwSize);
ok( ERROR_SUCCESS == dwRet, "%s failed, ret=%lu\n", sTestedFunction, dwRet);
ok( dwSize >= nUsedBuffer2, "Buffer size (%lu) should be >= (%lu)\n", dwSize, nUsedBuffer2);
/*
* Case 1 string shrinks during expanding
*/
strcpy(buf, sEmptyBuffer);
dwSize = 6;
dwType = -1;
dwRet = SHQueryValueExA( hKey, "Test1", NULL, &dwType, buf, &dwSize);
ok( ERROR_MORE_DATA == dwRet, "Expected ERROR_MORE_DATA, got (%lu)\n", dwRet);
ok( 0 == strcmp(sEmptyBuffer, buf) , "Comparing (%s) with (%s) failed\n", buf, sEmptyBuffer);
ok( dwSize == nUsedBuffer1, "Buffer sizes (%lu) and (%lu) are not equal\n", dwSize, nUsedBuffer1);
ok( REG_SZ == dwType , "Expected REG_SZ, got (%lu)\n", dwType);
/*
* string grows during expanding
* dwSize is smaller then the size of the unexpanded string
*/
strcpy(buf, sEmptyBuffer);
dwSize = 6;
dwType = -1;
dwRet = SHQueryValueExA( hKey, "Test3", NULL, &dwType, buf, &dwSize);
ok( ERROR_MORE_DATA == dwRet, "Expected ERROR_MORE_DATA, got (%lu)\n", dwRet);
ok( 0 == strcmp(sEmptyBuffer, buf) , "Comparing (%s) with (%s) failed\n", buf, sEmptyBuffer);
ok( dwSize >= nUsedBuffer2, "Buffer size (%lu) should be >= (%lu)\n", dwSize, nUsedBuffer2);
ok( REG_SZ == dwType , "Expected REG_SZ, got (%lu)\n", dwType);
/*
* string grows during expanding
* dwSize is larger then the size of the unexpanded string but smaller than the part before the backslash
* if the unexpanded string fits into the buffer it can get cut when expanded
*/
strcpy(buf, sEmptyBuffer);
dwSize = strlen(sEnvvar2) - 2;
dwType = -1;
dwRet = SHQueryValueExA( hKey, "Test3", NULL, &dwType, buf, &dwSize);
ok( ERROR_MORE_DATA == dwRet, "Expected ERROR_MORE_DATA, got (%lu)\n", dwRet);
todo_wine
{
ok( (0 == strcmp("", buf)) | (0 == strcmp(sTestpath2, buf)),
"Expected empty or unexpanded string (win98), got (%s)\n", buf);
}
ok( dwSize >= nUsedBuffer2, "Buffer size (%lu) should be >= (%lu)\n", dwSize, nUsedBuffer2);
ok( REG_SZ == dwType , "Expected REG_SZ, got (%lu)\n", dwType);
/*
* string grows during expanding
* dwSize is larger then the size of the part before the backslash but smaller then the expanded string
* if the unexpanded string fits into the buffer it can get cut when expanded
*/
strcpy(buf, sEmptyBuffer);
dwSize = sExpLen2 - 4;
dwType = -1;
dwRet = SHQueryValueExA( hKey, "Test3", NULL, &dwType, buf, &dwSize);
ok( ERROR_MORE_DATA == dwRet, "Expected ERROR_MORE_DATA, got (%lu)\n", dwRet);
todo_wine
{
ok( (0 == strcmp("", buf)) | (0 == strcmp(sEnvvar2, buf)),
"Expected empty or first part of the string \"%s\", got \"%s\"\n", sEnvvar2, buf);
}
ok( dwSize >= nUsedBuffer2, "Buffer size (%lu) should be >= (%lu)\n", dwSize, nUsedBuffer2);
ok( REG_SZ == dwType , "Expected REG_SZ, got (%lu)\n", dwType);
/*
* The buffer is NULL but the size is set
*/
strcpy(buf, sEmptyBuffer);
dwSize = 6;
dwType = -1;
dwRet = SHQueryValueExA( hKey, "Test3", NULL, &dwType, NULL, &dwSize);
ok( ERROR_SUCCESS == dwRet, "%s failed, ret=%lu\n", sTestedFunction, dwRet);
ok( dwSize >= nUsedBuffer2, "Buffer size (%lu) should be >= (%lu)\n", dwSize, nUsedBuffer2);
ok( REG_SZ == dwType , "Expected REG_SZ, got (%lu)\n", dwType);
RegCloseKey(hKey);
}
static void test_SHCopyKey(void)
{
HKEY hKeySrc, hKeyDst;
DWORD dwRet;
/* Delete existing destination sub keys */
hKeyDst = NULL;
if (!RegOpenKeyA(HKEY_CURRENT_USER, REG_TEST_KEY "\\CopyDestination", &hKeyDst) && hKeyDst)
{
SHDeleteKeyA(hKeyDst, NULL);
RegCloseKey(hKeyDst);
}
hKeyDst = NULL;
dwRet = RegCreateKeyA(HKEY_CURRENT_USER, REG_TEST_KEY "\\CopyDestination", &hKeyDst);
if (dwRet || !hKeyDst)
{
ok( 0, "Destination couldn't be created, RegCreateKeyA returned (%lu)\n", dwRet);
return;
}
hKeySrc = NULL;
dwRet = RegOpenKeyA(HKEY_LOCAL_MACHINE, REG_CURRENT_VERSION, &hKeySrc);
if (dwRet || !hKeySrc)
{
ok( 0, "Source couldn't be opened, RegOpenKeyA returned (%lu)\n", dwRet);
return;
}
if (pSHCopyKeyA)
{
dwRet = (*pSHCopyKeyA)(hKeySrc, NULL, hKeyDst, 0);
ok ( ERROR_SUCCESS == dwRet, "Copy failed, ret=(%lu)\n", dwRet);
}
RegCloseKey(hKeySrc);
RegCloseKey(hKeyDst);
/* Check we copied the sub keys, i.e. something that's on every windows system (including Wine) */
hKeyDst = NULL;
dwRet = RegOpenKeyA(HKEY_CURRENT_USER, REG_TEST_KEY "\\CopyDestination\\Setup", &hKeyDst);
if (dwRet || !hKeyDst)
{
ok ( 0, "Copy couldn't be opened, RegOpenKeyA returned (%lu)\n", dwRet);
return;
}
/* And the we copied the values too */
ok(!SHQueryValueExA(hKeyDst, "BootDir", NULL, NULL, NULL, NULL), "SHQueryValueExA failed\n");
RegCloseKey(hKeyDst);
}
static void test_SHDeleteKey(void)
{
HKEY hKeyTest, hKeyS;
DWORD dwRet;
int sysfail = 1;
if (!RegOpenKeyA(HKEY_CURRENT_USER, REG_TEST_KEY, &hKeyTest))
{
if (!RegCreateKey(hKeyTest, "ODBC", &hKeyS))
{
HKEY hKeyO;
if (!RegCreateKey(hKeyS, "ODBC.INI", &hKeyO))
{
RegCloseKey (hKeyO);
if (!RegCreateKey(hKeyS, "ODBCINST.INI", &hKeyO))
{
RegCloseKey (hKeyO);
sysfail = 0;
}
}
RegCloseKey (hKeyS);
}
RegCloseKey (hKeyTest);
}
if (!sysfail)
{
dwRet = SHDeleteKeyA(HKEY_CURRENT_USER, REG_TEST_KEY "\\ODBC");
ok ( ERROR_SUCCESS == dwRet, "SHDeleteKey failed, ret=(%lu)\n", dwRet);
dwRet = RegOpenKeyA(HKEY_CURRENT_USER, REG_TEST_KEY "\\ODBC", &hKeyS);
ok ( ERROR_FILE_NOT_FOUND == dwRet, "SHDeleteKey did not delete\n");
if (dwRet == ERROR_SUCCESS)
RegCloseKey (hKeyS);
}
else
ok( 0, "Could not set up SHDeleteKey test\n");
}
START_TEST(shreg)
{
HKEY hkey = create_test_entries();
if (!hkey) return;
hshlwapi = GetModuleHandleA("shlwapi.dll");
if (hshlwapi)
{
pSHCopyKeyA=(SHCopyKeyA_func)GetProcAddress(hshlwapi,"SHCopyKeyA");
pSHRegGetPathA=(SHRegGetPathA_func)GetProcAddress(hshlwapi,"SHRegGetPathA");
}
test_SHGetValue();
test_SHQUeryValueEx();
test_SHGetRegPath();
test_SHCopyKey();
test_SHDeleteKey();
delete_key( hkey, "Software\\Wine", "Test" );
}

View file

@ -0,0 +1,760 @@
/* Unit test suite for SHLWAPI string functions
*
* Copyright 2003 Jon Griffiths
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "wine/test.h"
#include "winbase.h"
#include "winerror.h"
#include "winnls.h"
#define NO_SHLWAPI_REG
#define NO_SHLWAPI_PATH
#define NO_SHLWAPI_GDI
#define NO_SHLWAPI_STREAM
#include "shlwapi.h"
#include "shtypes.h"
static HMODULE hShlwapi;
static LPSTR (WINAPI *pStrCpyNXA)(LPSTR,LPCSTR,int);
static LPWSTR (WINAPI *pStrCpyNXW)(LPWSTR,LPCWSTR,int);
static HRESULT (WINAPI *pStrRetToBSTR)(STRRET*,void*,BSTR*);
static DWORD (WINAPI *pSHAnsiToAnsi)(LPCSTR,LPSTR,int);
static DWORD (WINAPI *pSHUnicodeToUnicode)(LPCWSTR,LPWSTR,int);
static BOOL (WINAPI *pStrIsIntlEqualA)(BOOL,LPCSTR,LPCSTR,int);
static BOOL (WINAPI *pIntlStrEqWorkerA)(BOOL,LPCSTR,LPCSTR,int);
static BOOL (WINAPI *pStrIsIntlEqualW)(BOOL,LPCWSTR,LPCWSTR,int);
static BOOL (WINAPI *pIntlStrEqWorkerW)(BOOL,LPCWSTR,LPCWSTR,int);
static inline int strcmpW(const WCHAR *str1, const WCHAR *str2)
{
while (*str1 && (*str1 == *str2)) { str1++; str2++; }
return *str1 - *str2;
}
/* StrToInt/StrToIntEx results */
typedef struct tagStrToIntResult
{
const char* string;
int str_to_int;
int str_to_int_ex;
int str_to_int_hex;
} StrToIntResult;
static const StrToIntResult StrToInt_results[] = {
{ "1099", 1099, 1099, 1099 },
{ "+88987", 0, 88987, 88987 },
{ "012", 12, 12, 12 },
{ "-55", -55, -55, -55 },
{ "-0", 0, 0, 0 },
{ "0x44ff", 0, 0, 0x44ff },
{ "+0x44f4", 0, 0, 0x44f4 },
{ "-0x44fd", 0, 0, 0x44fd },
{ "+ 88987", 0, 0, 0 },
{ "- 55", 0, 0, 0 },
{ "- 0", 0, 0, 0 },
{ "+ 0x44f4", 0, 0, 0 },
{ "--0x44fd", 0, 0, 0 },
{ " 1999", 0, 1999, 1999 },
{ " +88987", 0, 88987, 88987 },
{ " 012", 0, 12, 12 },
{ " -55", 0, -55, -55 },
{ " 0x44ff", 0, 0, 0x44ff },
{ " +0x44f4", 0, 0, 0x44f4 },
{ " -0x44fd", 0, 0, 0x44fd },
{ NULL, 0, 0, 0 }
};
/* pStrFormatByteSize64/StrFormatKBSize results */
typedef struct tagStrFormatSizeResult
{
LONGLONG value;
const char* byte_size_64;
const char* kb_size;
} StrFormatSizeResult;
static const StrFormatSizeResult StrFormatSize_results[] = {
{ -1023, "-1023 bytes", "0 KB"},
{ -24, "-24 bytes", "0 KB"},
{ 309, "309 bytes", "1 KB"},
{ 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"},
{ 0, NULL, NULL }
};
/* StrFormatByteSize64/StrFormatKBSize results */
typedef struct tagStrFromTimeIntervalResult
{
DWORD ms;
int digits;
const char* time_interval;
} StrFromTimeIntervalResult;
static const StrFromTimeIntervalResult StrFromTimeInterval_results[] = {
{ 1, 1, " 0 sec" },
{ 1, 2, " 0 sec" },
{ 1, 3, " 0 sec" },
{ 1, 4, " 0 sec" },
{ 1, 5, " 0 sec" },
{ 1, 6, " 0 sec" },
{ 1, 7, " 0 sec" },
{ 1000000, 1, " 10 min" },
{ 1000000, 2, " 16 min" },
{ 1000000, 3, " 16 min 40 sec" },
{ 1000000, 4, " 16 min 40 sec" },
{ 1000000, 5, " 16 min 40 sec" },
{ 1000000, 6, " 16 min 40 sec" },
{ 1000000, 7, " 16 min 40 sec" },
{ 1999999, 1, " 30 min" },
{ 1999999, 2, " 33 min" },
{ 1999999, 3, " 33 min 20 sec" },
{ 1999999, 4, " 33 min 20 sec" },
{ 1999999, 5, " 33 min 20 sec" },
{ 1999999, 6, " 33 min 20 sec" },
{ 1999999, 7, " 33 min 20 sec" },
{ 3999997, 1, " 1 hr" },
{ 3999997, 2, " 1 hr 6 min" },
{ 3999997, 3, " 1 hr 6 min 40 sec" },
{ 3999997, 4, " 1 hr 6 min 40 sec" },
{ 3999997, 5, " 1 hr 6 min 40 sec" },
{ 3999997, 6, " 1 hr 6 min 40 sec" },
{ 3999997, 7, " 1 hr 6 min 40 sec" },
{ 149999851, 7, " 41 hr 40 min 0 sec" },
{ 150999850, 1, " 40 hr" },
{ 150999850, 2, " 41 hr" },
{ 150999850, 3, " 41 hr 50 min" },
{ 150999850, 4, " 41 hr 56 min" },
{ 150999850, 5, " 41 hr 56 min 40 sec" },
{ 150999850, 6, " 41 hr 56 min 40 sec" },
{ 150999850, 7, " 41 hr 56 min 40 sec" },
{ 493999507, 1, " 100 hr" },
{ 493999507, 2, " 130 hr" },
{ 493999507, 3, " 137 hr" },
{ 493999507, 4, " 137 hr 10 min" },
{ 493999507, 5, " 137 hr 13 min" },
{ 493999507, 6, " 137 hr 13 min 20 sec" },
{ 493999507, 7, " 137 hr 13 min 20 sec" },
{ 0, 0, NULL }
};
static void test_StrChrA(void)
{
char string[129];
WORD count;
/* this test crashes on win2k SP4 */
/*ok(!StrChrA(NULL,'\0'), "found a character in a NULL string!\n");*/
for (count = 32; count < 128; count++)
string[count] = (char)count;
string[128] = '\0';
for (count = 32; count < 128; count++)
{
LPSTR result = StrChrA(string+32, count);
ok(result - string == count,
"found char '%c' in wrong place: got %d, expected %d\n",
count, result - string, count);
}
for (count = 32; count < 128; count++)
{
LPSTR result = StrChrA(string+count+1, count);
ok(!result, "found char '%c' not in the string\n", count);
}
}
static void test_StrChrW(void)
{
WCHAR string[16385];
WORD count;
/* this test crashes on win2k SP4 */
/*ok(!StrChrW(NULL,'\0'), "found a character in a NULL string!\n");*/
for (count = 32; count < 16384; count++)
string[count] = count;
string[16384] = '\0';
for (count = 32; count < 16384; count++)
{
LPWSTR result = StrChrW(string+32, count);
ok((result - string) == count, "found char %d in wrong place\n", count);
}
for (count = 32; count < 16384; count++)
{
LPWSTR result = StrChrW(string+count+1, count);
ok(!result, "found char not in the string\n");
}
}
static void test_StrChrIA(void)
{
char string[129];
WORD count;
/* this test crashes on win2k SP4 */
/*ok(!StrChrIA(NULL,'\0'), "found a character in a NULL string!\n");*/
for (count = 32; count < 128; count++)
string[count] = (char)count;
string[128] = '\0';
for (count = 'A'; count <= 'X'; count++)
{
LPSTR result = StrChrIA(string+32, count);
ok(result - string == count, "found char '%c' in wrong place\n", count);
ok(StrChrIA(result, count)!=NULL, "didn't find lowercase '%c'\n", count);
}
for (count = 'a'; count < 'z'; count++)
{
LPSTR result = StrChrIA(string+count+1, count);
ok(!result, "found char not in the string\n");
}
}
static void test_StrChrIW(void)
{
WCHAR string[129];
WORD count;
/* this test crashes on win2k SP4 */
/*ok(!StrChrIA(NULL,'\0'), "found a character in a NULL string!\n");*/
for (count = 32; count < 128; count++)
string[count] = count;
string[128] = '\0';
for (count = 'A'; count <= 'X'; count++)
{
LPWSTR result = StrChrIW(string+32, count);
ok(result - string == count, "found char '%c' in wrong place\n", count);
ok(StrChrIW(result, count)!=NULL, "didn't find lowercase '%c'\n", count);
}
for (count = 'a'; count < 'z'; count++)
{
LPWSTR result = StrChrIW(string+count+1, count);
ok(!result, "found char not in the string\n");
}
}
static void test_StrRChrA(void)
{
char string[129];
WORD count;
/* this test crashes on win2k SP4 */
/*ok(!StrRChrA(NULL, NULL,'\0'), "found a character in a NULL string!\n");*/
for (count = 32; count < 128; count++)
string[count] = (char)count;
string[128] = '\0';
for (count = 32; count < 128; count++)
{
LPSTR result = StrRChrA(string+32, NULL, count);
ok(result - string == count, "found char %d in wrong place\n", count);
}
for (count = 32; count < 128; count++)
{
LPSTR result = StrRChrA(string+count+1, NULL, count);
ok(!result, "found char not in the string\n");
}
for (count = 32; count < 128; count++)
{
LPSTR result = StrRChrA(string+count+1, string + 127, count);
ok(!result, "found char not in the string\n");
}
}
static void test_StrRChrW(void)
{
WCHAR string[129];
WORD count;
/* this test crashes on win2k SP4 */
/*ok(!StrRChrW(NULL, NULL,'\0'), "found a character in a NULL string!\n");*/
for (count = 32; count < 128; count++)
string[count] = count;
string[128] = '\0';
for (count = 32; count < 128; count++)
{
LPWSTR result = StrRChrW(string+32, NULL, count);
ok(result - string == count,
"found char %d in wrong place: got %d, expected %d\n",
count, result - string, count);
}
for (count = 32; count < 128; count++)
{
LPWSTR result = StrRChrW(string+count+1, NULL, count);
ok(!result, "found char %d not in the string\n", count);
}
for (count = 32; count < 128; count++)
{
LPWSTR result = StrRChrW(string+count+1, string + 127, count);
ok(!result, "found char %d not in the string\n", count);
}
}
static void test_StrCpyW(void)
{
WCHAR szSrc[256];
WCHAR szBuff[256];
const StrFormatSizeResult* result = StrFormatSize_results;
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);
result++;
}
}
static void test_StrToIntA(void)
{
const StrToIntResult *result = StrToInt_results;
int return_val;
while (result->string)
{
return_val = StrToIntA(result->string);
ok(return_val == result->str_to_int, "converted '%s' wrong (%d)\n",
result->string, return_val);
result++;
}
}
static void test_StrToIntW(void)
{
WCHAR szBuff[256];
const StrToIntResult *result = StrToInt_results;
int return_val;
while (result->string)
{
MultiByteToWideChar(0,0,result->string,-1,szBuff,sizeof(szBuff)/sizeof(WCHAR));
return_val = StrToIntW(szBuff);
ok(return_val == result->str_to_int, "converted '%s' wrong (%d)\n",
result->string, return_val);
result++;
}
}
static void test_StrToIntExA(void)
{
const StrToIntResult *result = StrToInt_results;
int return_val;
BOOL bRet;
while (result->string)
{
return_val = -1;
bRet = StrToIntExA(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_int_ex, "converted '%s' wrong (%d)\n",
result->string, return_val);
result++;
}
result = StrToInt_results;
while (result->string)
{
return_val = -1;
bRet = StrToIntExA(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_int_hex, "converted '%s' wrong (%d)\n",
result->string, return_val);
result++;
}
}
static void test_StrToIntExW(void)
{
WCHAR szBuff[256];
const StrToIntResult *result = StrToInt_results;
int return_val;
BOOL bRet;
while (result->string)
{
return_val = -1;
MultiByteToWideChar(0,0,result->string,-1,szBuff,sizeof(szBuff)/sizeof(WCHAR));
bRet = StrToIntExW(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_int_ex, "converted '%s' wrong (%d)\n",
result->string, return_val);
result++;
}
result = StrToInt_results;
while (result->string)
{
return_val = -1;
MultiByteToWideChar(0,0,result->string,-1,szBuff,sizeof(szBuff)/sizeof(WCHAR));
bRet = StrToIntExW(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_int_hex, "converted '%s' wrong (%d)\n",
result->string, return_val);
result++;
}
}
static void test_StrDupA(void)
{
LPSTR lpszStr;
const StrFormatSizeResult* result = StrFormatSize_results;
while(result->value)
{
lpszStr = StrDupA(result->byte_size_64);
ok(lpszStr != NULL, "Dup failed\n");
if (lpszStr)
{
ok(!strcmp(result->byte_size_64, lpszStr), "Copied string wrong\n");
LocalFree((HLOCAL)lpszStr);
}
result++;
}
/* Later versions of shlwapi return NULL for this, but earlier versions
* returned an empty string (as Wine does).
*/
lpszStr = StrDupA(NULL);
ok(lpszStr == NULL || *lpszStr == '\0', "NULL string returned %p\n", lpszStr);
}
static void test_StrFormatByteSize64A(void)
{
char szBuff[256];
const StrFormatSizeResult* result = StrFormatSize_results;
while(result->value)
{
StrFormatByteSize64A(result->value, szBuff, 256);
ok(!strcmp(result->byte_size_64, szBuff),
"Formatted %lx%08lx wrong: got %s, expected %s\n",
(LONG)(result->value >> 32), (LONG)result->value, szBuff, result->byte_size_64);
result++;
}
}
static void test_StrFormatKBSizeW(void)
{
WCHAR szBuffW[256];
char szBuff[256];
const StrFormatSizeResult* result = StrFormatSize_results;
while(result->value)
{
StrFormatKBSizeW(result->value, szBuffW, 256);
WideCharToMultiByte(0,0,szBuffW,-1,szBuff,sizeof(szBuff)/sizeof(WCHAR),0,0);
ok(!strcmp(result->kb_size, szBuff),
"Formatted %lx%08lx wrong: got %s, expected %s\n",
(LONG)(result->value >> 32), (LONG)result->value, szBuff, result->kb_size);
result++;
}
}
static void test_StrFormatKBSizeA(void)
{
char szBuff[256];
const StrFormatSizeResult* result = StrFormatSize_results;
while(result->value)
{
StrFormatKBSizeA(result->value, szBuff, 256);
ok(!strcmp(result->kb_size, szBuff),
"Formatted %lx%08lx wrong: got %s, expected %s\n",
(LONG)(result->value >> 32), (LONG)result->value, szBuff, result->kb_size);
result++;
}
}
static void test_StrFromTimeIntervalA(void)
{
char szBuff[256];
const StrFromTimeIntervalResult* result = StrFromTimeInterval_results;
while(result->ms)
{
StrFromTimeIntervalA(szBuff, 256, result->ms, result->digits);
ok(!strcmp(result->time_interval, szBuff), "Formatted %ld %d wrong\n",
result->ms, result->digits);
result++;
}
}
static void test_StrCmpA(void)
{
static const char str1[] = {'a','b','c','d','e','f'};
static const char str2[] = {'a','B','c','d','e','f'};
ok(0 != StrCmpNA(str1, str2, 6), "StrCmpNA is case-insensitive\n");
ok(0 == StrCmpNIA(str1, str2, 6), "StrCmpNIA is case-sensitive\n");
ok(!ChrCmpIA('a', 'a'), "ChrCmpIA doesn't work at all!\n");
ok(!ChrCmpIA('b', 'B'), "ChrCmpIA is not case-insensitive\n");
ok(ChrCmpIA('a', 'z'), "ChrCmpIA believes that a == z!\n");
pStrIsIntlEqualA = (void *)GetProcAddress(hShlwapi, "StrIsIntlEqualA");
pIntlStrEqWorkerA = (void *)GetProcAddress(hShlwapi, "IntlStrEqWorkerA");
if (!pStrIsIntlEqualA)
return;
ok(pStrIsIntlEqualA(FALSE, str1, str2, 5), "StrIsIntlEqualA(FALSE,...) isn't case-insensitive\n");
ok(!pStrIsIntlEqualA(TRUE, str1, str2, 5), "StrIsIntlEqualA(TRUE,...) isn't case-sensitive\n");
if (!pIntlStrEqWorkerA)
return;
ok(pIntlStrEqWorkerA(FALSE, str1, str2, 5), "IntlStrEqWorkerA(FALSE,...) isn't case-insensitive\n");
ok(!pIntlStrEqWorkerA(TRUE, str1, str2, 5), "pIntlStrEqWorkerA(TRUE,...) isn't case-sensitive\n");
}
static void test_StrCmpW(void)
{
static const WCHAR str1[] = {'a','b','c','d','e','f'};
static const WCHAR str2[] = {'a','B','c','d','e','f'};
ok(0 != StrCmpNW(str1, str2, 5), "StrCmpNW is case-insensitive\n");
ok(0 == StrCmpNIW(str1, str2, 5), "StrCmpNIW is case-sensitive\n");
ok(!ChrCmpIW('a', 'a'), "ChrCmpIW doesn't work at all!\n");
ok(!ChrCmpIW('b', 'B'), "ChrCmpIW is not case-insensitive\n");
ok(ChrCmpIW('a', 'z'), "ChrCmpIW believes that a == z!\n");
pStrIsIntlEqualW = (void *)GetProcAddress(hShlwapi, "StrIsIntlEqualW");
pIntlStrEqWorkerW = (void *)GetProcAddress(hShlwapi, "IntlStrEqWorkerW");
if (!pStrIsIntlEqualW)
return;
ok(pStrIsIntlEqualW(FALSE, str1, str2, 5), "StrIsIntlEqualW(FALSE,...) isn't case-insensitive\n");
ok(!pStrIsIntlEqualW(TRUE, str1, str2, 5), "StrIsIntlEqualW(TRUE,...) isn't case-sensitive\n");
if (!pIntlStrEqWorkerW)
return;
ok(pIntlStrEqWorkerW(FALSE, str1, str2, 5), "IntlStrEqWorkerW(FALSE,...) isn't case-insensitive\n");
ok(!pIntlStrEqWorkerW(TRUE, str1, str2, 5), "IntlStrEqWorkerW(TRUE,...) isn't case-sensitive\n");
}
static WCHAR *CoDupStrW(const char* src)
{
INT len = MultiByteToWideChar(CP_ACP, 0, src, -1, NULL, 0);
WCHAR* szTemp = (WCHAR*)CoTaskMemAlloc(len * sizeof(WCHAR));
MultiByteToWideChar(CP_ACP, 0, src, -1, szTemp, len);
return szTemp;
}
static void test_StrRetToBSTR(void)
{
static const WCHAR szTestW[] = { 'T','e','s','t','\0' };
ITEMIDLIST iidl[10];
BSTR bstr;
STRRET strret;
HRESULT ret;
pStrRetToBSTR = (void *)GetProcAddress(hShlwapi, "StrRetToBSTR");
if (!pStrRetToBSTR) return;
strret.uType = STRRET_WSTR;
strret.u.pOleStr = CoDupStrW("Test");
bstr = 0;
ret = pStrRetToBSTR(&strret, NULL, &bstr);
ok(ret == S_OK && bstr && !strcmpW(bstr, szTestW),
"STRRET_WSTR: dup failed, ret=0x%08lx, bstr %p\n", ret, bstr);
if (bstr)
SysFreeString(bstr);
strret.uType = STRRET_CSTR;
lstrcpyA(strret.u.cStr, "Test");
ret = pStrRetToBSTR(&strret, NULL, &bstr);
ok(ret == S_OK && bstr && !strcmpW(bstr, szTestW),
"STRRET_CSTR: dup failed, ret=0x%08lx, bstr %p\n", ret, bstr);
if (bstr)
SysFreeString(bstr);
strret.uType = STRRET_OFFSET;
strret.u.uOffset = 1;
strcpy((char*)&iidl, " Test");
ret = pStrRetToBSTR(&strret, iidl, &bstr);
ok(ret == S_OK && bstr && !strcmpW(bstr, szTestW),
"STRRET_OFFSET: dup failed, ret=0x%08lx, bstr %p\n", ret, bstr);
if (bstr)
SysFreeString(bstr);
/* Native crashes if str is NULL */
}
static void test_StrCpyNXA(void)
{
LPCSTR lpSrc = "hello";
LPSTR lpszRes;
char dest[8];
pStrCpyNXA = (void *)GetProcAddress(hShlwapi, (LPSTR)399);
if (!pStrCpyNXA)
return;
memset(dest, '\n', sizeof(dest));
lpszRes = pStrCpyNXA(dest, lpSrc, sizeof(dest)/sizeof(dest[0]));
ok(lpszRes == dest + 5 && !memcmp(dest, "hello\0\n\n", sizeof(dest)),
"StrCpyNXA: expected %p, \"hello\\0\\n\\n\", got %p, \"%d,%d,%d,%d,%d,%d,%d,%d\"\n",
dest + 5, lpszRes, dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
}
static void test_StrCpyNXW(void)
{
static const WCHAR lpInit[] = { '\n','\n','\n','\n','\n','\n','\n','\n' };
static const WCHAR lpSrc[] = { 'h','e','l','l','o','\0' };
static const WCHAR lpRes[] = { 'h','e','l','l','o','\0','\n','\n' };
LPWSTR lpszRes;
WCHAR dest[8];
pStrCpyNXW = (void *)GetProcAddress(hShlwapi, (LPSTR)400);
if (!pStrCpyNXW)
return;
memcpy(dest, lpInit, sizeof(lpInit));
lpszRes = pStrCpyNXW(dest, lpSrc, sizeof(dest)/sizeof(dest[0]));
ok(lpszRes == dest + 5 && !memcmp(dest, lpRes, sizeof(dest)),
"StrCpyNXA: expected %p, \"hello\\0\\n\\n\", got %p, \"%d,%d,%d,%d,%d,%d,%d,%d\"\n",
dest + 5, lpszRes, dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
}
static void test_SHAnsiToAnsi(void)
{
char dest[8];
DWORD dwRet;
pSHAnsiToAnsi = (void *)GetProcAddress(hShlwapi, (LPSTR)345);
if (!pSHAnsiToAnsi)
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)),
"SHAnsiToAnsi: expected 6, \"hello\\0\\n\\n\", got %ld, \"%d,%d,%d,%d,%d,%d,%d,%d\"\n",
dwRet, dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
}
static void test_SHUnicodeToUnicode(void)
{
static const WCHAR lpInit[] = { '\n','\n','\n','\n','\n','\n','\n','\n' };
static const WCHAR lpSrc[] = { 'h','e','l','l','o','\0' };
static const WCHAR lpRes[] = { 'h','e','l','l','o','\0','\n','\n' };
WCHAR dest[8];
DWORD dwRet;
pSHUnicodeToUnicode = (void *)GetProcAddress(hShlwapi, (LPSTR)346);
if (!pSHUnicodeToUnicode)
return;
memcpy(dest, lpInit, sizeof(lpInit));
dwRet = pSHUnicodeToUnicode(lpSrc, dest, sizeof(dest)/sizeof(dest[0]));
ok(dwRet == 6 && !memcmp(dest, lpRes, sizeof(dest)),
"SHUnicodeToUnicode: expected 6, \"hello\\0\\n\\n\", got %ld, \"%d,%d,%d,%d,%d,%d,%d,%d\"\n",
dwRet, dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
}
START_TEST(string)
{
CoInitialize(0);
hShlwapi = GetModuleHandleA("shlwapi");
if (!hShlwapi)
return;
test_StrChrA();
test_StrChrW();
test_StrChrIA();
test_StrChrIW();
test_StrRChrA();
test_StrRChrW();
test_StrCpyW();
test_StrToIntA();
test_StrToIntW();
test_StrToIntExA();
test_StrToIntExW();
test_StrDupA();
if (0)
{
/* this test fails on locales which do not use '.' as a decimal separator */
test_StrFormatByteSize64A();
/* this test fails on locales which do not use '.' as a decimal separator */
test_StrFormatKBSizeA();
/* FIXME: Awaiting NLS fixes in kernel before these succeed */
test_StrFormatKBSizeW();
}
test_StrFromTimeIntervalA();
test_StrCmpA();
test_StrCmpW();
test_StrRetToBSTR();
test_StrCpyNXA();
test_StrCpyNXW();
test_SHAnsiToAnsi();
test_SHUnicodeToUnicode();
}

View file

@ -0,0 +1,32 @@
/* Automatically generated file; DO NOT EDIT!! */
/* stdarg.h is needed for Winelib */
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include "windef.h"
#include "winbase.h"
extern void func_clist(void);
extern void func_ordinal(void);
extern void func_path(void);
extern void func_shreg(void);
extern void func_string(void);
struct test
{
const char *name;
void (*func)(void);
};
const struct test winetest_testlist[] =
{
{ "clist", func_clist },
{ "ordinal", func_ordinal },
{ "shreg", func_shreg },
{ "string", func_string },
{ 0, 0 }
};
#define WINETEST_WANT_MAIN
#include "wine/test.h"