1 /* Unit test suite for SHLWAPI ordinal functions
3 * Copyright 2004 Jon Griffiths
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "wine/test.h"
37 /* Function ptrs for ordinal calls */
38 static HMODULE hShlwapi
;
39 static BOOL is_win2k_and_lower
;
42 static int (WINAPI
*pSHSearchMapInt
)(const int*,const int*,int,int);
43 static HRESULT (WINAPI
*pGetAcceptLanguagesA
)(LPSTR
,LPDWORD
);
45 static HANDLE (WINAPI
*pSHAllocShared
)(LPCVOID
,DWORD
,DWORD
);
46 static LPVOID (WINAPI
*pSHLockShared
)(HANDLE
,DWORD
);
47 static BOOL (WINAPI
*pSHUnlockShared
)(LPVOID
);
48 static BOOL (WINAPI
*pSHFreeShared
)(HANDLE
,DWORD
);
49 static HRESULT(WINAPIV
*pSHPackDispParams
)(DISPPARAMS
*,VARIANTARG
*,UINT
,...);
50 static HRESULT(WINAPI
*pIConnectionPoint_SimpleInvoke
)(IConnectionPoint
*,DISPID
,DISPPARAMS
*);
51 static HRESULT(WINAPI
*pIConnectionPoint_InvokeWithCancel
)(IConnectionPoint
*,DISPID
,DISPPARAMS
*,DWORD
,DWORD
);
52 static HRESULT(WINAPI
*pConnectToConnectionPoint
)(IUnknown
*,REFIID
,BOOL
,IUnknown
*, LPDWORD
,IConnectionPoint
**);
53 static HRESULT(WINAPI
*pSHPropertyBag_ReadLONG
)(IPropertyBag
*,LPCWSTR
,LPLONG
);
54 static LONG (WINAPI
*pSHSetWindowBits
)(HWND
, INT
, UINT
, UINT
);
55 static INT (WINAPI
*pSHFormatDateTimeA
)(const FILETIME UNALIGNED
*, DWORD
*, LPSTR
, UINT
);
56 static INT (WINAPI
*pSHFormatDateTimeW
)(const FILETIME UNALIGNED
*, DWORD
*, LPWSTR
, UINT
);
57 static DWORD (WINAPI
*pSHGetObjectCompatFlags
)(IUnknown
*, const CLSID
*);
58 static BOOL (WINAPI
*pGUIDFromStringA
)(LPSTR
, CLSID
*);
59 static HRESULT (WINAPI
*pIUnknown_QueryServiceExec
)(IUnknown
*, REFIID
, const GUID
*, DWORD
, DWORD
, VARIANT
*, VARIANT
*);
60 static HRESULT (WINAPI
*pIUnknown_ProfferService
)(IUnknown
*, REFGUID
, IServiceProvider
*, DWORD
*);
61 static HWND (WINAPI
*pSHCreateWorkerWindowA
)(LONG
, HWND
, DWORD
, DWORD
, HMENU
, LONG_PTR
);
62 static HRESULT (WINAPI
*pSHIShellFolder_EnumObjects
)(LPSHELLFOLDER
, HWND
, SHCONTF
, IEnumIDList
**);
63 static DWORD (WINAPI
*pSHGetIniStringW
)(LPCWSTR
, LPCWSTR
, LPWSTR
, DWORD
, LPCWSTR
);
64 static BOOL (WINAPI
*pSHSetIniStringW
)(LPCWSTR
, LPCWSTR
, LPCWSTR
, LPCWSTR
);
65 static HKEY (WINAPI
*pSHGetShellKey
)(DWORD
, LPCWSTR
, BOOL
);
66 static HRESULT (WINAPI
*pSKGetValueW
)(DWORD
, LPCWSTR
, LPCWSTR
, DWORD
*, void*, DWORD
*);
67 static HRESULT (WINAPI
*pSKSetValueW
)(DWORD
, LPCWSTR
, LPCWSTR
, DWORD
, void*, DWORD
);
68 static HRESULT (WINAPI
*pSKDeleteValueW
)(DWORD
, LPCWSTR
, LPCWSTR
);
69 static HRESULT (WINAPI
*pSKAllocValueW
)(DWORD
, LPCWSTR
, LPCWSTR
, DWORD
*, void**, DWORD
*);
70 static HWND (WINAPI
*pSHSetParentHwnd
)(HWND
, HWND
);
72 static HMODULE hmlang
;
73 static HRESULT (WINAPI
*pLcidToRfc1766A
)(LCID
, LPSTR
, INT
);
75 static HMODULE hshell32
;
76 static HRESULT (WINAPI
*pSHGetDesktopFolder
)(IShellFolder
**);
78 static const CHAR ie_international
[] = {
79 'S','o','f','t','w','a','r','e','\\',
80 'M','i','c','r','o','s','o','f','t','\\',
81 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
82 'I','n','t','e','r','n','a','t','i','o','n','a','l',0};
83 static const CHAR acceptlanguage
[] = {
84 'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0};
86 static int strcmp_wa(LPCWSTR strw
, const char *stra
)
89 WideCharToMultiByte(CP_ACP
, 0, strw
, -1, buf
, sizeof(buf
), NULL
, NULL
);
90 return lstrcmpA(stra
, buf
);
104 static void init_call_trace(call_trace_t
*ctrace
)
108 ctrace
->calls
= HeapAlloc(GetProcessHeap(), 0, sizeof(call_entry_t
) * ctrace
->alloc
);
111 static void free_call_trace(const call_trace_t
*ctrace
)
113 HeapFree(GetProcessHeap(), 0, ctrace
->calls
);
116 static void add_call(call_trace_t
*ctrace
, int id
, const void *arg0
,
117 const void *arg1
, const void *arg2
, const void *arg3
, const void *arg4
)
128 if (ctrace
->count
== ctrace
->alloc
)
131 ctrace
->calls
= HeapReAlloc(GetProcessHeap(),0, ctrace
->calls
, ctrace
->alloc
*sizeof(call_entry_t
));
134 ctrace
->calls
[ctrace
->count
++] = call
;
137 static void ok_trace_(call_trace_t
*texpected
, call_trace_t
*tgot
, int line
)
139 if (texpected
->count
== tgot
->count
)
143 for (i
= 0; i
< texpected
->count
; i
++)
145 call_entry_t
*expected
= &texpected
->calls
[i
];
146 call_entry_t
*got
= &tgot
->calls
[i
];
149 ok_(__FILE__
, line
)(expected
->id
== got
->id
, "got different ids %d: %d, %d\n", i
+1, expected
->id
, got
->id
);
151 for (j
= 0; j
< 5; j
++)
153 ok_(__FILE__
, line
)(expected
->args
[j
] == got
->args
[j
], "got different args[%d] for %d: %p, %p\n", j
, i
+1,
154 expected
->args
[j
], got
->args
[j
]);
159 ok_(__FILE__
, line
)(0, "traces length mismatch\n");
162 #define ok_trace(a, b) ok_trace_(a, b, __LINE__)
164 /* trace of actually made calls */
165 static call_trace_t trace_got
;
167 static void test_GetAcceptLanguagesA(void)
169 static LPCSTR table
[] = {"de,en-gb;q=0.7,en;q=0.3",
170 "de,en;q=0.3,en-gb;q=0.7", /* sorting is ignored */
171 "winetest", /* content is ignored */
181 LONG res_query
= ERROR_SUCCESS
;
184 DWORD maxlen
= sizeof(buffer
) - 2;
190 if (!pGetAcceptLanguagesA
) {
191 win_skip("GetAcceptLanguagesA is not available\n");
195 lcid
= GetUserDefaultLCID();
197 /* Get the original Value */
198 lres
= RegOpenKeyA(HKEY_CURRENT_USER
, ie_international
, &hroot
);
200 skip("RegOpenKey(%s) failed: %d\n", ie_international
, lres
);
203 len
= sizeof(original
);
205 res_query
= RegQueryValueExA(hroot
, acceptlanguage
, 0, NULL
, (PBYTE
)original
, &len
);
207 RegDeleteValue(hroot
, acceptlanguage
);
209 /* Some windows versions use "lang-COUNTRY" as default */
210 memset(language
, 0, sizeof(language
));
211 len
= GetLocaleInfoA(lcid
, LOCALE_SISO639LANGNAME
, language
, sizeof(language
));
214 lstrcat(language
, "-");
215 memset(buffer
, 0, sizeof(buffer
));
216 len
= GetLocaleInfoA(lcid
, LOCALE_SISO3166CTRYNAME
, buffer
, sizeof(buffer
) - len
- 1);
217 lstrcat(language
, buffer
);
221 /* LOCALE_SNAME has additional parts in some languages. Try only as last chance */
222 memset(language
, 0, sizeof(language
));
223 len
= GetLocaleInfoA(lcid
, LOCALE_SNAME
, language
, sizeof(language
));
226 /* get the default value */
228 memset(buffer
, '#', maxlen
);
230 hr
= pGetAcceptLanguagesA( buffer
, &len
);
233 win_skip("GetAcceptLanguagesA failed with 0x%x\n", hr
);
234 goto restore_original
;
237 if (lstrcmpA(buffer
, language
)) {
238 /* some windows versions use "lang" or "lang-country" as default */
240 if (pLcidToRfc1766A
) {
241 hr
= pLcidToRfc1766A(lcid
, language
, sizeof(language
));
242 ok(hr
== S_OK
, "LcidToRfc1766A returned 0x%x and %s\n", hr
, language
);
246 ok(!lstrcmpA(buffer
, language
),
247 "have '%s' (searching for '%s')\n", language
, buffer
);
249 if (lstrcmpA(buffer
, language
)) {
250 win_skip("no more ideas, how to build the default language '%s'\n", buffer
);
251 goto restore_original
;
254 trace("detected default: %s\n", language
);
255 while ((entry
= table
[i
])) {
257 exactsize
= lstrlenA(entry
);
259 lres
= RegSetValueExA(hroot
, acceptlanguage
, 0, REG_SZ
, (const BYTE
*) entry
, exactsize
+ 1);
260 ok(!lres
, "got %d for RegSetValueExA: %s\n", lres
, entry
);
262 /* len includes space for the terminating 0 before vista/w2k8 */
264 memset(buffer
, '#', maxlen
);
266 hr
= pGetAcceptLanguagesA( buffer
, &len
);
267 ok(((hr
== E_INVALIDARG
) && (len
== 0)) ||
269 ((len
== exactsize
) || (len
== exactsize
+1)) &&
270 !lstrcmpA(buffer
, entry
)),
271 "+2_#%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
274 memset(buffer
, '#', maxlen
);
276 hr
= pGetAcceptLanguagesA( buffer
, &len
);
277 ok(((hr
== E_INVALIDARG
) && (len
== 0)) ||
279 ((len
== exactsize
) || (len
== exactsize
+1)) &&
280 !lstrcmpA(buffer
, entry
)),
281 "+1_#%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
284 memset(buffer
, '#', maxlen
);
286 hr
= pGetAcceptLanguagesA( buffer
, &len
);
288 /* There is no space for the string in the registry.
289 When the buffer is large enough, the default language is returned
291 When the buffer is too small for that fallback, win7_32 and w2k8_64
292 and above fail with HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), but
293 recent os succeed and return a partial result while
294 older os succeed and overflow the buffer */
296 ok(((hr
== E_INVALIDARG
) && (len
== 0)) ||
297 (((hr
== S_OK
) && !lstrcmpA(buffer
, language
) && (len
== lstrlenA(language
))) ||
298 ((hr
== S_OK
) && !memcmp(buffer
, language
, len
)) ||
299 ((hr
== __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
)) && !len
)),
300 "==_#%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
304 memset(buffer
, '#', maxlen
);
306 hr
= pGetAcceptLanguagesA( buffer
, &len
);
307 ok(((hr
== E_INVALIDARG
) && (len
== 0)) ||
308 (((hr
== S_OK
) && !lstrcmpA(buffer
, language
) && (len
== lstrlenA(language
))) ||
309 ((hr
== S_OK
) && !memcmp(buffer
, language
, len
)) ||
310 ((hr
== __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
)) && !len
)),
311 "-1_#%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
315 memset(buffer
, '#', maxlen
);
317 hr
= pGetAcceptLanguagesA( buffer
, &len
);
318 ok(((hr
== E_INVALIDARG
) && (len
== 0)) ||
319 (((hr
== S_OK
) && !lstrcmpA(buffer
, language
) && (len
== lstrlenA(language
))) ||
320 ((hr
== S_OK
) && !memcmp(buffer
, language
, len
)) ||
321 ((hr
== __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
)) && !len
)),
322 "=1_#%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
325 hr
= pGetAcceptLanguagesA( NULL
, &len
);
327 /* w2k3 and below: E_FAIL and untouched len,
328 since w2k8: S_OK and needed size (excluding 0) */
329 ok( ((hr
== S_OK
) && (len
== exactsize
)) ||
330 ((hr
== E_FAIL
) && (len
== maxlen
)),
331 "NULL,max #%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
336 /* without a value in the registry, a default language is returned */
337 RegDeleteValue(hroot
, acceptlanguage
);
340 memset(buffer
, '#', maxlen
);
342 hr
= pGetAcceptLanguagesA( buffer
, &len
);
343 ok( ((hr
== S_OK
) && (len
== lstrlenA(language
))),
344 "max: got 0x%x with %d and %s (expected S_OK with %d and '%s'\n",
345 hr
, len
, buffer
, lstrlenA(language
), language
);
348 memset(buffer
, '#', maxlen
);
350 hr
= pGetAcceptLanguagesA( buffer
, &len
);
351 ok( (((hr
== S_OK
) || (hr
== E_INVALIDARG
)) && !memcmp(buffer
, language
, len
)) ||
352 ((hr
== __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
)) && !len
),
353 "=2: got 0x%x with %d and %s\n", hr
, len
, buffer
);
356 memset(buffer
, '#', maxlen
);
358 hr
= pGetAcceptLanguagesA( buffer
, &len
);
359 /* When the buffer is too small, win7_32 and w2k8_64 and above fail with
360 HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), other versions suceed
361 and return a partial 0 terminated result while other versions
362 fail with E_INVALIDARG and return a partial unterminated result */
363 ok( (((hr
== S_OK
) || (hr
== E_INVALIDARG
)) && !memcmp(buffer
, language
, len
)) ||
364 ((hr
== __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
)) && !len
),
365 "=1: got 0x%x with %d and %s\n", hr
, len
, buffer
);
368 memset(buffer
, '#', maxlen
);
370 hr
= pGetAcceptLanguagesA( buffer
, &len
);
371 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
372 ok((hr
== E_FAIL
) || (hr
== E_INVALIDARG
),
373 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr
);
375 memset(buffer
, '#', maxlen
);
377 hr
= pGetAcceptLanguagesA( buffer
, NULL
);
378 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
379 ok((hr
== E_FAIL
) || (hr
== E_INVALIDARG
),
380 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr
);
383 hr
= pGetAcceptLanguagesA( NULL
, NULL
);
384 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
385 ok((hr
== E_FAIL
) || (hr
== E_INVALIDARG
),
386 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr
);
390 len
= lstrlenA(original
);
391 lres
= RegSetValueExA(hroot
, acceptlanguage
, 0, REG_SZ
, (const BYTE
*) original
, len
? len
+ 1: 0);
392 ok(!lres
, "RegSetValueEx(%s) failed: %d\n", original
, lres
);
396 RegDeleteValue(hroot
, acceptlanguage
);
401 static void test_SHSearchMapInt(void)
403 int keys
[8], values
[8];
406 if (!pSHSearchMapInt
)
409 memset(keys
, 0, sizeof(keys
));
410 memset(values
, 0, sizeof(values
));
411 keys
[0] = 99; values
[0] = 101;
413 /* NULL key/value lists crash native, so skip testing them */
416 i
= pSHSearchMapInt(keys
, values
, 1, keys
[0]);
417 ok(i
== values
[0], "Len 1, expected %d, got %d\n", values
[0], i
);
419 /* Key doesn't exist */
420 i
= pSHSearchMapInt(keys
, values
, 1, 100);
421 ok(i
== -1, "Len 1 - bad key, expected -1, got %d\n", i
);
423 /* Len = 0 => not found */
424 i
= pSHSearchMapInt(keys
, values
, 0, keys
[0]);
425 ok(i
== -1, "Len 1 - passed len 0, expected -1, got %d\n", i
);
427 /* 2 elements, len = 1 */
428 keys
[1] = 98; values
[1] = 102;
429 i
= pSHSearchMapInt(keys
, values
, 1, keys
[1]);
430 ok(i
== -1, "Len 1 - array len 2, expected -1, got %d\n", i
);
432 /* 2 elements, len = 2 */
433 i
= pSHSearchMapInt(keys
, values
, 2, keys
[1]);
434 ok(i
== values
[1], "Len 2, expected %d, got %d\n", values
[1], i
);
436 /* Searches forward */
437 keys
[2] = 99; values
[2] = 103;
438 i
= pSHSearchMapInt(keys
, values
, 3, keys
[0]);
439 ok(i
== values
[0], "Len 3, expected %d, got %d\n", values
[0], i
);
442 static void test_alloc_shared(void)
450 procid
=GetCurrentProcessId();
451 hmem
=pSHAllocShared(NULL
,10,procid
);
452 ok(hmem
!=NULL
,"SHAllocShared(NULL...) failed: %u\n", GetLastError());
453 ret
= pSHFreeShared(hmem
, procid
);
454 ok( ret
, "SHFreeShared failed: %u\n", GetLastError());
457 hmem
=pSHAllocShared(&val
,4,procid
);
458 ok(hmem
!=NULL
,"SHAllocShared(NULL...) failed: %u\n", GetLastError());
460 p
=pSHLockShared(hmem
,procid
);
461 ok(p
!=NULL
,"SHLockShared failed: %u\n", GetLastError());
463 ok(*p
==val
,"Wrong value in shared memory: %d instead of %d\n",*p
,val
);
464 ret
= pSHUnlockShared(p
);
465 ok( ret
, "SHUnlockShared failed: %u\n", GetLastError());
467 ret
= pSHFreeShared(hmem
, procid
);
468 ok( ret
, "SHFreeShared failed: %u\n", GetLastError());
471 static void test_fdsa(void)
475 DWORD num_items
; /* Number of elements inserted */
476 void *mem
; /* Ptr to array */
477 DWORD blocks_alloced
; /* Number of elements allocated */
478 BYTE inc
; /* Number of elements to grow by when we need to expand */
479 BYTE block_size
; /* Size in bytes of an element */
480 BYTE flags
; /* Flags */
483 BOOL (WINAPI
*pFDSA_Initialize
)(DWORD block_size
, DWORD inc
, FDSA_info
*info
, void *mem
,
485 BOOL (WINAPI
*pFDSA_Destroy
)(FDSA_info
*info
);
486 DWORD (WINAPI
*pFDSA_InsertItem
)(FDSA_info
*info
, DWORD where
, const void *block
);
487 BOOL (WINAPI
*pFDSA_DeleteItem
)(FDSA_info
*info
, DWORD where
);
490 int block_size
= 10, init_blocks
= 4, inc
= 2;
494 pFDSA_Initialize
= (void *)GetProcAddress(hShlwapi
, (LPSTR
)208);
495 pFDSA_Destroy
= (void *)GetProcAddress(hShlwapi
, (LPSTR
)209);
496 pFDSA_InsertItem
= (void *)GetProcAddress(hShlwapi
, (LPSTR
)210);
497 pFDSA_DeleteItem
= (void *)GetProcAddress(hShlwapi
, (LPSTR
)211);
499 mem
= HeapAlloc(GetProcessHeap(), 0, block_size
* init_blocks
);
500 memset(&info
, 0, sizeof(info
));
502 ok(pFDSA_Initialize(block_size
, inc
, &info
, mem
, init_blocks
), "FDSA_Initialize rets FALSE\n");
503 ok(info
.num_items
== 0, "num_items = %d\n", info
.num_items
);
504 ok(info
.mem
== mem
, "mem = %p\n", info
.mem
);
505 ok(info
.blocks_alloced
== init_blocks
, "blocks_alloced = %d\n", info
.blocks_alloced
);
506 ok(info
.inc
== inc
, "inc = %d\n", info
.inc
);
507 ok(info
.block_size
== block_size
, "block_size = %d\n", info
.block_size
);
508 ok(info
.flags
== 0, "flags = %d\n", info
.flags
);
510 ret
= pFDSA_InsertItem(&info
, 1234, "1234567890");
511 ok(ret
== 0, "ret = %d\n", ret
);
512 ok(info
.num_items
== 1, "num_items = %d\n", info
.num_items
);
513 ok(info
.mem
== mem
, "mem = %p\n", info
.mem
);
514 ok(info
.blocks_alloced
== init_blocks
, "blocks_alloced = %d\n", info
.blocks_alloced
);
515 ok(info
.inc
== inc
, "inc = %d\n", info
.inc
);
516 ok(info
.block_size
== block_size
, "block_size = %d\n", info
.block_size
);
517 ok(info
.flags
== 0, "flags = %d\n", info
.flags
);
519 ret
= pFDSA_InsertItem(&info
, 1234, "abcdefghij");
520 ok(ret
== 1, "ret = %d\n", ret
);
522 ret
= pFDSA_InsertItem(&info
, 1, "klmnopqrst");
523 ok(ret
== 1, "ret = %d\n", ret
);
525 ret
= pFDSA_InsertItem(&info
, 0, "uvwxyzABCD");
526 ok(ret
== 0, "ret = %d\n", ret
);
527 ok(info
.mem
== mem
, "mem = %p\n", info
.mem
);
528 ok(info
.flags
== 0, "flags = %d\n", info
.flags
);
530 /* This next InsertItem will cause shlwapi to allocate its own mem buffer */
531 ret
= pFDSA_InsertItem(&info
, 0, "EFGHIJKLMN");
532 ok(ret
== 0, "ret = %d\n", ret
);
533 ok(info
.mem
!= mem
, "mem = %p\n", info
.mem
);
534 ok(info
.blocks_alloced
== init_blocks
+ inc
, "blocks_alloced = %d\n", info
.blocks_alloced
);
535 ok(info
.flags
== 0x1, "flags = %d\n", info
.flags
);
537 ok(!memcmp(info
.mem
, "EFGHIJKLMNuvwxyzABCD1234567890klmnopqrstabcdefghij", 50), "mem %s\n", (char*)info
.mem
);
539 ok(pFDSA_DeleteItem(&info
, 2), "rets FALSE\n");
540 ok(info
.mem
!= mem
, "mem = %p\n", info
.mem
);
541 ok(info
.blocks_alloced
== init_blocks
+ inc
, "blocks_alloced = %d\n", info
.blocks_alloced
);
542 ok(info
.flags
== 0x1, "flags = %d\n", info
.flags
);
544 ok(!memcmp(info
.mem
, "EFGHIJKLMNuvwxyzABCDklmnopqrstabcdefghij", 40), "mem %s\n", (char*)info
.mem
);
546 ok(pFDSA_DeleteItem(&info
, 3), "rets FALSE\n");
547 ok(info
.mem
!= mem
, "mem = %p\n", info
.mem
);
548 ok(info
.blocks_alloced
== init_blocks
+ inc
, "blocks_alloced = %d\n", info
.blocks_alloced
);
549 ok(info
.flags
== 0x1, "flags = %d\n", info
.flags
);
551 ok(!memcmp(info
.mem
, "EFGHIJKLMNuvwxyzABCDklmnopqrst", 30), "mem %s\n", (char*)info
.mem
);
553 ok(!pFDSA_DeleteItem(&info
, 4), "does not ret FALSE\n");
555 /* As shlwapi has allocated memory internally, Destroy will ret FALSE */
556 ok(!pFDSA_Destroy(&info
), "FDSA_Destroy does not ret FALSE\n");
559 /* When Initialize is called with inc = 0, set it to 1 */
560 ok(pFDSA_Initialize(block_size
, 0, &info
, mem
, init_blocks
), "FDSA_Initialize rets FALSE\n");
561 ok(info
.inc
== 1, "inc = %d\n", info
.inc
);
563 /* This time, because shlwapi hasn't had to allocate memory
564 internally, Destroy rets non-zero */
565 ok(pFDSA_Destroy(&info
), "FDSA_Destroy rets FALSE\n");
568 HeapFree(GetProcessHeap(), 0, mem
);
572 typedef struct SHELL_USER_SID
{
573 SID_IDENTIFIER_AUTHORITY sidAuthority
;
576 } SHELL_USER_SID
, *PSHELL_USER_SID
;
577 typedef struct SHELL_USER_PERMISSION
{
578 SHELL_USER_SID susID
;
583 DWORD dwInheritAccessMask
;
584 } SHELL_USER_PERMISSION
, *PSHELL_USER_PERMISSION
;
585 static void test_GetShellSecurityDescriptor(void)
587 SHELL_USER_PERMISSION supCurrentUserFull
= {
588 { {SECURITY_NULL_SID_AUTHORITY
}, 0, 0 },
589 ACCESS_ALLOWED_ACE_TYPE
, FALSE
,
591 #define MY_INHERITANCE 0xBE /* invalid value to proof behavior */
592 SHELL_USER_PERMISSION supEveryoneDenied
= {
593 { {SECURITY_WORLD_SID_AUTHORITY
}, SECURITY_WORLD_RID
, 0 },
594 ACCESS_DENIED_ACE_TYPE
, TRUE
,
595 GENERIC_WRITE
, MY_INHERITANCE
| 0xDEADBA00, GENERIC_READ
};
596 PSHELL_USER_PERMISSION rgsup
[2] = {
597 &supCurrentUserFull
, &supEveryoneDenied
,
599 SECURITY_DESCRIPTOR
* psd
;
600 SECURITY_DESCRIPTOR
* (WINAPI
*pGetShellSecurityDescriptor
)(PSHELL_USER_PERMISSION
*,int);
601 void *pChrCmpIW
= GetProcAddress(hShlwapi
, "ChrCmpIW");
603 pGetShellSecurityDescriptor
=(void*)GetProcAddress(hShlwapi
,(char*)475);
605 if(!pGetShellSecurityDescriptor
)
607 win_skip("GetShellSecurityDescriptor not available\n");
611 if(pChrCmpIW
&& pChrCmpIW
== pGetShellSecurityDescriptor
) /* win2k */
613 win_skip("Skipping for GetShellSecurityDescriptor, same ordinal used for ChrCmpIW\n");
617 psd
= pGetShellSecurityDescriptor(NULL
, 2);
619 broken(psd
==INVALID_HANDLE_VALUE
), /* IE5 */
620 "GetShellSecurityDescriptor should fail\n");
621 psd
= pGetShellSecurityDescriptor(rgsup
, 0);
622 ok(psd
==NULL
, "GetShellSecurityDescriptor should fail, got %p\n", psd
);
624 SetLastError(0xdeadbeef);
625 psd
= pGetShellSecurityDescriptor(rgsup
, 2);
626 if (psd
== NULL
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
628 /* The previous calls to GetShellSecurityDescriptor don't set the last error */
629 win_skip("GetShellSecurityDescriptor is not implemented\n");
632 if (psd
== INVALID_HANDLE_VALUE
)
634 win_skip("GetShellSecurityDescriptor is broken on IE5\n");
637 ok(psd
!=NULL
, "GetShellSecurityDescriptor failed\n");
640 BOOL bHasDacl
= FALSE
, bDefaulted
, ret
;
643 SECURITY_DESCRIPTOR_CONTROL control
;
645 ok(IsValidSecurityDescriptor(psd
), "returned value is not valid SD\n");
647 ret
= GetSecurityDescriptorControl(psd
, &control
, &dwRev
);
648 ok(ret
, "GetSecurityDescriptorControl failed with error %u\n", GetLastError());
649 ok(0 == (control
& SE_SELF_RELATIVE
), "SD should be absolute\n");
651 ret
= GetSecurityDescriptorDacl(psd
, &bHasDacl
, &pAcl
, &bDefaulted
);
652 ok(ret
, "GetSecurityDescriptorDacl failed with error %u\n", GetLastError());
654 ok(bHasDacl
, "SD has no DACL\n");
657 ok(!bDefaulted
, "DACL should not be defaulted\n");
659 ok(pAcl
!= NULL
, "NULL DACL!\n");
662 ACL_SIZE_INFORMATION asiSize
;
664 ok(IsValidAcl(pAcl
), "DACL is not valid\n");
666 ret
= GetAclInformation(pAcl
, &asiSize
, sizeof(asiSize
), AclSizeInformation
);
667 ok(ret
, "GetAclInformation failed with error %u\n", GetLastError());
669 ok(asiSize
.AceCount
== 3, "Incorrect number of ACEs: %d entries\n", asiSize
.AceCount
);
670 if (asiSize
.AceCount
== 3)
672 ACCESS_ALLOWED_ACE
*paaa
; /* will use for DENIED too */
674 ret
= GetAce(pAcl
, 0, (LPVOID
*)&paaa
);
675 ok(ret
, "GetAce failed with error %u\n", GetLastError());
676 ok(paaa
->Header
.AceType
== ACCESS_ALLOWED_ACE_TYPE
,
677 "Invalid ACE type %d\n", paaa
->Header
.AceType
);
678 ok(paaa
->Header
.AceFlags
== 0, "Invalid ACE flags %x\n", paaa
->Header
.AceFlags
);
679 ok(paaa
->Mask
== GENERIC_ALL
, "Invalid ACE mask %x\n", paaa
->Mask
);
681 ret
= GetAce(pAcl
, 1, (LPVOID
*)&paaa
);
682 ok(ret
, "GetAce failed with error %u\n", GetLastError());
683 ok(paaa
->Header
.AceType
== ACCESS_DENIED_ACE_TYPE
,
684 "Invalid ACE type %d\n", paaa
->Header
.AceType
);
685 /* first one of two ACEs generated from inheritable entry - without inheritance */
686 ok(paaa
->Header
.AceFlags
== 0, "Invalid ACE flags %x\n", paaa
->Header
.AceFlags
);
687 ok(paaa
->Mask
== GENERIC_WRITE
, "Invalid ACE mask %x\n", paaa
->Mask
);
689 ret
= GetAce(pAcl
, 2, (LPVOID
*)&paaa
);
690 ok(ret
, "GetAce failed with error %u\n", GetLastError());
691 ok(paaa
->Header
.AceType
== ACCESS_DENIED_ACE_TYPE
,
692 "Invalid ACE type %d\n", paaa
->Header
.AceType
);
693 /* second ACE - with inheritance */
694 ok(paaa
->Header
.AceFlags
== MY_INHERITANCE
,
695 "Invalid ACE flags %x\n", paaa
->Header
.AceFlags
);
696 ok(paaa
->Mask
== GENERIC_READ
, "Invalid ACE mask %x\n", paaa
->Mask
);
705 static void test_SHPackDispParams(void)
711 if(!pSHPackDispParams
)
712 win_skip("SHPackSidpParams not available\n");
714 memset(¶ms
, 0xc0, sizeof(params
));
715 memset(vars
, 0xc0, sizeof(vars
));
716 hres
= pSHPackDispParams(¶ms
, vars
, 1, VT_I4
, 0xdeadbeef);
717 ok(hres
== S_OK
, "SHPackDispParams failed: %08x\n", hres
);
718 ok(params
.cArgs
== 1, "params.cArgs = %d\n", params
.cArgs
);
719 ok(params
.cNamedArgs
== 0, "params.cNamedArgs = %d\n", params
.cArgs
);
720 ok(params
.rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", params
.rgdispidNamedArgs
);
721 ok(params
.rgvarg
== vars
, "params.rgvarg = %p\n", params
.rgvarg
);
722 ok(V_VT(vars
) == VT_I4
, "V_VT(var) = %d\n", V_VT(vars
));
723 ok(V_I4(vars
) == 0xdeadbeef, "failed %x\n", V_I4(vars
));
725 memset(¶ms
, 0xc0, sizeof(params
));
726 hres
= pSHPackDispParams(¶ms
, NULL
, 0, 0);
727 ok(hres
== S_OK
, "SHPackDispParams failed: %08x\n", hres
);
728 ok(params
.cArgs
== 0, "params.cArgs = %d\n", params
.cArgs
);
729 ok(params
.cNamedArgs
== 0, "params.cNamedArgs = %d\n", params
.cArgs
);
730 ok(params
.rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", params
.rgdispidNamedArgs
);
731 ok(params
.rgvarg
== NULL
, "params.rgvarg = %p\n", params
.rgvarg
);
733 memset(vars
, 0xc0, sizeof(vars
));
734 memset(¶ms
, 0xc0, sizeof(params
));
735 hres
= pSHPackDispParams(¶ms
, vars
, 4, VT_BSTR
, (void*)0xdeadbeef, VT_EMPTY
, 10,
736 VT_I4
, 100, VT_DISPATCH
, (void*)0xdeadbeef);
737 ok(hres
== S_OK
, "SHPackDispParams failed: %08x\n", hres
);
738 ok(params
.cArgs
== 4, "params.cArgs = %d\n", params
.cArgs
);
739 ok(params
.cNamedArgs
== 0, "params.cNamedArgs = %d\n", params
.cArgs
);
740 ok(params
.rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", params
.rgdispidNamedArgs
);
741 ok(params
.rgvarg
== vars
, "params.rgvarg = %p\n", params
.rgvarg
);
742 ok(V_VT(vars
) == VT_DISPATCH
, "V_VT(vars[0]) = %x\n", V_VT(vars
));
743 ok(V_I4(vars
) == 0xdeadbeef, "V_I4(vars[0]) = %x\n", V_I4(vars
));
744 ok(V_VT(vars
+1) == VT_I4
, "V_VT(vars[1]) = %d\n", V_VT(vars
+1));
745 ok(V_I4(vars
+1) == 100, "V_I4(vars[1]) = %x\n", V_I4(vars
+1));
746 ok(V_VT(vars
+2) == VT_I4
, "V_VT(vars[2]) = %d\n", V_VT(vars
+2));
747 ok(V_I4(vars
+2) == 10, "V_I4(vars[2]) = %x\n", V_I4(vars
+2));
748 ok(V_VT(vars
+3) == VT_BSTR
, "V_VT(vars[3]) = %d\n", V_VT(vars
+3));
749 ok(V_BSTR(vars
+3) == (void*)0xdeadbeef, "V_BSTR(vars[3]) = %p\n", V_BSTR(vars
+3));
754 IDispatch IDispatch_iface
;
758 static inline Disp
*impl_from_IDispatch(IDispatch
*iface
)
760 return CONTAINING_RECORD(iface
, Disp
, IDispatch_iface
);
763 typedef struct _contain
765 IConnectionPointContainer IConnectionPointContainer_iface
;
769 IConnectionPoint
**pt
;
772 static inline Contain
*impl_from_IConnectionPointContainer(IConnectionPointContainer
*iface
)
774 return CONTAINING_RECORD(iface
, Contain
, IConnectionPointContainer_iface
);
777 typedef struct _cntptn
779 IConnectionPoint IConnectionPoint_iface
;
788 static inline ConPt
*impl_from_IConnectionPoint(IConnectionPoint
*iface
)
790 return CONTAINING_RECORD(iface
, ConPt
, IConnectionPoint_iface
);
795 IEnumConnections IEnumConnections_iface
;
802 static inline EnumCon
*impl_from_IEnumConnections(IEnumConnections
*iface
)
804 return CONTAINING_RECORD(iface
, EnumCon
, IEnumConnections_iface
);
807 typedef struct _enumpt
809 IEnumConnectionPoints IEnumConnectionPoints_iface
;
816 static inline EnumPt
*impl_from_IEnumConnectionPoints(IEnumConnectionPoints
*iface
)
818 return CONTAINING_RECORD(iface
, EnumPt
, IEnumConnectionPoints_iface
);
822 static HRESULT WINAPI
Disp_QueryInterface(
829 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDispatch
))
836 IUnknown_AddRef(This
);
840 trace("no interface\n");
841 return E_NOINTERFACE
;
844 static ULONG WINAPI
Disp_AddRef(IDispatch
* This
)
846 Disp
*iface
= impl_from_IDispatch(This
);
847 return InterlockedIncrement(&iface
->refCount
);
850 static ULONG WINAPI
Disp_Release(IDispatch
* This
)
852 Disp
*iface
= impl_from_IDispatch(This
);
855 ret
= InterlockedDecrement(&iface
->refCount
);
857 HeapFree(GetProcessHeap(),0,This
);
861 static HRESULT WINAPI
Disp_GetTypeInfoCount(
865 return ERROR_SUCCESS
;
868 static HRESULT WINAPI
Disp_GetTypeInfo(
874 return ERROR_SUCCESS
;
877 static HRESULT WINAPI
Disp_GetIDsOfNames(
885 return ERROR_SUCCESS
;
888 static HRESULT WINAPI
Disp_Invoke(
894 DISPPARAMS
*pDispParams
,
896 EXCEPINFO
*pExcepInfo
,
899 trace("%p %x %p %x %x %p %p %p %p\n",This
,dispIdMember
,riid
,lcid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,puArgErr
);
901 ok(dispIdMember
== 0xa0 || dispIdMember
== 0xa1, "Unknown dispIdMember\n");
902 ok(pDispParams
!= NULL
, "Invoked with NULL pDispParams\n");
903 ok(wFlags
== DISPATCH_METHOD
, "Wrong flags %x\n",wFlags
);
904 ok(lcid
== 0,"Wrong lcid %x\n",lcid
);
905 if (dispIdMember
== 0xa0)
907 ok(pDispParams
->cArgs
== 0, "params.cArgs = %d\n", pDispParams
->cArgs
);
908 ok(pDispParams
->cNamedArgs
== 0, "params.cNamedArgs = %d\n", pDispParams
->cArgs
);
909 ok(pDispParams
->rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", pDispParams
->rgdispidNamedArgs
);
910 ok(pDispParams
->rgvarg
== NULL
, "params.rgvarg = %p\n", pDispParams
->rgvarg
);
912 else if (dispIdMember
== 0xa1)
914 ok(pDispParams
->cArgs
== 2, "params.cArgs = %d\n", pDispParams
->cArgs
);
915 ok(pDispParams
->cNamedArgs
== 0, "params.cNamedArgs = %d\n", pDispParams
->cArgs
);
916 ok(pDispParams
->rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", pDispParams
->rgdispidNamedArgs
);
917 ok(V_VT(pDispParams
->rgvarg
) == VT_BSTR
, "V_VT(var) = %d\n", V_VT(pDispParams
->rgvarg
));
918 ok(V_I4(pDispParams
->rgvarg
) == 0xdeadcafe , "failed %p\n", V_BSTR(pDispParams
->rgvarg
));
919 ok(V_VT(pDispParams
->rgvarg
+1) == VT_I4
, "V_VT(var) = %d\n", V_VT(pDispParams
->rgvarg
+1));
920 ok(V_I4(pDispParams
->rgvarg
+1) == 0xdeadbeef, "failed %x\n", V_I4(pDispParams
->rgvarg
+1));
923 return ERROR_SUCCESS
;
926 static const IDispatchVtbl disp_vtbl
= {
931 Disp_GetTypeInfoCount
,
937 static HRESULT WINAPI
Enum_QueryInterface(
938 IEnumConnections
* This
,
944 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IEnumConnections
))
951 IUnknown_AddRef(This
);
955 trace("no interface\n");
956 return E_NOINTERFACE
;
959 static ULONG WINAPI
Enum_AddRef(IEnumConnections
* This
)
961 EnumCon
*iface
= impl_from_IEnumConnections(This
);
962 return InterlockedIncrement(&iface
->refCount
);
965 static ULONG WINAPI
Enum_Release(IEnumConnections
* This
)
967 EnumCon
*iface
= impl_from_IEnumConnections(This
);
970 ret
= InterlockedDecrement(&iface
->refCount
);
972 HeapFree(GetProcessHeap(),0,This
);
976 static HRESULT WINAPI
Enum_Next(
977 IEnumConnections
* This
,
982 EnumCon
*iface
= impl_from_IEnumConnections(This
);
984 if (cConnections
> 0 && iface
->idx
< iface
->pt
->sinkCount
)
986 rgcd
->pUnk
= iface
->pt
->sink
[iface
->idx
];
987 IUnknown_AddRef(iface
->pt
->sink
[iface
->idx
]);
998 static HRESULT WINAPI
Enum_Skip(
999 IEnumConnections
* This
,
1005 static HRESULT WINAPI
Enum_Reset(
1006 IEnumConnections
* This
)
1011 static HRESULT WINAPI
Enum_Clone(
1012 IEnumConnections
* This
,
1013 IEnumConnections
**ppEnum
)
1018 static const IEnumConnectionsVtbl enum_vtbl
= {
1020 Enum_QueryInterface
,
1029 static HRESULT WINAPI
ConPt_QueryInterface(
1030 IConnectionPoint
* This
,
1036 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IConnectionPoint
))
1043 IUnknown_AddRef(This
);
1047 trace("no interface\n");
1048 return E_NOINTERFACE
;
1051 static ULONG WINAPI
ConPt_AddRef(
1052 IConnectionPoint
* This
)
1054 ConPt
*iface
= impl_from_IConnectionPoint(This
);
1055 return InterlockedIncrement(&iface
->refCount
);
1058 static ULONG WINAPI
ConPt_Release(
1059 IConnectionPoint
* This
)
1061 ConPt
*iface
= impl_from_IConnectionPoint(This
);
1064 ret
= InterlockedDecrement(&iface
->refCount
);
1067 if (iface
->sinkCount
> 0)
1070 for (i
= 0; i
< iface
->sinkCount
; i
++)
1073 IUnknown_Release(iface
->sink
[i
]);
1075 HeapFree(GetProcessHeap(),0,iface
->sink
);
1077 HeapFree(GetProcessHeap(),0,This
);
1082 static HRESULT WINAPI
ConPt_GetConnectionInterface(
1083 IConnectionPoint
* This
,
1087 ConPt
*iface
= impl_from_IConnectionPoint(This
);
1094 memcpy(pIID
,&iface
->id
,sizeof(GUID
));
1098 static HRESULT WINAPI
ConPt_GetConnectionPointContainer(
1099 IConnectionPoint
* This
,
1100 IConnectionPointContainer
**ppCPC
)
1102 ConPt
*iface
= impl_from_IConnectionPoint(This
);
1104 *ppCPC
= &iface
->container
->IConnectionPointContainer_iface
;
1108 static HRESULT WINAPI
ConPt_Advise(
1109 IConnectionPoint
* This
,
1113 ConPt
*iface
= impl_from_IConnectionPoint(This
);
1115 if (iface
->sinkCount
== 0)
1116 iface
->sink
= HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown
*));
1118 iface
->sink
= HeapReAlloc(GetProcessHeap(),0,iface
->sink
,sizeof(IUnknown
*)*(iface
->sinkCount
+1));
1119 iface
->sink
[iface
->sinkCount
] = pUnkSink
;
1120 IUnknown_AddRef(pUnkSink
);
1122 *pdwCookie
= iface
->sinkCount
;
1126 static HRESULT WINAPI
ConPt_Unadvise(
1127 IConnectionPoint
* This
,
1130 ConPt
*iface
= impl_from_IConnectionPoint(This
);
1132 if (dwCookie
> iface
->sinkCount
)
1136 IUnknown_Release(iface
->sink
[dwCookie
-1]);
1137 iface
->sink
[dwCookie
-1] = NULL
;
1142 static HRESULT WINAPI
ConPt_EnumConnections(
1143 IConnectionPoint
* This
,
1144 IEnumConnections
**ppEnum
)
1148 ec
= HeapAlloc(GetProcessHeap(),0,sizeof(EnumCon
));
1149 ec
->IEnumConnections_iface
.lpVtbl
= &enum_vtbl
;
1151 ec
->pt
= impl_from_IConnectionPoint(This
);
1153 *ppEnum
= &ec
->IEnumConnections_iface
;
1158 static const IConnectionPointVtbl point_vtbl
= {
1159 ConPt_QueryInterface
,
1163 ConPt_GetConnectionInterface
,
1164 ConPt_GetConnectionPointContainer
,
1167 ConPt_EnumConnections
1170 static HRESULT WINAPI
EnumPt_QueryInterface(
1171 IEnumConnectionPoints
* This
,
1177 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IEnumConnectionPoints
))
1184 IUnknown_AddRef(This
);
1188 trace("no interface\n");
1189 return E_NOINTERFACE
;
1192 static ULONG WINAPI
EnumPt_AddRef(IEnumConnectionPoints
* This
)
1194 EnumPt
*iface
= impl_from_IEnumConnectionPoints(This
);
1195 return InterlockedIncrement(&iface
->refCount
);
1198 static ULONG WINAPI
EnumPt_Release(IEnumConnectionPoints
* This
)
1200 EnumPt
*iface
= impl_from_IEnumConnectionPoints(This
);
1203 ret
= InterlockedDecrement(&iface
->refCount
);
1205 HeapFree(GetProcessHeap(),0,This
);
1209 static HRESULT WINAPI
EnumPt_Next(
1210 IEnumConnectionPoints
* This
,
1212 IConnectionPoint
**rgcd
,
1215 EnumPt
*iface
= impl_from_IEnumConnectionPoints(This
);
1217 if (cConnections
> 0 && iface
->idx
< iface
->container
->ptCount
)
1219 *rgcd
= iface
->container
->pt
[iface
->idx
];
1220 IUnknown_AddRef(iface
->container
->pt
[iface
->idx
]);
1230 static HRESULT WINAPI
EnumPt_Skip(
1231 IEnumConnectionPoints
* This
,
1237 static HRESULT WINAPI
EnumPt_Reset(
1238 IEnumConnectionPoints
* This
)
1243 static HRESULT WINAPI
EnumPt_Clone(
1244 IEnumConnectionPoints
* This
,
1245 IEnumConnectionPoints
**ppEnumPt
)
1250 static const IEnumConnectionPointsVtbl enumpt_vtbl
= {
1252 EnumPt_QueryInterface
,
1261 static HRESULT WINAPI
Contain_QueryInterface(
1262 IConnectionPointContainer
* This
,
1268 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IConnectionPointContainer
))
1275 IUnknown_AddRef(This
);
1279 trace("no interface\n");
1280 return E_NOINTERFACE
;
1283 static ULONG WINAPI
Contain_AddRef(
1284 IConnectionPointContainer
* This
)
1286 Contain
*iface
= impl_from_IConnectionPointContainer(This
);
1287 return InterlockedIncrement(&iface
->refCount
);
1290 static ULONG WINAPI
Contain_Release(
1291 IConnectionPointContainer
* This
)
1293 Contain
*iface
= impl_from_IConnectionPointContainer(This
);
1296 ret
= InterlockedDecrement(&iface
->refCount
);
1299 if (iface
->ptCount
> 0)
1302 for (i
= 0; i
< iface
->ptCount
; i
++)
1303 IUnknown_Release(iface
->pt
[i
]);
1304 HeapFree(GetProcessHeap(),0,iface
->pt
);
1306 HeapFree(GetProcessHeap(),0,This
);
1311 static HRESULT WINAPI
Contain_EnumConnectionPoints(
1312 IConnectionPointContainer
* This
,
1313 IEnumConnectionPoints
**ppEnum
)
1317 ec
= HeapAlloc(GetProcessHeap(),0,sizeof(EnumPt
));
1318 ec
->IEnumConnectionPoints_iface
.lpVtbl
= &enumpt_vtbl
;
1321 ec
->container
= impl_from_IConnectionPointContainer(This
);
1322 *ppEnum
= &ec
->IEnumConnectionPoints_iface
;
1327 static HRESULT WINAPI
Contain_FindConnectionPoint(
1328 IConnectionPointContainer
* This
,
1330 IConnectionPoint
**ppCP
)
1332 Contain
*iface
= impl_from_IConnectionPointContainer(This
);
1335 if (!IsEqualIID(riid
, &IID_NULL
) || iface
->ptCount
==0)
1337 pt
= HeapAlloc(GetProcessHeap(),0,sizeof(ConPt
));
1338 pt
->IConnectionPoint_iface
.lpVtbl
= &point_vtbl
;
1342 pt
->container
= iface
;
1343 pt
->id
= IID_IDispatch
;
1345 if (iface
->ptCount
== 0)
1346 iface
->pt
=HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown
*));
1348 iface
->pt
= HeapReAlloc(GetProcessHeap(),0,iface
->pt
,sizeof(IUnknown
*)*(iface
->ptCount
+1));
1349 iface
->pt
[iface
->ptCount
] = &pt
->IConnectionPoint_iface
;
1352 *ppCP
= &pt
->IConnectionPoint_iface
;
1356 *ppCP
= iface
->pt
[0];
1357 IUnknown_AddRef((IUnknown
*)*ppCP
);
1363 static const IConnectionPointContainerVtbl contain_vtbl
= {
1364 Contain_QueryInterface
,
1368 Contain_EnumConnectionPoints
,
1369 Contain_FindConnectionPoint
1372 static void test_IConnectionPoint(void)
1376 IConnectionPoint
*point
;
1379 DWORD cookie
= 0xffffffff;
1383 if (!pIConnectionPoint_SimpleInvoke
|| !pConnectToConnectionPoint
)
1385 win_skip("IConnectionPoint Apis not present\n");
1389 container
= HeapAlloc(GetProcessHeap(),0,sizeof(Contain
));
1390 container
->IConnectionPointContainer_iface
.lpVtbl
= &contain_vtbl
;
1391 container
->refCount
= 1;
1392 container
->ptCount
= 0;
1393 container
->pt
= NULL
;
1395 dispatch
= HeapAlloc(GetProcessHeap(),0,sizeof(Disp
));
1396 dispatch
->IDispatch_iface
.lpVtbl
= &disp_vtbl
;
1397 dispatch
->refCount
= 1;
1399 rc
= pConnectToConnectionPoint((IUnknown
*)dispatch
, &IID_NULL
, TRUE
, (IUnknown
*)container
, &cookie
, &point
);
1400 ok(rc
== S_OK
, "pConnectToConnectionPoint failed with %x\n",rc
);
1401 ok(point
!= NULL
, "returned ConnectionPoint is NULL\n");
1402 ok(cookie
!= 0xffffffff, "invalid cookie returned\n");
1404 rc
= pIConnectionPoint_SimpleInvoke(point
,0xa0,NULL
);
1405 ok(rc
== S_OK
, "pConnectToConnectionPoint failed with %x\n",rc
);
1407 if (pSHPackDispParams
)
1409 memset(¶ms
, 0xc0, sizeof(params
));
1410 memset(vars
, 0xc0, sizeof(vars
));
1411 rc
= pSHPackDispParams(¶ms
, vars
, 2, VT_I4
, 0xdeadbeef, VT_BSTR
, 0xdeadcafe);
1412 ok(rc
== S_OK
, "SHPackDispParams failed: %08x\n", rc
);
1414 rc
= pIConnectionPoint_SimpleInvoke(point
,0xa1,¶ms
);
1415 ok(rc
== S_OK
, "pConnectToConnectionPoint failed with %x\n",rc
);
1418 win_skip("pSHPackDispParams not present\n");
1420 rc
= pConnectToConnectionPoint(NULL
, &IID_NULL
, FALSE
, (IUnknown
*)container
, &cookie
, NULL
);
1421 ok(rc
== S_OK
, "pConnectToConnectionPoint failed with %x\n",rc
);
1423 /* MSDN says this should be required but it crashs on XP
1424 IUnknown_Release(point);
1426 ref
= IUnknown_Release((IUnknown
*)container
);
1427 ok(ref
== 0, "leftover IConnectionPointContainer reference %i\n",ref
);
1428 ref
= IUnknown_Release((IUnknown
*)dispatch
);
1429 ok(ref
== 0, "leftover IDispatch reference %i\n",ref
);
1432 typedef struct _propbag
1434 IPropertyBag IPropertyBag_iface
;
1439 static inline PropBag
*impl_from_IPropertyBag(IPropertyBag
*iface
)
1441 return CONTAINING_RECORD(iface
, PropBag
, IPropertyBag_iface
);
1445 static HRESULT WINAPI
Prop_QueryInterface(
1452 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IPropertyBag
))
1459 IUnknown_AddRef(This
);
1463 trace("no interface\n");
1464 return E_NOINTERFACE
;
1467 static ULONG WINAPI
Prop_AddRef(
1470 PropBag
*iface
= impl_from_IPropertyBag(This
);
1471 return InterlockedIncrement(&iface
->refCount
);
1474 static ULONG WINAPI
Prop_Release(
1477 PropBag
*iface
= impl_from_IPropertyBag(This
);
1480 ret
= InterlockedDecrement(&iface
->refCount
);
1482 HeapFree(GetProcessHeap(),0,This
);
1486 static HRESULT WINAPI
Prop_Read(
1488 LPCOLESTR pszPropName
,
1490 IErrorLog
*pErrorLog
)
1492 V_VT(pVar
) = VT_BLOB
|VT_BYREF
;
1493 V_BYREF(pVar
) = (LPVOID
)0xdeadcafe;
1497 static HRESULT WINAPI
Prop_Write(
1499 LPCOLESTR pszPropName
,
1506 static const IPropertyBagVtbl prop_vtbl
= {
1507 Prop_QueryInterface
,
1515 static void test_SHPropertyBag_ReadLONG(void)
1520 static const WCHAR szName1
[] = {'n','a','m','e','1',0};
1522 if (!pSHPropertyBag_ReadLONG
)
1524 win_skip("SHPropertyBag_ReadLONG not present\n");
1528 pb
= HeapAlloc(GetProcessHeap(),0,sizeof(PropBag
));
1530 pb
->IPropertyBag_iface
.lpVtbl
= &prop_vtbl
;
1533 rc
= pSHPropertyBag_ReadLONG(NULL
, szName1
, &out
);
1534 ok(rc
== E_INVALIDARG
|| broken(rc
== 0), "incorrect return %x\n",rc
);
1535 ok(out
== 0xfeedface, "value should not have changed\n");
1536 rc
= pSHPropertyBag_ReadLONG(&pb
->IPropertyBag_iface
, NULL
, &out
);
1537 ok(rc
== E_INVALIDARG
|| broken(rc
== 0) || broken(rc
== 1), "incorrect return %x\n",rc
);
1538 ok(out
== 0xfeedface, "value should not have changed\n");
1539 rc
= pSHPropertyBag_ReadLONG(&pb
->IPropertyBag_iface
, szName1
, NULL
);
1540 ok(rc
== E_INVALIDARG
|| broken(rc
== 0) || broken(rc
== 1), "incorrect return %x\n",rc
);
1541 ok(out
== 0xfeedface, "value should not have changed\n");
1542 rc
= pSHPropertyBag_ReadLONG(&pb
->IPropertyBag_iface
, szName1
, &out
);
1543 ok(rc
== DISP_E_BADVARTYPE
|| broken(rc
== 0) || broken(rc
== 1), "incorrect return %x\n",rc
);
1544 ok(out
== 0xfeedface || broken(out
== 0xfeedfa00), "value should not have changed %x\n",out
);
1545 IUnknown_Release((IUnknown
*)pb
);
1550 static void test_SHSetWindowBits(void)
1553 DWORD style
, styleold
;
1556 if(!pSHSetWindowBits
)
1558 win_skip("SHSetWindowBits is not available\n");
1563 clsA
.lpfnWndProc
= DefWindowProcA
;
1564 clsA
.cbClsExtra
= 0;
1565 clsA
.cbWndExtra
= 0;
1566 clsA
.hInstance
= GetModuleHandleA(NULL
);
1568 clsA
.hCursor
= LoadCursorA(0, IDC_ARROW
);
1569 clsA
.hbrBackground
= NULL
;
1570 clsA
.lpszMenuName
= NULL
;
1571 clsA
.lpszClassName
= "Shlwapi test class";
1572 RegisterClassA(&clsA
);
1574 hwnd
= CreateWindowA("Shlwapi test class", "Test", WS_VISIBLE
, 0, 0, 100, 100,
1575 NULL
, NULL
, GetModuleHandle(NULL
), 0);
1576 ok(IsWindow(hwnd
), "failed to create window\n");
1579 SetLastError(0xdeadbeef);
1580 style
= pSHSetWindowBits(NULL
, GWL_STYLE
, 0, 0);
1581 ok(style
== 0, "expected 0 retval, got %d\n", style
);
1582 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
||
1583 broken(GetLastError() == 0xdeadbeef), /* Win9x/WinMe */
1584 "expected ERROR_INVALID_WINDOW_HANDLE, got %d\n", GetLastError());
1586 /* zero mask, zero flags */
1587 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1588 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, 0, 0);
1589 ok(styleold
== style
, "expected old style\n");
1590 ok(styleold
== GetWindowLongA(hwnd
, GWL_STYLE
), "expected to keep old style\n");
1593 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1594 ok(styleold
& WS_VISIBLE
, "expected WS_VISIBLE\n");
1595 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, WS_VISIBLE
, 0);
1597 ok(style
== styleold
, "expected previous style, got %x\n", style
);
1598 ok((GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
) == 0, "expected updated style\n");
1600 /* test mask, unset style bit used */
1601 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1602 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, WS_VISIBLE
, 0);
1603 ok(style
== styleold
, "expected previous style, got %x\n", style
);
1604 ok(styleold
== GetWindowLongA(hwnd
, GWL_STYLE
), "expected to keep old style\n");
1606 /* set back with flags */
1607 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1608 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, WS_VISIBLE
, WS_VISIBLE
);
1609 ok(style
== styleold
, "expected previous style, got %x\n", style
);
1610 ok(GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
, "expected updated style\n");
1612 /* reset and try to set without a mask */
1613 pSHSetWindowBits(hwnd
, GWL_STYLE
, WS_VISIBLE
, 0);
1614 ok((GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
) == 0, "expected updated style\n");
1615 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1616 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, 0, WS_VISIBLE
);
1617 ok(style
== styleold
, "expected previous style, got %x\n", style
);
1618 ok((GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
) == 0, "expected updated style\n");
1620 DestroyWindow(hwnd
);
1622 UnregisterClassA("Shlwapi test class", GetModuleHandleA(NULL
));
1625 static void test_SHFormatDateTimeA(void)
1627 FILETIME UNALIGNED filetime
;
1628 CHAR buff
[100], buff2
[100], buff3
[100];
1633 if(!pSHFormatDateTimeA
)
1635 win_skip("pSHFormatDateTimeA isn't available\n");
1641 /* crashes on native */
1642 pSHFormatDateTimeA(NULL
, NULL
, NULL
, 0);
1646 SystemTimeToFileTime(&st
, &filetime
);
1647 /* SHFormatDateTime expects input as utc */
1648 LocalFileTimeToFileTime(&filetime
, &filetime
);
1650 /* no way to get required buffer length here */
1651 SetLastError(0xdeadbeef);
1652 ret
= pSHFormatDateTimeA(&filetime
, NULL
, NULL
, 0);
1653 ok(ret
== 0, "got %d\n", ret
);
1654 ok(GetLastError() == 0xdeadbeef || broken(GetLastError() == ERROR_SUCCESS
/* Win7 */),
1655 "expected 0xdeadbeef, got %d\n", GetLastError());
1657 SetLastError(0xdeadbeef);
1658 buff
[0] = 'a'; buff
[1] = 0;
1659 ret
= pSHFormatDateTimeA(&filetime
, NULL
, buff
, 0);
1660 ok(ret
== 0, "got %d\n", ret
);
1661 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1662 ok(buff
[0] == 'a', "expected same string, got %s\n", buff
);
1664 /* flags needs to have FDTF_NOAUTOREADINGORDER for these tests to succeed on Vista+ */
1666 /* all combinations documented as invalid succeeded */
1667 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTTIME
| FDTF_LONGTIME
;
1668 SetLastError(0xdeadbeef);
1669 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1670 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1671 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1673 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTDATE
| FDTF_LONGDATE
;
1674 SetLastError(0xdeadbeef);
1675 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1676 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1677 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1679 flags
= FDTF_SHORTDATE
| FDTF_LTRDATE
| FDTF_RTLDATE
;
1680 SetLastError(0xdeadbeef);
1681 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1682 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1683 ok(GetLastError() == 0xdeadbeef ||
1684 broken(GetLastError() == ERROR_INVALID_FLAGS
), /* Win9x/WinMe */
1685 "expected 0xdeadbeef, got %d\n", GetLastError());
1687 /* now check returned strings */
1688 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTTIME
;
1689 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1690 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1691 ret
= GetTimeFormat(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff2
, sizeof(buff2
));
1692 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1693 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1695 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGTIME
;
1696 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1697 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1698 ret
= GetTimeFormat(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff2
, sizeof(buff2
));
1699 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1700 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1702 /* both time flags */
1703 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGTIME
| FDTF_SHORTTIME
;
1704 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1705 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1706 ret
= GetTimeFormat(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff2
, sizeof(buff2
));
1707 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1708 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1710 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTDATE
;
1711 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1712 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1713 ret
= GetDateFormat(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1714 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1715 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1717 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGDATE
;
1718 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1719 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1720 ret
= GetDateFormat(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1721 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1722 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1724 /* both date flags */
1725 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGDATE
| FDTF_SHORTDATE
;
1726 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1727 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1728 ret
= GetDateFormat(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1729 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1730 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1732 /* various combinations of date/time flags */
1733 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGDATE
| FDTF_SHORTTIME
;
1734 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1735 ok(ret
== lstrlenA(buff
)+1, "got %d, length %d\n", ret
, lstrlenA(buff
)+1);
1736 ret
= GetTimeFormat(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff3
, sizeof(buff3
));
1737 ok(ret
== lstrlenA(buff3
)+1, "got %d\n", ret
);
1738 ok(lstrcmpA(buff3
, buff
+ lstrlenA(buff
) - lstrlenA(buff3
)) == 0,
1739 "expected (%s), got (%s) for time part\n",
1740 buff3
, buff
+ lstrlenA(buff
) - lstrlenA(buff3
));
1741 ret
= GetDateFormat(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1742 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1743 buff
[lstrlenA(buff2
)] = '\0';
1744 ok(lstrcmpA(buff2
, buff
) == 0, "expected (%s) got (%s) for date part\n",
1747 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGDATE
| FDTF_LONGTIME
;
1748 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1749 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1750 ret
= GetTimeFormat(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff3
, sizeof(buff3
));
1751 ok(ret
== lstrlenA(buff3
)+1, "got %d\n", ret
);
1752 ok(lstrcmpA(buff3
, buff
+ lstrlenA(buff
) - lstrlenA(buff3
)) == 0,
1753 "expected (%s), got (%s) for time part\n",
1754 buff3
, buff
+ lstrlenA(buff
) - lstrlenA(buff3
));
1755 ret
= GetDateFormat(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1756 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1757 buff
[lstrlenA(buff2
)] = '\0';
1758 ok(lstrcmpA(buff2
, buff
) == 0, "expected (%s) got (%s) for date part\n",
1761 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTDATE
| FDTF_SHORTTIME
;
1762 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1763 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1764 ret
= GetDateFormat(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1765 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1767 ret
= GetTimeFormat(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff3
, sizeof(buff3
));
1768 ok(ret
== lstrlenA(buff3
)+1, "got %d\n", ret
);
1769 strcat(buff2
, buff3
);
1770 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1772 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTDATE
| FDTF_LONGTIME
;
1773 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1774 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1775 ret
= GetDateFormat(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1776 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1778 ret
= GetTimeFormat(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff3
, sizeof(buff3
));
1779 ok(ret
== lstrlenA(buff3
)+1, "got %d\n", ret
);
1780 strcat(buff2
, buff3
);
1781 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1784 static void test_SHFormatDateTimeW(void)
1786 FILETIME UNALIGNED filetime
;
1787 WCHAR buff
[100], buff2
[100], buff3
[100], *p1
, *p2
;
1791 static const WCHAR spaceW
[] = {' ',0};
1792 #define UNICODE_LTR_MARK 0x200e
1794 if(!pSHFormatDateTimeW
)
1796 win_skip("pSHFormatDateTimeW isn't available\n");
1802 /* crashes on native */
1803 pSHFormatDateTimeW(NULL
, NULL
, NULL
, 0);
1807 SystemTimeToFileTime(&st
, &filetime
);
1808 /* SHFormatDateTime expects input as utc */
1809 LocalFileTimeToFileTime(&filetime
, &filetime
);
1811 /* no way to get required buffer length here */
1812 SetLastError(0xdeadbeef);
1813 ret
= pSHFormatDateTimeW(&filetime
, NULL
, NULL
, 0);
1814 ok(ret
== 0, "expected 0, got %d\n", ret
);
1815 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1817 SetLastError(0xdeadbeef);
1818 buff
[0] = 'a'; buff
[1] = 0;
1819 ret
= pSHFormatDateTimeW(&filetime
, NULL
, buff
, 0);
1820 ok(ret
== 0, "expected 0, got %d\n", ret
);
1821 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1822 ok(buff
[0] == 'a', "expected same string\n");
1824 /* all combinations documented as invalid succeeded */
1825 flags
= FDTF_SHORTTIME
| FDTF_LONGTIME
;
1826 SetLastError(0xdeadbeef);
1827 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1828 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1829 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1830 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1832 flags
= FDTF_SHORTDATE
| FDTF_LONGDATE
;
1833 SetLastError(0xdeadbeef);
1834 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1835 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1836 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1837 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1839 flags
= FDTF_SHORTDATE
| FDTF_LTRDATE
| FDTF_RTLDATE
;
1840 SetLastError(0xdeadbeef);
1841 buff
[0] = 0; /* NT4 doesn't clear the buffer on failure */
1842 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1843 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1844 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1845 ok(GetLastError() == 0xdeadbeef ||
1846 broken(GetLastError() == ERROR_INVALID_FLAGS
), /* Win9x/WinMe/NT4 */
1847 "expected 0xdeadbeef, got %d\n", GetLastError());
1849 /* now check returned strings */
1850 flags
= FDTF_SHORTTIME
;
1851 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1852 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1853 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1854 SetLastError(0xdeadbeef);
1855 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1856 if (ret
== 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
1858 win_skip("Needed W-functions are not implemented\n");
1861 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1862 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1864 flags
= FDTF_LONGTIME
;
1865 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1866 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1867 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1868 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1869 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1870 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1872 /* both time flags */
1873 flags
= FDTF_LONGTIME
| FDTF_SHORTTIME
;
1874 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1875 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1876 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1877 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1878 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1879 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal string\n");
1881 flags
= FDTF_SHORTDATE
;
1882 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1883 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1884 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1885 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1886 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1887 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1889 flags
= FDTF_LONGDATE
;
1890 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1891 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1892 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1893 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1894 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1895 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1897 /* both date flags */
1898 flags
= FDTF_LONGDATE
| FDTF_SHORTDATE
;
1899 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1900 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1901 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1902 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1903 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1904 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1906 /* various combinations of date/time flags */
1907 flags
= FDTF_LONGDATE
| FDTF_SHORTTIME
;
1908 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1909 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1910 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1911 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff3
, sizeof(buff3
)/sizeof(WCHAR
));
1912 ok(ret
== lstrlenW(buff3
)+1, "expected %d, got %d\n", lstrlenW(buff3
)+1, ret
);
1913 ok(lstrcmpW(buff3
, buff
+ lstrlenW(buff
) - lstrlenW(buff3
)) == 0,
1914 "expected (%s), got (%s) for time part\n",
1915 wine_dbgstr_w(buff3
), wine_dbgstr_w(buff
+ lstrlenW(buff
) - lstrlenW(buff3
)));
1916 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1917 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1922 while (*p1
== UNICODE_LTR_MARK
)
1924 while (*p2
== UNICODE_LTR_MARK
)
1930 ok(lstrcmpW(buff2
, buff
) == 0, "expected (%s) got (%s) for date part\n",
1931 wine_dbgstr_w(buff2
), wine_dbgstr_w(buff
));
1933 flags
= FDTF_LONGDATE
| FDTF_LONGTIME
;
1934 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1935 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1936 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1937 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff3
, sizeof(buff3
)/sizeof(WCHAR
));
1938 ok(ret
== lstrlenW(buff3
)+1, "expected %d, got %d\n", lstrlenW(buff3
)+1, ret
);
1939 ok(lstrcmpW(buff3
, buff
+ lstrlenW(buff
) - lstrlenW(buff3
)) == 0,
1940 "expected (%s), got (%s) for time part\n",
1941 wine_dbgstr_w(buff3
), wine_dbgstr_w(buff
+ lstrlenW(buff
) - lstrlenW(buff3
)));
1942 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1943 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1948 while (*p1
== UNICODE_LTR_MARK
)
1950 while (*p2
== UNICODE_LTR_MARK
)
1956 ok(lstrcmpW(buff2
, buff
) == 0, "expected (%s) got (%s) for date part\n",
1957 wine_dbgstr_w(buff2
), wine_dbgstr_w(buff
));
1959 flags
= FDTF_SHORTDATE
| FDTF_SHORTTIME
;
1960 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1961 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1962 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1963 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1964 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1965 lstrcatW(buff2
, spaceW
);
1966 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff3
, sizeof(buff3
)/sizeof(WCHAR
));
1967 ok(ret
== lstrlenW(buff3
)+1, "expected %d, got %d\n", lstrlenW(buff3
)+1, ret
);
1968 lstrcatW(buff2
, buff3
);
1969 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1971 flags
= FDTF_SHORTDATE
| FDTF_LONGTIME
;
1972 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1973 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1974 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1975 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1976 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1977 lstrcatW(buff2
, spaceW
);
1978 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff3
, sizeof(buff3
)/sizeof(WCHAR
));
1979 ok(ret
== lstrlenW(buff3
)+1, "expected %d, got %d\n", lstrlenW(buff3
)+1, ret
);
1980 lstrcatW(buff2
, buff3
);
1981 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1984 static void test_SHGetObjectCompatFlags(void)
1986 struct compat_value
{
1991 struct compat_value values
[] = {
1992 { "OTNEEDSSFCACHE", 0x1 },
1993 { "NO_WEBVIEW", 0x2 },
1994 { "UNBINDABLE", 0x4 },
1996 { "NEEDSFILESYSANCESTOR", 0x10 },
1997 { "NOTAFILESYSTEM", 0x20 },
1998 { "CTXMENU_NOVERBS", 0x40 },
1999 { "CTXMENU_LIMITEDQI", 0x80 },
2000 { "COCREATESHELLFOLDERONLY", 0x100 },
2001 { "NEEDSSTORAGEANCESTOR", 0x200 },
2002 { "NOLEGACYWEBVIEW", 0x400 },
2003 { "CTXMENU_XPQCMFLAGS", 0x1000 },
2004 { "NOIPROPERTYSTORE", 0x2000 }
2007 static const char compat_path
[] = "Software\\Microsoft\\Windows\\CurrentVersion\\ShellCompatibility\\Objects";
2008 void *pColorAdjustLuma
= GetProcAddress(hShlwapi
, "ColorAdjustLuma");
2009 CHAR keyA
[39]; /* {CLSID} */
2014 if (!pSHGetObjectCompatFlags
)
2016 win_skip("SHGetObjectCompatFlags isn't available\n");
2020 if (pColorAdjustLuma
&& pColorAdjustLuma
== pSHGetObjectCompatFlags
) /* win2k */
2022 win_skip("Skipping SHGetObjectCompatFlags, same ordinal used for ColorAdjustLuma\n");
2027 ret
= pSHGetObjectCompatFlags(NULL
, NULL
);
2028 ok(ret
== 0, "got %d\n", ret
);
2030 ret
= RegOpenKeyA(HKEY_LOCAL_MACHINE
, compat_path
, &root
);
2031 if (ret
!= ERROR_SUCCESS
)
2033 skip("No compatibility class data found\n");
2037 for (i
= 0; RegEnumKeyA(root
, i
, keyA
, sizeof(keyA
)) == ERROR_SUCCESS
; i
++)
2041 if (RegOpenKeyA(root
, keyA
, &clsid_key
) == ERROR_SUCCESS
)
2044 DWORD expected
= 0, got
, length
= sizeof(valueA
);
2048 for (v
= 0; RegEnumValueA(clsid_key
, v
, valueA
, &length
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
; v
++)
2052 for (j
= 0; j
< sizeof(values
)/sizeof(struct compat_value
); j
++)
2053 if (lstrcmpA(values
[j
].nameA
, valueA
) == 0)
2055 expected
|= values
[j
].value
;
2059 length
= sizeof(valueA
);
2062 pGUIDFromStringA(keyA
, &clsid
);
2063 got
= pSHGetObjectCompatFlags(NULL
, &clsid
);
2064 ok(got
== expected
, "got 0x%08x, expected 0x%08x. Key %s\n", got
, expected
, keyA
);
2066 RegCloseKey(clsid_key
);
2074 IOleCommandTarget IOleCommandTarget_iface
;
2076 } IOleCommandTargetImpl
;
2078 static inline IOleCommandTargetImpl
*impl_from_IOleCommandTarget(IOleCommandTarget
*iface
)
2080 return CONTAINING_RECORD(iface
, IOleCommandTargetImpl
, IOleCommandTarget_iface
);
2083 static const IOleCommandTargetVtbl IOleCommandTargetImpl_Vtbl
;
2085 static IOleCommandTarget
* IOleCommandTargetImpl_Construct(void)
2087 IOleCommandTargetImpl
*obj
;
2089 obj
= HeapAlloc(GetProcessHeap(), 0, sizeof(*obj
));
2090 obj
->IOleCommandTarget_iface
.lpVtbl
= &IOleCommandTargetImpl_Vtbl
;
2093 return &obj
->IOleCommandTarget_iface
;
2096 static HRESULT WINAPI
IOleCommandTargetImpl_QueryInterface(IOleCommandTarget
*iface
, REFIID riid
, void **ppvObj
)
2098 IOleCommandTargetImpl
*This
= impl_from_IOleCommandTarget(iface
);
2100 if (IsEqualIID(riid
, &IID_IUnknown
) ||
2101 IsEqualIID(riid
, &IID_IOleCommandTarget
))
2108 IUnknown_AddRef(iface
);
2112 return E_NOINTERFACE
;
2115 static ULONG WINAPI
IOleCommandTargetImpl_AddRef(IOleCommandTarget
*iface
)
2117 IOleCommandTargetImpl
*This
= impl_from_IOleCommandTarget(iface
);
2118 return InterlockedIncrement(&This
->ref
);
2121 static ULONG WINAPI
IOleCommandTargetImpl_Release(IOleCommandTarget
*iface
)
2123 IOleCommandTargetImpl
*This
= impl_from_IOleCommandTarget(iface
);
2124 ULONG ref
= InterlockedDecrement(&This
->ref
);
2128 HeapFree(GetProcessHeap(), 0, This
);
2134 static HRESULT WINAPI
IOleCommandTargetImpl_QueryStatus(
2135 IOleCommandTarget
*iface
, const GUID
*group
, ULONG cCmds
, OLECMD prgCmds
[], OLECMDTEXT
*pCmdText
)
2140 static HRESULT WINAPI
IOleCommandTargetImpl_Exec(
2141 IOleCommandTarget
*iface
,
2142 const GUID
*CmdGroup
,
2148 add_call(&trace_got
, 3, CmdGroup
, (void*)(DWORD_PTR
)nCmdID
, (void*)(DWORD_PTR
)nCmdexecopt
, pvaIn
, pvaOut
);
2152 static const IOleCommandTargetVtbl IOleCommandTargetImpl_Vtbl
=
2154 IOleCommandTargetImpl_QueryInterface
,
2155 IOleCommandTargetImpl_AddRef
,
2156 IOleCommandTargetImpl_Release
,
2157 IOleCommandTargetImpl_QueryStatus
,
2158 IOleCommandTargetImpl_Exec
2162 IServiceProvider IServiceProvider_iface
;
2164 } IServiceProviderImpl
;
2166 static inline IServiceProviderImpl
*impl_from_IServiceProvider(IServiceProvider
*iface
)
2168 return CONTAINING_RECORD(iface
, IServiceProviderImpl
, IServiceProvider_iface
);
2172 IProfferService IProfferService_iface
;
2174 } IProfferServiceImpl
;
2176 static inline IProfferServiceImpl
*impl_from_IProfferService(IProfferService
*iface
)
2178 return CONTAINING_RECORD(iface
, IProfferServiceImpl
, IProfferService_iface
);
2182 static const IServiceProviderVtbl IServiceProviderImpl_Vtbl
;
2183 static const IProfferServiceVtbl IProfferServiceImpl_Vtbl
;
2185 static IServiceProvider
* IServiceProviderImpl_Construct(void)
2187 IServiceProviderImpl
*obj
;
2189 obj
= HeapAlloc(GetProcessHeap(), 0, sizeof(*obj
));
2190 obj
->IServiceProvider_iface
.lpVtbl
= &IServiceProviderImpl_Vtbl
;
2193 return &obj
->IServiceProvider_iface
;
2196 static IProfferService
* IProfferServiceImpl_Construct(void)
2198 IProfferServiceImpl
*obj
;
2200 obj
= HeapAlloc(GetProcessHeap(), 0, sizeof(*obj
));
2201 obj
->IProfferService_iface
.lpVtbl
= &IProfferServiceImpl_Vtbl
;
2204 return &obj
->IProfferService_iface
;
2207 static HRESULT WINAPI
IServiceProviderImpl_QueryInterface(IServiceProvider
*iface
, REFIID riid
, void **ppvObj
)
2209 IServiceProviderImpl
*This
= impl_from_IServiceProvider(iface
);
2211 if (IsEqualIID(riid
, &IID_IUnknown
) ||
2212 IsEqualIID(riid
, &IID_IServiceProvider
))
2219 IUnknown_AddRef(iface
);
2220 /* native uses redefined IID_IServiceProvider symbol, so we can't compare pointers */
2221 if (IsEqualIID(riid
, &IID_IServiceProvider
))
2222 add_call(&trace_got
, 1, iface
, &IID_IServiceProvider
, 0, 0, 0);
2226 return E_NOINTERFACE
;
2229 static ULONG WINAPI
IServiceProviderImpl_AddRef(IServiceProvider
*iface
)
2231 IServiceProviderImpl
*This
= impl_from_IServiceProvider(iface
);
2232 return InterlockedIncrement(&This
->ref
);
2235 static ULONG WINAPI
IServiceProviderImpl_Release(IServiceProvider
*iface
)
2237 IServiceProviderImpl
*This
= impl_from_IServiceProvider(iface
);
2238 ULONG ref
= InterlockedDecrement(&This
->ref
);
2242 HeapFree(GetProcessHeap(), 0, This
);
2248 static HRESULT WINAPI
IServiceProviderImpl_QueryService(
2249 IServiceProvider
*iface
, REFGUID service
, REFIID riid
, void **ppv
)
2251 /* native uses redefined pointer for IID_IOleCommandTarget, not one from uuid.lib */
2252 if (IsEqualIID(riid
, &IID_IOleCommandTarget
))
2254 add_call(&trace_got
, 2, iface
, service
, &IID_IOleCommandTarget
, 0, 0);
2255 *ppv
= IOleCommandTargetImpl_Construct();
2257 if (IsEqualIID(riid
, &IID_IProfferService
))
2259 if (IsEqualIID(service
, &IID_IProfferService
))
2260 add_call(&trace_got
, 2, &IID_IProfferService
, &IID_IProfferService
, 0, 0, 0);
2261 *ppv
= IProfferServiceImpl_Construct();
2266 static const IServiceProviderVtbl IServiceProviderImpl_Vtbl
=
2268 IServiceProviderImpl_QueryInterface
,
2269 IServiceProviderImpl_AddRef
,
2270 IServiceProviderImpl_Release
,
2271 IServiceProviderImpl_QueryService
2274 static void test_IUnknown_QueryServiceExec(void)
2276 IServiceProvider
*provider
= IServiceProviderImpl_Construct();
2277 static const GUID dummy_serviceid
= { 0xdeadbeef };
2278 static const GUID dummy_groupid
= { 0xbeefbeef };
2279 call_trace_t trace_expected
;
2282 /* on <=W2K platforms same ordinal used for another export with different
2283 prototype, so skipping using this indirect condition */
2284 if (is_win2k_and_lower
)
2286 win_skip("IUnknown_QueryServiceExec is not available\n");
2290 /* null source pointer */
2291 hr
= pIUnknown_QueryServiceExec(NULL
, &dummy_serviceid
, &dummy_groupid
, 0, 0, 0, 0);
2292 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
2295 IUnknown_QueryServiceExec( ptr1, serviceid, groupid, arg1, arg2, arg3, arg4);
2296 -> IUnknown_QueryInterface( ptr1, &IID_IServiceProvider, &prov );
2297 -> IServiceProvider_QueryService( prov, serviceid, &IID_IOleCommandTarget, &obj );
2298 -> IOleCommandTarget_Exec( obj, groupid, arg1, arg2, arg3, arg4 );
2300 init_call_trace(&trace_expected
);
2302 add_call(&trace_expected
, 1, provider
, &IID_IServiceProvider
, 0, 0, 0);
2303 add_call(&trace_expected
, 2, provider
, &dummy_serviceid
, &IID_IOleCommandTarget
, 0, 0);
2304 add_call(&trace_expected
, 3, &dummy_groupid
, (void*)0x1, (void*)0x2, (void*)0x3, (void*)0x4);
2306 init_call_trace(&trace_got
);
2307 hr
= pIUnknown_QueryServiceExec((IUnknown
*)provider
, &dummy_serviceid
, &dummy_groupid
, 0x1, 0x2, (void*)0x3, (void*)0x4);
2308 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2310 ok_trace(&trace_expected
, &trace_got
);
2312 free_call_trace(&trace_expected
);
2313 free_call_trace(&trace_got
);
2315 IServiceProvider_Release(provider
);
2319 static HRESULT WINAPI
IProfferServiceImpl_QueryInterface(IProfferService
*iface
, REFIID riid
, void **ppvObj
)
2321 IProfferServiceImpl
*This
= impl_from_IProfferService(iface
);
2323 if (IsEqualIID(riid
, &IID_IUnknown
) ||
2324 IsEqualIID(riid
, &IID_IProfferService
))
2328 else if (IsEqualIID(riid
, &IID_IServiceProvider
))
2330 *ppvObj
= IServiceProviderImpl_Construct();
2331 add_call(&trace_got
, 1, iface
, &IID_IServiceProvider
, 0, 0, 0);
2337 IUnknown_AddRef(iface
);
2341 return E_NOINTERFACE
;
2344 static ULONG WINAPI
IProfferServiceImpl_AddRef(IProfferService
*iface
)
2346 IProfferServiceImpl
*This
= impl_from_IProfferService(iface
);
2347 return InterlockedIncrement(&This
->ref
);
2350 static ULONG WINAPI
IProfferServiceImpl_Release(IProfferService
*iface
)
2352 IProfferServiceImpl
*This
= impl_from_IProfferService(iface
);
2353 ULONG ref
= InterlockedDecrement(&This
->ref
);
2357 HeapFree(GetProcessHeap(), 0, This
);
2363 static HRESULT WINAPI
IProfferServiceImpl_ProfferService(IProfferService
*iface
,
2364 REFGUID service
, IServiceProvider
*pService
, DWORD
*pCookie
)
2366 *pCookie
= 0xdeadbeef;
2367 add_call(&trace_got
, 3, service
, pService
, pCookie
, 0, 0);
2371 static HRESULT WINAPI
IProfferServiceImpl_RevokeService(IProfferService
*iface
, DWORD cookie
)
2373 add_call(&trace_got
, 4, (void*)(DWORD_PTR
)cookie
, 0, 0, 0, 0);
2377 static const IProfferServiceVtbl IProfferServiceImpl_Vtbl
=
2379 IProfferServiceImpl_QueryInterface
,
2380 IProfferServiceImpl_AddRef
,
2381 IProfferServiceImpl_Release
,
2382 IProfferServiceImpl_ProfferService
,
2383 IProfferServiceImpl_RevokeService
2386 static void test_IUnknown_ProfferService(void)
2388 IServiceProvider
*provider
= IServiceProviderImpl_Construct();
2389 IProfferService
*proff
= IProfferServiceImpl_Construct();
2390 static const GUID dummy_serviceid
= { 0xdeadbeef };
2391 call_trace_t trace_expected
;
2395 /* on <=W2K platforms same ordinal used for another export with different
2396 prototype, so skipping using this indirect condition */
2397 if (is_win2k_and_lower
)
2399 win_skip("IUnknown_ProfferService is not available\n");
2403 /* null source pointer */
2404 hr
= pIUnknown_ProfferService(NULL
, &dummy_serviceid
, 0, 0);
2405 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
2408 IUnknown_ProfferService( ptr1, serviceid, arg1, arg2);
2409 -> IUnknown_QueryInterface( ptr1, &IID_IServiceProvider, &provider );
2410 -> IServiceProvider_QueryService( provider, &IID_IProfferService, &IID_IProfferService, &proffer );
2412 if (service pointer not null):
2413 -> IProfferService_ProfferService( proffer, serviceid, arg1, arg2 );
2415 -> IProfferService_RevokeService( proffer, *arg2 );
2417 init_call_trace(&trace_expected
);
2419 add_call(&trace_expected
, 1, proff
, &IID_IServiceProvider
, 0, 0, 0);
2420 add_call(&trace_expected
, 2, &IID_IProfferService
, &IID_IProfferService
, 0, 0, 0);
2421 add_call(&trace_expected
, 3, &dummy_serviceid
, provider
, &cookie
, 0, 0);
2423 init_call_trace(&trace_got
);
2425 hr
= pIUnknown_ProfferService((IUnknown
*)proff
, &dummy_serviceid
, provider
, &cookie
);
2426 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2427 ok(cookie
== 0xdeadbeef, "got %x\n", cookie
);
2429 ok_trace(&trace_expected
, &trace_got
);
2430 free_call_trace(&trace_got
);
2431 free_call_trace(&trace_expected
);
2433 /* same with ::Revoke path */
2434 init_call_trace(&trace_expected
);
2436 add_call(&trace_expected
, 1, proff
, &IID_IServiceProvider
, 0, 0, 0);
2437 add_call(&trace_expected
, 2, &IID_IProfferService
, &IID_IProfferService
, 0, 0, 0);
2438 add_call(&trace_expected
, 4, (void*)(DWORD_PTR
)cookie
, 0, 0, 0, 0);
2440 init_call_trace(&trace_got
);
2441 ok(cookie
!= 0, "got %x\n", cookie
);
2442 hr
= pIUnknown_ProfferService((IUnknown
*)proff
, &dummy_serviceid
, 0, &cookie
);
2443 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2444 ok(cookie
== 0, "got %x\n", cookie
);
2445 ok_trace(&trace_expected
, &trace_got
);
2446 free_call_trace(&trace_got
);
2447 free_call_trace(&trace_expected
);
2449 IServiceProvider_Release(provider
);
2450 IProfferService_Release(proff
);
2453 static void test_SHCreateWorkerWindowA(void)
2461 if (is_win2k_and_lower
)
2463 win_skip("SHCreateWorkerWindowA not available\n");
2467 hwnd
= pSHCreateWorkerWindowA(0, NULL
, 0, 0, 0, 0);
2468 ok(hwnd
!= 0, "expected window\n");
2470 GetClassName(hwnd
, classA
, 20);
2471 ok(lstrcmpA(classA
, "WorkerA") == 0, "expected WorkerA class, got %s\n", classA
);
2473 ret
= GetWindowLongPtrA(hwnd
, 0);
2474 ok(ret
== 0, "got %ld\n", ret
);
2477 memset(&cliA
, 0, sizeof(cliA
));
2478 res
= GetClassInfoA(GetModuleHandle("shlwapi.dll"), "WorkerA", &cliA
);
2479 ok(res
, "failed to get class info\n");
2480 ok(cliA
.style
== 0, "got 0x%08x\n", cliA
.style
);
2481 ok(cliA
.cbClsExtra
== 0, "got %d\n", cliA
.cbClsExtra
);
2482 ok(cliA
.cbWndExtra
== sizeof(LONG_PTR
), "got %d\n", cliA
.cbWndExtra
);
2483 ok(cliA
.lpszMenuName
== 0, "got %s\n", cliA
.lpszMenuName
);
2485 DestroyWindow(hwnd
);
2487 /* set extra bytes */
2488 hwnd
= pSHCreateWorkerWindowA(0, NULL
, 0, 0, 0, 0xdeadbeef);
2489 ok(hwnd
!= 0, "expected window\n");
2491 GetClassName(hwnd
, classA
, 20);
2492 ok(lstrcmpA(classA
, "WorkerA") == 0, "expected WorkerA class, got %s\n", classA
);
2494 ret
= GetWindowLongPtrA(hwnd
, 0);
2495 ok(ret
== 0xdeadbeef, "got %ld\n", ret
);
2498 ret
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
2499 ok(ret
== WS_EX_WINDOWEDGE
||
2500 ret
== (WS_EX_WINDOWEDGE
|WS_EX_LAYOUTRTL
) /* systems with RTL locale */, "0x%08lx\n", ret
);
2502 DestroyWindow(hwnd
);
2504 hwnd
= pSHCreateWorkerWindowA(0, NULL
, WS_EX_TOOLWINDOW
, 0, 0, 0);
2505 ret
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
2506 ok(ret
== (WS_EX_WINDOWEDGE
|WS_EX_TOOLWINDOW
) ||
2507 ret
== (WS_EX_WINDOWEDGE
|WS_EX_TOOLWINDOW
|WS_EX_LAYOUTRTL
) /* systems with RTL locale */, "0x%08lx\n", ret
);
2508 DestroyWindow(hwnd
);
2511 static HRESULT WINAPI
SF_QueryInterface(IShellFolder
*iface
,
2512 REFIID riid
, void **ppv
)
2514 /* SHIShellFolder_EnumObjects doesn't QI the object for IShellFolder */
2515 ok(!IsEqualGUID(&IID_IShellFolder
, riid
),
2516 "Unexpected QI for IShellFolder\n");
2517 return E_NOINTERFACE
;
2520 static ULONG WINAPI
SF_AddRef(IShellFolder
*iface
)
2525 static ULONG WINAPI
SF_Release(IShellFolder
*iface
)
2530 static HRESULT WINAPI
SF_ParseDisplayName(IShellFolder
*iface
,
2531 HWND owner
, LPBC reserved
, LPOLESTR displayName
, ULONG
*eaten
,
2532 LPITEMIDLIST
*idl
, ULONG
*attr
)
2534 ok(0, "Didn't expect ParseDisplayName\n");
2538 static HRESULT WINAPI
SF_EnumObjects(IShellFolder
*iface
,
2539 HWND owner
, SHCONTF flags
, IEnumIDList
**enm
)
2541 *enm
= (IEnumIDList
*)0xcafebabe;
2545 static HRESULT WINAPI
SF_BindToObject(IShellFolder
*iface
,
2546 LPCITEMIDLIST idl
, LPBC reserved
, REFIID riid
, void **obj
)
2548 ok(0, "Didn't expect BindToObject\n");
2552 static HRESULT WINAPI
SF_BindToStorage(IShellFolder
*iface
,
2553 LPCITEMIDLIST idl
, LPBC reserved
, REFIID riid
, void **obj
)
2555 ok(0, "Didn't expect BindToStorage\n");
2559 static HRESULT WINAPI
SF_CompareIDs(IShellFolder
*iface
,
2560 LPARAM lparam
, LPCITEMIDLIST idl1
, LPCITEMIDLIST idl2
)
2562 ok(0, "Didn't expect CompareIDs\n");
2566 static HRESULT WINAPI
SF_CreateViewObject(IShellFolder
*iface
,
2567 HWND owner
, REFIID riid
, void **out
)
2569 ok(0, "Didn't expect CreateViewObject\n");
2573 static HRESULT WINAPI
SF_GetAttributesOf(IShellFolder
*iface
,
2574 UINT cidl
, LPCITEMIDLIST
*idl
, SFGAOF
*inOut
)
2576 ok(0, "Didn't expect GetAttributesOf\n");
2580 static HRESULT WINAPI
SF_GetUIObjectOf(IShellFolder
*iface
,
2581 HWND owner
, UINT cidl
, LPCITEMIDLIST
*idls
, REFIID riid
, UINT
*inOut
,
2584 ok(0, "Didn't expect GetUIObjectOf\n");
2588 static HRESULT WINAPI
SF_GetDisplayNameOf(IShellFolder
*iface
,
2589 LPCITEMIDLIST idl
, SHGDNF flags
, STRRET
*name
)
2591 ok(0, "Didn't expect GetDisplayNameOf\n");
2595 static HRESULT WINAPI
SF_SetNameOf(IShellFolder
*iface
,
2596 HWND hwnd
, LPCITEMIDLIST idl
, LPCOLESTR name
, SHGDNF flags
,
2597 LPITEMIDLIST
*idlOut
)
2599 ok(0, "Didn't expect SetNameOf\n");
2603 static IShellFolderVtbl ShellFolderVtbl
= {
2607 SF_ParseDisplayName
,
2612 SF_CreateViewObject
,
2615 SF_GetDisplayNameOf
,
2619 static IShellFolder ShellFolder
= { &ShellFolderVtbl
};
2621 static void test_SHIShellFolder_EnumObjects(void)
2625 IShellFolder
*folder
;
2627 if(!pSHIShellFolder_EnumObjects
|| is_win2k_and_lower
){
2628 win_skip("SHIShellFolder_EnumObjects not available\n");
2633 /* NULL object crashes on Windows */
2634 pSHIShellFolder_EnumObjects(NULL
, NULL
, 0, NULL
);
2637 /* SHIShellFolder_EnumObjects doesn't QI the object for IShellFolder */
2638 enm
= (IEnumIDList
*)0xdeadbeef;
2639 hres
= pSHIShellFolder_EnumObjects(&ShellFolder
, NULL
, 0, &enm
);
2640 ok(hres
== S_OK
, "SHIShellFolder_EnumObjects failed: 0x%08x\n", hres
);
2641 ok(enm
== (IEnumIDList
*)0xcafebabe, "Didn't get expected enumerator location, instead: %p\n", enm
);
2643 /* SHIShellFolder_EnumObjects isn't strict about the IShellFolder object */
2644 hres
= pSHGetDesktopFolder(&folder
);
2645 ok(hres
== S_OK
, "SHGetDesktopFolder failed: 0x%08x\n", hres
);
2648 hres
= pSHIShellFolder_EnumObjects(folder
, NULL
, 0, &enm
);
2649 ok(hres
== S_OK
, "SHIShellFolder_EnumObjects failed: 0x%08x\n", hres
);
2650 ok(enm
!= NULL
, "Didn't get an enumerator\n");
2652 IEnumIDList_Release(enm
);
2654 IShellFolder_Release(folder
);
2657 static void write_inifile(LPCWSTR filename
)
2662 static const char data
[] =
2665 "AnotherKey=asdf\r\n";
2667 file
= CreateFileW(filename
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
2668 if(file
== INVALID_HANDLE_VALUE
)
2671 WriteFile(file
, data
, sizeof(data
), &written
, NULL
);
2676 #define verify_inifile(f, e) r_verify_inifile(__LINE__, f, e)
2677 static void r_verify_inifile(unsigned l
, LPCWSTR filename
, LPCSTR exp
)
2683 file
= CreateFileW(filename
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, 0, NULL
);
2684 if(file
== INVALID_HANDLE_VALUE
)
2687 ReadFile(file
, buf
, sizeof(buf
) * sizeof(CHAR
), &read
, NULL
);
2692 ok_(__FILE__
,l
)(!strcmp(buf
, exp
), "Expected:\n%s\nGot:\n%s\n", exp
,
2696 static void test_SHGetIniString(void)
2699 WCHAR out
[64] = {0};
2701 static const WCHAR TestAppW
[] = {'T','e','s','t','A','p','p',0};
2702 static const WCHAR TestIniW
[] = {'C',':','\\','t','e','s','t','.','i','n','i',0};
2703 static const WCHAR AKeyW
[] = {'A','K','e','y',0};
2704 static const WCHAR AnotherKeyW
[] = {'A','n','o','t','h','e','r','K','e','y',0};
2705 static const WCHAR JunkKeyW
[] = {'J','u','n','k','K','e','y',0};
2707 if(!pSHGetIniStringW
|| is_win2k_and_lower
){
2708 win_skip("SHGetIniStringW is not available\n");
2712 write_inifile(TestIniW
);
2715 /* these crash on Windows */
2716 pSHGetIniStringW(NULL
, NULL
, NULL
, 0, NULL
);
2717 pSHGetIniStringW(NULL
, AKeyW
, out
, sizeof(out
), TestIniW
);
2718 pSHGetIniStringW(TestAppW
, AKeyW
, NULL
, sizeof(out
), TestIniW
);
2721 ret
= pSHGetIniStringW(TestAppW
, AKeyW
, out
, 0, TestIniW
);
2722 ok(ret
== 0, "SHGetIniStringW should have given 0, instead: %d\n", ret
);
2724 /* valid arguments */
2725 ret
= pSHGetIniStringW(TestAppW
, NULL
, out
, sizeof(out
), TestIniW
);
2726 ok(broken(ret
== 0) || /* win 98 */
2727 ret
== 4, "SHGetIniStringW should have given 4, instead: %d\n", ret
);
2728 ok(!lstrcmpW(out
, AKeyW
), "Expected %s, got: %s\n",
2729 wine_dbgstr_w(AKeyW
), wine_dbgstr_w(out
));
2731 ret
= pSHGetIniStringW(TestAppW
, AKeyW
, out
, sizeof(out
), TestIniW
);
2732 ok(broken(ret
== 0) || /* win 98 */
2733 ret
== 1, "SHGetIniStringW should have given 1, instead: %d\n", ret
);
2734 ok(broken(*out
== 0) || /*win 98 */
2735 !strcmp_wa(out
, "1"), "Expected L\"1\", got: %s\n", wine_dbgstr_w(out
));
2737 ret
= pSHGetIniStringW(TestAppW
, AnotherKeyW
, out
, sizeof(out
), TestIniW
);
2738 ok(broken(ret
== 0) || /* win 98 */
2739 ret
== 4, "SHGetIniStringW should have given 4, instead: %d\n", ret
);
2740 ok(broken(*out
== 0) || /* win 98 */
2741 !strcmp_wa(out
, "asdf"), "Expected L\"asdf\", got: %s\n", wine_dbgstr_w(out
));
2743 ret
= pSHGetIniStringW(TestAppW
, JunkKeyW
, out
, sizeof(out
), TestIniW
);
2744 ok(ret
== 0, "SHGetIniStringW should have given 0, instead: %d\n", ret
);
2745 ok(*out
== 0, "Expected L\"\", got: %s\n", wine_dbgstr_w(out
));
2747 DeleteFileW(TestIniW
);
2750 static void test_SHSetIniString(void)
2754 static const WCHAR TestAppW
[] = {'T','e','s','t','A','p','p',0};
2755 static const WCHAR AnotherAppW
[] = {'A','n','o','t','h','e','r','A','p','p',0};
2756 static const WCHAR TestIniW
[] = {'C',':','\\','t','e','s','t','.','i','n','i',0};
2757 static const WCHAR AKeyW
[] = {'A','K','e','y',0};
2758 static const WCHAR NewKeyW
[] = {'N','e','w','K','e','y',0};
2759 static const WCHAR AValueW
[] = {'A','V','a','l','u','e',0};
2761 if(!pSHSetIniStringW
|| is_win2k_and_lower
){
2762 win_skip("SHSetIniStringW is not available\n");
2766 write_inifile(TestIniW
);
2768 ret
= pSHSetIniStringW(TestAppW
, AKeyW
, AValueW
, TestIniW
);
2769 ok(ret
== TRUE
, "SHSetIniStringW should not have failed\n");
2770 todo_wine
/* wine sticks an extra \r\n at the end of the file */
2771 verify_inifile(TestIniW
, "[TestApp]\r\nAKey=AValue\r\nAnotherKey=asdf\r\n");
2773 ret
= pSHSetIniStringW(TestAppW
, AKeyW
, NULL
, TestIniW
);
2774 ok(ret
== TRUE
, "SHSetIniStringW should not have failed\n");
2775 verify_inifile(TestIniW
, "[TestApp]\r\nAnotherKey=asdf\r\n");
2777 ret
= pSHSetIniStringW(AnotherAppW
, NewKeyW
, AValueW
, TestIniW
);
2778 ok(ret
== TRUE
, "SHSetIniStringW should not have failed\n");
2779 verify_inifile(TestIniW
, "[TestApp]\r\nAnotherKey=asdf\r\n[AnotherApp]\r\nNewKey=AValue\r\n");
2781 ret
= pSHSetIniStringW(TestAppW
, NULL
, AValueW
, TestIniW
);
2782 ok(ret
== TRUE
, "SHSetIniStringW should not have failed\n");
2783 verify_inifile(TestIniW
, "[AnotherApp]\r\nNewKey=AValue\r\n");
2785 DeleteFileW(TestIniW
);
2788 enum _shellkey_flags
{
2789 SHKEY_Root_HKCU
= 0x1,
2790 SHKEY_Root_HKLM
= 0x2,
2791 SHKEY_Key_Explorer
= 0x00,
2792 SHKEY_Key_Shell
= 0x10,
2793 SHKEY_Key_ShellNoRoam
= 0x20,
2794 SHKEY_Key_Classes
= 0x30,
2795 SHKEY_Subkey_Default
= 0x0000,
2796 SHKEY_Subkey_ResourceName
= 0x1000,
2797 SHKEY_Subkey_Handlers
= 0x2000,
2798 SHKEY_Subkey_Associations
= 0x3000,
2799 SHKEY_Subkey_Volatile
= 0x4000,
2800 SHKEY_Subkey_MUICache
= 0x5000,
2801 SHKEY_Subkey_FileExts
= 0x6000
2804 static void test_SHGetShellKey(void)
2806 static const WCHAR ShellFoldersW
[] = { 'S','h','e','l','l',' ','F','o','l','d','e','r','s',0 };
2807 static const WCHAR WineTestW
[] = { 'W','i','n','e','T','e','s','t',0 };
2809 void *pPathBuildRootW
= GetProcAddress(hShlwapi
, "PathBuildRootW");
2810 DWORD
*alloc_data
, data
, size
;
2814 if (!pSHGetShellKey
)
2816 win_skip("SHGetShellKey(ordinal 491) isn't available\n");
2821 if (pPathBuildRootW
&& pPathBuildRootW
== pSHGetShellKey
)
2823 win_skip("SHGetShellKey(ordinal 491) used for PathBuildRootW\n");
2827 if (is_win9x
|| is_win2k_and_lower
)
2829 win_skip("Ordinal 491 used for another call, skipping SHGetShellKey tests\n");
2833 /* Vista+ limits SHKEY enumeration values */
2834 SetLastError(0xdeadbeef);
2835 hkey
= pSHGetShellKey(SHKEY_Key_Explorer
, ShellFoldersW
, FALSE
);
2838 /* Tests not working on Vista+ */
2841 hkey
= pSHGetShellKey(SHKEY_Root_HKLM
|SHKEY_Key_Classes
, NULL
, FALSE
);
2842 ok(hkey
!= NULL
, "hkey = NULL\n");
2846 hkey
= pSHGetShellKey(SHKEY_Root_HKCU
|SHKEY_Key_Explorer
, ShellFoldersW
, FALSE
);
2847 ok(hkey
!= NULL
, "hkey = NULL\n");
2850 hkey
= pSHGetShellKey(SHKEY_Root_HKLM
|SHKEY_Key_Explorer
, ShellFoldersW
, FALSE
);
2851 ok(hkey
!= NULL
, "hkey = NULL\n");
2854 hkey
= pSHGetShellKey(SHKEY_Root_HKLM
, WineTestW
, FALSE
);
2855 ok(hkey
== NULL
, "hkey != NULL\n");
2857 hkey
= pSHGetShellKey(SHKEY_Root_HKLM
, NULL
, FALSE
);
2858 ok(hkey
!= NULL
, "Can't open key\n");
2859 ok(SUCCEEDED(RegDeleteKeyW(hkey
, WineTestW
)), "Can't delete key\n");
2862 hkey
= pSHGetShellKey(SHKEY_Root_HKLM
, WineTestW
, TRUE
);
2863 if (!hkey
&& GetLastError() == ERROR_ACCESS_DENIED
)
2865 skip("Not authorized to create keys\n");
2868 ok(hkey
!= NULL
, "Can't create key\n");
2871 if (!pSKGetValueW
|| !pSKSetValueW
|| !pSKDeleteValueW
|| !pSKAllocValueW
)
2873 win_skip("SKGetValueW, SKSetValueW, SKDeleteValueW or SKAllocValueW not available\n");
2877 size
= sizeof(data
);
2878 hres
= pSKGetValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
, NULL
, &data
, &size
);
2879 ok(hres
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), "hres = %x\n", hres
);
2882 hres
= pSKSetValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
, REG_DWORD
, &data
, sizeof(DWORD
));
2883 ok(hres
== S_OK
, "hres = %x\n", hres
);
2886 hres
= pSKGetValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
, NULL
, NULL
, &size
);
2887 ok(hres
== S_OK
, "hres = %x\n", hres
);
2888 ok(size
== sizeof(DWORD
), "size = %d\n", size
);
2891 hres
= pSKGetValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
, NULL
, &data
, &size
);
2892 ok(hres
== S_OK
, "hres = %x\n", hres
);
2893 ok(size
== sizeof(DWORD
), "size = %d\n", size
);
2894 ok(data
== 1234, "data = %d\n", data
);
2896 hres
= pSKAllocValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
, NULL
, (void**)&alloc_data
, &size
);
2897 ok(hres
== S_OK
, "hres= %x\n", hres
);
2898 ok(size
== sizeof(DWORD
), "size = %d\n", size
);
2899 if (SUCCEEDED(hres
))
2901 ok(*alloc_data
== 1234, "*alloc_data = %d\n", *alloc_data
);
2902 LocalFree(alloc_data
);
2905 hres
= pSKDeleteValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
);
2906 ok(hres
== S_OK
, "hres = %x\n", hres
);
2908 hres
= pSKDeleteValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
);
2909 ok(hres
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), "hres = %x\n", hres
);
2911 hres
= pSKGetValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
, NULL
, &data
, &size
);
2912 ok(hres
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), "hres = %x\n", hres
);
2914 hkey
= pSHGetShellKey(SHKEY_Root_HKLM
, NULL
, FALSE
);
2915 ok(hkey
!= NULL
, "Can't create key\n");
2916 ok(SUCCEEDED(RegDeleteKeyW(hkey
, WineTestW
)), "Can't delete key\n");
2920 static void init_pointers(void)
2922 #define MAKEFUNC(f, ord) (p##f = (void*)GetProcAddress(hShlwapi, (LPSTR)(ord)))
2923 MAKEFUNC(SHAllocShared
, 7);
2924 MAKEFUNC(SHLockShared
, 8);
2925 MAKEFUNC(SHUnlockShared
, 9);
2926 MAKEFUNC(SHFreeShared
, 10);
2927 MAKEFUNC(GetAcceptLanguagesA
, 14);
2928 MAKEFUNC(SHSetWindowBits
, 165);
2929 MAKEFUNC(SHSetParentHwnd
, 167);
2930 MAKEFUNC(ConnectToConnectionPoint
, 168);
2931 MAKEFUNC(SHSearchMapInt
, 198);
2932 MAKEFUNC(SHCreateWorkerWindowA
, 257);
2933 MAKEFUNC(GUIDFromStringA
, 269);
2934 MAKEFUNC(SHPackDispParams
, 282);
2935 MAKEFUNC(IConnectionPoint_InvokeWithCancel
, 283);
2936 MAKEFUNC(IConnectionPoint_SimpleInvoke
, 284);
2937 MAKEFUNC(SHGetIniStringW
, 294);
2938 MAKEFUNC(SHSetIniStringW
, 295);
2939 MAKEFUNC(SHFormatDateTimeA
, 353);
2940 MAKEFUNC(SHFormatDateTimeW
, 354);
2941 MAKEFUNC(SHIShellFolder_EnumObjects
, 404);
2942 MAKEFUNC(SHGetObjectCompatFlags
, 476);
2943 MAKEFUNC(IUnknown_QueryServiceExec
, 484);
2944 MAKEFUNC(SHGetShellKey
, 491);
2945 MAKEFUNC(SHPropertyBag_ReadLONG
, 496);
2946 MAKEFUNC(IUnknown_ProfferService
, 514);
2947 MAKEFUNC(SKGetValueW
, 516);
2948 MAKEFUNC(SKSetValueW
, 517);
2949 MAKEFUNC(SKDeleteValueW
, 518);
2950 MAKEFUNC(SKAllocValueW
, 519);
2954 static void test_SHSetParentHwnd(void)
2956 HWND hwnd
, hwnd2
, ret
;
2959 if (!pSHSetParentHwnd
)
2961 win_skip("SHSetParentHwnd not available\n");
2965 hwnd
= CreateWindowA("Button", "", WS_VISIBLE
, 0, 0, 10, 10, NULL
, NULL
, NULL
, NULL
);
2966 ok(hwnd
!= NULL
, "got %p\n", hwnd
);
2968 hwnd2
= CreateWindowA("Button", "", WS_VISIBLE
| WS_CHILD
, 0, 0, 10, 10, hwnd
, NULL
, NULL
, NULL
);
2969 ok(hwnd2
!= NULL
, "got %p\n", hwnd2
);
2972 ret
= pSHSetParentHwnd(NULL
, NULL
);
2973 ok(ret
== NULL
, "got %p\n", ret
);
2975 /* set to no parent while already no parent present */
2976 ret
= GetParent(hwnd
);
2977 ok(ret
== NULL
, "got %p\n", ret
);
2978 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
2979 ok((style
& (WS_POPUP
|WS_CHILD
)) == 0, "got style 0x%08x\n", style
);
2980 ret
= pSHSetParentHwnd(hwnd
, NULL
);
2981 ok(ret
== NULL
, "got %p\n", ret
);
2982 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
2983 ok((style
& (WS_POPUP
|WS_CHILD
)) == 0, "got style 0x%08x\n", style
);
2985 /* reset to null parent from not null */
2986 ret
= GetParent(hwnd2
);
2987 ok(ret
== hwnd
, "got %p\n", ret
);
2988 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
2989 ok((style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
, "got style 0x%08x\n", style
);
2990 ret
= pSHSetParentHwnd(hwnd2
, NULL
);
2991 ok(ret
== NULL
, "got %p\n", ret
);
2992 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
2993 ok((style
& (WS_POPUP
|WS_CHILD
)) == WS_POPUP
, "got style 0x%08x\n", style
);
2994 ret
= GetParent(hwnd2
);
2995 ok(ret
== NULL
, "got %p\n", ret
);
2997 /* set parent back */
2998 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
2999 SetWindowLongA(hwnd2
, GWL_STYLE
, style
& ~(WS_CHILD
|WS_POPUP
));
3000 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
3001 ok((style
& (WS_CHILD
|WS_POPUP
)) == 0, "got 0x%08x\n", style
);
3003 ret
= pSHSetParentHwnd(hwnd2
, hwnd
);
3004 todo_wine
ok(ret
== NULL
, "got %p\n", ret
);
3006 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
3007 ok((style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
, "got style 0x%08x\n", style
);
3008 ret
= GetParent(hwnd2
);
3009 ok(ret
== hwnd
, "got %p\n", ret
);
3011 /* try to set same parent again */
3013 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
3014 SetWindowLongA(hwnd2
, GWL_STYLE
, style
| WS_POPUP
);
3015 ret
= pSHSetParentHwnd(hwnd2
, hwnd
);
3016 todo_wine
ok(ret
== NULL
, "got %p\n", ret
);
3017 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
3018 ok((style
& (WS_CHILD
|WS_POPUP
)) == WS_CHILD
, "got 0x%08x\n", style
);
3019 ret
= GetParent(hwnd2
);
3020 ok(ret
== hwnd
, "got %p\n", ret
);
3022 /* without WS_POPUP */
3023 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
3024 SetWindowLongA(hwnd2
, GWL_STYLE
, style
| ~WS_POPUP
);
3025 ret
= pSHSetParentHwnd(hwnd2
, hwnd
);
3026 todo_wine
ok(ret
== hwnd
, "got %p\n", ret
);
3027 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
3028 ok((style
& (WS_CHILD
|WS_POPUP
)) == WS_CHILD
, "got 0x%08x\n", style
);
3029 ret
= GetParent(hwnd2
);
3030 ok(ret
== hwnd
, "got %p\n", ret
);
3032 DestroyWindow(hwnd
);
3033 DestroyWindow(hwnd2
);
3038 hShlwapi
= GetModuleHandleA("shlwapi.dll");
3039 is_win2k_and_lower
= GetProcAddress(hShlwapi
, "StrChrNW") == 0;
3040 is_win9x
= GetProcAddress(hShlwapi
, (LPSTR
)99) == 0; /* StrCpyNXA */
3042 /* SHCreateStreamOnFileEx was introduced in shlwapi v6.0 */
3043 if(!GetProcAddress(hShlwapi
, "SHCreateStreamOnFileEx")){
3044 win_skip("Too old shlwapi version\n");
3050 hmlang
= LoadLibraryA("mlang.dll");
3051 pLcidToRfc1766A
= (void *)GetProcAddress(hmlang
, "LcidToRfc1766A");
3053 hshell32
= LoadLibraryA("shell32.dll");
3054 pSHGetDesktopFolder
= (void *)GetProcAddress(hshell32
, "SHGetDesktopFolder");
3056 test_GetAcceptLanguagesA();
3057 test_SHSearchMapInt();
3058 test_alloc_shared();
3060 test_GetShellSecurityDescriptor();
3061 test_SHPackDispParams();
3062 test_IConnectionPoint();
3063 test_SHPropertyBag_ReadLONG();
3064 test_SHSetWindowBits();
3065 test_SHFormatDateTimeA();
3066 test_SHFormatDateTimeW();
3067 test_SHGetObjectCompatFlags();
3068 test_IUnknown_QueryServiceExec();
3069 test_IUnknown_ProfferService();
3070 test_SHCreateWorkerWindowA();
3071 test_SHIShellFolder_EnumObjects();
3072 test_SHGetIniString();
3073 test_SHSetIniString();
3074 test_SHGetShellKey();
3075 test_SHSetParentHwnd();
3077 FreeLibrary(hshell32
);
3078 FreeLibrary(hmlang
);