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
24 #include "wine/test.h"
37 /* Function ptrs for ordinal calls */
38 static HMODULE hShlwapi;
39 static BOOL is_win2k_and_lower;
42 static int (WINAPI *pSHSearchMapInt)(const int*,const int*,int,int);
43 static HRESULT (WINAPI *pGetAcceptLanguagesA)(LPSTR,LPDWORD);
45 static HANDLE (WINAPI *pSHAllocShared)(LPCVOID,DWORD,DWORD);
46 static LPVOID (WINAPI *pSHLockShared)(HANDLE,DWORD);
47 static BOOL (WINAPI *pSHUnlockShared)(LPVOID);
48 static BOOL (WINAPI *pSHFreeShared)(HANDLE,DWORD);
49 static HRESULT(WINAPIV *pSHPackDispParams)(DISPPARAMS*,VARIANTARG*,UINT,...);
50 static HRESULT(WINAPI *pIConnectionPoint_SimpleInvoke)(IConnectionPoint*,DISPID,DISPPARAMS*);
51 static HRESULT(WINAPI *pIConnectionPoint_InvokeWithCancel)(IConnectionPoint*,DISPID,DISPPARAMS*,DWORD,DWORD);
52 static HRESULT(WINAPI *pConnectToConnectionPoint)(IUnknown*,REFIID,BOOL,IUnknown*, LPDWORD,IConnectionPoint **);
53 static HRESULT(WINAPI *pSHPropertyBag_ReadLONG)(IPropertyBag *,LPCWSTR,LPLONG);
54 static LONG (WINAPI *pSHSetWindowBits)(HWND, INT, UINT, UINT);
55 static INT (WINAPI *pSHFormatDateTimeA)(const FILETIME UNALIGNED*, DWORD*, LPSTR, UINT);
56 static INT (WINAPI *pSHFormatDateTimeW)(const FILETIME UNALIGNED*, DWORD*, LPWSTR, UINT);
57 static DWORD (WINAPI *pSHGetObjectCompatFlags)(IUnknown*, const CLSID*);
58 static BOOL (WINAPI *pGUIDFromStringA)(LPSTR, CLSID *);
59 static HRESULT (WINAPI *pIUnknown_QueryServiceExec)(IUnknown*, REFIID, const GUID*, DWORD, DWORD, VARIANT*, VARIANT*);
60 static HRESULT (WINAPI *pIUnknown_ProfferService)(IUnknown*, REFGUID, IServiceProvider*, DWORD*);
61 static HWND (WINAPI *pSHCreateWorkerWindowA)(LONG, HWND, DWORD, DWORD, HMENU, LONG_PTR);
62 static HRESULT (WINAPI *pSHIShellFolder_EnumObjects)(LPSHELLFOLDER, HWND, SHCONTF, IEnumIDList**);
63 static DWORD (WINAPI *pSHGetIniStringW)(LPCWSTR, LPCWSTR, LPWSTR, DWORD, LPCWSTR);
64 static BOOL (WINAPI *pSHSetIniStringW)(LPCWSTR, LPCWSTR, LPCWSTR, LPCWSTR);
65 static HKEY (WINAPI *pSHGetShellKey)(DWORD, LPCWSTR, BOOL);
66 static HRESULT (WINAPI *pSKGetValueW)(DWORD, LPCWSTR, LPCWSTR, DWORD*, void*, DWORD*);
67 static HRESULT (WINAPI *pSKSetValueW)(DWORD, LPCWSTR, LPCWSTR, DWORD, void*, DWORD);
68 static HRESULT (WINAPI *pSKDeleteValueW)(DWORD, LPCWSTR, LPCWSTR);
69 static HRESULT (WINAPI *pSKAllocValueW)(DWORD, LPCWSTR, LPCWSTR, DWORD*, void**, DWORD*);
70 static HWND (WINAPI *pSHSetParentHwnd)(HWND, HWND);
72 static HMODULE hmlang;
73 static HRESULT (WINAPI *pLcidToRfc1766A)(LCID, LPSTR, INT);
75 static HMODULE hshell32;
76 static HRESULT (WINAPI *pSHGetDesktopFolder)(IShellFolder**);
78 static const CHAR ie_international[] = {
79 'S','o','f','t','w','a','r','e','\\',
80 'M','i','c','r','o','s','o','f','t','\\',
81 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
82 'I','n','t','e','r','n','a','t','i','o','n','a','l',0};
83 static const CHAR acceptlanguage[] = {
84 'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0};
86 static int strcmp_wa(LPCWSTR strw, const char *stra)
89 WideCharToMultiByte(CP_ACP, 0, strw, -1, buf, sizeof(buf), NULL, NULL);
90 return lstrcmpA(stra, buf);
104 static void init_call_trace(call_trace_t *ctrace)
108 ctrace->calls = HeapAlloc(GetProcessHeap(), 0, sizeof(call_entry_t) * ctrace->alloc);
111 static void free_call_trace(const call_trace_t *ctrace)
113 HeapFree(GetProcessHeap(), 0, ctrace->calls);
116 static void add_call(call_trace_t *ctrace, int id, const void *arg0,
117 const void *arg1, const void *arg2, const void *arg3, const void *arg4)
128 if (ctrace->count == ctrace->alloc)
131 ctrace->calls = HeapReAlloc(GetProcessHeap(),0, ctrace->calls, ctrace->alloc*sizeof(call_entry_t));
134 ctrace->calls[ctrace->count++] = call;
137 static void ok_trace_(call_trace_t *texpected, call_trace_t *tgot, int line)
139 if (texpected->count == tgot->count)
143 for (i = 0; i < texpected->count; i++)
145 call_entry_t *expected = &texpected->calls[i];
146 call_entry_t *got = &tgot->calls[i];
149 ok_(__FILE__, line)(expected->id == got->id, "got different ids %d: %d, %d\n", i+1, expected->id, got->id);
151 for (j = 0; j < 5; j++)
153 ok_(__FILE__, line)(expected->args[j] == got->args[j], "got different args[%d] for %d: %p, %p\n", j, i+1,
154 expected->args[j], got->args[j]);
159 ok_(__FILE__, line)(0, "traces length mismatch\n");
162 #define ok_trace(a, b) ok_trace_(a, b, __LINE__)
164 /* trace of actually made calls */
165 static call_trace_t trace_got;
167 static void test_GetAcceptLanguagesA(void)
169 static LPCSTR table[] = {"de,en-gb;q=0.7,en;q=0.3",
170 "de,en;q=0.3,en-gb;q=0.7", /* sorting is ignored */
171 "winetest", /* content is ignored */
181 LONG res_query = ERROR_SUCCESS;
184 DWORD maxlen = sizeof(buffer) - 2;
190 if (!pGetAcceptLanguagesA) {
191 win_skip("GetAcceptLanguagesA is not available\n");
195 lcid = GetUserDefaultLCID();
197 /* Get the original Value */
198 lres = RegOpenKeyA(HKEY_CURRENT_USER, ie_international, &hroot);
200 skip("RegOpenKey(%s) failed: %d\n", ie_international, lres);
203 len = sizeof(original);
205 res_query = RegQueryValueExA(hroot, acceptlanguage, 0, NULL, (PBYTE)original, &len);
207 RegDeleteValue(hroot, acceptlanguage);
209 /* Some windows versions use "lang-COUNTRY" as default */
210 memset(language, 0, sizeof(language));
211 len = GetLocaleInfoA(lcid, LOCALE_SISO639LANGNAME, language, sizeof(language));
214 lstrcat(language, "-");
215 memset(buffer, 0, sizeof(buffer));
216 len = GetLocaleInfoA(lcid, LOCALE_SISO3166CTRYNAME, buffer, sizeof(buffer) - len - 1);
217 lstrcat(language, buffer);
221 /* LOCALE_SNAME has additional parts in some languages. Try only as last chance */
222 memset(language, 0, sizeof(language));
223 len = GetLocaleInfoA(lcid, LOCALE_SNAME, language, sizeof(language));
226 /* get the default value */
228 memset(buffer, '#', maxlen);
230 hr = pGetAcceptLanguagesA( buffer, &len);
233 win_skip("GetAcceptLanguagesA failed with 0x%x\n", hr);
234 goto restore_original;
237 if (lstrcmpA(buffer, language)) {
238 /* some windows versions use "lang" or "lang-country" as default */
240 if (pLcidToRfc1766A) {
241 hr = pLcidToRfc1766A(lcid, language, sizeof(language));
242 ok(hr == S_OK, "LcidToRfc1766A returned 0x%x and %s\n", hr, language);
246 ok(!lstrcmpA(buffer, language),
247 "have '%s' (searching for '%s')\n", language, buffer);
249 if (lstrcmpA(buffer, language)) {
250 win_skip("no more ideas, how to build the default language '%s'\n", buffer);
251 goto restore_original;
254 trace("detected default: %s\n", language);
255 while ((entry = table[i])) {
257 exactsize = lstrlenA(entry);
259 lres = RegSetValueExA(hroot, acceptlanguage, 0, REG_SZ, (const BYTE *) entry, exactsize + 1);
260 ok(!lres, "got %d for RegSetValueExA: %s\n", lres, entry);
262 /* len includes space for the terminating 0 before vista/w2k8 */
264 memset(buffer, '#', maxlen);
266 hr = pGetAcceptLanguagesA( buffer, &len);
267 ok(((hr == E_INVALIDARG) && (len == 0)) ||
269 ((len == exactsize) || (len == exactsize+1)) &&
270 !lstrcmpA(buffer, entry)),
271 "+2_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
274 memset(buffer, '#', maxlen);
276 hr = pGetAcceptLanguagesA( buffer, &len);
277 ok(((hr == E_INVALIDARG) && (len == 0)) ||
279 ((len == exactsize) || (len == exactsize+1)) &&
280 !lstrcmpA(buffer, entry)),
281 "+1_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
284 memset(buffer, '#', maxlen);
286 hr = pGetAcceptLanguagesA( buffer, &len);
288 /* There is no space for the string in the registry.
289 When the buffer is large enough, the default language is returned
291 When the buffer is too small for that fallback, win7_32 and w2k8_64
292 and above fail with HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), but
293 recent os succeed and return a partial result while
294 older os succeed and overflow the buffer */
296 ok(((hr == E_INVALIDARG) && (len == 0)) ||
297 (((hr == S_OK) && !lstrcmpA(buffer, language) && (len == lstrlenA(language))) ||
298 ((hr == S_OK) && !memcmp(buffer, language, len)) ||
299 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len)),
300 "==_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
304 memset(buffer, '#', maxlen);
306 hr = pGetAcceptLanguagesA( buffer, &len);
307 ok(((hr == E_INVALIDARG) && (len == 0)) ||
308 (((hr == S_OK) && !lstrcmpA(buffer, language) && (len == lstrlenA(language))) ||
309 ((hr == S_OK) && !memcmp(buffer, language, len)) ||
310 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len)),
311 "-1_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
315 memset(buffer, '#', maxlen);
317 hr = pGetAcceptLanguagesA( buffer, &len);
318 ok(((hr == E_INVALIDARG) && (len == 0)) ||
319 (((hr == S_OK) && !lstrcmpA(buffer, language) && (len == lstrlenA(language))) ||
320 ((hr == S_OK) && !memcmp(buffer, language, len)) ||
321 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len)),
322 "=1_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
325 hr = pGetAcceptLanguagesA( NULL, &len);
327 /* w2k3 and below: E_FAIL and untouched len,
328 since w2k8: S_OK and needed size (excluding 0) */
329 ok( ((hr == S_OK) && (len == exactsize)) ||
330 ((hr == E_FAIL) && (len == maxlen)),
331 "NULL,max #%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
336 /* without a value in the registry, a default language is returned */
337 RegDeleteValue(hroot, acceptlanguage);
340 memset(buffer, '#', maxlen);
342 hr = pGetAcceptLanguagesA( buffer, &len);
343 ok( ((hr == S_OK) && (len == lstrlenA(language))),
344 "max: got 0x%x with %d and %s (expected S_OK with %d and '%s'\n",
345 hr, len, buffer, lstrlenA(language), language);
348 memset(buffer, '#', maxlen);
350 hr = pGetAcceptLanguagesA( buffer, &len);
351 ok( (((hr == S_OK) || (hr == E_INVALIDARG)) && !memcmp(buffer, language, len)) ||
352 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len),
353 "=2: got 0x%x with %d and %s\n", hr, len, buffer);
356 memset(buffer, '#', maxlen);
358 hr = pGetAcceptLanguagesA( buffer, &len);
359 /* When the buffer is too small, win7_32 and w2k8_64 and above fail with
360 HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), other versions succeed
361 and return a partial 0 terminated result while other versions
362 fail with E_INVALIDARG and return a partial unterminated result */
363 ok( (((hr == S_OK) || (hr == E_INVALIDARG)) && !memcmp(buffer, language, len)) ||
364 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len),
365 "=1: got 0x%x with %d and %s\n", hr, len, buffer);
368 memset(buffer, '#', maxlen);
370 hr = pGetAcceptLanguagesA( buffer, &len);
371 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
372 ok((hr == E_FAIL) || (hr == E_INVALIDARG),
373 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr);
375 memset(buffer, '#', maxlen);
377 hr = pGetAcceptLanguagesA( buffer, NULL);
378 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
379 ok((hr == E_FAIL) || (hr == E_INVALIDARG),
380 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr);
383 hr = pGetAcceptLanguagesA( NULL, NULL);
384 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
385 ok((hr == E_FAIL) || (hr == E_INVALIDARG),
386 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr);
390 len = lstrlenA(original);
391 lres = RegSetValueExA(hroot, acceptlanguage, 0, REG_SZ, (const BYTE *) original, len ? len + 1: 0);
392 ok(!lres, "RegSetValueEx(%s) failed: %d\n", original, lres);
396 RegDeleteValue(hroot, acceptlanguage);
401 static void test_SHSearchMapInt(void)
403 int keys[8], values[8];
406 if (!pSHSearchMapInt)
409 memset(keys, 0, sizeof(keys));
410 memset(values, 0, sizeof(values));
411 keys[0] = 99; values[0] = 101;
413 /* NULL key/value lists crash native, so skip testing them */
416 i = pSHSearchMapInt(keys, values, 1, keys[0]);
417 ok(i == values[0], "Len 1, expected %d, got %d\n", values[0], i);
419 /* Key doesn't exist */
420 i = pSHSearchMapInt(keys, values, 1, 100);
421 ok(i == -1, "Len 1 - bad key, expected -1, got %d\n", i);
423 /* Len = 0 => not found */
424 i = pSHSearchMapInt(keys, values, 0, keys[0]);
425 ok(i == -1, "Len 1 - passed len 0, expected -1, got %d\n", i);
427 /* 2 elements, len = 1 */
428 keys[1] = 98; values[1] = 102;
429 i = pSHSearchMapInt(keys, values, 1, keys[1]);
430 ok(i == -1, "Len 1 - array len 2, expected -1, got %d\n", i);
432 /* 2 elements, len = 2 */
433 i = pSHSearchMapInt(keys, values, 2, keys[1]);
434 ok(i == values[1], "Len 2, expected %d, got %d\n", values[1], i);
436 /* Searches forward */
437 keys[2] = 99; values[2] = 103;
438 i = pSHSearchMapInt(keys, values, 3, keys[0]);
439 ok(i == values[0], "Len 3, expected %d, got %d\n", values[0], i);
442 static void test_alloc_shared(void)
450 procid=GetCurrentProcessId();
451 hmem=pSHAllocShared(NULL,10,procid);
452 ok(hmem!=NULL,"SHAllocShared(NULL...) failed: %u\n", GetLastError());
453 ret = pSHFreeShared(hmem, procid);
454 ok( ret, "SHFreeShared failed: %u\n", GetLastError());
457 hmem=pSHAllocShared(&val,4,procid);
458 ok(hmem!=NULL,"SHAllocShared(NULL...) failed: %u\n", GetLastError());
460 p=pSHLockShared(hmem,procid);
461 ok(p!=NULL,"SHLockShared failed: %u\n", GetLastError());
463 ok(*p==val,"Wrong value in shared memory: %d instead of %d\n",*p,val);
464 ret = pSHUnlockShared(p);
465 ok( ret, "SHUnlockShared failed: %u\n", GetLastError());
467 ret = pSHFreeShared(hmem, procid);
468 ok( ret, "SHFreeShared failed: %u\n", GetLastError());
471 static void test_fdsa(void)
475 DWORD num_items; /* Number of elements inserted */
476 void *mem; /* Ptr to array */
477 DWORD blocks_alloced; /* Number of elements allocated */
478 BYTE inc; /* Number of elements to grow by when we need to expand */
479 BYTE block_size; /* Size in bytes of an element */
480 BYTE flags; /* Flags */
483 BOOL (WINAPI *pFDSA_Initialize)(DWORD block_size, DWORD inc, FDSA_info *info, void *mem,
485 BOOL (WINAPI *pFDSA_Destroy)(FDSA_info *info);
486 DWORD (WINAPI *pFDSA_InsertItem)(FDSA_info *info, DWORD where, const void *block);
487 BOOL (WINAPI *pFDSA_DeleteItem)(FDSA_info *info, DWORD where);
490 int block_size = 10, init_blocks = 4, inc = 2;
494 pFDSA_Initialize = (void *)GetProcAddress(hShlwapi, (LPSTR)208);
495 pFDSA_Destroy = (void *)GetProcAddress(hShlwapi, (LPSTR)209);
496 pFDSA_InsertItem = (void *)GetProcAddress(hShlwapi, (LPSTR)210);
497 pFDSA_DeleteItem = (void *)GetProcAddress(hShlwapi, (LPSTR)211);
499 mem = HeapAlloc(GetProcessHeap(), 0, block_size * init_blocks);
500 memset(&info, 0, sizeof(info));
502 ok(pFDSA_Initialize(block_size, inc, &info, mem, init_blocks), "FDSA_Initialize rets FALSE\n");
503 ok(info.num_items == 0, "num_items = %d\n", info.num_items);
504 ok(info.mem == mem, "mem = %p\n", info.mem);
505 ok(info.blocks_alloced == init_blocks, "blocks_alloced = %d\n", info.blocks_alloced);
506 ok(info.inc == inc, "inc = %d\n", info.inc);
507 ok(info.block_size == block_size, "block_size = %d\n", info.block_size);
508 ok(info.flags == 0, "flags = %d\n", info.flags);
510 ret = pFDSA_InsertItem(&info, 1234, "1234567890");
511 ok(ret == 0, "ret = %d\n", ret);
512 ok(info.num_items == 1, "num_items = %d\n", info.num_items);
513 ok(info.mem == mem, "mem = %p\n", info.mem);
514 ok(info.blocks_alloced == init_blocks, "blocks_alloced = %d\n", info.blocks_alloced);
515 ok(info.inc == inc, "inc = %d\n", info.inc);
516 ok(info.block_size == block_size, "block_size = %d\n", info.block_size);
517 ok(info.flags == 0, "flags = %d\n", info.flags);
519 ret = pFDSA_InsertItem(&info, 1234, "abcdefghij");
520 ok(ret == 1, "ret = %d\n", ret);
522 ret = pFDSA_InsertItem(&info, 1, "klmnopqrst");
523 ok(ret == 1, "ret = %d\n", ret);
525 ret = pFDSA_InsertItem(&info, 0, "uvwxyzABCD");
526 ok(ret == 0, "ret = %d\n", ret);
527 ok(info.mem == mem, "mem = %p\n", info.mem);
528 ok(info.flags == 0, "flags = %d\n", info.flags);
530 /* This next InsertItem will cause shlwapi to allocate its own mem buffer */
531 ret = pFDSA_InsertItem(&info, 0, "EFGHIJKLMN");
532 ok(ret == 0, "ret = %d\n", ret);
533 ok(info.mem != mem, "mem = %p\n", info.mem);
534 ok(info.blocks_alloced == init_blocks + inc, "blocks_alloced = %d\n", info.blocks_alloced);
535 ok(info.flags == 0x1, "flags = %d\n", info.flags);
537 ok(!memcmp(info.mem, "EFGHIJKLMNuvwxyzABCD1234567890klmnopqrstabcdefghij", 50), "mem %s\n", (char*)info.mem);
539 ok(pFDSA_DeleteItem(&info, 2), "rets FALSE\n");
540 ok(info.mem != mem, "mem = %p\n", info.mem);
541 ok(info.blocks_alloced == init_blocks + inc, "blocks_alloced = %d\n", info.blocks_alloced);
542 ok(info.flags == 0x1, "flags = %d\n", info.flags);
544 ok(!memcmp(info.mem, "EFGHIJKLMNuvwxyzABCDklmnopqrstabcdefghij", 40), "mem %s\n", (char*)info.mem);
546 ok(pFDSA_DeleteItem(&info, 3), "rets FALSE\n");
547 ok(info.mem != mem, "mem = %p\n", info.mem);
548 ok(info.blocks_alloced == init_blocks + inc, "blocks_alloced = %d\n", info.blocks_alloced);
549 ok(info.flags == 0x1, "flags = %d\n", info.flags);
551 ok(!memcmp(info.mem, "EFGHIJKLMNuvwxyzABCDklmnopqrst", 30), "mem %s\n", (char*)info.mem);
553 ok(!pFDSA_DeleteItem(&info, 4), "does not ret FALSE\n");
555 /* As shlwapi has allocated memory internally, Destroy will ret FALSE */
556 ok(!pFDSA_Destroy(&info), "FDSA_Destroy does not ret FALSE\n");
559 /* When Initialize is called with inc = 0, set it to 1 */
560 ok(pFDSA_Initialize(block_size, 0, &info, mem, init_blocks), "FDSA_Initialize rets FALSE\n");
561 ok(info.inc == 1, "inc = %d\n", info.inc);
563 /* This time, because shlwapi hasn't had to allocate memory
564 internally, Destroy rets non-zero */
565 ok(pFDSA_Destroy(&info), "FDSA_Destroy rets FALSE\n");
568 HeapFree(GetProcessHeap(), 0, mem);
572 typedef struct SHELL_USER_SID {
573 SID_IDENTIFIER_AUTHORITY sidAuthority;
576 } SHELL_USER_SID, *PSHELL_USER_SID;
577 typedef struct SHELL_USER_PERMISSION {
578 SHELL_USER_SID susID;
583 DWORD dwInheritAccessMask;
584 } SHELL_USER_PERMISSION, *PSHELL_USER_PERMISSION;
585 static void test_GetShellSecurityDescriptor(void)
587 SHELL_USER_PERMISSION supCurrentUserFull = {
588 { {SECURITY_NULL_SID_AUTHORITY}, 0, 0 },
589 ACCESS_ALLOWED_ACE_TYPE, FALSE,
591 #define MY_INHERITANCE 0xBE /* invalid value to proof behavior */
592 SHELL_USER_PERMISSION supEveryoneDenied = {
593 { {SECURITY_WORLD_SID_AUTHORITY}, SECURITY_WORLD_RID, 0 },
594 ACCESS_DENIED_ACE_TYPE, TRUE,
595 GENERIC_WRITE, MY_INHERITANCE | 0xDEADBA00, GENERIC_READ };
596 PSHELL_USER_PERMISSION rgsup[2] = {
597 &supCurrentUserFull, &supEveryoneDenied,
599 SECURITY_DESCRIPTOR* psd;
600 SECURITY_DESCRIPTOR* (WINAPI*pGetShellSecurityDescriptor)(PSHELL_USER_PERMISSION*,int);
601 void *pChrCmpIW = GetProcAddress(hShlwapi, "ChrCmpIW");
603 pGetShellSecurityDescriptor=(void*)GetProcAddress(hShlwapi,(char*)475);
605 if(!pGetShellSecurityDescriptor)
607 win_skip("GetShellSecurityDescriptor not available\n");
611 if(pChrCmpIW && pChrCmpIW == pGetShellSecurityDescriptor) /* win2k */
613 win_skip("Skipping for GetShellSecurityDescriptor, same ordinal used for ChrCmpIW\n");
617 psd = pGetShellSecurityDescriptor(NULL, 2);
619 broken(psd==INVALID_HANDLE_VALUE), /* IE5 */
620 "GetShellSecurityDescriptor should fail\n");
621 psd = pGetShellSecurityDescriptor(rgsup, 0);
622 ok(psd==NULL, "GetShellSecurityDescriptor should fail, got %p\n", psd);
624 SetLastError(0xdeadbeef);
625 psd = pGetShellSecurityDescriptor(rgsup, 2);
626 if (psd == NULL && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
628 /* The previous calls to GetShellSecurityDescriptor don't set the last error */
629 win_skip("GetShellSecurityDescriptor is not implemented\n");
632 if (psd == INVALID_HANDLE_VALUE)
634 win_skip("GetShellSecurityDescriptor is broken on IE5\n");
637 ok(psd!=NULL, "GetShellSecurityDescriptor failed\n");
640 BOOL bHasDacl = FALSE, bDefaulted, ret;
643 SECURITY_DESCRIPTOR_CONTROL control;
645 ok(IsValidSecurityDescriptor(psd), "returned value is not valid SD\n");
647 ret = GetSecurityDescriptorControl(psd, &control, &dwRev);
648 ok(ret, "GetSecurityDescriptorControl failed with error %u\n", GetLastError());
649 ok(0 == (control & SE_SELF_RELATIVE), "SD should be absolute\n");
651 ret = GetSecurityDescriptorDacl(psd, &bHasDacl, &pAcl, &bDefaulted);
652 ok(ret, "GetSecurityDescriptorDacl failed with error %u\n", GetLastError());
654 ok(bHasDacl, "SD has no DACL\n");
657 ok(!bDefaulted, "DACL should not be defaulted\n");
659 ok(pAcl != NULL, "NULL DACL!\n");
662 ACL_SIZE_INFORMATION asiSize;
664 ok(IsValidAcl(pAcl), "DACL is not valid\n");
666 ret = GetAclInformation(pAcl, &asiSize, sizeof(asiSize), AclSizeInformation);
667 ok(ret, "GetAclInformation failed with error %u\n", GetLastError());
669 ok(asiSize.AceCount == 3, "Incorrect number of ACEs: %d entries\n", asiSize.AceCount);
670 if (asiSize.AceCount == 3)
672 ACCESS_ALLOWED_ACE *paaa; /* will use for DENIED too */
674 ret = GetAce(pAcl, 0, (LPVOID*)&paaa);
675 ok(ret, "GetAce failed with error %u\n", GetLastError());
676 ok(paaa->Header.AceType == ACCESS_ALLOWED_ACE_TYPE,
677 "Invalid ACE type %d\n", paaa->Header.AceType);
678 ok(paaa->Header.AceFlags == 0, "Invalid ACE flags %x\n", paaa->Header.AceFlags);
679 ok(paaa->Mask == GENERIC_ALL, "Invalid ACE mask %x\n", paaa->Mask);
681 ret = GetAce(pAcl, 1, (LPVOID*)&paaa);
682 ok(ret, "GetAce failed with error %u\n", GetLastError());
683 ok(paaa->Header.AceType == ACCESS_DENIED_ACE_TYPE,
684 "Invalid ACE type %d\n", paaa->Header.AceType);
685 /* first one of two ACEs generated from inheritable entry - without inheritance */
686 ok(paaa->Header.AceFlags == 0, "Invalid ACE flags %x\n", paaa->Header.AceFlags);
687 ok(paaa->Mask == GENERIC_WRITE, "Invalid ACE mask %x\n", paaa->Mask);
689 ret = GetAce(pAcl, 2, (LPVOID*)&paaa);
690 ok(ret, "GetAce failed with error %u\n", GetLastError());
691 ok(paaa->Header.AceType == ACCESS_DENIED_ACE_TYPE,
692 "Invalid ACE type %d\n", paaa->Header.AceType);
693 /* second ACE - with inheritance */
694 ok(paaa->Header.AceFlags == MY_INHERITANCE,
695 "Invalid ACE flags %x\n", paaa->Header.AceFlags);
696 ok(paaa->Mask == GENERIC_READ, "Invalid ACE mask %x\n", paaa->Mask);
705 static void test_SHPackDispParams(void)
711 if(!pSHPackDispParams)
712 win_skip("SHPackSidpParams not available\n");
714 memset(¶ms, 0xc0, sizeof(params));
715 memset(vars, 0xc0, sizeof(vars));
716 hres = pSHPackDispParams(¶ms, vars, 1, VT_I4, 0xdeadbeef);
717 ok(hres == S_OK, "SHPackDispParams failed: %08x\n", hres);
718 ok(params.cArgs == 1, "params.cArgs = %d\n", params.cArgs);
719 ok(params.cNamedArgs == 0, "params.cNamedArgs = %d\n", params.cArgs);
720 ok(params.rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", params.rgdispidNamedArgs);
721 ok(params.rgvarg == vars, "params.rgvarg = %p\n", params.rgvarg);
722 ok(V_VT(vars) == VT_I4, "V_VT(var) = %d\n", V_VT(vars));
723 ok(V_I4(vars) == 0xdeadbeef, "failed %x\n", V_I4(vars));
725 memset(¶ms, 0xc0, sizeof(params));
726 hres = pSHPackDispParams(¶ms, NULL, 0, 0);
727 ok(hres == S_OK, "SHPackDispParams failed: %08x\n", hres);
728 ok(params.cArgs == 0, "params.cArgs = %d\n", params.cArgs);
729 ok(params.cNamedArgs == 0, "params.cNamedArgs = %d\n", params.cArgs);
730 ok(params.rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", params.rgdispidNamedArgs);
731 ok(params.rgvarg == NULL, "params.rgvarg = %p\n", params.rgvarg);
733 memset(vars, 0xc0, sizeof(vars));
734 memset(¶ms, 0xc0, sizeof(params));
735 hres = pSHPackDispParams(¶ms, vars, 4, VT_BSTR, (void*)0xdeadbeef, VT_EMPTY, 10,
736 VT_I4, 100, VT_DISPATCH, (void*)0xdeadbeef);
737 ok(hres == S_OK, "SHPackDispParams failed: %08x\n", hres);
738 ok(params.cArgs == 4, "params.cArgs = %d\n", params.cArgs);
739 ok(params.cNamedArgs == 0, "params.cNamedArgs = %d\n", params.cArgs);
740 ok(params.rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", params.rgdispidNamedArgs);
741 ok(params.rgvarg == vars, "params.rgvarg = %p\n", params.rgvarg);
742 ok(V_VT(vars) == VT_DISPATCH, "V_VT(vars[0]) = %x\n", V_VT(vars));
743 ok(V_I4(vars) == 0xdeadbeef, "V_I4(vars[0]) = %x\n", V_I4(vars));
744 ok(V_VT(vars+1) == VT_I4, "V_VT(vars[1]) = %d\n", V_VT(vars+1));
745 ok(V_I4(vars+1) == 100, "V_I4(vars[1]) = %x\n", V_I4(vars+1));
746 ok(V_VT(vars+2) == VT_I4, "V_VT(vars[2]) = %d\n", V_VT(vars+2));
747 ok(V_I4(vars+2) == 10, "V_I4(vars[2]) = %x\n", V_I4(vars+2));
748 ok(V_VT(vars+3) == VT_BSTR, "V_VT(vars[3]) = %d\n", V_VT(vars+3));
749 ok(V_BSTR(vars+3) == (void*)0xdeadbeef, "V_BSTR(vars[3]) = %p\n", V_BSTR(vars+3));
754 IDispatch IDispatch_iface;
758 static inline Disp *impl_from_IDispatch(IDispatch *iface)
760 return CONTAINING_RECORD(iface, Disp, IDispatch_iface);
763 typedef struct _contain
765 IConnectionPointContainer IConnectionPointContainer_iface;
769 IConnectionPoint **pt;
772 static inline Contain *impl_from_IConnectionPointContainer(IConnectionPointContainer *iface)
774 return CONTAINING_RECORD(iface, Contain, IConnectionPointContainer_iface);
777 typedef struct _cntptn
779 IConnectionPoint IConnectionPoint_iface;
788 static inline ConPt *impl_from_IConnectionPoint(IConnectionPoint *iface)
790 return CONTAINING_RECORD(iface, ConPt, IConnectionPoint_iface);
795 IEnumConnections IEnumConnections_iface;
802 static inline EnumCon *impl_from_IEnumConnections(IEnumConnections *iface)
804 return CONTAINING_RECORD(iface, EnumCon, IEnumConnections_iface);
807 typedef struct _enumpt
809 IEnumConnectionPoints IEnumConnectionPoints_iface;
816 static inline EnumPt *impl_from_IEnumConnectionPoints(IEnumConnectionPoints *iface)
818 return CONTAINING_RECORD(iface, EnumPt, IEnumConnectionPoints_iface);
822 static HRESULT WINAPI Disp_QueryInterface(
829 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch))
836 IDispatch_AddRef(This);
840 trace("no interface\n");
841 return E_NOINTERFACE;
844 static ULONG WINAPI Disp_AddRef(IDispatch* This)
846 Disp *iface = impl_from_IDispatch(This);
847 return InterlockedIncrement(&iface->refCount);
850 static ULONG WINAPI Disp_Release(IDispatch* This)
852 Disp *iface = impl_from_IDispatch(This);
855 ret = InterlockedDecrement(&iface->refCount);
857 HeapFree(GetProcessHeap(),0,This);
861 static HRESULT WINAPI Disp_GetTypeInfoCount(
865 return ERROR_SUCCESS;
868 static HRESULT WINAPI Disp_GetTypeInfo(
874 return ERROR_SUCCESS;
877 static HRESULT WINAPI Disp_GetIDsOfNames(
885 return ERROR_SUCCESS;
888 static HRESULT WINAPI Disp_Invoke(
894 DISPPARAMS *pDispParams,
896 EXCEPINFO *pExcepInfo,
899 trace("%p %x %p %x %x %p %p %p %p\n",This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr);
901 ok(dispIdMember == 0xa0 || dispIdMember == 0xa1, "Unknown dispIdMember\n");
902 ok(pDispParams != NULL, "Invoked with NULL pDispParams\n");
903 ok(wFlags == DISPATCH_METHOD, "Wrong flags %x\n",wFlags);
904 ok(lcid == 0,"Wrong lcid %x\n",lcid);
905 if (dispIdMember == 0xa0)
907 ok(pDispParams->cArgs == 0, "params.cArgs = %d\n", pDispParams->cArgs);
908 ok(pDispParams->cNamedArgs == 0, "params.cNamedArgs = %d\n", pDispParams->cArgs);
909 ok(pDispParams->rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", pDispParams->rgdispidNamedArgs);
910 ok(pDispParams->rgvarg == NULL, "params.rgvarg = %p\n", pDispParams->rgvarg);
912 else if (dispIdMember == 0xa1)
914 ok(pDispParams->cArgs == 2, "params.cArgs = %d\n", pDispParams->cArgs);
915 ok(pDispParams->cNamedArgs == 0, "params.cNamedArgs = %d\n", pDispParams->cArgs);
916 ok(pDispParams->rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", pDispParams->rgdispidNamedArgs);
917 ok(V_VT(pDispParams->rgvarg) == VT_BSTR, "V_VT(var) = %d\n", V_VT(pDispParams->rgvarg));
918 ok(V_I4(pDispParams->rgvarg) == 0xdeadcafe , "failed %p\n", V_BSTR(pDispParams->rgvarg));
919 ok(V_VT(pDispParams->rgvarg+1) == VT_I4, "V_VT(var) = %d\n", V_VT(pDispParams->rgvarg+1));
920 ok(V_I4(pDispParams->rgvarg+1) == 0xdeadbeef, "failed %x\n", V_I4(pDispParams->rgvarg+1));
923 return ERROR_SUCCESS;
926 static const IDispatchVtbl disp_vtbl = {
931 Disp_GetTypeInfoCount,
937 static HRESULT WINAPI Enum_QueryInterface(
938 IEnumConnections* This,
944 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IEnumConnections))
951 IEnumConnections_AddRef(This);
955 trace("no interface\n");
956 return E_NOINTERFACE;
959 static ULONG WINAPI Enum_AddRef(IEnumConnections* This)
961 EnumCon *iface = impl_from_IEnumConnections(This);
962 return InterlockedIncrement(&iface->refCount);
965 static ULONG WINAPI Enum_Release(IEnumConnections* This)
967 EnumCon *iface = impl_from_IEnumConnections(This);
970 ret = InterlockedDecrement(&iface->refCount);
972 HeapFree(GetProcessHeap(),0,This);
976 static HRESULT WINAPI Enum_Next(
977 IEnumConnections* This,
982 EnumCon *iface = impl_from_IEnumConnections(This);
984 if (cConnections > 0 && iface->idx < iface->pt->sinkCount)
986 rgcd->pUnk = iface->pt->sink[iface->idx];
987 IUnknown_AddRef(iface->pt->sink[iface->idx]);
998 static HRESULT WINAPI Enum_Skip(
999 IEnumConnections* This,
1005 static HRESULT WINAPI Enum_Reset(
1006 IEnumConnections* This)
1011 static HRESULT WINAPI Enum_Clone(
1012 IEnumConnections* This,
1013 IEnumConnections **ppEnum)
1018 static const IEnumConnectionsVtbl enum_vtbl = {
1020 Enum_QueryInterface,
1029 static HRESULT WINAPI ConPt_QueryInterface(
1030 IConnectionPoint* This,
1036 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IConnectionPoint))
1043 IConnectionPoint_AddRef(This);
1047 trace("no interface\n");
1048 return E_NOINTERFACE;
1051 static ULONG WINAPI ConPt_AddRef(
1052 IConnectionPoint* This)
1054 ConPt *iface = impl_from_IConnectionPoint(This);
1055 return InterlockedIncrement(&iface->refCount);
1058 static ULONG WINAPI ConPt_Release(
1059 IConnectionPoint* This)
1061 ConPt *iface = impl_from_IConnectionPoint(This);
1064 ret = InterlockedDecrement(&iface->refCount);
1067 if (iface->sinkCount > 0)
1070 for (i = 0; i < iface->sinkCount; i++)
1073 IUnknown_Release(iface->sink[i]);
1075 HeapFree(GetProcessHeap(),0,iface->sink);
1077 HeapFree(GetProcessHeap(),0,This);
1082 static HRESULT WINAPI ConPt_GetConnectionInterface(
1083 IConnectionPoint* This,
1087 ConPt *iface = impl_from_IConnectionPoint(This);
1094 memcpy(pIID,&iface->id,sizeof(GUID));
1098 static HRESULT WINAPI ConPt_GetConnectionPointContainer(
1099 IConnectionPoint* This,
1100 IConnectionPointContainer **ppCPC)
1102 ConPt *iface = impl_from_IConnectionPoint(This);
1104 *ppCPC = &iface->container->IConnectionPointContainer_iface;
1108 static HRESULT WINAPI ConPt_Advise(
1109 IConnectionPoint* This,
1113 ConPt *iface = impl_from_IConnectionPoint(This);
1115 if (iface->sinkCount == 0)
1116 iface->sink = HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown*));
1118 iface->sink = HeapReAlloc(GetProcessHeap(),0,iface->sink,sizeof(IUnknown*)*(iface->sinkCount+1));
1119 iface->sink[iface->sinkCount] = pUnkSink;
1120 IUnknown_AddRef(pUnkSink);
1122 *pdwCookie = iface->sinkCount;
1126 static HRESULT WINAPI ConPt_Unadvise(
1127 IConnectionPoint* This,
1130 ConPt *iface = impl_from_IConnectionPoint(This);
1132 if (dwCookie > iface->sinkCount)
1136 IUnknown_Release(iface->sink[dwCookie-1]);
1137 iface->sink[dwCookie-1] = NULL;
1142 static HRESULT WINAPI ConPt_EnumConnections(
1143 IConnectionPoint* This,
1144 IEnumConnections **ppEnum)
1148 ec = HeapAlloc(GetProcessHeap(),0,sizeof(EnumCon));
1149 ec->IEnumConnections_iface.lpVtbl = &enum_vtbl;
1151 ec->pt = impl_from_IConnectionPoint(This);
1153 *ppEnum = &ec->IEnumConnections_iface;
1158 static const IConnectionPointVtbl point_vtbl = {
1159 ConPt_QueryInterface,
1163 ConPt_GetConnectionInterface,
1164 ConPt_GetConnectionPointContainer,
1167 ConPt_EnumConnections
1170 static HRESULT WINAPI EnumPt_QueryInterface(
1171 IEnumConnectionPoints* This,
1177 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IEnumConnectionPoints))
1184 IEnumConnectionPoints_AddRef(This);
1188 trace("no interface\n");
1189 return E_NOINTERFACE;
1192 static ULONG WINAPI EnumPt_AddRef(IEnumConnectionPoints* This)
1194 EnumPt *iface = impl_from_IEnumConnectionPoints(This);
1195 return InterlockedIncrement(&iface->refCount);
1198 static ULONG WINAPI EnumPt_Release(IEnumConnectionPoints* This)
1200 EnumPt *iface = impl_from_IEnumConnectionPoints(This);
1203 ret = InterlockedDecrement(&iface->refCount);
1205 HeapFree(GetProcessHeap(),0,This);
1209 static HRESULT WINAPI EnumPt_Next(
1210 IEnumConnectionPoints* This,
1212 IConnectionPoint **rgcd,
1215 EnumPt *iface = impl_from_IEnumConnectionPoints(This);
1217 if (cConnections > 0 && iface->idx < iface->container->ptCount)
1219 *rgcd = iface->container->pt[iface->idx];
1220 IConnectionPoint_AddRef(iface->container->pt[iface->idx]);
1230 static HRESULT WINAPI EnumPt_Skip(
1231 IEnumConnectionPoints* This,
1237 static HRESULT WINAPI EnumPt_Reset(
1238 IEnumConnectionPoints* This)
1243 static HRESULT WINAPI EnumPt_Clone(
1244 IEnumConnectionPoints* This,
1245 IEnumConnectionPoints **ppEnumPt)
1250 static const IEnumConnectionPointsVtbl enumpt_vtbl = {
1252 EnumPt_QueryInterface,
1261 static HRESULT WINAPI Contain_QueryInterface(
1262 IConnectionPointContainer* This,
1268 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IConnectionPointContainer))
1275 IConnectionPointContainer_AddRef(This);
1279 trace("no interface\n");
1280 return E_NOINTERFACE;
1283 static ULONG WINAPI Contain_AddRef(
1284 IConnectionPointContainer* This)
1286 Contain *iface = impl_from_IConnectionPointContainer(This);
1287 return InterlockedIncrement(&iface->refCount);
1290 static ULONG WINAPI Contain_Release(
1291 IConnectionPointContainer* This)
1293 Contain *iface = impl_from_IConnectionPointContainer(This);
1296 ret = InterlockedDecrement(&iface->refCount);
1299 if (iface->ptCount > 0)
1302 for (i = 0; i < iface->ptCount; i++)
1303 IConnectionPoint_Release(iface->pt[i]);
1304 HeapFree(GetProcessHeap(),0,iface->pt);
1306 HeapFree(GetProcessHeap(),0,This);
1311 static HRESULT WINAPI Contain_EnumConnectionPoints(
1312 IConnectionPointContainer* This,
1313 IEnumConnectionPoints **ppEnum)
1317 ec = HeapAlloc(GetProcessHeap(),0,sizeof(EnumPt));
1318 ec->IEnumConnectionPoints_iface.lpVtbl = &enumpt_vtbl;
1321 ec->container = impl_from_IConnectionPointContainer(This);
1322 *ppEnum = &ec->IEnumConnectionPoints_iface;
1327 static HRESULT WINAPI Contain_FindConnectionPoint(
1328 IConnectionPointContainer* This,
1330 IConnectionPoint **ppCP)
1332 Contain *iface = impl_from_IConnectionPointContainer(This);
1335 if (!IsEqualIID(riid, &IID_NULL) || iface->ptCount ==0)
1337 pt = HeapAlloc(GetProcessHeap(),0,sizeof(ConPt));
1338 pt->IConnectionPoint_iface.lpVtbl = &point_vtbl;
1342 pt->container = iface;
1343 pt->id = IID_IDispatch;
1345 if (iface->ptCount == 0)
1346 iface->pt =HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown*));
1348 iface->pt = HeapReAlloc(GetProcessHeap(),0,iface->pt,sizeof(IUnknown*)*(iface->ptCount+1));
1349 iface->pt[iface->ptCount] = &pt->IConnectionPoint_iface;
1352 *ppCP = &pt->IConnectionPoint_iface;
1356 *ppCP = iface->pt[0];
1357 IUnknown_AddRef((IUnknown*)*ppCP);
1363 static const IConnectionPointContainerVtbl contain_vtbl = {
1364 Contain_QueryInterface,
1368 Contain_EnumConnectionPoints,
1369 Contain_FindConnectionPoint
1372 static void test_IConnectionPoint(void)
1376 IConnectionPoint *point;
1379 DWORD cookie = 0xffffffff;
1383 if (!pIConnectionPoint_SimpleInvoke || !pConnectToConnectionPoint)
1385 win_skip("IConnectionPoint Apis not present\n");
1389 container = HeapAlloc(GetProcessHeap(),0,sizeof(Contain));
1390 container->IConnectionPointContainer_iface.lpVtbl = &contain_vtbl;
1391 container->refCount = 1;
1392 container->ptCount = 0;
1393 container->pt = NULL;
1395 dispatch = HeapAlloc(GetProcessHeap(),0,sizeof(Disp));
1396 dispatch->IDispatch_iface.lpVtbl = &disp_vtbl;
1397 dispatch->refCount = 1;
1399 rc = pConnectToConnectionPoint((IUnknown*)dispatch, &IID_NULL, TRUE, (IUnknown*)container, &cookie, &point);
1400 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
1401 ok(point != NULL, "returned ConnectionPoint is NULL\n");
1402 ok(cookie != 0xffffffff, "invalid cookie returned\n");
1404 rc = pIConnectionPoint_SimpleInvoke(point,0xa0,NULL);
1405 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
1407 if (pSHPackDispParams)
1409 memset(¶ms, 0xc0, sizeof(params));
1410 memset(vars, 0xc0, sizeof(vars));
1411 rc = pSHPackDispParams(¶ms, vars, 2, VT_I4, 0xdeadbeef, VT_BSTR, 0xdeadcafe);
1412 ok(rc == S_OK, "SHPackDispParams failed: %08x\n", rc);
1414 rc = pIConnectionPoint_SimpleInvoke(point,0xa1,¶ms);
1415 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
1418 win_skip("pSHPackDispParams not present\n");
1420 rc = pConnectToConnectionPoint(NULL, &IID_NULL, FALSE, (IUnknown*)container, &cookie, NULL);
1421 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
1423 /* MSDN says this should be required but it crashs on XP
1424 IUnknown_Release(point);
1426 ref = IUnknown_Release((IUnknown*)container);
1427 ok(ref == 0, "leftover IConnectionPointContainer reference %i\n",ref);
1428 ref = IUnknown_Release((IUnknown*)dispatch);
1429 ok(ref == 0, "leftover IDispatch reference %i\n",ref);
1432 typedef struct _propbag
1434 IPropertyBag IPropertyBag_iface;
1439 static inline PropBag *impl_from_IPropertyBag(IPropertyBag *iface)
1441 return CONTAINING_RECORD(iface, PropBag, IPropertyBag_iface);
1445 static HRESULT WINAPI Prop_QueryInterface(
1452 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IPropertyBag))
1459 IPropertyBag_AddRef(This);
1463 trace("no interface\n");
1464 return E_NOINTERFACE;
1467 static ULONG WINAPI Prop_AddRef(
1470 PropBag *iface = impl_from_IPropertyBag(This);
1471 return InterlockedIncrement(&iface->refCount);
1474 static ULONG WINAPI Prop_Release(
1477 PropBag *iface = impl_from_IPropertyBag(This);
1480 ret = InterlockedDecrement(&iface->refCount);
1482 HeapFree(GetProcessHeap(),0,This);
1486 static HRESULT WINAPI Prop_Read(
1488 LPCOLESTR pszPropName,
1490 IErrorLog *pErrorLog)
1492 V_VT(pVar) = VT_BLOB|VT_BYREF;
1493 V_BYREF(pVar) = (LPVOID)0xdeadcafe;
1497 static HRESULT WINAPI Prop_Write(
1499 LPCOLESTR pszPropName,
1506 static const IPropertyBagVtbl prop_vtbl = {
1507 Prop_QueryInterface,
1515 static void test_SHPropertyBag_ReadLONG(void)
1520 static const WCHAR szName1[] = {'n','a','m','e','1',0};
1522 if (!pSHPropertyBag_ReadLONG)
1524 win_skip("SHPropertyBag_ReadLONG not present\n");
1528 pb = HeapAlloc(GetProcessHeap(),0,sizeof(PropBag));
1530 pb->IPropertyBag_iface.lpVtbl = &prop_vtbl;
1533 rc = pSHPropertyBag_ReadLONG(NULL, szName1, &out);
1534 ok(rc == E_INVALIDARG || broken(rc == 0), "incorrect return %x\n",rc);
1535 ok(out == 0xfeedface, "value should not have changed\n");
1536 rc = pSHPropertyBag_ReadLONG(&pb->IPropertyBag_iface, NULL, &out);
1537 ok(rc == E_INVALIDARG || broken(rc == 0) || broken(rc == 1), "incorrect return %x\n",rc);
1538 ok(out == 0xfeedface, "value should not have changed\n");
1539 rc = pSHPropertyBag_ReadLONG(&pb->IPropertyBag_iface, szName1, NULL);
1540 ok(rc == E_INVALIDARG || broken(rc == 0) || broken(rc == 1), "incorrect return %x\n",rc);
1541 rc = pSHPropertyBag_ReadLONG(&pb->IPropertyBag_iface, szName1, &out);
1542 ok(rc == DISP_E_BADVARTYPE || broken(rc == 0) || broken(rc == 1), "incorrect return %x\n",rc);
1543 ok(out == 0xfeedface || broken(out == 0xfeedfa00), "value should not have changed %x\n",out);
1544 IUnknown_Release((IUnknown*)pb);
1549 static void test_SHSetWindowBits(void)
1552 DWORD style, styleold;
1555 if(!pSHSetWindowBits)
1557 win_skip("SHSetWindowBits is not available\n");
1562 clsA.lpfnWndProc = DefWindowProcA;
1563 clsA.cbClsExtra = 0;
1564 clsA.cbWndExtra = 0;
1565 clsA.hInstance = GetModuleHandleA(NULL);
1567 clsA.hCursor = LoadCursorA(0, IDC_ARROW);
1568 clsA.hbrBackground = NULL;
1569 clsA.lpszMenuName = NULL;
1570 clsA.lpszClassName = "Shlwapi test class";
1571 RegisterClassA(&clsA);
1573 hwnd = CreateWindowA("Shlwapi test class", "Test", WS_VISIBLE, 0, 0, 100, 100,
1574 NULL, NULL, GetModuleHandle(NULL), 0);
1575 ok(IsWindow(hwnd), "failed to create window\n");
1578 SetLastError(0xdeadbeef);
1579 style = pSHSetWindowBits(NULL, GWL_STYLE, 0, 0);
1580 ok(style == 0, "expected 0 retval, got %d\n", style);
1581 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE ||
1582 broken(GetLastError() == 0xdeadbeef), /* Win9x/WinMe */
1583 "expected ERROR_INVALID_WINDOW_HANDLE, got %d\n", GetLastError());
1585 /* zero mask, zero flags */
1586 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1587 style = pSHSetWindowBits(hwnd, GWL_STYLE, 0, 0);
1588 ok(styleold == style, "expected old style\n");
1589 ok(styleold == GetWindowLongA(hwnd, GWL_STYLE), "expected to keep old style\n");
1592 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1593 ok(styleold & WS_VISIBLE, "expected WS_VISIBLE\n");
1594 style = pSHSetWindowBits(hwnd, GWL_STYLE, WS_VISIBLE, 0);
1596 ok(style == styleold, "expected previous style, got %x\n", style);
1597 ok((GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE) == 0, "expected updated style\n");
1599 /* test mask, unset style bit used */
1600 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1601 style = pSHSetWindowBits(hwnd, GWL_STYLE, WS_VISIBLE, 0);
1602 ok(style == styleold, "expected previous style, got %x\n", style);
1603 ok(styleold == GetWindowLongA(hwnd, GWL_STYLE), "expected to keep old style\n");
1605 /* set back with flags */
1606 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1607 style = pSHSetWindowBits(hwnd, GWL_STYLE, WS_VISIBLE, WS_VISIBLE);
1608 ok(style == styleold, "expected previous style, got %x\n", style);
1609 ok(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE, "expected updated style\n");
1611 /* reset and try to set without a mask */
1612 pSHSetWindowBits(hwnd, GWL_STYLE, WS_VISIBLE, 0);
1613 ok((GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE) == 0, "expected updated style\n");
1614 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1615 style = pSHSetWindowBits(hwnd, GWL_STYLE, 0, WS_VISIBLE);
1616 ok(style == styleold, "expected previous style, got %x\n", style);
1617 ok((GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE) == 0, "expected updated style\n");
1619 DestroyWindow(hwnd);
1621 UnregisterClassA("Shlwapi test class", GetModuleHandleA(NULL));
1624 static void test_SHFormatDateTimeA(void)
1626 FILETIME UNALIGNED filetime;
1627 CHAR buff[100], buff2[100], buff3[100];
1632 if(!pSHFormatDateTimeA)
1634 win_skip("pSHFormatDateTimeA isn't available\n");
1640 /* crashes on native */
1641 pSHFormatDateTimeA(NULL, NULL, NULL, 0);
1645 SystemTimeToFileTime(&st, &filetime);
1646 /* SHFormatDateTime expects input as utc */
1647 LocalFileTimeToFileTime(&filetime, &filetime);
1649 /* no way to get required buffer length here */
1650 SetLastError(0xdeadbeef);
1651 ret = pSHFormatDateTimeA(&filetime, NULL, NULL, 0);
1652 ok(ret == 0, "got %d\n", ret);
1653 ok(GetLastError() == 0xdeadbeef || broken(GetLastError() == ERROR_SUCCESS /* Win7 */),
1654 "expected 0xdeadbeef, got %d\n", GetLastError());
1656 SetLastError(0xdeadbeef);
1657 buff[0] = 'a'; buff[1] = 0;
1658 ret = pSHFormatDateTimeA(&filetime, NULL, buff, 0);
1659 ok(ret == 0, "got %d\n", ret);
1660 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1661 ok(buff[0] == 'a', "expected same string, got %s\n", buff);
1663 /* flags needs to have FDTF_NOAUTOREADINGORDER for these tests to succeed on Vista+ */
1665 /* all combinations documented as invalid succeeded */
1666 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTTIME | FDTF_LONGTIME;
1667 SetLastError(0xdeadbeef);
1668 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1669 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1670 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1672 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTDATE | FDTF_LONGDATE;
1673 SetLastError(0xdeadbeef);
1674 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1675 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1676 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1678 flags = FDTF_SHORTDATE | FDTF_LTRDATE | FDTF_RTLDATE;
1679 SetLastError(0xdeadbeef);
1680 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1681 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1682 ok(GetLastError() == 0xdeadbeef ||
1683 broken(GetLastError() == ERROR_INVALID_FLAGS), /* Win9x/WinMe */
1684 "expected 0xdeadbeef, got %d\n", GetLastError());
1686 /* now check returned strings */
1687 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTTIME;
1688 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1689 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1690 ret = GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff2, sizeof(buff2));
1691 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1692 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1694 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGTIME;
1695 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1696 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1697 ret = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2));
1698 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1699 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1701 /* both time flags */
1702 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGTIME | FDTF_SHORTTIME;
1703 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1704 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1705 ret = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2));
1706 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1707 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1709 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTDATE;
1710 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1711 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1712 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2));
1713 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1714 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1716 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGDATE;
1717 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1718 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1719 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
1720 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1721 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1723 /* both date flags */
1724 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGDATE | FDTF_SHORTDATE;
1725 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1726 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1727 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
1728 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1729 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1731 /* various combinations of date/time flags */
1732 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGDATE | FDTF_SHORTTIME;
1733 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1734 ok(ret == lstrlenA(buff)+1, "got %d, length %d\n", ret, lstrlenA(buff)+1);
1735 ret = GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3));
1736 ok(ret == lstrlenA(buff3)+1, "got %d\n", ret);
1737 ok(lstrcmpA(buff3, buff + lstrlenA(buff) - lstrlenA(buff3)) == 0,
1738 "expected (%s), got (%s) for time part\n",
1739 buff3, buff + lstrlenA(buff) - lstrlenA(buff3));
1740 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
1741 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1742 buff[lstrlenA(buff2)] = '\0';
1743 ok(lstrcmpA(buff2, buff) == 0, "expected (%s) got (%s) for date part\n",
1746 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGDATE | FDTF_LONGTIME;
1747 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1748 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1749 ret = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3));
1750 ok(ret == lstrlenA(buff3)+1, "got %d\n", ret);
1751 ok(lstrcmpA(buff3, buff + lstrlenA(buff) - lstrlenA(buff3)) == 0,
1752 "expected (%s), got (%s) for time part\n",
1753 buff3, buff + lstrlenA(buff) - lstrlenA(buff3));
1754 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
1755 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1756 buff[lstrlenA(buff2)] = '\0';
1757 ok(lstrcmpA(buff2, buff) == 0, "expected (%s) got (%s) for date part\n",
1760 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTDATE | FDTF_SHORTTIME;
1761 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1762 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1763 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2));
1764 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1766 ret = GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3));
1767 ok(ret == lstrlenA(buff3)+1, "got %d\n", ret);
1768 strcat(buff2, buff3);
1769 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1771 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTDATE | FDTF_LONGTIME;
1772 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1773 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1774 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2));
1775 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1777 ret = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3));
1778 ok(ret == lstrlenA(buff3)+1, "got %d\n", ret);
1779 strcat(buff2, buff3);
1780 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1783 static void test_SHFormatDateTimeW(void)
1785 FILETIME UNALIGNED filetime;
1786 WCHAR buff[100], buff2[100], buff3[100], *p1, *p2;
1790 static const WCHAR spaceW[] = {' ',0};
1791 #define UNICODE_LTR_MARK 0x200e
1793 if(!pSHFormatDateTimeW)
1795 win_skip("pSHFormatDateTimeW isn't available\n");
1801 /* crashes on native */
1802 pSHFormatDateTimeW(NULL, NULL, NULL, 0);
1806 SystemTimeToFileTime(&st, &filetime);
1807 /* SHFormatDateTime expects input as utc */
1808 LocalFileTimeToFileTime(&filetime, &filetime);
1810 /* no way to get required buffer length here */
1811 SetLastError(0xdeadbeef);
1812 ret = pSHFormatDateTimeW(&filetime, NULL, NULL, 0);
1813 ok(ret == 0, "expected 0, got %d\n", ret);
1814 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1816 SetLastError(0xdeadbeef);
1817 buff[0] = 'a'; buff[1] = 0;
1818 ret = pSHFormatDateTimeW(&filetime, NULL, buff, 0);
1819 ok(ret == 0, "expected 0, got %d\n", ret);
1820 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1821 ok(buff[0] == 'a', "expected same string\n");
1823 /* all combinations documented as invalid succeeded */
1824 flags = FDTF_SHORTTIME | FDTF_LONGTIME;
1825 SetLastError(0xdeadbeef);
1826 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1827 ok(ret == lstrlenW(buff)+1 || ret == lstrlenW(buff),
1828 "expected %d or %d, got %d\n", lstrlenW(buff)+1, lstrlenW(buff), ret);
1829 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1831 flags = FDTF_SHORTDATE | FDTF_LONGDATE;
1832 SetLastError(0xdeadbeef);
1833 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1834 ok(ret == lstrlenW(buff)+1 || ret == lstrlenW(buff),
1835 "expected %d or %d, got %d\n", lstrlenW(buff)+1, lstrlenW(buff), ret);
1836 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1838 flags = FDTF_SHORTDATE | FDTF_LTRDATE | FDTF_RTLDATE;
1839 SetLastError(0xdeadbeef);
1840 buff[0] = 0; /* NT4 doesn't clear the buffer on failure */
1841 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1842 ok(ret == lstrlenW(buff)+1 || ret == lstrlenW(buff),
1843 "expected %d or %d, got %d\n", lstrlenW(buff)+1, lstrlenW(buff), ret);
1844 ok(GetLastError() == 0xdeadbeef ||
1845 broken(GetLastError() == ERROR_INVALID_FLAGS), /* Win9x/WinMe/NT4 */
1846 "expected 0xdeadbeef, got %d\n", GetLastError());
1848 /* now check returned strings */
1849 flags = FDTF_SHORTTIME;
1850 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1851 ok(ret == lstrlenW(buff)+1 || ret == lstrlenW(buff),
1852 "expected %d or %d, got %d\n", lstrlenW(buff)+1, lstrlenW(buff), ret);
1853 SetLastError(0xdeadbeef);
1854 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1855 if (ret == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1857 win_skip("Needed W-functions are not implemented\n");
1860 ok(ret == lstrlenW(buff2)+1, "expected %d, got %d\n", lstrlenW(buff2)+1, ret);
1861 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1863 flags = FDTF_LONGTIME;
1864 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1865 ok(ret == lstrlenW(buff)+1 || ret == lstrlenW(buff),
1866 "expected %d or %d, got %d\n", lstrlenW(buff)+1, lstrlenW(buff), ret);
1867 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1868 ok(ret == lstrlenW(buff2)+1, "expected %d, got %d\n", lstrlenW(buff2)+1, ret);
1869 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1871 /* both time flags */
1872 flags = FDTF_LONGTIME | FDTF_SHORTTIME;
1873 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1874 ok(ret == lstrlenW(buff)+1 || ret == lstrlenW(buff),
1875 "expected %d or %d, got %d\n", lstrlenW(buff)+1, lstrlenW(buff), ret);
1876 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1877 ok(ret == lstrlenW(buff2)+1, "expected %d, got %d\n", lstrlenW(buff2)+1, ret);
1878 ok(lstrcmpW(buff, buff2) == 0, "expected equal string\n");
1880 flags = FDTF_SHORTDATE;
1881 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1882 ok(ret == lstrlenW(buff)+1 || ret == lstrlenW(buff),
1883 "expected %d or %d, got %d\n", lstrlenW(buff)+1, lstrlenW(buff), ret);
1884 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1885 ok(ret == lstrlenW(buff2)+1, "expected %d, got %d\n", lstrlenW(buff2)+1, ret);
1886 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1888 flags = FDTF_LONGDATE;
1889 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1890 ok(ret == lstrlenW(buff)+1 || ret == lstrlenW(buff),
1891 "expected %d or %d, got %d\n", lstrlenW(buff)+1, lstrlenW(buff), ret);
1892 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1893 ok(ret == lstrlenW(buff2)+1, "expected %d, got %d\n", lstrlenW(buff2)+1, ret);
1894 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1896 /* both date flags */
1897 flags = FDTF_LONGDATE | FDTF_SHORTDATE;
1898 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1899 ok(ret == lstrlenW(buff)+1 || ret == lstrlenW(buff),
1900 "expected %d or %d, got %d\n", lstrlenW(buff)+1, lstrlenW(buff), ret);
1901 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1902 ok(ret == lstrlenW(buff2)+1, "expected %d, got %d\n", lstrlenW(buff2)+1, ret);
1903 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1905 /* various combinations of date/time flags */
1906 flags = FDTF_LONGDATE | FDTF_SHORTTIME;
1907 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1908 ok(ret == lstrlenW(buff)+1 || ret == lstrlenW(buff),
1909 "expected %d or %d, got %d\n", lstrlenW(buff)+1, lstrlenW(buff), ret);
1910 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
1911 ok(ret == lstrlenW(buff3)+1, "expected %d, got %d\n", lstrlenW(buff3)+1, ret);
1912 ok(lstrcmpW(buff3, buff + lstrlenW(buff) - lstrlenW(buff3)) == 0,
1913 "expected (%s), got (%s) for time part\n",
1914 wine_dbgstr_w(buff3), wine_dbgstr_w(buff + lstrlenW(buff) - lstrlenW(buff3)));
1915 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1916 ok(ret == lstrlenW(buff2)+1, "expected %d, got %d\n", lstrlenW(buff2)+1, ret);
1921 while (*p1 == UNICODE_LTR_MARK)
1923 while (*p2 == UNICODE_LTR_MARK)
1929 ok(lstrcmpW(buff2, buff) == 0, "expected (%s) got (%s) for date part\n",
1930 wine_dbgstr_w(buff2), wine_dbgstr_w(buff));
1932 flags = FDTF_LONGDATE | FDTF_LONGTIME;
1933 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1934 ok(ret == lstrlenW(buff)+1 || ret == lstrlenW(buff),
1935 "expected %d or %d, got %d\n", lstrlenW(buff)+1, lstrlenW(buff), ret);
1936 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
1937 ok(ret == lstrlenW(buff3)+1, "expected %d, got %d\n", lstrlenW(buff3)+1, ret);
1938 ok(lstrcmpW(buff3, buff + lstrlenW(buff) - lstrlenW(buff3)) == 0,
1939 "expected (%s), got (%s) for time part\n",
1940 wine_dbgstr_w(buff3), wine_dbgstr_w(buff + lstrlenW(buff) - lstrlenW(buff3)));
1941 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1942 ok(ret == lstrlenW(buff2)+1, "expected %d, got %d\n", lstrlenW(buff2)+1, ret);
1947 while (*p1 == UNICODE_LTR_MARK)
1949 while (*p2 == UNICODE_LTR_MARK)
1955 ok(lstrcmpW(buff2, buff) == 0, "expected (%s) got (%s) for date part\n",
1956 wine_dbgstr_w(buff2), wine_dbgstr_w(buff));
1958 flags = FDTF_SHORTDATE | FDTF_SHORTTIME;
1959 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1960 ok(ret == lstrlenW(buff)+1 || ret == lstrlenW(buff),
1961 "expected %d or %d, got %d\n", lstrlenW(buff)+1, lstrlenW(buff), ret);
1962 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1963 ok(ret == lstrlenW(buff2)+1, "expected %d, got %d\n", lstrlenW(buff2)+1, ret);
1964 lstrcatW(buff2, spaceW);
1965 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
1966 ok(ret == lstrlenW(buff3)+1, "expected %d, got %d\n", lstrlenW(buff3)+1, ret);
1967 lstrcatW(buff2, buff3);
1968 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1970 flags = FDTF_SHORTDATE | FDTF_LONGTIME;
1971 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1972 ok(ret == lstrlenW(buff)+1 || ret == lstrlenW(buff),
1973 "expected %d or %d, got %d\n", lstrlenW(buff)+1, lstrlenW(buff), ret);
1974 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1975 ok(ret == lstrlenW(buff2)+1, "expected %d, got %d\n", lstrlenW(buff2)+1, ret);
1976 lstrcatW(buff2, spaceW);
1977 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
1978 ok(ret == lstrlenW(buff3)+1, "expected %d, got %d\n", lstrlenW(buff3)+1, ret);
1979 lstrcatW(buff2, buff3);
1980 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1983 static void test_SHGetObjectCompatFlags(void)
1985 struct compat_value {
1990 struct compat_value values[] = {
1991 { "OTNEEDSSFCACHE", 0x1 },
1992 { "NO_WEBVIEW", 0x2 },
1993 { "UNBINDABLE", 0x4 },
1995 { "NEEDSFILESYSANCESTOR", 0x10 },
1996 { "NOTAFILESYSTEM", 0x20 },
1997 { "CTXMENU_NOVERBS", 0x40 },
1998 { "CTXMENU_LIMITEDQI", 0x80 },
1999 { "COCREATESHELLFOLDERONLY", 0x100 },
2000 { "NEEDSSTORAGEANCESTOR", 0x200 },
2001 { "NOLEGACYWEBVIEW", 0x400 },
2002 { "CTXMENU_XPQCMFLAGS", 0x1000 },
2003 { "NOIPROPERTYSTORE", 0x2000 }
2006 static const char compat_path[] = "Software\\Microsoft\\Windows\\CurrentVersion\\ShellCompatibility\\Objects";
2007 void *pColorAdjustLuma = GetProcAddress(hShlwapi, "ColorAdjustLuma");
2008 CHAR keyA[39]; /* {CLSID} */
2013 if (!pSHGetObjectCompatFlags)
2015 win_skip("SHGetObjectCompatFlags isn't available\n");
2019 if (pColorAdjustLuma && pColorAdjustLuma == pSHGetObjectCompatFlags) /* win2k */
2021 win_skip("Skipping SHGetObjectCompatFlags, same ordinal used for ColorAdjustLuma\n");
2026 ret = pSHGetObjectCompatFlags(NULL, NULL);
2027 ok(ret == 0, "got %d\n", ret);
2029 ret = RegOpenKeyA(HKEY_LOCAL_MACHINE, compat_path, &root);
2030 if (ret != ERROR_SUCCESS)
2032 skip("No compatibility class data found\n");
2036 for (i = 0; RegEnumKeyA(root, i, keyA, sizeof(keyA)) == ERROR_SUCCESS; i++)
2040 if (RegOpenKeyA(root, keyA, &clsid_key) == ERROR_SUCCESS)
2043 DWORD expected = 0, got, length = sizeof(valueA);
2047 for (v = 0; RegEnumValueA(clsid_key, v, valueA, &length, NULL, NULL, NULL, NULL) == ERROR_SUCCESS; v++)
2051 for (j = 0; j < sizeof(values)/sizeof(struct compat_value); j++)
2052 if (lstrcmpA(values[j].nameA, valueA) == 0)
2054 expected |= values[j].value;
2058 length = sizeof(valueA);
2061 pGUIDFromStringA(keyA, &clsid);
2062 got = pSHGetObjectCompatFlags(NULL, &clsid);
2063 ok(got == expected, "got 0x%08x, expected 0x%08x. Key %s\n", got, expected, keyA);
2065 RegCloseKey(clsid_key);
2073 IOleCommandTarget IOleCommandTarget_iface;
2075 } IOleCommandTargetImpl;
2077 static inline IOleCommandTargetImpl *impl_from_IOleCommandTarget(IOleCommandTarget *iface)
2079 return CONTAINING_RECORD(iface, IOleCommandTargetImpl, IOleCommandTarget_iface);
2082 static const IOleCommandTargetVtbl IOleCommandTargetImpl_Vtbl;
2084 static IOleCommandTarget* IOleCommandTargetImpl_Construct(void)
2086 IOleCommandTargetImpl *obj;
2088 obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*obj));
2089 obj->IOleCommandTarget_iface.lpVtbl = &IOleCommandTargetImpl_Vtbl;
2092 return &obj->IOleCommandTarget_iface;
2095 static HRESULT WINAPI IOleCommandTargetImpl_QueryInterface(IOleCommandTarget *iface, REFIID riid, void **ppvObj)
2097 IOleCommandTargetImpl *This = impl_from_IOleCommandTarget(iface);
2099 if (IsEqualIID(riid, &IID_IUnknown) ||
2100 IsEqualIID(riid, &IID_IOleCommandTarget))
2107 IOleCommandTarget_AddRef(iface);
2111 return E_NOINTERFACE;
2114 static ULONG WINAPI IOleCommandTargetImpl_AddRef(IOleCommandTarget *iface)
2116 IOleCommandTargetImpl *This = impl_from_IOleCommandTarget(iface);
2117 return InterlockedIncrement(&This->ref);
2120 static ULONG WINAPI IOleCommandTargetImpl_Release(IOleCommandTarget *iface)
2122 IOleCommandTargetImpl *This = impl_from_IOleCommandTarget(iface);
2123 ULONG ref = InterlockedDecrement(&This->ref);
2127 HeapFree(GetProcessHeap(), 0, This);
2133 static HRESULT WINAPI IOleCommandTargetImpl_QueryStatus(
2134 IOleCommandTarget *iface, const GUID *group, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText)
2139 static HRESULT WINAPI IOleCommandTargetImpl_Exec(
2140 IOleCommandTarget *iface,
2141 const GUID *CmdGroup,
2147 add_call(&trace_got, 3, CmdGroup, (void*)(DWORD_PTR)nCmdID, (void*)(DWORD_PTR)nCmdexecopt, pvaIn, pvaOut);
2151 static const IOleCommandTargetVtbl IOleCommandTargetImpl_Vtbl =
2153 IOleCommandTargetImpl_QueryInterface,
2154 IOleCommandTargetImpl_AddRef,
2155 IOleCommandTargetImpl_Release,
2156 IOleCommandTargetImpl_QueryStatus,
2157 IOleCommandTargetImpl_Exec
2161 IServiceProvider IServiceProvider_iface;
2163 } IServiceProviderImpl;
2165 static inline IServiceProviderImpl *impl_from_IServiceProvider(IServiceProvider *iface)
2167 return CONTAINING_RECORD(iface, IServiceProviderImpl, IServiceProvider_iface);
2171 IProfferService IProfferService_iface;
2173 } IProfferServiceImpl;
2175 static inline IProfferServiceImpl *impl_from_IProfferService(IProfferService *iface)
2177 return CONTAINING_RECORD(iface, IProfferServiceImpl, IProfferService_iface);
2181 static const IServiceProviderVtbl IServiceProviderImpl_Vtbl;
2182 static const IProfferServiceVtbl IProfferServiceImpl_Vtbl;
2184 static IServiceProvider* IServiceProviderImpl_Construct(void)
2186 IServiceProviderImpl *obj;
2188 obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*obj));
2189 obj->IServiceProvider_iface.lpVtbl = &IServiceProviderImpl_Vtbl;
2192 return &obj->IServiceProvider_iface;
2195 static IProfferService* IProfferServiceImpl_Construct(void)
2197 IProfferServiceImpl *obj;
2199 obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*obj));
2200 obj->IProfferService_iface.lpVtbl = &IProfferServiceImpl_Vtbl;
2203 return &obj->IProfferService_iface;
2206 static HRESULT WINAPI IServiceProviderImpl_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppvObj)
2208 IServiceProviderImpl *This = impl_from_IServiceProvider(iface);
2210 if (IsEqualIID(riid, &IID_IUnknown) ||
2211 IsEqualIID(riid, &IID_IServiceProvider))
2218 IServiceProvider_AddRef(iface);
2219 /* native uses redefined IID_IServiceProvider symbol, so we can't compare pointers */
2220 if (IsEqualIID(riid, &IID_IServiceProvider))
2221 add_call(&trace_got, 1, iface, &IID_IServiceProvider, 0, 0, 0);
2225 return E_NOINTERFACE;
2228 static ULONG WINAPI IServiceProviderImpl_AddRef(IServiceProvider *iface)
2230 IServiceProviderImpl *This = impl_from_IServiceProvider(iface);
2231 return InterlockedIncrement(&This->ref);
2234 static ULONG WINAPI IServiceProviderImpl_Release(IServiceProvider *iface)
2236 IServiceProviderImpl *This = impl_from_IServiceProvider(iface);
2237 ULONG ref = InterlockedDecrement(&This->ref);
2241 HeapFree(GetProcessHeap(), 0, This);
2247 static HRESULT WINAPI IServiceProviderImpl_QueryService(
2248 IServiceProvider *iface, REFGUID service, REFIID riid, void **ppv)
2250 /* native uses redefined pointer for IID_IOleCommandTarget, not one from uuid.lib */
2251 if (IsEqualIID(riid, &IID_IOleCommandTarget))
2253 add_call(&trace_got, 2, iface, service, &IID_IOleCommandTarget, 0, 0);
2254 *ppv = IOleCommandTargetImpl_Construct();
2256 if (IsEqualIID(riid, &IID_IProfferService))
2258 if (IsEqualIID(service, &IID_IProfferService))
2259 add_call(&trace_got, 2, &IID_IProfferService, &IID_IProfferService, 0, 0, 0);
2260 *ppv = IProfferServiceImpl_Construct();
2265 static const IServiceProviderVtbl IServiceProviderImpl_Vtbl =
2267 IServiceProviderImpl_QueryInterface,
2268 IServiceProviderImpl_AddRef,
2269 IServiceProviderImpl_Release,
2270 IServiceProviderImpl_QueryService
2273 static void test_IUnknown_QueryServiceExec(void)
2275 IServiceProvider *provider = IServiceProviderImpl_Construct();
2276 static const GUID dummy_serviceid = { 0xdeadbeef };
2277 static const GUID dummy_groupid = { 0xbeefbeef };
2278 call_trace_t trace_expected;
2281 /* on <=W2K platforms same ordinal used for another export with different
2282 prototype, so skipping using this indirect condition */
2283 if (is_win2k_and_lower)
2285 win_skip("IUnknown_QueryServiceExec is not available\n");
2289 /* null source pointer */
2290 hr = pIUnknown_QueryServiceExec(NULL, &dummy_serviceid, &dummy_groupid, 0, 0, 0, 0);
2291 ok(hr == E_FAIL, "got 0x%08x\n", hr);
2294 IUnknown_QueryServiceExec( ptr1, serviceid, groupid, arg1, arg2, arg3, arg4);
2295 -> IUnknown_QueryInterface( ptr1, &IID_IServiceProvider, &prov );
2296 -> IServiceProvider_QueryService( prov, serviceid, &IID_IOleCommandTarget, &obj );
2297 -> IOleCommandTarget_Exec( obj, groupid, arg1, arg2, arg3, arg4 );
2299 init_call_trace(&trace_expected);
2301 add_call(&trace_expected, 1, provider, &IID_IServiceProvider, 0, 0, 0);
2302 add_call(&trace_expected, 2, provider, &dummy_serviceid, &IID_IOleCommandTarget, 0, 0);
2303 add_call(&trace_expected, 3, &dummy_groupid, (void*)0x1, (void*)0x2, (void*)0x3, (void*)0x4);
2305 init_call_trace(&trace_got);
2306 hr = pIUnknown_QueryServiceExec((IUnknown*)provider, &dummy_serviceid, &dummy_groupid, 0x1, 0x2, (void*)0x3, (void*)0x4);
2307 ok(hr == S_OK, "got 0x%08x\n", hr);
2309 ok_trace(&trace_expected, &trace_got);
2311 free_call_trace(&trace_expected);
2312 free_call_trace(&trace_got);
2314 IServiceProvider_Release(provider);
2318 static HRESULT WINAPI IProfferServiceImpl_QueryInterface(IProfferService *iface, REFIID riid, void **ppvObj)
2320 IProfferServiceImpl *This = impl_from_IProfferService(iface);
2322 if (IsEqualIID(riid, &IID_IUnknown) ||
2323 IsEqualIID(riid, &IID_IProfferService))
2327 else if (IsEqualIID(riid, &IID_IServiceProvider))
2329 *ppvObj = IServiceProviderImpl_Construct();
2330 add_call(&trace_got, 1, iface, &IID_IServiceProvider, 0, 0, 0);
2336 IProfferService_AddRef(iface);
2340 return E_NOINTERFACE;
2343 static ULONG WINAPI IProfferServiceImpl_AddRef(IProfferService *iface)
2345 IProfferServiceImpl *This = impl_from_IProfferService(iface);
2346 return InterlockedIncrement(&This->ref);
2349 static ULONG WINAPI IProfferServiceImpl_Release(IProfferService *iface)
2351 IProfferServiceImpl *This = impl_from_IProfferService(iface);
2352 ULONG ref = InterlockedDecrement(&This->ref);
2356 HeapFree(GetProcessHeap(), 0, This);
2362 static HRESULT WINAPI IProfferServiceImpl_ProfferService(IProfferService *iface,
2363 REFGUID service, IServiceProvider *pService, DWORD *pCookie)
2365 *pCookie = 0xdeadbeef;
2366 add_call(&trace_got, 3, service, pService, pCookie, 0, 0);
2370 static HRESULT WINAPI IProfferServiceImpl_RevokeService(IProfferService *iface, DWORD cookie)
2372 add_call(&trace_got, 4, (void*)(DWORD_PTR)cookie, 0, 0, 0, 0);
2376 static const IProfferServiceVtbl IProfferServiceImpl_Vtbl =
2378 IProfferServiceImpl_QueryInterface,
2379 IProfferServiceImpl_AddRef,
2380 IProfferServiceImpl_Release,
2381 IProfferServiceImpl_ProfferService,
2382 IProfferServiceImpl_RevokeService
2385 static void test_IUnknown_ProfferService(void)
2387 IServiceProvider *provider = IServiceProviderImpl_Construct();
2388 IProfferService *proff = IProfferServiceImpl_Construct();
2389 static const GUID dummy_serviceid = { 0xdeadbeef };
2390 call_trace_t trace_expected;
2394 /* on <=W2K platforms same ordinal used for another export with different
2395 prototype, so skipping using this indirect condition */
2396 if (is_win2k_and_lower)
2398 win_skip("IUnknown_ProfferService is not available\n");
2402 /* null source pointer */
2403 hr = pIUnknown_ProfferService(NULL, &dummy_serviceid, 0, 0);
2404 ok(hr == E_FAIL, "got 0x%08x\n", hr);
2407 IUnknown_ProfferService( ptr1, serviceid, arg1, arg2);
2408 -> IUnknown_QueryInterface( ptr1, &IID_IServiceProvider, &provider );
2409 -> IServiceProvider_QueryService( provider, &IID_IProfferService, &IID_IProfferService, &proffer );
2411 if (service pointer not null):
2412 -> IProfferService_ProfferService( proffer, serviceid, arg1, arg2 );
2414 -> IProfferService_RevokeService( proffer, *arg2 );
2416 init_call_trace(&trace_expected);
2418 add_call(&trace_expected, 1, proff, &IID_IServiceProvider, 0, 0, 0);
2419 add_call(&trace_expected, 2, &IID_IProfferService, &IID_IProfferService, 0, 0, 0);
2420 add_call(&trace_expected, 3, &dummy_serviceid, provider, &cookie, 0, 0);
2422 init_call_trace(&trace_got);
2424 hr = pIUnknown_ProfferService((IUnknown*)proff, &dummy_serviceid, provider, &cookie);
2425 ok(hr == S_OK, "got 0x%08x\n", hr);
2426 ok(cookie == 0xdeadbeef, "got %x\n", cookie);
2428 ok_trace(&trace_expected, &trace_got);
2429 free_call_trace(&trace_got);
2430 free_call_trace(&trace_expected);
2432 /* same with ::Revoke path */
2433 init_call_trace(&trace_expected);
2435 add_call(&trace_expected, 1, proff, &IID_IServiceProvider, 0, 0, 0);
2436 add_call(&trace_expected, 2, &IID_IProfferService, &IID_IProfferService, 0, 0, 0);
2437 add_call(&trace_expected, 4, (void*)(DWORD_PTR)cookie, 0, 0, 0, 0);
2439 init_call_trace(&trace_got);
2440 ok(cookie != 0, "got %x\n", cookie);
2441 hr = pIUnknown_ProfferService((IUnknown*)proff, &dummy_serviceid, 0, &cookie);
2442 ok(hr == S_OK, "got 0x%08x\n", hr);
2443 ok(cookie == 0, "got %x\n", cookie);
2444 ok_trace(&trace_expected, &trace_got);
2445 free_call_trace(&trace_got);
2446 free_call_trace(&trace_expected);
2448 IServiceProvider_Release(provider);
2449 IProfferService_Release(proff);
2452 static void test_SHCreateWorkerWindowA(void)
2460 if (is_win2k_and_lower)
2462 win_skip("SHCreateWorkerWindowA not available\n");
2466 hwnd = pSHCreateWorkerWindowA(0, NULL, 0, 0, 0, 0);
2467 ok(hwnd != 0, "expected window\n");
2469 GetClassName(hwnd, classA, 20);
2470 ok(lstrcmpA(classA, "WorkerA") == 0, "expected WorkerA class, got %s\n", classA);
2472 ret = GetWindowLongPtrA(hwnd, 0);
2473 ok(ret == 0, "got %ld\n", ret);
2476 memset(&cliA, 0, sizeof(cliA));
2477 res = GetClassInfoA(GetModuleHandle("shlwapi.dll"), "WorkerA", &cliA);
2478 ok(res, "failed to get class info\n");
2479 ok(cliA.style == 0, "got 0x%08x\n", cliA.style);
2480 ok(cliA.cbClsExtra == 0, "got %d\n", cliA.cbClsExtra);
2481 ok(cliA.cbWndExtra == sizeof(LONG_PTR), "got %d\n", cliA.cbWndExtra);
2482 ok(cliA.lpszMenuName == 0, "got %s\n", cliA.lpszMenuName);
2484 DestroyWindow(hwnd);
2486 /* set extra bytes */
2487 hwnd = pSHCreateWorkerWindowA(0, NULL, 0, 0, 0, 0xdeadbeef);
2488 ok(hwnd != 0, "expected window\n");
2490 GetClassName(hwnd, classA, 20);
2491 ok(lstrcmpA(classA, "WorkerA") == 0, "expected WorkerA class, got %s\n", classA);
2493 ret = GetWindowLongPtrA(hwnd, 0);
2494 ok(ret == 0xdeadbeef, "got %ld\n", ret);
2497 ret = GetWindowLongA(hwnd, GWL_EXSTYLE);
2498 ok(ret == WS_EX_WINDOWEDGE ||
2499 ret == (WS_EX_WINDOWEDGE|WS_EX_LAYOUTRTL) /* systems with RTL locale */, "0x%08lx\n", ret);
2501 DestroyWindow(hwnd);
2503 hwnd = pSHCreateWorkerWindowA(0, NULL, WS_EX_TOOLWINDOW, 0, 0, 0);
2504 ret = GetWindowLongA(hwnd, GWL_EXSTYLE);
2505 ok(ret == (WS_EX_WINDOWEDGE|WS_EX_TOOLWINDOW) ||
2506 ret == (WS_EX_WINDOWEDGE|WS_EX_TOOLWINDOW|WS_EX_LAYOUTRTL) /* systems with RTL locale */, "0x%08lx\n", ret);
2507 DestroyWindow(hwnd);
2510 static HRESULT WINAPI SF_QueryInterface(IShellFolder *iface,
2511 REFIID riid, void **ppv)
2513 /* SHIShellFolder_EnumObjects doesn't QI the object for IShellFolder */
2514 ok(!IsEqualGUID(&IID_IShellFolder, riid),
2515 "Unexpected QI for IShellFolder\n");
2516 return E_NOINTERFACE;
2519 static ULONG WINAPI SF_AddRef(IShellFolder *iface)
2524 static ULONG WINAPI SF_Release(IShellFolder *iface)
2529 static HRESULT WINAPI SF_ParseDisplayName(IShellFolder *iface,
2530 HWND owner, LPBC reserved, LPOLESTR displayName, ULONG *eaten,
2531 LPITEMIDLIST *idl, ULONG *attr)
2533 ok(0, "Didn't expect ParseDisplayName\n");
2537 static HRESULT WINAPI SF_EnumObjects(IShellFolder *iface,
2538 HWND owner, SHCONTF flags, IEnumIDList **enm)
2540 *enm = (IEnumIDList*)0xcafebabe;
2544 static HRESULT WINAPI SF_BindToObject(IShellFolder *iface,
2545 LPCITEMIDLIST idl, LPBC reserved, REFIID riid, void **obj)
2547 ok(0, "Didn't expect BindToObject\n");
2551 static HRESULT WINAPI SF_BindToStorage(IShellFolder *iface,
2552 LPCITEMIDLIST idl, LPBC reserved, REFIID riid, void **obj)
2554 ok(0, "Didn't expect BindToStorage\n");
2558 static HRESULT WINAPI SF_CompareIDs(IShellFolder *iface,
2559 LPARAM lparam, LPCITEMIDLIST idl1, LPCITEMIDLIST idl2)
2561 ok(0, "Didn't expect CompareIDs\n");
2565 static HRESULT WINAPI SF_CreateViewObject(IShellFolder *iface,
2566 HWND owner, REFIID riid, void **out)
2568 ok(0, "Didn't expect CreateViewObject\n");
2572 static HRESULT WINAPI SF_GetAttributesOf(IShellFolder *iface,
2573 UINT cidl, LPCITEMIDLIST *idl, SFGAOF *inOut)
2575 ok(0, "Didn't expect GetAttributesOf\n");
2579 static HRESULT WINAPI SF_GetUIObjectOf(IShellFolder *iface,
2580 HWND owner, UINT cidl, LPCITEMIDLIST *idls, REFIID riid, UINT *inOut,
2583 ok(0, "Didn't expect GetUIObjectOf\n");
2587 static HRESULT WINAPI SF_GetDisplayNameOf(IShellFolder *iface,
2588 LPCITEMIDLIST idl, SHGDNF flags, STRRET *name)
2590 ok(0, "Didn't expect GetDisplayNameOf\n");
2594 static HRESULT WINAPI SF_SetNameOf(IShellFolder *iface,
2595 HWND hwnd, LPCITEMIDLIST idl, LPCOLESTR name, SHGDNF flags,
2596 LPITEMIDLIST *idlOut)
2598 ok(0, "Didn't expect SetNameOf\n");
2602 static IShellFolderVtbl ShellFolderVtbl = {
2606 SF_ParseDisplayName,
2611 SF_CreateViewObject,
2614 SF_GetDisplayNameOf,
2618 static IShellFolder ShellFolder = { &ShellFolderVtbl };
2620 static void test_SHIShellFolder_EnumObjects(void)
2624 IShellFolder *folder;
2626 if(!pSHIShellFolder_EnumObjects || is_win2k_and_lower){
2627 win_skip("SHIShellFolder_EnumObjects not available\n");
2632 /* NULL object crashes on Windows */
2633 pSHIShellFolder_EnumObjects(NULL, NULL, 0, NULL);
2636 /* SHIShellFolder_EnumObjects doesn't QI the object for IShellFolder */
2637 enm = (IEnumIDList*)0xdeadbeef;
2638 hres = pSHIShellFolder_EnumObjects(&ShellFolder, NULL, 0, &enm);
2639 ok(hres == S_OK, "SHIShellFolder_EnumObjects failed: 0x%08x\n", hres);
2640 ok(enm == (IEnumIDList*)0xcafebabe, "Didn't get expected enumerator location, instead: %p\n", enm);
2642 /* SHIShellFolder_EnumObjects isn't strict about the IShellFolder object */
2643 hres = pSHGetDesktopFolder(&folder);
2644 ok(hres == S_OK, "SHGetDesktopFolder failed: 0x%08x\n", hres);
2647 hres = pSHIShellFolder_EnumObjects(folder, NULL, 0, &enm);
2648 ok(hres == S_OK, "SHIShellFolder_EnumObjects failed: 0x%08x\n", hres);
2649 ok(enm != NULL, "Didn't get an enumerator\n");
2651 IEnumIDList_Release(enm);
2653 IShellFolder_Release(folder);
2656 static void write_inifile(LPCWSTR filename)
2661 static const char data[] =
2664 "AnotherKey=asdf\r\n";
2666 file = CreateFileW(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
2667 if(file == INVALID_HANDLE_VALUE)
2670 WriteFile(file, data, sizeof(data), &written, NULL);
2675 #define verify_inifile(f, e) r_verify_inifile(__LINE__, f, e)
2676 static void r_verify_inifile(unsigned l, LPCWSTR filename, LPCSTR exp)
2682 file = CreateFileW(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
2683 if(file == INVALID_HANDLE_VALUE)
2686 ReadFile(file, buf, sizeof(buf) * sizeof(CHAR), &read, NULL);
2691 ok_(__FILE__,l)(!strcmp(buf, exp), "Expected:\n%s\nGot:\n%s\n", exp,
2695 static void test_SHGetIniString(void)
2698 WCHAR out[64] = {0};
2700 static const WCHAR TestAppW[] = {'T','e','s','t','A','p','p',0};
2701 static const WCHAR TestIniW[] = {'C',':','\\','t','e','s','t','.','i','n','i',0};
2702 static const WCHAR AKeyW[] = {'A','K','e','y',0};
2703 static const WCHAR AnotherKeyW[] = {'A','n','o','t','h','e','r','K','e','y',0};
2704 static const WCHAR JunkKeyW[] = {'J','u','n','k','K','e','y',0};
2706 if(!pSHGetIniStringW || is_win2k_and_lower){
2707 win_skip("SHGetIniStringW is not available\n");
2711 write_inifile(TestIniW);
2714 /* these crash on Windows */
2715 pSHGetIniStringW(NULL, NULL, NULL, 0, NULL);
2716 pSHGetIniStringW(NULL, AKeyW, out, sizeof(out), TestIniW);
2717 pSHGetIniStringW(TestAppW, AKeyW, NULL, sizeof(out), TestIniW);
2720 ret = pSHGetIniStringW(TestAppW, AKeyW, out, 0, TestIniW);
2721 ok(ret == 0, "SHGetIniStringW should have given 0, instead: %d\n", ret);
2723 /* valid arguments */
2724 ret = pSHGetIniStringW(TestAppW, NULL, out, sizeof(out), TestIniW);
2725 ok(broken(ret == 0) || /* win 98 */
2726 ret == 4, "SHGetIniStringW should have given 4, instead: %d\n", ret);
2727 ok(!lstrcmpW(out, AKeyW), "Expected %s, got: %s\n",
2728 wine_dbgstr_w(AKeyW), wine_dbgstr_w(out));
2730 ret = pSHGetIniStringW(TestAppW, AKeyW, out, sizeof(out), TestIniW);
2731 ok(broken(ret == 0) || /* win 98 */
2732 ret == 1, "SHGetIniStringW should have given 1, instead: %d\n", ret);
2733 ok(broken(*out == 0) || /*win 98 */
2734 !strcmp_wa(out, "1"), "Expected L\"1\", got: %s\n", wine_dbgstr_w(out));
2736 ret = pSHGetIniStringW(TestAppW, AnotherKeyW, out, sizeof(out), TestIniW);
2737 ok(broken(ret == 0) || /* win 98 */
2738 ret == 4, "SHGetIniStringW should have given 4, instead: %d\n", ret);
2739 ok(broken(*out == 0) || /* win 98 */
2740 !strcmp_wa(out, "asdf"), "Expected L\"asdf\", got: %s\n", wine_dbgstr_w(out));
2742 ret = pSHGetIniStringW(TestAppW, JunkKeyW, out, sizeof(out), TestIniW);
2743 ok(ret == 0, "SHGetIniStringW should have given 0, instead: %d\n", ret);
2744 ok(*out == 0, "Expected L\"\", got: %s\n", wine_dbgstr_w(out));
2746 DeleteFileW(TestIniW);
2749 static void test_SHSetIniString(void)
2753 static const WCHAR TestAppW[] = {'T','e','s','t','A','p','p',0};
2754 static const WCHAR AnotherAppW[] = {'A','n','o','t','h','e','r','A','p','p',0};
2755 static const WCHAR TestIniW[] = {'C',':','\\','t','e','s','t','.','i','n','i',0};
2756 static const WCHAR AKeyW[] = {'A','K','e','y',0};
2757 static const WCHAR NewKeyW[] = {'N','e','w','K','e','y',0};
2758 static const WCHAR AValueW[] = {'A','V','a','l','u','e',0};
2760 if(!pSHSetIniStringW || is_win2k_and_lower){
2761 win_skip("SHSetIniStringW is not available\n");
2765 write_inifile(TestIniW);
2767 ret = pSHSetIniStringW(TestAppW, AKeyW, AValueW, TestIniW);
2768 ok(ret == TRUE, "SHSetIniStringW should not have failed\n");
2769 todo_wine /* wine sticks an extra \r\n at the end of the file */
2770 verify_inifile(TestIniW, "[TestApp]\r\nAKey=AValue\r\nAnotherKey=asdf\r\n");
2772 ret = pSHSetIniStringW(TestAppW, AKeyW, NULL, TestIniW);
2773 ok(ret == TRUE, "SHSetIniStringW should not have failed\n");
2774 verify_inifile(TestIniW, "[TestApp]\r\nAnotherKey=asdf\r\n");
2776 ret = pSHSetIniStringW(AnotherAppW, NewKeyW, AValueW, TestIniW);
2777 ok(ret == TRUE, "SHSetIniStringW should not have failed\n");
2778 verify_inifile(TestIniW, "[TestApp]\r\nAnotherKey=asdf\r\n[AnotherApp]\r\nNewKey=AValue\r\n");
2780 ret = pSHSetIniStringW(TestAppW, NULL, AValueW, TestIniW);
2781 ok(ret == TRUE, "SHSetIniStringW should not have failed\n");
2782 verify_inifile(TestIniW, "[AnotherApp]\r\nNewKey=AValue\r\n");
2784 DeleteFileW(TestIniW);
2787 enum _shellkey_flags {
2788 SHKEY_Root_HKCU = 0x1,
2789 SHKEY_Root_HKLM = 0x2,
2790 SHKEY_Key_Explorer = 0x00,
2791 SHKEY_Key_Shell = 0x10,
2792 SHKEY_Key_ShellNoRoam = 0x20,
2793 SHKEY_Key_Classes = 0x30,
2794 SHKEY_Subkey_Default = 0x0000,
2795 SHKEY_Subkey_ResourceName = 0x1000,
2796 SHKEY_Subkey_Handlers = 0x2000,
2797 SHKEY_Subkey_Associations = 0x3000,
2798 SHKEY_Subkey_Volatile = 0x4000,
2799 SHKEY_Subkey_MUICache = 0x5000,
2800 SHKEY_Subkey_FileExts = 0x6000
2803 static void test_SHGetShellKey(void)
2805 static const WCHAR ShellFoldersW[] = { 'S','h','e','l','l',' ','F','o','l','d','e','r','s',0 };
2806 static const WCHAR WineTestW[] = { 'W','i','n','e','T','e','s','t',0 };
2808 void *pPathBuildRootW = GetProcAddress(hShlwapi, "PathBuildRootW");
2809 DWORD *alloc_data, data, size;
2813 if (!pSHGetShellKey)
2815 win_skip("SHGetShellKey(ordinal 491) isn't available\n");
2820 if (pPathBuildRootW && pPathBuildRootW == pSHGetShellKey)
2822 win_skip("SHGetShellKey(ordinal 491) used for PathBuildRootW\n");
2826 if (is_win9x || is_win2k_and_lower)
2828 win_skip("Ordinal 491 used for another call, skipping SHGetShellKey tests\n");
2832 /* Vista+ limits SHKEY enumeration values */
2833 SetLastError(0xdeadbeef);
2834 hkey = pSHGetShellKey(SHKEY_Key_Explorer, ShellFoldersW, FALSE);
2837 /* Tests not working on Vista+ */
2840 hkey = pSHGetShellKey(SHKEY_Root_HKLM|SHKEY_Key_Classes, NULL, FALSE);
2841 ok(hkey != NULL, "hkey = NULL\n");
2845 hkey = pSHGetShellKey(SHKEY_Root_HKCU|SHKEY_Key_Explorer, ShellFoldersW, FALSE);
2846 ok(hkey != NULL, "hkey = NULL\n");
2849 hkey = pSHGetShellKey(SHKEY_Root_HKLM|SHKEY_Key_Explorer, ShellFoldersW, FALSE);
2850 ok(hkey != NULL, "hkey = NULL\n");
2853 hkey = pSHGetShellKey(SHKEY_Root_HKLM, WineTestW, FALSE);
2854 ok(hkey == NULL, "hkey != NULL\n");
2856 hkey = pSHGetShellKey(SHKEY_Root_HKLM, NULL, FALSE);
2857 ok(hkey != NULL, "Can't open key\n");
2858 ok(SUCCEEDED(RegDeleteKeyW(hkey, WineTestW)), "Can't delete key\n");
2861 hkey = pSHGetShellKey(SHKEY_Root_HKLM, WineTestW, TRUE);
2862 if (!hkey && GetLastError() == ERROR_ACCESS_DENIED)
2864 skip("Not authorized to create keys\n");
2867 ok(hkey != NULL, "Can't create key\n");
2870 if (!pSKGetValueW || !pSKSetValueW || !pSKDeleteValueW || !pSKAllocValueW)
2872 win_skip("SKGetValueW, SKSetValueW, SKDeleteValueW or SKAllocValueW not available\n");
2876 size = sizeof(data);
2877 hres = pSKGetValueW(SHKEY_Root_HKLM, WineTestW, NULL, NULL, &data, &size);
2878 ok(hres == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "hres = %x\n", hres);
2881 hres = pSKSetValueW(SHKEY_Root_HKLM, WineTestW, NULL, REG_DWORD, &data, sizeof(DWORD));
2882 ok(hres == S_OK, "hres = %x\n", hres);
2885 hres = pSKGetValueW(SHKEY_Root_HKLM, WineTestW, NULL, NULL, NULL, &size);
2886 ok(hres == S_OK, "hres = %x\n", hres);
2887 ok(size == sizeof(DWORD), "size = %d\n", size);
2890 hres = pSKGetValueW(SHKEY_Root_HKLM, WineTestW, NULL, NULL, &data, &size);
2891 ok(hres == S_OK, "hres = %x\n", hres);
2892 ok(size == sizeof(DWORD), "size = %d\n", size);
2893 ok(data == 1234, "data = %d\n", data);
2895 hres = pSKAllocValueW(SHKEY_Root_HKLM, WineTestW, NULL, NULL, (void**)&alloc_data, &size);
2896 ok(hres == S_OK, "hres= %x\n", hres);
2897 ok(size == sizeof(DWORD), "size = %d\n", size);
2898 if (SUCCEEDED(hres))
2900 ok(*alloc_data == 1234, "*alloc_data = %d\n", *alloc_data);
2901 LocalFree(alloc_data);
2904 hres = pSKDeleteValueW(SHKEY_Root_HKLM, WineTestW, NULL);
2905 ok(hres == S_OK, "hres = %x\n", hres);
2907 hres = pSKDeleteValueW(SHKEY_Root_HKLM, WineTestW, NULL);
2908 ok(hres == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "hres = %x\n", hres);
2910 hres = pSKGetValueW(SHKEY_Root_HKLM, WineTestW, NULL, NULL, &data, &size);
2911 ok(hres == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "hres = %x\n", hres);
2913 hkey = pSHGetShellKey(SHKEY_Root_HKLM, NULL, FALSE);
2914 ok(hkey != NULL, "Can't create key\n");
2915 ok(SUCCEEDED(RegDeleteKeyW(hkey, WineTestW)), "Can't delete key\n");
2919 static void init_pointers(void)
2921 #define MAKEFUNC(f, ord) (p##f = (void*)GetProcAddress(hShlwapi, (LPSTR)(ord)))
2922 MAKEFUNC(SHAllocShared, 7);
2923 MAKEFUNC(SHLockShared, 8);
2924 MAKEFUNC(SHUnlockShared, 9);
2925 MAKEFUNC(SHFreeShared, 10);
2926 MAKEFUNC(GetAcceptLanguagesA, 14);
2927 MAKEFUNC(SHSetWindowBits, 165);
2928 MAKEFUNC(SHSetParentHwnd, 167);
2929 MAKEFUNC(ConnectToConnectionPoint, 168);
2930 MAKEFUNC(SHSearchMapInt, 198);
2931 MAKEFUNC(SHCreateWorkerWindowA, 257);
2932 MAKEFUNC(GUIDFromStringA, 269);
2933 MAKEFUNC(SHPackDispParams, 282);
2934 MAKEFUNC(IConnectionPoint_InvokeWithCancel, 283);
2935 MAKEFUNC(IConnectionPoint_SimpleInvoke, 284);
2936 MAKEFUNC(SHGetIniStringW, 294);
2937 MAKEFUNC(SHSetIniStringW, 295);
2938 MAKEFUNC(SHFormatDateTimeA, 353);
2939 MAKEFUNC(SHFormatDateTimeW, 354);
2940 MAKEFUNC(SHIShellFolder_EnumObjects, 404);
2941 MAKEFUNC(SHGetObjectCompatFlags, 476);
2942 MAKEFUNC(IUnknown_QueryServiceExec, 484);
2943 MAKEFUNC(SHGetShellKey, 491);
2944 MAKEFUNC(SHPropertyBag_ReadLONG, 496);
2945 MAKEFUNC(IUnknown_ProfferService, 514);
2946 MAKEFUNC(SKGetValueW, 516);
2947 MAKEFUNC(SKSetValueW, 517);
2948 MAKEFUNC(SKDeleteValueW, 518);
2949 MAKEFUNC(SKAllocValueW, 519);
2953 static void test_SHSetParentHwnd(void)
2955 HWND hwnd, hwnd2, ret;
2958 if (!pSHSetParentHwnd)
2960 win_skip("SHSetParentHwnd not available\n");
2964 hwnd = CreateWindowA("Button", "", WS_VISIBLE, 0, 0, 10, 10, NULL, NULL, NULL, NULL);
2965 ok(hwnd != NULL, "got %p\n", hwnd);
2967 hwnd2 = CreateWindowA("Button", "", WS_VISIBLE | WS_CHILD, 0, 0, 10, 10, hwnd, NULL, NULL, NULL);
2968 ok(hwnd2 != NULL, "got %p\n", hwnd2);
2971 ret = pSHSetParentHwnd(NULL, NULL);
2972 ok(ret == NULL, "got %p\n", ret);
2974 /* set to no parent while already no parent present */
2975 ret = GetParent(hwnd);
2976 ok(ret == NULL, "got %p\n", ret);
2977 style = GetWindowLongA(hwnd, GWL_STYLE);
2978 ok((style & (WS_POPUP|WS_CHILD)) == 0, "got style 0x%08x\n", style);
2979 ret = pSHSetParentHwnd(hwnd, NULL);
2980 ok(ret == NULL, "got %p\n", ret);
2981 style = GetWindowLongA(hwnd, GWL_STYLE);
2982 ok((style & (WS_POPUP|WS_CHILD)) == 0, "got style 0x%08x\n", style);
2984 /* reset to null parent from not null */
2985 ret = GetParent(hwnd2);
2986 ok(ret == hwnd, "got %p\n", ret);
2987 style = GetWindowLongA(hwnd2, GWL_STYLE);
2988 ok((style & (WS_POPUP|WS_CHILD)) == WS_CHILD, "got style 0x%08x\n", style);
2989 ret = pSHSetParentHwnd(hwnd2, NULL);
2990 ok(ret == NULL, "got %p\n", ret);
2991 style = GetWindowLongA(hwnd2, GWL_STYLE);
2992 ok((style & (WS_POPUP|WS_CHILD)) == WS_POPUP, "got style 0x%08x\n", style);
2993 ret = GetParent(hwnd2);
2994 ok(ret == NULL, "got %p\n", ret);
2996 /* set parent back */
2997 style = GetWindowLongA(hwnd2, GWL_STYLE);
2998 SetWindowLongA(hwnd2, GWL_STYLE, style & ~(WS_CHILD|WS_POPUP));
2999 style = GetWindowLongA(hwnd2, GWL_STYLE);
3000 ok((style & (WS_CHILD|WS_POPUP)) == 0, "got 0x%08x\n", style);
3002 ret = pSHSetParentHwnd(hwnd2, hwnd);
3003 todo_wine ok(ret == NULL, "got %p\n", ret);
3005 style = GetWindowLongA(hwnd2, GWL_STYLE);
3006 ok((style & (WS_POPUP|WS_CHILD)) == WS_CHILD, "got style 0x%08x\n", style);
3007 ret = GetParent(hwnd2);
3008 ok(ret == hwnd, "got %p\n", ret);
3010 /* try to set same parent again */
3012 style = GetWindowLongA(hwnd2, GWL_STYLE);
3013 SetWindowLongA(hwnd2, GWL_STYLE, style | WS_POPUP);
3014 ret = pSHSetParentHwnd(hwnd2, hwnd);
3015 todo_wine ok(ret == NULL, "got %p\n", ret);
3016 style = GetWindowLongA(hwnd2, GWL_STYLE);
3017 ok((style & (WS_CHILD|WS_POPUP)) == WS_CHILD, "got 0x%08x\n", style);
3018 ret = GetParent(hwnd2);
3019 ok(ret == hwnd, "got %p\n", ret);
3021 /* without WS_POPUP */
3022 style = GetWindowLongA(hwnd2, GWL_STYLE);
3023 SetWindowLongA(hwnd2, GWL_STYLE, style | ~WS_POPUP);
3024 ret = pSHSetParentHwnd(hwnd2, hwnd);
3025 todo_wine ok(ret == hwnd, "got %p\n", ret);
3026 style = GetWindowLongA(hwnd2, GWL_STYLE);
3027 ok((style & (WS_CHILD|WS_POPUP)) == WS_CHILD, "got 0x%08x\n", style);
3028 ret = GetParent(hwnd2);
3029 ok(ret == hwnd, "got %p\n", ret);
3031 DestroyWindow(hwnd);
3032 DestroyWindow(hwnd2);
3037 hShlwapi = GetModuleHandleA("shlwapi.dll");
3038 is_win2k_and_lower = GetProcAddress(hShlwapi, "StrChrNW") == 0;
3039 is_win9x = GetProcAddress(hShlwapi, (LPSTR)99) == 0; /* StrCpyNXA */
3041 /* SHCreateStreamOnFileEx was introduced in shlwapi v6.0 */
3042 if(!GetProcAddress(hShlwapi, "SHCreateStreamOnFileEx")){
3043 win_skip("Too old shlwapi version\n");
3049 hmlang = LoadLibraryA("mlang.dll");
3050 pLcidToRfc1766A = (void *)GetProcAddress(hmlang, "LcidToRfc1766A");
3052 hshell32 = LoadLibraryA("shell32.dll");
3053 pSHGetDesktopFolder = (void *)GetProcAddress(hshell32, "SHGetDesktopFolder");
3055 test_GetAcceptLanguagesA();
3056 test_SHSearchMapInt();
3057 test_alloc_shared();
3059 test_GetShellSecurityDescriptor();
3060 test_SHPackDispParams();
3061 test_IConnectionPoint();
3062 test_SHPropertyBag_ReadLONG();
3063 test_SHSetWindowBits();
3064 test_SHFormatDateTimeA();
3065 test_SHFormatDateTimeW();
3066 test_SHGetObjectCompatFlags();
3067 test_IUnknown_QueryServiceExec();
3068 test_IUnknown_ProfferService();
3069 test_SHCreateWorkerWindowA();
3070 test_SHIShellFolder_EnumObjects();
3071 test_SHGetIniString();
3072 test_SHSetIniString();
3073 test_SHGetShellKey();
3074 test_SHSetParentHwnd();
3076 FreeLibrary(hshell32);
3077 FreeLibrary(hmlang);