-add_definitions(
- -D__ROS_LONG64__
- -D_DLL -D__USE_CRTIMP)
+add_definitions(-D__ROS_LONG64__)
remove_definitions(-DWINVER=0x502 -D_WIN32_IE=0x600 -D_WIN32_WINNT=0x502)
path.c
shreg.c
string.c
+ thread.c
url.c
- testlist.c
- thread.c)
+ testlist.c)
add_executable(shlwapi_winetest ${SOURCE})
target_link_libraries(shlwapi_winetest wine uuid)
static HRESULT (WINAPI *pSHLWAPI_214)(_IDummyStream*,ULARGE_INTEGER*);
-static void InitFunctionPtrs(void)
+static BOOL InitFunctionPtrs(void)
{
SHLWAPI_hshlwapi = GetModuleHandleA("shlwapi.dll");
+ /* SHCreateStreamOnFileEx was introduced in shlwapi v6.0 */
+ if(!GetProcAddress(SHLWAPI_hshlwapi, "SHCreateStreamOnFileEx")){
+ win_skip("Too old shlwapi version\n");
+ return FALSE;
+ }
+
pSHLWAPI_17 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)17);
ok(pSHLWAPI_17 != 0, "No Ordinal 17\n");
pSHLWAPI_18 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)18);
ok(pSHLWAPI_213 != 0, "No Ordinal 213\n");
pSHLWAPI_214 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)214);
ok(pSHLWAPI_214 != 0, "No Ordinal 214\n");
+
+ return TRUE;
}
static void InitDummyStream(_IDummyStream* iface)
inserted = (LPSHLWAPI_CLIST)buff;
inserted->ulSize = sizeof(SHLWAPI_CLIST) -1;
inserted->ulId = 33;
- hRet = pSHLWAPI_20(&list, inserted);
+
/* The call succeeds but the item is not inserted, except on some early
* versions which return failure. Wine behaves like later versions.
*/
- if (0)
- {
- ok(hRet == S_OK, "failed bad element size\n");
- }
+ pSHLWAPI_20(&list, inserted);
+
inserted = pSHLWAPI_22(list, 33);
ok(inserted == NULL, "inserted bad element size\n");
inserted = (LPSHLWAPI_CLIST)buff;
inserted->ulSize = 44;
inserted->ulId = ~0U;
- hRet = pSHLWAPI_20(&list, inserted);
+
/* See comment above, some early versions fail this call */
- if (0)
- {
- ok(hRet == S_OK, "failed adding a container\n");
- }
+ pSHLWAPI_20(&list, inserted);
+
item = SHLWAPI_CLIST_items;
/* Look for nonexistent item in populated list */
START_TEST(clist)
{
- InitFunctionPtrs();
+ if(!InitFunctionPtrs())
+ return;
test_CList();
static DWORD (WINAPI *pSHLWAPI_23)(REFGUID, LPSTR, INT) = 0;
/* GUIDs to test */
-const GUID * TEST_guids[] = {
+static const GUID * TEST_guids[] = {
&CLSID_ShellDesktop,
&CLSID_ShellLink,
&CATID_BrowsableShellExt,
NULL
};
-DEFINE_GUID(IID_Endianess, 0x01020304, 0x0506, 0x0708, 0x09, 0x0A, 0x0B,
+DEFINE_GUID(IID_Endianness, 0x01020304, 0x0506, 0x0708, 0x09, 0x0A, 0x0B,
0x0C, 0x0D, 0x0E, 0x0F, 0x0A);
static void test_ClassIDs(void)
i++;
}
- /* Test endianess */
- dwLen = pSHLWAPI_23(&IID_Endianess, szBuff, 256);
- ok(dwLen == (is_vista ? S_OK : 39), "wrong size %u for IID_Endianess\n", dwLen);
+ /* Test endianness */
+ dwLen = pSHLWAPI_23(&IID_Endianness, szBuff, 256);
+ ok(dwLen == (is_vista ? S_OK : 39), "wrong size %u for IID_Endianness\n", dwLen);
ok(!strcmp(szBuff, "{01020304-0506-0708-090A-0B0C0D0E0F0A}"),
- "Endianess Broken, got '%s'\n", szBuff);
+ "Endianness Broken, got '%s'\n", szBuff);
/* test lengths */
szBuff[0] = ':';
- dwLen = pSHLWAPI_23(&IID_Endianess, szBuff, 0);
+ dwLen = pSHLWAPI_23(&IID_Endianness, szBuff, 0);
ok(dwLen == (is_vista ? E_FAIL : 0), "accepted bad length\n");
ok(szBuff[0] == ':', "wrote to buffer with no length\n");
szBuff[0] = ':';
- dwLen = pSHLWAPI_23(&IID_Endianess, szBuff, 38);
+ dwLen = pSHLWAPI_23(&IID_Endianness, szBuff, 38);
ok(dwLen == (is_vista ? E_FAIL : 0), "accepted bad length\n");
ok(szBuff[0] == ':', "wrote to buffer with no length\n");
szBuff[0] = ':';
- dwLen = pSHLWAPI_23(&IID_Endianess, szBuff, 39);
+ dwLen = pSHLWAPI_23(&IID_Endianness, szBuff, 39);
ok(dwLen == (is_vista ? S_OK : 39), "rejected ok length\n");
ok(szBuff[0] == '{', "Didn't write to buffer with ok length\n");
bRet = pSHLWAPI_269(szBuff, &guid);
ok(bRet == FALSE, "accepted invalid string\n");
- dwLen = pSHLWAPI_23(&IID_Endianess, szBuff, 39);
+ dwLen = pSHLWAPI_23(&IID_Endianness, szBuff, 39);
ok(dwLen == (is_vista ? S_OK : 39), "rejected ok length\n");
ok(szBuff[0] == '{', "Didn't write to buffer with ok length\n");
}
START_TEST(clsid)
{
hShlwapi = GetModuleHandleA("shlwapi.dll");
+
+ /* SHCreateStreamOnFileEx was introduced in shlwapi v6.0 */
+ if(!GetProcAddress(hShlwapi, "SHCreateStreamOnFileEx")){
+ win_skip("Too old shlwapi version\n");
+ return;
+ }
+
pSHLWAPI_269 = (void*)GetProcAddress(hShlwapi, (LPSTR)269);
pSHLWAPI_23 = (void*)GetProcAddress(hShlwapi, (LPSTR)23);
ok(stream != NULL, "SHCreateStreamOnFileA: expected a valid IStream object, got NULL\n");
if (stream) {
+ BOOL delret;
test_IStream_invalid_operations(stream, mode);
refcount = IStream_Release(stream);
ok(refcount == 0, "SHCreateStreamOnFileA: expected 0, got %d\n", refcount);
- ok(DeleteFileA(test_file), "SHCreateStreamOnFileA: could not delete file '%s', got error %d\n", test_file, GetLastError());
+ delret = DeleteFileA(test_file);
+ ok(delret, "SHCreateStreamOnFileA: could not delete file '%s', got error %d\n",
+ test_file, GetLastError());
}
}
ok(stream != NULL, "SHCreateStreamOnFileW: expected a valid IStream object, got NULL\n");
if (stream) {
+ BOOL delret;
test_IStream_invalid_operations(stream, mode);
refcount = IStream_Release(stream);
ok(refcount == 0, "SHCreateStreamOnFileW: expected 0, got %d\n", refcount);
- ok(DeleteFileA(test_fileA),
- "SHCreateStreamOnFileW: could not delete the test file, got error %d\n",
- GetLastError());
+ delret = DeleteFileA(test_fileA);
+ ok(delret, "SHCreateStreamOnFileW: could not delete the test file, got error %d\n",
+ GetLastError());
}
}
WCHAR test_file[MAX_PATH];
CHAR test_fileA[MAX_PATH];
static const CHAR testEx_txt[] = "\\testEx.txt";
+ BOOL delret;
trace("SHCreateStreamOnFileEx: testing mode %d, STGM flags %08x\n", mode, stgm);
refcount = IStream_Release(stream);
ok(refcount == 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount);
- ok(DeleteFileA(test_fileA),
- "SHCreateStreamOnFileEx: could not delete the test file, got error %d\n",
- GetLastError());
+ delret = DeleteFileA(test_fileA);
+ ok(delret, "SHCreateStreamOnFileEx: could not delete the test file, got error %d\n",
+ GetLastError());
}
stream = NULL;
refcount = IStream_Release(stream);
ok(refcount == 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount);
- ok(DeleteFileA(test_fileA),
- "SHCreateStreamOnFileEx: could not delete the test file, got error %d\n",
- GetLastError());
+ delret = DeleteFileA(test_fileA);
+ ok(delret, "SHCreateStreamOnFileEx: could not delete the test file, got error %d\n",
+ GetLastError());
}
stream = NULL;
ok(refcount == 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount);
}
- ok(DeleteFileA(test_fileA),
- "SHCreateStreamOnFileEx: could not delete the test file, got error %d\n",
- GetLastError());
+ delret = DeleteFileA(test_fileA);
+ ok(delret, "SHCreateStreamOnFileEx: could not delete the test file, got error %d\n",
+ GetLastError());
}
#include <stdio.h>
#define COBJMACROS
+#define CONST_VTABLE
#include "wine/test.h"
#include "winbase.h"
#include "winerror.h"
#include "shlwapi.h"
#include "docobj.h"
#include "shobjidl.h"
+#include "shlobj.h"
/* Function ptrs for ordinal calls */
static HMODULE hShlwapi;
static BOOL is_win2k_and_lower;
+static BOOL is_win9x;
static int (WINAPI *pSHSearchMapInt)(const int*,const int*,int,int);
static HRESULT (WINAPI *pGetAcceptLanguagesA)(LPSTR,LPDWORD);
static HRESULT (WINAPI *pIUnknown_QueryServiceExec)(IUnknown*, REFIID, const GUID*, DWORD, DWORD, VARIANT*, VARIANT*);
static HRESULT (WINAPI *pIUnknown_ProfferService)(IUnknown*, REFGUID, IServiceProvider*, DWORD*);
static HWND (WINAPI *pSHCreateWorkerWindowA)(LONG, HWND, DWORD, DWORD, HMENU, LONG_PTR);
+static HRESULT (WINAPI *pSHIShellFolder_EnumObjects)(LPSHELLFOLDER, HWND, SHCONTF, IEnumIDList**);
+static DWORD (WINAPI *pSHGetIniStringW)(LPCWSTR, LPCWSTR, LPWSTR, DWORD, LPCWSTR);
+static BOOL (WINAPI *pSHSetIniStringW)(LPCWSTR, LPCWSTR, LPCWSTR, LPCWSTR);
+static HKEY (WINAPI *pSHGetShellKey)(DWORD, LPCWSTR, BOOL);
+static HRESULT (WINAPI *pSKGetValueW)(DWORD, LPCWSTR, LPCWSTR, DWORD*, void*, DWORD*);
+static HRESULT (WINAPI *pSKSetValueW)(DWORD, LPCWSTR, LPCWSTR, DWORD, void*, DWORD);
+static HRESULT (WINAPI *pSKDeleteValueW)(DWORD, LPCWSTR, LPCWSTR);
+static HRESULT (WINAPI *pSKAllocValueW)(DWORD, LPCWSTR, LPCWSTR, DWORD*, void**, DWORD*);
+static HWND (WINAPI *pSHSetParentHwnd)(HWND, HWND);
static HMODULE hmlang;
static HRESULT (WINAPI *pLcidToRfc1766A)(LCID, LPSTR, INT);
+static HMODULE hshell32;
+static HRESULT (WINAPI *pSHGetDesktopFolder)(IShellFolder**);
+
static const CHAR ie_international[] = {
'S','o','f','t','w','a','r','e','\\',
'M','i','c','r','o','s','o','f','t','\\',
static const CHAR acceptlanguage[] = {
'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0};
+static int strcmp_wa(LPCWSTR strw, const char *stra)
+{
+ CHAR buf[512];
+ WideCharToMultiByte(CP_ACP, 0, strw, -1, buf, sizeof(buf), NULL, NULL);
+ return lstrcmpA(stra, buf);
+}
+
typedef struct {
int id;
const void *args[5];
buffer[maxlen] = 0;
hr = pGetAcceptLanguagesA( buffer, &len);
/* When the buffer is too small, win7_32 and w2k8_64 and above fail with
- HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), other versions suceed
+ HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), other versions succeed
and return a partial 0 terminated result while other versions
fail with E_INVALIDARG and return a partial unterminated result */
ok( (((hr == S_OK) || (hr == E_INVALIDARG)) && !memcmp(buffer, language, len)) ||
};
SECURITY_DESCRIPTOR* psd;
SECURITY_DESCRIPTOR* (WINAPI*pGetShellSecurityDescriptor)(PSHELL_USER_PERMISSION*,int);
+ void *pChrCmpIW = GetProcAddress(hShlwapi, "ChrCmpIW");
pGetShellSecurityDescriptor=(void*)GetProcAddress(hShlwapi,(char*)475);
return;
}
+ if(pChrCmpIW && pChrCmpIW == pGetShellSecurityDescriptor) /* win2k */
+ {
+ win_skip("Skipping for GetShellSecurityDescriptor, same ordinal used for ChrCmpIW\n");
+ return;
+ }
+
psd = pGetShellSecurityDescriptor(NULL, 2);
ok(psd==NULL ||
broken(psd==INVALID_HANDLE_VALUE), /* IE5 */
"GetShellSecurityDescriptor should fail\n");
psd = pGetShellSecurityDescriptor(rgsup, 0);
- ok(psd==NULL, "GetShellSecurityDescriptor should fail\n");
+ ok(psd==NULL, "GetShellSecurityDescriptor should fail, got %p\n", psd);
SetLastError(0xdeadbeef);
psd = pGetShellSecurityDescriptor(rgsup, 2);
win_skip("GetShellSecurityDescriptor is not implemented\n");
return;
}
- if (psd==INVALID_HANDLE_VALUE)
+ if (psd == INVALID_HANDLE_VALUE)
{
win_skip("GetShellSecurityDescriptor is broken on IE5\n");
return;
ok(psd!=NULL, "GetShellSecurityDescriptor failed\n");
if (psd!=NULL)
{
- BOOL bHasDacl = FALSE, bDefaulted;
+ BOOL bHasDacl = FALSE, bDefaulted, ret;
PACL pAcl;
DWORD dwRev;
SECURITY_DESCRIPTOR_CONTROL control;
ok(IsValidSecurityDescriptor(psd), "returned value is not valid SD\n");
- ok(GetSecurityDescriptorControl(psd, &control, &dwRev),
- "GetSecurityDescriptorControl failed with error %u\n", GetLastError());
+ ret = GetSecurityDescriptorControl(psd, &control, &dwRev);
+ ok(ret, "GetSecurityDescriptorControl failed with error %u\n", GetLastError());
ok(0 == (control & SE_SELF_RELATIVE), "SD should be absolute\n");
- ok(GetSecurityDescriptorDacl(psd, &bHasDacl, &pAcl, &bDefaulted),
- "GetSecurityDescriptorDacl failed with error %u\n", GetLastError());
+ ret = GetSecurityDescriptorDacl(psd, &bHasDacl, &pAcl, &bDefaulted);
+ ok(ret, "GetSecurityDescriptorDacl failed with error %u\n", GetLastError());
ok(bHasDacl, "SD has no DACL\n");
if (bHasDacl)
ok(IsValidAcl(pAcl), "DACL is not valid\n");
- ok(GetAclInformation(pAcl, &asiSize, sizeof(asiSize), AclSizeInformation),
- "GetAclInformation failed with error %u\n", GetLastError());
+ ret = GetAclInformation(pAcl, &asiSize, sizeof(asiSize), AclSizeInformation);
+ ok(ret, "GetAclInformation failed with error %u\n", GetLastError());
ok(asiSize.AceCount == 3, "Incorrect number of ACEs: %d entries\n", asiSize.AceCount);
if (asiSize.AceCount == 3)
{
ACCESS_ALLOWED_ACE *paaa; /* will use for DENIED too */
- ok(GetAce(pAcl, 0, (LPVOID*)&paaa), "GetAce failed with error %u\n", GetLastError());
+ ret = GetAce(pAcl, 0, (LPVOID*)&paaa);
+ ok(ret, "GetAce failed with error %u\n", GetLastError());
ok(paaa->Header.AceType == ACCESS_ALLOWED_ACE_TYPE,
"Invalid ACE type %d\n", paaa->Header.AceType);
ok(paaa->Header.AceFlags == 0, "Invalid ACE flags %x\n", paaa->Header.AceFlags);
ok(paaa->Mask == GENERIC_ALL, "Invalid ACE mask %x\n", paaa->Mask);
- ok(GetAce(pAcl, 1, (LPVOID*)&paaa), "GetAce failed with error %u\n", GetLastError());
+ ret = GetAce(pAcl, 1, (LPVOID*)&paaa);
+ ok(ret, "GetAce failed with error %u\n", GetLastError());
ok(paaa->Header.AceType == ACCESS_DENIED_ACE_TYPE,
"Invalid ACE type %d\n", paaa->Header.AceType);
/* first one of two ACEs generated from inheritable entry - without inheritance */
ok(paaa->Header.AceFlags == 0, "Invalid ACE flags %x\n", paaa->Header.AceFlags);
ok(paaa->Mask == GENERIC_WRITE, "Invalid ACE mask %x\n", paaa->Mask);
- ok(GetAce(pAcl, 2, (LPVOID*)&paaa), "GetAce failed with error %u\n", GetLastError());
+ ret = GetAce(pAcl, 2, (LPVOID*)&paaa);
+ ok(ret, "GetAce failed with error %u\n", GetLastError());
ok(paaa->Header.AceType == ACCESS_DENIED_ACE_TYPE,
"Invalid ACE type %d\n", paaa->Header.AceType);
/* second ACE - with inheritance */
typedef struct _disp
{
- const IDispatchVtbl *vtbl;
+ IDispatch IDispatch_iface;
LONG refCount;
} Disp;
+static inline Disp *impl_from_IDispatch(IDispatch *iface)
+{
+ return CONTAINING_RECORD(iface, Disp, IDispatch_iface);
+}
+
typedef struct _contain
{
- const IConnectionPointContainerVtbl *vtbl;
+ IConnectionPointContainer IConnectionPointContainer_iface;
LONG refCount;
UINT ptCount;
IConnectionPoint **pt;
} Contain;
+static inline Contain *impl_from_IConnectionPointContainer(IConnectionPointContainer *iface)
+{
+ return CONTAINING_RECORD(iface, Contain, IConnectionPointContainer_iface);
+}
+
typedef struct _cntptn
{
- const IConnectionPointVtbl *vtbl;
+ IConnectionPoint IConnectionPoint_iface;
LONG refCount;
Contain *container;
IUnknown **sink;
} ConPt;
+static inline ConPt *impl_from_IConnectionPoint(IConnectionPoint *iface)
+{
+ return CONTAINING_RECORD(iface, ConPt, IConnectionPoint_iface);
+}
+
typedef struct _enum
{
- const IEnumConnectionsVtbl *vtbl;
+ IEnumConnections IEnumConnections_iface;
LONG refCount;
UINT idx;
ConPt *pt;
} EnumCon;
+static inline EnumCon *impl_from_IEnumConnections(IEnumConnections *iface)
+{
+ return CONTAINING_RECORD(iface, EnumCon, IEnumConnections_iface);
+}
+
typedef struct _enumpt
{
- const IEnumConnectionPointsVtbl *vtbl;
+ IEnumConnectionPoints IEnumConnectionPoints_iface;
LONG refCount;
int idx;
Contain *container;
} EnumPt;
+static inline EnumPt *impl_from_IEnumConnectionPoints(IEnumConnectionPoints *iface)
+{
+ return CONTAINING_RECORD(iface, EnumPt, IEnumConnectionPoints_iface);
+}
+
static HRESULT WINAPI Disp_QueryInterface(
IDispatch* This,
if (*ppvObject)
{
- IUnknown_AddRef(This);
+ IDispatch_AddRef(This);
return S_OK;
}
static ULONG WINAPI Disp_AddRef(IDispatch* This)
{
- Disp *iface = (Disp*)This;
+ Disp *iface = impl_from_IDispatch(This);
return InterlockedIncrement(&iface->refCount);
}
static ULONG WINAPI Disp_Release(IDispatch* This)
{
- Disp *iface = (Disp*)This;
+ Disp *iface = impl_from_IDispatch(This);
ULONG ret;
ret = InterlockedDecrement(&iface->refCount);
if (*ppvObject)
{
- IUnknown_AddRef(This);
+ IEnumConnections_AddRef(This);
return S_OK;
}
static ULONG WINAPI Enum_AddRef(IEnumConnections* This)
{
- EnumCon *iface = (EnumCon*)This;
+ EnumCon *iface = impl_from_IEnumConnections(This);
return InterlockedIncrement(&iface->refCount);
}
static ULONG WINAPI Enum_Release(IEnumConnections* This)
{
- EnumCon *iface = (EnumCon*)This;
+ EnumCon *iface = impl_from_IEnumConnections(This);
ULONG ret;
ret = InterlockedDecrement(&iface->refCount);
LPCONNECTDATA rgcd,
ULONG *pcFetched)
{
- EnumCon *iface = (EnumCon*)This;
+ EnumCon *iface = impl_from_IEnumConnections(This);
if (cConnections > 0 && iface->idx < iface->pt->sinkCount)
{
if (*ppvObject)
{
- IUnknown_AddRef(This);
+ IConnectionPoint_AddRef(This);
return S_OK;
}
static ULONG WINAPI ConPt_AddRef(
IConnectionPoint* This)
{
- ConPt *iface = (ConPt*)This;
+ ConPt *iface = impl_from_IConnectionPoint(This);
return InterlockedIncrement(&iface->refCount);
}
static ULONG WINAPI ConPt_Release(
IConnectionPoint* This)
{
- ConPt *iface = (ConPt*)This;
+ ConPt *iface = impl_from_IConnectionPoint(This);
ULONG ret;
ret = InterlockedDecrement(&iface->refCount);
IID *pIID)
{
static int i = 0;
- ConPt *iface = (ConPt*)This;
+ ConPt *iface = impl_from_IConnectionPoint(This);
if (i==0)
{
i++;
IConnectionPoint* This,
IConnectionPointContainer **ppCPC)
{
- ConPt *iface = (ConPt*)This;
+ ConPt *iface = impl_from_IConnectionPoint(This);
- *ppCPC = (IConnectionPointContainer*)iface->container;
+ *ppCPC = &iface->container->IConnectionPointContainer_iface;
return S_OK;
}
IUnknown *pUnkSink,
DWORD *pdwCookie)
{
- ConPt *iface = (ConPt*)This;
+ ConPt *iface = impl_from_IConnectionPoint(This);
if (iface->sinkCount == 0)
iface->sink = HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown*));
IConnectionPoint* This,
DWORD dwCookie)
{
- ConPt *iface = (ConPt*)This;
+ ConPt *iface = impl_from_IConnectionPoint(This);
if (dwCookie > iface->sinkCount)
return E_FAIL;
EnumCon *ec;
ec = HeapAlloc(GetProcessHeap(),0,sizeof(EnumCon));
- ec->vtbl = &enum_vtbl;
+ ec->IEnumConnections_iface.lpVtbl = &enum_vtbl;
ec->refCount = 1;
- ec->pt = (ConPt*)This;
+ ec->pt = impl_from_IConnectionPoint(This);
ec->idx = 0;
- *ppEnum = (IEnumConnections*)ec;
+ *ppEnum = &ec->IEnumConnections_iface;
return S_OK;
}
if (*ppvObject)
{
- IUnknown_AddRef(This);
+ IEnumConnectionPoints_AddRef(This);
return S_OK;
}
static ULONG WINAPI EnumPt_AddRef(IEnumConnectionPoints* This)
{
- EnumPt *iface = (EnumPt*)This;
+ EnumPt *iface = impl_from_IEnumConnectionPoints(This);
return InterlockedIncrement(&iface->refCount);
}
static ULONG WINAPI EnumPt_Release(IEnumConnectionPoints* This)
{
- EnumPt *iface = (EnumPt*)This;
+ EnumPt *iface = impl_from_IEnumConnectionPoints(This);
ULONG ret;
ret = InterlockedDecrement(&iface->refCount);
IConnectionPoint **rgcd,
ULONG *pcFetched)
{
- EnumPt *iface = (EnumPt*)This;
+ EnumPt *iface = impl_from_IEnumConnectionPoints(This);
if (cConnections > 0 && iface->idx < iface->container->ptCount)
{
*rgcd = iface->container->pt[iface->idx];
- IUnknown_AddRef(iface->container->pt[iface->idx]);
+ IConnectionPoint_AddRef(iface->container->pt[iface->idx]);
if (pcFetched)
*pcFetched = 1;
iface->idx++;
if (*ppvObject)
{
- IUnknown_AddRef(This);
+ IConnectionPointContainer_AddRef(This);
return S_OK;
}
static ULONG WINAPI Contain_AddRef(
IConnectionPointContainer* This)
{
- Contain *iface = (Contain*)This;
+ Contain *iface = impl_from_IConnectionPointContainer(This);
return InterlockedIncrement(&iface->refCount);
}
static ULONG WINAPI Contain_Release(
IConnectionPointContainer* This)
{
- Contain *iface = (Contain*)This;
+ Contain *iface = impl_from_IConnectionPointContainer(This);
ULONG ret;
ret = InterlockedDecrement(&iface->refCount);
{
int i;
for (i = 0; i < iface->ptCount; i++)
- IUnknown_Release(iface->pt[i]);
+ IConnectionPoint_Release(iface->pt[i]);
HeapFree(GetProcessHeap(),0,iface->pt);
}
HeapFree(GetProcessHeap(),0,This);
EnumPt *ec;
ec = HeapAlloc(GetProcessHeap(),0,sizeof(EnumPt));
- ec->vtbl = &enumpt_vtbl;
+ ec->IEnumConnectionPoints_iface.lpVtbl = &enumpt_vtbl;
ec->refCount = 1;
ec->idx= 0;
- ec->container = (Contain*)This;
- *ppEnum = (IEnumConnectionPoints*)ec;
+ ec->container = impl_from_IConnectionPointContainer(This);
+ *ppEnum = &ec->IEnumConnectionPoints_iface;
return S_OK;
}
REFIID riid,
IConnectionPoint **ppCP)
{
- Contain *iface = (Contain*)This;
+ Contain *iface = impl_from_IConnectionPointContainer(This);
ConPt *pt;
if (!IsEqualIID(riid, &IID_NULL) || iface->ptCount ==0)
{
pt = HeapAlloc(GetProcessHeap(),0,sizeof(ConPt));
- pt->vtbl = &point_vtbl;
+ pt->IConnectionPoint_iface.lpVtbl = &point_vtbl;
pt->refCount = 1;
pt->sinkCount = 0;
pt->sink = NULL;
iface->pt =HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown*));
else
iface->pt = HeapReAlloc(GetProcessHeap(),0,iface->pt,sizeof(IUnknown*)*(iface->ptCount+1));
- iface->pt[iface->ptCount] = (IConnectionPoint*)pt;
+ iface->pt[iface->ptCount] = &pt->IConnectionPoint_iface;
iface->ptCount++;
- *ppCP = (IConnectionPoint*)pt;
+ *ppCP = &pt->IConnectionPoint_iface;
}
else
{
}
container = HeapAlloc(GetProcessHeap(),0,sizeof(Contain));
- container->vtbl = &contain_vtbl;
+ container->IConnectionPointContainer_iface.lpVtbl = &contain_vtbl;
container->refCount = 1;
container->ptCount = 0;
container->pt = NULL;
dispatch = HeapAlloc(GetProcessHeap(),0,sizeof(Disp));
- dispatch->vtbl = &disp_vtbl;
+ dispatch->IDispatch_iface.lpVtbl = &disp_vtbl;
dispatch->refCount = 1;
rc = pConnectToConnectionPoint((IUnknown*)dispatch, &IID_NULL, TRUE, (IUnknown*)container, &cookie, &point);
typedef struct _propbag
{
- const IPropertyBagVtbl *vtbl;
+ IPropertyBag IPropertyBag_iface;
LONG refCount;
} PropBag;
+static inline PropBag *impl_from_IPropertyBag(IPropertyBag *iface)
+{
+ return CONTAINING_RECORD(iface, PropBag, IPropertyBag_iface);
+}
+
static HRESULT WINAPI Prop_QueryInterface(
IPropertyBag* This,
if (*ppvObject)
{
- IUnknown_AddRef(This);
+ IPropertyBag_AddRef(This);
return S_OK;
}
static ULONG WINAPI Prop_AddRef(
IPropertyBag* This)
{
- PropBag *iface = (PropBag*)This;
+ PropBag *iface = impl_from_IPropertyBag(This);
return InterlockedIncrement(&iface->refCount);
}
static ULONG WINAPI Prop_Release(
IPropertyBag* This)
{
- PropBag *iface = (PropBag*)This;
+ PropBag *iface = impl_from_IPropertyBag(This);
ULONG ret;
ret = InterlockedDecrement(&iface->refCount);
pb = HeapAlloc(GetProcessHeap(),0,sizeof(PropBag));
pb->refCount = 1;
- pb->vtbl = &prop_vtbl;
+ pb->IPropertyBag_iface.lpVtbl = &prop_vtbl;
out = 0xfeedface;
rc = pSHPropertyBag_ReadLONG(NULL, szName1, &out);
ok(rc == E_INVALIDARG || broken(rc == 0), "incorrect return %x\n",rc);
ok(out == 0xfeedface, "value should not have changed\n");
- rc = pSHPropertyBag_ReadLONG((IPropertyBag*)pb, NULL, &out);
+ rc = pSHPropertyBag_ReadLONG(&pb->IPropertyBag_iface, NULL, &out);
ok(rc == E_INVALIDARG || broken(rc == 0) || broken(rc == 1), "incorrect return %x\n",rc);
ok(out == 0xfeedface, "value should not have changed\n");
- rc = pSHPropertyBag_ReadLONG((IPropertyBag*)pb, szName1, NULL);
+ rc = pSHPropertyBag_ReadLONG(&pb->IPropertyBag_iface, szName1, NULL);
ok(rc == E_INVALIDARG || broken(rc == 0) || broken(rc == 1), "incorrect return %x\n",rc);
- ok(out == 0xfeedface, "value should not have changed\n");
- rc = pSHPropertyBag_ReadLONG((IPropertyBag*)pb, szName1, &out);
+ rc = pSHPropertyBag_ReadLONG(&pb->IPropertyBag_iface, szName1, &out);
ok(rc == DISP_E_BADVARTYPE || broken(rc == 0) || broken(rc == 1), "incorrect return %x\n",rc);
ok(out == 0xfeedface || broken(out == 0xfeedfa00), "value should not have changed %x\n",out);
IUnknown_Release((IUnknown*)pb);
if (0)
{
/* crashes on native */
- ret = pSHFormatDateTimeA(NULL, NULL, NULL, 0);
+ pSHFormatDateTimeA(NULL, NULL, NULL, 0);
}
GetLocalTime(&st);
SetLastError(0xdeadbeef);
ret = pSHFormatDateTimeA(&filetime, NULL, NULL, 0);
ok(ret == 0, "got %d\n", ret);
- ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
+ ok(GetLastError() == 0xdeadbeef || broken(GetLastError() == ERROR_SUCCESS /* Win7 */),
+ "expected 0xdeadbeef, got %d\n", GetLastError());
SetLastError(0xdeadbeef);
buff[0] = 'a'; buff[1] = 0;
flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGDATE | FDTF_SHORTTIME;
ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
ok(ret == lstrlenA(buff)+1, "got %d, length %d\n", ret, lstrlenA(buff)+1);
- ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
- ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
- strcat(buff2, ", ");
ret = GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3));
ok(ret == lstrlenA(buff3)+1, "got %d\n", ret);
- strcat(buff2, buff3);
- ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
+ ok(lstrcmpA(buff3, buff + lstrlenA(buff) - lstrlenA(buff3)) == 0,
+ "expected (%s), got (%s) for time part\n",
+ buff3, buff + lstrlenA(buff) - lstrlenA(buff3));
+ ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
+ ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
+ buff[lstrlenA(buff2)] = '\0';
+ ok(lstrcmpA(buff2, buff) == 0, "expected (%s) got (%s) for date part\n",
+ buff2, buff);
flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGDATE | FDTF_LONGTIME;
ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
- ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
- ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
- strcat(buff2, ", ");
ret = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3));
ok(ret == lstrlenA(buff3)+1, "got %d\n", ret);
- strcat(buff2, buff3);
- ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
+ ok(lstrcmpA(buff3, buff + lstrlenA(buff) - lstrlenA(buff3)) == 0,
+ "expected (%s), got (%s) for time part\n",
+ buff3, buff + lstrlenA(buff) - lstrlenA(buff3));
+ ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
+ ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
+ buff[lstrlenA(buff2)] = '\0';
+ ok(lstrcmpA(buff2, buff) == 0, "expected (%s) got (%s) for date part\n",
+ buff2, buff);
flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTDATE | FDTF_SHORTTIME;
ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
static void test_SHFormatDateTimeW(void)
{
FILETIME UNALIGNED filetime;
- WCHAR buff[100], buff2[100], buff3[100];
+ WCHAR buff[100], buff2[100], buff3[100], *p1, *p2;
SYSTEMTIME st;
DWORD flags;
INT ret;
static const WCHAR spaceW[] = {' ',0};
- static const WCHAR commaW[] = {',',' ',0};
+#define UNICODE_LTR_MARK 0x200e
if(!pSHFormatDateTimeW)
{
if (0)
{
/* crashes on native */
- ret = pSHFormatDateTimeW(NULL, NULL, NULL, 0);
+ pSHFormatDateTimeW(NULL, NULL, NULL, 0);
}
GetLocalTime(&st);
/* no way to get required buffer length here */
SetLastError(0xdeadbeef);
ret = pSHFormatDateTimeW(&filetime, NULL, NULL, 0);
- ok(ret == 0, "got %d\n", ret);
+ ok(ret == 0, "expected 0, got %d\n", ret);
ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
SetLastError(0xdeadbeef);
buff[0] = 'a'; buff[1] = 0;
ret = pSHFormatDateTimeW(&filetime, NULL, buff, 0);
- ok(ret == 0, "got %d\n", ret);
+ ok(ret == 0, "expected 0, got %d\n", ret);
ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
ok(buff[0] == 'a', "expected same string\n");
flags = FDTF_SHORTTIME | FDTF_LONGTIME;
SetLastError(0xdeadbeef);
ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
- ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
+ ok(ret == lstrlenW(buff)+1 || ret == lstrlenW(buff),
+ "expected %d or %d, got %d\n", lstrlenW(buff)+1, lstrlenW(buff), ret);
ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
flags = FDTF_SHORTDATE | FDTF_LONGDATE;
SetLastError(0xdeadbeef);
ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
- ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
+ ok(ret == lstrlenW(buff)+1 || ret == lstrlenW(buff),
+ "expected %d or %d, got %d\n", lstrlenW(buff)+1, lstrlenW(buff), ret);
ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
flags = FDTF_SHORTDATE | FDTF_LTRDATE | FDTF_RTLDATE;
SetLastError(0xdeadbeef);
buff[0] = 0; /* NT4 doesn't clear the buffer on failure */
ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
- ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
+ ok(ret == lstrlenW(buff)+1 || ret == lstrlenW(buff),
+ "expected %d or %d, got %d\n", lstrlenW(buff)+1, lstrlenW(buff), ret);
ok(GetLastError() == 0xdeadbeef ||
broken(GetLastError() == ERROR_INVALID_FLAGS), /* Win9x/WinMe/NT4 */
"expected 0xdeadbeef, got %d\n", GetLastError());
/* now check returned strings */
flags = FDTF_SHORTTIME;
ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
- ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
+ ok(ret == lstrlenW(buff)+1 || ret == lstrlenW(buff),
+ "expected %d or %d, got %d\n", lstrlenW(buff)+1, lstrlenW(buff), ret);
SetLastError(0xdeadbeef);
ret = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
if (ret == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
win_skip("Needed W-functions are not implemented\n");
return;
}
- ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
+ ok(ret == lstrlenW(buff2)+1, "expected %d, got %d\n", lstrlenW(buff2)+1, ret);
ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
flags = FDTF_LONGTIME;
ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
- ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
+ ok(ret == lstrlenW(buff)+1 || ret == lstrlenW(buff),
+ "expected %d or %d, got %d\n", lstrlenW(buff)+1, lstrlenW(buff), ret);
ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
- ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
+ ok(ret == lstrlenW(buff2)+1, "expected %d, got %d\n", lstrlenW(buff2)+1, ret);
ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
/* both time flags */
flags = FDTF_LONGTIME | FDTF_SHORTTIME;
ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
- ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
+ ok(ret == lstrlenW(buff)+1 || ret == lstrlenW(buff),
+ "expected %d or %d, got %d\n", lstrlenW(buff)+1, lstrlenW(buff), ret);
ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
- ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
+ ok(ret == lstrlenW(buff2)+1, "expected %d, got %d\n", lstrlenW(buff2)+1, ret);
ok(lstrcmpW(buff, buff2) == 0, "expected equal string\n");
flags = FDTF_SHORTDATE;
ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
- ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
+ ok(ret == lstrlenW(buff)+1 || ret == lstrlenW(buff),
+ "expected %d or %d, got %d\n", lstrlenW(buff)+1, lstrlenW(buff), ret);
ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
- ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
+ ok(ret == lstrlenW(buff2)+1, "expected %d, got %d\n", lstrlenW(buff2)+1, ret);
ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
flags = FDTF_LONGDATE;
ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
- ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
+ ok(ret == lstrlenW(buff)+1 || ret == lstrlenW(buff),
+ "expected %d or %d, got %d\n", lstrlenW(buff)+1, lstrlenW(buff), ret);
ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
- ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
+ ok(ret == lstrlenW(buff2)+1, "expected %d, got %d\n", lstrlenW(buff2)+1, ret);
ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
/* both date flags */
flags = FDTF_LONGDATE | FDTF_SHORTDATE;
ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
- ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
+ ok(ret == lstrlenW(buff)+1 || ret == lstrlenW(buff),
+ "expected %d or %d, got %d\n", lstrlenW(buff)+1, lstrlenW(buff), ret);
ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
- ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
+ ok(ret == lstrlenW(buff2)+1, "expected %d, got %d\n", lstrlenW(buff2)+1, ret);
ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
/* various combinations of date/time flags */
flags = FDTF_LONGDATE | FDTF_SHORTTIME;
ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
- ok(ret == lstrlenW(buff)+1, "got %d, length %d\n", ret, lstrlenW(buff)+1);
- ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
- ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
- lstrcatW(buff2, commaW);
+ ok(ret == lstrlenW(buff)+1 || ret == lstrlenW(buff),
+ "expected %d or %d, got %d\n", lstrlenW(buff)+1, lstrlenW(buff), ret);
ret = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
- ok(ret == lstrlenW(buff3)+1, "got %d\n", ret);
- lstrcatW(buff2, buff3);
- ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
+ ok(ret == lstrlenW(buff3)+1, "expected %d, got %d\n", lstrlenW(buff3)+1, ret);
+ ok(lstrcmpW(buff3, buff + lstrlenW(buff) - lstrlenW(buff3)) == 0,
+ "expected (%s), got (%s) for time part\n",
+ wine_dbgstr_w(buff3), wine_dbgstr_w(buff + lstrlenW(buff) - lstrlenW(buff3)));
+ ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
+ ok(ret == lstrlenW(buff2)+1, "expected %d, got %d\n", lstrlenW(buff2)+1, ret);
+ p1 = buff;
+ p2 = buff2;
+ while (*p2 != '\0')
+ {
+ while (*p1 == UNICODE_LTR_MARK)
+ p1++;
+ while (*p2 == UNICODE_LTR_MARK)
+ p2++;
+ p1++;
+ p2++;
+ }
+ *p1 = '\0';
+ ok(lstrcmpW(buff2, buff) == 0, "expected (%s) got (%s) for date part\n",
+ wine_dbgstr_w(buff2), wine_dbgstr_w(buff));
flags = FDTF_LONGDATE | FDTF_LONGTIME;
ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
- ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
- ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
- ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
- lstrcatW(buff2, commaW);
+ ok(ret == lstrlenW(buff)+1 || ret == lstrlenW(buff),
+ "expected %d or %d, got %d\n", lstrlenW(buff)+1, lstrlenW(buff), ret);
ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
- ok(ret == lstrlenW(buff3)+1, "got %d\n", ret);
- lstrcatW(buff2, buff3);
- ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
+ ok(ret == lstrlenW(buff3)+1, "expected %d, got %d\n", lstrlenW(buff3)+1, ret);
+ ok(lstrcmpW(buff3, buff + lstrlenW(buff) - lstrlenW(buff3)) == 0,
+ "expected (%s), got (%s) for time part\n",
+ wine_dbgstr_w(buff3), wine_dbgstr_w(buff + lstrlenW(buff) - lstrlenW(buff3)));
+ ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
+ ok(ret == lstrlenW(buff2)+1, "expected %d, got %d\n", lstrlenW(buff2)+1, ret);
+ p1 = buff;
+ p2 = buff2;
+ while (*p2 != '\0')
+ {
+ while (*p1 == UNICODE_LTR_MARK)
+ p1++;
+ while (*p2 == UNICODE_LTR_MARK)
+ p2++;
+ p1++;
+ p2++;
+ }
+ *p1 = '\0';
+ ok(lstrcmpW(buff2, buff) == 0, "expected (%s) got (%s) for date part\n",
+ wine_dbgstr_w(buff2), wine_dbgstr_w(buff));
flags = FDTF_SHORTDATE | FDTF_SHORTTIME;
ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
- ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
+ ok(ret == lstrlenW(buff)+1 || ret == lstrlenW(buff),
+ "expected %d or %d, got %d\n", lstrlenW(buff)+1, lstrlenW(buff), ret);
ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
- ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
+ ok(ret == lstrlenW(buff2)+1, "expected %d, got %d\n", lstrlenW(buff2)+1, ret);
lstrcatW(buff2, spaceW);
ret = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
- ok(ret == lstrlenW(buff3)+1, "got %d\n", ret);
+ ok(ret == lstrlenW(buff3)+1, "expected %d, got %d\n", lstrlenW(buff3)+1, ret);
lstrcatW(buff2, buff3);
ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
flags = FDTF_SHORTDATE | FDTF_LONGTIME;
ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
- ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
+ ok(ret == lstrlenW(buff)+1 || ret == lstrlenW(buff),
+ "expected %d or %d, got %d\n", lstrlenW(buff)+1, lstrlenW(buff), ret);
ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
- ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
+ ok(ret == lstrlenW(buff2)+1, "expected %d, got %d\n", lstrlenW(buff2)+1, ret);
lstrcatW(buff2, spaceW);
ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
- ok(ret == lstrlenW(buff3)+1, "got %d\n", ret);
+ ok(ret == lstrlenW(buff3)+1, "expected %d, got %d\n", lstrlenW(buff3)+1, ret);
lstrcatW(buff2, buff3);
ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
}
};
static const char compat_path[] = "Software\\Microsoft\\Windows\\CurrentVersion\\ShellCompatibility\\Objects";
+ void *pColorAdjustLuma = GetProcAddress(hShlwapi, "ColorAdjustLuma");
CHAR keyA[39]; /* {CLSID} */
HKEY root;
DWORD ret;
return;
}
+ if (pColorAdjustLuma && pColorAdjustLuma == pSHGetObjectCompatFlags) /* win2k */
+ {
+ win_skip("Skipping SHGetObjectCompatFlags, same ordinal used for ColorAdjustLuma\n");
+ return;
+ }
+
/* null args */
ret = pSHGetObjectCompatFlags(NULL, NULL);
ok(ret == 0, "got %d\n", ret);
}
typedef struct {
- const IOleCommandTargetVtbl *lpVtbl;
+ IOleCommandTarget IOleCommandTarget_iface;
LONG ref;
} IOleCommandTargetImpl;
+static inline IOleCommandTargetImpl *impl_from_IOleCommandTarget(IOleCommandTarget *iface)
+{
+ return CONTAINING_RECORD(iface, IOleCommandTargetImpl, IOleCommandTarget_iface);
+}
+
static const IOleCommandTargetVtbl IOleCommandTargetImpl_Vtbl;
static IOleCommandTarget* IOleCommandTargetImpl_Construct(void)
IOleCommandTargetImpl *obj;
obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*obj));
- obj->lpVtbl = &IOleCommandTargetImpl_Vtbl;
+ obj->IOleCommandTarget_iface.lpVtbl = &IOleCommandTargetImpl_Vtbl;
obj->ref = 1;
- return (IOleCommandTarget*)obj;
+ return &obj->IOleCommandTarget_iface;
}
static HRESULT WINAPI IOleCommandTargetImpl_QueryInterface(IOleCommandTarget *iface, REFIID riid, void **ppvObj)
{
- IOleCommandTargetImpl *This = (IOleCommandTargetImpl *)iface;
+ IOleCommandTargetImpl *This = impl_from_IOleCommandTarget(iface);
if (IsEqualIID(riid, &IID_IUnknown) ||
IsEqualIID(riid, &IID_IOleCommandTarget))
if(*ppvObj)
{
- IUnknown_AddRef(iface);
+ IOleCommandTarget_AddRef(iface);
return S_OK;
}
static ULONG WINAPI IOleCommandTargetImpl_AddRef(IOleCommandTarget *iface)
{
- IOleCommandTargetImpl *This = (IOleCommandTargetImpl *)iface;
+ IOleCommandTargetImpl *This = impl_from_IOleCommandTarget(iface);
return InterlockedIncrement(&This->ref);
}
static ULONG WINAPI IOleCommandTargetImpl_Release(IOleCommandTarget *iface)
{
- IOleCommandTargetImpl *This = (IOleCommandTargetImpl *)iface;
+ IOleCommandTargetImpl *This = impl_from_IOleCommandTarget(iface);
ULONG ref = InterlockedDecrement(&This->ref);
if (!ref)
};
typedef struct {
- const IServiceProviderVtbl *lpVtbl;
+ IServiceProvider IServiceProvider_iface;
LONG ref;
} IServiceProviderImpl;
+static inline IServiceProviderImpl *impl_from_IServiceProvider(IServiceProvider *iface)
+{
+ return CONTAINING_RECORD(iface, IServiceProviderImpl, IServiceProvider_iface);
+}
+
typedef struct {
- const IProfferServiceVtbl *lpVtbl;
+ IProfferService IProfferService_iface;
LONG ref;
} IProfferServiceImpl;
+static inline IProfferServiceImpl *impl_from_IProfferService(IProfferService *iface)
+{
+ return CONTAINING_RECORD(iface, IProfferServiceImpl, IProfferService_iface);
+}
+
static const IServiceProviderVtbl IServiceProviderImpl_Vtbl;
static const IProfferServiceVtbl IProfferServiceImpl_Vtbl;
IServiceProviderImpl *obj;
obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*obj));
- obj->lpVtbl = &IServiceProviderImpl_Vtbl;
+ obj->IServiceProvider_iface.lpVtbl = &IServiceProviderImpl_Vtbl;
obj->ref = 1;
- return (IServiceProvider*)obj;
+ return &obj->IServiceProvider_iface;
}
static IProfferService* IProfferServiceImpl_Construct(void)
IProfferServiceImpl *obj;
obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*obj));
- obj->lpVtbl = &IProfferServiceImpl_Vtbl;
+ obj->IProfferService_iface.lpVtbl = &IProfferServiceImpl_Vtbl;
obj->ref = 1;
- return (IProfferService*)obj;
+ return &obj->IProfferService_iface;
}
static HRESULT WINAPI IServiceProviderImpl_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppvObj)
{
- IServiceProviderImpl *This = (IServiceProviderImpl *)iface;
+ IServiceProviderImpl *This = impl_from_IServiceProvider(iface);
if (IsEqualIID(riid, &IID_IUnknown) ||
IsEqualIID(riid, &IID_IServiceProvider))
if(*ppvObj)
{
- IUnknown_AddRef(iface);
+ IServiceProvider_AddRef(iface);
/* native uses redefined IID_IServiceProvider symbol, so we can't compare pointers */
if (IsEqualIID(riid, &IID_IServiceProvider))
add_call(&trace_got, 1, iface, &IID_IServiceProvider, 0, 0, 0);
static ULONG WINAPI IServiceProviderImpl_AddRef(IServiceProvider *iface)
{
- IServiceProviderImpl *This = (IServiceProviderImpl *)iface;
+ IServiceProviderImpl *This = impl_from_IServiceProvider(iface);
return InterlockedIncrement(&This->ref);
}
static ULONG WINAPI IServiceProviderImpl_Release(IServiceProvider *iface)
{
- IServiceProviderImpl *This = (IServiceProviderImpl *)iface;
+ IServiceProviderImpl *This = impl_from_IServiceProvider(iface);
ULONG ref = InterlockedDecrement(&This->ref);
if (!ref)
static HRESULT WINAPI IProfferServiceImpl_QueryInterface(IProfferService *iface, REFIID riid, void **ppvObj)
{
- IProfferServiceImpl *This = (IProfferServiceImpl *)iface;
+ IProfferServiceImpl *This = impl_from_IProfferService(iface);
if (IsEqualIID(riid, &IID_IUnknown) ||
IsEqualIID(riid, &IID_IProfferService))
if(*ppvObj)
{
- IUnknown_AddRef(iface);
+ IProfferService_AddRef(iface);
return S_OK;
}
static ULONG WINAPI IProfferServiceImpl_AddRef(IProfferService *iface)
{
- IProfferServiceImpl *This = (IProfferServiceImpl *)iface;
+ IProfferServiceImpl *This = impl_from_IProfferService(iface);
return InterlockedIncrement(&This->ref);
}
static ULONG WINAPI IProfferServiceImpl_Release(IProfferService *iface)
{
- IProfferServiceImpl *This = (IProfferServiceImpl *)iface;
+ IProfferServiceImpl *This = impl_from_IProfferService(iface);
ULONG ref = InterlockedDecrement(&This->ref);
if (!ref)
static HRESULT WINAPI IProfferServiceImpl_ProfferService(IProfferService *iface,
REFGUID service, IServiceProvider *pService, DWORD *pCookie)
{
+ *pCookie = 0xdeadbeef;
add_call(&trace_got, 3, service, pService, pCookie, 0, 0);
return S_OK;
}
add_call(&trace_expected, 3, &dummy_serviceid, provider, &cookie, 0, 0);
init_call_trace(&trace_got);
+ cookie = 0;
hr = pIUnknown_ProfferService((IUnknown*)proff, &dummy_serviceid, provider, &cookie);
ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(cookie == 0xdeadbeef, "got %x\n", cookie);
ok_trace(&trace_expected, &trace_got);
free_call_trace(&trace_got);
add_call(&trace_expected, 4, (void*)(DWORD_PTR)cookie, 0, 0, 0, 0);
init_call_trace(&trace_got);
+ ok(cookie != 0, "got %x\n", cookie);
hr = pIUnknown_ProfferService((IUnknown*)proff, &dummy_serviceid, 0, &cookie);
ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(cookie == 0, "got %x\n", cookie);
ok_trace(&trace_expected, &trace_got);
free_call_trace(&trace_got);
free_call_trace(&trace_expected);
/* test exstyle */
ret = GetWindowLongA(hwnd, GWL_EXSTYLE);
- ok(ret == WS_EX_WINDOWEDGE, "0x%08lx\n", ret);
+ ok(ret == WS_EX_WINDOWEDGE ||
+ ret == (WS_EX_WINDOWEDGE|WS_EX_LAYOUTRTL) /* systems with RTL locale */, "0x%08lx\n", ret);
DestroyWindow(hwnd);
hwnd = pSHCreateWorkerWindowA(0, NULL, WS_EX_TOOLWINDOW, 0, 0, 0);
ret = GetWindowLongA(hwnd, GWL_EXSTYLE);
- ok(ret == (WS_EX_WINDOWEDGE|WS_EX_TOOLWINDOW), "0x%08lx\n", ret);
+ ok(ret == (WS_EX_WINDOWEDGE|WS_EX_TOOLWINDOW) ||
+ ret == (WS_EX_WINDOWEDGE|WS_EX_TOOLWINDOW|WS_EX_LAYOUTRTL) /* systems with RTL locale */, "0x%08lx\n", ret);
DestroyWindow(hwnd);
}
+static HRESULT WINAPI SF_QueryInterface(IShellFolder *iface,
+ REFIID riid, void **ppv)
+{
+ /* SHIShellFolder_EnumObjects doesn't QI the object for IShellFolder */
+ ok(!IsEqualGUID(&IID_IShellFolder, riid),
+ "Unexpected QI for IShellFolder\n");
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI SF_AddRef(IShellFolder *iface)
+{
+ return 2;
+}
+
+static ULONG WINAPI SF_Release(IShellFolder *iface)
+{
+ return 1;
+}
+
+static HRESULT WINAPI SF_ParseDisplayName(IShellFolder *iface,
+ HWND owner, LPBC reserved, LPOLESTR displayName, ULONG *eaten,
+ LPITEMIDLIST *idl, ULONG *attr)
+{
+ ok(0, "Didn't expect ParseDisplayName\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI SF_EnumObjects(IShellFolder *iface,
+ HWND owner, SHCONTF flags, IEnumIDList **enm)
+{
+ *enm = (IEnumIDList*)0xcafebabe;
+ return S_OK;
+}
+
+static HRESULT WINAPI SF_BindToObject(IShellFolder *iface,
+ LPCITEMIDLIST idl, LPBC reserved, REFIID riid, void **obj)
+{
+ ok(0, "Didn't expect BindToObject\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI SF_BindToStorage(IShellFolder *iface,
+ LPCITEMIDLIST idl, LPBC reserved, REFIID riid, void **obj)
+{
+ ok(0, "Didn't expect BindToStorage\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI SF_CompareIDs(IShellFolder *iface,
+ LPARAM lparam, LPCITEMIDLIST idl1, LPCITEMIDLIST idl2)
+{
+ ok(0, "Didn't expect CompareIDs\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI SF_CreateViewObject(IShellFolder *iface,
+ HWND owner, REFIID riid, void **out)
+{
+ ok(0, "Didn't expect CreateViewObject\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI SF_GetAttributesOf(IShellFolder *iface,
+ UINT cidl, LPCITEMIDLIST *idl, SFGAOF *inOut)
+{
+ ok(0, "Didn't expect GetAttributesOf\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI SF_GetUIObjectOf(IShellFolder *iface,
+ HWND owner, UINT cidl, LPCITEMIDLIST *idls, REFIID riid, UINT *inOut,
+ void **out)
+{
+ ok(0, "Didn't expect GetUIObjectOf\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI SF_GetDisplayNameOf(IShellFolder *iface,
+ LPCITEMIDLIST idl, SHGDNF flags, STRRET *name)
+{
+ ok(0, "Didn't expect GetDisplayNameOf\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI SF_SetNameOf(IShellFolder *iface,
+ HWND hwnd, LPCITEMIDLIST idl, LPCOLESTR name, SHGDNF flags,
+ LPITEMIDLIST *idlOut)
+{
+ ok(0, "Didn't expect SetNameOf\n");
+ return E_NOTIMPL;
+}
+
+static IShellFolderVtbl ShellFolderVtbl = {
+ SF_QueryInterface,
+ SF_AddRef,
+ SF_Release,
+ SF_ParseDisplayName,
+ SF_EnumObjects,
+ SF_BindToObject,
+ SF_BindToStorage,
+ SF_CompareIDs,
+ SF_CreateViewObject,
+ SF_GetAttributesOf,
+ SF_GetUIObjectOf,
+ SF_GetDisplayNameOf,
+ SF_SetNameOf
+};
+
+static IShellFolder ShellFolder = { &ShellFolderVtbl };
+
+static void test_SHIShellFolder_EnumObjects(void)
+{
+ IEnumIDList *enm;
+ HRESULT hres;
+ IShellFolder *folder;
+
+ if(!pSHIShellFolder_EnumObjects || is_win2k_and_lower){
+ win_skip("SHIShellFolder_EnumObjects not available\n");
+ return;
+ }
+
+ if(0){
+ /* NULL object crashes on Windows */
+ pSHIShellFolder_EnumObjects(NULL, NULL, 0, NULL);
+ }
+
+ /* SHIShellFolder_EnumObjects doesn't QI the object for IShellFolder */
+ enm = (IEnumIDList*)0xdeadbeef;
+ hres = pSHIShellFolder_EnumObjects(&ShellFolder, NULL, 0, &enm);
+ ok(hres == S_OK, "SHIShellFolder_EnumObjects failed: 0x%08x\n", hres);
+ ok(enm == (IEnumIDList*)0xcafebabe, "Didn't get expected enumerator location, instead: %p\n", enm);
+
+ /* SHIShellFolder_EnumObjects isn't strict about the IShellFolder object */
+ hres = pSHGetDesktopFolder(&folder);
+ ok(hres == S_OK, "SHGetDesktopFolder failed: 0x%08x\n", hres);
+
+ enm = NULL;
+ hres = pSHIShellFolder_EnumObjects(folder, NULL, 0, &enm);
+ ok(hres == S_OK, "SHIShellFolder_EnumObjects failed: 0x%08x\n", hres);
+ ok(enm != NULL, "Didn't get an enumerator\n");
+ if(enm)
+ IEnumIDList_Release(enm);
+
+ IShellFolder_Release(folder);
+}
+
+static void write_inifile(LPCWSTR filename)
+{
+ DWORD written;
+ HANDLE file;
+
+ static const char data[] =
+ "[TestApp]\r\n"
+ "AKey=1\r\n"
+ "AnotherKey=asdf\r\n";
+
+ file = CreateFileW(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
+ if(file == INVALID_HANDLE_VALUE)
+ return;
+
+ WriteFile(file, data, sizeof(data), &written, NULL);
+
+ CloseHandle(file);
+}
+
+#define verify_inifile(f, e) r_verify_inifile(__LINE__, f, e)
+static void r_verify_inifile(unsigned l, LPCWSTR filename, LPCSTR exp)
+{
+ HANDLE file;
+ CHAR buf[1024];
+ DWORD read;
+
+ file = CreateFileW(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
+ if(file == INVALID_HANDLE_VALUE)
+ return;
+
+ ReadFile(file, buf, sizeof(buf) * sizeof(CHAR), &read, NULL);
+ buf[read] = '\0';
+
+ CloseHandle(file);
+
+ ok_(__FILE__,l)(!strcmp(buf, exp), "Expected:\n%s\nGot:\n%s\n", exp,
+ buf);
+}
+
+static void test_SHGetIniString(void)
+{
+ DWORD ret;
+ WCHAR out[64] = {0};
+
+ static const WCHAR TestAppW[] = {'T','e','s','t','A','p','p',0};
+ static const WCHAR TestIniW[] = {'C',':','\\','t','e','s','t','.','i','n','i',0};
+ static const WCHAR AKeyW[] = {'A','K','e','y',0};
+ static const WCHAR AnotherKeyW[] = {'A','n','o','t','h','e','r','K','e','y',0};
+ static const WCHAR JunkKeyW[] = {'J','u','n','k','K','e','y',0};
+
+ if(!pSHGetIniStringW || is_win2k_and_lower){
+ win_skip("SHGetIniStringW is not available\n");
+ return;
+ }
+
+ write_inifile(TestIniW);
+
+ if(0){
+ /* these crash on Windows */
+ pSHGetIniStringW(NULL, NULL, NULL, 0, NULL);
+ pSHGetIniStringW(NULL, AKeyW, out, sizeof(out), TestIniW);
+ pSHGetIniStringW(TestAppW, AKeyW, NULL, sizeof(out), TestIniW);
+ }
+
+ ret = pSHGetIniStringW(TestAppW, AKeyW, out, 0, TestIniW);
+ ok(ret == 0, "SHGetIniStringW should have given 0, instead: %d\n", ret);
+
+ /* valid arguments */
+ ret = pSHGetIniStringW(TestAppW, NULL, out, sizeof(out), TestIniW);
+ ok(broken(ret == 0) || /* win 98 */
+ ret == 4, "SHGetIniStringW should have given 4, instead: %d\n", ret);
+ ok(!lstrcmpW(out, AKeyW), "Expected %s, got: %s\n",
+ wine_dbgstr_w(AKeyW), wine_dbgstr_w(out));
+
+ ret = pSHGetIniStringW(TestAppW, AKeyW, out, sizeof(out), TestIniW);
+ ok(broken(ret == 0) || /* win 98 */
+ ret == 1, "SHGetIniStringW should have given 1, instead: %d\n", ret);
+ ok(broken(*out == 0) || /*win 98 */
+ !strcmp_wa(out, "1"), "Expected L\"1\", got: %s\n", wine_dbgstr_w(out));
+
+ ret = pSHGetIniStringW(TestAppW, AnotherKeyW, out, sizeof(out), TestIniW);
+ ok(broken(ret == 0) || /* win 98 */
+ ret == 4, "SHGetIniStringW should have given 4, instead: %d\n", ret);
+ ok(broken(*out == 0) || /* win 98 */
+ !strcmp_wa(out, "asdf"), "Expected L\"asdf\", got: %s\n", wine_dbgstr_w(out));
+
+ ret = pSHGetIniStringW(TestAppW, JunkKeyW, out, sizeof(out), TestIniW);
+ ok(ret == 0, "SHGetIniStringW should have given 0, instead: %d\n", ret);
+ ok(*out == 0, "Expected L\"\", got: %s\n", wine_dbgstr_w(out));
+
+ DeleteFileW(TestIniW);
+}
+
+static void test_SHSetIniString(void)
+{
+ BOOL ret;
+
+ static const WCHAR TestAppW[] = {'T','e','s','t','A','p','p',0};
+ static const WCHAR AnotherAppW[] = {'A','n','o','t','h','e','r','A','p','p',0};
+ static const WCHAR TestIniW[] = {'C',':','\\','t','e','s','t','.','i','n','i',0};
+ static const WCHAR AKeyW[] = {'A','K','e','y',0};
+ static const WCHAR NewKeyW[] = {'N','e','w','K','e','y',0};
+ static const WCHAR AValueW[] = {'A','V','a','l','u','e',0};
+
+ if(!pSHSetIniStringW || is_win2k_and_lower){
+ win_skip("SHSetIniStringW is not available\n");
+ return;
+ }
+
+ write_inifile(TestIniW);
+
+ ret = pSHSetIniStringW(TestAppW, AKeyW, AValueW, TestIniW);
+ ok(ret == TRUE, "SHSetIniStringW should not have failed\n");
+ todo_wine /* wine sticks an extra \r\n at the end of the file */
+ verify_inifile(TestIniW, "[TestApp]\r\nAKey=AValue\r\nAnotherKey=asdf\r\n");
+
+ ret = pSHSetIniStringW(TestAppW, AKeyW, NULL, TestIniW);
+ ok(ret == TRUE, "SHSetIniStringW should not have failed\n");
+ verify_inifile(TestIniW, "[TestApp]\r\nAnotherKey=asdf\r\n");
+
+ ret = pSHSetIniStringW(AnotherAppW, NewKeyW, AValueW, TestIniW);
+ ok(ret == TRUE, "SHSetIniStringW should not have failed\n");
+ verify_inifile(TestIniW, "[TestApp]\r\nAnotherKey=asdf\r\n[AnotherApp]\r\nNewKey=AValue\r\n");
+
+ ret = pSHSetIniStringW(TestAppW, NULL, AValueW, TestIniW);
+ ok(ret == TRUE, "SHSetIniStringW should not have failed\n");
+ verify_inifile(TestIniW, "[AnotherApp]\r\nNewKey=AValue\r\n");
+
+ DeleteFileW(TestIniW);
+}
+
+enum _shellkey_flags {
+ SHKEY_Root_HKCU = 0x1,
+ SHKEY_Root_HKLM = 0x2,
+ SHKEY_Key_Explorer = 0x00,
+ SHKEY_Key_Shell = 0x10,
+ SHKEY_Key_ShellNoRoam = 0x20,
+ SHKEY_Key_Classes = 0x30,
+ SHKEY_Subkey_Default = 0x0000,
+ SHKEY_Subkey_ResourceName = 0x1000,
+ SHKEY_Subkey_Handlers = 0x2000,
+ SHKEY_Subkey_Associations = 0x3000,
+ SHKEY_Subkey_Volatile = 0x4000,
+ SHKEY_Subkey_MUICache = 0x5000,
+ SHKEY_Subkey_FileExts = 0x6000
+};
+
+static void test_SHGetShellKey(void)
+{
+ static const WCHAR ShellFoldersW[] = { 'S','h','e','l','l',' ','F','o','l','d','e','r','s',0 };
+ static const WCHAR WineTestW[] = { 'W','i','n','e','T','e','s','t',0 };
+
+ void *pPathBuildRootW = GetProcAddress(hShlwapi, "PathBuildRootW");
+ DWORD *alloc_data, data, size;
+ HKEY hkey;
+ HRESULT hres;
+
+ if (!pSHGetShellKey)
+ {
+ win_skip("SHGetShellKey(ordinal 491) isn't available\n");
+ return;
+ }
+
+ /* some win2k */
+ if (pPathBuildRootW && pPathBuildRootW == pSHGetShellKey)
+ {
+ win_skip("SHGetShellKey(ordinal 491) used for PathBuildRootW\n");
+ return;
+ }
+
+ if (is_win9x || is_win2k_and_lower)
+ {
+ win_skip("Ordinal 491 used for another call, skipping SHGetShellKey tests\n");
+ return;
+ }
+
+ /* Vista+ limits SHKEY enumeration values */
+ SetLastError(0xdeadbeef);
+ hkey = pSHGetShellKey(SHKEY_Key_Explorer, ShellFoldersW, FALSE);
+ if (hkey)
+ {
+ /* Tests not working on Vista+ */
+ RegCloseKey(hkey);
+
+ hkey = pSHGetShellKey(SHKEY_Root_HKLM|SHKEY_Key_Classes, NULL, FALSE);
+ ok(hkey != NULL, "hkey = NULL\n");
+ RegCloseKey(hkey);
+ }
+
+ hkey = pSHGetShellKey(SHKEY_Root_HKCU|SHKEY_Key_Explorer, ShellFoldersW, FALSE);
+ ok(hkey != NULL, "hkey = NULL\n");
+ RegCloseKey(hkey);
+
+ hkey = pSHGetShellKey(SHKEY_Root_HKLM|SHKEY_Key_Explorer, ShellFoldersW, FALSE);
+ ok(hkey != NULL, "hkey = NULL\n");
+ RegCloseKey(hkey);
+
+ hkey = pSHGetShellKey(SHKEY_Root_HKLM, WineTestW, FALSE);
+ ok(hkey == NULL, "hkey != NULL\n");
+
+ hkey = pSHGetShellKey(SHKEY_Root_HKLM, NULL, FALSE);
+ ok(hkey != NULL, "Can't open key\n");
+ ok(SUCCEEDED(RegDeleteKeyW(hkey, WineTestW)), "Can't delete key\n");
+ RegCloseKey(hkey);
+
+ hkey = pSHGetShellKey(SHKEY_Root_HKLM, WineTestW, TRUE);
+ if (!hkey && GetLastError() == ERROR_ACCESS_DENIED)
+ {
+ skip("Not authorized to create keys\n");
+ return;
+ }
+ ok(hkey != NULL, "Can't create key\n");
+ RegCloseKey(hkey);
+
+ if (!pSKGetValueW || !pSKSetValueW || !pSKDeleteValueW || !pSKAllocValueW)
+ {
+ win_skip("SKGetValueW, SKSetValueW, SKDeleteValueW or SKAllocValueW not available\n");
+ return;
+ }
+
+ size = sizeof(data);
+ hres = pSKGetValueW(SHKEY_Root_HKLM, WineTestW, NULL, NULL, &data, &size);
+ ok(hres == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "hres = %x\n", hres);
+
+ data = 1234;
+ hres = pSKSetValueW(SHKEY_Root_HKLM, WineTestW, NULL, REG_DWORD, &data, sizeof(DWORD));
+ ok(hres == S_OK, "hres = %x\n", hres);
+
+ size = 1;
+ hres = pSKGetValueW(SHKEY_Root_HKLM, WineTestW, NULL, NULL, NULL, &size);
+ ok(hres == S_OK, "hres = %x\n", hres);
+ ok(size == sizeof(DWORD), "size = %d\n", size);
+
+ data = 0xdeadbeef;
+ hres = pSKGetValueW(SHKEY_Root_HKLM, WineTestW, NULL, NULL, &data, &size);
+ ok(hres == S_OK, "hres = %x\n", hres);
+ ok(size == sizeof(DWORD), "size = %d\n", size);
+ ok(data == 1234, "data = %d\n", data);
+
+ hres = pSKAllocValueW(SHKEY_Root_HKLM, WineTestW, NULL, NULL, (void**)&alloc_data, &size);
+ ok(hres == S_OK, "hres= %x\n", hres);
+ ok(size == sizeof(DWORD), "size = %d\n", size);
+ if (SUCCEEDED(hres))
+ {
+ ok(*alloc_data == 1234, "*alloc_data = %d\n", *alloc_data);
+ LocalFree(alloc_data);
+ }
+
+ hres = pSKDeleteValueW(SHKEY_Root_HKLM, WineTestW, NULL);
+ ok(hres == S_OK, "hres = %x\n", hres);
+
+ hres = pSKDeleteValueW(SHKEY_Root_HKLM, WineTestW, NULL);
+ ok(hres == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "hres = %x\n", hres);
+
+ hres = pSKGetValueW(SHKEY_Root_HKLM, WineTestW, NULL, NULL, &data, &size);
+ ok(hres == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "hres = %x\n", hres);
+
+ hkey = pSHGetShellKey(SHKEY_Root_HKLM, NULL, FALSE);
+ ok(hkey != NULL, "Can't create key\n");
+ ok(SUCCEEDED(RegDeleteKeyW(hkey, WineTestW)), "Can't delete key\n");
+ RegCloseKey(hkey);
+}
+
static void init_pointers(void)
{
#define MAKEFUNC(f, ord) (p##f = (void*)GetProcAddress(hShlwapi, (LPSTR)(ord)))
MAKEFUNC(SHFreeShared, 10);
MAKEFUNC(GetAcceptLanguagesA, 14);
MAKEFUNC(SHSetWindowBits, 165);
+ MAKEFUNC(SHSetParentHwnd, 167);
MAKEFUNC(ConnectToConnectionPoint, 168);
MAKEFUNC(SHSearchMapInt, 198);
MAKEFUNC(SHCreateWorkerWindowA, 257);
MAKEFUNC(SHPackDispParams, 282);
MAKEFUNC(IConnectionPoint_InvokeWithCancel, 283);
MAKEFUNC(IConnectionPoint_SimpleInvoke, 284);
+ MAKEFUNC(SHGetIniStringW, 294);
+ MAKEFUNC(SHSetIniStringW, 295);
MAKEFUNC(SHFormatDateTimeA, 353);
MAKEFUNC(SHFormatDateTimeW, 354);
+ MAKEFUNC(SHIShellFolder_EnumObjects, 404);
MAKEFUNC(SHGetObjectCompatFlags, 476);
MAKEFUNC(IUnknown_QueryServiceExec, 484);
+ MAKEFUNC(SHGetShellKey, 491);
MAKEFUNC(SHPropertyBag_ReadLONG, 496);
MAKEFUNC(IUnknown_ProfferService, 514);
+ MAKEFUNC(SKGetValueW, 516);
+ MAKEFUNC(SKSetValueW, 517);
+ MAKEFUNC(SKDeleteValueW, 518);
+ MAKEFUNC(SKAllocValueW, 519);
#undef MAKEFUNC
}
+static void test_SHSetParentHwnd(void)
+{
+ HWND hwnd, hwnd2, ret;
+ DWORD style;
+
+ if (!pSHSetParentHwnd)
+ {
+ win_skip("SHSetParentHwnd not available\n");
+ return;
+ }
+
+ hwnd = CreateWindowA("Button", "", WS_VISIBLE, 0, 0, 10, 10, NULL, NULL, NULL, NULL);
+ ok(hwnd != NULL, "got %p\n", hwnd);
+
+ hwnd2 = CreateWindowA("Button", "", WS_VISIBLE | WS_CHILD, 0, 0, 10, 10, hwnd, NULL, NULL, NULL);
+ ok(hwnd2 != NULL, "got %p\n", hwnd2);
+
+ /* null params */
+ ret = pSHSetParentHwnd(NULL, NULL);
+ ok(ret == NULL, "got %p\n", ret);
+
+ /* set to no parent while already no parent present */
+ ret = GetParent(hwnd);
+ ok(ret == NULL, "got %p\n", ret);
+ style = GetWindowLongA(hwnd, GWL_STYLE);
+ ok((style & (WS_POPUP|WS_CHILD)) == 0, "got style 0x%08x\n", style);
+ ret = pSHSetParentHwnd(hwnd, NULL);
+ ok(ret == NULL, "got %p\n", ret);
+ style = GetWindowLongA(hwnd, GWL_STYLE);
+ ok((style & (WS_POPUP|WS_CHILD)) == 0, "got style 0x%08x\n", style);
+
+ /* reset to null parent from not null */
+ ret = GetParent(hwnd2);
+ ok(ret == hwnd, "got %p\n", ret);
+ style = GetWindowLongA(hwnd2, GWL_STYLE);
+ ok((style & (WS_POPUP|WS_CHILD)) == WS_CHILD, "got style 0x%08x\n", style);
+ ret = pSHSetParentHwnd(hwnd2, NULL);
+ ok(ret == NULL, "got %p\n", ret);
+ style = GetWindowLongA(hwnd2, GWL_STYLE);
+ ok((style & (WS_POPUP|WS_CHILD)) == WS_POPUP, "got style 0x%08x\n", style);
+ ret = GetParent(hwnd2);
+ ok(ret == NULL, "got %p\n", ret);
+
+ /* set parent back */
+ style = GetWindowLongA(hwnd2, GWL_STYLE);
+ SetWindowLongA(hwnd2, GWL_STYLE, style & ~(WS_CHILD|WS_POPUP));
+ style = GetWindowLongA(hwnd2, GWL_STYLE);
+ ok((style & (WS_CHILD|WS_POPUP)) == 0, "got 0x%08x\n", style);
+
+ ret = pSHSetParentHwnd(hwnd2, hwnd);
+ todo_wine ok(ret == NULL, "got %p\n", ret);
+
+ style = GetWindowLongA(hwnd2, GWL_STYLE);
+ ok((style & (WS_POPUP|WS_CHILD)) == WS_CHILD, "got style 0x%08x\n", style);
+ ret = GetParent(hwnd2);
+ ok(ret == hwnd, "got %p\n", ret);
+
+ /* try to set same parent again */
+ /* with WS_POPUP */
+ style = GetWindowLongA(hwnd2, GWL_STYLE);
+ SetWindowLongA(hwnd2, GWL_STYLE, style | WS_POPUP);
+ ret = pSHSetParentHwnd(hwnd2, hwnd);
+ todo_wine ok(ret == NULL, "got %p\n", ret);
+ style = GetWindowLongA(hwnd2, GWL_STYLE);
+ ok((style & (WS_CHILD|WS_POPUP)) == WS_CHILD, "got 0x%08x\n", style);
+ ret = GetParent(hwnd2);
+ ok(ret == hwnd, "got %p\n", ret);
+
+ /* without WS_POPUP */
+ style = GetWindowLongA(hwnd2, GWL_STYLE);
+ SetWindowLongA(hwnd2, GWL_STYLE, style | ~WS_POPUP);
+ ret = pSHSetParentHwnd(hwnd2, hwnd);
+ todo_wine ok(ret == hwnd, "got %p\n", ret);
+ style = GetWindowLongA(hwnd2, GWL_STYLE);
+ ok((style & (WS_CHILD|WS_POPUP)) == WS_CHILD, "got 0x%08x\n", style);
+ ret = GetParent(hwnd2);
+ ok(ret == hwnd, "got %p\n", ret);
+
+ DestroyWindow(hwnd);
+ DestroyWindow(hwnd2);
+}
+
START_TEST(ordinal)
{
hShlwapi = GetModuleHandleA("shlwapi.dll");
is_win2k_and_lower = GetProcAddress(hShlwapi, "StrChrNW") == 0;
+ is_win9x = GetProcAddress(hShlwapi, (LPSTR)99) == 0; /* StrCpyNXA */
+
+ /* SHCreateStreamOnFileEx was introduced in shlwapi v6.0 */
+ if(!GetProcAddress(hShlwapi, "SHCreateStreamOnFileEx")){
+ win_skip("Too old shlwapi version\n");
+ return;
+ }
init_pointers();
hmlang = LoadLibraryA("mlang.dll");
pLcidToRfc1766A = (void *)GetProcAddress(hmlang, "LcidToRfc1766A");
+ hshell32 = LoadLibraryA("shell32.dll");
+ pSHGetDesktopFolder = (void *)GetProcAddress(hshell32, "SHGetDesktopFolder");
+
test_GetAcceptLanguagesA();
test_SHSearchMapInt();
test_alloc_shared();
test_IUnknown_QueryServiceExec();
test_IUnknown_ProfferService();
test_SHCreateWorkerWindowA();
+ test_SHIShellFolder_EnumObjects();
+ test_SHGetIniString();
+ test_SHSetIniString();
+ test_SHGetShellKey();
+ test_SHSetParentHwnd();
+
+ FreeLibrary(hshell32);
+ FreeLibrary(hmlang);
}
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
/* ################ */
-struct {
+static const struct {
const char *url;
const char *path;
DWORD ret;
{NULL, FALSE}
};
-struct {
+static const struct {
const char *path;
const char *result;
} TEST_PATH_UNQUOTE_SPACES[] = {
{
HMODULE hShlwapi = GetModuleHandleA("shlwapi.dll");
+ /* SHCreateStreamOnFileEx was introduced in shlwapi v6.0 */
+ if(!GetProcAddress(hShlwapi, "SHCreateStreamOnFileEx")){
+ win_skip("Too old shlwapi version\n");
+ return;
+ }
+
pPathCreateFromUrlA = (void*)GetProcAddress(hShlwapi, "PathCreateFromUrlA");
pPathCreateFromUrlW = (void*)GetProcAddress(hShlwapi, "PathCreateFromUrlW");
pPathCombineW = (void*)GetProcAddress(hShlwapi, "PathCombineW");
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#define REG_CURRENT_VERSION "Software\\Microsoft\\Windows\\CurrentVersion\\explorer"
static HMODULE hshlwapi;
-typedef DWORD (WINAPI *SHCopyKeyA_func)(HKEY,LPCSTR,HKEY,DWORD);
-static SHCopyKeyA_func pSHCopyKeyA;
-typedef DWORD (WINAPI *SHRegGetPathA_func)(HKEY,LPCSTR,LPCSTR,LPSTR,DWORD);
-static SHRegGetPathA_func pSHRegGetPathA;
-typedef LSTATUS (WINAPI *SHRegGetValueA_func)(HKEY,LPCSTR,LPCSTR,SRRF,LPDWORD,LPVOID,LPDWORD);
-static SHRegGetValueA_func pSHRegGetValueA;
+
+static DWORD (WINAPI *pSHCopyKeyA)(HKEY,LPCSTR,HKEY,DWORD);
+static DWORD (WINAPI *pSHRegGetPathA)(HKEY,LPCSTR,LPCSTR,LPSTR,DWORD);
+static LSTATUS (WINAPI *pSHRegGetValueA)(HKEY,LPCSTR,LPCSTR,SRRF,LPDWORD,LPVOID,LPDWORD);
+static LSTATUS (WINAPI *pSHRegCreateUSKeyW)(LPCWSTR,REGSAM,HUSKEY,PHUSKEY,DWORD);
static char sTestpath1[] = "%LONGSYSTEMVAR%\\subdir1";
static char sTestpath2[] = "%FOO%\\subdir1";
ok( 0 == strcmp(sExpTestpath1, buf) , "Comparing (%s) with (%s) failed\n", buf, sExpTestpath1);
}
-static void test_SHQUeryValueEx(void)
+static void test_SHQueryValueEx(void)
{
HKEY hKey;
DWORD dwSize;
ok( 0, "Could not set up SHDeleteKey test\n");
}
+static void test_SHRegCreateUSKeyW(void)
+{
+ static const WCHAR subkeyW[] = {'s','u','b','k','e','y',0};
+ LONG ret;
+
+ if (!pSHRegCreateUSKeyW)
+ {
+ win_skip("SHRegCreateUSKeyW not available\n");
+ return;
+ }
+
+ ret = pSHRegCreateUSKeyW(subkeyW, KEY_ALL_ACCESS, NULL, NULL, SHREGSET_FORCE_HKCU);
+ ok(ret == ERROR_INVALID_PARAMETER, "got %d\n", ret);
+}
+
START_TEST(shreg)
{
- HKEY hkey = create_test_entries();
-
- if (!hkey) return;
-
- hshlwapi = GetModuleHandleA("shlwapi.dll");
- pSHCopyKeyA=(SHCopyKeyA_func)GetProcAddress(hshlwapi,"SHCopyKeyA");
- pSHRegGetPathA=(SHRegGetPathA_func)GetProcAddress(hshlwapi,"SHRegGetPathA");
- pSHRegGetValueA=(SHRegGetValueA_func)GetProcAddress(hshlwapi,"SHRegGetValueA");
- test_SHGetValue();
- test_SHRegGetValue();
- test_SHQUeryValueEx();
- test_SHGetRegPath();
- test_SHCopyKey();
- test_SHDeleteKey();
- delete_key( hkey, "Software\\Wine", "Test" );
+ HKEY hkey = create_test_entries();
+
+ if (!hkey) return;
+
+ hshlwapi = GetModuleHandleA("shlwapi.dll");
+
+ /* SHCreateStreamOnFileEx was introduced in shlwapi v6.0 */
+ if(!GetProcAddress(hshlwapi, "SHCreateStreamOnFileEx")){
+ win_skip("Too old shlwapi version\n");
+ return;
+ }
+
+ pSHCopyKeyA = (void*)GetProcAddress(hshlwapi,"SHCopyKeyA");
+ pSHRegGetPathA = (void*)GetProcAddress(hshlwapi,"SHRegGetPathA");
+ pSHRegGetValueA = (void*)GetProcAddress(hshlwapi,"SHRegGetValueA");
+ pSHRegCreateUSKeyW = (void*)GetProcAddress(hshlwapi, "SHRegCreateUSKeyW");
+
+ test_SHGetValue();
+ test_SHRegGetValue();
+ test_SHQueryValueEx();
+ test_SHGetRegPath();
+ test_SHCopyKey();
+ test_SHDeleteKey();
+ test_SHRegCreateUSKeyW();
+
+ delete_key( hkey, "Software\\Wine", "Test" );
}
static LPWSTR (WINAPI *pStrFormatKBSizeW)(LONGLONG,LPWSTR,UINT);
static BOOL (WINAPI *pStrIsIntlEqualA)(BOOL,LPCSTR,LPCSTR,int);
static BOOL (WINAPI *pStrIsIntlEqualW)(BOOL,LPCWSTR,LPCWSTR,int);
-static HRESULT (WINAPI *pStrRetToBSTR)(STRRET*,void*,BSTR*);
+static LPWSTR (WINAPI *pStrPBrkW)(LPCWSTR,LPCWSTR);
+static LPSTR (WINAPI *pStrRChrA)(LPCSTR,LPCSTR,WORD);
+static HRESULT (WINAPI *pStrRetToBSTR)(STRRET*,LPCITEMIDLIST,BSTR*);
static HRESULT (WINAPI *pStrRetToBufA)(STRRET*,LPCITEMIDLIST,LPSTR,UINT);
static HRESULT (WINAPI *pStrRetToBufW)(STRRET*,LPCITEMIDLIST,LPWSTR,UINT);
+static LPWSTR (WINAPI *pStrStrNW)(LPCWSTR,LPCWSTR,UINT);
+static LPWSTR (WINAPI *pStrStrNIW)(LPCWSTR,LPCWSTR,UINT);
static INT (WINAPIV *pwnsprintfA)(LPSTR,INT,LPCSTR, ...);
static INT (WINAPIV *pwnsprintfW)(LPWSTR,INT,LPCWSTR, ...);
static LPWSTR (WINAPI *pStrChrNW)(LPWSTR,WCHAR,UINT);
+static BOOL (WINAPI *pStrToInt64ExA)(LPCSTR,DWORD,LONGLONG*);
+static BOOL (WINAPI *pStrToInt64ExW)(LPCWSTR,DWORD,LONGLONG*);
static int strcmpW(const WCHAR *str1, const WCHAR *str2)
{
{
const char* string;
int str_to_int;
- int str_to_int_ex;
- int str_to_int_hex;
+ LONGLONG str_to_int64_ex;
+ LONGLONG str_to_int64_hex;
} StrToIntResult;
static const StrToIntResult StrToInt_results[] = {
{ "1099", 1099, 1099, 1099 },
+ { "4294967319", 23, ((LONGLONG)1 << 32) | 23, ((LONGLONG)1 << 32) | 23 },
{ "+88987", 0, 88987, 88987 },
{ "012", 12, 12, 12 },
{ "-55", -55, -55, -55 },
{ "-0", 0, 0, 0 },
{ "0x44ff", 0, 0, 0x44ff },
+ { "0x2bdc546291f4b1", 0, 0, ((LONGLONG)0x2bdc54 << 32) | 0x6291f4b1 },
{ "+0x44f4", 0, 0, 0x44f4 },
{ "-0x44fd", 0, 0, 0x44fd },
{ "+ 88987", 0, 0, 0 },
LONGLONG value;
const char* byte_size_64;
const char* kb_size;
+ int kb_size_broken;
+ const char* kb_size2;
} StrFormatSizeResult;
{ 10191, "9.95 KB", "10 KB"},
{ 100353, "98.0 KB", "99 KB"},
{ 1022286, "998 KB", "999 KB"},
- { 1046862, "0.99 MB", "1,023 KB"},
- { 1048574619, "999 MB", "1,023,999 KB"},
- { 1073741775, "0.99 GB", "1,048,576 KB"},
- { ((LONGLONG)0x000000f9 << 32) | 0xfffff94e, "999 GB", "1,048,575,999 KB"},
- { ((LONGLONG)0x000000ff << 32) | 0xfffffa9b, "0.99 TB", "1,073,741,823 KB"},
- { ((LONGLONG)0x0003e7ff << 32) | 0xfffffa9b, "999 TB", "1,073,741,823,999 KB"},
- { ((LONGLONG)0x0003ffff << 32) | 0xfffffbe8, "0.99 PB", "1,099,511,627,775 KB"},
- { ((LONGLONG)0x0f9fffff << 32) | 0xfffffd35, "999 PB", "1,099,511,627,776,000 KB"},
- { ((LONGLONG)0x0fffffff << 32) | 0xfffffa9b, "0.99 EB", "1,125,899,906,842,623 KB"},
+ { 1046862, "0.99 MB", "1,023 KB", 1, "1023 KB"},
+ { 1048574619, "999 MB", "1,023,999 KB", 1, "1023999 KB"},
+ { 1073741775, "0.99 GB", "1,048,576 KB", 1, "1048576 KB"},
+ { ((LONGLONG)0x000000f9 << 32) | 0xfffff94e, "999 GB", "1,048,575,999 KB", 1, "1048575999 KB"},
+ { ((LONGLONG)0x000000ff << 32) | 0xfffffa9b, "0.99 TB", "1,073,741,823 KB", 1, "1073741823 KB"},
+ { ((LONGLONG)0x0003e7ff << 32) | 0xfffffa9b, "999 TB", "1,073,741,823,999 KB", 1, "4294967295 KB"},
+ { ((LONGLONG)0x0003ffff << 32) | 0xfffffbe8, "0.99 PB", "1,099,511,627,775 KB", 1, "4294967295 KB"},
+ { ((LONGLONG)0x0f9fffff << 32) | 0xfffffd35, "999 PB", "1,099,511,627,776,000 KB", 1, "0 KB"},
+ { ((LONGLONG)0x0fffffff << 32) | 0xfffffa9b, "0.99 EB", "1,125,899,906,842,623 KB", 1, "4294967295 KB"},
{ 0, NULL, NULL }
};
-/* StrFormatByteSize64/StrFormatKBSize results */
+/* StrFromTimeIntervalA/StrFromTimeIntervalW results */
typedef struct tagStrFromTimeIntervalResult
{
DWORD ms;
{ 0, 0, NULL }
};
+
+/* Returns true if the user interface is in English. Note that this does not
+ * presume of the formatting of dates, numbers, etc.
+ */
+static BOOL is_lang_english(void)
+{
+ static HMODULE hkernel32 = NULL;
+ static LANGID (WINAPI *pGetThreadUILanguage)(void) = NULL;
+ static LANGID (WINAPI *pGetUserDefaultUILanguage)(void) = NULL;
+
+ if (!hkernel32)
+ {
+ hkernel32 = GetModuleHandleA("kernel32.dll");
+ pGetThreadUILanguage = (void*)GetProcAddress(hkernel32, "GetThreadUILanguage");
+ pGetUserDefaultUILanguage = (void*)GetProcAddress(hkernel32, "GetUserDefaultUILanguage");
+ }
+ if (pGetThreadUILanguage)
+ return PRIMARYLANGID(pGetThreadUILanguage()) == LANG_ENGLISH;
+ if (pGetUserDefaultUILanguage)
+ return PRIMARYLANGID(pGetUserDefaultUILanguage()) == LANG_ENGLISH;
+
+ return PRIMARYLANGID(GetUserDefaultLangID()) == LANG_ENGLISH;
+}
+
+/* Returns true if the dates, numbers, etc. are formatted using English
+ * conventions.
+ */
+static BOOL is_locale_english(void)
+{
+ /* Surprisingly GetThreadLocale() is irrelevant here */
+ return PRIMARYLANGID(GetUserDefaultLangID()) == LANG_ENGLISH;
+}
+
static void test_StrChrA(void)
{
char string[129];
WCHAR szSrc[256];
WCHAR szBuff[256];
const StrFormatSizeResult* result = StrFormatSize_results;
-
+ LPWSTR lpRes;
while(result->value)
{
MultiByteToWideChar(0,0,result->byte_size_64,-1,szSrc,sizeof(szSrc)/sizeof(WCHAR));
- StrCpyW(szBuff, szSrc);
- ok(!StrCmpW(szSrc, szBuff), "Copied string %s wrong\n", result->byte_size_64);
+ lpRes = StrCpyW(szBuff, szSrc);
+ ok(!StrCmpW(szSrc, szBuff) && lpRes == szBuff, "Copied string %s wrong\n", result->byte_size_64);
result++;
}
+
+ /* this test crashes on win2k SP4 */
+ /*lpRes = StrCpyW(szBuff, NULL);*/
+ /*ok(lpRes == szBuff, "Wrong return value: got %p expected %p\n", lpRes, szBuff);*/
+
+ /* this test crashes on win2k SP4 */
+ /*lpRes = StrCpyW(NULL, szSrc);*/
+ /*ok(lpRes == NULL, "Wrong return value: got %p expected NULL\n", lpRes);*/
+
+ /* this test crashes on win2k SP4 */
+ /*lpRes = StrCpyW(NULL, NULL);*/
+ /*ok(lpRes == NULL, "Wrong return value: got %p expected NULL\n", lpRes);*/
}
static void test_StrChrNW(void)
ok(!bRet || return_val != -1, "No result returned from '%s'\n",
result->string);
if (bRet)
- ok(return_val == result->str_to_int_ex, "converted '%s' wrong (%d)\n",
+ ok(return_val == (int)result->str_to_int64_ex, "converted '%s' wrong (%d)\n",
result->string, return_val);
result++;
}
ok(!bRet || return_val != -1, "No result returned from '%s'\n",
result->string);
if (bRet)
- ok(return_val == result->str_to_int_hex, "converted '%s' wrong (%d)\n",
+ ok(return_val == (int)result->str_to_int64_hex, "converted '%s' wrong (%d)\n",
result->string, return_val);
result++;
}
ok(!bRet || return_val != -1, "No result returned from '%s'\n",
result->string);
if (bRet)
- ok(return_val == result->str_to_int_ex, "converted '%s' wrong (%d)\n",
+ ok(return_val == (int)result->str_to_int64_ex, "converted '%s' wrong (%d)\n",
result->string, return_val);
result++;
}
ok(!bRet || return_val != -1, "No result returned from '%s'\n",
result->string);
if (bRet)
- ok(return_val == result->str_to_int_hex, "converted '%s' wrong (%d)\n",
+ ok(return_val == (int)result->str_to_int64_hex, "converted '%s' wrong (%d)\n",
result->string, return_val);
result++;
}
}
+static void test_StrToInt64ExA(void)
+{
+ const StrToIntResult *result = StrToInt_results;
+ LONGLONG return_val;
+ BOOL bRet;
+
+ if (!pStrToInt64ExA)
+ {
+ win_skip("StrToInt64ExA() is not available\n");
+ return;
+ }
+
+ while (result->string)
+ {
+ return_val = -1;
+ bRet = pStrToInt64ExA(result->string,0,&return_val);
+ ok(!bRet || return_val != -1, "No result returned from '%s'\n",
+ result->string);
+ if (bRet)
+ ok(return_val == result->str_to_int64_ex, "converted '%s' wrong (%08x%08x)\n",
+ result->string, (DWORD)(return_val >> 32), (DWORD)return_val);
+ result++;
+ }
+
+ result = StrToInt_results;
+ while (result->string)
+ {
+ return_val = -1;
+ bRet = pStrToInt64ExA(result->string,STIF_SUPPORT_HEX,&return_val);
+ ok(!bRet || return_val != -1, "No result returned from '%s'\n",
+ result->string);
+ if (bRet)
+ ok(return_val == result->str_to_int64_hex, "converted '%s' wrong (%08x%08x)\n",
+ result->string, (DWORD)(return_val >> 32), (DWORD)return_val);
+ result++;
+ }
+}
+
+static void test_StrToInt64ExW(void)
+{
+ WCHAR szBuff[256];
+ const StrToIntResult *result = StrToInt_results;
+ LONGLONG return_val;
+ BOOL bRet;
+
+ if (!pStrToInt64ExW)
+ {
+ win_skip("StrToInt64ExW() is not available\n");
+ return;
+ }
+
+ while (result->string)
+ {
+ return_val = -1;
+ MultiByteToWideChar(0,0,result->string,-1,szBuff,sizeof(szBuff)/sizeof(WCHAR));
+ bRet = pStrToInt64ExW(szBuff, 0, &return_val);
+ ok(!bRet || return_val != -1, "No result returned from '%s'\n",
+ result->string);
+ if (bRet)
+ ok(return_val == result->str_to_int64_ex, "converted '%s' wrong (%08x%08x)\n",
+ result->string, (DWORD)(return_val >> 32), (DWORD)return_val);
+ result++;
+ }
+
+ result = StrToInt_results;
+ while (result->string)
+ {
+ return_val = -1;
+ MultiByteToWideChar(0,0,result->string,-1,szBuff,sizeof(szBuff)/sizeof(WCHAR));
+ bRet = pStrToInt64ExW(szBuff, STIF_SUPPORT_HEX, &return_val);
+ ok(!bRet || return_val != -1, "No result returned from '%s'\n",
+ result->string);
+ if (bRet)
+ ok(return_val == result->str_to_int64_hex, "converted '%s' wrong (%08x%08x)\n",
+ result->string, (DWORD)(return_val >> 32), (DWORD)return_val);
+ result++;
+ }
+}
+
static void test_StrDupA(void)
{
LPSTR lpszStr;
{
pStrFormatKBSizeW(result->value, szBuffW, 256);
WideCharToMultiByte(0,0,szBuffW,-1,szBuff,sizeof(szBuff)/sizeof(WCHAR),0,0);
- ok(!strcmp(result->kb_size, szBuff),
- "Formatted %x%08x wrong: got %s, expected %s\n",
+
+ ok(!strcmp(result->kb_size, szBuff), "Formatted %x%08x wrong: got %s, expected %s\n",
(LONG)(result->value >> 32), (LONG)result->value, szBuff, result->kb_size);
result++;
}
{
pStrFormatKBSizeA(result->value, szBuff, 256);
- ok(!strcmp(result->kb_size, szBuff),
+ /* shlwapi on Win98 SE does not appear to apply delimiters to the output
+ * and does not correctly handle extremely large values. */
+ ok(!strcmp(result->kb_size, szBuff) ||
+ (result->kb_size_broken && !strcmp(result->kb_size2, szBuff)),
"Formatted %x%08x wrong: got %s, expected %s\n",
(LONG)(result->value >> 32), (LONG)result->value, szBuff, result->kb_size);
result++;
{
StrFromTimeIntervalA(szBuff, 256, result->ms, result->digits);
- ok(!strcmp(result->time_interval, szBuff), "Formatted %d %d wrong\n",
- result->ms, result->digits);
+ ok(!strcmp(result->time_interval, szBuff), "Formatted %d %d wrong: %s\n",
+ result->ms, result->digits, szBuff);
result++;
}
}
static const WCHAR wszPattern4[] = {'a','b',0};
LPWSTR retW;
LPSTR retA;
-
+
check_strrstri(A, szTest, 4, "A", szTest+1);
check_strrstri(A, szTest, 4, "aX", szTest+1);
check_strrstri(A, szTest, 4, "Ay", NULL);
return;
}
+ if (pSHAnsiToAnsi == (void *)pStrPBrkW)
+ {
+ win_skip("Ordinal 345 corresponds to StrPBrkW, skipping SHAnsiToAnsi tests\n");
+ return;
+ }
+
memset(dest, '\n', sizeof(dest));
dwRet = pSHAnsiToAnsi("hello", dest, sizeof(dest)/sizeof(dest[0]));
ok(dwRet == 6 && !memcmp(dest, "hello\0\n\n", sizeof(dest)),
return;
}
+ if (pSHUnicodeToUnicode == (void *)pStrRChrA)
+ {
+ win_skip("Ordinal 346 corresponds to StrRChrA, skipping SHUnicodeToUnicode tests\n");
+ return;
+ }
+
memcpy(dest, lpInit, sizeof(lpInit));
dwRet = pSHUnicodeToUnicode(lpSrc, dest, sizeof(dest)/sizeof(dest[0]));
ok(dwRet == 6 && !memcmp(dest, lpRes, sizeof(dest)),
{
memset(buf, 0xbf, sizeof(buf));
ret = pwnsprintfA(buf, 10, "%s", str1);
- ok(broken(ret == 9) || ret == -1 /* Vista */, "Unexpected wsnprintfA return %d, expected 9 or -1\n", ret);
+ ok(broken(ret == 9) || ret == -1 /* Vista */, "Unexpected wnsprintfA return %d, expected 9 or -1\n", ret);
expect_eq(buf[9], 0, CHAR, "%x");
expect_eq(buf[10], (CHAR)0xbf, CHAR, "%x");
}
{
memset(wbuf, 0xbf, sizeof(wbuf));
ret = pwnsprintfW(wbuf, 10, fmt, wstr1);
- ok(broken(ret == 9) || ret == -1 /* Vista */, "Unexpected wsnprintfW return %d, expected 9 or -1\n", ret);
+ ok(broken(ret == 9) || ret == -1 /* Vista */, "Unexpected wnsprintfW return %d, expected 9 or -1\n", ret);
expect_eq(wbuf[9], 0, WCHAR, "%x");
expect_eq(wbuf[10], (WCHAR)0xbfbf, WCHAR, "%x");
}
win_skip("wnsprintfW() is not available\n");
}
+static void test_StrStrA(void)
+{
+ static const char *deadbeefA = "DeAdBeEf";
+
+ const struct
+ {
+ const char *search;
+ const char *expect;
+ } StrStrA_cases[] =
+ {
+ {"", NULL},
+ {"DeAd", deadbeefA},
+ {"dead", NULL},
+ {"AdBe", deadbeefA + 2},
+ {"adbe", NULL},
+ {"BeEf", deadbeefA + 4},
+ {"beef", NULL},
+ };
+
+ LPSTR ret;
+ int i;
+
+ /* Tests crash on Win2k */
+ if (0)
+ {
+ ret = StrStrA(NULL, NULL);
+ ok(!ret, "Expected StrStrA to return NULL, got %p\n", ret);
+
+ ret = StrStrA(NULL, "");
+ ok(!ret, "Expected StrStrA to return NULL, got %p\n", ret);
+
+ ret = StrStrA("", NULL);
+ ok(!ret, "Expected StrStrA to return NULL, got %p\n", ret);
+ }
+
+ ret = StrStrA("", "");
+ ok(!ret, "Expected StrStrA to return NULL, got %p\n", ret);
+
+ for (i = 0; i < sizeof(StrStrA_cases)/sizeof(StrStrA_cases[0]); i++)
+ {
+ ret = StrStrA(deadbeefA, StrStrA_cases[i].search);
+ ok(ret == StrStrA_cases[i].expect,
+ "[%d] Expected StrStrA to return %p, got %p\n",
+ i, StrStrA_cases[i].expect, ret);
+ }
+}
+
+static void test_StrStrW(void)
+{
+ static const WCHAR emptyW[] = {0};
+ static const WCHAR deadbeefW[] = {'D','e','A','d','B','e','E','f',0};
+ static const WCHAR deadW[] = {'D','e','A','d',0};
+ static const WCHAR dead_lowerW[] = {'d','e','a','d',0};
+ static const WCHAR adbeW[] = {'A','d','B','e',0};
+ static const WCHAR adbe_lowerW[] = {'a','d','b','e',0};
+ static const WCHAR beefW[] = {'B','e','E','f',0};
+ static const WCHAR beef_lowerW[] = {'b','e','e','f',0};
+
+ const struct
+ {
+ const WCHAR *search;
+ const WCHAR *expect;
+ } StrStrW_cases[] =
+ {
+ {emptyW, NULL},
+ {deadW, deadbeefW},
+ {dead_lowerW, NULL},
+ {adbeW, deadbeefW + 2},
+ {adbe_lowerW, NULL},
+ {beefW, deadbeefW + 4},
+ {beef_lowerW, NULL},
+ };
+
+ LPWSTR ret;
+ int i;
+
+ /* Tests crash on Win2k */
+ if (0)
+ {
+ ret = StrStrW(NULL, NULL);
+ ok(!ret, "Expected StrStrW to return NULL, got %p\n", ret);
+
+ ret = StrStrW(NULL, emptyW);
+ ok(!ret, "Expected StrStrW to return NULL, got %p\n", ret);
+
+ ret = StrStrW(emptyW, NULL);
+ ok(!ret, "Expected StrStrW to return NULL, got %p\n", ret);
+ }
+
+ ret = StrStrW(emptyW, emptyW);
+ ok(!ret, "Expected StrStrW to return NULL, got %p\n", ret);
+
+ for (i = 0; i < sizeof(StrStrW_cases)/sizeof(StrStrW_cases[0]); i++)
+ {
+ ret = StrStrW(deadbeefW, StrStrW_cases[i].search);
+ ok(ret == StrStrW_cases[i].expect,
+ "[%d] Expected StrStrW to return %p, got %p\n",
+ i, StrStrW_cases[i].expect, ret);
+ }
+}
+
+static void test_StrStrIA(void)
+{
+ static const char *deadbeefA = "DeAdBeEf";
+
+ const struct
+ {
+ const char *search;
+ const char *expect;
+ } StrStrIA_cases[] =
+ {
+ {"", NULL},
+ {"DeAd", deadbeefA},
+ {"dead", deadbeefA},
+ {"AdBe", deadbeefA + 2},
+ {"adbe", deadbeefA + 2},
+ {"BeEf", deadbeefA + 4},
+ {"beef", deadbeefA + 4},
+ {"cafe", NULL},
+ };
+
+ LPSTR ret;
+ int i;
+
+ /* Tests crash on Win2k */
+ if (0)
+ {
+ ret = StrStrIA(NULL, NULL);
+ ok(!ret, "Expected StrStrIA to return NULL, got %p\n", ret);
+
+ ret = StrStrIA(NULL, "");
+ ok(!ret, "Expected StrStrIA to return NULL, got %p\n", ret);
+
+ ret = StrStrIA("", NULL);
+ ok(!ret, "Expected StrStrIA to return NULL, got %p\n", ret);
+ }
+
+ ret = StrStrIA("", "");
+ ok(!ret, "Expected StrStrIA to return NULL, got %p\n", ret);
+
+ for (i = 0; i < sizeof(StrStrIA_cases)/sizeof(StrStrIA_cases[0]); i++)
+ {
+ ret = StrStrIA(deadbeefA, StrStrIA_cases[i].search);
+ ok(ret == StrStrIA_cases[i].expect,
+ "[%d] Expected StrStrIA to return %p, got %p\n",
+ i, StrStrIA_cases[i].expect, ret);
+ }
+}
+
+static void test_StrStrIW(void)
+{
+ static const WCHAR emptyW[] = {0};
+ static const WCHAR deadbeefW[] = {'D','e','A','d','B','e','E','f',0};
+ static const WCHAR deadW[] = {'D','e','A','d',0};
+ static const WCHAR dead_lowerW[] = {'d','e','a','d',0};
+ static const WCHAR adbeW[] = {'A','d','B','e',0};
+ static const WCHAR adbe_lowerW[] = {'a','d','b','e',0};
+ static const WCHAR beefW[] = {'B','e','E','f',0};
+ static const WCHAR beef_lowerW[] = {'b','e','e','f',0};
+ static const WCHAR cafeW[] = {'c','a','f','e',0};
+
+ const struct
+ {
+ const WCHAR *search;
+ const WCHAR *expect;
+ } StrStrIW_cases[] =
+ {
+ {emptyW, NULL},
+ {deadW, deadbeefW},
+ {dead_lowerW, deadbeefW},
+ {adbeW, deadbeefW + 2},
+ {adbe_lowerW, deadbeefW + 2},
+ {beefW, deadbeefW + 4},
+ {beef_lowerW, deadbeefW + 4},
+ {cafeW, NULL},
+ };
+
+ LPWSTR ret;
+ int i;
+
+ /* Tests crash on Win2k */
+ if (0)
+ {
+ ret = StrStrIW(NULL, NULL);
+ ok(!ret, "Expected StrStrIW to return NULL, got %p\n", ret);
+
+ ret = StrStrIW(NULL, emptyW);
+ ok(!ret, "Expected StrStrIW to return NULL, got %p\n", ret);
+
+ ret = StrStrIW(emptyW, NULL);
+ ok(!ret, "Expected StrStrIW to return NULL, got %p\n", ret);
+ }
+
+ ret = StrStrIW(emptyW, emptyW);
+ ok(!ret, "Expected StrStrIW to return NULL, got %p\n", ret);
+
+ for (i = 0; i < sizeof(StrStrIW_cases)/sizeof(StrStrIW_cases[0]); i++)
+ {
+ ret = StrStrIW(deadbeefW, StrStrIW_cases[i].search);
+ ok(ret == StrStrIW_cases[i].expect,
+ "[%d] Expected StrStrIW to return %p, got %p\n",
+ i, StrStrIW_cases[i].expect, ret);
+ }
+}
+
+static void test_StrStrNW(void)
+{
+ static const WCHAR emptyW[] = {0};
+ static const WCHAR deadbeefW[] = {'D','e','A','d','B','e','E','f',0};
+ static const WCHAR deadW[] = {'D','e','A','d',0};
+ static const WCHAR dead_lowerW[] = {'d','e','a','d',0};
+ static const WCHAR adbeW[] = {'A','d','B','e',0};
+ static const WCHAR adbe_lowerW[] = {'a','d','b','e',0};
+ static const WCHAR beefW[] = {'B','e','E','f',0};
+ static const WCHAR beef_lowerW[] = {'b','e','e','f',0};
+
+ const struct
+ {
+ const WCHAR *search;
+ const UINT count;
+ const WCHAR *expect;
+ } StrStrNW_cases[] =
+ {
+ {emptyW, sizeof(deadbeefW)/sizeof(WCHAR), NULL},
+ {deadW, sizeof(deadbeefW)/sizeof(WCHAR), deadbeefW},
+ {dead_lowerW, sizeof(deadbeefW)/sizeof(WCHAR), NULL},
+ {adbeW, sizeof(deadbeefW)/sizeof(WCHAR), deadbeefW + 2},
+ {adbe_lowerW, sizeof(deadbeefW)/sizeof(WCHAR), NULL},
+ {beefW, sizeof(deadbeefW)/sizeof(WCHAR), deadbeefW + 4},
+ {beef_lowerW, sizeof(deadbeefW)/sizeof(WCHAR), NULL},
+ {beefW, 0, NULL},
+ {beefW, 1, NULL},
+ {beefW, 2, NULL},
+ {beefW, 3, NULL},
+ {beefW, 4, NULL},
+ {beefW, 5, deadbeefW + 4},
+ {beefW, 6, deadbeefW + 4},
+ {beefW, 7, deadbeefW + 4},
+ {beefW, 8, deadbeefW + 4},
+ {beefW, 9, deadbeefW + 4},
+ };
+
+ LPWSTR ret;
+ UINT i;
+
+ if (!pStrStrNW)
+ {
+ win_skip("StrStrNW() is not available\n");
+ return;
+ }
+
+ ret = pStrStrNW(NULL, NULL, 0);
+ ok(!ret, "Expected StrStrNW to return NULL, got %p\n", ret);
+
+ ret = pStrStrNW(NULL, NULL, 10);
+ ok(!ret, "Expected StrStrNW to return NULL, got %p\n", ret);
+
+ ret = pStrStrNW(NULL, emptyW, 10);
+ ok(!ret, "Expected StrStrNW to return NULL, got %p\n", ret);
+
+ ret = pStrStrNW(emptyW, NULL, 10);
+ ok(!ret, "Expected StrStrNW to return NULL, got %p\n", ret);
+
+ ret = pStrStrNW(emptyW, emptyW, 10);
+ ok(!ret, "Expected StrStrNW to return NULL, got %p\n", ret);
+
+ for (i = 0; i < sizeof(StrStrNW_cases)/sizeof(StrStrNW_cases[0]); i++)
+ {
+ ret = pStrStrNW(deadbeefW, StrStrNW_cases[i].search, StrStrNW_cases[i].count);
+ ok(ret == StrStrNW_cases[i].expect,
+ "[%d] Expected StrStrNW to return %p, got %p\n",
+ i, StrStrNW_cases[i].expect, ret);
+ }
+
+ /* StrStrNW accepts counts larger than the search string length but rejects
+ * counts larger than around 2G. The limit seems to change based on the
+ * caller executable itself. */
+ ret = pStrStrNW(deadbeefW, beefW, 100);
+ ok(ret == deadbeefW + 4, "Expected StrStrNW to return deadbeefW + 4, got %p\n", ret);
+
+ if (0)
+ {
+ ret = pStrStrNW(deadbeefW, beefW, ~0U);
+ ok(!ret, "Expected StrStrNW to return NULL, got %p\n", ret);
+ }
+}
+
+static void test_StrStrNIW(void)
+{
+ static const WCHAR emptyW[] = {0};
+ static const WCHAR deadbeefW[] = {'D','e','A','d','B','e','E','f',0};
+ static const WCHAR deadW[] = {'D','e','A','d',0};
+ static const WCHAR dead_lowerW[] = {'d','e','a','d',0};
+ static const WCHAR adbeW[] = {'A','d','B','e',0};
+ static const WCHAR adbe_lowerW[] = {'a','d','b','e',0};
+ static const WCHAR beefW[] = {'B','e','E','f',0};
+ static const WCHAR beef_lowerW[] = {'b','e','e','f',0};
+ static const WCHAR cafeW[] = {'c','a','f','e',0};
+
+ const struct
+ {
+ const WCHAR *search;
+ const UINT count;
+ const WCHAR *expect;
+ } StrStrNIW_cases[] =
+ {
+ {emptyW, sizeof(deadbeefW)/sizeof(WCHAR), NULL},
+ {deadW, sizeof(deadbeefW)/sizeof(WCHAR), deadbeefW},
+ {dead_lowerW, sizeof(deadbeefW)/sizeof(WCHAR), deadbeefW},
+ {adbeW, sizeof(deadbeefW)/sizeof(WCHAR), deadbeefW + 2},
+ {adbe_lowerW, sizeof(deadbeefW)/sizeof(WCHAR), deadbeefW + 2},
+ {beefW, sizeof(deadbeefW)/sizeof(WCHAR), deadbeefW + 4},
+ {beef_lowerW, sizeof(deadbeefW)/sizeof(WCHAR), deadbeefW + 4},
+ {cafeW, sizeof(deadbeefW)/sizeof(WCHAR), NULL},
+ {beefW, 0, NULL},
+ {beefW, 1, NULL},
+ {beefW, 2, NULL},
+ {beefW, 3, NULL},
+ {beefW, 4, NULL},
+ {beefW, 5, deadbeefW + 4},
+ {beefW, 6, deadbeefW + 4},
+ {beefW, 7, deadbeefW + 4},
+ {beefW, 8, deadbeefW + 4},
+ {beefW, 9, deadbeefW + 4},
+ {beef_lowerW, 0, NULL},
+ {beef_lowerW, 1, NULL},
+ {beef_lowerW, 2, NULL},
+ {beef_lowerW, 3, NULL},
+ {beef_lowerW, 4, NULL},
+ {beef_lowerW, 5, deadbeefW + 4},
+ {beef_lowerW, 6, deadbeefW + 4},
+ {beef_lowerW, 7, deadbeefW + 4},
+ {beef_lowerW, 8, deadbeefW + 4},
+ {beef_lowerW, 9, deadbeefW + 4},
+ };
+
+ LPWSTR ret;
+ UINT i;
+
+ if (!pStrStrNIW)
+ {
+ win_skip("StrStrNIW() is not available\n");
+ return;
+ }
+
+ ret = pStrStrNIW(NULL, NULL, 0);
+ ok(!ret, "Expected StrStrNIW to return NULL, got %p\n", ret);
+
+ ret = pStrStrNIW(NULL, NULL, 10);
+ ok(!ret, "Expected StrStrNIW to return NULL, got %p\n", ret);
+
+ ret = pStrStrNIW(NULL, emptyW, 10);
+ ok(!ret, "Expected StrStrNIW to return NULL, got %p\n", ret);
+
+ ret = pStrStrNIW(emptyW, NULL, 10);
+ ok(!ret, "Expected StrStrNIW to return NULL, got %p\n", ret);
+
+ ret = pStrStrNIW(emptyW, emptyW, 10);
+ ok(!ret, "Expected StrStrNIW to return NULL, got %p\n", ret);
+
+ for (i = 0; i < sizeof(StrStrNIW_cases)/sizeof(StrStrNIW_cases[0]); i++)
+ {
+ ret = pStrStrNIW(deadbeefW, StrStrNIW_cases[i].search, StrStrNIW_cases[i].count);
+ ok(ret == StrStrNIW_cases[i].expect,
+ "[%d] Expected StrStrNIW to return %p, got %p\n",
+ i, StrStrNIW_cases[i].expect, ret);
+ }
+
+ /* StrStrNIW accepts counts larger than the search string length but rejects
+ * counts larger than around 2G. The limit seems to change based on the
+ * caller executable itself. */
+ ret = pStrStrNIW(deadbeefW, beefW, 100);
+ ok(ret == deadbeefW + 4, "Expected StrStrNIW to return deadbeefW + 4, got %p\n", ret);
+
+ if (0)
+ {
+ ret = pStrStrNIW(deadbeefW, beefW, ~0U);
+ ok(!ret, "Expected StrStrNIW to return NULL, got %p\n", ret);
+ }
+}
+
START_TEST(string)
{
HMODULE hShlwapi;
pStrFormatKBSizeW = (void *)GetProcAddress(hShlwapi, "StrFormatKBSizeW");
pStrIsIntlEqualA = (void *)GetProcAddress(hShlwapi, "StrIsIntlEqualA");
pStrIsIntlEqualW = (void *)GetProcAddress(hShlwapi, "StrIsIntlEqualW");
+ pStrPBrkW = (void *)GetProcAddress(hShlwapi, "StrPBrkW");
+ pStrRChrA = (void *)GetProcAddress(hShlwapi, "StrRChrA");
pStrRetToBSTR = (void *)GetProcAddress(hShlwapi, "StrRetToBSTR");
pStrRetToBufA = (void *)GetProcAddress(hShlwapi, "StrRetToBufA");
pStrRetToBufW = (void *)GetProcAddress(hShlwapi, "StrRetToBufW");
+ pStrStrNW = (void *)GetProcAddress(hShlwapi, "StrStrNW");
+ pStrStrNIW = (void *)GetProcAddress(hShlwapi, "StrStrNIW");
pwnsprintfA = (void *)GetProcAddress(hShlwapi, "wnsprintfA");
pwnsprintfW = (void *)GetProcAddress(hShlwapi, "wnsprintfW");
+ pStrToInt64ExA = (void *)GetProcAddress(hShlwapi, "StrToInt64ExA");
+ pStrToInt64ExW = (void *)GetProcAddress(hShlwapi, "StrToInt64ExW");
test_StrChrA();
test_StrChrW();
test_StrToIntW();
test_StrToIntExA();
test_StrToIntExW();
+ test_StrToInt64ExA();
+ test_StrToInt64ExW();
test_StrDupA();
- if (lstrcmp(thousandDelim, ",")==0 && lstrcmp(decimalDelim, ".")==0)
+
+ /* language-dependent test */
+ if (is_lang_english() && is_locale_english())
{
- /* these tests are locale-dependent */
test_StrFormatByteSize64A();
test_StrFormatKBSizeA();
test_StrFormatKBSizeW();
}
-
- /* language-dependent test */
- if (PRIMARYLANGID(GetUserDefaultLangID()) != LANG_ENGLISH)
- trace("Skipping StrFromTimeInterval test for non English language\n");
else
+ skip("An English UI and locale is required for the StrFormat*Size tests\n");
+ if (is_lang_english())
test_StrFromTimeIntervalA();
+ else
+ skip("An English UI is required for the StrFromTimeInterval tests\n");
test_StrCmpA();
test_StrCmpW();
test_SHAnsiToAnsi();
test_SHUnicodeToUnicode();
test_StrXXX_overflows();
+ test_StrStrA();
+ test_StrStrW();
+ test_StrStrIA();
+ test_StrStrIW();
+ test_StrStrNW();
+ test_StrStrNIW();
CoUninitialize();
}
#include <stdarg.h>
#define COBJMACROS
+#define CONST_VTABLE
+
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
typedef struct
{
- const IUnknownVtbl* lpVtbl;
+ IUnknown IUnknown_iface;
LONG *ref;
} threadref;
+static inline threadref *impl_from_IUnknown(IUnknown *iface)
+{
+ return CONTAINING_RECORD(iface, threadref, IUnknown_iface);
+}
+
static HRESULT WINAPI threadref_QueryInterface(IUnknown *iface, REFIID riid, LPVOID *ppvObj)
{
- threadref * This = (threadref *)iface;
+ threadref * This = impl_from_IUnknown(iface);
trace("unexpected QueryInterface(%p, %p, %p) called\n", This, riid, ppvObj);
*ppvObj = NULL;
static ULONG WINAPI threadref_AddRef(IUnknown *iface)
{
- threadref * This = (threadref *)iface;
+ threadref * This = impl_from_IUnknown(iface);
AddRef_called++;
return InterlockedIncrement(This->ref);
static ULONG WINAPI threadref_Release(IUnknown *iface)
{
- threadref * This = (threadref *)iface;
+ threadref * This = impl_from_IUnknown(iface);
trace("unexpected Release(%p) called\n", This);
return InterlockedDecrement(This->ref);
static void init_threadref(threadref* iface, LONG *refcount)
{
- iface->lpVtbl = &threadref_vt;
+ iface->IUnknown_iface.lpVtbl = &threadref_vt;
iface->ref = refcount;
}
if (0) {
/* this crash on Windows */
- hr = pSHGetThreadRef(NULL);
+ pSHGetThreadRef(NULL);
}
}
init_threadref(&ref, &refcount);
AddRef_called = 0;
refcount = 1;
- hr = pSHSetThreadRef( (IUnknown *)&ref);
+ hr = pSHSetThreadRef(&ref.IUnknown_iface);
ok( (hr == S_OK) && (refcount == 1) && (!AddRef_called),
"got 0x%x with %d, %d (expected S_OK with 1, 0)\n",
hr, refcount, AddRef_called);
refcount = 1;
punk = NULL;
hr = pSHGetThreadRef(&punk);
- ok( (hr == S_OK) && (punk == (IUnknown *)&ref) && (refcount == 2) && (AddRef_called == 1),
+ ok( (hr == S_OK) && (punk == &ref.IUnknown_iface) && (refcount == 2) && (AddRef_called == 1),
"got 0x%x and %p with %d, %d (expected S_OK and %p with 2, 1)\n",
hr, punk, refcount, AddRef_called, &ref);
static const char* TEST_URL_1 = "http://www.winehq.org/tests?date=10/10/1923";
static const char* TEST_URL_2 = "http://localhost:8080/tests%2e.html?date=Mon%2010/10/1923";
static const char* TEST_URL_3 = "http://foo:bar@localhost:21/internal.php?query=x&return=y";
+static const char* TEST_URL_4 = "http://foo:bar@google.*.com:21/internal.php?query=x&return=y";
+
static const WCHAR winehqW[] = {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.','o','r','g','/',0};
static const CHAR winehqA[] = {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.','o','r','g','/',0};
{"winehq.org", URL_APPLY_GUESSSCHEME | URL_APPLY_DEFAULT, S_OK, 17, "http://winehq.org"},
{"winehq.org", URL_APPLY_GUESSSCHEME, S_FALSE, TEST_APPLY_MAX_LENGTH, untouchedA},
{"winehq.org", URL_APPLY_DEFAULT, S_OK, 17, "http://winehq.org"},
+ {"http://www.winehq.org", URL_APPLY_GUESSSCHEME , S_FALSE, TEST_APPLY_MAX_LENGTH, untouchedA},
+ {"http://www.winehq.org", URL_APPLY_GUESSSCHEME | URL_APPLY_FORCEAPPLY, S_FALSE, TEST_APPLY_MAX_LENGTH, untouchedA},
+ {"http://www.winehq.org", URL_APPLY_GUESSSCHEME | URL_APPLY_FORCEAPPLY | URL_APPLY_DEFAULT, S_OK, 28, "http://http://www.winehq.org"},
+ {"http://www.winehq.org", URL_APPLY_GUESSSCHEME | URL_APPLY_DEFAULT, S_FALSE, TEST_APPLY_MAX_LENGTH, untouchedA},
{"", URL_APPLY_GUESSSCHEME | URL_APPLY_DEFAULT, S_OK, 7, "http://"},
{"", URL_APPLY_GUESSSCHEME, S_FALSE, TEST_APPLY_MAX_LENGTH, untouchedA},
- {"", URL_APPLY_DEFAULT, S_OK, 7, "http://"}
+ {"", URL_APPLY_DEFAULT, S_OK, 7, "http://"},
+ {"u:\\windows", URL_APPLY_GUESSFILE | URL_APPLY_DEFAULT, S_OK, 18, "file:///u:/windows"},
+ {"u:\\windows", URL_APPLY_GUESSFILE, S_OK, 18, "file:///u:/windows"},
+ {"u:\\windows", URL_APPLY_DEFAULT, S_OK, 17, "http://u:\\windows"},
+ {"file:///c:/windows", URL_APPLY_GUESSFILE , S_FALSE, TEST_APPLY_MAX_LENGTH, untouchedA},
+ {"aa:\\windows", URL_APPLY_GUESSFILE , S_FALSE, TEST_APPLY_MAX_LENGTH, untouchedA},
};
/* ################ */
static const TEST_URL_CANONICALIZE TEST_CANONICALIZE[] = {
{"http://www.winehq.org/tests/../tests/../..", 0, S_OK, "http://www.winehq.org/", TRUE},
+ {"http://www.winehq.org/..", 0, S_OK, "http://www.winehq.org/..", FALSE},
+ {"http://www.winehq.org/tests/tests2/../../tests", 0, S_OK, "http://www.winehq.org/tests", FALSE},
{"http://www.winehq.org/tests/../tests", 0, S_OK, "http://www.winehq.org/tests", FALSE},
{"http://www.winehq.org/tests\n", URL_WININET_COMPATIBILITY|URL_ESCAPE_SPACES_ONLY|URL_ESCAPE_UNSAFE, S_OK, "http://www.winehq.org/tests", FALSE},
{"http://www.winehq.org/tests\r", URL_WININET_COMPATIBILITY|URL_ESCAPE_SPACES_ONLY|URL_ESCAPE_UNSAFE, S_OK, "http://www.winehq.org/tests", FALSE},
{"http://www.winehq.org/tests/../", 0, S_OK, "http://www.winehq.org/", FALSE},
{"http://www.winehq.org/tests/..?query=x&return=y", 0, S_OK, "http://www.winehq.org/?query=x&return=y", FALSE},
{"http://www.winehq.org/tests/../?query=x&return=y", 0, S_OK, "http://www.winehq.org/?query=x&return=y", FALSE},
+ {"\tht\ttp\t://www\t.w\tineh\t\tq.or\tg\t/\ttests/..\t?\tquer\ty=x\t\t&re\tturn=y\t\t", 0, S_OK, "http://www.winehq.org/?query=x&return=y", FALSE},
{"http://www.winehq.org/tests/..#example", 0, S_OK, "http://www.winehq.org/#example", FALSE},
{"http://www.winehq.org/tests/../#example", 0, S_OK, "http://www.winehq.org/#example", FALSE},
{"http://www.winehq.org/tests\\../#example", 0, S_OK, "http://www.winehq.org/#example", FALSE},
{"http://www.winehq.org/tests/../#example", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests/../#example", FALSE},
{"http://www.winehq.org/tests/foo bar", URL_ESCAPE_SPACES_ONLY| URL_DONT_ESCAPE_EXTRA_INFO , S_OK, "http://www.winehq.org/tests/foo%20bar", FALSE},
{"http://www.winehq.org/tests/foo%20bar", URL_UNESCAPE , S_OK, "http://www.winehq.org/tests/foo bar", FALSE},
+ {"http://www.winehq.org", 0, S_OK, "http://www.winehq.org/", FALSE},
+ {"http:///www.winehq.org", 0, S_OK, "http:///www.winehq.org", FALSE},
+ {"http:////www.winehq.org", 0, S_OK, "http:////www.winehq.org", FALSE},
{"file:///c:/tests/foo%20bar", URL_UNESCAPE , S_OK, "file:///c:/tests/foo bar", FALSE},
{"file:///c:/tests\\foo%20bar", URL_UNESCAPE , S_OK, "file:///c:/tests/foo bar", FALSE},
{"file:///c:/tests/foo%20bar", 0, S_OK, "file:///c:/tests/foo%20bar", FALSE},
{"file:///c://tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\\\tests\\foo bar", FALSE},
{"file:///c:\\tests\\foo bar", 0, S_OK, "file:///c:/tests/foo bar", FALSE},
{"file:///c:\\tests\\foo bar", URL_DONT_SIMPLIFY, S_OK, "file:///c:/tests/foo bar", FALSE},
+ {"file:///c:\\tests\\foobar", 0, S_OK, "file:///c:/tests/foobar", FALSE},
+ {"file:///c:\\tests\\foobar", URL_WININET_COMPATIBILITY, S_OK, "file://c:\\tests\\foobar", FALSE},
+ {"file://home/user/file", 0, S_OK, "file://home/user/file", FALSE},
+ {"file:///home/user/file", 0, S_OK, "file:///home/user/file", FALSE},
+ {"file:////home/user/file", 0, S_OK, "file://home/user/file", FALSE},
+ {"file://home/user/file", URL_WININET_COMPATIBILITY, S_OK, "file://\\\\home\\user\\file", FALSE},
+ {"file:///home/user/file", URL_WININET_COMPATIBILITY, S_OK, "file://\\home\\user\\file", FALSE},
+ {"file:////home/user/file", URL_WININET_COMPATIBILITY, S_OK, "file://\\\\home\\user\\file", FALSE},
+ {"file://///home/user/file", URL_WININET_COMPATIBILITY, S_OK, "file://\\\\home\\user\\file", FALSE},
+ {"file://C:/user/file", 0, S_OK, "file:///C:/user/file", FALSE},
+ {"file://C:/user/file/../asdf", 0, S_OK, "file:///C:/user/asdf", FALSE},
+ {"file:///C:/user/file", 0, S_OK, "file:///C:/user/file", FALSE},
+ {"file:////C:/user/file", 0, S_OK, "file:///C:/user/file", FALSE},
+ {"file://C:/user/file", URL_WININET_COMPATIBILITY, S_OK, "file://C:\\user\\file", FALSE},
+ {"file:///C:/user/file", URL_WININET_COMPATIBILITY, S_OK, "file://C:\\user\\file", FALSE},
+ {"file:////C:/user/file", URL_WININET_COMPATIBILITY, S_OK, "file://C:\\user\\file", FALSE},
+ {"http:///www.winehq.org", 0, S_OK, "http:///www.winehq.org", FALSE},
+ {"http:///www.winehq.org", URL_WININET_COMPATIBILITY, S_OK, "http:///www.winehq.org", FALSE},
{"http://www.winehq.org/site/about", URL_FILE_USE_PATHURL, S_OK, "http://www.winehq.org/site/about", FALSE},
{"file_://www.winehq.org/site/about", URL_FILE_USE_PATHURL, S_OK, "file_://www.winehq.org/site/about", FALSE},
{"c:\\dir\\file", 0, S_OK, "file:///c:/dir/file", FALSE},
{"c:dir\\file", 0, S_OK, "file:///c:dir/file", FALSE},
{"c:\\tests\\foo bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar", FALSE},
{"c:\\tests\\foo bar", 0, S_OK, "file:///c:/tests/foo%20bar", FALSE},
+ {"c\t:\t\\te\tsts\\fo\to \tbar\t", 0, S_OK, "file:///c:/tests/foo%20bar", FALSE},
{"res://file", 0, S_OK, "res://file/", FALSE},
{"res://file", URL_FILE_USE_PATHURL, S_OK, "res://file/", FALSE},
{"res:///c:/tests/foo%20bar", URL_UNESCAPE , S_OK, "res:///c:/tests/foo bar", FALSE},
{"res://c:\\tests/res\\foo%20bar/strange\\sth", URL_FILE_USE_PATHURL, S_OK, "res://c:\\tests/res\\foo%20bar/strange\\sth", FALSE},
{"res://c:\\tests/res\\foo%20bar/strange\\sth", URL_UNESCAPE, S_OK, "res://c:\\tests/res\\foo bar/strange\\sth", FALSE},
{"A", 0, S_OK, "A", FALSE},
+ {"../A", 0, S_OK, "../A", FALSE},
+ {"A/../B", 0, S_OK, "B", TRUE},
{"/uri-res/N2R?urn:sha1:B3K", URL_DONT_ESCAPE_EXTRA_INFO | URL_WININET_COMPATIBILITY /*0x82000000*/, S_OK, "/uri-res/N2R?urn:sha1:B3K", FALSE} /*LimeWire online installer calls this*/,
{"http:www.winehq.org/dir/../index.html", 0, S_OK, "http:www.winehq.org/index.html"},
{"http://localhost/test.html", URL_FILE_USE_PATHURL, S_OK, "http://localhost/test.html"},
{"http://localhost/te%20st.html", URL_FILE_USE_PATHURL, S_OK, "http://localhost/te%20st.html"},
- {"http://www.winehq.org/%E6%A1%9C.html", URL_FILE_USE_PATHURL, S_OK, "http://www.winehq.org/%E6%A1%9C.html"}
+ {"http://www.winehq.org/%E6%A1%9C.html", URL_FILE_USE_PATHURL, S_OK, "http://www.winehq.org/%E6%A1%9C.html"},
+ {"mk:@MSITStore:C:\\Program Files/AutoCAD 2008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm", 0, S_OK, "mk:@MSITStore:C:\\Program Files/AutoCAD 2008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm"},
+ {"ftp:@MSITStore:C:\\Program Files/AutoCAD 2008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm", 0, S_OK, "ftp:@MSITStore:C:\\Program Files/AutoCAD 2008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm"},
+ {"file:@MSITStore:C:\\Program Files/AutoCAD 2008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm", 0, S_OK, "file:@MSITStore:C:/Program Files/AutoCAD 2008/Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm"},
+ {"http:@MSITStore:C:\\Program Files/AutoCAD 2008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm", 0, S_OK, "http:@MSITStore:C:/Program Files/AutoCAD 2008/Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm"},
+ {"http:@MSITStore:C:\\Program Files/AutoCAD 2008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm", URL_FILE_USE_PATHURL, S_OK, "http:@MSITStore:C:/Program Files/AutoCAD 2008/Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm"},
+ {"mk:@MSITStore:C:\\Program Files/AutoCAD 2008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm", URL_FILE_USE_PATHURL, S_OK, "mk:@MSITStore:C:\\Program Files/AutoCAD 2008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm"},
};
/* ################ */
{"http://www.winehq.org/tests/#example", "tests9", 0, S_OK, "http://www.winehq.org/tests/tests9"},
{"http://www.winehq.org/tests/../tests/", "/tests10/..", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests10/.."},
{"http://www.winehq.org/tests/../", "tests11", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests/../tests11"},
+ {"http://www.winehq.org/test12", "#", 0, S_OK, "http://www.winehq.org/test12#"},
+ {"http://www.winehq.org/test13#aaa", "#bbb", 0, S_OK, "http://www.winehq.org/test13#bbb"},
+ {"http://www.winehq.org/test14#aaa/bbb#ccc", "#", 0, S_OK, "http://www.winehq.org/test14#"},
{"file:///C:\\dir\\file.txt", "test.txt", 0, S_OK, "file:///C:/dir/test.txt"},
{"file:///C:\\dir\\file.txt#hash\\hash", "test.txt", 0, S_OK, "file:///C:/dir/file.txt#hash/test.txt"},
{"file:///C:\\dir\\file.html#hash\\hash", "test.html", 0, S_OK, "file:///C:/dir/test.html"},
{"foo:today", "foo:calendar", 0, S_OK, "foo:calendar"},
{"foo:today", "bar:calendar", 0, S_OK, "bar:calendar"},
{"foo:/today", "foo:calendar", 0, S_OK, "foo:/calendar"},
- {"foo:/today/", "foo:calendar", 0, S_OK, "foo:/today/calendar"},
+ {"Foo:/today/", "fOo:calendar", 0, S_OK, "foo:/today/calendar"},
{"mk:@MSITStore:dir/test.chm::dir/index.html", "image.jpg", 0, S_OK, "mk:@MSITStore:dir/test.chm::dir/image.jpg"},
{"mk:@MSITStore:dir/test.chm::dir/dir2/index.html", "../image.jpg", 0, S_OK, "mk:@MSITStore:dir/test.chm::dir/image.jpg"},
/* UrlCombine case 2 tests. Schemes do not match */
{"outbind://xxxxxxxxx/","http:wine16/dir",0, S_OK,"http:wine16/dir"},
{"http://xxxxxxxxx","outbind:wine17/dir",URL_PLUGGABLE_PROTOCOL, S_OK,"outbind:wine17/dir"},
{"xxx://xxxxxxxxx","ftp:wine18/dir",URL_PLUGGABLE_PROTOCOL, S_OK,"ftp:wine18/dir"},
- {"ftp://xxxxxxxxx/","xxx:wine19/dir",URL_PLUGGABLE_PROTOCOL, S_OK,"xxx:wine19/dir"},
+ {"ftp://xxxxxxxxx/","xXx:wine19/dir",URL_PLUGGABLE_PROTOCOL, S_OK,"xxx:wine19/dir"},
{"outbind://xxxxxxxxx/","http:wine20/dir",URL_PLUGGABLE_PROTOCOL, S_OK,"http:wine20/dir"},
{"file:///c:/dir/file.txt","index.html?test=c:/abc",URL_ESCAPE_SPACES_ONLY|URL_DONT_ESCAPE_EXTRA_INFO,S_OK,"file:///c:/dir/index.html?test=c:/abc"}
};
{"c:foo\\bar", "file:///c:foo/bar", S_OK},
{"c:\\foo/b a%r", "file:///c:/foo/b%20a%25r", S_OK},
{"c:\\foo\\foo bar", "file:///c:/foo/foo%20bar", S_OK},
+ {"file:///c:/foo/bar", "file:///c:/foo/bar", S_FALSE},
#if 0
/* The following test fails on native shlwapi as distributed with Win95/98.
* Wine matches the behaviour of later versions.
const char* http_url = "http://user:pass 123@www.wine hq.org";
const char* res_url = "res://some.dll/find.dlg";
const char* about_url = "about:blank";
+ const char* excid_url = "x-excid://36C00000/guid:{048B4E89-2E92-496F-A837-33BA02FF6D32}/Message.htm";
+ const char* foo_url = "foo://bar-url/test";
+ const char* short_url = "ascheme:";
CHAR szPart[INTERNET_MAX_URL_LENGTH];
DWORD dwSize;
ok(szPart[0]==0, "UrlGetPartA(\"hi\") return \"%s\" instead of \"\"\n", szPart);
ok(dwSize == 0, "dwSize = %d\n", dwSize);
+ if(pUrlGetPartW)
+ {
+ const WCHAR hiW[] = {'h','i',0};
+ WCHAR bufW[5];
+
+ /* UrlGetPartW returns S_OK instead of S_FALSE */
+ dwSize = sizeof szPart;
+ bufW[0]='x'; bufW[1]=0;
+ res = pUrlGetPartW(hiW, bufW, &dwSize, URL_PART_SCHEME, 0);
+ todo_wine ok(res==S_OK, "UrlGetPartW(\"hi\") returned %08X\n", res);
+ ok(bufW[0] == 0, "UrlGetPartW(\"hi\") return \"%c\"\n", bufW[0]);
+ ok(dwSize == 0, "dwSize = %d\n", dwSize);
+ }
+
dwSize = sizeof szPart;
szPart[0]='x'; szPart[1]=0;
res = pUrlGetPartA("hi", szPart, &dwSize, URL_PART_QUERY, 0);
test_url_part(TEST_URL_3, URL_PART_SCHEME, 0, "http");
test_url_part(TEST_URL_3, URL_PART_QUERY, 0, "?query=x&return=y");
+ test_url_part(TEST_URL_4, URL_PART_HOSTNAME, 0, "google.*.com");
+
test_url_part(file_url, URL_PART_HOSTNAME, 0, "h o s t");
test_url_part(http_url, URL_PART_HOSTNAME, 0, "www.wine hq.org");
test_url_part(about_url, URL_PART_SCHEME, 0, "about");
+ test_url_part(excid_url, URL_PART_SCHEME, 0, "x-excid");
+ test_url_part(foo_url, URL_PART_SCHEME, 0, "foo");
+ test_url_part(short_url, URL_PART_SCHEME, 0, "ascheme");
+
dwSize = sizeof(szPart);
res = pUrlGetPartA(about_url, szPart, &dwSize, URL_PART_HOSTNAME, 0);
ok(res==E_FAIL, "returned %08x\n", res);
szPart[0] = 'x'; szPart[1] = '\0';
res = pUrlGetPartA("index.htm", szPart, &dwSize, URL_PART_HOSTNAME, 0);
ok(res==E_FAIL, "returned %08x\n", res);
+
+ dwSize = sizeof(szPart);
+ szPart[0] = 'x'; szPart[1] = '\0';
+ res = pUrlGetPartA(excid_url, szPart, &dwSize, URL_PART_HOSTNAME, 0);
+ ok(res==E_FAIL, "returned %08x\n", res);
+ ok(szPart[0] == 'x', "szPart[0] = %c\n", szPart[0]);
+ ok(dwSize == sizeof(szPart), "dwSize = %d\n", dwSize);
+
+ dwSize = sizeof(szPart);
+ szPart[0] = 'x'; szPart[1] = '\0';
+ res = pUrlGetPartA(excid_url, szPart, &dwSize, URL_PART_QUERY, 0);
+ ok(res==S_FALSE, "returned %08x\n", res);
+ ok(szPart[0] == 0, "szPart[0] = %c\n", szPart[0]);
+ ok(dwSize == 0, "dwSize = %d\n", dwSize);
+
+ dwSize = sizeof(szPart);
+ szPart[0] = 'x'; szPart[1] = '\0';
+ res = pUrlGetPartA(foo_url, szPart, &dwSize, URL_PART_HOSTNAME, 0);
+ ok(res==E_FAIL, "returned %08x\n", res);
+ ok(szPart[0] == 'x', "szPart[0] = %c\n", szPart[0]);
+ ok(dwSize == sizeof(szPart), "dwSize = %d\n", dwSize);
+
+ dwSize = sizeof(szPart);
+ szPart[0] = 'x'; szPart[1] = '\0';
+ res = pUrlGetPartA(foo_url, szPart, &dwSize, URL_PART_QUERY, 0);
+ ok(res==S_FALSE, "returned %08x\n", res);
+ ok(szPart[0] == 0, "szPart[0] = %c\n", szPart[0]);
+ ok(dwSize == 0, "dwSize = %d\n", dwSize);
}
/* ########################### */
static void test_UrlEscape(void)
{
+ static const WCHAR out[] = { 'f','o','o','%','2','0','b','a','r',0 };
+
DWORD size = 0;
HRESULT ret;
unsigned int i;
char empty_string[] = "";
+ WCHAR overwrite[] = { 'f','o','o',' ','b','a','r',0,0,0 };
if (!pUrlEscapeA) {
win_skip("UrlEscapeA noz found\n");
ok(size == 1, "got %d, expected %d\n", size, 1);
size = 1;
+ empty_string[0] = 127;
ret = pUrlEscapeA("/woningplan/woonkamer basis.swf", empty_string, &size, URL_ESCAPE_SPACES_ONLY);
ok(ret == E_POINTER, "got %x, expected %x\n", ret, E_POINTER);
ok(size == 34, "got %d, expected %d\n", size, 34);
+ ok(empty_string[0] == 127, "String has changed, empty_string[0] = %d\n", empty_string[0]);
+
+ if(pUrlEscapeW) {
+ WCHAR wc;
+
+ size = sizeof(overwrite)/sizeof(WCHAR);
+ ret = pUrlEscapeW(overwrite, overwrite, &size, URL_ESCAPE_SPACES_ONLY);
+ ok(ret == S_OK, "got %x, expected S_OK\n", ret);
+ ok(size == 9, "got %d, expected 9\n", size);
+ ok(!lstrcmpW(overwrite, out), "got %s, expected %s\n", wine_dbgstr_w(overwrite), wine_dbgstr_w(out));
+
+ size = 1;
+ wc = 127;
+ ret = pUrlEscapeW(overwrite, &wc, &size, URL_ESCAPE_SPACES_ONLY);
+ ok(ret == E_POINTER, "got %x, expected %x\n", ret, E_POINTER);
+ ok(size == 10, "got %d, expected 10\n", size);
+ ok(wc == 127, "String has changed, wc = %d\n", wc);
+ }
for(i=0; i<sizeof(TEST_ESCAPE)/sizeof(TEST_ESCAPE[0]); i++) {
test_url_escape(TEST_ESCAPE[i].url, TEST_ESCAPE[i].flags,
START_TEST(url)
{
+ char *pFunc;
hShlwapi = GetModuleHandleA("shlwapi.dll");
+
+ /* SHCreateStreamOnFileEx was introduced in shlwapi v6.0 */
+ pFunc = (void*)GetProcAddress(hShlwapi, "SHCreateStreamOnFileEx");
+ if(!pFunc){
+ win_skip("Too old shlwapi version\n");
+ return;
+ }
+
pUrlUnescapeA = (void *) GetProcAddress(hShlwapi, "UrlUnescapeA");
pUrlUnescapeW = (void *) GetProcAddress(hShlwapi, "UrlUnescapeW");
pUrlIsA = (void *) GetProcAddress(hShlwapi, "UrlIsA");