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;
40 static int (WINAPI *pSHSearchMapInt)(const int*,const int*,int,int);
41 static HRESULT (WINAPI *pGetAcceptLanguagesA)(LPSTR,LPDWORD);
43 static HANDLE (WINAPI *pSHAllocShared)(LPCVOID,DWORD,DWORD);
44 static LPVOID (WINAPI *pSHLockShared)(HANDLE,DWORD);
45 static BOOL (WINAPI *pSHUnlockShared)(LPVOID);
46 static BOOL (WINAPI *pSHFreeShared)(HANDLE,DWORD);
47 static HRESULT(WINAPIV *pSHPackDispParams)(DISPPARAMS*,VARIANTARG*,UINT,...);
48 static HRESULT(WINAPI *pIConnectionPoint_SimpleInvoke)(IConnectionPoint*,DISPID,DISPPARAMS*);
49 static HRESULT(WINAPI *pIConnectionPoint_InvokeWithCancel)(IConnectionPoint*,DISPID,DISPPARAMS*,DWORD,DWORD);
50 static HRESULT(WINAPI *pConnectToConnectionPoint)(IUnknown*,REFIID,BOOL,IUnknown*, LPDWORD,IConnectionPoint **);
51 static HRESULT(WINAPI *pSHPropertyBag_ReadLONG)(IPropertyBag *,LPCWSTR,LPLONG);
52 static LONG (WINAPI *pSHSetWindowBits)(HWND, INT, UINT, UINT);
53 static INT (WINAPI *pSHFormatDateTimeA)(const FILETIME UNALIGNED*, DWORD*, LPSTR, UINT);
54 static INT (WINAPI *pSHFormatDateTimeW)(const FILETIME UNALIGNED*, DWORD*, LPWSTR, UINT);
55 static DWORD (WINAPI *pSHGetObjectCompatFlags)(IUnknown*, const CLSID*);
56 static BOOL (WINAPI *pGUIDFromStringA)(LPSTR, CLSID *);
57 static HRESULT (WINAPI *pIUnknown_QueryServiceExec)(IUnknown*, REFIID, const GUID*, DWORD, DWORD, VARIANT*, VARIANT*);
58 static HRESULT (WINAPI *pIUnknown_ProfferService)(IUnknown*, REFGUID, IServiceProvider*, DWORD*);
59 static HWND (WINAPI *pSHCreateWorkerWindowA)(LONG, HWND, DWORD, DWORD, HMENU, LONG_PTR);
60 static HRESULT (WINAPI *pSHIShellFolder_EnumObjects)(LPSHELLFOLDER, HWND, SHCONTF, IEnumIDList**);
61 static DWORD (WINAPI *pSHGetIniStringW)(LPCWSTR, LPCWSTR, LPWSTR, DWORD, LPCWSTR);
63 static HMODULE hmlang;
64 static HRESULT (WINAPI *pLcidToRfc1766A)(LCID, LPSTR, INT);
66 static const CHAR ie_international[] = {
67 'S','o','f','t','w','a','r','e','\\',
68 'M','i','c','r','o','s','o','f','t','\\',
69 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
70 'I','n','t','e','r','n','a','t','i','o','n','a','l',0};
71 static const CHAR acceptlanguage[] = {
72 'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0};
74 static int strcmp_wa(LPCWSTR strw, const char *stra)
77 WideCharToMultiByte(CP_ACP, 0, strw, -1, buf, sizeof(buf), NULL, NULL);
78 return lstrcmpA(stra, buf);
92 static void init_call_trace(call_trace_t *ctrace)
96 ctrace->calls = HeapAlloc(GetProcessHeap(), 0, sizeof(call_entry_t) * ctrace->alloc);
99 static void free_call_trace(const call_trace_t *ctrace)
101 HeapFree(GetProcessHeap(), 0, ctrace->calls);
104 static void add_call(call_trace_t *ctrace, int id, const void *arg0,
105 const void *arg1, const void *arg2, const void *arg3, const void *arg4)
116 if (ctrace->count == ctrace->alloc)
119 ctrace->calls = HeapReAlloc(GetProcessHeap(),0, ctrace->calls, ctrace->alloc*sizeof(call_entry_t));
122 ctrace->calls[ctrace->count++] = call;
125 static void ok_trace_(call_trace_t *texpected, call_trace_t *tgot, int line)
127 if (texpected->count == tgot->count)
131 for (i = 0; i < texpected->count; i++)
133 call_entry_t *expected = &texpected->calls[i];
134 call_entry_t *got = &tgot->calls[i];
137 ok_(__FILE__, line)(expected->id == got->id, "got different ids %d: %d, %d\n", i+1, expected->id, got->id);
139 for (j = 0; j < 5; j++)
141 ok_(__FILE__, line)(expected->args[j] == got->args[j], "got different args[%d] for %d: %p, %p\n", j, i+1,
142 expected->args[j], got->args[j]);
147 ok_(__FILE__, line)(0, "traces length mismatch\n");
150 #define ok_trace(a, b) ok_trace_(a, b, __LINE__)
152 /* trace of actually made calls */
153 static call_trace_t trace_got;
155 static void test_GetAcceptLanguagesA(void)
157 static LPCSTR table[] = {"de,en-gb;q=0.7,en;q=0.3",
158 "de,en;q=0.3,en-gb;q=0.7", /* sorting is ignored */
159 "winetest", /* content is ignored */
169 LONG res_query = ERROR_SUCCESS;
172 DWORD maxlen = sizeof(buffer) - 2;
178 if (!pGetAcceptLanguagesA) {
179 win_skip("GetAcceptLanguagesA is not available\n");
183 lcid = GetUserDefaultLCID();
185 /* Get the original Value */
186 lres = RegOpenKeyA(HKEY_CURRENT_USER, ie_international, &hroot);
188 skip("RegOpenKey(%s) failed: %d\n", ie_international, lres);
191 len = sizeof(original);
193 res_query = RegQueryValueExA(hroot, acceptlanguage, 0, NULL, (PBYTE)original, &len);
195 RegDeleteValue(hroot, acceptlanguage);
197 /* Some windows versions use "lang-COUNTRY" as default */
198 memset(language, 0, sizeof(language));
199 len = GetLocaleInfoA(lcid, LOCALE_SISO639LANGNAME, language, sizeof(language));
202 lstrcat(language, "-");
203 memset(buffer, 0, sizeof(buffer));
204 len = GetLocaleInfoA(lcid, LOCALE_SISO3166CTRYNAME, buffer, sizeof(buffer) - len - 1);
205 lstrcat(language, buffer);
209 /* LOCALE_SNAME has additional parts in some languages. Try only as last chance */
210 memset(language, 0, sizeof(language));
211 len = GetLocaleInfoA(lcid, LOCALE_SNAME, language, sizeof(language));
214 /* get the default value */
216 memset(buffer, '#', maxlen);
218 hr = pGetAcceptLanguagesA( buffer, &len);
221 win_skip("GetAcceptLanguagesA failed with 0x%x\n", hr);
222 goto restore_original;
225 if (lstrcmpA(buffer, language)) {
226 /* some windows versions use "lang" or "lang-country" as default */
228 if (pLcidToRfc1766A) {
229 hr = pLcidToRfc1766A(lcid, language, sizeof(language));
230 ok(hr == S_OK, "LcidToRfc1766A returned 0x%x and %s\n", hr, language);
234 ok(!lstrcmpA(buffer, language),
235 "have '%s' (searching for '%s')\n", language, buffer);
237 if (lstrcmpA(buffer, language)) {
238 win_skip("no more ideas, how to build the default language '%s'\n", buffer);
239 goto restore_original;
242 trace("detected default: %s\n", language);
243 while ((entry = table[i])) {
245 exactsize = lstrlenA(entry);
247 lres = RegSetValueExA(hroot, acceptlanguage, 0, REG_SZ, (const BYTE *) entry, exactsize + 1);
248 ok(!lres, "got %d for RegSetValueExA: %s\n", lres, entry);
250 /* len includes space for the terminating 0 before vista/w2k8 */
252 memset(buffer, '#', maxlen);
254 hr = pGetAcceptLanguagesA( buffer, &len);
255 ok(((hr == E_INVALIDARG) && (len == 0)) ||
257 ((len == exactsize) || (len == exactsize+1)) &&
258 !lstrcmpA(buffer, entry)),
259 "+2_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
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 "+1_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
272 memset(buffer, '#', maxlen);
274 hr = pGetAcceptLanguagesA( buffer, &len);
276 /* There is no space for the string in the registry.
277 When the buffer is large enough, the default language is returned
279 When the buffer is too small for that fallback, win7_32 and w2k8_64
280 and above fail with HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), but
281 recent os succeed and return a partial result while
282 older os succeed and overflow the buffer */
284 ok(((hr == E_INVALIDARG) && (len == 0)) ||
285 (((hr == S_OK) && !lstrcmpA(buffer, language) && (len == lstrlenA(language))) ||
286 ((hr == S_OK) && !memcmp(buffer, language, len)) ||
287 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len)),
288 "==_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
292 memset(buffer, '#', maxlen);
294 hr = pGetAcceptLanguagesA( buffer, &len);
295 ok(((hr == E_INVALIDARG) && (len == 0)) ||
296 (((hr == S_OK) && !lstrcmpA(buffer, language) && (len == lstrlenA(language))) ||
297 ((hr == S_OK) && !memcmp(buffer, language, len)) ||
298 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len)),
299 "-1_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
303 memset(buffer, '#', maxlen);
305 hr = pGetAcceptLanguagesA( buffer, &len);
306 ok(((hr == E_INVALIDARG) && (len == 0)) ||
307 (((hr == S_OK) && !lstrcmpA(buffer, language) && (len == lstrlenA(language))) ||
308 ((hr == S_OK) && !memcmp(buffer, language, len)) ||
309 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len)),
310 "=1_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
313 hr = pGetAcceptLanguagesA( NULL, &len);
315 /* w2k3 and below: E_FAIL and untouched len,
316 since w2k8: S_OK and needed size (excluding 0) */
317 ok( ((hr == S_OK) && (len == exactsize)) ||
318 ((hr == E_FAIL) && (len == maxlen)),
319 "NULL,max #%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
324 /* without a value in the registry, a default language is returned */
325 RegDeleteValue(hroot, acceptlanguage);
328 memset(buffer, '#', maxlen);
330 hr = pGetAcceptLanguagesA( buffer, &len);
331 ok( ((hr == S_OK) && (len == lstrlenA(language))),
332 "max: got 0x%x with %d and %s (expected S_OK with %d and '%s'\n",
333 hr, len, buffer, lstrlenA(language), language);
336 memset(buffer, '#', maxlen);
338 hr = pGetAcceptLanguagesA( buffer, &len);
339 ok( (((hr == S_OK) || (hr == E_INVALIDARG)) && !memcmp(buffer, language, len)) ||
340 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len),
341 "=2: got 0x%x with %d and %s\n", hr, len, buffer);
344 memset(buffer, '#', maxlen);
346 hr = pGetAcceptLanguagesA( buffer, &len);
347 /* When the buffer is too small, win7_32 and w2k8_64 and above fail with
348 HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), other versions suceed
349 and return a partial 0 terminated result while other versions
350 fail with E_INVALIDARG and return a partial unterminated result */
351 ok( (((hr == S_OK) || (hr == E_INVALIDARG)) && !memcmp(buffer, language, len)) ||
352 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len),
353 "=1: got 0x%x with %d and %s\n", hr, len, buffer);
356 memset(buffer, '#', maxlen);
358 hr = pGetAcceptLanguagesA( buffer, &len);
359 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
360 ok((hr == E_FAIL) || (hr == E_INVALIDARG),
361 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr);
363 memset(buffer, '#', maxlen);
365 hr = pGetAcceptLanguagesA( buffer, NULL);
366 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
367 ok((hr == E_FAIL) || (hr == E_INVALIDARG),
368 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr);
371 hr = pGetAcceptLanguagesA( NULL, NULL);
372 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
373 ok((hr == E_FAIL) || (hr == E_INVALIDARG),
374 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr);
378 len = lstrlenA(original);
379 lres = RegSetValueExA(hroot, acceptlanguage, 0, REG_SZ, (const BYTE *) original, len ? len + 1: 0);
380 ok(!lres, "RegSetValueEx(%s) failed: %d\n", original, lres);
384 RegDeleteValue(hroot, acceptlanguage);
389 static void test_SHSearchMapInt(void)
391 int keys[8], values[8];
394 if (!pSHSearchMapInt)
397 memset(keys, 0, sizeof(keys));
398 memset(values, 0, sizeof(values));
399 keys[0] = 99; values[0] = 101;
401 /* NULL key/value lists crash native, so skip testing them */
404 i = pSHSearchMapInt(keys, values, 1, keys[0]);
405 ok(i == values[0], "Len 1, expected %d, got %d\n", values[0], i);
407 /* Key doesn't exist */
408 i = pSHSearchMapInt(keys, values, 1, 100);
409 ok(i == -1, "Len 1 - bad key, expected -1, got %d\n", i);
411 /* Len = 0 => not found */
412 i = pSHSearchMapInt(keys, values, 0, keys[0]);
413 ok(i == -1, "Len 1 - passed len 0, expected -1, got %d\n", i);
415 /* 2 elements, len = 1 */
416 keys[1] = 98; values[1] = 102;
417 i = pSHSearchMapInt(keys, values, 1, keys[1]);
418 ok(i == -1, "Len 1 - array len 2, expected -1, got %d\n", i);
420 /* 2 elements, len = 2 */
421 i = pSHSearchMapInt(keys, values, 2, keys[1]);
422 ok(i == values[1], "Len 2, expected %d, got %d\n", values[1], i);
424 /* Searches forward */
425 keys[2] = 99; values[2] = 103;
426 i = pSHSearchMapInt(keys, values, 3, keys[0]);
427 ok(i == values[0], "Len 3, expected %d, got %d\n", values[0], i);
430 static void test_alloc_shared(void)
438 procid=GetCurrentProcessId();
439 hmem=pSHAllocShared(NULL,10,procid);
440 ok(hmem!=NULL,"SHAllocShared(NULL...) failed: %u\n", GetLastError());
441 ret = pSHFreeShared(hmem, procid);
442 ok( ret, "SHFreeShared failed: %u\n", GetLastError());
445 hmem=pSHAllocShared(&val,4,procid);
446 ok(hmem!=NULL,"SHAllocShared(NULL...) failed: %u\n", GetLastError());
448 p=pSHLockShared(hmem,procid);
449 ok(p!=NULL,"SHLockShared failed: %u\n", GetLastError());
451 ok(*p==val,"Wrong value in shared memory: %d instead of %d\n",*p,val);
452 ret = pSHUnlockShared(p);
453 ok( ret, "SHUnlockShared failed: %u\n", GetLastError());
455 ret = pSHFreeShared(hmem, procid);
456 ok( ret, "SHFreeShared failed: %u\n", GetLastError());
459 static void test_fdsa(void)
463 DWORD num_items; /* Number of elements inserted */
464 void *mem; /* Ptr to array */
465 DWORD blocks_alloced; /* Number of elements allocated */
466 BYTE inc; /* Number of elements to grow by when we need to expand */
467 BYTE block_size; /* Size in bytes of an element */
468 BYTE flags; /* Flags */
471 BOOL (WINAPI *pFDSA_Initialize)(DWORD block_size, DWORD inc, FDSA_info *info, void *mem,
473 BOOL (WINAPI *pFDSA_Destroy)(FDSA_info *info);
474 DWORD (WINAPI *pFDSA_InsertItem)(FDSA_info *info, DWORD where, const void *block);
475 BOOL (WINAPI *pFDSA_DeleteItem)(FDSA_info *info, DWORD where);
478 int block_size = 10, init_blocks = 4, inc = 2;
482 pFDSA_Initialize = (void *)GetProcAddress(hShlwapi, (LPSTR)208);
483 pFDSA_Destroy = (void *)GetProcAddress(hShlwapi, (LPSTR)209);
484 pFDSA_InsertItem = (void *)GetProcAddress(hShlwapi, (LPSTR)210);
485 pFDSA_DeleteItem = (void *)GetProcAddress(hShlwapi, (LPSTR)211);
487 mem = HeapAlloc(GetProcessHeap(), 0, block_size * init_blocks);
488 memset(&info, 0, sizeof(info));
490 ok(pFDSA_Initialize(block_size, inc, &info, mem, init_blocks), "FDSA_Initialize rets FALSE\n");
491 ok(info.num_items == 0, "num_items = %d\n", info.num_items);
492 ok(info.mem == mem, "mem = %p\n", info.mem);
493 ok(info.blocks_alloced == init_blocks, "blocks_alloced = %d\n", info.blocks_alloced);
494 ok(info.inc == inc, "inc = %d\n", info.inc);
495 ok(info.block_size == block_size, "block_size = %d\n", info.block_size);
496 ok(info.flags == 0, "flags = %d\n", info.flags);
498 ret = pFDSA_InsertItem(&info, 1234, "1234567890");
499 ok(ret == 0, "ret = %d\n", ret);
500 ok(info.num_items == 1, "num_items = %d\n", info.num_items);
501 ok(info.mem == mem, "mem = %p\n", info.mem);
502 ok(info.blocks_alloced == init_blocks, "blocks_alloced = %d\n", info.blocks_alloced);
503 ok(info.inc == inc, "inc = %d\n", info.inc);
504 ok(info.block_size == block_size, "block_size = %d\n", info.block_size);
505 ok(info.flags == 0, "flags = %d\n", info.flags);
507 ret = pFDSA_InsertItem(&info, 1234, "abcdefghij");
508 ok(ret == 1, "ret = %d\n", ret);
510 ret = pFDSA_InsertItem(&info, 1, "klmnopqrst");
511 ok(ret == 1, "ret = %d\n", ret);
513 ret = pFDSA_InsertItem(&info, 0, "uvwxyzABCD");
514 ok(ret == 0, "ret = %d\n", ret);
515 ok(info.mem == mem, "mem = %p\n", info.mem);
516 ok(info.flags == 0, "flags = %d\n", info.flags);
518 /* This next InsertItem will cause shlwapi to allocate its own mem buffer */
519 ret = pFDSA_InsertItem(&info, 0, "EFGHIJKLMN");
520 ok(ret == 0, "ret = %d\n", ret);
521 ok(info.mem != mem, "mem = %p\n", info.mem);
522 ok(info.blocks_alloced == init_blocks + inc, "blocks_alloced = %d\n", info.blocks_alloced);
523 ok(info.flags == 0x1, "flags = %d\n", info.flags);
525 ok(!memcmp(info.mem, "EFGHIJKLMNuvwxyzABCD1234567890klmnopqrstabcdefghij", 50), "mem %s\n", (char*)info.mem);
527 ok(pFDSA_DeleteItem(&info, 2), "rets FALSE\n");
528 ok(info.mem != mem, "mem = %p\n", info.mem);
529 ok(info.blocks_alloced == init_blocks + inc, "blocks_alloced = %d\n", info.blocks_alloced);
530 ok(info.flags == 0x1, "flags = %d\n", info.flags);
532 ok(!memcmp(info.mem, "EFGHIJKLMNuvwxyzABCDklmnopqrstabcdefghij", 40), "mem %s\n", (char*)info.mem);
534 ok(pFDSA_DeleteItem(&info, 3), "rets FALSE\n");
535 ok(info.mem != mem, "mem = %p\n", info.mem);
536 ok(info.blocks_alloced == init_blocks + inc, "blocks_alloced = %d\n", info.blocks_alloced);
537 ok(info.flags == 0x1, "flags = %d\n", info.flags);
539 ok(!memcmp(info.mem, "EFGHIJKLMNuvwxyzABCDklmnopqrst", 30), "mem %s\n", (char*)info.mem);
541 ok(!pFDSA_DeleteItem(&info, 4), "does not ret FALSE\n");
543 /* As shlwapi has allocated memory internally, Destroy will ret FALSE */
544 ok(!pFDSA_Destroy(&info), "FDSA_Destroy does not ret FALSE\n");
547 /* When Initialize is called with inc = 0, set it to 1 */
548 ok(pFDSA_Initialize(block_size, 0, &info, mem, init_blocks), "FDSA_Initialize rets FALSE\n");
549 ok(info.inc == 1, "inc = %d\n", info.inc);
551 /* This time, because shlwapi hasn't had to allocate memory
552 internally, Destroy rets non-zero */
553 ok(pFDSA_Destroy(&info), "FDSA_Destroy rets FALSE\n");
556 HeapFree(GetProcessHeap(), 0, mem);
560 typedef struct SHELL_USER_SID {
561 SID_IDENTIFIER_AUTHORITY sidAuthority;
564 } SHELL_USER_SID, *PSHELL_USER_SID;
565 typedef struct SHELL_USER_PERMISSION {
566 SHELL_USER_SID susID;
571 DWORD dwInheritAccessMask;
572 } SHELL_USER_PERMISSION, *PSHELL_USER_PERMISSION;
573 static void test_GetShellSecurityDescriptor(void)
575 SHELL_USER_PERMISSION supCurrentUserFull = {
576 { {SECURITY_NULL_SID_AUTHORITY}, 0, 0 },
577 ACCESS_ALLOWED_ACE_TYPE, FALSE,
579 #define MY_INHERITANCE 0xBE /* invalid value to proof behavior */
580 SHELL_USER_PERMISSION supEveryoneDenied = {
581 { {SECURITY_WORLD_SID_AUTHORITY}, SECURITY_WORLD_RID, 0 },
582 ACCESS_DENIED_ACE_TYPE, TRUE,
583 GENERIC_WRITE, MY_INHERITANCE | 0xDEADBA00, GENERIC_READ };
584 PSHELL_USER_PERMISSION rgsup[2] = {
585 &supCurrentUserFull, &supEveryoneDenied,
587 SECURITY_DESCRIPTOR* psd;
588 SECURITY_DESCRIPTOR* (WINAPI*pGetShellSecurityDescriptor)(PSHELL_USER_PERMISSION*,int);
590 pGetShellSecurityDescriptor=(void*)GetProcAddress(hShlwapi,(char*)475);
592 if(!pGetShellSecurityDescriptor)
594 win_skip("GetShellSecurityDescriptor not available\n");
598 psd = pGetShellSecurityDescriptor(NULL, 2);
600 broken(psd==INVALID_HANDLE_VALUE), /* IE5 */
601 "GetShellSecurityDescriptor should fail\n");
602 psd = pGetShellSecurityDescriptor(rgsup, 0);
603 ok(psd==NULL, "GetShellSecurityDescriptor should fail\n");
605 SetLastError(0xdeadbeef);
606 psd = pGetShellSecurityDescriptor(rgsup, 2);
607 if (psd == NULL && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
609 /* The previous calls to GetShellSecurityDescriptor don't set the last error */
610 win_skip("GetShellSecurityDescriptor is not implemented\n");
613 if (psd==INVALID_HANDLE_VALUE)
615 win_skip("GetShellSecurityDescriptor is broken on IE5\n");
618 ok(psd!=NULL, "GetShellSecurityDescriptor failed\n");
621 BOOL bHasDacl = FALSE, bDefaulted;
624 SECURITY_DESCRIPTOR_CONTROL control;
626 ok(IsValidSecurityDescriptor(psd), "returned value is not valid SD\n");
628 ok(GetSecurityDescriptorControl(psd, &control, &dwRev),
629 "GetSecurityDescriptorControl failed with error %u\n", GetLastError());
630 ok(0 == (control & SE_SELF_RELATIVE), "SD should be absolute\n");
632 ok(GetSecurityDescriptorDacl(psd, &bHasDacl, &pAcl, &bDefaulted),
633 "GetSecurityDescriptorDacl failed with error %u\n", GetLastError());
635 ok(bHasDacl, "SD has no DACL\n");
638 ok(!bDefaulted, "DACL should not be defaulted\n");
640 ok(pAcl != NULL, "NULL DACL!\n");
643 ACL_SIZE_INFORMATION asiSize;
645 ok(IsValidAcl(pAcl), "DACL is not valid\n");
647 ok(GetAclInformation(pAcl, &asiSize, sizeof(asiSize), AclSizeInformation),
648 "GetAclInformation failed with error %u\n", GetLastError());
650 ok(asiSize.AceCount == 3, "Incorrect number of ACEs: %d entries\n", asiSize.AceCount);
651 if (asiSize.AceCount == 3)
653 ACCESS_ALLOWED_ACE *paaa; /* will use for DENIED too */
655 ok(GetAce(pAcl, 0, (LPVOID*)&paaa), "GetAce failed with error %u\n", GetLastError());
656 ok(paaa->Header.AceType == ACCESS_ALLOWED_ACE_TYPE,
657 "Invalid ACE type %d\n", paaa->Header.AceType);
658 ok(paaa->Header.AceFlags == 0, "Invalid ACE flags %x\n", paaa->Header.AceFlags);
659 ok(paaa->Mask == GENERIC_ALL, "Invalid ACE mask %x\n", paaa->Mask);
661 ok(GetAce(pAcl, 1, (LPVOID*)&paaa), "GetAce failed with error %u\n", GetLastError());
662 ok(paaa->Header.AceType == ACCESS_DENIED_ACE_TYPE,
663 "Invalid ACE type %d\n", paaa->Header.AceType);
664 /* first one of two ACEs generated from inheritable entry - without inheritance */
665 ok(paaa->Header.AceFlags == 0, "Invalid ACE flags %x\n", paaa->Header.AceFlags);
666 ok(paaa->Mask == GENERIC_WRITE, "Invalid ACE mask %x\n", paaa->Mask);
668 ok(GetAce(pAcl, 2, (LPVOID*)&paaa), "GetAce failed with error %u\n", GetLastError());
669 ok(paaa->Header.AceType == ACCESS_DENIED_ACE_TYPE,
670 "Invalid ACE type %d\n", paaa->Header.AceType);
671 /* second ACE - with inheritance */
672 ok(paaa->Header.AceFlags == MY_INHERITANCE,
673 "Invalid ACE flags %x\n", paaa->Header.AceFlags);
674 ok(paaa->Mask == GENERIC_READ, "Invalid ACE mask %x\n", paaa->Mask);
683 static void test_SHPackDispParams(void)
689 if(!pSHPackDispParams)
690 win_skip("SHPackSidpParams not available\n");
692 memset(¶ms, 0xc0, sizeof(params));
693 memset(vars, 0xc0, sizeof(vars));
694 hres = pSHPackDispParams(¶ms, vars, 1, VT_I4, 0xdeadbeef);
695 ok(hres == S_OK, "SHPackDispParams failed: %08x\n", hres);
696 ok(params.cArgs == 1, "params.cArgs = %d\n", params.cArgs);
697 ok(params.cNamedArgs == 0, "params.cNamedArgs = %d\n", params.cArgs);
698 ok(params.rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", params.rgdispidNamedArgs);
699 ok(params.rgvarg == vars, "params.rgvarg = %p\n", params.rgvarg);
700 ok(V_VT(vars) == VT_I4, "V_VT(var) = %d\n", V_VT(vars));
701 ok(V_I4(vars) == 0xdeadbeef, "failed %x\n", V_I4(vars));
703 memset(¶ms, 0xc0, sizeof(params));
704 hres = pSHPackDispParams(¶ms, NULL, 0, 0);
705 ok(hres == S_OK, "SHPackDispParams failed: %08x\n", hres);
706 ok(params.cArgs == 0, "params.cArgs = %d\n", params.cArgs);
707 ok(params.cNamedArgs == 0, "params.cNamedArgs = %d\n", params.cArgs);
708 ok(params.rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", params.rgdispidNamedArgs);
709 ok(params.rgvarg == NULL, "params.rgvarg = %p\n", params.rgvarg);
711 memset(vars, 0xc0, sizeof(vars));
712 memset(¶ms, 0xc0, sizeof(params));
713 hres = pSHPackDispParams(¶ms, vars, 4, VT_BSTR, (void*)0xdeadbeef, VT_EMPTY, 10,
714 VT_I4, 100, VT_DISPATCH, (void*)0xdeadbeef);
715 ok(hres == S_OK, "SHPackDispParams failed: %08x\n", hres);
716 ok(params.cArgs == 4, "params.cArgs = %d\n", params.cArgs);
717 ok(params.cNamedArgs == 0, "params.cNamedArgs = %d\n", params.cArgs);
718 ok(params.rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", params.rgdispidNamedArgs);
719 ok(params.rgvarg == vars, "params.rgvarg = %p\n", params.rgvarg);
720 ok(V_VT(vars) == VT_DISPATCH, "V_VT(vars[0]) = %x\n", V_VT(vars));
721 ok(V_I4(vars) == 0xdeadbeef, "V_I4(vars[0]) = %x\n", V_I4(vars));
722 ok(V_VT(vars+1) == VT_I4, "V_VT(vars[1]) = %d\n", V_VT(vars+1));
723 ok(V_I4(vars+1) == 100, "V_I4(vars[1]) = %x\n", V_I4(vars+1));
724 ok(V_VT(vars+2) == VT_I4, "V_VT(vars[2]) = %d\n", V_VT(vars+2));
725 ok(V_I4(vars+2) == 10, "V_I4(vars[2]) = %x\n", V_I4(vars+2));
726 ok(V_VT(vars+3) == VT_BSTR, "V_VT(vars[3]) = %d\n", V_VT(vars+3));
727 ok(V_BSTR(vars+3) == (void*)0xdeadbeef, "V_BSTR(vars[3]) = %p\n", V_BSTR(vars+3));
732 const IDispatchVtbl *vtbl;
736 typedef struct _contain
738 const IConnectionPointContainerVtbl *vtbl;
742 IConnectionPoint **pt;
745 typedef struct _cntptn
747 const IConnectionPointVtbl *vtbl;
758 const IEnumConnectionsVtbl *vtbl;
765 typedef struct _enumpt
767 const IEnumConnectionPointsVtbl *vtbl;
775 static HRESULT WINAPI Disp_QueryInterface(
782 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch))
789 IUnknown_AddRef(This);
793 trace("no interface\n");
794 return E_NOINTERFACE;
797 static ULONG WINAPI Disp_AddRef(IDispatch* This)
799 Disp *iface = (Disp*)This;
800 return InterlockedIncrement(&iface->refCount);
803 static ULONG WINAPI Disp_Release(IDispatch* This)
805 Disp *iface = (Disp*)This;
808 ret = InterlockedDecrement(&iface->refCount);
810 HeapFree(GetProcessHeap(),0,This);
814 static HRESULT WINAPI Disp_GetTypeInfoCount(
818 return ERROR_SUCCESS;
821 static HRESULT WINAPI Disp_GetTypeInfo(
827 return ERROR_SUCCESS;
830 static HRESULT WINAPI Disp_GetIDsOfNames(
838 return ERROR_SUCCESS;
841 static HRESULT WINAPI Disp_Invoke(
847 DISPPARAMS *pDispParams,
849 EXCEPINFO *pExcepInfo,
852 trace("%p %x %p %x %x %p %p %p %p\n",This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr);
854 ok(dispIdMember == 0xa0 || dispIdMember == 0xa1, "Unknown dispIdMember\n");
855 ok(pDispParams != NULL, "Invoked with NULL pDispParams\n");
856 ok(wFlags == DISPATCH_METHOD, "Wrong flags %x\n",wFlags);
857 ok(lcid == 0,"Wrong lcid %x\n",lcid);
858 if (dispIdMember == 0xa0)
860 ok(pDispParams->cArgs == 0, "params.cArgs = %d\n", pDispParams->cArgs);
861 ok(pDispParams->cNamedArgs == 0, "params.cNamedArgs = %d\n", pDispParams->cArgs);
862 ok(pDispParams->rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", pDispParams->rgdispidNamedArgs);
863 ok(pDispParams->rgvarg == NULL, "params.rgvarg = %p\n", pDispParams->rgvarg);
865 else if (dispIdMember == 0xa1)
867 ok(pDispParams->cArgs == 2, "params.cArgs = %d\n", pDispParams->cArgs);
868 ok(pDispParams->cNamedArgs == 0, "params.cNamedArgs = %d\n", pDispParams->cArgs);
869 ok(pDispParams->rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", pDispParams->rgdispidNamedArgs);
870 ok(V_VT(pDispParams->rgvarg) == VT_BSTR, "V_VT(var) = %d\n", V_VT(pDispParams->rgvarg));
871 ok(V_I4(pDispParams->rgvarg) == 0xdeadcafe , "failed %p\n", V_BSTR(pDispParams->rgvarg));
872 ok(V_VT(pDispParams->rgvarg+1) == VT_I4, "V_VT(var) = %d\n", V_VT(pDispParams->rgvarg+1));
873 ok(V_I4(pDispParams->rgvarg+1) == 0xdeadbeef, "failed %x\n", V_I4(pDispParams->rgvarg+1));
876 return ERROR_SUCCESS;
879 static const IDispatchVtbl disp_vtbl = {
884 Disp_GetTypeInfoCount,
890 static HRESULT WINAPI Enum_QueryInterface(
891 IEnumConnections* This,
897 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IEnumConnections))
904 IUnknown_AddRef(This);
908 trace("no interface\n");
909 return E_NOINTERFACE;
912 static ULONG WINAPI Enum_AddRef(IEnumConnections* This)
914 EnumCon *iface = (EnumCon*)This;
915 return InterlockedIncrement(&iface->refCount);
918 static ULONG WINAPI Enum_Release(IEnumConnections* This)
920 EnumCon *iface = (EnumCon*)This;
923 ret = InterlockedDecrement(&iface->refCount);
925 HeapFree(GetProcessHeap(),0,This);
929 static HRESULT WINAPI Enum_Next(
930 IEnumConnections* This,
935 EnumCon *iface = (EnumCon*)This;
937 if (cConnections > 0 && iface->idx < iface->pt->sinkCount)
939 rgcd->pUnk = iface->pt->sink[iface->idx];
940 IUnknown_AddRef(iface->pt->sink[iface->idx]);
951 static HRESULT WINAPI Enum_Skip(
952 IEnumConnections* This,
958 static HRESULT WINAPI Enum_Reset(
959 IEnumConnections* This)
964 static HRESULT WINAPI Enum_Clone(
965 IEnumConnections* This,
966 IEnumConnections **ppEnum)
971 static const IEnumConnectionsVtbl enum_vtbl = {
982 static HRESULT WINAPI ConPt_QueryInterface(
983 IConnectionPoint* This,
989 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IConnectionPoint))
996 IUnknown_AddRef(This);
1000 trace("no interface\n");
1001 return E_NOINTERFACE;
1004 static ULONG WINAPI ConPt_AddRef(
1005 IConnectionPoint* This)
1007 ConPt *iface = (ConPt*)This;
1008 return InterlockedIncrement(&iface->refCount);
1011 static ULONG WINAPI ConPt_Release(
1012 IConnectionPoint* This)
1014 ConPt *iface = (ConPt*)This;
1017 ret = InterlockedDecrement(&iface->refCount);
1020 if (iface->sinkCount > 0)
1023 for (i = 0; i < iface->sinkCount; i++)
1026 IUnknown_Release(iface->sink[i]);
1028 HeapFree(GetProcessHeap(),0,iface->sink);
1030 HeapFree(GetProcessHeap(),0,This);
1035 static HRESULT WINAPI ConPt_GetConnectionInterface(
1036 IConnectionPoint* This,
1040 ConPt *iface = (ConPt*)This;
1047 memcpy(pIID,&iface->id,sizeof(GUID));
1051 static HRESULT WINAPI ConPt_GetConnectionPointContainer(
1052 IConnectionPoint* This,
1053 IConnectionPointContainer **ppCPC)
1055 ConPt *iface = (ConPt*)This;
1057 *ppCPC = (IConnectionPointContainer*)iface->container;
1061 static HRESULT WINAPI ConPt_Advise(
1062 IConnectionPoint* This,
1066 ConPt *iface = (ConPt*)This;
1068 if (iface->sinkCount == 0)
1069 iface->sink = HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown*));
1071 iface->sink = HeapReAlloc(GetProcessHeap(),0,iface->sink,sizeof(IUnknown*)*(iface->sinkCount+1));
1072 iface->sink[iface->sinkCount] = pUnkSink;
1073 IUnknown_AddRef(pUnkSink);
1075 *pdwCookie = iface->sinkCount;
1079 static HRESULT WINAPI ConPt_Unadvise(
1080 IConnectionPoint* This,
1083 ConPt *iface = (ConPt*)This;
1085 if (dwCookie > iface->sinkCount)
1089 IUnknown_Release(iface->sink[dwCookie-1]);
1090 iface->sink[dwCookie-1] = NULL;
1095 static HRESULT WINAPI ConPt_EnumConnections(
1096 IConnectionPoint* This,
1097 IEnumConnections **ppEnum)
1101 ec = HeapAlloc(GetProcessHeap(),0,sizeof(EnumCon));
1102 ec->vtbl = &enum_vtbl;
1104 ec->pt = (ConPt*)This;
1106 *ppEnum = (IEnumConnections*)ec;
1111 static const IConnectionPointVtbl point_vtbl = {
1112 ConPt_QueryInterface,
1116 ConPt_GetConnectionInterface,
1117 ConPt_GetConnectionPointContainer,
1120 ConPt_EnumConnections
1123 static HRESULT WINAPI EnumPt_QueryInterface(
1124 IEnumConnectionPoints* This,
1130 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IEnumConnectionPoints))
1137 IUnknown_AddRef(This);
1141 trace("no interface\n");
1142 return E_NOINTERFACE;
1145 static ULONG WINAPI EnumPt_AddRef(IEnumConnectionPoints* This)
1147 EnumPt *iface = (EnumPt*)This;
1148 return InterlockedIncrement(&iface->refCount);
1151 static ULONG WINAPI EnumPt_Release(IEnumConnectionPoints* This)
1153 EnumPt *iface = (EnumPt*)This;
1156 ret = InterlockedDecrement(&iface->refCount);
1158 HeapFree(GetProcessHeap(),0,This);
1162 static HRESULT WINAPI EnumPt_Next(
1163 IEnumConnectionPoints* This,
1165 IConnectionPoint **rgcd,
1168 EnumPt *iface = (EnumPt*)This;
1170 if (cConnections > 0 && iface->idx < iface->container->ptCount)
1172 *rgcd = iface->container->pt[iface->idx];
1173 IUnknown_AddRef(iface->container->pt[iface->idx]);
1183 static HRESULT WINAPI EnumPt_Skip(
1184 IEnumConnectionPoints* This,
1190 static HRESULT WINAPI EnumPt_Reset(
1191 IEnumConnectionPoints* This)
1196 static HRESULT WINAPI EnumPt_Clone(
1197 IEnumConnectionPoints* This,
1198 IEnumConnectionPoints **ppEnumPt)
1203 static const IEnumConnectionPointsVtbl enumpt_vtbl = {
1205 EnumPt_QueryInterface,
1214 static HRESULT WINAPI Contain_QueryInterface(
1215 IConnectionPointContainer* This,
1221 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IConnectionPointContainer))
1228 IUnknown_AddRef(This);
1232 trace("no interface\n");
1233 return E_NOINTERFACE;
1236 static ULONG WINAPI Contain_AddRef(
1237 IConnectionPointContainer* This)
1239 Contain *iface = (Contain*)This;
1240 return InterlockedIncrement(&iface->refCount);
1243 static ULONG WINAPI Contain_Release(
1244 IConnectionPointContainer* This)
1246 Contain *iface = (Contain*)This;
1249 ret = InterlockedDecrement(&iface->refCount);
1252 if (iface->ptCount > 0)
1255 for (i = 0; i < iface->ptCount; i++)
1256 IUnknown_Release(iface->pt[i]);
1257 HeapFree(GetProcessHeap(),0,iface->pt);
1259 HeapFree(GetProcessHeap(),0,This);
1264 static HRESULT WINAPI Contain_EnumConnectionPoints(
1265 IConnectionPointContainer* This,
1266 IEnumConnectionPoints **ppEnum)
1270 ec = HeapAlloc(GetProcessHeap(),0,sizeof(EnumPt));
1271 ec->vtbl = &enumpt_vtbl;
1274 ec->container = (Contain*)This;
1275 *ppEnum = (IEnumConnectionPoints*)ec;
1280 static HRESULT WINAPI Contain_FindConnectionPoint(
1281 IConnectionPointContainer* This,
1283 IConnectionPoint **ppCP)
1285 Contain *iface = (Contain*)This;
1288 if (!IsEqualIID(riid, &IID_NULL) || iface->ptCount ==0)
1290 pt = HeapAlloc(GetProcessHeap(),0,sizeof(ConPt));
1291 pt->vtbl = &point_vtbl;
1295 pt->container = iface;
1296 pt->id = IID_IDispatch;
1298 if (iface->ptCount == 0)
1299 iface->pt =HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown*));
1301 iface->pt = HeapReAlloc(GetProcessHeap(),0,iface->pt,sizeof(IUnknown*)*(iface->ptCount+1));
1302 iface->pt[iface->ptCount] = (IConnectionPoint*)pt;
1305 *ppCP = (IConnectionPoint*)pt;
1309 *ppCP = iface->pt[0];
1310 IUnknown_AddRef((IUnknown*)*ppCP);
1316 static const IConnectionPointContainerVtbl contain_vtbl = {
1317 Contain_QueryInterface,
1321 Contain_EnumConnectionPoints,
1322 Contain_FindConnectionPoint
1325 static void test_IConnectionPoint(void)
1329 IConnectionPoint *point;
1332 DWORD cookie = 0xffffffff;
1336 if (!pIConnectionPoint_SimpleInvoke || !pConnectToConnectionPoint)
1338 win_skip("IConnectionPoint Apis not present\n");
1342 container = HeapAlloc(GetProcessHeap(),0,sizeof(Contain));
1343 container->vtbl = &contain_vtbl;
1344 container->refCount = 1;
1345 container->ptCount = 0;
1346 container->pt = NULL;
1348 dispatch = HeapAlloc(GetProcessHeap(),0,sizeof(Disp));
1349 dispatch->vtbl = &disp_vtbl;
1350 dispatch->refCount = 1;
1352 rc = pConnectToConnectionPoint((IUnknown*)dispatch, &IID_NULL, TRUE, (IUnknown*)container, &cookie, &point);
1353 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
1354 ok(point != NULL, "returned ConnectionPoint is NULL\n");
1355 ok(cookie != 0xffffffff, "invalid cookie returned\n");
1357 rc = pIConnectionPoint_SimpleInvoke(point,0xa0,NULL);
1358 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
1360 if (pSHPackDispParams)
1362 memset(¶ms, 0xc0, sizeof(params));
1363 memset(vars, 0xc0, sizeof(vars));
1364 rc = pSHPackDispParams(¶ms, vars, 2, VT_I4, 0xdeadbeef, VT_BSTR, 0xdeadcafe);
1365 ok(rc == S_OK, "SHPackDispParams failed: %08x\n", rc);
1367 rc = pIConnectionPoint_SimpleInvoke(point,0xa1,¶ms);
1368 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
1371 win_skip("pSHPackDispParams not present\n");
1373 rc = pConnectToConnectionPoint(NULL, &IID_NULL, FALSE, (IUnknown*)container, &cookie, NULL);
1374 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
1376 /* MSDN says this should be required but it crashs on XP
1377 IUnknown_Release(point);
1379 ref = IUnknown_Release((IUnknown*)container);
1380 ok(ref == 0, "leftover IConnectionPointContainer reference %i\n",ref);
1381 ref = IUnknown_Release((IUnknown*)dispatch);
1382 ok(ref == 0, "leftover IDispatch reference %i\n",ref);
1385 typedef struct _propbag
1387 const IPropertyBagVtbl *vtbl;
1393 static HRESULT WINAPI Prop_QueryInterface(
1400 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IPropertyBag))
1407 IUnknown_AddRef(This);
1411 trace("no interface\n");
1412 return E_NOINTERFACE;
1415 static ULONG WINAPI Prop_AddRef(
1418 PropBag *iface = (PropBag*)This;
1419 return InterlockedIncrement(&iface->refCount);
1422 static ULONG WINAPI Prop_Release(
1425 PropBag *iface = (PropBag*)This;
1428 ret = InterlockedDecrement(&iface->refCount);
1430 HeapFree(GetProcessHeap(),0,This);
1434 static HRESULT WINAPI Prop_Read(
1436 LPCOLESTR pszPropName,
1438 IErrorLog *pErrorLog)
1440 V_VT(pVar) = VT_BLOB|VT_BYREF;
1441 V_BYREF(pVar) = (LPVOID)0xdeadcafe;
1445 static HRESULT WINAPI Prop_Write(
1447 LPCOLESTR pszPropName,
1454 static const IPropertyBagVtbl prop_vtbl = {
1455 Prop_QueryInterface,
1463 static void test_SHPropertyBag_ReadLONG(void)
1468 static const WCHAR szName1[] = {'n','a','m','e','1',0};
1470 if (!pSHPropertyBag_ReadLONG)
1472 win_skip("SHPropertyBag_ReadLONG not present\n");
1476 pb = HeapAlloc(GetProcessHeap(),0,sizeof(PropBag));
1478 pb->vtbl = &prop_vtbl;
1481 rc = pSHPropertyBag_ReadLONG(NULL, szName1, &out);
1482 ok(rc == E_INVALIDARG || broken(rc == 0), "incorrect return %x\n",rc);
1483 ok(out == 0xfeedface, "value should not have changed\n");
1484 rc = pSHPropertyBag_ReadLONG((IPropertyBag*)pb, NULL, &out);
1485 ok(rc == E_INVALIDARG || broken(rc == 0) || broken(rc == 1), "incorrect return %x\n",rc);
1486 ok(out == 0xfeedface, "value should not have changed\n");
1487 rc = pSHPropertyBag_ReadLONG((IPropertyBag*)pb, szName1, NULL);
1488 ok(rc == E_INVALIDARG || broken(rc == 0) || broken(rc == 1), "incorrect return %x\n",rc);
1489 ok(out == 0xfeedface, "value should not have changed\n");
1490 rc = pSHPropertyBag_ReadLONG((IPropertyBag*)pb, szName1, &out);
1491 ok(rc == DISP_E_BADVARTYPE || broken(rc == 0) || broken(rc == 1), "incorrect return %x\n",rc);
1492 ok(out == 0xfeedface || broken(out == 0xfeedfa00), "value should not have changed %x\n",out);
1493 IUnknown_Release((IUnknown*)pb);
1498 static void test_SHSetWindowBits(void)
1501 DWORD style, styleold;
1504 if(!pSHSetWindowBits)
1506 win_skip("SHSetWindowBits is not available\n");
1511 clsA.lpfnWndProc = DefWindowProcA;
1512 clsA.cbClsExtra = 0;
1513 clsA.cbWndExtra = 0;
1514 clsA.hInstance = GetModuleHandleA(NULL);
1516 clsA.hCursor = LoadCursorA(0, IDC_ARROW);
1517 clsA.hbrBackground = NULL;
1518 clsA.lpszMenuName = NULL;
1519 clsA.lpszClassName = "Shlwapi test class";
1520 RegisterClassA(&clsA);
1522 hwnd = CreateWindowA("Shlwapi test class", "Test", WS_VISIBLE, 0, 0, 100, 100,
1523 NULL, NULL, GetModuleHandle(NULL), 0);
1524 ok(IsWindow(hwnd), "failed to create window\n");
1527 SetLastError(0xdeadbeef);
1528 style = pSHSetWindowBits(NULL, GWL_STYLE, 0, 0);
1529 ok(style == 0, "expected 0 retval, got %d\n", style);
1530 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE ||
1531 broken(GetLastError() == 0xdeadbeef), /* Win9x/WinMe */
1532 "expected ERROR_INVALID_WINDOW_HANDLE, got %d\n", GetLastError());
1534 /* zero mask, zero flags */
1535 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1536 style = pSHSetWindowBits(hwnd, GWL_STYLE, 0, 0);
1537 ok(styleold == style, "expected old style\n");
1538 ok(styleold == GetWindowLongA(hwnd, GWL_STYLE), "expected to keep old style\n");
1541 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1542 ok(styleold & WS_VISIBLE, "expected WS_VISIBLE\n");
1543 style = pSHSetWindowBits(hwnd, GWL_STYLE, WS_VISIBLE, 0);
1545 ok(style == styleold, "expected previous style, got %x\n", style);
1546 ok((GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE) == 0, "expected updated style\n");
1548 /* test mask, unset style bit used */
1549 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1550 style = pSHSetWindowBits(hwnd, GWL_STYLE, WS_VISIBLE, 0);
1551 ok(style == styleold, "expected previous style, got %x\n", style);
1552 ok(styleold == GetWindowLongA(hwnd, GWL_STYLE), "expected to keep old style\n");
1554 /* set back with flags */
1555 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1556 style = pSHSetWindowBits(hwnd, GWL_STYLE, WS_VISIBLE, WS_VISIBLE);
1557 ok(style == styleold, "expected previous style, got %x\n", style);
1558 ok(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE, "expected updated style\n");
1560 /* reset and try to set without a mask */
1561 pSHSetWindowBits(hwnd, GWL_STYLE, WS_VISIBLE, 0);
1562 ok((GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE) == 0, "expected updated style\n");
1563 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1564 style = pSHSetWindowBits(hwnd, GWL_STYLE, 0, WS_VISIBLE);
1565 ok(style == styleold, "expected previous style, got %x\n", style);
1566 ok((GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE) == 0, "expected updated style\n");
1568 DestroyWindow(hwnd);
1570 UnregisterClassA("Shlwapi test class", GetModuleHandleA(NULL));
1573 static void test_SHFormatDateTimeA(void)
1575 FILETIME UNALIGNED filetime;
1576 CHAR buff[100], buff2[100], buff3[100];
1581 if(!pSHFormatDateTimeA)
1583 win_skip("pSHFormatDateTimeA isn't available\n");
1589 /* crashes on native */
1590 ret = pSHFormatDateTimeA(NULL, NULL, NULL, 0);
1594 SystemTimeToFileTime(&st, &filetime);
1595 /* SHFormatDateTime expects input as utc */
1596 LocalFileTimeToFileTime(&filetime, &filetime);
1598 /* no way to get required buffer length here */
1599 SetLastError(0xdeadbeef);
1600 ret = pSHFormatDateTimeA(&filetime, NULL, NULL, 0);
1601 ok(ret == 0, "got %d\n", ret);
1602 ok(GetLastError() == 0xdeadbeef || broken(GetLastError() == ERROR_SUCCESS /* Win7 */),
1603 "expected 0xdeadbeef, got %d\n", GetLastError());
1605 SetLastError(0xdeadbeef);
1606 buff[0] = 'a'; buff[1] = 0;
1607 ret = pSHFormatDateTimeA(&filetime, NULL, buff, 0);
1608 ok(ret == 0, "got %d\n", ret);
1609 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1610 ok(buff[0] == 'a', "expected same string, got %s\n", buff);
1612 /* flags needs to have FDTF_NOAUTOREADINGORDER for these tests to succeed on Vista+ */
1614 /* all combinations documented as invalid succeeded */
1615 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTTIME | FDTF_LONGTIME;
1616 SetLastError(0xdeadbeef);
1617 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1618 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1619 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1621 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTDATE | FDTF_LONGDATE;
1622 SetLastError(0xdeadbeef);
1623 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1624 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1625 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1627 flags = FDTF_SHORTDATE | FDTF_LTRDATE | FDTF_RTLDATE;
1628 SetLastError(0xdeadbeef);
1629 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1630 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1631 ok(GetLastError() == 0xdeadbeef ||
1632 broken(GetLastError() == ERROR_INVALID_FLAGS), /* Win9x/WinMe */
1633 "expected 0xdeadbeef, got %d\n", GetLastError());
1635 /* now check returned strings */
1636 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTTIME;
1637 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1638 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1639 ret = GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff2, sizeof(buff2));
1640 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1641 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1643 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGTIME;
1644 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1645 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1646 ret = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2));
1647 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1648 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1650 /* both time flags */
1651 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGTIME | FDTF_SHORTTIME;
1652 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1653 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1654 ret = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2));
1655 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1656 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1658 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTDATE;
1659 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1660 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1661 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2));
1662 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1663 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1665 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGDATE;
1666 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1667 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1668 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
1669 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1670 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1672 /* both date flags */
1673 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGDATE | FDTF_SHORTDATE;
1674 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1675 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1676 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
1677 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1678 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1680 /* various combinations of date/time flags */
1681 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGDATE | FDTF_SHORTTIME;
1682 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1683 ok(ret == lstrlenA(buff)+1, "got %d, length %d\n", ret, lstrlenA(buff)+1);
1684 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
1685 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1686 strcat(buff2, ", ");
1687 ret = GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3));
1688 ok(ret == lstrlenA(buff3)+1, "got %d\n", ret);
1689 strcat(buff2, buff3);
1690 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1692 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGDATE | FDTF_LONGTIME;
1693 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1694 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1695 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
1696 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1697 strcat(buff2, ", ");
1698 ret = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3));
1699 ok(ret == lstrlenA(buff3)+1, "got %d\n", ret);
1700 strcat(buff2, buff3);
1701 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1703 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTDATE | FDTF_SHORTTIME;
1704 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1705 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1706 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2));
1707 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1709 ret = GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3));
1710 ok(ret == lstrlenA(buff3)+1, "got %d\n", ret);
1711 strcat(buff2, buff3);
1712 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1714 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTDATE | FDTF_LONGTIME;
1715 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1716 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1717 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2));
1718 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1720 ret = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3));
1721 ok(ret == lstrlenA(buff3)+1, "got %d\n", ret);
1722 strcat(buff2, buff3);
1723 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1726 static void test_SHFormatDateTimeW(void)
1728 FILETIME UNALIGNED filetime;
1729 WCHAR buff[100], buff2[100], buff3[100];
1733 static const WCHAR spaceW[] = {' ',0};
1734 static const WCHAR commaW[] = {',',' ',0};
1736 if(!pSHFormatDateTimeW)
1738 win_skip("pSHFormatDateTimeW isn't available\n");
1744 /* crashes on native */
1745 ret = pSHFormatDateTimeW(NULL, NULL, NULL, 0);
1749 SystemTimeToFileTime(&st, &filetime);
1750 /* SHFormatDateTime expects input as utc */
1751 LocalFileTimeToFileTime(&filetime, &filetime);
1753 /* no way to get required buffer length here */
1754 SetLastError(0xdeadbeef);
1755 ret = pSHFormatDateTimeW(&filetime, NULL, NULL, 0);
1756 ok(ret == 0, "got %d\n", ret);
1757 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1759 SetLastError(0xdeadbeef);
1760 buff[0] = 'a'; buff[1] = 0;
1761 ret = pSHFormatDateTimeW(&filetime, NULL, buff, 0);
1762 ok(ret == 0, "got %d\n", ret);
1763 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1764 ok(buff[0] == 'a', "expected same string\n");
1766 /* all combinations documented as invalid succeeded */
1767 flags = FDTF_SHORTTIME | FDTF_LONGTIME;
1768 SetLastError(0xdeadbeef);
1769 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1770 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1771 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1773 flags = FDTF_SHORTDATE | FDTF_LONGDATE;
1774 SetLastError(0xdeadbeef);
1775 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1776 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1777 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1779 flags = FDTF_SHORTDATE | FDTF_LTRDATE | FDTF_RTLDATE;
1780 SetLastError(0xdeadbeef);
1781 buff[0] = 0; /* NT4 doesn't clear the buffer on failure */
1782 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1783 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1784 ok(GetLastError() == 0xdeadbeef ||
1785 broken(GetLastError() == ERROR_INVALID_FLAGS), /* Win9x/WinMe/NT4 */
1786 "expected 0xdeadbeef, got %d\n", GetLastError());
1788 /* now check returned strings */
1789 flags = FDTF_SHORTTIME;
1790 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1791 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1792 SetLastError(0xdeadbeef);
1793 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1794 if (ret == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1796 win_skip("Needed W-functions are not implemented\n");
1799 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1800 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1802 flags = FDTF_LONGTIME;
1803 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1804 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1805 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1806 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1807 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1809 /* both time flags */
1810 flags = FDTF_LONGTIME | FDTF_SHORTTIME;
1811 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1812 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1813 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1814 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1815 ok(lstrcmpW(buff, buff2) == 0, "expected equal string\n");
1817 flags = FDTF_SHORTDATE;
1818 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1819 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1820 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1821 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1822 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1824 flags = FDTF_LONGDATE;
1825 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1826 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1827 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1828 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1829 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1831 /* both date flags */
1832 flags = FDTF_LONGDATE | FDTF_SHORTDATE;
1833 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1834 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1835 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1836 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1837 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1839 /* various combinations of date/time flags */
1840 flags = FDTF_LONGDATE | FDTF_SHORTTIME;
1841 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1842 ok(ret == lstrlenW(buff)+1, "got %d, length %d\n", ret, lstrlenW(buff)+1);
1843 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1844 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1845 lstrcatW(buff2, commaW);
1846 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
1847 ok(ret == lstrlenW(buff3)+1, "got %d\n", ret);
1848 lstrcatW(buff2, buff3);
1849 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1851 flags = FDTF_LONGDATE | FDTF_LONGTIME;
1852 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1853 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1854 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1855 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1856 lstrcatW(buff2, commaW);
1857 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
1858 ok(ret == lstrlenW(buff3)+1, "got %d\n", ret);
1859 lstrcatW(buff2, buff3);
1860 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1862 flags = FDTF_SHORTDATE | FDTF_SHORTTIME;
1863 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1864 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1865 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1866 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1867 lstrcatW(buff2, spaceW);
1868 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
1869 ok(ret == lstrlenW(buff3)+1, "got %d\n", ret);
1870 lstrcatW(buff2, buff3);
1871 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1873 flags = FDTF_SHORTDATE | FDTF_LONGTIME;
1874 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1875 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1876 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1877 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1878 lstrcatW(buff2, spaceW);
1879 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
1880 ok(ret == lstrlenW(buff3)+1, "got %d\n", ret);
1881 lstrcatW(buff2, buff3);
1882 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1885 static void test_SHGetObjectCompatFlags(void)
1887 struct compat_value {
1892 struct compat_value values[] = {
1893 { "OTNEEDSSFCACHE", 0x1 },
1894 { "NO_WEBVIEW", 0x2 },
1895 { "UNBINDABLE", 0x4 },
1897 { "NEEDSFILESYSANCESTOR", 0x10 },
1898 { "NOTAFILESYSTEM", 0x20 },
1899 { "CTXMENU_NOVERBS", 0x40 },
1900 { "CTXMENU_LIMITEDQI", 0x80 },
1901 { "COCREATESHELLFOLDERONLY", 0x100 },
1902 { "NEEDSSTORAGEANCESTOR", 0x200 },
1903 { "NOLEGACYWEBVIEW", 0x400 },
1904 { "CTXMENU_XPQCMFLAGS", 0x1000 },
1905 { "NOIPROPERTYSTORE", 0x2000 }
1908 static const char compat_path[] = "Software\\Microsoft\\Windows\\CurrentVersion\\ShellCompatibility\\Objects";
1909 CHAR keyA[39]; /* {CLSID} */
1914 if (!pSHGetObjectCompatFlags)
1916 win_skip("SHGetObjectCompatFlags isn't available\n");
1921 ret = pSHGetObjectCompatFlags(NULL, NULL);
1922 ok(ret == 0, "got %d\n", ret);
1924 ret = RegOpenKeyA(HKEY_LOCAL_MACHINE, compat_path, &root);
1925 if (ret != ERROR_SUCCESS)
1927 skip("No compatibility class data found\n");
1931 for (i = 0; RegEnumKeyA(root, i, keyA, sizeof(keyA)) == ERROR_SUCCESS; i++)
1935 if (RegOpenKeyA(root, keyA, &clsid_key) == ERROR_SUCCESS)
1938 DWORD expected = 0, got, length = sizeof(valueA);
1942 for (v = 0; RegEnumValueA(clsid_key, v, valueA, &length, NULL, NULL, NULL, NULL) == ERROR_SUCCESS; v++)
1946 for (j = 0; j < sizeof(values)/sizeof(struct compat_value); j++)
1947 if (lstrcmpA(values[j].nameA, valueA) == 0)
1949 expected |= values[j].value;
1953 length = sizeof(valueA);
1956 pGUIDFromStringA(keyA, &clsid);
1957 got = pSHGetObjectCompatFlags(NULL, &clsid);
1958 ok(got == expected, "got 0x%08x, expected 0x%08x. Key %s\n", got, expected, keyA);
1960 RegCloseKey(clsid_key);
1968 const IOleCommandTargetVtbl *lpVtbl;
1970 } IOleCommandTargetImpl;
1972 static const IOleCommandTargetVtbl IOleCommandTargetImpl_Vtbl;
1974 static IOleCommandTarget* IOleCommandTargetImpl_Construct(void)
1976 IOleCommandTargetImpl *obj;
1978 obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*obj));
1979 obj->lpVtbl = &IOleCommandTargetImpl_Vtbl;
1982 return (IOleCommandTarget*)obj;
1985 static HRESULT WINAPI IOleCommandTargetImpl_QueryInterface(IOleCommandTarget *iface, REFIID riid, void **ppvObj)
1987 IOleCommandTargetImpl *This = (IOleCommandTargetImpl *)iface;
1989 if (IsEqualIID(riid, &IID_IUnknown) ||
1990 IsEqualIID(riid, &IID_IOleCommandTarget))
1997 IUnknown_AddRef(iface);
2001 return E_NOINTERFACE;
2004 static ULONG WINAPI IOleCommandTargetImpl_AddRef(IOleCommandTarget *iface)
2006 IOleCommandTargetImpl *This = (IOleCommandTargetImpl *)iface;
2007 return InterlockedIncrement(&This->ref);
2010 static ULONG WINAPI IOleCommandTargetImpl_Release(IOleCommandTarget *iface)
2012 IOleCommandTargetImpl *This = (IOleCommandTargetImpl *)iface;
2013 ULONG ref = InterlockedDecrement(&This->ref);
2017 HeapFree(GetProcessHeap(), 0, This);
2023 static HRESULT WINAPI IOleCommandTargetImpl_QueryStatus(
2024 IOleCommandTarget *iface, const GUID *group, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText)
2029 static HRESULT WINAPI IOleCommandTargetImpl_Exec(
2030 IOleCommandTarget *iface,
2031 const GUID *CmdGroup,
2037 add_call(&trace_got, 3, CmdGroup, (void*)(DWORD_PTR)nCmdID, (void*)(DWORD_PTR)nCmdexecopt, pvaIn, pvaOut);
2041 static const IOleCommandTargetVtbl IOleCommandTargetImpl_Vtbl =
2043 IOleCommandTargetImpl_QueryInterface,
2044 IOleCommandTargetImpl_AddRef,
2045 IOleCommandTargetImpl_Release,
2046 IOleCommandTargetImpl_QueryStatus,
2047 IOleCommandTargetImpl_Exec
2051 const IServiceProviderVtbl *lpVtbl;
2053 } IServiceProviderImpl;
2056 const IProfferServiceVtbl *lpVtbl;
2058 } IProfferServiceImpl;
2061 static const IServiceProviderVtbl IServiceProviderImpl_Vtbl;
2062 static const IProfferServiceVtbl IProfferServiceImpl_Vtbl;
2064 static IServiceProvider* IServiceProviderImpl_Construct(void)
2066 IServiceProviderImpl *obj;
2068 obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*obj));
2069 obj->lpVtbl = &IServiceProviderImpl_Vtbl;
2072 return (IServiceProvider*)obj;
2075 static IProfferService* IProfferServiceImpl_Construct(void)
2077 IProfferServiceImpl *obj;
2079 obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*obj));
2080 obj->lpVtbl = &IProfferServiceImpl_Vtbl;
2083 return (IProfferService*)obj;
2086 static HRESULT WINAPI IServiceProviderImpl_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppvObj)
2088 IServiceProviderImpl *This = (IServiceProviderImpl *)iface;
2090 if (IsEqualIID(riid, &IID_IUnknown) ||
2091 IsEqualIID(riid, &IID_IServiceProvider))
2098 IUnknown_AddRef(iface);
2099 /* native uses redefined IID_IServiceProvider symbol, so we can't compare pointers */
2100 if (IsEqualIID(riid, &IID_IServiceProvider))
2101 add_call(&trace_got, 1, iface, &IID_IServiceProvider, 0, 0, 0);
2105 return E_NOINTERFACE;
2108 static ULONG WINAPI IServiceProviderImpl_AddRef(IServiceProvider *iface)
2110 IServiceProviderImpl *This = (IServiceProviderImpl *)iface;
2111 return InterlockedIncrement(&This->ref);
2114 static ULONG WINAPI IServiceProviderImpl_Release(IServiceProvider *iface)
2116 IServiceProviderImpl *This = (IServiceProviderImpl *)iface;
2117 ULONG ref = InterlockedDecrement(&This->ref);
2121 HeapFree(GetProcessHeap(), 0, This);
2127 static HRESULT WINAPI IServiceProviderImpl_QueryService(
2128 IServiceProvider *iface, REFGUID service, REFIID riid, void **ppv)
2130 /* native uses redefined pointer for IID_IOleCommandTarget, not one from uuid.lib */
2131 if (IsEqualIID(riid, &IID_IOleCommandTarget))
2133 add_call(&trace_got, 2, iface, service, &IID_IOleCommandTarget, 0, 0);
2134 *ppv = IOleCommandTargetImpl_Construct();
2136 if (IsEqualIID(riid, &IID_IProfferService))
2138 if (IsEqualIID(service, &IID_IProfferService))
2139 add_call(&trace_got, 2, &IID_IProfferService, &IID_IProfferService, 0, 0, 0);
2140 *ppv = IProfferServiceImpl_Construct();
2145 static const IServiceProviderVtbl IServiceProviderImpl_Vtbl =
2147 IServiceProviderImpl_QueryInterface,
2148 IServiceProviderImpl_AddRef,
2149 IServiceProviderImpl_Release,
2150 IServiceProviderImpl_QueryService
2153 static void test_IUnknown_QueryServiceExec(void)
2155 IServiceProvider *provider = IServiceProviderImpl_Construct();
2156 static const GUID dummy_serviceid = { 0xdeadbeef };
2157 static const GUID dummy_groupid = { 0xbeefbeef };
2158 call_trace_t trace_expected;
2161 /* on <=W2K platforms same ordinal used for another export with different
2162 prototype, so skipping using this indirect condition */
2163 if (is_win2k_and_lower)
2165 win_skip("IUnknown_QueryServiceExec is not available\n");
2169 /* null source pointer */
2170 hr = pIUnknown_QueryServiceExec(NULL, &dummy_serviceid, &dummy_groupid, 0, 0, 0, 0);
2171 ok(hr == E_FAIL, "got 0x%08x\n", hr);
2174 IUnknown_QueryServiceExec( ptr1, serviceid, groupid, arg1, arg2, arg3, arg4);
2175 -> IUnknown_QueryInterface( ptr1, &IID_IServiceProvider, &prov );
2176 -> IServiceProvider_QueryService( prov, serviceid, &IID_IOleCommandTarget, &obj );
2177 -> IOleCommandTarget_Exec( obj, groupid, arg1, arg2, arg3, arg4 );
2179 init_call_trace(&trace_expected);
2181 add_call(&trace_expected, 1, provider, &IID_IServiceProvider, 0, 0, 0);
2182 add_call(&trace_expected, 2, provider, &dummy_serviceid, &IID_IOleCommandTarget, 0, 0);
2183 add_call(&trace_expected, 3, &dummy_groupid, (void*)0x1, (void*)0x2, (void*)0x3, (void*)0x4);
2185 init_call_trace(&trace_got);
2186 hr = pIUnknown_QueryServiceExec((IUnknown*)provider, &dummy_serviceid, &dummy_groupid, 0x1, 0x2, (void*)0x3, (void*)0x4);
2187 ok(hr == S_OK, "got 0x%08x\n", hr);
2189 ok_trace(&trace_expected, &trace_got);
2191 free_call_trace(&trace_expected);
2192 free_call_trace(&trace_got);
2194 IServiceProvider_Release(provider);
2198 static HRESULT WINAPI IProfferServiceImpl_QueryInterface(IProfferService *iface, REFIID riid, void **ppvObj)
2200 IProfferServiceImpl *This = (IProfferServiceImpl *)iface;
2202 if (IsEqualIID(riid, &IID_IUnknown) ||
2203 IsEqualIID(riid, &IID_IProfferService))
2207 else if (IsEqualIID(riid, &IID_IServiceProvider))
2209 *ppvObj = IServiceProviderImpl_Construct();
2210 add_call(&trace_got, 1, iface, &IID_IServiceProvider, 0, 0, 0);
2216 IUnknown_AddRef(iface);
2220 return E_NOINTERFACE;
2223 static ULONG WINAPI IProfferServiceImpl_AddRef(IProfferService *iface)
2225 IProfferServiceImpl *This = (IProfferServiceImpl *)iface;
2226 return InterlockedIncrement(&This->ref);
2229 static ULONG WINAPI IProfferServiceImpl_Release(IProfferService *iface)
2231 IProfferServiceImpl *This = (IProfferServiceImpl *)iface;
2232 ULONG ref = InterlockedDecrement(&This->ref);
2236 HeapFree(GetProcessHeap(), 0, This);
2242 static HRESULT WINAPI IProfferServiceImpl_ProfferService(IProfferService *iface,
2243 REFGUID service, IServiceProvider *pService, DWORD *pCookie)
2245 add_call(&trace_got, 3, service, pService, pCookie, 0, 0);
2249 static HRESULT WINAPI IProfferServiceImpl_RevokeService(IProfferService *iface, DWORD cookie)
2251 add_call(&trace_got, 4, (void*)(DWORD_PTR)cookie, 0, 0, 0, 0);
2255 static const IProfferServiceVtbl IProfferServiceImpl_Vtbl =
2257 IProfferServiceImpl_QueryInterface,
2258 IProfferServiceImpl_AddRef,
2259 IProfferServiceImpl_Release,
2260 IProfferServiceImpl_ProfferService,
2261 IProfferServiceImpl_RevokeService
2264 static void test_IUnknown_ProfferService(void)
2266 IServiceProvider *provider = IServiceProviderImpl_Construct();
2267 IProfferService *proff = IProfferServiceImpl_Construct();
2268 static const GUID dummy_serviceid = { 0xdeadbeef };
2269 call_trace_t trace_expected;
2273 /* on <=W2K platforms same ordinal used for another export with different
2274 prototype, so skipping using this indirect condition */
2275 if (is_win2k_and_lower)
2277 win_skip("IUnknown_ProfferService is not available\n");
2281 /* null source pointer */
2282 hr = pIUnknown_ProfferService(NULL, &dummy_serviceid, 0, 0);
2283 ok(hr == E_FAIL, "got 0x%08x\n", hr);
2286 IUnknown_ProfferService( ptr1, serviceid, arg1, arg2);
2287 -> IUnknown_QueryInterface( ptr1, &IID_IServiceProvider, &provider );
2288 -> IServiceProvider_QueryService( provider, &IID_IProfferService, &IID_IProfferService, &proffer );
2290 if (service pointer not null):
2291 -> IProfferService_ProfferService( proffer, serviceid, arg1, arg2 );
2293 -> IProfferService_RevokeService( proffer, *arg2 );
2295 init_call_trace(&trace_expected);
2297 add_call(&trace_expected, 1, proff, &IID_IServiceProvider, 0, 0, 0);
2298 add_call(&trace_expected, 2, &IID_IProfferService, &IID_IProfferService, 0, 0, 0);
2299 add_call(&trace_expected, 3, &dummy_serviceid, provider, &cookie, 0, 0);
2301 init_call_trace(&trace_got);
2302 hr = pIUnknown_ProfferService((IUnknown*)proff, &dummy_serviceid, provider, &cookie);
2303 ok(hr == S_OK, "got 0x%08x\n", hr);
2305 ok_trace(&trace_expected, &trace_got);
2306 free_call_trace(&trace_got);
2307 free_call_trace(&trace_expected);
2309 /* same with ::Revoke path */
2310 init_call_trace(&trace_expected);
2312 add_call(&trace_expected, 1, proff, &IID_IServiceProvider, 0, 0, 0);
2313 add_call(&trace_expected, 2, &IID_IProfferService, &IID_IProfferService, 0, 0, 0);
2314 add_call(&trace_expected, 4, (void*)(DWORD_PTR)cookie, 0, 0, 0, 0);
2316 init_call_trace(&trace_got);
2317 hr = pIUnknown_ProfferService((IUnknown*)proff, &dummy_serviceid, 0, &cookie);
2318 ok(hr == S_OK, "got 0x%08x\n", hr);
2319 ok_trace(&trace_expected, &trace_got);
2320 free_call_trace(&trace_got);
2321 free_call_trace(&trace_expected);
2323 IServiceProvider_Release(provider);
2324 IProfferService_Release(proff);
2327 static void test_SHCreateWorkerWindowA(void)
2335 if (is_win2k_and_lower)
2337 win_skip("SHCreateWorkerWindowA not available\n");
2341 hwnd = pSHCreateWorkerWindowA(0, NULL, 0, 0, 0, 0);
2342 ok(hwnd != 0, "expected window\n");
2344 GetClassName(hwnd, classA, 20);
2345 ok(lstrcmpA(classA, "WorkerA") == 0, "expected WorkerA class, got %s\n", classA);
2347 ret = GetWindowLongPtrA(hwnd, 0);
2348 ok(ret == 0, "got %ld\n", ret);
2351 memset(&cliA, 0, sizeof(cliA));
2352 res = GetClassInfoA(GetModuleHandle("shlwapi.dll"), "WorkerA", &cliA);
2353 ok(res, "failed to get class info\n");
2354 ok(cliA.style == 0, "got 0x%08x\n", cliA.style);
2355 ok(cliA.cbClsExtra == 0, "got %d\n", cliA.cbClsExtra);
2356 ok(cliA.cbWndExtra == sizeof(LONG_PTR), "got %d\n", cliA.cbWndExtra);
2357 ok(cliA.lpszMenuName == 0, "got %s\n", cliA.lpszMenuName);
2359 DestroyWindow(hwnd);
2361 /* set extra bytes */
2362 hwnd = pSHCreateWorkerWindowA(0, NULL, 0, 0, 0, 0xdeadbeef);
2363 ok(hwnd != 0, "expected window\n");
2365 GetClassName(hwnd, classA, 20);
2366 ok(lstrcmpA(classA, "WorkerA") == 0, "expected WorkerA class, got %s\n", classA);
2368 ret = GetWindowLongPtrA(hwnd, 0);
2369 ok(ret == 0xdeadbeef, "got %ld\n", ret);
2372 ret = GetWindowLongA(hwnd, GWL_EXSTYLE);
2373 ok(ret == WS_EX_WINDOWEDGE, "0x%08lx\n", ret);
2375 DestroyWindow(hwnd);
2377 hwnd = pSHCreateWorkerWindowA(0, NULL, WS_EX_TOOLWINDOW, 0, 0, 0);
2378 ret = GetWindowLongA(hwnd, GWL_EXSTYLE);
2379 ok(ret == (WS_EX_WINDOWEDGE|WS_EX_TOOLWINDOW), "0x%08lx\n", ret);
2380 DestroyWindow(hwnd);
2383 static HRESULT WINAPI SF_QueryInterface(IShellFolder *iface,
2384 REFIID riid, void **ppv)
2386 /* SHIShellFolder_EnumObjects doesn't QI the object for IShellFolder */
2387 ok(!IsEqualGUID(&IID_IShellFolder, riid),
2388 "Unexpected QI for IShellFolder\n");
2389 return E_NOINTERFACE;
2392 static ULONG WINAPI SF_AddRef(IShellFolder *iface)
2397 static ULONG WINAPI SF_Release(IShellFolder *iface)
2402 static HRESULT WINAPI SF_ParseDisplayName(IShellFolder *iface,
2403 HWND owner, LPBC reserved, LPOLESTR displayName, ULONG *eaten,
2404 LPITEMIDLIST *idl, ULONG *attr)
2406 ok(0, "Didn't expect ParseDisplayName\n");
2410 static HRESULT WINAPI SF_EnumObjects(IShellFolder *iface,
2411 HWND owner, SHCONTF flags, IEnumIDList **enm)
2413 *enm = (IEnumIDList*)0xcafebabe;
2417 static HRESULT WINAPI SF_BindToObject(IShellFolder *iface,
2418 LPCITEMIDLIST idl, LPBC reserved, REFIID riid, void **obj)
2420 ok(0, "Didn't expect BindToObject\n");
2424 static HRESULT WINAPI SF_BindToStorage(IShellFolder *iface,
2425 LPCITEMIDLIST idl, LPBC reserved, REFIID riid, void **obj)
2427 ok(0, "Didn't expect BindToStorage\n");
2431 static HRESULT WINAPI SF_CompareIDs(IShellFolder *iface,
2432 LPARAM lparam, LPCITEMIDLIST idl1, LPCITEMIDLIST idl2)
2434 ok(0, "Didn't expect CompareIDs\n");
2438 static HRESULT WINAPI SF_CreateViewObject(IShellFolder *iface,
2439 HWND owner, REFIID riid, void **out)
2441 ok(0, "Didn't expect CreateViewObject\n");
2445 static HRESULT WINAPI SF_GetAttributesOf(IShellFolder *iface,
2446 UINT cidl, LPCITEMIDLIST *idl, SFGAOF *inOut)
2448 ok(0, "Didn't expect GetAttributesOf\n");
2452 static HRESULT WINAPI SF_GetUIObjectOf(IShellFolder *iface,
2453 HWND owner, UINT cidl, LPCITEMIDLIST *idls, REFIID riid, UINT *inOut,
2456 ok(0, "Didn't expect GetUIObjectOf\n");
2460 static HRESULT WINAPI SF_GetDisplayNameOf(IShellFolder *iface,
2461 LPCITEMIDLIST idl, SHGDNF flags, STRRET *name)
2463 ok(0, "Didn't expect GetDisplayNameOf\n");
2467 static HRESULT WINAPI SF_SetNameOf(IShellFolder *iface,
2468 HWND hwnd, LPCITEMIDLIST idl, LPCOLESTR name, SHGDNF flags,
2469 LPITEMIDLIST *idlOut)
2471 ok(0, "Didn't expect SetNameOf\n");
2475 static IShellFolderVtbl ShellFolderVtbl = {
2479 SF_ParseDisplayName,
2484 SF_CreateViewObject,
2487 SF_GetDisplayNameOf,
2491 static IShellFolder ShellFolder = { &ShellFolderVtbl };
2493 static void test_SHIShellFolder_EnumObjects(void)
2497 IShellFolder *folder;
2499 if(!pSHIShellFolder_EnumObjects || is_win2k_and_lower){
2500 win_skip("SHIShellFolder_EnumObjects not available\n");
2505 /* NULL object crashes on Windows */
2506 hres = pSHIShellFolder_EnumObjects(NULL, NULL, 0, NULL);
2509 /* SHIShellFolder_EnumObjects doesn't QI the object for IShellFolder */
2510 enm = (IEnumIDList*)0xdeadbeef;
2511 hres = pSHIShellFolder_EnumObjects(&ShellFolder, NULL, 0, &enm);
2512 ok(hres == S_OK, "SHIShellFolder_EnumObjects failed: 0x%08x\n", hres);
2513 ok(enm == (IEnumIDList*)0xcafebabe, "Didn't get expected enumerator location, instead: %p\n", enm);
2515 /* SHIShellFolder_EnumObjects isn't strict about the IShellFolder object */
2516 hres = SHGetDesktopFolder(&folder);
2517 ok(hres == S_OK, "SHGetDesktopFolder failed: 0x%08x\n", hres);
2520 hres = pSHIShellFolder_EnumObjects(folder, NULL, 0, &enm);
2521 ok(hres == S_OK, "SHIShellFolder_EnumObjects failed: 0x%08x\n", hres);
2522 ok(enm != NULL, "Didn't get an enumerator\n");
2524 IEnumIDList_Release(enm);
2526 IShellFolder_Release(folder);
2529 static void write_inifile(LPCWSTR filename)
2534 static const char data[] =
2537 "AnotherKey=asdf\r\n";
2539 file = CreateFileW(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
2540 if(file == INVALID_HANDLE_VALUE)
2543 WriteFile(file, data, sizeof(data), &written, NULL);
2548 static void test_SHGetIniString(void)
2551 WCHAR out[64] = {0};
2553 static const WCHAR TestAppW[] = {'T','e','s','t','A','p','p',0};
2554 static const WCHAR TestIniW[] = {'C',':','\\','t','e','s','t','.','i','n','i',0};
2555 static const WCHAR AKeyW[] = {'A','K','e','y',0};
2556 static const WCHAR AnotherKeyW[] = {'A','n','o','t','h','e','r','K','e','y',0};
2557 static const WCHAR JunkKeyW[] = {'J','u','n','k','K','e','y',0};
2559 if(!pSHGetIniStringW || is_win2k_and_lower){
2560 win_skip("SHGetIniStringW is not available\n");
2564 write_inifile(TestIniW);
2567 /* these crash on Windows */
2568 ret = pSHGetIniStringW(NULL, NULL, NULL, 0, NULL);
2569 ret = pSHGetIniStringW(NULL, AKeyW, out, sizeof(out), TestIniW);
2570 ret = pSHGetIniStringW(TestAppW, AKeyW, NULL, sizeof(out), TestIniW);
2573 ret = pSHGetIniStringW(TestAppW, AKeyW, out, 0, TestIniW);
2574 ok(ret == 0, "SHGetIniStringW should have given 0, instead: %d\n", ret);
2576 /* valid arguments */
2577 ret = pSHGetIniStringW(TestAppW, NULL, out, sizeof(out), TestIniW);
2578 ok(broken(ret == 0) || /* win 98 */
2579 ret == 4, "SHGetIniStringW should have given 4, instead: %d\n", ret);
2580 ok(!lstrcmpW(out, AKeyW), "Expected %s, got: %s\n",
2581 wine_dbgstr_w(AKeyW), wine_dbgstr_w(out));
2583 ret = pSHGetIniStringW(TestAppW, AKeyW, out, sizeof(out), TestIniW);
2584 ok(broken(ret == 0) || /* win 98 */
2585 ret == 1, "SHGetIniStringW should have given 1, instead: %d\n", ret);
2586 ok(broken(*out == 0) || /*win 98 */
2587 !strcmp_wa(out, "1"), "Expected L\"1\", got: %s\n", wine_dbgstr_w(out));
2589 ret = pSHGetIniStringW(TestAppW, AnotherKeyW, out, sizeof(out), TestIniW);
2590 ok(broken(ret == 0) || /* win 98 */
2591 ret == 4, "SHGetIniStringW should have given 4, instead: %d\n", ret);
2592 ok(broken(*out == 0) || /* win 98 */
2593 !strcmp_wa(out, "asdf"), "Expected L\"asdf\", got: %s\n", wine_dbgstr_w(out));
2595 ret = pSHGetIniStringW(TestAppW, JunkKeyW, out, sizeof(out), TestIniW);
2596 ok(ret == 0, "SHGetIniStringW should have given 0, instead: %d\n", ret);
2597 ok(*out == 0, "Expected L\"\", got: %s\n", wine_dbgstr_w(out));
2599 DeleteFileW(TestIniW);
2602 static void init_pointers(void)
2604 #define MAKEFUNC(f, ord) (p##f = (void*)GetProcAddress(hShlwapi, (LPSTR)(ord)))
2605 MAKEFUNC(SHAllocShared, 7);
2606 MAKEFUNC(SHLockShared, 8);
2607 MAKEFUNC(SHUnlockShared, 9);
2608 MAKEFUNC(SHFreeShared, 10);
2609 MAKEFUNC(GetAcceptLanguagesA, 14);
2610 MAKEFUNC(SHSetWindowBits, 165);
2611 MAKEFUNC(ConnectToConnectionPoint, 168);
2612 MAKEFUNC(SHSearchMapInt, 198);
2613 MAKEFUNC(SHCreateWorkerWindowA, 257);
2614 MAKEFUNC(GUIDFromStringA, 269);
2615 MAKEFUNC(SHPackDispParams, 282);
2616 MAKEFUNC(IConnectionPoint_InvokeWithCancel, 283);
2617 MAKEFUNC(IConnectionPoint_SimpleInvoke, 284);
2618 MAKEFUNC(SHGetIniStringW, 294);
2619 MAKEFUNC(SHFormatDateTimeA, 353);
2620 MAKEFUNC(SHFormatDateTimeW, 354);
2621 MAKEFUNC(SHIShellFolder_EnumObjects, 404);
2622 MAKEFUNC(SHGetObjectCompatFlags, 476);
2623 MAKEFUNC(IUnknown_QueryServiceExec, 484);
2624 MAKEFUNC(SHPropertyBag_ReadLONG, 496);
2625 MAKEFUNC(IUnknown_ProfferService, 514);
2631 hShlwapi = GetModuleHandleA("shlwapi.dll");
2632 is_win2k_and_lower = GetProcAddress(hShlwapi, "StrChrNW") == 0;
2636 hmlang = LoadLibraryA("mlang.dll");
2637 pLcidToRfc1766A = (void *)GetProcAddress(hmlang, "LcidToRfc1766A");
2639 test_GetAcceptLanguagesA();
2640 test_SHSearchMapInt();
2641 test_alloc_shared();
2643 test_GetShellSecurityDescriptor();
2644 test_SHPackDispParams();
2645 test_IConnectionPoint();
2646 test_SHPropertyBag_ReadLONG();
2647 test_SHSetWindowBits();
2648 test_SHFormatDateTimeA();
2649 test_SHFormatDateTimeW();
2650 test_SHGetObjectCompatFlags();
2651 test_IUnknown_QueryServiceExec();
2652 test_IUnknown_ProfferService();
2653 test_SHCreateWorkerWindowA();
2654 test_SHIShellFolder_EnumObjects();
2655 test_SHGetIniString();