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"
36 /* Function ptrs for ordinal calls */
37 static HMODULE hShlwapi;
38 static BOOL is_win2k_and_lower;
41 static int (WINAPI *pSHSearchMapInt)(const int*,const int*,int,int);
42 static HRESULT (WINAPI *pGetAcceptLanguagesA)(LPSTR,LPDWORD);
44 static HANDLE (WINAPI *pSHAllocShared)(LPCVOID,DWORD,DWORD);
45 static LPVOID (WINAPI *pSHLockShared)(HANDLE,DWORD);
46 static BOOL (WINAPI *pSHUnlockShared)(LPVOID);
47 static BOOL (WINAPI *pSHFreeShared)(HANDLE,DWORD);
48 static HRESULT(WINAPIV *pSHPackDispParams)(DISPPARAMS*,VARIANTARG*,UINT,...);
49 static HRESULT(WINAPI *pIConnectionPoint_SimpleInvoke)(IConnectionPoint*,DISPID,DISPPARAMS*);
50 static HRESULT(WINAPI *pIConnectionPoint_InvokeWithCancel)(IConnectionPoint*,DISPID,DISPPARAMS*,DWORD,DWORD);
51 static HRESULT(WINAPI *pConnectToConnectionPoint)(IUnknown*,REFIID,BOOL,IUnknown*, LPDWORD,IConnectionPoint **);
52 static HRESULT(WINAPI *pSHPropertyBag_ReadLONG)(IPropertyBag *,LPCWSTR,LPLONG);
53 static LONG (WINAPI *pSHSetWindowBits)(HWND, INT, UINT, UINT);
54 static INT (WINAPI *pSHFormatDateTimeA)(const FILETIME UNALIGNED*, DWORD*, LPSTR, UINT);
55 static INT (WINAPI *pSHFormatDateTimeW)(const FILETIME UNALIGNED*, DWORD*, LPWSTR, UINT);
56 static DWORD (WINAPI *pSHGetObjectCompatFlags)(IUnknown*, const CLSID*);
57 static BOOL (WINAPI *pGUIDFromStringA)(LPSTR, CLSID *);
58 static HRESULT (WINAPI *pIUnknown_QueryServiceExec)(IUnknown*, REFIID, const GUID*, DWORD, DWORD, VARIANT*, VARIANT*);
59 static HRESULT (WINAPI *pIUnknown_ProfferService)(IUnknown*, REFGUID, IServiceProvider*, DWORD*);
60 static HWND (WINAPI *pSHCreateWorkerWindowA)(LONG, HWND, DWORD, DWORD, HMENU, LONG_PTR);
61 static HRESULT (WINAPI *pSHIShellFolder_EnumObjects)(LPSHELLFOLDER, HWND, SHCONTF, IEnumIDList**);
62 static DWORD (WINAPI *pSHGetIniStringW)(LPCWSTR, LPCWSTR, LPWSTR, DWORD, LPCWSTR);
63 static BOOL (WINAPI *pSHSetIniStringW)(LPCWSTR, LPCWSTR, LPCWSTR, LPCWSTR);
64 static HKEY (WINAPI *pSHGetShellKey)(DWORD, LPCWSTR, BOOL);
65 static HRESULT (WINAPI *pSKGetValueW)(DWORD, LPCWSTR, LPCWSTR, DWORD*, void*, DWORD*);
66 static HRESULT (WINAPI *pSKSetValueW)(DWORD, LPCWSTR, LPCWSTR, DWORD, void*, DWORD);
67 static HRESULT (WINAPI *pSKDeleteValueW)(DWORD, LPCWSTR, LPCWSTR);
68 static HRESULT (WINAPI *pSKAllocValueW)(DWORD, LPCWSTR, LPCWSTR, DWORD*, void**, DWORD*);
70 static HMODULE hmlang;
71 static HRESULT (WINAPI *pLcidToRfc1766A)(LCID, LPSTR, INT);
73 static HMODULE hshell32;
74 static HRESULT (WINAPI *pSHGetDesktopFolder)(IShellFolder**);
76 static const CHAR ie_international[] = {
77 'S','o','f','t','w','a','r','e','\\',
78 'M','i','c','r','o','s','o','f','t','\\',
79 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
80 'I','n','t','e','r','n','a','t','i','o','n','a','l',0};
81 static const CHAR acceptlanguage[] = {
82 'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0};
84 static int strcmp_wa(LPCWSTR strw, const char *stra)
87 WideCharToMultiByte(CP_ACP, 0, strw, -1, buf, sizeof(buf), NULL, NULL);
88 return lstrcmpA(stra, buf);
102 static void init_call_trace(call_trace_t *ctrace)
106 ctrace->calls = HeapAlloc(GetProcessHeap(), 0, sizeof(call_entry_t) * ctrace->alloc);
109 static void free_call_trace(const call_trace_t *ctrace)
111 HeapFree(GetProcessHeap(), 0, ctrace->calls);
114 static void add_call(call_trace_t *ctrace, int id, const void *arg0,
115 const void *arg1, const void *arg2, const void *arg3, const void *arg4)
126 if (ctrace->count == ctrace->alloc)
129 ctrace->calls = HeapReAlloc(GetProcessHeap(),0, ctrace->calls, ctrace->alloc*sizeof(call_entry_t));
132 ctrace->calls[ctrace->count++] = call;
135 static void ok_trace_(call_trace_t *texpected, call_trace_t *tgot, int line)
137 if (texpected->count == tgot->count)
141 for (i = 0; i < texpected->count; i++)
143 call_entry_t *expected = &texpected->calls[i];
144 call_entry_t *got = &tgot->calls[i];
147 ok_(__FILE__, line)(expected->id == got->id, "got different ids %d: %d, %d\n", i+1, expected->id, got->id);
149 for (j = 0; j < 5; j++)
151 ok_(__FILE__, line)(expected->args[j] == got->args[j], "got different args[%d] for %d: %p, %p\n", j, i+1,
152 expected->args[j], got->args[j]);
157 ok_(__FILE__, line)(0, "traces length mismatch\n");
160 #define ok_trace(a, b) ok_trace_(a, b, __LINE__)
162 /* trace of actually made calls */
163 static call_trace_t trace_got;
165 static void test_GetAcceptLanguagesA(void)
167 static LPCSTR table[] = {"de,en-gb;q=0.7,en;q=0.3",
168 "de,en;q=0.3,en-gb;q=0.7", /* sorting is ignored */
169 "winetest", /* content is ignored */
179 LONG res_query = ERROR_SUCCESS;
182 DWORD maxlen = sizeof(buffer) - 2;
188 if (!pGetAcceptLanguagesA) {
189 win_skip("GetAcceptLanguagesA is not available\n");
193 lcid = GetUserDefaultLCID();
195 /* Get the original Value */
196 lres = RegOpenKeyA(HKEY_CURRENT_USER, ie_international, &hroot);
198 skip("RegOpenKey(%s) failed: %d\n", ie_international, lres);
201 len = sizeof(original);
203 res_query = RegQueryValueExA(hroot, acceptlanguage, 0, NULL, (PBYTE)original, &len);
205 RegDeleteValue(hroot, acceptlanguage);
207 /* Some windows versions use "lang-COUNTRY" as default */
208 memset(language, 0, sizeof(language));
209 len = GetLocaleInfoA(lcid, LOCALE_SISO639LANGNAME, language, sizeof(language));
212 lstrcat(language, "-");
213 memset(buffer, 0, sizeof(buffer));
214 len = GetLocaleInfoA(lcid, LOCALE_SISO3166CTRYNAME, buffer, sizeof(buffer) - len - 1);
215 lstrcat(language, buffer);
219 /* LOCALE_SNAME has additional parts in some languages. Try only as last chance */
220 memset(language, 0, sizeof(language));
221 len = GetLocaleInfoA(lcid, LOCALE_SNAME, language, sizeof(language));
224 /* get the default value */
226 memset(buffer, '#', maxlen);
228 hr = pGetAcceptLanguagesA( buffer, &len);
231 win_skip("GetAcceptLanguagesA failed with 0x%x\n", hr);
232 goto restore_original;
235 if (lstrcmpA(buffer, language)) {
236 /* some windows versions use "lang" or "lang-country" as default */
238 if (pLcidToRfc1766A) {
239 hr = pLcidToRfc1766A(lcid, language, sizeof(language));
240 ok(hr == S_OK, "LcidToRfc1766A returned 0x%x and %s\n", hr, language);
244 ok(!lstrcmpA(buffer, language),
245 "have '%s' (searching for '%s')\n", language, buffer);
247 if (lstrcmpA(buffer, language)) {
248 win_skip("no more ideas, how to build the default language '%s'\n", buffer);
249 goto restore_original;
252 trace("detected default: %s\n", language);
253 while ((entry = table[i])) {
255 exactsize = lstrlenA(entry);
257 lres = RegSetValueExA(hroot, acceptlanguage, 0, REG_SZ, (const BYTE *) entry, exactsize + 1);
258 ok(!lres, "got %d for RegSetValueExA: %s\n", lres, entry);
260 /* len includes space for the terminating 0 before vista/w2k8 */
262 memset(buffer, '#', maxlen);
264 hr = pGetAcceptLanguagesA( buffer, &len);
265 ok(((hr == E_INVALIDARG) && (len == 0)) ||
267 ((len == exactsize) || (len == exactsize+1)) &&
268 !lstrcmpA(buffer, entry)),
269 "+2_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
272 memset(buffer, '#', maxlen);
274 hr = pGetAcceptLanguagesA( buffer, &len);
275 ok(((hr == E_INVALIDARG) && (len == 0)) ||
277 ((len == exactsize) || (len == exactsize+1)) &&
278 !lstrcmpA(buffer, entry)),
279 "+1_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
282 memset(buffer, '#', maxlen);
284 hr = pGetAcceptLanguagesA( buffer, &len);
286 /* There is no space for the string in the registry.
287 When the buffer is large enough, the default language is returned
289 When the buffer is too small for that fallback, win7_32 and w2k8_64
290 and above fail with HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), but
291 recent os succeed and return a partial result while
292 older os succeed and overflow the buffer */
294 ok(((hr == E_INVALIDARG) && (len == 0)) ||
295 (((hr == S_OK) && !lstrcmpA(buffer, language) && (len == lstrlenA(language))) ||
296 ((hr == S_OK) && !memcmp(buffer, language, len)) ||
297 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len)),
298 "==_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
302 memset(buffer, '#', maxlen);
304 hr = pGetAcceptLanguagesA( buffer, &len);
305 ok(((hr == E_INVALIDARG) && (len == 0)) ||
306 (((hr == S_OK) && !lstrcmpA(buffer, language) && (len == lstrlenA(language))) ||
307 ((hr == S_OK) && !memcmp(buffer, language, len)) ||
308 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len)),
309 "-1_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
313 memset(buffer, '#', maxlen);
315 hr = pGetAcceptLanguagesA( buffer, &len);
316 ok(((hr == E_INVALIDARG) && (len == 0)) ||
317 (((hr == S_OK) && !lstrcmpA(buffer, language) && (len == lstrlenA(language))) ||
318 ((hr == S_OK) && !memcmp(buffer, language, len)) ||
319 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len)),
320 "=1_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
323 hr = pGetAcceptLanguagesA( NULL, &len);
325 /* w2k3 and below: E_FAIL and untouched len,
326 since w2k8: S_OK and needed size (excluding 0) */
327 ok( ((hr == S_OK) && (len == exactsize)) ||
328 ((hr == E_FAIL) && (len == maxlen)),
329 "NULL,max #%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
334 /* without a value in the registry, a default language is returned */
335 RegDeleteValue(hroot, acceptlanguage);
338 memset(buffer, '#', maxlen);
340 hr = pGetAcceptLanguagesA( buffer, &len);
341 ok( ((hr == S_OK) && (len == lstrlenA(language))),
342 "max: got 0x%x with %d and %s (expected S_OK with %d and '%s'\n",
343 hr, len, buffer, lstrlenA(language), language);
346 memset(buffer, '#', maxlen);
348 hr = pGetAcceptLanguagesA( buffer, &len);
349 ok( (((hr == S_OK) || (hr == E_INVALIDARG)) && !memcmp(buffer, language, len)) ||
350 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len),
351 "=2: got 0x%x with %d and %s\n", hr, len, buffer);
354 memset(buffer, '#', maxlen);
356 hr = pGetAcceptLanguagesA( buffer, &len);
357 /* When the buffer is too small, win7_32 and w2k8_64 and above fail with
358 HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), other versions suceed
359 and return a partial 0 terminated result while other versions
360 fail with E_INVALIDARG and return a partial unterminated result */
361 ok( (((hr == S_OK) || (hr == E_INVALIDARG)) && !memcmp(buffer, language, len)) ||
362 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len),
363 "=1: got 0x%x with %d and %s\n", hr, len, buffer);
366 memset(buffer, '#', maxlen);
368 hr = pGetAcceptLanguagesA( buffer, &len);
369 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
370 ok((hr == E_FAIL) || (hr == E_INVALIDARG),
371 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr);
373 memset(buffer, '#', maxlen);
375 hr = pGetAcceptLanguagesA( buffer, NULL);
376 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
377 ok((hr == E_FAIL) || (hr == E_INVALIDARG),
378 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr);
381 hr = pGetAcceptLanguagesA( NULL, NULL);
382 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
383 ok((hr == E_FAIL) || (hr == E_INVALIDARG),
384 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr);
388 len = lstrlenA(original);
389 lres = RegSetValueExA(hroot, acceptlanguage, 0, REG_SZ, (const BYTE *) original, len ? len + 1: 0);
390 ok(!lres, "RegSetValueEx(%s) failed: %d\n", original, lres);
394 RegDeleteValue(hroot, acceptlanguage);
399 static void test_SHSearchMapInt(void)
401 int keys[8], values[8];
404 if (!pSHSearchMapInt)
407 memset(keys, 0, sizeof(keys));
408 memset(values, 0, sizeof(values));
409 keys[0] = 99; values[0] = 101;
411 /* NULL key/value lists crash native, so skip testing them */
414 i = pSHSearchMapInt(keys, values, 1, keys[0]);
415 ok(i == values[0], "Len 1, expected %d, got %d\n", values[0], i);
417 /* Key doesn't exist */
418 i = pSHSearchMapInt(keys, values, 1, 100);
419 ok(i == -1, "Len 1 - bad key, expected -1, got %d\n", i);
421 /* Len = 0 => not found */
422 i = pSHSearchMapInt(keys, values, 0, keys[0]);
423 ok(i == -1, "Len 1 - passed len 0, expected -1, got %d\n", i);
425 /* 2 elements, len = 1 */
426 keys[1] = 98; values[1] = 102;
427 i = pSHSearchMapInt(keys, values, 1, keys[1]);
428 ok(i == -1, "Len 1 - array len 2, expected -1, got %d\n", i);
430 /* 2 elements, len = 2 */
431 i = pSHSearchMapInt(keys, values, 2, keys[1]);
432 ok(i == values[1], "Len 2, expected %d, got %d\n", values[1], i);
434 /* Searches forward */
435 keys[2] = 99; values[2] = 103;
436 i = pSHSearchMapInt(keys, values, 3, keys[0]);
437 ok(i == values[0], "Len 3, expected %d, got %d\n", values[0], i);
440 static void test_alloc_shared(void)
448 procid=GetCurrentProcessId();
449 hmem=pSHAllocShared(NULL,10,procid);
450 ok(hmem!=NULL,"SHAllocShared(NULL...) failed: %u\n", GetLastError());
451 ret = pSHFreeShared(hmem, procid);
452 ok( ret, "SHFreeShared failed: %u\n", GetLastError());
455 hmem=pSHAllocShared(&val,4,procid);
456 ok(hmem!=NULL,"SHAllocShared(NULL...) failed: %u\n", GetLastError());
458 p=pSHLockShared(hmem,procid);
459 ok(p!=NULL,"SHLockShared failed: %u\n", GetLastError());
461 ok(*p==val,"Wrong value in shared memory: %d instead of %d\n",*p,val);
462 ret = pSHUnlockShared(p);
463 ok( ret, "SHUnlockShared failed: %u\n", GetLastError());
465 ret = pSHFreeShared(hmem, procid);
466 ok( ret, "SHFreeShared failed: %u\n", GetLastError());
469 static void test_fdsa(void)
473 DWORD num_items; /* Number of elements inserted */
474 void *mem; /* Ptr to array */
475 DWORD blocks_alloced; /* Number of elements allocated */
476 BYTE inc; /* Number of elements to grow by when we need to expand */
477 BYTE block_size; /* Size in bytes of an element */
478 BYTE flags; /* Flags */
481 BOOL (WINAPI *pFDSA_Initialize)(DWORD block_size, DWORD inc, FDSA_info *info, void *mem,
483 BOOL (WINAPI *pFDSA_Destroy)(FDSA_info *info);
484 DWORD (WINAPI *pFDSA_InsertItem)(FDSA_info *info, DWORD where, const void *block);
485 BOOL (WINAPI *pFDSA_DeleteItem)(FDSA_info *info, DWORD where);
488 int block_size = 10, init_blocks = 4, inc = 2;
492 pFDSA_Initialize = (void *)GetProcAddress(hShlwapi, (LPSTR)208);
493 pFDSA_Destroy = (void *)GetProcAddress(hShlwapi, (LPSTR)209);
494 pFDSA_InsertItem = (void *)GetProcAddress(hShlwapi, (LPSTR)210);
495 pFDSA_DeleteItem = (void *)GetProcAddress(hShlwapi, (LPSTR)211);
497 mem = HeapAlloc(GetProcessHeap(), 0, block_size * init_blocks);
498 memset(&info, 0, sizeof(info));
500 ok(pFDSA_Initialize(block_size, inc, &info, mem, init_blocks), "FDSA_Initialize rets FALSE\n");
501 ok(info.num_items == 0, "num_items = %d\n", info.num_items);
502 ok(info.mem == mem, "mem = %p\n", info.mem);
503 ok(info.blocks_alloced == init_blocks, "blocks_alloced = %d\n", info.blocks_alloced);
504 ok(info.inc == inc, "inc = %d\n", info.inc);
505 ok(info.block_size == block_size, "block_size = %d\n", info.block_size);
506 ok(info.flags == 0, "flags = %d\n", info.flags);
508 ret = pFDSA_InsertItem(&info, 1234, "1234567890");
509 ok(ret == 0, "ret = %d\n", ret);
510 ok(info.num_items == 1, "num_items = %d\n", info.num_items);
511 ok(info.mem == mem, "mem = %p\n", info.mem);
512 ok(info.blocks_alloced == init_blocks, "blocks_alloced = %d\n", info.blocks_alloced);
513 ok(info.inc == inc, "inc = %d\n", info.inc);
514 ok(info.block_size == block_size, "block_size = %d\n", info.block_size);
515 ok(info.flags == 0, "flags = %d\n", info.flags);
517 ret = pFDSA_InsertItem(&info, 1234, "abcdefghij");
518 ok(ret == 1, "ret = %d\n", ret);
520 ret = pFDSA_InsertItem(&info, 1, "klmnopqrst");
521 ok(ret == 1, "ret = %d\n", ret);
523 ret = pFDSA_InsertItem(&info, 0, "uvwxyzABCD");
524 ok(ret == 0, "ret = %d\n", ret);
525 ok(info.mem == mem, "mem = %p\n", info.mem);
526 ok(info.flags == 0, "flags = %d\n", info.flags);
528 /* This next InsertItem will cause shlwapi to allocate its own mem buffer */
529 ret = pFDSA_InsertItem(&info, 0, "EFGHIJKLMN");
530 ok(ret == 0, "ret = %d\n", ret);
531 ok(info.mem != mem, "mem = %p\n", info.mem);
532 ok(info.blocks_alloced == init_blocks + inc, "blocks_alloced = %d\n", info.blocks_alloced);
533 ok(info.flags == 0x1, "flags = %d\n", info.flags);
535 ok(!memcmp(info.mem, "EFGHIJKLMNuvwxyzABCD1234567890klmnopqrstabcdefghij", 50), "mem %s\n", (char*)info.mem);
537 ok(pFDSA_DeleteItem(&info, 2), "rets FALSE\n");
538 ok(info.mem != mem, "mem = %p\n", info.mem);
539 ok(info.blocks_alloced == init_blocks + inc, "blocks_alloced = %d\n", info.blocks_alloced);
540 ok(info.flags == 0x1, "flags = %d\n", info.flags);
542 ok(!memcmp(info.mem, "EFGHIJKLMNuvwxyzABCDklmnopqrstabcdefghij", 40), "mem %s\n", (char*)info.mem);
544 ok(pFDSA_DeleteItem(&info, 3), "rets FALSE\n");
545 ok(info.mem != mem, "mem = %p\n", info.mem);
546 ok(info.blocks_alloced == init_blocks + inc, "blocks_alloced = %d\n", info.blocks_alloced);
547 ok(info.flags == 0x1, "flags = %d\n", info.flags);
549 ok(!memcmp(info.mem, "EFGHIJKLMNuvwxyzABCDklmnopqrst", 30), "mem %s\n", (char*)info.mem);
551 ok(!pFDSA_DeleteItem(&info, 4), "does not ret FALSE\n");
553 /* As shlwapi has allocated memory internally, Destroy will ret FALSE */
554 ok(!pFDSA_Destroy(&info), "FDSA_Destroy does not ret FALSE\n");
557 /* When Initialize is called with inc = 0, set it to 1 */
558 ok(pFDSA_Initialize(block_size, 0, &info, mem, init_blocks), "FDSA_Initialize rets FALSE\n");
559 ok(info.inc == 1, "inc = %d\n", info.inc);
561 /* This time, because shlwapi hasn't had to allocate memory
562 internally, Destroy rets non-zero */
563 ok(pFDSA_Destroy(&info), "FDSA_Destroy rets FALSE\n");
566 HeapFree(GetProcessHeap(), 0, mem);
570 typedef struct SHELL_USER_SID {
571 SID_IDENTIFIER_AUTHORITY sidAuthority;
574 } SHELL_USER_SID, *PSHELL_USER_SID;
575 typedef struct SHELL_USER_PERMISSION {
576 SHELL_USER_SID susID;
581 DWORD dwInheritAccessMask;
582 } SHELL_USER_PERMISSION, *PSHELL_USER_PERMISSION;
583 static void test_GetShellSecurityDescriptor(void)
585 SHELL_USER_PERMISSION supCurrentUserFull = {
586 { {SECURITY_NULL_SID_AUTHORITY}, 0, 0 },
587 ACCESS_ALLOWED_ACE_TYPE, FALSE,
589 #define MY_INHERITANCE 0xBE /* invalid value to proof behavior */
590 SHELL_USER_PERMISSION supEveryoneDenied = {
591 { {SECURITY_WORLD_SID_AUTHORITY}, SECURITY_WORLD_RID, 0 },
592 ACCESS_DENIED_ACE_TYPE, TRUE,
593 GENERIC_WRITE, MY_INHERITANCE | 0xDEADBA00, GENERIC_READ };
594 PSHELL_USER_PERMISSION rgsup[2] = {
595 &supCurrentUserFull, &supEveryoneDenied,
597 SECURITY_DESCRIPTOR* psd;
598 SECURITY_DESCRIPTOR* (WINAPI*pGetShellSecurityDescriptor)(PSHELL_USER_PERMISSION*,int);
599 void *pChrCmpIW = GetProcAddress(hShlwapi, "ChrCmpIW");
601 pGetShellSecurityDescriptor=(void*)GetProcAddress(hShlwapi,(char*)475);
603 if(!pGetShellSecurityDescriptor)
605 win_skip("GetShellSecurityDescriptor not available\n");
609 if(pChrCmpIW && pChrCmpIW == pGetShellSecurityDescriptor) /* win2k */
611 win_skip("Skipping for GetShellSecurityDescriptor, same ordinal used for ChrCmpIW\n");
615 psd = pGetShellSecurityDescriptor(NULL, 2);
617 broken(psd==INVALID_HANDLE_VALUE), /* IE5 */
618 "GetShellSecurityDescriptor should fail\n");
619 psd = pGetShellSecurityDescriptor(rgsup, 0);
620 ok(psd==NULL, "GetShellSecurityDescriptor should fail, got %p\n", psd);
622 SetLastError(0xdeadbeef);
623 psd = pGetShellSecurityDescriptor(rgsup, 2);
624 if (psd == NULL && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
626 /* The previous calls to GetShellSecurityDescriptor don't set the last error */
627 win_skip("GetShellSecurityDescriptor is not implemented\n");
630 if (psd == INVALID_HANDLE_VALUE)
632 win_skip("GetShellSecurityDescriptor is broken on IE5\n");
635 ok(psd!=NULL, "GetShellSecurityDescriptor failed\n");
638 BOOL bHasDacl = FALSE, bDefaulted;
641 SECURITY_DESCRIPTOR_CONTROL control;
643 ok(IsValidSecurityDescriptor(psd), "returned value is not valid SD\n");
645 ok(GetSecurityDescriptorControl(psd, &control, &dwRev),
646 "GetSecurityDescriptorControl failed with error %u\n", GetLastError());
647 ok(0 == (control & SE_SELF_RELATIVE), "SD should be absolute\n");
649 ok(GetSecurityDescriptorDacl(psd, &bHasDacl, &pAcl, &bDefaulted),
650 "GetSecurityDescriptorDacl failed with error %u\n", GetLastError());
652 ok(bHasDacl, "SD has no DACL\n");
655 ok(!bDefaulted, "DACL should not be defaulted\n");
657 ok(pAcl != NULL, "NULL DACL!\n");
660 ACL_SIZE_INFORMATION asiSize;
662 ok(IsValidAcl(pAcl), "DACL is not valid\n");
664 ok(GetAclInformation(pAcl, &asiSize, sizeof(asiSize), AclSizeInformation),
665 "GetAclInformation failed with error %u\n", GetLastError());
667 ok(asiSize.AceCount == 3, "Incorrect number of ACEs: %d entries\n", asiSize.AceCount);
668 if (asiSize.AceCount == 3)
670 ACCESS_ALLOWED_ACE *paaa; /* will use for DENIED too */
672 ok(GetAce(pAcl, 0, (LPVOID*)&paaa), "GetAce failed with error %u\n", GetLastError());
673 ok(paaa->Header.AceType == ACCESS_ALLOWED_ACE_TYPE,
674 "Invalid ACE type %d\n", paaa->Header.AceType);
675 ok(paaa->Header.AceFlags == 0, "Invalid ACE flags %x\n", paaa->Header.AceFlags);
676 ok(paaa->Mask == GENERIC_ALL, "Invalid ACE mask %x\n", paaa->Mask);
678 ok(GetAce(pAcl, 1, (LPVOID*)&paaa), "GetAce failed with error %u\n", GetLastError());
679 ok(paaa->Header.AceType == ACCESS_DENIED_ACE_TYPE,
680 "Invalid ACE type %d\n", paaa->Header.AceType);
681 /* first one of two ACEs generated from inheritable entry - without inheritance */
682 ok(paaa->Header.AceFlags == 0, "Invalid ACE flags %x\n", paaa->Header.AceFlags);
683 ok(paaa->Mask == GENERIC_WRITE, "Invalid ACE mask %x\n", paaa->Mask);
685 ok(GetAce(pAcl, 2, (LPVOID*)&paaa), "GetAce failed with error %u\n", GetLastError());
686 ok(paaa->Header.AceType == ACCESS_DENIED_ACE_TYPE,
687 "Invalid ACE type %d\n", paaa->Header.AceType);
688 /* second ACE - with inheritance */
689 ok(paaa->Header.AceFlags == MY_INHERITANCE,
690 "Invalid ACE flags %x\n", paaa->Header.AceFlags);
691 ok(paaa->Mask == GENERIC_READ, "Invalid ACE mask %x\n", paaa->Mask);
700 static void test_SHPackDispParams(void)
706 if(!pSHPackDispParams)
707 win_skip("SHPackSidpParams not available\n");
709 memset(¶ms, 0xc0, sizeof(params));
710 memset(vars, 0xc0, sizeof(vars));
711 hres = pSHPackDispParams(¶ms, vars, 1, VT_I4, 0xdeadbeef);
712 ok(hres == S_OK, "SHPackDispParams failed: %08x\n", hres);
713 ok(params.cArgs == 1, "params.cArgs = %d\n", params.cArgs);
714 ok(params.cNamedArgs == 0, "params.cNamedArgs = %d\n", params.cArgs);
715 ok(params.rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", params.rgdispidNamedArgs);
716 ok(params.rgvarg == vars, "params.rgvarg = %p\n", params.rgvarg);
717 ok(V_VT(vars) == VT_I4, "V_VT(var) = %d\n", V_VT(vars));
718 ok(V_I4(vars) == 0xdeadbeef, "failed %x\n", V_I4(vars));
720 memset(¶ms, 0xc0, sizeof(params));
721 hres = pSHPackDispParams(¶ms, NULL, 0, 0);
722 ok(hres == S_OK, "SHPackDispParams failed: %08x\n", hres);
723 ok(params.cArgs == 0, "params.cArgs = %d\n", params.cArgs);
724 ok(params.cNamedArgs == 0, "params.cNamedArgs = %d\n", params.cArgs);
725 ok(params.rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", params.rgdispidNamedArgs);
726 ok(params.rgvarg == NULL, "params.rgvarg = %p\n", params.rgvarg);
728 memset(vars, 0xc0, sizeof(vars));
729 memset(¶ms, 0xc0, sizeof(params));
730 hres = pSHPackDispParams(¶ms, vars, 4, VT_BSTR, (void*)0xdeadbeef, VT_EMPTY, 10,
731 VT_I4, 100, VT_DISPATCH, (void*)0xdeadbeef);
732 ok(hres == S_OK, "SHPackDispParams failed: %08x\n", hres);
733 ok(params.cArgs == 4, "params.cArgs = %d\n", params.cArgs);
734 ok(params.cNamedArgs == 0, "params.cNamedArgs = %d\n", params.cArgs);
735 ok(params.rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", params.rgdispidNamedArgs);
736 ok(params.rgvarg == vars, "params.rgvarg = %p\n", params.rgvarg);
737 ok(V_VT(vars) == VT_DISPATCH, "V_VT(vars[0]) = %x\n", V_VT(vars));
738 ok(V_I4(vars) == 0xdeadbeef, "V_I4(vars[0]) = %x\n", V_I4(vars));
739 ok(V_VT(vars+1) == VT_I4, "V_VT(vars[1]) = %d\n", V_VT(vars+1));
740 ok(V_I4(vars+1) == 100, "V_I4(vars[1]) = %x\n", V_I4(vars+1));
741 ok(V_VT(vars+2) == VT_I4, "V_VT(vars[2]) = %d\n", V_VT(vars+2));
742 ok(V_I4(vars+2) == 10, "V_I4(vars[2]) = %x\n", V_I4(vars+2));
743 ok(V_VT(vars+3) == VT_BSTR, "V_VT(vars[3]) = %d\n", V_VT(vars+3));
744 ok(V_BSTR(vars+3) == (void*)0xdeadbeef, "V_BSTR(vars[3]) = %p\n", V_BSTR(vars+3));
749 const IDispatchVtbl *vtbl;
753 typedef struct _contain
755 const IConnectionPointContainerVtbl *vtbl;
759 IConnectionPoint **pt;
762 typedef struct _cntptn
764 const IConnectionPointVtbl *vtbl;
775 const IEnumConnectionsVtbl *vtbl;
782 typedef struct _enumpt
784 const IEnumConnectionPointsVtbl *vtbl;
792 static HRESULT WINAPI Disp_QueryInterface(
799 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch))
806 IUnknown_AddRef(This);
810 trace("no interface\n");
811 return E_NOINTERFACE;
814 static ULONG WINAPI Disp_AddRef(IDispatch* This)
816 Disp *iface = (Disp*)This;
817 return InterlockedIncrement(&iface->refCount);
820 static ULONG WINAPI Disp_Release(IDispatch* This)
822 Disp *iface = (Disp*)This;
825 ret = InterlockedDecrement(&iface->refCount);
827 HeapFree(GetProcessHeap(),0,This);
831 static HRESULT WINAPI Disp_GetTypeInfoCount(
835 return ERROR_SUCCESS;
838 static HRESULT WINAPI Disp_GetTypeInfo(
844 return ERROR_SUCCESS;
847 static HRESULT WINAPI Disp_GetIDsOfNames(
855 return ERROR_SUCCESS;
858 static HRESULT WINAPI Disp_Invoke(
864 DISPPARAMS *pDispParams,
866 EXCEPINFO *pExcepInfo,
869 trace("%p %x %p %x %x %p %p %p %p\n",This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr);
871 ok(dispIdMember == 0xa0 || dispIdMember == 0xa1, "Unknown dispIdMember\n");
872 ok(pDispParams != NULL, "Invoked with NULL pDispParams\n");
873 ok(wFlags == DISPATCH_METHOD, "Wrong flags %x\n",wFlags);
874 ok(lcid == 0,"Wrong lcid %x\n",lcid);
875 if (dispIdMember == 0xa0)
877 ok(pDispParams->cArgs == 0, "params.cArgs = %d\n", pDispParams->cArgs);
878 ok(pDispParams->cNamedArgs == 0, "params.cNamedArgs = %d\n", pDispParams->cArgs);
879 ok(pDispParams->rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", pDispParams->rgdispidNamedArgs);
880 ok(pDispParams->rgvarg == NULL, "params.rgvarg = %p\n", pDispParams->rgvarg);
882 else if (dispIdMember == 0xa1)
884 ok(pDispParams->cArgs == 2, "params.cArgs = %d\n", pDispParams->cArgs);
885 ok(pDispParams->cNamedArgs == 0, "params.cNamedArgs = %d\n", pDispParams->cArgs);
886 ok(pDispParams->rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", pDispParams->rgdispidNamedArgs);
887 ok(V_VT(pDispParams->rgvarg) == VT_BSTR, "V_VT(var) = %d\n", V_VT(pDispParams->rgvarg));
888 ok(V_I4(pDispParams->rgvarg) == 0xdeadcafe , "failed %p\n", V_BSTR(pDispParams->rgvarg));
889 ok(V_VT(pDispParams->rgvarg+1) == VT_I4, "V_VT(var) = %d\n", V_VT(pDispParams->rgvarg+1));
890 ok(V_I4(pDispParams->rgvarg+1) == 0xdeadbeef, "failed %x\n", V_I4(pDispParams->rgvarg+1));
893 return ERROR_SUCCESS;
896 static const IDispatchVtbl disp_vtbl = {
901 Disp_GetTypeInfoCount,
907 static HRESULT WINAPI Enum_QueryInterface(
908 IEnumConnections* This,
914 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IEnumConnections))
921 IUnknown_AddRef(This);
925 trace("no interface\n");
926 return E_NOINTERFACE;
929 static ULONG WINAPI Enum_AddRef(IEnumConnections* This)
931 EnumCon *iface = (EnumCon*)This;
932 return InterlockedIncrement(&iface->refCount);
935 static ULONG WINAPI Enum_Release(IEnumConnections* This)
937 EnumCon *iface = (EnumCon*)This;
940 ret = InterlockedDecrement(&iface->refCount);
942 HeapFree(GetProcessHeap(),0,This);
946 static HRESULT WINAPI Enum_Next(
947 IEnumConnections* This,
952 EnumCon *iface = (EnumCon*)This;
954 if (cConnections > 0 && iface->idx < iface->pt->sinkCount)
956 rgcd->pUnk = iface->pt->sink[iface->idx];
957 IUnknown_AddRef(iface->pt->sink[iface->idx]);
968 static HRESULT WINAPI Enum_Skip(
969 IEnumConnections* This,
975 static HRESULT WINAPI Enum_Reset(
976 IEnumConnections* This)
981 static HRESULT WINAPI Enum_Clone(
982 IEnumConnections* This,
983 IEnumConnections **ppEnum)
988 static const IEnumConnectionsVtbl enum_vtbl = {
999 static HRESULT WINAPI ConPt_QueryInterface(
1000 IConnectionPoint* This,
1006 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IConnectionPoint))
1013 IUnknown_AddRef(This);
1017 trace("no interface\n");
1018 return E_NOINTERFACE;
1021 static ULONG WINAPI ConPt_AddRef(
1022 IConnectionPoint* This)
1024 ConPt *iface = (ConPt*)This;
1025 return InterlockedIncrement(&iface->refCount);
1028 static ULONG WINAPI ConPt_Release(
1029 IConnectionPoint* This)
1031 ConPt *iface = (ConPt*)This;
1034 ret = InterlockedDecrement(&iface->refCount);
1037 if (iface->sinkCount > 0)
1040 for (i = 0; i < iface->sinkCount; i++)
1043 IUnknown_Release(iface->sink[i]);
1045 HeapFree(GetProcessHeap(),0,iface->sink);
1047 HeapFree(GetProcessHeap(),0,This);
1052 static HRESULT WINAPI ConPt_GetConnectionInterface(
1053 IConnectionPoint* This,
1057 ConPt *iface = (ConPt*)This;
1064 memcpy(pIID,&iface->id,sizeof(GUID));
1068 static HRESULT WINAPI ConPt_GetConnectionPointContainer(
1069 IConnectionPoint* This,
1070 IConnectionPointContainer **ppCPC)
1072 ConPt *iface = (ConPt*)This;
1074 *ppCPC = (IConnectionPointContainer*)iface->container;
1078 static HRESULT WINAPI ConPt_Advise(
1079 IConnectionPoint* This,
1083 ConPt *iface = (ConPt*)This;
1085 if (iface->sinkCount == 0)
1086 iface->sink = HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown*));
1088 iface->sink = HeapReAlloc(GetProcessHeap(),0,iface->sink,sizeof(IUnknown*)*(iface->sinkCount+1));
1089 iface->sink[iface->sinkCount] = pUnkSink;
1090 IUnknown_AddRef(pUnkSink);
1092 *pdwCookie = iface->sinkCount;
1096 static HRESULT WINAPI ConPt_Unadvise(
1097 IConnectionPoint* This,
1100 ConPt *iface = (ConPt*)This;
1102 if (dwCookie > iface->sinkCount)
1106 IUnknown_Release(iface->sink[dwCookie-1]);
1107 iface->sink[dwCookie-1] = NULL;
1112 static HRESULT WINAPI ConPt_EnumConnections(
1113 IConnectionPoint* This,
1114 IEnumConnections **ppEnum)
1118 ec = HeapAlloc(GetProcessHeap(),0,sizeof(EnumCon));
1119 ec->vtbl = &enum_vtbl;
1121 ec->pt = (ConPt*)This;
1123 *ppEnum = (IEnumConnections*)ec;
1128 static const IConnectionPointVtbl point_vtbl = {
1129 ConPt_QueryInterface,
1133 ConPt_GetConnectionInterface,
1134 ConPt_GetConnectionPointContainer,
1137 ConPt_EnumConnections
1140 static HRESULT WINAPI EnumPt_QueryInterface(
1141 IEnumConnectionPoints* This,
1147 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IEnumConnectionPoints))
1154 IUnknown_AddRef(This);
1158 trace("no interface\n");
1159 return E_NOINTERFACE;
1162 static ULONG WINAPI EnumPt_AddRef(IEnumConnectionPoints* This)
1164 EnumPt *iface = (EnumPt*)This;
1165 return InterlockedIncrement(&iface->refCount);
1168 static ULONG WINAPI EnumPt_Release(IEnumConnectionPoints* This)
1170 EnumPt *iface = (EnumPt*)This;
1173 ret = InterlockedDecrement(&iface->refCount);
1175 HeapFree(GetProcessHeap(),0,This);
1179 static HRESULT WINAPI EnumPt_Next(
1180 IEnumConnectionPoints* This,
1182 IConnectionPoint **rgcd,
1185 EnumPt *iface = (EnumPt*)This;
1187 if (cConnections > 0 && iface->idx < iface->container->ptCount)
1189 *rgcd = iface->container->pt[iface->idx];
1190 IUnknown_AddRef(iface->container->pt[iface->idx]);
1200 static HRESULT WINAPI EnumPt_Skip(
1201 IEnumConnectionPoints* This,
1207 static HRESULT WINAPI EnumPt_Reset(
1208 IEnumConnectionPoints* This)
1213 static HRESULT WINAPI EnumPt_Clone(
1214 IEnumConnectionPoints* This,
1215 IEnumConnectionPoints **ppEnumPt)
1220 static const IEnumConnectionPointsVtbl enumpt_vtbl = {
1222 EnumPt_QueryInterface,
1231 static HRESULT WINAPI Contain_QueryInterface(
1232 IConnectionPointContainer* This,
1238 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IConnectionPointContainer))
1245 IUnknown_AddRef(This);
1249 trace("no interface\n");
1250 return E_NOINTERFACE;
1253 static ULONG WINAPI Contain_AddRef(
1254 IConnectionPointContainer* This)
1256 Contain *iface = (Contain*)This;
1257 return InterlockedIncrement(&iface->refCount);
1260 static ULONG WINAPI Contain_Release(
1261 IConnectionPointContainer* This)
1263 Contain *iface = (Contain*)This;
1266 ret = InterlockedDecrement(&iface->refCount);
1269 if (iface->ptCount > 0)
1272 for (i = 0; i < iface->ptCount; i++)
1273 IUnknown_Release(iface->pt[i]);
1274 HeapFree(GetProcessHeap(),0,iface->pt);
1276 HeapFree(GetProcessHeap(),0,This);
1281 static HRESULT WINAPI Contain_EnumConnectionPoints(
1282 IConnectionPointContainer* This,
1283 IEnumConnectionPoints **ppEnum)
1287 ec = HeapAlloc(GetProcessHeap(),0,sizeof(EnumPt));
1288 ec->vtbl = &enumpt_vtbl;
1291 ec->container = (Contain*)This;
1292 *ppEnum = (IEnumConnectionPoints*)ec;
1297 static HRESULT WINAPI Contain_FindConnectionPoint(
1298 IConnectionPointContainer* This,
1300 IConnectionPoint **ppCP)
1302 Contain *iface = (Contain*)This;
1305 if (!IsEqualIID(riid, &IID_NULL) || iface->ptCount ==0)
1307 pt = HeapAlloc(GetProcessHeap(),0,sizeof(ConPt));
1308 pt->vtbl = &point_vtbl;
1312 pt->container = iface;
1313 pt->id = IID_IDispatch;
1315 if (iface->ptCount == 0)
1316 iface->pt =HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown*));
1318 iface->pt = HeapReAlloc(GetProcessHeap(),0,iface->pt,sizeof(IUnknown*)*(iface->ptCount+1));
1319 iface->pt[iface->ptCount] = (IConnectionPoint*)pt;
1322 *ppCP = (IConnectionPoint*)pt;
1326 *ppCP = iface->pt[0];
1327 IUnknown_AddRef((IUnknown*)*ppCP);
1333 static const IConnectionPointContainerVtbl contain_vtbl = {
1334 Contain_QueryInterface,
1338 Contain_EnumConnectionPoints,
1339 Contain_FindConnectionPoint
1342 static void test_IConnectionPoint(void)
1346 IConnectionPoint *point;
1349 DWORD cookie = 0xffffffff;
1353 if (!pIConnectionPoint_SimpleInvoke || !pConnectToConnectionPoint)
1355 win_skip("IConnectionPoint Apis not present\n");
1359 container = HeapAlloc(GetProcessHeap(),0,sizeof(Contain));
1360 container->vtbl = &contain_vtbl;
1361 container->refCount = 1;
1362 container->ptCount = 0;
1363 container->pt = NULL;
1365 dispatch = HeapAlloc(GetProcessHeap(),0,sizeof(Disp));
1366 dispatch->vtbl = &disp_vtbl;
1367 dispatch->refCount = 1;
1369 rc = pConnectToConnectionPoint((IUnknown*)dispatch, &IID_NULL, TRUE, (IUnknown*)container, &cookie, &point);
1370 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
1371 ok(point != NULL, "returned ConnectionPoint is NULL\n");
1372 ok(cookie != 0xffffffff, "invalid cookie returned\n");
1374 rc = pIConnectionPoint_SimpleInvoke(point,0xa0,NULL);
1375 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
1377 if (pSHPackDispParams)
1379 memset(¶ms, 0xc0, sizeof(params));
1380 memset(vars, 0xc0, sizeof(vars));
1381 rc = pSHPackDispParams(¶ms, vars, 2, VT_I4, 0xdeadbeef, VT_BSTR, 0xdeadcafe);
1382 ok(rc == S_OK, "SHPackDispParams failed: %08x\n", rc);
1384 rc = pIConnectionPoint_SimpleInvoke(point,0xa1,¶ms);
1385 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
1388 win_skip("pSHPackDispParams not present\n");
1390 rc = pConnectToConnectionPoint(NULL, &IID_NULL, FALSE, (IUnknown*)container, &cookie, NULL);
1391 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
1393 /* MSDN says this should be required but it crashs on XP
1394 IUnknown_Release(point);
1396 ref = IUnknown_Release((IUnknown*)container);
1397 ok(ref == 0, "leftover IConnectionPointContainer reference %i\n",ref);
1398 ref = IUnknown_Release((IUnknown*)dispatch);
1399 ok(ref == 0, "leftover IDispatch reference %i\n",ref);
1402 typedef struct _propbag
1404 const IPropertyBagVtbl *vtbl;
1410 static HRESULT WINAPI Prop_QueryInterface(
1417 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IPropertyBag))
1424 IUnknown_AddRef(This);
1428 trace("no interface\n");
1429 return E_NOINTERFACE;
1432 static ULONG WINAPI Prop_AddRef(
1435 PropBag *iface = (PropBag*)This;
1436 return InterlockedIncrement(&iface->refCount);
1439 static ULONG WINAPI Prop_Release(
1442 PropBag *iface = (PropBag*)This;
1445 ret = InterlockedDecrement(&iface->refCount);
1447 HeapFree(GetProcessHeap(),0,This);
1451 static HRESULT WINAPI Prop_Read(
1453 LPCOLESTR pszPropName,
1455 IErrorLog *pErrorLog)
1457 V_VT(pVar) = VT_BLOB|VT_BYREF;
1458 V_BYREF(pVar) = (LPVOID)0xdeadcafe;
1462 static HRESULT WINAPI Prop_Write(
1464 LPCOLESTR pszPropName,
1471 static const IPropertyBagVtbl prop_vtbl = {
1472 Prop_QueryInterface,
1480 static void test_SHPropertyBag_ReadLONG(void)
1485 static const WCHAR szName1[] = {'n','a','m','e','1',0};
1487 if (!pSHPropertyBag_ReadLONG)
1489 win_skip("SHPropertyBag_ReadLONG not present\n");
1493 pb = HeapAlloc(GetProcessHeap(),0,sizeof(PropBag));
1495 pb->vtbl = &prop_vtbl;
1498 rc = pSHPropertyBag_ReadLONG(NULL, szName1, &out);
1499 ok(rc == E_INVALIDARG || broken(rc == 0), "incorrect return %x\n",rc);
1500 ok(out == 0xfeedface, "value should not have changed\n");
1501 rc = pSHPropertyBag_ReadLONG((IPropertyBag*)pb, NULL, &out);
1502 ok(rc == E_INVALIDARG || broken(rc == 0) || broken(rc == 1), "incorrect return %x\n",rc);
1503 ok(out == 0xfeedface, "value should not have changed\n");
1504 rc = pSHPropertyBag_ReadLONG((IPropertyBag*)pb, szName1, NULL);
1505 ok(rc == E_INVALIDARG || broken(rc == 0) || broken(rc == 1), "incorrect return %x\n",rc);
1506 ok(out == 0xfeedface, "value should not have changed\n");
1507 rc = pSHPropertyBag_ReadLONG((IPropertyBag*)pb, szName1, &out);
1508 ok(rc == DISP_E_BADVARTYPE || broken(rc == 0) || broken(rc == 1), "incorrect return %x\n",rc);
1509 ok(out == 0xfeedface || broken(out == 0xfeedfa00), "value should not have changed %x\n",out);
1510 IUnknown_Release((IUnknown*)pb);
1515 static void test_SHSetWindowBits(void)
1518 DWORD style, styleold;
1521 if(!pSHSetWindowBits)
1523 win_skip("SHSetWindowBits is not available\n");
1528 clsA.lpfnWndProc = DefWindowProcA;
1529 clsA.cbClsExtra = 0;
1530 clsA.cbWndExtra = 0;
1531 clsA.hInstance = GetModuleHandleA(NULL);
1533 clsA.hCursor = LoadCursorA(0, IDC_ARROW);
1534 clsA.hbrBackground = NULL;
1535 clsA.lpszMenuName = NULL;
1536 clsA.lpszClassName = "Shlwapi test class";
1537 RegisterClassA(&clsA);
1539 hwnd = CreateWindowA("Shlwapi test class", "Test", WS_VISIBLE, 0, 0, 100, 100,
1540 NULL, NULL, GetModuleHandle(NULL), 0);
1541 ok(IsWindow(hwnd), "failed to create window\n");
1544 SetLastError(0xdeadbeef);
1545 style = pSHSetWindowBits(NULL, GWL_STYLE, 0, 0);
1546 ok(style == 0, "expected 0 retval, got %d\n", style);
1547 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE ||
1548 broken(GetLastError() == 0xdeadbeef), /* Win9x/WinMe */
1549 "expected ERROR_INVALID_WINDOW_HANDLE, got %d\n", GetLastError());
1551 /* zero mask, zero flags */
1552 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1553 style = pSHSetWindowBits(hwnd, GWL_STYLE, 0, 0);
1554 ok(styleold == style, "expected old style\n");
1555 ok(styleold == GetWindowLongA(hwnd, GWL_STYLE), "expected to keep old style\n");
1558 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1559 ok(styleold & WS_VISIBLE, "expected WS_VISIBLE\n");
1560 style = pSHSetWindowBits(hwnd, GWL_STYLE, WS_VISIBLE, 0);
1562 ok(style == styleold, "expected previous style, got %x\n", style);
1563 ok((GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE) == 0, "expected updated style\n");
1565 /* test mask, unset style bit used */
1566 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1567 style = pSHSetWindowBits(hwnd, GWL_STYLE, WS_VISIBLE, 0);
1568 ok(style == styleold, "expected previous style, got %x\n", style);
1569 ok(styleold == GetWindowLongA(hwnd, GWL_STYLE), "expected to keep old style\n");
1571 /* set back with flags */
1572 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1573 style = pSHSetWindowBits(hwnd, GWL_STYLE, WS_VISIBLE, WS_VISIBLE);
1574 ok(style == styleold, "expected previous style, got %x\n", style);
1575 ok(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE, "expected updated style\n");
1577 /* reset and try to set without a mask */
1578 pSHSetWindowBits(hwnd, GWL_STYLE, WS_VISIBLE, 0);
1579 ok((GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE) == 0, "expected updated style\n");
1580 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1581 style = pSHSetWindowBits(hwnd, GWL_STYLE, 0, WS_VISIBLE);
1582 ok(style == styleold, "expected previous style, got %x\n", style);
1583 ok((GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE) == 0, "expected updated style\n");
1585 DestroyWindow(hwnd);
1587 UnregisterClassA("Shlwapi test class", GetModuleHandleA(NULL));
1590 static void test_SHFormatDateTimeA(void)
1592 FILETIME UNALIGNED filetime;
1593 CHAR buff[100], buff2[100], buff3[100];
1598 if(!pSHFormatDateTimeA)
1600 win_skip("pSHFormatDateTimeA isn't available\n");
1606 /* crashes on native */
1607 ret = pSHFormatDateTimeA(NULL, NULL, NULL, 0);
1611 SystemTimeToFileTime(&st, &filetime);
1612 /* SHFormatDateTime expects input as utc */
1613 LocalFileTimeToFileTime(&filetime, &filetime);
1615 /* no way to get required buffer length here */
1616 SetLastError(0xdeadbeef);
1617 ret = pSHFormatDateTimeA(&filetime, NULL, NULL, 0);
1618 ok(ret == 0, "got %d\n", ret);
1619 ok(GetLastError() == 0xdeadbeef || broken(GetLastError() == ERROR_SUCCESS /* Win7 */),
1620 "expected 0xdeadbeef, got %d\n", GetLastError());
1622 SetLastError(0xdeadbeef);
1623 buff[0] = 'a'; buff[1] = 0;
1624 ret = pSHFormatDateTimeA(&filetime, NULL, buff, 0);
1625 ok(ret == 0, "got %d\n", ret);
1626 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1627 ok(buff[0] == 'a', "expected same string, got %s\n", buff);
1629 /* flags needs to have FDTF_NOAUTOREADINGORDER for these tests to succeed on Vista+ */
1631 /* all combinations documented as invalid succeeded */
1632 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTTIME | FDTF_LONGTIME;
1633 SetLastError(0xdeadbeef);
1634 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1635 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1636 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1638 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTDATE | FDTF_LONGDATE;
1639 SetLastError(0xdeadbeef);
1640 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1641 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1642 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1644 flags = FDTF_SHORTDATE | FDTF_LTRDATE | FDTF_RTLDATE;
1645 SetLastError(0xdeadbeef);
1646 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1647 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1648 ok(GetLastError() == 0xdeadbeef ||
1649 broken(GetLastError() == ERROR_INVALID_FLAGS), /* Win9x/WinMe */
1650 "expected 0xdeadbeef, got %d\n", GetLastError());
1652 /* now check returned strings */
1653 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTTIME;
1654 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1655 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1656 ret = GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff2, sizeof(buff2));
1657 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1658 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1660 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGTIME;
1661 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1662 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1663 ret = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2));
1664 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1665 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1667 /* both time flags */
1668 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGTIME | FDTF_SHORTTIME;
1669 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1670 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1671 ret = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2));
1672 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1673 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1675 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTDATE;
1676 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1677 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1678 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2));
1679 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1680 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1682 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGDATE;
1683 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1684 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1685 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
1686 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1687 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1689 /* both date flags */
1690 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGDATE | FDTF_SHORTDATE;
1691 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1692 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1693 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
1694 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1695 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1697 /* various combinations of date/time flags */
1698 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGDATE | FDTF_SHORTTIME;
1699 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1700 ok(ret == lstrlenA(buff)+1, "got %d, length %d\n", ret, lstrlenA(buff)+1);
1701 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
1702 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1703 strcat(buff2, ", ");
1704 ret = GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3));
1705 ok(ret == lstrlenA(buff3)+1, "got %d\n", ret);
1706 strcat(buff2, buff3);
1707 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1709 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGDATE | FDTF_LONGTIME;
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_LONGDATE, &st, NULL, buff2, sizeof(buff2));
1713 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1714 strcat(buff2, ", ");
1715 ret = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3));
1716 ok(ret == lstrlenA(buff3)+1, "got %d\n", ret);
1717 strcat(buff2, buff3);
1718 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1720 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTDATE | FDTF_SHORTTIME;
1721 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1722 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1723 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2));
1724 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1726 ret = GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3));
1727 ok(ret == lstrlenA(buff3)+1, "got %d\n", ret);
1728 strcat(buff2, buff3);
1729 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1731 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTDATE | FDTF_LONGTIME;
1732 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1733 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1734 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2));
1735 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1737 ret = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3));
1738 ok(ret == lstrlenA(buff3)+1, "got %d\n", ret);
1739 strcat(buff2, buff3);
1740 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1743 static void test_SHFormatDateTimeW(void)
1745 FILETIME UNALIGNED filetime;
1746 WCHAR buff[100], buff2[100], buff3[100];
1750 static const WCHAR spaceW[] = {' ',0};
1751 static const WCHAR commaW[] = {',',' ',0};
1753 if(!pSHFormatDateTimeW)
1755 win_skip("pSHFormatDateTimeW isn't available\n");
1761 /* crashes on native */
1762 ret = pSHFormatDateTimeW(NULL, NULL, NULL, 0);
1766 SystemTimeToFileTime(&st, &filetime);
1767 /* SHFormatDateTime expects input as utc */
1768 LocalFileTimeToFileTime(&filetime, &filetime);
1770 /* no way to get required buffer length here */
1771 SetLastError(0xdeadbeef);
1772 ret = pSHFormatDateTimeW(&filetime, NULL, NULL, 0);
1773 ok(ret == 0, "got %d\n", ret);
1774 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1776 SetLastError(0xdeadbeef);
1777 buff[0] = 'a'; buff[1] = 0;
1778 ret = pSHFormatDateTimeW(&filetime, NULL, buff, 0);
1779 ok(ret == 0, "got %d\n", ret);
1780 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1781 ok(buff[0] == 'a', "expected same string\n");
1783 /* all combinations documented as invalid succeeded */
1784 flags = FDTF_SHORTTIME | FDTF_LONGTIME;
1785 SetLastError(0xdeadbeef);
1786 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1787 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1788 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1790 flags = FDTF_SHORTDATE | FDTF_LONGDATE;
1791 SetLastError(0xdeadbeef);
1792 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1793 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1794 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1796 flags = FDTF_SHORTDATE | FDTF_LTRDATE | FDTF_RTLDATE;
1797 SetLastError(0xdeadbeef);
1798 buff[0] = 0; /* NT4 doesn't clear the buffer on failure */
1799 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1800 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1801 ok(GetLastError() == 0xdeadbeef ||
1802 broken(GetLastError() == ERROR_INVALID_FLAGS), /* Win9x/WinMe/NT4 */
1803 "expected 0xdeadbeef, got %d\n", GetLastError());
1805 /* now check returned strings */
1806 flags = FDTF_SHORTTIME;
1807 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1808 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1809 SetLastError(0xdeadbeef);
1810 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1811 if (ret == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1813 win_skip("Needed W-functions are not implemented\n");
1816 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1817 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1819 flags = FDTF_LONGTIME;
1820 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1821 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1822 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1823 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1824 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1826 /* both time flags */
1827 flags = FDTF_LONGTIME | FDTF_SHORTTIME;
1828 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1829 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1830 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1831 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1832 ok(lstrcmpW(buff, buff2) == 0, "expected equal string\n");
1834 flags = FDTF_SHORTDATE;
1835 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1836 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1837 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1838 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1839 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1841 flags = FDTF_LONGDATE;
1842 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1843 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1844 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1845 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1846 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1848 /* both date flags */
1849 flags = FDTF_LONGDATE | FDTF_SHORTDATE;
1850 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1851 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1852 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1853 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1854 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1856 /* various combinations of date/time flags */
1857 flags = FDTF_LONGDATE | FDTF_SHORTTIME;
1858 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1859 ok(ret == lstrlenW(buff)+1, "got %d, length %d\n", ret, lstrlenW(buff)+1);
1860 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1861 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1862 lstrcatW(buff2, commaW);
1863 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
1864 ok(ret == lstrlenW(buff3)+1, "got %d\n", ret);
1865 lstrcatW(buff2, buff3);
1866 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1868 flags = FDTF_LONGDATE | FDTF_LONGTIME;
1869 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1870 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1871 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1872 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1873 lstrcatW(buff2, commaW);
1874 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
1875 ok(ret == lstrlenW(buff3)+1, "got %d\n", ret);
1876 lstrcatW(buff2, buff3);
1877 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1879 flags = FDTF_SHORTDATE | FDTF_SHORTTIME;
1880 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1881 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1882 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1883 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1884 lstrcatW(buff2, spaceW);
1885 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
1886 ok(ret == lstrlenW(buff3)+1, "got %d\n", ret);
1887 lstrcatW(buff2, buff3);
1888 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1890 flags = FDTF_SHORTDATE | FDTF_LONGTIME;
1891 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1892 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1893 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1894 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1895 lstrcatW(buff2, spaceW);
1896 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
1897 ok(ret == lstrlenW(buff3)+1, "got %d\n", ret);
1898 lstrcatW(buff2, buff3);
1899 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1902 static void test_SHGetObjectCompatFlags(void)
1904 struct compat_value {
1909 struct compat_value values[] = {
1910 { "OTNEEDSSFCACHE", 0x1 },
1911 { "NO_WEBVIEW", 0x2 },
1912 { "UNBINDABLE", 0x4 },
1914 { "NEEDSFILESYSANCESTOR", 0x10 },
1915 { "NOTAFILESYSTEM", 0x20 },
1916 { "CTXMENU_NOVERBS", 0x40 },
1917 { "CTXMENU_LIMITEDQI", 0x80 },
1918 { "COCREATESHELLFOLDERONLY", 0x100 },
1919 { "NEEDSSTORAGEANCESTOR", 0x200 },
1920 { "NOLEGACYWEBVIEW", 0x400 },
1921 { "CTXMENU_XPQCMFLAGS", 0x1000 },
1922 { "NOIPROPERTYSTORE", 0x2000 }
1925 static const char compat_path[] = "Software\\Microsoft\\Windows\\CurrentVersion\\ShellCompatibility\\Objects";
1926 void *pColorAdjustLuma = GetProcAddress(hShlwapi, "ColorAdjustLuma");
1927 CHAR keyA[39]; /* {CLSID} */
1932 if (!pSHGetObjectCompatFlags)
1934 win_skip("SHGetObjectCompatFlags isn't available\n");
1938 if (pColorAdjustLuma && pColorAdjustLuma == pSHGetObjectCompatFlags) /* win2k */
1940 win_skip("Skipping SHGetObjectCompatFlags, same ordinal used for ColorAdjustLuma\n");
1945 ret = pSHGetObjectCompatFlags(NULL, NULL);
1946 ok(ret == 0, "got %d\n", ret);
1948 ret = RegOpenKeyA(HKEY_LOCAL_MACHINE, compat_path, &root);
1949 if (ret != ERROR_SUCCESS)
1951 skip("No compatibility class data found\n");
1955 for (i = 0; RegEnumKeyA(root, i, keyA, sizeof(keyA)) == ERROR_SUCCESS; i++)
1959 if (RegOpenKeyA(root, keyA, &clsid_key) == ERROR_SUCCESS)
1962 DWORD expected = 0, got, length = sizeof(valueA);
1966 for (v = 0; RegEnumValueA(clsid_key, v, valueA, &length, NULL, NULL, NULL, NULL) == ERROR_SUCCESS; v++)
1970 for (j = 0; j < sizeof(values)/sizeof(struct compat_value); j++)
1971 if (lstrcmpA(values[j].nameA, valueA) == 0)
1973 expected |= values[j].value;
1977 length = sizeof(valueA);
1980 pGUIDFromStringA(keyA, &clsid);
1981 got = pSHGetObjectCompatFlags(NULL, &clsid);
1982 ok(got == expected, "got 0x%08x, expected 0x%08x. Key %s\n", got, expected, keyA);
1984 RegCloseKey(clsid_key);
1992 const IOleCommandTargetVtbl *lpVtbl;
1994 } IOleCommandTargetImpl;
1996 static const IOleCommandTargetVtbl IOleCommandTargetImpl_Vtbl;
1998 static IOleCommandTarget* IOleCommandTargetImpl_Construct(void)
2000 IOleCommandTargetImpl *obj;
2002 obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*obj));
2003 obj->lpVtbl = &IOleCommandTargetImpl_Vtbl;
2006 return (IOleCommandTarget*)obj;
2009 static HRESULT WINAPI IOleCommandTargetImpl_QueryInterface(IOleCommandTarget *iface, REFIID riid, void **ppvObj)
2011 IOleCommandTargetImpl *This = (IOleCommandTargetImpl *)iface;
2013 if (IsEqualIID(riid, &IID_IUnknown) ||
2014 IsEqualIID(riid, &IID_IOleCommandTarget))
2021 IUnknown_AddRef(iface);
2025 return E_NOINTERFACE;
2028 static ULONG WINAPI IOleCommandTargetImpl_AddRef(IOleCommandTarget *iface)
2030 IOleCommandTargetImpl *This = (IOleCommandTargetImpl *)iface;
2031 return InterlockedIncrement(&This->ref);
2034 static ULONG WINAPI IOleCommandTargetImpl_Release(IOleCommandTarget *iface)
2036 IOleCommandTargetImpl *This = (IOleCommandTargetImpl *)iface;
2037 ULONG ref = InterlockedDecrement(&This->ref);
2041 HeapFree(GetProcessHeap(), 0, This);
2047 static HRESULT WINAPI IOleCommandTargetImpl_QueryStatus(
2048 IOleCommandTarget *iface, const GUID *group, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText)
2053 static HRESULT WINAPI IOleCommandTargetImpl_Exec(
2054 IOleCommandTarget *iface,
2055 const GUID *CmdGroup,
2061 add_call(&trace_got, 3, CmdGroup, (void*)(DWORD_PTR)nCmdID, (void*)(DWORD_PTR)nCmdexecopt, pvaIn, pvaOut);
2065 static const IOleCommandTargetVtbl IOleCommandTargetImpl_Vtbl =
2067 IOleCommandTargetImpl_QueryInterface,
2068 IOleCommandTargetImpl_AddRef,
2069 IOleCommandTargetImpl_Release,
2070 IOleCommandTargetImpl_QueryStatus,
2071 IOleCommandTargetImpl_Exec
2075 const IServiceProviderVtbl *lpVtbl;
2077 } IServiceProviderImpl;
2080 const IProfferServiceVtbl *lpVtbl;
2082 } IProfferServiceImpl;
2085 static const IServiceProviderVtbl IServiceProviderImpl_Vtbl;
2086 static const IProfferServiceVtbl IProfferServiceImpl_Vtbl;
2088 static IServiceProvider* IServiceProviderImpl_Construct(void)
2090 IServiceProviderImpl *obj;
2092 obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*obj));
2093 obj->lpVtbl = &IServiceProviderImpl_Vtbl;
2096 return (IServiceProvider*)obj;
2099 static IProfferService* IProfferServiceImpl_Construct(void)
2101 IProfferServiceImpl *obj;
2103 obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*obj));
2104 obj->lpVtbl = &IProfferServiceImpl_Vtbl;
2107 return (IProfferService*)obj;
2110 static HRESULT WINAPI IServiceProviderImpl_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppvObj)
2112 IServiceProviderImpl *This = (IServiceProviderImpl *)iface;
2114 if (IsEqualIID(riid, &IID_IUnknown) ||
2115 IsEqualIID(riid, &IID_IServiceProvider))
2122 IUnknown_AddRef(iface);
2123 /* native uses redefined IID_IServiceProvider symbol, so we can't compare pointers */
2124 if (IsEqualIID(riid, &IID_IServiceProvider))
2125 add_call(&trace_got, 1, iface, &IID_IServiceProvider, 0, 0, 0);
2129 return E_NOINTERFACE;
2132 static ULONG WINAPI IServiceProviderImpl_AddRef(IServiceProvider *iface)
2134 IServiceProviderImpl *This = (IServiceProviderImpl *)iface;
2135 return InterlockedIncrement(&This->ref);
2138 static ULONG WINAPI IServiceProviderImpl_Release(IServiceProvider *iface)
2140 IServiceProviderImpl *This = (IServiceProviderImpl *)iface;
2141 ULONG ref = InterlockedDecrement(&This->ref);
2145 HeapFree(GetProcessHeap(), 0, This);
2151 static HRESULT WINAPI IServiceProviderImpl_QueryService(
2152 IServiceProvider *iface, REFGUID service, REFIID riid, void **ppv)
2154 /* native uses redefined pointer for IID_IOleCommandTarget, not one from uuid.lib */
2155 if (IsEqualIID(riid, &IID_IOleCommandTarget))
2157 add_call(&trace_got, 2, iface, service, &IID_IOleCommandTarget, 0, 0);
2158 *ppv = IOleCommandTargetImpl_Construct();
2160 if (IsEqualIID(riid, &IID_IProfferService))
2162 if (IsEqualIID(service, &IID_IProfferService))
2163 add_call(&trace_got, 2, &IID_IProfferService, &IID_IProfferService, 0, 0, 0);
2164 *ppv = IProfferServiceImpl_Construct();
2169 static const IServiceProviderVtbl IServiceProviderImpl_Vtbl =
2171 IServiceProviderImpl_QueryInterface,
2172 IServiceProviderImpl_AddRef,
2173 IServiceProviderImpl_Release,
2174 IServiceProviderImpl_QueryService
2177 static void test_IUnknown_QueryServiceExec(void)
2179 IServiceProvider *provider = IServiceProviderImpl_Construct();
2180 static const GUID dummy_serviceid = { 0xdeadbeef };
2181 static const GUID dummy_groupid = { 0xbeefbeef };
2182 call_trace_t trace_expected;
2185 /* on <=W2K platforms same ordinal used for another export with different
2186 prototype, so skipping using this indirect condition */
2187 if (is_win2k_and_lower)
2189 win_skip("IUnknown_QueryServiceExec is not available\n");
2193 /* null source pointer */
2194 hr = pIUnknown_QueryServiceExec(NULL, &dummy_serviceid, &dummy_groupid, 0, 0, 0, 0);
2195 ok(hr == E_FAIL, "got 0x%08x\n", hr);
2198 IUnknown_QueryServiceExec( ptr1, serviceid, groupid, arg1, arg2, arg3, arg4);
2199 -> IUnknown_QueryInterface( ptr1, &IID_IServiceProvider, &prov );
2200 -> IServiceProvider_QueryService( prov, serviceid, &IID_IOleCommandTarget, &obj );
2201 -> IOleCommandTarget_Exec( obj, groupid, arg1, arg2, arg3, arg4 );
2203 init_call_trace(&trace_expected);
2205 add_call(&trace_expected, 1, provider, &IID_IServiceProvider, 0, 0, 0);
2206 add_call(&trace_expected, 2, provider, &dummy_serviceid, &IID_IOleCommandTarget, 0, 0);
2207 add_call(&trace_expected, 3, &dummy_groupid, (void*)0x1, (void*)0x2, (void*)0x3, (void*)0x4);
2209 init_call_trace(&trace_got);
2210 hr = pIUnknown_QueryServiceExec((IUnknown*)provider, &dummy_serviceid, &dummy_groupid, 0x1, 0x2, (void*)0x3, (void*)0x4);
2211 ok(hr == S_OK, "got 0x%08x\n", hr);
2213 ok_trace(&trace_expected, &trace_got);
2215 free_call_trace(&trace_expected);
2216 free_call_trace(&trace_got);
2218 IServiceProvider_Release(provider);
2222 static HRESULT WINAPI IProfferServiceImpl_QueryInterface(IProfferService *iface, REFIID riid, void **ppvObj)
2224 IProfferServiceImpl *This = (IProfferServiceImpl *)iface;
2226 if (IsEqualIID(riid, &IID_IUnknown) ||
2227 IsEqualIID(riid, &IID_IProfferService))
2231 else if (IsEqualIID(riid, &IID_IServiceProvider))
2233 *ppvObj = IServiceProviderImpl_Construct();
2234 add_call(&trace_got, 1, iface, &IID_IServiceProvider, 0, 0, 0);
2240 IUnknown_AddRef(iface);
2244 return E_NOINTERFACE;
2247 static ULONG WINAPI IProfferServiceImpl_AddRef(IProfferService *iface)
2249 IProfferServiceImpl *This = (IProfferServiceImpl *)iface;
2250 return InterlockedIncrement(&This->ref);
2253 static ULONG WINAPI IProfferServiceImpl_Release(IProfferService *iface)
2255 IProfferServiceImpl *This = (IProfferServiceImpl *)iface;
2256 ULONG ref = InterlockedDecrement(&This->ref);
2260 HeapFree(GetProcessHeap(), 0, This);
2266 static HRESULT WINAPI IProfferServiceImpl_ProfferService(IProfferService *iface,
2267 REFGUID service, IServiceProvider *pService, DWORD *pCookie)
2269 add_call(&trace_got, 3, service, pService, pCookie, 0, 0);
2273 static HRESULT WINAPI IProfferServiceImpl_RevokeService(IProfferService *iface, DWORD cookie)
2275 add_call(&trace_got, 4, (void*)(DWORD_PTR)cookie, 0, 0, 0, 0);
2279 static const IProfferServiceVtbl IProfferServiceImpl_Vtbl =
2281 IProfferServiceImpl_QueryInterface,
2282 IProfferServiceImpl_AddRef,
2283 IProfferServiceImpl_Release,
2284 IProfferServiceImpl_ProfferService,
2285 IProfferServiceImpl_RevokeService
2288 static void test_IUnknown_ProfferService(void)
2290 IServiceProvider *provider = IServiceProviderImpl_Construct();
2291 IProfferService *proff = IProfferServiceImpl_Construct();
2292 static const GUID dummy_serviceid = { 0xdeadbeef };
2293 call_trace_t trace_expected;
2297 /* on <=W2K platforms same ordinal used for another export with different
2298 prototype, so skipping using this indirect condition */
2299 if (is_win2k_and_lower)
2301 win_skip("IUnknown_ProfferService is not available\n");
2305 /* null source pointer */
2306 hr = pIUnknown_ProfferService(NULL, &dummy_serviceid, 0, 0);
2307 ok(hr == E_FAIL, "got 0x%08x\n", hr);
2310 IUnknown_ProfferService( ptr1, serviceid, arg1, arg2);
2311 -> IUnknown_QueryInterface( ptr1, &IID_IServiceProvider, &provider );
2312 -> IServiceProvider_QueryService( provider, &IID_IProfferService, &IID_IProfferService, &proffer );
2314 if (service pointer not null):
2315 -> IProfferService_ProfferService( proffer, serviceid, arg1, arg2 );
2317 -> IProfferService_RevokeService( proffer, *arg2 );
2319 init_call_trace(&trace_expected);
2321 add_call(&trace_expected, 1, proff, &IID_IServiceProvider, 0, 0, 0);
2322 add_call(&trace_expected, 2, &IID_IProfferService, &IID_IProfferService, 0, 0, 0);
2323 add_call(&trace_expected, 3, &dummy_serviceid, provider, &cookie, 0, 0);
2325 init_call_trace(&trace_got);
2326 hr = pIUnknown_ProfferService((IUnknown*)proff, &dummy_serviceid, provider, &cookie);
2327 ok(hr == S_OK, "got 0x%08x\n", hr);
2329 ok_trace(&trace_expected, &trace_got);
2330 free_call_trace(&trace_got);
2331 free_call_trace(&trace_expected);
2333 /* same with ::Revoke path */
2334 init_call_trace(&trace_expected);
2336 add_call(&trace_expected, 1, proff, &IID_IServiceProvider, 0, 0, 0);
2337 add_call(&trace_expected, 2, &IID_IProfferService, &IID_IProfferService, 0, 0, 0);
2338 add_call(&trace_expected, 4, (void*)(DWORD_PTR)cookie, 0, 0, 0, 0);
2340 init_call_trace(&trace_got);
2341 hr = pIUnknown_ProfferService((IUnknown*)proff, &dummy_serviceid, 0, &cookie);
2342 ok(hr == S_OK, "got 0x%08x\n", hr);
2343 ok_trace(&trace_expected, &trace_got);
2344 free_call_trace(&trace_got);
2345 free_call_trace(&trace_expected);
2347 IServiceProvider_Release(provider);
2348 IProfferService_Release(proff);
2351 static void test_SHCreateWorkerWindowA(void)
2359 if (is_win2k_and_lower)
2361 win_skip("SHCreateWorkerWindowA not available\n");
2365 hwnd = pSHCreateWorkerWindowA(0, NULL, 0, 0, 0, 0);
2366 ok(hwnd != 0, "expected window\n");
2368 GetClassName(hwnd, classA, 20);
2369 ok(lstrcmpA(classA, "WorkerA") == 0, "expected WorkerA class, got %s\n", classA);
2371 ret = GetWindowLongPtrA(hwnd, 0);
2372 ok(ret == 0, "got %ld\n", ret);
2375 memset(&cliA, 0, sizeof(cliA));
2376 res = GetClassInfoA(GetModuleHandle("shlwapi.dll"), "WorkerA", &cliA);
2377 ok(res, "failed to get class info\n");
2378 ok(cliA.style == 0, "got 0x%08x\n", cliA.style);
2379 ok(cliA.cbClsExtra == 0, "got %d\n", cliA.cbClsExtra);
2380 ok(cliA.cbWndExtra == sizeof(LONG_PTR), "got %d\n", cliA.cbWndExtra);
2381 ok(cliA.lpszMenuName == 0, "got %s\n", cliA.lpszMenuName);
2383 DestroyWindow(hwnd);
2385 /* set extra bytes */
2386 hwnd = pSHCreateWorkerWindowA(0, NULL, 0, 0, 0, 0xdeadbeef);
2387 ok(hwnd != 0, "expected window\n");
2389 GetClassName(hwnd, classA, 20);
2390 ok(lstrcmpA(classA, "WorkerA") == 0, "expected WorkerA class, got %s\n", classA);
2392 ret = GetWindowLongPtrA(hwnd, 0);
2393 ok(ret == 0xdeadbeef, "got %ld\n", ret);
2396 ret = GetWindowLongA(hwnd, GWL_EXSTYLE);
2397 ok(ret == WS_EX_WINDOWEDGE ||
2398 ret == (WS_EX_WINDOWEDGE|WS_EX_LAYOUTRTL) /* systems with RTL locale */, "0x%08lx\n", ret);
2400 DestroyWindow(hwnd);
2402 hwnd = pSHCreateWorkerWindowA(0, NULL, WS_EX_TOOLWINDOW, 0, 0, 0);
2403 ret = GetWindowLongA(hwnd, GWL_EXSTYLE);
2404 ok(ret == (WS_EX_WINDOWEDGE|WS_EX_TOOLWINDOW) ||
2405 ret == (WS_EX_WINDOWEDGE|WS_EX_TOOLWINDOW|WS_EX_LAYOUTRTL) /* systems with RTL locale */, "0x%08lx\n", ret);
2406 DestroyWindow(hwnd);
2409 static HRESULT WINAPI SF_QueryInterface(IShellFolder *iface,
2410 REFIID riid, void **ppv)
2412 /* SHIShellFolder_EnumObjects doesn't QI the object for IShellFolder */
2413 ok(!IsEqualGUID(&IID_IShellFolder, riid),
2414 "Unexpected QI for IShellFolder\n");
2415 return E_NOINTERFACE;
2418 static ULONG WINAPI SF_AddRef(IShellFolder *iface)
2423 static ULONG WINAPI SF_Release(IShellFolder *iface)
2428 static HRESULT WINAPI SF_ParseDisplayName(IShellFolder *iface,
2429 HWND owner, LPBC reserved, LPOLESTR displayName, ULONG *eaten,
2430 LPITEMIDLIST *idl, ULONG *attr)
2432 ok(0, "Didn't expect ParseDisplayName\n");
2436 static HRESULT WINAPI SF_EnumObjects(IShellFolder *iface,
2437 HWND owner, SHCONTF flags, IEnumIDList **enm)
2439 *enm = (IEnumIDList*)0xcafebabe;
2443 static HRESULT WINAPI SF_BindToObject(IShellFolder *iface,
2444 LPCITEMIDLIST idl, LPBC reserved, REFIID riid, void **obj)
2446 ok(0, "Didn't expect BindToObject\n");
2450 static HRESULT WINAPI SF_BindToStorage(IShellFolder *iface,
2451 LPCITEMIDLIST idl, LPBC reserved, REFIID riid, void **obj)
2453 ok(0, "Didn't expect BindToStorage\n");
2457 static HRESULT WINAPI SF_CompareIDs(IShellFolder *iface,
2458 LPARAM lparam, LPCITEMIDLIST idl1, LPCITEMIDLIST idl2)
2460 ok(0, "Didn't expect CompareIDs\n");
2464 static HRESULT WINAPI SF_CreateViewObject(IShellFolder *iface,
2465 HWND owner, REFIID riid, void **out)
2467 ok(0, "Didn't expect CreateViewObject\n");
2471 static HRESULT WINAPI SF_GetAttributesOf(IShellFolder *iface,
2472 UINT cidl, LPCITEMIDLIST *idl, SFGAOF *inOut)
2474 ok(0, "Didn't expect GetAttributesOf\n");
2478 static HRESULT WINAPI SF_GetUIObjectOf(IShellFolder *iface,
2479 HWND owner, UINT cidl, LPCITEMIDLIST *idls, REFIID riid, UINT *inOut,
2482 ok(0, "Didn't expect GetUIObjectOf\n");
2486 static HRESULT WINAPI SF_GetDisplayNameOf(IShellFolder *iface,
2487 LPCITEMIDLIST idl, SHGDNF flags, STRRET *name)
2489 ok(0, "Didn't expect GetDisplayNameOf\n");
2493 static HRESULT WINAPI SF_SetNameOf(IShellFolder *iface,
2494 HWND hwnd, LPCITEMIDLIST idl, LPCOLESTR name, SHGDNF flags,
2495 LPITEMIDLIST *idlOut)
2497 ok(0, "Didn't expect SetNameOf\n");
2501 static IShellFolderVtbl ShellFolderVtbl = {
2505 SF_ParseDisplayName,
2510 SF_CreateViewObject,
2513 SF_GetDisplayNameOf,
2517 static IShellFolder ShellFolder = { &ShellFolderVtbl };
2519 static void test_SHIShellFolder_EnumObjects(void)
2523 IShellFolder *folder;
2525 if(!pSHIShellFolder_EnumObjects || is_win2k_and_lower){
2526 win_skip("SHIShellFolder_EnumObjects not available\n");
2531 /* NULL object crashes on Windows */
2532 hres = pSHIShellFolder_EnumObjects(NULL, NULL, 0, NULL);
2535 /* SHIShellFolder_EnumObjects doesn't QI the object for IShellFolder */
2536 enm = (IEnumIDList*)0xdeadbeef;
2537 hres = pSHIShellFolder_EnumObjects(&ShellFolder, NULL, 0, &enm);
2538 ok(hres == S_OK, "SHIShellFolder_EnumObjects failed: 0x%08x\n", hres);
2539 ok(enm == (IEnumIDList*)0xcafebabe, "Didn't get expected enumerator location, instead: %p\n", enm);
2541 /* SHIShellFolder_EnumObjects isn't strict about the IShellFolder object */
2542 hres = pSHGetDesktopFolder(&folder);
2543 ok(hres == S_OK, "SHGetDesktopFolder failed: 0x%08x\n", hres);
2546 hres = pSHIShellFolder_EnumObjects(folder, NULL, 0, &enm);
2547 ok(hres == S_OK, "SHIShellFolder_EnumObjects failed: 0x%08x\n", hres);
2548 ok(enm != NULL, "Didn't get an enumerator\n");
2550 IEnumIDList_Release(enm);
2552 IShellFolder_Release(folder);
2555 static void write_inifile(LPCWSTR filename)
2560 static const char data[] =
2563 "AnotherKey=asdf\r\n";
2565 file = CreateFileW(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
2566 if(file == INVALID_HANDLE_VALUE)
2569 WriteFile(file, data, sizeof(data), &written, NULL);
2574 #define verify_inifile(f, e) r_verify_inifile(__LINE__, f, e)
2575 static void r_verify_inifile(unsigned l, LPCWSTR filename, LPCSTR exp)
2581 file = CreateFileW(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
2582 if(file == INVALID_HANDLE_VALUE)
2585 ReadFile(file, buf, sizeof(buf) * sizeof(CHAR), &read, NULL);
2590 ok_(__FILE__,l)(!strcmp(buf, exp), "Expected:\n%s\nGot:\n%s\n", exp,
2594 static void test_SHGetIniString(void)
2597 WCHAR out[64] = {0};
2599 static const WCHAR TestAppW[] = {'T','e','s','t','A','p','p',0};
2600 static const WCHAR TestIniW[] = {'C',':','\\','t','e','s','t','.','i','n','i',0};
2601 static const WCHAR AKeyW[] = {'A','K','e','y',0};
2602 static const WCHAR AnotherKeyW[] = {'A','n','o','t','h','e','r','K','e','y',0};
2603 static const WCHAR JunkKeyW[] = {'J','u','n','k','K','e','y',0};
2605 if(!pSHGetIniStringW || is_win2k_and_lower){
2606 win_skip("SHGetIniStringW is not available\n");
2610 write_inifile(TestIniW);
2613 /* these crash on Windows */
2614 ret = pSHGetIniStringW(NULL, NULL, NULL, 0, NULL);
2615 ret = pSHGetIniStringW(NULL, AKeyW, out, sizeof(out), TestIniW);
2616 ret = pSHGetIniStringW(TestAppW, AKeyW, NULL, sizeof(out), TestIniW);
2619 ret = pSHGetIniStringW(TestAppW, AKeyW, out, 0, TestIniW);
2620 ok(ret == 0, "SHGetIniStringW should have given 0, instead: %d\n", ret);
2622 /* valid arguments */
2623 ret = pSHGetIniStringW(TestAppW, NULL, out, sizeof(out), TestIniW);
2624 ok(broken(ret == 0) || /* win 98 */
2625 ret == 4, "SHGetIniStringW should have given 4, instead: %d\n", ret);
2626 ok(!lstrcmpW(out, AKeyW), "Expected %s, got: %s\n",
2627 wine_dbgstr_w(AKeyW), wine_dbgstr_w(out));
2629 ret = pSHGetIniStringW(TestAppW, AKeyW, out, sizeof(out), TestIniW);
2630 ok(broken(ret == 0) || /* win 98 */
2631 ret == 1, "SHGetIniStringW should have given 1, instead: %d\n", ret);
2632 ok(broken(*out == 0) || /*win 98 */
2633 !strcmp_wa(out, "1"), "Expected L\"1\", got: %s\n", wine_dbgstr_w(out));
2635 ret = pSHGetIniStringW(TestAppW, AnotherKeyW, out, sizeof(out), TestIniW);
2636 ok(broken(ret == 0) || /* win 98 */
2637 ret == 4, "SHGetIniStringW should have given 4, instead: %d\n", ret);
2638 ok(broken(*out == 0) || /* win 98 */
2639 !strcmp_wa(out, "asdf"), "Expected L\"asdf\", got: %s\n", wine_dbgstr_w(out));
2641 ret = pSHGetIniStringW(TestAppW, JunkKeyW, out, sizeof(out), TestIniW);
2642 ok(ret == 0, "SHGetIniStringW should have given 0, instead: %d\n", ret);
2643 ok(*out == 0, "Expected L\"\", got: %s\n", wine_dbgstr_w(out));
2645 DeleteFileW(TestIniW);
2648 static void test_SHSetIniString(void)
2652 static const WCHAR TestAppW[] = {'T','e','s','t','A','p','p',0};
2653 static const WCHAR AnotherAppW[] = {'A','n','o','t','h','e','r','A','p','p',0};
2654 static const WCHAR TestIniW[] = {'C',':','\\','t','e','s','t','.','i','n','i',0};
2655 static const WCHAR AKeyW[] = {'A','K','e','y',0};
2656 static const WCHAR NewKeyW[] = {'N','e','w','K','e','y',0};
2657 static const WCHAR AValueW[] = {'A','V','a','l','u','e',0};
2659 if(!pSHSetIniStringW || is_win2k_and_lower){
2660 win_skip("SHSetIniStringW is not available\n");
2664 write_inifile(TestIniW);
2666 ret = pSHSetIniStringW(TestAppW, AKeyW, AValueW, TestIniW);
2667 ok(ret == TRUE, "SHSetIniStringW should not have failed\n");
2668 todo_wine /* wine sticks an extra \r\n at the end of the file */
2669 verify_inifile(TestIniW, "[TestApp]\r\nAKey=AValue\r\nAnotherKey=asdf\r\n");
2671 ret = pSHSetIniStringW(TestAppW, AKeyW, NULL, TestIniW);
2672 ok(ret == TRUE, "SHSetIniStringW should not have failed\n");
2673 verify_inifile(TestIniW, "[TestApp]\r\nAnotherKey=asdf\r\n");
2675 ret = pSHSetIniStringW(AnotherAppW, NewKeyW, AValueW, TestIniW);
2676 ok(ret == TRUE, "SHSetIniStringW should not have failed\n");
2677 verify_inifile(TestIniW, "[TestApp]\r\nAnotherKey=asdf\r\n[AnotherApp]\r\nNewKey=AValue\r\n");
2679 ret = pSHSetIniStringW(TestAppW, NULL, AValueW, TestIniW);
2680 ok(ret == TRUE, "SHSetIniStringW should not have failed\n");
2681 verify_inifile(TestIniW, "[AnotherApp]\r\nNewKey=AValue\r\n");
2683 DeleteFileW(TestIniW);
2686 enum _shellkey_flags {
2687 SHKEY_Root_HKCU = 0x1,
2688 SHKEY_Root_HKLM = 0x2,
2689 SHKEY_Key_Explorer = 0x00,
2690 SHKEY_Key_Shell = 0x10,
2691 SHKEY_Key_ShellNoRoam = 0x20,
2692 SHKEY_Key_Classes = 0x30,
2693 SHKEY_Subkey_Default = 0x0000,
2694 SHKEY_Subkey_ResourceName = 0x1000,
2695 SHKEY_Subkey_Handlers = 0x2000,
2696 SHKEY_Subkey_Associations = 0x3000,
2697 SHKEY_Subkey_Volatile = 0x4000,
2698 SHKEY_Subkey_MUICache = 0x5000,
2699 SHKEY_Subkey_FileExts = 0x6000
2702 static void test_SHGetShellKey(void)
2704 static const WCHAR ShellFoldersW[] = { 'S','h','e','l','l',' ','F','o','l','d','e','r','s',0 };
2705 static const WCHAR WineTestW[] = { 'W','i','n','e','T','e','s','t',0 };
2707 void *pPathBuildRootW = GetProcAddress(hShlwapi, "PathBuildRootW");
2708 DWORD *alloc_data, data, size;
2712 if (!pSHGetShellKey)
2714 win_skip("SHGetShellKey(ordinal 491) isn't available\n");
2719 if (pPathBuildRootW && pPathBuildRootW == pSHGetShellKey)
2721 win_skip("SHGetShellKey(ordinal 491) used for PathBuildRootW\n");
2725 if (is_win9x || is_win2k_and_lower)
2727 win_skip("Ordinal 491 used for another call, skipping SHGetShellKey tests\n");
2731 /* Vista+ limits SHKEY enumeration values */
2732 SetLastError(0xdeadbeef);
2733 hkey = pSHGetShellKey(SHKEY_Key_Explorer, ShellFoldersW, FALSE);
2736 /* Tests not working on Vista+ */
2739 hkey = pSHGetShellKey(SHKEY_Root_HKLM|SHKEY_Key_Classes, NULL, FALSE);
2740 ok(hkey != NULL, "hkey = NULL\n");
2744 hkey = pSHGetShellKey(SHKEY_Root_HKCU|SHKEY_Key_Explorer, ShellFoldersW, FALSE);
2745 ok(hkey != NULL, "hkey = NULL\n");
2748 hkey = pSHGetShellKey(SHKEY_Root_HKLM|SHKEY_Key_Explorer, ShellFoldersW, FALSE);
2749 ok(hkey != NULL, "hkey = NULL\n");
2752 hkey = pSHGetShellKey(SHKEY_Root_HKLM, WineTestW, FALSE);
2753 ok(hkey == NULL, "hkey != NULL\n");
2755 hkey = pSHGetShellKey(SHKEY_Root_HKLM, WineTestW, TRUE);
2756 ok(hkey != NULL, "Can't create key\n");
2759 hkey = pSHGetShellKey(SHKEY_Root_HKLM, NULL, FALSE);
2760 ok(hkey != NULL, "Can't create key\n");
2761 ok(SUCCEEDED(RegDeleteKeyW(hkey, WineTestW)), "Can't delte key\n");
2764 if (!pSKGetValueW || !pSKSetValueW || !pSKDeleteValueW || !pSKAllocValueW)
2766 win_skip("SKGetValueW, SKSetValueW, SKDeleteValueW or SKAllocValueW not available\n");
2770 hres = pSKGetValueW(SHKEY_Root_HKLM, WineTestW, NULL, NULL, &data, &size);
2771 ok(hres == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "hres = %x\n", hres);
2774 hres = pSKSetValueW(SHKEY_Root_HKLM, WineTestW, NULL, REG_DWORD, &data, sizeof(DWORD));
2775 ok(hres == S_OK, "hres = %x\n", hres);
2778 hres = pSKGetValueW(SHKEY_Root_HKLM, WineTestW, NULL, NULL, NULL, &size);
2779 ok(hres == S_OK, "hres = %x\n", hres);
2780 ok(size == sizeof(DWORD), "size = %d\n", size);
2783 hres = pSKGetValueW(SHKEY_Root_HKLM, WineTestW, NULL, NULL, &data, &size);
2784 ok(hres == S_OK, "hres = %x\n", hres);
2785 ok(size == sizeof(DWORD), "size = %d\n", size);
2786 ok(data == 1234, "data = %d\n", data);
2788 hres = pSKAllocValueW(SHKEY_Root_HKLM, WineTestW, NULL, NULL, (void**)&alloc_data, &size);
2789 ok(hres == S_OK, "hres= %x\n", hres);
2790 ok(size == sizeof(DWORD), "size = %d\n", size);
2791 ok(*alloc_data == 1234, "*alloc_data = %d\n", *alloc_data);
2792 LocalFree(alloc_data);
2794 hres = pSKDeleteValueW(SHKEY_Root_HKLM, WineTestW, NULL);
2795 ok(hres == S_OK, "hres = %x\n", hres);
2797 hres = pSKDeleteValueW(SHKEY_Root_HKLM, WineTestW, NULL);
2798 ok(hres == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "hres = %x\n", hres);
2800 hres = pSKGetValueW(SHKEY_Root_HKLM, WineTestW, NULL, NULL, &data, &size);
2801 ok(hres == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "hres = %x\n", hres);
2803 hkey = pSHGetShellKey(SHKEY_Root_HKLM, NULL, FALSE);
2804 ok(hkey != NULL, "Can't create key\n");
2805 ok(SUCCEEDED(RegDeleteKeyW(hkey, WineTestW)), "Can't delte key\n");
2809 static void init_pointers(void)
2811 #define MAKEFUNC(f, ord) (p##f = (void*)GetProcAddress(hShlwapi, (LPSTR)(ord)))
2812 MAKEFUNC(SHAllocShared, 7);
2813 MAKEFUNC(SHLockShared, 8);
2814 MAKEFUNC(SHUnlockShared, 9);
2815 MAKEFUNC(SHFreeShared, 10);
2816 MAKEFUNC(GetAcceptLanguagesA, 14);
2817 MAKEFUNC(SHSetWindowBits, 165);
2818 MAKEFUNC(ConnectToConnectionPoint, 168);
2819 MAKEFUNC(SHSearchMapInt, 198);
2820 MAKEFUNC(SHCreateWorkerWindowA, 257);
2821 MAKEFUNC(GUIDFromStringA, 269);
2822 MAKEFUNC(SHPackDispParams, 282);
2823 MAKEFUNC(IConnectionPoint_InvokeWithCancel, 283);
2824 MAKEFUNC(IConnectionPoint_SimpleInvoke, 284);
2825 MAKEFUNC(SHGetIniStringW, 294);
2826 MAKEFUNC(SHSetIniStringW, 295);
2827 MAKEFUNC(SHFormatDateTimeA, 353);
2828 MAKEFUNC(SHFormatDateTimeW, 354);
2829 MAKEFUNC(SHIShellFolder_EnumObjects, 404);
2830 MAKEFUNC(SHGetObjectCompatFlags, 476);
2831 MAKEFUNC(IUnknown_QueryServiceExec, 484);
2832 MAKEFUNC(SHGetShellKey, 491);
2833 MAKEFUNC(SHPropertyBag_ReadLONG, 496);
2834 MAKEFUNC(IUnknown_ProfferService, 514);
2835 MAKEFUNC(SKGetValueW, 516);
2836 MAKEFUNC(SKSetValueW, 517);
2837 MAKEFUNC(SKDeleteValueW, 518);
2838 MAKEFUNC(SKAllocValueW, 519);
2844 hShlwapi = GetModuleHandleA("shlwapi.dll");
2845 is_win2k_and_lower = GetProcAddress(hShlwapi, "StrChrNW") == 0;
2846 is_win9x = GetProcAddress(hShlwapi, (LPSTR)99) == 0; /* StrCpyNXA */
2848 /* SHCreateStreamOnFileEx was introduced in shlwapi v6.0 */
2849 if(!GetProcAddress(hShlwapi, "SHCreateStreamOnFileEx")){
2850 win_skip("Too old shlwapi version\n");
2856 hmlang = LoadLibraryA("mlang.dll");
2857 pLcidToRfc1766A = (void *)GetProcAddress(hmlang, "LcidToRfc1766A");
2859 hshell32 = LoadLibraryA("shell32.dll");
2860 pSHGetDesktopFolder = (void *)GetProcAddress(hshell32, "SHGetDesktopFolder");
2862 test_GetAcceptLanguagesA();
2863 test_SHSearchMapInt();
2864 test_alloc_shared();
2866 test_GetShellSecurityDescriptor();
2867 test_SHPackDispParams();
2868 test_IConnectionPoint();
2869 test_SHPropertyBag_ReadLONG();
2870 test_SHSetWindowBits();
2871 test_SHFormatDateTimeA();
2872 test_SHFormatDateTimeW();
2873 test_SHGetObjectCompatFlags();
2874 test_IUnknown_QueryServiceExec();
2875 test_IUnknown_ProfferService();
2876 test_SHCreateWorkerWindowA();
2877 test_SHIShellFolder_EnumObjects();
2878 test_SHGetIniString();
2879 test_SHSetIniString();
2880 test_SHGetShellKey();
2882 FreeLibrary(hshell32);
2883 FreeLibrary(hmlang);