1 /* Unit test suite for SHLWAPI ordinal functions
3 * Copyright 2004 Jon Griffiths
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "wine/test.h"
33 /* Function ptrs for ordinal calls */
34 static HMODULE hShlwapi;
35 static int (WINAPI *pSHSearchMapInt)(const int*,const int*,int,int);
36 static HRESULT (WINAPI *pGetAcceptLanguagesA)(LPSTR,LPDWORD);
38 static HANDLE (WINAPI *pSHAllocShared)(LPCVOID,DWORD,DWORD);
39 static LPVOID (WINAPI *pSHLockShared)(HANDLE,DWORD);
40 static BOOL (WINAPI *pSHUnlockShared)(LPVOID);
41 static BOOL (WINAPI *pSHFreeShared)(HANDLE,DWORD);
42 static HRESULT(WINAPIV *pSHPackDispParams)(DISPPARAMS*,VARIANTARG*,UINT,...);
43 static HRESULT(WINAPI *pIConnectionPoint_SimpleInvoke)(IConnectionPoint*,DISPID,DISPPARAMS*);
44 static HRESULT(WINAPI *pIConnectionPoint_InvokeWithCancel)(IConnectionPoint*,DISPID,DISPPARAMS*,DWORD,DWORD);
45 static HRESULT(WINAPI *pConnectToConnectionPoint)(IUnknown*,REFIID,BOOL,IUnknown*, LPDWORD,IConnectionPoint **);
46 static HRESULT(WINAPI *pSHPropertyBag_ReadLONG)(IPropertyBag *,LPCWSTR,LPLONG);
47 static LONG (WINAPI *pSHSetWindowBits)(HWND, INT, UINT, UINT);
48 static INT (WINAPI *pSHFormatDateTimeA)(const FILETIME UNALIGNED*, DWORD*, LPSTR, UINT);
49 static INT (WINAPI *pSHFormatDateTimeW)(const FILETIME UNALIGNED*, DWORD*, LPWSTR, UINT);
51 static HMODULE hmlang;
52 static HRESULT (WINAPI *pLcidToRfc1766A)(LCID, LPSTR, INT);
54 static const CHAR ie_international[] = {
55 'S','o','f','t','w','a','r','e','\\',
56 'M','i','c','r','o','s','o','f','t','\\',
57 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
58 'I','n','t','e','r','n','a','t','i','o','n','a','l',0};
59 static const CHAR acceptlanguage[] = {
60 'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0};
63 static void test_GetAcceptLanguagesA(void)
65 static LPCSTR table[] = {"de,en-gb;q=0.7,en;q=0.3",
66 "de,en;q=0.3,en-gb;q=0.7", /* sorting is ignored */
67 "winetest", /* content is ignored */
77 LONG res_query = ERROR_SUCCESS;
80 DWORD maxlen = sizeof(buffer) - 2;
86 if (!pGetAcceptLanguagesA) {
87 win_skip("GetAcceptLanguagesA is not available\n");
91 lcid = GetUserDefaultLCID();
93 /* Get the original Value */
94 lres = RegOpenKeyA(HKEY_CURRENT_USER, ie_international, &hroot);
96 skip("RegOpenKey(%s) failed: %d\n", ie_international, lres);
99 len = sizeof(original);
101 res_query = RegQueryValueExA(hroot, acceptlanguage, 0, NULL, (PBYTE)original, &len);
103 RegDeleteValue(hroot, acceptlanguage);
105 /* Some windows versions use "lang-COUNTRY" as default */
106 memset(language, 0, sizeof(language));
107 len = GetLocaleInfoA(lcid, LOCALE_SISO639LANGNAME, language, sizeof(language));
110 lstrcat(language, "-");
111 memset(buffer, 0, sizeof(buffer));
112 len = GetLocaleInfoA(lcid, LOCALE_SISO3166CTRYNAME, buffer, sizeof(buffer) - len - 1);
113 lstrcat(language, buffer);
117 /* LOCALE_SNAME has additional parts in some languages. Try only as last chance */
118 memset(language, 0, sizeof(language));
119 len = GetLocaleInfoA(lcid, LOCALE_SNAME, language, sizeof(language));
122 /* get the default value */
124 memset(buffer, '#', maxlen);
126 hr = pGetAcceptLanguagesA( buffer, &len);
129 win_skip("GetAcceptLanguagesA failed with 0x%x\n", hr);
130 goto restore_original;
133 if (lstrcmpA(buffer, language)) {
134 /* some windows versions use "lang" or "lang-country" as default */
136 if (pLcidToRfc1766A) {
137 hr = pLcidToRfc1766A(lcid, language, sizeof(language));
138 ok(hr == S_OK, "LcidToRfc1766A returned 0x%x and %s\n", hr, language);
142 ok(!lstrcmpA(buffer, language),
143 "have '%s' (searching for '%s')\n", language, buffer);
145 if (lstrcmpA(buffer, language)) {
146 win_skip("no more ideas, how to build the default language '%s'\n", buffer);
147 goto restore_original;
150 trace("detected default: %s\n", language);
151 while ((entry = table[i])) {
153 exactsize = lstrlenA(entry);
155 lres = RegSetValueExA(hroot, acceptlanguage, 0, REG_SZ, (const BYTE *) entry, exactsize + 1);
156 ok(!lres, "got %d for RegSetValueExA: %s\n", lres, entry);
158 /* len includes space for the terminating 0 before vista/w2k8 */
160 memset(buffer, '#', maxlen);
162 hr = pGetAcceptLanguagesA( buffer, &len);
163 ok(((hr == E_INVALIDARG) && (len == 0)) ||
165 ((len == exactsize) || (len == exactsize+1)) &&
166 !lstrcmpA(buffer, entry)),
167 "+2_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
170 memset(buffer, '#', maxlen);
172 hr = pGetAcceptLanguagesA( buffer, &len);
173 ok(((hr == E_INVALIDARG) && (len == 0)) ||
175 ((len == exactsize) || (len == exactsize+1)) &&
176 !lstrcmpA(buffer, entry)),
177 "+1_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
180 memset(buffer, '#', maxlen);
182 hr = pGetAcceptLanguagesA( buffer, &len);
184 /* There is no space for the string in the registry.
185 When the buffer is large enough, the default language is returned
187 When the buffer is to small for that fallback, win7_32 and w2k8_64
188 and above fail with HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), but
189 recent os succeed and return a partial result while
190 older os succeed and overflow the buffer */
192 ok(((hr == E_INVALIDARG) && (len == 0)) ||
193 (((hr == S_OK) && !lstrcmpA(buffer, language) && (len == lstrlenA(language))) ||
194 ((hr == S_OK) && !memcmp(buffer, language, len)) ||
195 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len)),
196 "==_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
200 memset(buffer, '#', maxlen);
202 hr = pGetAcceptLanguagesA( buffer, &len);
203 ok(((hr == E_INVALIDARG) && (len == 0)) ||
204 (((hr == S_OK) && !lstrcmpA(buffer, language) && (len == lstrlenA(language))) ||
205 ((hr == S_OK) && !memcmp(buffer, language, len)) ||
206 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len)),
207 "-1_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
211 memset(buffer, '#', maxlen);
213 hr = pGetAcceptLanguagesA( buffer, &len);
214 ok(((hr == E_INVALIDARG) && (len == 0)) ||
215 (((hr == S_OK) && !lstrcmpA(buffer, language) && (len == lstrlenA(language))) ||
216 ((hr == S_OK) && !memcmp(buffer, language, len)) ||
217 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len)),
218 "=1_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
221 hr = pGetAcceptLanguagesA( NULL, &len);
223 /* w2k3 and below: E_FAIL and untouched len,
224 since w2k8: S_OK and needed size (excluding 0) */
225 ok( ((hr == S_OK) && (len == exactsize)) ||
226 ((hr == E_FAIL) && (len == maxlen)),
227 "NULL,max #%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
232 /* without a value in the registry, a default language is returned */
233 RegDeleteValue(hroot, acceptlanguage);
236 memset(buffer, '#', maxlen);
238 hr = pGetAcceptLanguagesA( buffer, &len);
239 ok( ((hr == S_OK) && (len == lstrlenA(language))),
240 "max: got 0x%x with %d and %s (expected S_OK with %d and '%s'\n",
241 hr, len, buffer, lstrlenA(language), language);
244 memset(buffer, '#', maxlen);
246 hr = pGetAcceptLanguagesA( buffer, &len);
247 ok( (((hr == S_OK) || (hr == E_INVALIDARG)) && !memcmp(buffer, language, len)) ||
248 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len),
249 "=2: got 0x%x with %d and %s\n", hr, len, buffer);
252 memset(buffer, '#', maxlen);
254 hr = pGetAcceptLanguagesA( buffer, &len);
255 /* When the buffer is to small, win7_32 and w2k8_64 and above fail with
256 HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), other versions suceed
257 and return a partial 0 terminated result while other versions
258 fail with E_INVALIDARG and return a partial unterminated result */
259 ok( (((hr == S_OK) || (hr == E_INVALIDARG)) && !memcmp(buffer, language, len)) ||
260 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len),
261 "=1: got 0x%x with %d and %s\n", hr, len, buffer);
264 memset(buffer, '#', maxlen);
266 hr = pGetAcceptLanguagesA( buffer, &len);
267 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
268 ok((hr == E_FAIL) || (hr == E_INVALIDARG),
269 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr);
271 memset(buffer, '#', maxlen);
273 hr = pGetAcceptLanguagesA( buffer, NULL);
274 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
275 ok((hr == E_FAIL) || (hr == E_INVALIDARG),
276 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr);
279 hr = pGetAcceptLanguagesA( NULL, NULL);
280 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
281 ok((hr == E_FAIL) || (hr == E_INVALIDARG),
282 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr);
286 len = lstrlenA(original);
287 lres = RegSetValueExA(hroot, acceptlanguage, 0, REG_SZ, (const BYTE *) original, len ? len + 1: 0);
288 ok(!lres, "RegSetValueEx(%s) failed: %d\n", original, lres);
292 RegDeleteValue(hroot, acceptlanguage);
297 static void test_SHSearchMapInt(void)
299 int keys[8], values[8];
302 if (!pSHSearchMapInt)
305 memset(keys, 0, sizeof(keys));
306 memset(values, 0, sizeof(values));
307 keys[0] = 99; values[0] = 101;
309 /* NULL key/value lists crash native, so skip testing them */
312 i = pSHSearchMapInt(keys, values, 1, keys[0]);
313 ok(i == values[0], "Len 1, expected %d, got %d\n", values[0], i);
315 /* Key doesn't exist */
316 i = pSHSearchMapInt(keys, values, 1, 100);
317 ok(i == -1, "Len 1 - bad key, expected -1, got %d\n", i);
319 /* Len = 0 => not found */
320 i = pSHSearchMapInt(keys, values, 0, keys[0]);
321 ok(i == -1, "Len 1 - passed len 0, expected -1, got %d\n", i);
323 /* 2 elements, len = 1 */
324 keys[1] = 98; values[1] = 102;
325 i = pSHSearchMapInt(keys, values, 1, keys[1]);
326 ok(i == -1, "Len 1 - array len 2, expected -1, got %d\n", i);
328 /* 2 elements, len = 2 */
329 i = pSHSearchMapInt(keys, values, 2, keys[1]);
330 ok(i == values[1], "Len 2, expected %d, got %d\n", values[1], i);
332 /* Searches forward */
333 keys[2] = 99; values[2] = 103;
334 i = pSHSearchMapInt(keys, values, 3, keys[0]);
335 ok(i == values[0], "Len 3, expected %d, got %d\n", values[0], i);
338 static void test_alloc_shared(void)
346 procid=GetCurrentProcessId();
347 hmem=pSHAllocShared(NULL,10,procid);
348 ok(hmem!=NULL,"SHAllocShared(NULL...) failed: %u\n", GetLastError());
349 ret = pSHFreeShared(hmem, procid);
350 ok( ret, "SHFreeShared failed: %u\n", GetLastError());
353 hmem=pSHAllocShared(&val,4,procid);
354 ok(hmem!=NULL,"SHAllocShared(NULL...) failed: %u\n", GetLastError());
356 p=pSHLockShared(hmem,procid);
357 ok(p!=NULL,"SHLockShared failed: %u\n", GetLastError());
359 ok(*p==val,"Wrong value in shared memory: %d instead of %d\n",*p,val);
360 ret = pSHUnlockShared(p);
361 ok( ret, "SHUnlockShared failed: %u\n", GetLastError());
363 ret = pSHFreeShared(hmem, procid);
364 ok( ret, "SHFreeShared failed: %u\n", GetLastError());
367 static void test_fdsa(void)
371 DWORD num_items; /* Number of elements inserted */
372 void *mem; /* Ptr to array */
373 DWORD blocks_alloced; /* Number of elements allocated */
374 BYTE inc; /* Number of elements to grow by when we need to expand */
375 BYTE block_size; /* Size in bytes of an element */
376 BYTE flags; /* Flags */
379 BOOL (WINAPI *pFDSA_Initialize)(DWORD block_size, DWORD inc, FDSA_info *info, void *mem,
381 BOOL (WINAPI *pFDSA_Destroy)(FDSA_info *info);
382 DWORD (WINAPI *pFDSA_InsertItem)(FDSA_info *info, DWORD where, const void *block);
383 BOOL (WINAPI *pFDSA_DeleteItem)(FDSA_info *info, DWORD where);
386 int block_size = 10, init_blocks = 4, inc = 2;
390 pFDSA_Initialize = (void *)GetProcAddress(hShlwapi, (LPSTR)208);
391 pFDSA_Destroy = (void *)GetProcAddress(hShlwapi, (LPSTR)209);
392 pFDSA_InsertItem = (void *)GetProcAddress(hShlwapi, (LPSTR)210);
393 pFDSA_DeleteItem = (void *)GetProcAddress(hShlwapi, (LPSTR)211);
395 mem = HeapAlloc(GetProcessHeap(), 0, block_size * init_blocks);
396 memset(&info, 0, sizeof(info));
398 ok(pFDSA_Initialize(block_size, inc, &info, mem, init_blocks), "FDSA_Initialize rets FALSE\n");
399 ok(info.num_items == 0, "num_items = %d\n", info.num_items);
400 ok(info.mem == mem, "mem = %p\n", info.mem);
401 ok(info.blocks_alloced == init_blocks, "blocks_alloced = %d\n", info.blocks_alloced);
402 ok(info.inc == inc, "inc = %d\n", info.inc);
403 ok(info.block_size == block_size, "block_size = %d\n", info.block_size);
404 ok(info.flags == 0, "flags = %d\n", info.flags);
406 ret = pFDSA_InsertItem(&info, 1234, "1234567890");
407 ok(ret == 0, "ret = %d\n", ret);
408 ok(info.num_items == 1, "num_items = %d\n", info.num_items);
409 ok(info.mem == mem, "mem = %p\n", info.mem);
410 ok(info.blocks_alloced == init_blocks, "blocks_alloced = %d\n", info.blocks_alloced);
411 ok(info.inc == inc, "inc = %d\n", info.inc);
412 ok(info.block_size == block_size, "block_size = %d\n", info.block_size);
413 ok(info.flags == 0, "flags = %d\n", info.flags);
415 ret = pFDSA_InsertItem(&info, 1234, "abcdefghij");
416 ok(ret == 1, "ret = %d\n", ret);
418 ret = pFDSA_InsertItem(&info, 1, "klmnopqrst");
419 ok(ret == 1, "ret = %d\n", ret);
421 ret = pFDSA_InsertItem(&info, 0, "uvwxyzABCD");
422 ok(ret == 0, "ret = %d\n", ret);
423 ok(info.mem == mem, "mem = %p\n", info.mem);
424 ok(info.flags == 0, "flags = %d\n", info.flags);
426 /* This next InsertItem will cause shlwapi to allocate its own mem buffer */
427 ret = pFDSA_InsertItem(&info, 0, "EFGHIJKLMN");
428 ok(ret == 0, "ret = %d\n", ret);
429 ok(info.mem != mem, "mem = %p\n", info.mem);
430 ok(info.blocks_alloced == init_blocks + inc, "blocks_alloced = %d\n", info.blocks_alloced);
431 ok(info.flags == 0x1, "flags = %d\n", info.flags);
433 ok(!memcmp(info.mem, "EFGHIJKLMNuvwxyzABCD1234567890klmnopqrstabcdefghij", 50), "mem %s\n", (char*)info.mem);
435 ok(pFDSA_DeleteItem(&info, 2), "rets FALSE\n");
436 ok(info.mem != mem, "mem = %p\n", info.mem);
437 ok(info.blocks_alloced == init_blocks + inc, "blocks_alloced = %d\n", info.blocks_alloced);
438 ok(info.flags == 0x1, "flags = %d\n", info.flags);
440 ok(!memcmp(info.mem, "EFGHIJKLMNuvwxyzABCDklmnopqrstabcdefghij", 40), "mem %s\n", (char*)info.mem);
442 ok(pFDSA_DeleteItem(&info, 3), "rets FALSE\n");
443 ok(info.mem != mem, "mem = %p\n", info.mem);
444 ok(info.blocks_alloced == init_blocks + inc, "blocks_alloced = %d\n", info.blocks_alloced);
445 ok(info.flags == 0x1, "flags = %d\n", info.flags);
447 ok(!memcmp(info.mem, "EFGHIJKLMNuvwxyzABCDklmnopqrst", 30), "mem %s\n", (char*)info.mem);
449 ok(!pFDSA_DeleteItem(&info, 4), "does not ret FALSE\n");
451 /* As shlwapi has allocated memory internally, Destroy will ret FALSE */
452 ok(!pFDSA_Destroy(&info), "FDSA_Destroy does not ret FALSE\n");
455 /* When Initialize is called with inc = 0, set it to 1 */
456 ok(pFDSA_Initialize(block_size, 0, &info, mem, init_blocks), "FDSA_Initialize rets FALSE\n");
457 ok(info.inc == 1, "inc = %d\n", info.inc);
459 /* This time, because shlwapi hasn't had to allocate memory
460 internally, Destroy rets non-zero */
461 ok(pFDSA_Destroy(&info), "FDSA_Destroy rets FALSE\n");
464 HeapFree(GetProcessHeap(), 0, mem);
468 typedef struct SHELL_USER_SID {
469 SID_IDENTIFIER_AUTHORITY sidAuthority;
472 } SHELL_USER_SID, *PSHELL_USER_SID;
473 typedef struct SHELL_USER_PERMISSION {
474 SHELL_USER_SID susID;
479 DWORD dwInheritAccessMask;
480 } SHELL_USER_PERMISSION, *PSHELL_USER_PERMISSION;
481 static void test_GetShellSecurityDescriptor(void)
483 SHELL_USER_PERMISSION supCurrentUserFull = {
484 { {SECURITY_NULL_SID_AUTHORITY}, 0, 0 },
485 ACCESS_ALLOWED_ACE_TYPE, FALSE,
487 #define MY_INHERITANCE 0xBE /* invalid value to proof behavior */
488 SHELL_USER_PERMISSION supEveryoneDenied = {
489 { {SECURITY_WORLD_SID_AUTHORITY}, SECURITY_WORLD_RID, 0 },
490 ACCESS_DENIED_ACE_TYPE, TRUE,
491 GENERIC_WRITE, MY_INHERITANCE | 0xDEADBA00, GENERIC_READ };
492 PSHELL_USER_PERMISSION rgsup[2] = {
493 &supCurrentUserFull, &supEveryoneDenied,
495 SECURITY_DESCRIPTOR* psd;
496 SECURITY_DESCRIPTOR* (WINAPI*pGetShellSecurityDescriptor)(PSHELL_USER_PERMISSION*,int);
498 pGetShellSecurityDescriptor=(void*)GetProcAddress(hShlwapi,(char*)475);
500 if(!pGetShellSecurityDescriptor)
502 win_skip("GetShellSecurityDescriptor not available\n");
506 psd = pGetShellSecurityDescriptor(NULL, 2);
508 broken(psd==INVALID_HANDLE_VALUE), /* IE5 */
509 "GetShellSecurityDescriptor should fail\n");
510 psd = pGetShellSecurityDescriptor(rgsup, 0);
511 ok(psd==NULL, "GetShellSecurityDescriptor should fail\n");
513 SetLastError(0xdeadbeef);
514 psd = pGetShellSecurityDescriptor(rgsup, 2);
515 if (psd == NULL && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
517 /* The previous calls to GetShellSecurityDescriptor don't set the last error */
518 win_skip("GetShellSecurityDescriptor is not implemented\n");
521 if (psd==INVALID_HANDLE_VALUE)
523 win_skip("GetShellSecurityDescriptor is broken on IE5\n");
526 ok(psd!=NULL, "GetShellSecurityDescriptor failed\n");
529 BOOL bHasDacl = FALSE, bDefaulted;
532 SECURITY_DESCRIPTOR_CONTROL control;
534 ok(IsValidSecurityDescriptor(psd), "returned value is not valid SD\n");
536 ok(GetSecurityDescriptorControl(psd, &control, &dwRev),
537 "GetSecurityDescriptorControl failed with error %u\n", GetLastError());
538 ok(0 == (control & SE_SELF_RELATIVE), "SD should be absolute\n");
540 ok(GetSecurityDescriptorDacl(psd, &bHasDacl, &pAcl, &bDefaulted),
541 "GetSecurityDescriptorDacl failed with error %u\n", GetLastError());
543 ok(bHasDacl, "SD has no DACL\n");
546 ok(!bDefaulted, "DACL should not be defaulted\n");
548 ok(pAcl != NULL, "NULL DACL!\n");
551 ACL_SIZE_INFORMATION asiSize;
553 ok(IsValidAcl(pAcl), "DACL is not valid\n");
555 ok(GetAclInformation(pAcl, &asiSize, sizeof(asiSize), AclSizeInformation),
556 "GetAclInformation failed with error %u\n", GetLastError());
558 ok(asiSize.AceCount == 3, "Incorrect number of ACEs: %d entries\n", asiSize.AceCount);
559 if (asiSize.AceCount == 3)
561 ACCESS_ALLOWED_ACE *paaa; /* will use for DENIED too */
563 ok(GetAce(pAcl, 0, (LPVOID*)&paaa), "GetAce failed with error %u\n", GetLastError());
564 ok(paaa->Header.AceType == ACCESS_ALLOWED_ACE_TYPE,
565 "Invalid ACE type %d\n", paaa->Header.AceType);
566 ok(paaa->Header.AceFlags == 0, "Invalid ACE flags %x\n", paaa->Header.AceFlags);
567 ok(paaa->Mask == GENERIC_ALL, "Invalid ACE mask %x\n", paaa->Mask);
569 ok(GetAce(pAcl, 1, (LPVOID*)&paaa), "GetAce failed with error %u\n", GetLastError());
570 ok(paaa->Header.AceType == ACCESS_DENIED_ACE_TYPE,
571 "Invalid ACE type %d\n", paaa->Header.AceType);
572 /* first one of two ACEs generated from inheritable entry - without inheritance */
573 ok(paaa->Header.AceFlags == 0, "Invalid ACE flags %x\n", paaa->Header.AceFlags);
574 ok(paaa->Mask == GENERIC_WRITE, "Invalid ACE mask %x\n", paaa->Mask);
576 ok(GetAce(pAcl, 2, (LPVOID*)&paaa), "GetAce failed with error %u\n", GetLastError());
577 ok(paaa->Header.AceType == ACCESS_DENIED_ACE_TYPE,
578 "Invalid ACE type %d\n", paaa->Header.AceType);
579 /* second ACE - with inheritance */
580 ok(paaa->Header.AceFlags == MY_INHERITANCE,
581 "Invalid ACE flags %x\n", paaa->Header.AceFlags);
582 ok(paaa->Mask == GENERIC_READ, "Invalid ACE mask %x\n", paaa->Mask);
591 static void test_SHPackDispParams(void)
597 if(!pSHPackDispParams)
598 win_skip("SHPackSidpParams not available\n");
600 memset(¶ms, 0xc0, sizeof(params));
601 memset(vars, 0xc0, sizeof(vars));
602 hres = pSHPackDispParams(¶ms, vars, 1, VT_I4, 0xdeadbeef);
603 ok(hres == S_OK, "SHPackDispParams failed: %08x\n", hres);
604 ok(params.cArgs == 1, "params.cArgs = %d\n", params.cArgs);
605 ok(params.cNamedArgs == 0, "params.cNamedArgs = %d\n", params.cArgs);
606 ok(params.rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", params.rgdispidNamedArgs);
607 ok(params.rgvarg == vars, "params.rgvarg = %p\n", params.rgvarg);
608 ok(V_VT(vars) == VT_I4, "V_VT(var) = %d\n", V_VT(vars));
609 ok(V_I4(vars) == 0xdeadbeef, "failed %x\n", V_I4(vars));
611 memset(¶ms, 0xc0, sizeof(params));
612 hres = pSHPackDispParams(¶ms, NULL, 0, 0);
613 ok(hres == S_OK, "SHPackDispParams failed: %08x\n", hres);
614 ok(params.cArgs == 0, "params.cArgs = %d\n", params.cArgs);
615 ok(params.cNamedArgs == 0, "params.cNamedArgs = %d\n", params.cArgs);
616 ok(params.rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", params.rgdispidNamedArgs);
617 ok(params.rgvarg == NULL, "params.rgvarg = %p\n", params.rgvarg);
619 memset(vars, 0xc0, sizeof(vars));
620 memset(¶ms, 0xc0, sizeof(params));
621 hres = pSHPackDispParams(¶ms, vars, 4, VT_BSTR, (void*)0xdeadbeef, VT_EMPTY, 10,
622 VT_I4, 100, VT_DISPATCH, (void*)0xdeadbeef);
623 ok(hres == S_OK, "SHPackDispParams failed: %08x\n", hres);
624 ok(params.cArgs == 4, "params.cArgs = %d\n", params.cArgs);
625 ok(params.cNamedArgs == 0, "params.cNamedArgs = %d\n", params.cArgs);
626 ok(params.rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", params.rgdispidNamedArgs);
627 ok(params.rgvarg == vars, "params.rgvarg = %p\n", params.rgvarg);
628 ok(V_VT(vars) == VT_DISPATCH, "V_VT(vars[0]) = %x\n", V_VT(vars));
629 ok(V_I4(vars) == 0xdeadbeef, "V_I4(vars[0]) = %x\n", V_I4(vars));
630 ok(V_VT(vars+1) == VT_I4, "V_VT(vars[1]) = %d\n", V_VT(vars+1));
631 ok(V_I4(vars+1) == 100, "V_I4(vars[1]) = %x\n", V_I4(vars+1));
632 ok(V_VT(vars+2) == VT_I4, "V_VT(vars[2]) = %d\n", V_VT(vars+2));
633 ok(V_I4(vars+2) == 10, "V_I4(vars[2]) = %x\n", V_I4(vars+2));
634 ok(V_VT(vars+3) == VT_BSTR, "V_VT(vars[3]) = %d\n", V_VT(vars+3));
635 ok(V_BSTR(vars+3) == (void*)0xdeadbeef, "V_BSTR(vars[3]) = %p\n", V_BSTR(vars+3));
640 const IDispatchVtbl *vtbl;
644 typedef struct _contain
646 const IConnectionPointContainerVtbl *vtbl;
650 IConnectionPoint **pt;
653 typedef struct _cntptn
655 const IConnectionPointVtbl *vtbl;
666 const IEnumConnectionsVtbl *vtbl;
673 typedef struct _enumpt
675 const IEnumConnectionPointsVtbl *vtbl;
683 static HRESULT WINAPI Disp_QueryInterface(
690 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch))
697 IUnknown_AddRef(This);
701 trace("no interface\n");
702 return E_NOINTERFACE;
705 static ULONG WINAPI Disp_AddRef(IDispatch* This)
707 Disp *iface = (Disp*)This;
708 return InterlockedIncrement(&iface->refCount);
711 static ULONG WINAPI Disp_Release(IDispatch* This)
713 Disp *iface = (Disp*)This;
716 ret = InterlockedDecrement(&iface->refCount);
718 HeapFree(GetProcessHeap(),0,This);
722 static HRESULT WINAPI Disp_GetTypeInfoCount(
726 return ERROR_SUCCESS;
729 static HRESULT WINAPI Disp_GetTypeInfo(
735 return ERROR_SUCCESS;
738 static HRESULT WINAPI Disp_GetIDsOfNames(
746 return ERROR_SUCCESS;
749 static HRESULT WINAPI Disp_Invoke(
755 DISPPARAMS *pDispParams,
757 EXCEPINFO *pExcepInfo,
760 trace("%p %x %p %x %x %p %p %p %p\n",This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr);
762 ok(dispIdMember == 0xa0 || dispIdMember == 0xa1, "Unknown dispIdMember\n");
763 ok(pDispParams != NULL, "Invoked with NULL pDispParams\n");
764 ok(wFlags == DISPATCH_METHOD, "Wrong flags %x\n",wFlags);
765 ok(lcid == 0,"Wrong lcid %x\n",lcid);
766 if (dispIdMember == 0xa0)
768 ok(pDispParams->cArgs == 0, "params.cArgs = %d\n", pDispParams->cArgs);
769 ok(pDispParams->cNamedArgs == 0, "params.cNamedArgs = %d\n", pDispParams->cArgs);
770 ok(pDispParams->rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", pDispParams->rgdispidNamedArgs);
771 ok(pDispParams->rgvarg == NULL, "params.rgvarg = %p\n", pDispParams->rgvarg);
773 else if (dispIdMember == 0xa1)
775 ok(pDispParams->cArgs == 2, "params.cArgs = %d\n", pDispParams->cArgs);
776 ok(pDispParams->cNamedArgs == 0, "params.cNamedArgs = %d\n", pDispParams->cArgs);
777 ok(pDispParams->rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", pDispParams->rgdispidNamedArgs);
778 ok(V_VT(pDispParams->rgvarg) == VT_BSTR, "V_VT(var) = %d\n", V_VT(pDispParams->rgvarg));
779 ok(V_I4(pDispParams->rgvarg) == 0xdeadcafe , "failed %p\n", V_BSTR(pDispParams->rgvarg));
780 ok(V_VT(pDispParams->rgvarg+1) == VT_I4, "V_VT(var) = %d\n", V_VT(pDispParams->rgvarg+1));
781 ok(V_I4(pDispParams->rgvarg+1) == 0xdeadbeef, "failed %x\n", V_I4(pDispParams->rgvarg+1));
784 return ERROR_SUCCESS;
787 static const IDispatchVtbl disp_vtbl = {
792 Disp_GetTypeInfoCount,
798 static HRESULT WINAPI Enum_QueryInterface(
799 IEnumConnections* This,
805 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IEnumConnections))
812 IUnknown_AddRef(This);
816 trace("no interface\n");
817 return E_NOINTERFACE;
820 static ULONG WINAPI Enum_AddRef(IEnumConnections* This)
822 EnumCon *iface = (EnumCon*)This;
823 return InterlockedIncrement(&iface->refCount);
826 static ULONG WINAPI Enum_Release(IEnumConnections* This)
828 EnumCon *iface = (EnumCon*)This;
831 ret = InterlockedDecrement(&iface->refCount);
833 HeapFree(GetProcessHeap(),0,This);
837 static HRESULT WINAPI Enum_Next(
838 IEnumConnections* This,
843 EnumCon *iface = (EnumCon*)This;
845 if (cConnections > 0 && iface->idx < iface->pt->sinkCount)
847 rgcd->pUnk = iface->pt->sink[iface->idx];
848 IUnknown_AddRef(iface->pt->sink[iface->idx]);
859 static HRESULT WINAPI Enum_Skip(
860 IEnumConnections* This,
866 static HRESULT WINAPI Enum_Reset(
867 IEnumConnections* This)
872 static HRESULT WINAPI Enum_Clone(
873 IEnumConnections* This,
874 IEnumConnections **ppEnum)
879 static const IEnumConnectionsVtbl enum_vtbl = {
890 static HRESULT WINAPI ConPt_QueryInterface(
891 IConnectionPoint* This,
897 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IConnectionPoint))
904 IUnknown_AddRef(This);
908 trace("no interface\n");
909 return E_NOINTERFACE;
912 static ULONG WINAPI ConPt_AddRef(
913 IConnectionPoint* This)
915 ConPt *iface = (ConPt*)This;
916 return InterlockedIncrement(&iface->refCount);
919 static ULONG WINAPI ConPt_Release(
920 IConnectionPoint* This)
922 ConPt *iface = (ConPt*)This;
925 ret = InterlockedDecrement(&iface->refCount);
928 if (iface->sinkCount > 0)
931 for (i = 0; i < iface->sinkCount; i++)
934 IUnknown_Release(iface->sink[i]);
936 HeapFree(GetProcessHeap(),0,iface->sink);
938 HeapFree(GetProcessHeap(),0,This);
943 static HRESULT WINAPI ConPt_GetConnectionInterface(
944 IConnectionPoint* This,
948 ConPt *iface = (ConPt*)This;
955 memcpy(pIID,&iface->id,sizeof(GUID));
959 static HRESULT WINAPI ConPt_GetConnectionPointContainer(
960 IConnectionPoint* This,
961 IConnectionPointContainer **ppCPC)
963 ConPt *iface = (ConPt*)This;
965 *ppCPC = (IConnectionPointContainer*)iface->container;
969 static HRESULT WINAPI ConPt_Advise(
970 IConnectionPoint* This,
974 ConPt *iface = (ConPt*)This;
976 if (iface->sinkCount == 0)
977 iface->sink = HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown*));
979 iface->sink = HeapReAlloc(GetProcessHeap(),0,iface->sink,sizeof(IUnknown*)*(iface->sinkCount+1));
980 iface->sink[iface->sinkCount] = pUnkSink;
981 IUnknown_AddRef(pUnkSink);
983 *pdwCookie = iface->sinkCount;
987 static HRESULT WINAPI ConPt_Unadvise(
988 IConnectionPoint* This,
991 ConPt *iface = (ConPt*)This;
993 if (dwCookie > iface->sinkCount)
997 IUnknown_Release(iface->sink[dwCookie-1]);
998 iface->sink[dwCookie-1] = NULL;
1003 static HRESULT WINAPI ConPt_EnumConnections(
1004 IConnectionPoint* This,
1005 IEnumConnections **ppEnum)
1009 ec = HeapAlloc(GetProcessHeap(),0,sizeof(EnumCon));
1010 ec->vtbl = &enum_vtbl;
1012 ec->pt = (ConPt*)This;
1014 *ppEnum = (IEnumConnections*)ec;
1019 static const IConnectionPointVtbl point_vtbl = {
1020 ConPt_QueryInterface,
1024 ConPt_GetConnectionInterface,
1025 ConPt_GetConnectionPointContainer,
1028 ConPt_EnumConnections
1031 static HRESULT WINAPI EnumPt_QueryInterface(
1032 IEnumConnectionPoints* This,
1038 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IEnumConnectionPoints))
1045 IUnknown_AddRef(This);
1049 trace("no interface\n");
1050 return E_NOINTERFACE;
1053 static ULONG WINAPI EnumPt_AddRef(IEnumConnectionPoints* This)
1055 EnumPt *iface = (EnumPt*)This;
1056 return InterlockedIncrement(&iface->refCount);
1059 static ULONG WINAPI EnumPt_Release(IEnumConnectionPoints* This)
1061 EnumPt *iface = (EnumPt*)This;
1064 ret = InterlockedDecrement(&iface->refCount);
1066 HeapFree(GetProcessHeap(),0,This);
1070 static HRESULT WINAPI EnumPt_Next(
1071 IEnumConnectionPoints* This,
1073 IConnectionPoint **rgcd,
1076 EnumPt *iface = (EnumPt*)This;
1078 if (cConnections > 0 && iface->idx < iface->container->ptCount)
1080 *rgcd = iface->container->pt[iface->idx];
1081 IUnknown_AddRef(iface->container->pt[iface->idx]);
1091 static HRESULT WINAPI EnumPt_Skip(
1092 IEnumConnectionPoints* This,
1098 static HRESULT WINAPI EnumPt_Reset(
1099 IEnumConnectionPoints* This)
1104 static HRESULT WINAPI EnumPt_Clone(
1105 IEnumConnectionPoints* This,
1106 IEnumConnectionPoints **ppEnumPt)
1111 static const IEnumConnectionPointsVtbl enumpt_vtbl = {
1113 EnumPt_QueryInterface,
1122 static HRESULT WINAPI Contain_QueryInterface(
1123 IConnectionPointContainer* This,
1129 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IConnectionPointContainer))
1136 IUnknown_AddRef(This);
1140 trace("no interface\n");
1141 return E_NOINTERFACE;
1144 static ULONG WINAPI Contain_AddRef(
1145 IConnectionPointContainer* This)
1147 Contain *iface = (Contain*)This;
1148 return InterlockedIncrement(&iface->refCount);
1151 static ULONG WINAPI Contain_Release(
1152 IConnectionPointContainer* This)
1154 Contain *iface = (Contain*)This;
1157 ret = InterlockedDecrement(&iface->refCount);
1160 if (iface->ptCount > 0)
1163 for (i = 0; i < iface->ptCount; i++)
1164 IUnknown_Release(iface->pt[i]);
1165 HeapFree(GetProcessHeap(),0,iface->pt);
1167 HeapFree(GetProcessHeap(),0,This);
1172 static HRESULT WINAPI Contain_EnumConnectionPoints(
1173 IConnectionPointContainer* This,
1174 IEnumConnectionPoints **ppEnum)
1178 ec = HeapAlloc(GetProcessHeap(),0,sizeof(EnumPt));
1179 ec->vtbl = &enumpt_vtbl;
1182 ec->container = (Contain*)This;
1183 *ppEnum = (IEnumConnectionPoints*)ec;
1188 static HRESULT WINAPI Contain_FindConnectionPoint(
1189 IConnectionPointContainer* This,
1191 IConnectionPoint **ppCP)
1193 Contain *iface = (Contain*)This;
1196 if (!IsEqualIID(riid, &IID_NULL) || iface->ptCount ==0)
1198 pt = HeapAlloc(GetProcessHeap(),0,sizeof(ConPt));
1199 pt->vtbl = &point_vtbl;
1203 pt->container = iface;
1204 pt->id = IID_IDispatch;
1206 if (iface->ptCount == 0)
1207 iface->pt =HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown*));
1209 iface->pt = HeapReAlloc(GetProcessHeap(),0,iface->pt,sizeof(IUnknown*)*(iface->ptCount+1));
1210 iface->pt[iface->ptCount] = (IConnectionPoint*)pt;
1213 *ppCP = (IConnectionPoint*)pt;
1217 *ppCP = iface->pt[0];
1218 IUnknown_AddRef((IUnknown*)*ppCP);
1224 static const IConnectionPointContainerVtbl contain_vtbl = {
1225 Contain_QueryInterface,
1229 Contain_EnumConnectionPoints,
1230 Contain_FindConnectionPoint
1233 static void test_IConnectionPoint(void)
1237 IConnectionPoint *point;
1240 DWORD cookie = 0xffffffff;
1244 if (!pIConnectionPoint_SimpleInvoke || !pConnectToConnectionPoint)
1246 win_skip("IConnectionPoint Apis not present\n");
1250 container = HeapAlloc(GetProcessHeap(),0,sizeof(Contain));
1251 container->vtbl = &contain_vtbl;
1252 container->refCount = 1;
1253 container->ptCount = 0;
1254 container->pt = NULL;
1256 dispatch = HeapAlloc(GetProcessHeap(),0,sizeof(Disp));
1257 dispatch->vtbl = &disp_vtbl;
1258 dispatch->refCount = 1;
1260 rc = pConnectToConnectionPoint((IUnknown*)dispatch, &IID_NULL, TRUE, (IUnknown*)container, &cookie, &point);
1261 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
1262 ok(point != NULL, "returned ConnectionPoint is NULL\n");
1263 ok(cookie != 0xffffffff, "invalid cookie returned\n");
1265 rc = pIConnectionPoint_SimpleInvoke(point,0xa0,NULL);
1266 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
1268 if (pSHPackDispParams)
1270 memset(¶ms, 0xc0, sizeof(params));
1271 memset(vars, 0xc0, sizeof(vars));
1272 rc = pSHPackDispParams(¶ms, vars, 2, VT_I4, 0xdeadbeef, VT_BSTR, 0xdeadcafe);
1273 ok(rc == S_OK, "SHPackDispParams failed: %08x\n", rc);
1275 rc = pIConnectionPoint_SimpleInvoke(point,0xa1,¶ms);
1276 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
1279 win_skip("pSHPackDispParams not present\n");
1281 rc = pConnectToConnectionPoint(NULL, &IID_NULL, FALSE, (IUnknown*)container, &cookie, NULL);
1282 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
1284 /* MSDN says this should be required but it crashs on XP
1285 IUnknown_Release(point);
1287 ref = IUnknown_Release((IUnknown*)container);
1288 ok(ref == 0, "leftover IConnectionPointContainer reference %i\n",ref);
1289 ref = IUnknown_Release((IUnknown*)dispatch);
1290 ok(ref == 0, "leftover IDispatch reference %i\n",ref);
1293 typedef struct _propbag
1295 const IPropertyBagVtbl *vtbl;
1301 static HRESULT WINAPI Prop_QueryInterface(
1308 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IPropertyBag))
1315 IUnknown_AddRef(This);
1319 trace("no interface\n");
1320 return E_NOINTERFACE;
1323 static ULONG WINAPI Prop_AddRef(
1326 PropBag *iface = (PropBag*)This;
1327 return InterlockedIncrement(&iface->refCount);
1330 static ULONG WINAPI Prop_Release(
1333 PropBag *iface = (PropBag*)This;
1336 ret = InterlockedDecrement(&iface->refCount);
1338 HeapFree(GetProcessHeap(),0,This);
1342 static HRESULT WINAPI Prop_Read(
1344 LPCOLESTR pszPropName,
1346 IErrorLog *pErrorLog)
1348 V_VT(pVar) = VT_BLOB|VT_BYREF;
1349 V_BYREF(pVar) = (LPVOID)0xdeadcafe;
1353 static HRESULT WINAPI Prop_Write(
1355 LPCOLESTR pszPropName,
1362 static const IPropertyBagVtbl prop_vtbl = {
1363 Prop_QueryInterface,
1371 static void test_SHPropertyBag_ReadLONG(void)
1376 static const WCHAR szName1[] = {'n','a','m','e','1',0};
1378 if (!pSHPropertyBag_ReadLONG)
1380 win_skip("SHPropertyBag_ReadLONG not present\n");
1384 pb = HeapAlloc(GetProcessHeap(),0,sizeof(PropBag));
1386 pb->vtbl = &prop_vtbl;
1389 rc = pSHPropertyBag_ReadLONG(NULL, szName1, &out);
1390 ok(rc == E_INVALIDARG || broken(rc == 0), "incorrect return %x\n",rc);
1391 ok(out == 0xfeedface, "value should not have changed\n");
1392 rc = pSHPropertyBag_ReadLONG((IPropertyBag*)pb, NULL, &out);
1393 ok(rc == E_INVALIDARG || broken(rc == 0) || broken(rc == 1), "incorrect return %x\n",rc);
1394 ok(out == 0xfeedface, "value should not have changed\n");
1395 rc = pSHPropertyBag_ReadLONG((IPropertyBag*)pb, szName1, NULL);
1396 ok(rc == E_INVALIDARG || broken(rc == 0) || broken(rc == 1), "incorrect return %x\n",rc);
1397 ok(out == 0xfeedface, "value should not have changed\n");
1398 rc = pSHPropertyBag_ReadLONG((IPropertyBag*)pb, szName1, &out);
1399 ok(rc == DISP_E_BADVARTYPE || broken(rc == 0) || broken(rc == 1), "incorrect return %x\n",rc);
1400 ok(out == 0xfeedface || broken(out == 0xfeedfa00), "value should not have changed %x\n",out);
1401 IUnknown_Release((IUnknown*)pb);
1406 static void test_SHSetWindowBits(void)
1409 DWORD style, styleold;
1412 if(!pSHSetWindowBits)
1414 win_skip("SHSetWindowBits is not available\n");
1419 clsA.lpfnWndProc = DefWindowProcA;
1420 clsA.cbClsExtra = 0;
1421 clsA.cbWndExtra = 0;
1422 clsA.hInstance = GetModuleHandleA(NULL);
1424 clsA.hCursor = LoadCursorA(0, IDC_ARROW);
1425 clsA.hbrBackground = NULL;
1426 clsA.lpszMenuName = NULL;
1427 clsA.lpszClassName = "Shlwapi test class";
1428 RegisterClassA(&clsA);
1430 hwnd = CreateWindowA("Shlwapi test class", "Test", WS_VISIBLE, 0, 0, 100, 100,
1431 NULL, NULL, GetModuleHandle(NULL), 0);
1432 ok(IsWindow(hwnd), "failed to create window\n");
1435 SetLastError(0xdeadbeef);
1436 style = pSHSetWindowBits(NULL, GWL_STYLE, 0, 0);
1437 ok(style == 0, "expected 0 retval, got %d\n", style);
1438 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE,
1439 "expected ERROR_INVALID_WINDOW_HANDLE, got %d\n", GetLastError());
1441 /* zero mask, zero flags */
1442 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1443 style = pSHSetWindowBits(hwnd, GWL_STYLE, 0, 0);
1444 ok(styleold == style, "expected old style\n");
1445 ok(styleold == GetWindowLongA(hwnd, GWL_STYLE), "expected to keep old style\n");
1448 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1449 ok(styleold & WS_VISIBLE, "expected WS_VISIBLE\n");
1450 style = pSHSetWindowBits(hwnd, GWL_STYLE, WS_VISIBLE, 0);
1452 ok(style == styleold, "expected previous style, got %x\n", style);
1453 ok((GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE) == 0, "expected updated style\n");
1455 /* test mask, unset style bit used */
1456 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1457 style = pSHSetWindowBits(hwnd, GWL_STYLE, WS_VISIBLE, 0);
1458 ok(style == styleold, "expected previous style, got %x\n", style);
1459 ok(styleold == GetWindowLongA(hwnd, GWL_STYLE), "expected to keep old style\n");
1461 /* set back with flags */
1462 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1463 style = pSHSetWindowBits(hwnd, GWL_STYLE, WS_VISIBLE, WS_VISIBLE);
1464 ok(style == styleold, "expected previous style, got %x\n", style);
1465 ok(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE, "expected updated style\n");
1467 /* reset and try to set without a mask */
1468 pSHSetWindowBits(hwnd, GWL_STYLE, WS_VISIBLE, 0);
1469 ok((GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE) == 0, "expected updated style\n");
1470 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1471 style = pSHSetWindowBits(hwnd, GWL_STYLE, 0, WS_VISIBLE);
1472 ok(style == styleold, "expected previous style, got %x\n", style);
1473 ok((GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE) == 0, "expected updated style\n");
1475 DestroyWindow(hwnd);
1477 UnregisterClassA("Shlwapi test class", GetModuleHandleA(NULL));
1480 static void test_SHFormatDateTimeA(void)
1482 FILETIME UNALIGNED filetime;
1483 CHAR buff[100], buff2[100], buff3[100];
1488 if(!pSHFormatDateTimeA)
1490 win_skip("pSHFormatDateTimeA isn't available\n");
1496 /* crashes on native */
1497 ret = pSHFormatDateTimeA(NULL, NULL, NULL, 0);
1501 SystemTimeToFileTime(&st, &filetime);
1502 /* SHFormatDateTime expects input as utc */
1503 LocalFileTimeToFileTime(&filetime, &filetime);
1505 /* no way to get required buffer length here */
1506 SetLastError(0xdeadbeef);
1507 ret = pSHFormatDateTimeA(&filetime, NULL, NULL, 0);
1508 ok(ret == 0, "got %d\n", ret);
1509 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1511 SetLastError(0xdeadbeef);
1512 buff[0] = 'a'; buff[1] = 0;
1513 ret = pSHFormatDateTimeA(&filetime, NULL, buff, 0);
1514 ok(ret == 0, "got %d\n", ret);
1515 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1516 ok(buff[0] == 'a', "expected same string, got %s\n", buff);
1518 /* all combinations documented as invalid succeeded */
1519 flags = FDTF_SHORTTIME | FDTF_LONGTIME;
1520 SetLastError(0xdeadbeef);
1521 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1522 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1523 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1525 flags = FDTF_SHORTDATE | FDTF_LONGDATE;
1526 SetLastError(0xdeadbeef);
1527 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1528 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1529 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1531 flags = FDTF_SHORTDATE | FDTF_LTRDATE | FDTF_RTLDATE;
1532 SetLastError(0xdeadbeef);
1533 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1534 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1535 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1537 /* now check returned strings */
1538 flags = FDTF_SHORTTIME;
1539 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1540 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1541 ret = GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff2, sizeof(buff2));
1542 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1543 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1545 flags = FDTF_LONGTIME;
1546 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1547 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1548 ret = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2));
1549 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1550 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1552 /* both time flags */
1553 flags = FDTF_LONGTIME | FDTF_SHORTTIME;
1554 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1555 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1556 ret = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2));
1557 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1558 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1560 flags = FDTF_SHORTDATE;
1561 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1562 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1563 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2));
1564 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1565 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1567 flags = FDTF_LONGDATE;
1568 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1569 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1570 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
1571 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1572 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1574 /* both date flags */
1575 flags = FDTF_LONGDATE | FDTF_SHORTDATE;
1576 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1577 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1578 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
1579 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1580 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1582 /* various combinations of date/time flags */
1583 flags = FDTF_LONGDATE | FDTF_SHORTTIME;
1584 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1585 ok(ret == lstrlenA(buff)+1, "got %d, length %d\n", ret, lstrlenA(buff)+1);
1586 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
1587 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1588 strcat(buff2, ", ");
1589 ret = GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3));
1590 ok(ret == lstrlenA(buff3)+1, "got %d\n", ret);
1591 strcat(buff2, buff3);
1592 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1594 flags = FDTF_LONGDATE | FDTF_LONGTIME;
1595 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1596 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1597 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
1598 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1599 strcat(buff2, ", ");
1600 ret = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3));
1601 ok(ret == lstrlenA(buff3)+1, "got %d\n", ret);
1602 strcat(buff2, buff3);
1603 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1605 flags = FDTF_SHORTDATE | FDTF_SHORTTIME;
1606 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1607 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1608 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2));
1609 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1611 ret = GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3));
1612 ok(ret == lstrlenA(buff3)+1, "got %d\n", ret);
1613 strcat(buff2, buff3);
1614 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1616 flags = FDTF_SHORTDATE | FDTF_LONGTIME;
1617 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1618 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1619 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2));
1620 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1622 ret = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3));
1623 ok(ret == lstrlenA(buff3)+1, "got %d\n", ret);
1624 strcat(buff2, buff3);
1625 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1628 static void test_SHFormatDateTimeW(void)
1630 FILETIME UNALIGNED filetime;
1631 WCHAR buff[100], buff2[100], buff3[100];
1635 static const WCHAR spaceW[] = {' ',0};
1636 static const WCHAR commaW[] = {',',' ',0};
1638 if(!pSHFormatDateTimeW)
1640 win_skip("pSHFormatDateTimeW isn't available\n");
1646 /* crashes on native */
1647 ret = pSHFormatDateTimeW(NULL, NULL, NULL, 0);
1651 SystemTimeToFileTime(&st, &filetime);
1652 /* SHFormatDateTime expects input as utc */
1653 LocalFileTimeToFileTime(&filetime, &filetime);
1655 /* no way to get required buffer length here */
1656 SetLastError(0xdeadbeef);
1657 ret = pSHFormatDateTimeW(&filetime, NULL, NULL, 0);
1658 ok(ret == 0, "got %d\n", ret);
1659 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1661 SetLastError(0xdeadbeef);
1662 buff[0] = 'a'; buff[1] = 0;
1663 ret = pSHFormatDateTimeW(&filetime, NULL, buff, 0);
1664 ok(ret == 0, "got %d\n", ret);
1665 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1666 ok(buff[0] == 'a', "expected same string\n");
1668 /* all combinations documented as invalid succeeded */
1669 flags = FDTF_SHORTTIME | FDTF_LONGTIME;
1670 SetLastError(0xdeadbeef);
1671 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1672 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1673 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1675 flags = FDTF_SHORTDATE | FDTF_LONGDATE;
1676 SetLastError(0xdeadbeef);
1677 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1678 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1679 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1681 flags = FDTF_SHORTDATE | FDTF_LTRDATE | FDTF_RTLDATE;
1682 SetLastError(0xdeadbeef);
1683 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1684 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1685 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1687 /* now check returned strings */
1688 flags = FDTF_SHORTTIME;
1689 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1690 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1691 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1692 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1693 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1695 flags = FDTF_LONGTIME;
1696 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1697 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1698 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1699 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1700 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1702 /* both time flags */
1703 flags = FDTF_LONGTIME | FDTF_SHORTTIME;
1704 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1705 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1706 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1707 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1708 ok(lstrcmpW(buff, buff2) == 0, "expected equal string\n");
1710 flags = FDTF_SHORTDATE;
1711 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1712 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1713 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1714 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1715 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1717 flags = FDTF_LONGDATE;
1718 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1719 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1720 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1721 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1722 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1724 /* both date flags */
1725 flags = FDTF_LONGDATE | FDTF_SHORTDATE;
1726 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1727 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1728 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1729 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1730 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1732 /* various combinations of date/time flags */
1733 flags = FDTF_LONGDATE | FDTF_SHORTTIME;
1734 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1735 ok(ret == lstrlenW(buff)+1, "got %d, length %d\n", ret, lstrlenW(buff)+1);
1736 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1737 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1738 lstrcatW(buff2, commaW);
1739 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
1740 ok(ret == lstrlenW(buff3)+1, "got %d\n", ret);
1741 lstrcatW(buff2, buff3);
1742 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1744 flags = FDTF_LONGDATE | FDTF_LONGTIME;
1745 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1746 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1747 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1748 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1749 lstrcatW(buff2, commaW);
1750 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
1751 ok(ret == lstrlenW(buff3)+1, "got %d\n", ret);
1752 lstrcatW(buff2, buff3);
1753 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1755 flags = FDTF_SHORTDATE | FDTF_SHORTTIME;
1756 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1757 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1758 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1759 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1760 lstrcatW(buff2, spaceW);
1761 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
1762 ok(ret == lstrlenW(buff3)+1, "got %d\n", ret);
1763 lstrcatW(buff2, buff3);
1764 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1766 flags = FDTF_SHORTDATE | FDTF_LONGTIME;
1767 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1768 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1769 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1770 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1771 lstrcatW(buff2, spaceW);
1772 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
1773 ok(ret == lstrlenW(buff3)+1, "got %d\n", ret);
1774 lstrcatW(buff2, buff3);
1775 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1778 static void init_pointers(void)
1780 #define MAKEFUNC(f, ord) (p##f = (void*)GetProcAddress(hShlwapi, (LPSTR)(ord)))
1781 MAKEFUNC(SHAllocShared, 7);
1782 MAKEFUNC(SHLockShared, 8);
1783 MAKEFUNC(SHUnlockShared, 9);
1784 MAKEFUNC(SHFreeShared, 10);
1785 MAKEFUNC(GetAcceptLanguagesA, 14);
1786 MAKEFUNC(SHSetWindowBits, 165);
1787 MAKEFUNC(ConnectToConnectionPoint, 168);
1788 MAKEFUNC(SHSearchMapInt, 198);
1789 MAKEFUNC(SHPackDispParams, 282);
1790 MAKEFUNC(IConnectionPoint_InvokeWithCancel, 283);
1791 MAKEFUNC(IConnectionPoint_SimpleInvoke, 284);
1792 MAKEFUNC(SHFormatDateTimeA, 353);
1793 MAKEFUNC(SHFormatDateTimeW, 354);
1794 MAKEFUNC(SHPropertyBag_ReadLONG, 496);
1800 hShlwapi = GetModuleHandleA("shlwapi.dll");
1804 hmlang = LoadLibraryA("mlang.dll");
1805 pLcidToRfc1766A = (void *)GetProcAddress(hmlang, "LcidToRfc1766A");
1807 test_GetAcceptLanguagesA();
1808 test_SHSearchMapInt();
1809 test_alloc_shared();
1811 test_GetShellSecurityDescriptor();
1812 test_SHPackDispParams();
1813 test_IConnectionPoint();
1814 test_SHPropertyBag_ReadLONG();
1815 test_SHSetWindowBits();
1816 test_SHFormatDateTimeA();
1817 test_SHFormatDateTimeW();