1 /* Unit test suite for SHLWAPI ordinal functions
3 * Copyright 2004 Jon Griffiths
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "wine/test.h"
36 /* Function ptrs for ordinal calls */
37 static HMODULE hShlwapi
;
38 static BOOL is_win2k_and_lower
;
41 static int (WINAPI
*pSHSearchMapInt
)(const int*,const int*,int,int);
42 static HRESULT (WINAPI
*pGetAcceptLanguagesA
)(LPSTR
,LPDWORD
);
44 static HANDLE (WINAPI
*pSHAllocShared
)(LPCVOID
,DWORD
,DWORD
);
45 static LPVOID (WINAPI
*pSHLockShared
)(HANDLE
,DWORD
);
46 static BOOL (WINAPI
*pSHUnlockShared
)(LPVOID
);
47 static BOOL (WINAPI
*pSHFreeShared
)(HANDLE
,DWORD
);
48 static HRESULT(WINAPIV
*pSHPackDispParams
)(DISPPARAMS
*,VARIANTARG
*,UINT
,...);
49 static HRESULT(WINAPI
*pIConnectionPoint_SimpleInvoke
)(IConnectionPoint
*,DISPID
,DISPPARAMS
*);
50 static HRESULT(WINAPI
*pIConnectionPoint_InvokeWithCancel
)(IConnectionPoint
*,DISPID
,DISPPARAMS
*,DWORD
,DWORD
);
51 static HRESULT(WINAPI
*pConnectToConnectionPoint
)(IUnknown
*,REFIID
,BOOL
,IUnknown
*, LPDWORD
,IConnectionPoint
**);
52 static HRESULT(WINAPI
*pSHPropertyBag_ReadLONG
)(IPropertyBag
*,LPCWSTR
,LPLONG
);
53 static LONG (WINAPI
*pSHSetWindowBits
)(HWND
, INT
, UINT
, UINT
);
54 static INT (WINAPI
*pSHFormatDateTimeA
)(const FILETIME UNALIGNED
*, DWORD
*, LPSTR
, UINT
);
55 static INT (WINAPI
*pSHFormatDateTimeW
)(const FILETIME UNALIGNED
*, DWORD
*, LPWSTR
, UINT
);
56 static DWORD (WINAPI
*pSHGetObjectCompatFlags
)(IUnknown
*, const CLSID
*);
57 static BOOL (WINAPI
*pGUIDFromStringA
)(LPSTR
, CLSID
*);
58 static HRESULT (WINAPI
*pIUnknown_QueryServiceExec
)(IUnknown
*, REFIID
, const GUID
*, DWORD
, DWORD
, VARIANT
*, VARIANT
*);
59 static HRESULT (WINAPI
*pIUnknown_ProfferService
)(IUnknown
*, REFGUID
, IServiceProvider
*, DWORD
*);
60 static HWND (WINAPI
*pSHCreateWorkerWindowA
)(LONG
, HWND
, DWORD
, DWORD
, HMENU
, LONG_PTR
);
61 static HRESULT (WINAPI
*pSHIShellFolder_EnumObjects
)(LPSHELLFOLDER
, HWND
, SHCONTF
, IEnumIDList
**);
62 static DWORD (WINAPI
*pSHGetIniStringW
)(LPCWSTR
, LPCWSTR
, LPWSTR
, DWORD
, LPCWSTR
);
63 static BOOL (WINAPI
*pSHSetIniStringW
)(LPCWSTR
, LPCWSTR
, LPCWSTR
, LPCWSTR
);
64 static HKEY (WINAPI
*pSHGetShellKey
)(DWORD
, LPWSTR
, BOOL
);
66 static HMODULE hmlang
;
67 static HRESULT (WINAPI
*pLcidToRfc1766A
)(LCID
, LPSTR
, INT
);
69 static HMODULE hshell32
;
70 static HRESULT (WINAPI
*pSHGetDesktopFolder
)(IShellFolder
**);
72 static const CHAR ie_international
[] = {
73 'S','o','f','t','w','a','r','e','\\',
74 'M','i','c','r','o','s','o','f','t','\\',
75 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
76 'I','n','t','e','r','n','a','t','i','o','n','a','l',0};
77 static const CHAR acceptlanguage
[] = {
78 'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0};
80 static int strcmp_wa(LPCWSTR strw
, const char *stra
)
83 WideCharToMultiByte(CP_ACP
, 0, strw
, -1, buf
, sizeof(buf
), NULL
, NULL
);
84 return lstrcmpA(stra
, buf
);
98 static void init_call_trace(call_trace_t
*ctrace
)
102 ctrace
->calls
= HeapAlloc(GetProcessHeap(), 0, sizeof(call_entry_t
) * ctrace
->alloc
);
105 static void free_call_trace(const call_trace_t
*ctrace
)
107 HeapFree(GetProcessHeap(), 0, ctrace
->calls
);
110 static void add_call(call_trace_t
*ctrace
, int id
, const void *arg0
,
111 const void *arg1
, const void *arg2
, const void *arg3
, const void *arg4
)
122 if (ctrace
->count
== ctrace
->alloc
)
125 ctrace
->calls
= HeapReAlloc(GetProcessHeap(),0, ctrace
->calls
, ctrace
->alloc
*sizeof(call_entry_t
));
128 ctrace
->calls
[ctrace
->count
++] = call
;
131 static void ok_trace_(call_trace_t
*texpected
, call_trace_t
*tgot
, int line
)
133 if (texpected
->count
== tgot
->count
)
137 for (i
= 0; i
< texpected
->count
; i
++)
139 call_entry_t
*expected
= &texpected
->calls
[i
];
140 call_entry_t
*got
= &tgot
->calls
[i
];
143 ok_(__FILE__
, line
)(expected
->id
== got
->id
, "got different ids %d: %d, %d\n", i
+1, expected
->id
, got
->id
);
145 for (j
= 0; j
< 5; j
++)
147 ok_(__FILE__
, line
)(expected
->args
[j
] == got
->args
[j
], "got different args[%d] for %d: %p, %p\n", j
, i
+1,
148 expected
->args
[j
], got
->args
[j
]);
153 ok_(__FILE__
, line
)(0, "traces length mismatch\n");
156 #define ok_trace(a, b) ok_trace_(a, b, __LINE__)
158 /* trace of actually made calls */
159 static call_trace_t trace_got
;
161 static void test_GetAcceptLanguagesA(void)
163 static LPCSTR table
[] = {"de,en-gb;q=0.7,en;q=0.3",
164 "de,en;q=0.3,en-gb;q=0.7", /* sorting is ignored */
165 "winetest", /* content is ignored */
175 LONG res_query
= ERROR_SUCCESS
;
178 DWORD maxlen
= sizeof(buffer
) - 2;
184 if (!pGetAcceptLanguagesA
) {
185 win_skip("GetAcceptLanguagesA is not available\n");
189 lcid
= GetUserDefaultLCID();
191 /* Get the original Value */
192 lres
= RegOpenKeyA(HKEY_CURRENT_USER
, ie_international
, &hroot
);
194 skip("RegOpenKey(%s) failed: %d\n", ie_international
, lres
);
197 len
= sizeof(original
);
199 res_query
= RegQueryValueExA(hroot
, acceptlanguage
, 0, NULL
, (PBYTE
)original
, &len
);
201 RegDeleteValue(hroot
, acceptlanguage
);
203 /* Some windows versions use "lang-COUNTRY" as default */
204 memset(language
, 0, sizeof(language
));
205 len
= GetLocaleInfoA(lcid
, LOCALE_SISO639LANGNAME
, language
, sizeof(language
));
208 lstrcat(language
, "-");
209 memset(buffer
, 0, sizeof(buffer
));
210 len
= GetLocaleInfoA(lcid
, LOCALE_SISO3166CTRYNAME
, buffer
, sizeof(buffer
) - len
- 1);
211 lstrcat(language
, buffer
);
215 /* LOCALE_SNAME has additional parts in some languages. Try only as last chance */
216 memset(language
, 0, sizeof(language
));
217 len
= GetLocaleInfoA(lcid
, LOCALE_SNAME
, language
, sizeof(language
));
220 /* get the default value */
222 memset(buffer
, '#', maxlen
);
224 hr
= pGetAcceptLanguagesA( buffer
, &len
);
227 win_skip("GetAcceptLanguagesA failed with 0x%x\n", hr
);
228 goto restore_original
;
231 if (lstrcmpA(buffer
, language
)) {
232 /* some windows versions use "lang" or "lang-country" as default */
234 if (pLcidToRfc1766A
) {
235 hr
= pLcidToRfc1766A(lcid
, language
, sizeof(language
));
236 ok(hr
== S_OK
, "LcidToRfc1766A returned 0x%x and %s\n", hr
, language
);
240 ok(!lstrcmpA(buffer
, language
),
241 "have '%s' (searching for '%s')\n", language
, buffer
);
243 if (lstrcmpA(buffer
, language
)) {
244 win_skip("no more ideas, how to build the default language '%s'\n", buffer
);
245 goto restore_original
;
248 trace("detected default: %s\n", language
);
249 while ((entry
= table
[i
])) {
251 exactsize
= lstrlenA(entry
);
253 lres
= RegSetValueExA(hroot
, acceptlanguage
, 0, REG_SZ
, (const BYTE
*) entry
, exactsize
+ 1);
254 ok(!lres
, "got %d for RegSetValueExA: %s\n", lres
, entry
);
256 /* len includes space for the terminating 0 before vista/w2k8 */
258 memset(buffer
, '#', maxlen
);
260 hr
= pGetAcceptLanguagesA( buffer
, &len
);
261 ok(((hr
== E_INVALIDARG
) && (len
== 0)) ||
263 ((len
== exactsize
) || (len
== exactsize
+1)) &&
264 !lstrcmpA(buffer
, entry
)),
265 "+2_#%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
268 memset(buffer
, '#', maxlen
);
270 hr
= pGetAcceptLanguagesA( buffer
, &len
);
271 ok(((hr
== E_INVALIDARG
) && (len
== 0)) ||
273 ((len
== exactsize
) || (len
== exactsize
+1)) &&
274 !lstrcmpA(buffer
, entry
)),
275 "+1_#%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
278 memset(buffer
, '#', maxlen
);
280 hr
= pGetAcceptLanguagesA( buffer
, &len
);
282 /* There is no space for the string in the registry.
283 When the buffer is large enough, the default language is returned
285 When the buffer is too small for that fallback, win7_32 and w2k8_64
286 and above fail with HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), but
287 recent os succeed and return a partial result while
288 older os succeed and overflow the buffer */
290 ok(((hr
== E_INVALIDARG
) && (len
== 0)) ||
291 (((hr
== S_OK
) && !lstrcmpA(buffer
, language
) && (len
== lstrlenA(language
))) ||
292 ((hr
== S_OK
) && !memcmp(buffer
, language
, len
)) ||
293 ((hr
== __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
)) && !len
)),
294 "==_#%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
298 memset(buffer
, '#', maxlen
);
300 hr
= pGetAcceptLanguagesA( buffer
, &len
);
301 ok(((hr
== E_INVALIDARG
) && (len
== 0)) ||
302 (((hr
== S_OK
) && !lstrcmpA(buffer
, language
) && (len
== lstrlenA(language
))) ||
303 ((hr
== S_OK
) && !memcmp(buffer
, language
, len
)) ||
304 ((hr
== __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
)) && !len
)),
305 "-1_#%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
309 memset(buffer
, '#', maxlen
);
311 hr
= pGetAcceptLanguagesA( buffer
, &len
);
312 ok(((hr
== E_INVALIDARG
) && (len
== 0)) ||
313 (((hr
== S_OK
) && !lstrcmpA(buffer
, language
) && (len
== lstrlenA(language
))) ||
314 ((hr
== S_OK
) && !memcmp(buffer
, language
, len
)) ||
315 ((hr
== __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
)) && !len
)),
316 "=1_#%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
319 hr
= pGetAcceptLanguagesA( NULL
, &len
);
321 /* w2k3 and below: E_FAIL and untouched len,
322 since w2k8: S_OK and needed size (excluding 0) */
323 ok( ((hr
== S_OK
) && (len
== exactsize
)) ||
324 ((hr
== E_FAIL
) && (len
== maxlen
)),
325 "NULL,max #%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
330 /* without a value in the registry, a default language is returned */
331 RegDeleteValue(hroot
, acceptlanguage
);
334 memset(buffer
, '#', maxlen
);
336 hr
= pGetAcceptLanguagesA( buffer
, &len
);
337 ok( ((hr
== S_OK
) && (len
== lstrlenA(language
))),
338 "max: got 0x%x with %d and %s (expected S_OK with %d and '%s'\n",
339 hr
, len
, buffer
, lstrlenA(language
), language
);
342 memset(buffer
, '#', maxlen
);
344 hr
= pGetAcceptLanguagesA( buffer
, &len
);
345 ok( (((hr
== S_OK
) || (hr
== E_INVALIDARG
)) && !memcmp(buffer
, language
, len
)) ||
346 ((hr
== __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
)) && !len
),
347 "=2: got 0x%x with %d and %s\n", hr
, len
, buffer
);
350 memset(buffer
, '#', maxlen
);
352 hr
= pGetAcceptLanguagesA( buffer
, &len
);
353 /* When the buffer is too small, win7_32 and w2k8_64 and above fail with
354 HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), other versions suceed
355 and return a partial 0 terminated result while other versions
356 fail with E_INVALIDARG and return a partial unterminated result */
357 ok( (((hr
== S_OK
) || (hr
== E_INVALIDARG
)) && !memcmp(buffer
, language
, len
)) ||
358 ((hr
== __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
)) && !len
),
359 "=1: got 0x%x with %d and %s\n", hr
, len
, buffer
);
362 memset(buffer
, '#', maxlen
);
364 hr
= pGetAcceptLanguagesA( buffer
, &len
);
365 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
366 ok((hr
== E_FAIL
) || (hr
== E_INVALIDARG
),
367 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr
);
369 memset(buffer
, '#', maxlen
);
371 hr
= pGetAcceptLanguagesA( buffer
, NULL
);
372 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
373 ok((hr
== E_FAIL
) || (hr
== E_INVALIDARG
),
374 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr
);
377 hr
= pGetAcceptLanguagesA( NULL
, 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
);
384 len
= lstrlenA(original
);
385 lres
= RegSetValueExA(hroot
, acceptlanguage
, 0, REG_SZ
, (const BYTE
*) original
, len
? len
+ 1: 0);
386 ok(!lres
, "RegSetValueEx(%s) failed: %d\n", original
, lres
);
390 RegDeleteValue(hroot
, acceptlanguage
);
395 static void test_SHSearchMapInt(void)
397 int keys
[8], values
[8];
400 if (!pSHSearchMapInt
)
403 memset(keys
, 0, sizeof(keys
));
404 memset(values
, 0, sizeof(values
));
405 keys
[0] = 99; values
[0] = 101;
407 /* NULL key/value lists crash native, so skip testing them */
410 i
= pSHSearchMapInt(keys
, values
, 1, keys
[0]);
411 ok(i
== values
[0], "Len 1, expected %d, got %d\n", values
[0], i
);
413 /* Key doesn't exist */
414 i
= pSHSearchMapInt(keys
, values
, 1, 100);
415 ok(i
== -1, "Len 1 - bad key, expected -1, got %d\n", i
);
417 /* Len = 0 => not found */
418 i
= pSHSearchMapInt(keys
, values
, 0, keys
[0]);
419 ok(i
== -1, "Len 1 - passed len 0, expected -1, got %d\n", i
);
421 /* 2 elements, len = 1 */
422 keys
[1] = 98; values
[1] = 102;
423 i
= pSHSearchMapInt(keys
, values
, 1, keys
[1]);
424 ok(i
== -1, "Len 1 - array len 2, expected -1, got %d\n", i
);
426 /* 2 elements, len = 2 */
427 i
= pSHSearchMapInt(keys
, values
, 2, keys
[1]);
428 ok(i
== values
[1], "Len 2, expected %d, got %d\n", values
[1], i
);
430 /* Searches forward */
431 keys
[2] = 99; values
[2] = 103;
432 i
= pSHSearchMapInt(keys
, values
, 3, keys
[0]);
433 ok(i
== values
[0], "Len 3, expected %d, got %d\n", values
[0], i
);
436 static void test_alloc_shared(void)
444 procid
=GetCurrentProcessId();
445 hmem
=pSHAllocShared(NULL
,10,procid
);
446 ok(hmem
!=NULL
,"SHAllocShared(NULL...) failed: %u\n", GetLastError());
447 ret
= pSHFreeShared(hmem
, procid
);
448 ok( ret
, "SHFreeShared failed: %u\n", GetLastError());
451 hmem
=pSHAllocShared(&val
,4,procid
);
452 ok(hmem
!=NULL
,"SHAllocShared(NULL...) failed: %u\n", GetLastError());
454 p
=pSHLockShared(hmem
,procid
);
455 ok(p
!=NULL
,"SHLockShared failed: %u\n", GetLastError());
457 ok(*p
==val
,"Wrong value in shared memory: %d instead of %d\n",*p
,val
);
458 ret
= pSHUnlockShared(p
);
459 ok( ret
, "SHUnlockShared failed: %u\n", GetLastError());
461 ret
= pSHFreeShared(hmem
, procid
);
462 ok( ret
, "SHFreeShared failed: %u\n", GetLastError());
465 static void test_fdsa(void)
469 DWORD num_items
; /* Number of elements inserted */
470 void *mem
; /* Ptr to array */
471 DWORD blocks_alloced
; /* Number of elements allocated */
472 BYTE inc
; /* Number of elements to grow by when we need to expand */
473 BYTE block_size
; /* Size in bytes of an element */
474 BYTE flags
; /* Flags */
477 BOOL (WINAPI
*pFDSA_Initialize
)(DWORD block_size
, DWORD inc
, FDSA_info
*info
, void *mem
,
479 BOOL (WINAPI
*pFDSA_Destroy
)(FDSA_info
*info
);
480 DWORD (WINAPI
*pFDSA_InsertItem
)(FDSA_info
*info
, DWORD where
, const void *block
);
481 BOOL (WINAPI
*pFDSA_DeleteItem
)(FDSA_info
*info
, DWORD where
);
484 int block_size
= 10, init_blocks
= 4, inc
= 2;
488 pFDSA_Initialize
= (void *)GetProcAddress(hShlwapi
, (LPSTR
)208);
489 pFDSA_Destroy
= (void *)GetProcAddress(hShlwapi
, (LPSTR
)209);
490 pFDSA_InsertItem
= (void *)GetProcAddress(hShlwapi
, (LPSTR
)210);
491 pFDSA_DeleteItem
= (void *)GetProcAddress(hShlwapi
, (LPSTR
)211);
493 mem
= HeapAlloc(GetProcessHeap(), 0, block_size
* init_blocks
);
494 memset(&info
, 0, sizeof(info
));
496 ok(pFDSA_Initialize(block_size
, inc
, &info
, mem
, init_blocks
), "FDSA_Initialize rets FALSE\n");
497 ok(info
.num_items
== 0, "num_items = %d\n", info
.num_items
);
498 ok(info
.mem
== mem
, "mem = %p\n", info
.mem
);
499 ok(info
.blocks_alloced
== init_blocks
, "blocks_alloced = %d\n", info
.blocks_alloced
);
500 ok(info
.inc
== inc
, "inc = %d\n", info
.inc
);
501 ok(info
.block_size
== block_size
, "block_size = %d\n", info
.block_size
);
502 ok(info
.flags
== 0, "flags = %d\n", info
.flags
);
504 ret
= pFDSA_InsertItem(&info
, 1234, "1234567890");
505 ok(ret
== 0, "ret = %d\n", ret
);
506 ok(info
.num_items
== 1, "num_items = %d\n", info
.num_items
);
507 ok(info
.mem
== mem
, "mem = %p\n", info
.mem
);
508 ok(info
.blocks_alloced
== init_blocks
, "blocks_alloced = %d\n", info
.blocks_alloced
);
509 ok(info
.inc
== inc
, "inc = %d\n", info
.inc
);
510 ok(info
.block_size
== block_size
, "block_size = %d\n", info
.block_size
);
511 ok(info
.flags
== 0, "flags = %d\n", info
.flags
);
513 ret
= pFDSA_InsertItem(&info
, 1234, "abcdefghij");
514 ok(ret
== 1, "ret = %d\n", ret
);
516 ret
= pFDSA_InsertItem(&info
, 1, "klmnopqrst");
517 ok(ret
== 1, "ret = %d\n", ret
);
519 ret
= pFDSA_InsertItem(&info
, 0, "uvwxyzABCD");
520 ok(ret
== 0, "ret = %d\n", ret
);
521 ok(info
.mem
== mem
, "mem = %p\n", info
.mem
);
522 ok(info
.flags
== 0, "flags = %d\n", info
.flags
);
524 /* This next InsertItem will cause shlwapi to allocate its own mem buffer */
525 ret
= pFDSA_InsertItem(&info
, 0, "EFGHIJKLMN");
526 ok(ret
== 0, "ret = %d\n", ret
);
527 ok(info
.mem
!= mem
, "mem = %p\n", info
.mem
);
528 ok(info
.blocks_alloced
== init_blocks
+ inc
, "blocks_alloced = %d\n", info
.blocks_alloced
);
529 ok(info
.flags
== 0x1, "flags = %d\n", info
.flags
);
531 ok(!memcmp(info
.mem
, "EFGHIJKLMNuvwxyzABCD1234567890klmnopqrstabcdefghij", 50), "mem %s\n", (char*)info
.mem
);
533 ok(pFDSA_DeleteItem(&info
, 2), "rets FALSE\n");
534 ok(info
.mem
!= mem
, "mem = %p\n", info
.mem
);
535 ok(info
.blocks_alloced
== init_blocks
+ inc
, "blocks_alloced = %d\n", info
.blocks_alloced
);
536 ok(info
.flags
== 0x1, "flags = %d\n", info
.flags
);
538 ok(!memcmp(info
.mem
, "EFGHIJKLMNuvwxyzABCDklmnopqrstabcdefghij", 40), "mem %s\n", (char*)info
.mem
);
540 ok(pFDSA_DeleteItem(&info
, 3), "rets FALSE\n");
541 ok(info
.mem
!= mem
, "mem = %p\n", info
.mem
);
542 ok(info
.blocks_alloced
== init_blocks
+ inc
, "blocks_alloced = %d\n", info
.blocks_alloced
);
543 ok(info
.flags
== 0x1, "flags = %d\n", info
.flags
);
545 ok(!memcmp(info
.mem
, "EFGHIJKLMNuvwxyzABCDklmnopqrst", 30), "mem %s\n", (char*)info
.mem
);
547 ok(!pFDSA_DeleteItem(&info
, 4), "does not ret FALSE\n");
549 /* As shlwapi has allocated memory internally, Destroy will ret FALSE */
550 ok(!pFDSA_Destroy(&info
), "FDSA_Destroy does not ret FALSE\n");
553 /* When Initialize is called with inc = 0, set it to 1 */
554 ok(pFDSA_Initialize(block_size
, 0, &info
, mem
, init_blocks
), "FDSA_Initialize rets FALSE\n");
555 ok(info
.inc
== 1, "inc = %d\n", info
.inc
);
557 /* This time, because shlwapi hasn't had to allocate memory
558 internally, Destroy rets non-zero */
559 ok(pFDSA_Destroy(&info
), "FDSA_Destroy rets FALSE\n");
562 HeapFree(GetProcessHeap(), 0, mem
);
566 typedef struct SHELL_USER_SID
{
567 SID_IDENTIFIER_AUTHORITY sidAuthority
;
570 } SHELL_USER_SID
, *PSHELL_USER_SID
;
571 typedef struct SHELL_USER_PERMISSION
{
572 SHELL_USER_SID susID
;
577 DWORD dwInheritAccessMask
;
578 } SHELL_USER_PERMISSION
, *PSHELL_USER_PERMISSION
;
579 static void test_GetShellSecurityDescriptor(void)
581 SHELL_USER_PERMISSION supCurrentUserFull
= {
582 { {SECURITY_NULL_SID_AUTHORITY
}, 0, 0 },
583 ACCESS_ALLOWED_ACE_TYPE
, FALSE
,
585 #define MY_INHERITANCE 0xBE /* invalid value to proof behavior */
586 SHELL_USER_PERMISSION supEveryoneDenied
= {
587 { {SECURITY_WORLD_SID_AUTHORITY
}, SECURITY_WORLD_RID
, 0 },
588 ACCESS_DENIED_ACE_TYPE
, TRUE
,
589 GENERIC_WRITE
, MY_INHERITANCE
| 0xDEADBA00, GENERIC_READ
};
590 PSHELL_USER_PERMISSION rgsup
[2] = {
591 &supCurrentUserFull
, &supEveryoneDenied
,
593 SECURITY_DESCRIPTOR
* psd
;
594 SECURITY_DESCRIPTOR
* (WINAPI
*pGetShellSecurityDescriptor
)(PSHELL_USER_PERMISSION
*,int);
595 void *pChrCmpIW
= GetProcAddress(hShlwapi
, "ChrCmpIW");
597 pGetShellSecurityDescriptor
=(void*)GetProcAddress(hShlwapi
,(char*)475);
599 if(!pGetShellSecurityDescriptor
)
601 win_skip("GetShellSecurityDescriptor not available\n");
605 if(pChrCmpIW
&& pChrCmpIW
== pGetShellSecurityDescriptor
) /* win2k */
607 win_skip("Skipping for GetShellSecurityDescriptor, same ordinal used for ChrCmpIW\n");
611 psd
= pGetShellSecurityDescriptor(NULL
, 2);
613 broken(psd
==INVALID_HANDLE_VALUE
), /* IE5 */
614 "GetShellSecurityDescriptor should fail\n");
615 psd
= pGetShellSecurityDescriptor(rgsup
, 0);
616 ok(psd
==NULL
, "GetShellSecurityDescriptor should fail, got %p\n", psd
);
618 SetLastError(0xdeadbeef);
619 psd
= pGetShellSecurityDescriptor(rgsup
, 2);
620 if (psd
== NULL
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
622 /* The previous calls to GetShellSecurityDescriptor don't set the last error */
623 win_skip("GetShellSecurityDescriptor is not implemented\n");
626 if (psd
== INVALID_HANDLE_VALUE
)
628 win_skip("GetShellSecurityDescriptor is broken on IE5\n");
631 ok(psd
!=NULL
, "GetShellSecurityDescriptor failed\n");
634 BOOL bHasDacl
= FALSE
, bDefaulted
;
637 SECURITY_DESCRIPTOR_CONTROL control
;
639 ok(IsValidSecurityDescriptor(psd
), "returned value is not valid SD\n");
641 ok(GetSecurityDescriptorControl(psd
, &control
, &dwRev
),
642 "GetSecurityDescriptorControl failed with error %u\n", GetLastError());
643 ok(0 == (control
& SE_SELF_RELATIVE
), "SD should be absolute\n");
645 ok(GetSecurityDescriptorDacl(psd
, &bHasDacl
, &pAcl
, &bDefaulted
),
646 "GetSecurityDescriptorDacl failed with error %u\n", GetLastError());
648 ok(bHasDacl
, "SD has no DACL\n");
651 ok(!bDefaulted
, "DACL should not be defaulted\n");
653 ok(pAcl
!= NULL
, "NULL DACL!\n");
656 ACL_SIZE_INFORMATION asiSize
;
658 ok(IsValidAcl(pAcl
), "DACL is not valid\n");
660 ok(GetAclInformation(pAcl
, &asiSize
, sizeof(asiSize
), AclSizeInformation
),
661 "GetAclInformation failed with error %u\n", GetLastError());
663 ok(asiSize
.AceCount
== 3, "Incorrect number of ACEs: %d entries\n", asiSize
.AceCount
);
664 if (asiSize
.AceCount
== 3)
666 ACCESS_ALLOWED_ACE
*paaa
; /* will use for DENIED too */
668 ok(GetAce(pAcl
, 0, (LPVOID
*)&paaa
), "GetAce failed with error %u\n", GetLastError());
669 ok(paaa
->Header
.AceType
== ACCESS_ALLOWED_ACE_TYPE
,
670 "Invalid ACE type %d\n", paaa
->Header
.AceType
);
671 ok(paaa
->Header
.AceFlags
== 0, "Invalid ACE flags %x\n", paaa
->Header
.AceFlags
);
672 ok(paaa
->Mask
== GENERIC_ALL
, "Invalid ACE mask %x\n", paaa
->Mask
);
674 ok(GetAce(pAcl
, 1, (LPVOID
*)&paaa
), "GetAce failed with error %u\n", GetLastError());
675 ok(paaa
->Header
.AceType
== ACCESS_DENIED_ACE_TYPE
,
676 "Invalid ACE type %d\n", paaa
->Header
.AceType
);
677 /* first one of two ACEs generated from inheritable entry - without inheritance */
678 ok(paaa
->Header
.AceFlags
== 0, "Invalid ACE flags %x\n", paaa
->Header
.AceFlags
);
679 ok(paaa
->Mask
== GENERIC_WRITE
, "Invalid ACE mask %x\n", paaa
->Mask
);
681 ok(GetAce(pAcl
, 2, (LPVOID
*)&paaa
), "GetAce failed with error %u\n", GetLastError());
682 ok(paaa
->Header
.AceType
== ACCESS_DENIED_ACE_TYPE
,
683 "Invalid ACE type %d\n", paaa
->Header
.AceType
);
684 /* second ACE - with inheritance */
685 ok(paaa
->Header
.AceFlags
== MY_INHERITANCE
,
686 "Invalid ACE flags %x\n", paaa
->Header
.AceFlags
);
687 ok(paaa
->Mask
== GENERIC_READ
, "Invalid ACE mask %x\n", paaa
->Mask
);
696 static void test_SHPackDispParams(void)
702 if(!pSHPackDispParams
)
703 win_skip("SHPackSidpParams not available\n");
705 memset(¶ms
, 0xc0, sizeof(params
));
706 memset(vars
, 0xc0, sizeof(vars
));
707 hres
= pSHPackDispParams(¶ms
, vars
, 1, VT_I4
, 0xdeadbeef);
708 ok(hres
== S_OK
, "SHPackDispParams failed: %08x\n", hres
);
709 ok(params
.cArgs
== 1, "params.cArgs = %d\n", params
.cArgs
);
710 ok(params
.cNamedArgs
== 0, "params.cNamedArgs = %d\n", params
.cArgs
);
711 ok(params
.rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", params
.rgdispidNamedArgs
);
712 ok(params
.rgvarg
== vars
, "params.rgvarg = %p\n", params
.rgvarg
);
713 ok(V_VT(vars
) == VT_I4
, "V_VT(var) = %d\n", V_VT(vars
));
714 ok(V_I4(vars
) == 0xdeadbeef, "failed %x\n", V_I4(vars
));
716 memset(¶ms
, 0xc0, sizeof(params
));
717 hres
= pSHPackDispParams(¶ms
, NULL
, 0, 0);
718 ok(hres
== S_OK
, "SHPackDispParams failed: %08x\n", hres
);
719 ok(params
.cArgs
== 0, "params.cArgs = %d\n", params
.cArgs
);
720 ok(params
.cNamedArgs
== 0, "params.cNamedArgs = %d\n", params
.cArgs
);
721 ok(params
.rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", params
.rgdispidNamedArgs
);
722 ok(params
.rgvarg
== NULL
, "params.rgvarg = %p\n", params
.rgvarg
);
724 memset(vars
, 0xc0, sizeof(vars
));
725 memset(¶ms
, 0xc0, sizeof(params
));
726 hres
= pSHPackDispParams(¶ms
, vars
, 4, VT_BSTR
, (void*)0xdeadbeef, VT_EMPTY
, 10,
727 VT_I4
, 100, VT_DISPATCH
, (void*)0xdeadbeef);
728 ok(hres
== S_OK
, "SHPackDispParams failed: %08x\n", hres
);
729 ok(params
.cArgs
== 4, "params.cArgs = %d\n", params
.cArgs
);
730 ok(params
.cNamedArgs
== 0, "params.cNamedArgs = %d\n", params
.cArgs
);
731 ok(params
.rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", params
.rgdispidNamedArgs
);
732 ok(params
.rgvarg
== vars
, "params.rgvarg = %p\n", params
.rgvarg
);
733 ok(V_VT(vars
) == VT_DISPATCH
, "V_VT(vars[0]) = %x\n", V_VT(vars
));
734 ok(V_I4(vars
) == 0xdeadbeef, "V_I4(vars[0]) = %x\n", V_I4(vars
));
735 ok(V_VT(vars
+1) == VT_I4
, "V_VT(vars[1]) = %d\n", V_VT(vars
+1));
736 ok(V_I4(vars
+1) == 100, "V_I4(vars[1]) = %x\n", V_I4(vars
+1));
737 ok(V_VT(vars
+2) == VT_I4
, "V_VT(vars[2]) = %d\n", V_VT(vars
+2));
738 ok(V_I4(vars
+2) == 10, "V_I4(vars[2]) = %x\n", V_I4(vars
+2));
739 ok(V_VT(vars
+3) == VT_BSTR
, "V_VT(vars[3]) = %d\n", V_VT(vars
+3));
740 ok(V_BSTR(vars
+3) == (void*)0xdeadbeef, "V_BSTR(vars[3]) = %p\n", V_BSTR(vars
+3));
745 const IDispatchVtbl
*vtbl
;
749 typedef struct _contain
751 const IConnectionPointContainerVtbl
*vtbl
;
755 IConnectionPoint
**pt
;
758 typedef struct _cntptn
760 const IConnectionPointVtbl
*vtbl
;
771 const IEnumConnectionsVtbl
*vtbl
;
778 typedef struct _enumpt
780 const IEnumConnectionPointsVtbl
*vtbl
;
788 static HRESULT WINAPI
Disp_QueryInterface(
795 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDispatch
))
802 IUnknown_AddRef(This
);
806 trace("no interface\n");
807 return E_NOINTERFACE
;
810 static ULONG WINAPI
Disp_AddRef(IDispatch
* This
)
812 Disp
*iface
= (Disp
*)This
;
813 return InterlockedIncrement(&iface
->refCount
);
816 static ULONG WINAPI
Disp_Release(IDispatch
* This
)
818 Disp
*iface
= (Disp
*)This
;
821 ret
= InterlockedDecrement(&iface
->refCount
);
823 HeapFree(GetProcessHeap(),0,This
);
827 static HRESULT WINAPI
Disp_GetTypeInfoCount(
831 return ERROR_SUCCESS
;
834 static HRESULT WINAPI
Disp_GetTypeInfo(
840 return ERROR_SUCCESS
;
843 static HRESULT WINAPI
Disp_GetIDsOfNames(
851 return ERROR_SUCCESS
;
854 static HRESULT WINAPI
Disp_Invoke(
860 DISPPARAMS
*pDispParams
,
862 EXCEPINFO
*pExcepInfo
,
865 trace("%p %x %p %x %x %p %p %p %p\n",This
,dispIdMember
,riid
,lcid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,puArgErr
);
867 ok(dispIdMember
== 0xa0 || dispIdMember
== 0xa1, "Unknown dispIdMember\n");
868 ok(pDispParams
!= NULL
, "Invoked with NULL pDispParams\n");
869 ok(wFlags
== DISPATCH_METHOD
, "Wrong flags %x\n",wFlags
);
870 ok(lcid
== 0,"Wrong lcid %x\n",lcid
);
871 if (dispIdMember
== 0xa0)
873 ok(pDispParams
->cArgs
== 0, "params.cArgs = %d\n", pDispParams
->cArgs
);
874 ok(pDispParams
->cNamedArgs
== 0, "params.cNamedArgs = %d\n", pDispParams
->cArgs
);
875 ok(pDispParams
->rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", pDispParams
->rgdispidNamedArgs
);
876 ok(pDispParams
->rgvarg
== NULL
, "params.rgvarg = %p\n", pDispParams
->rgvarg
);
878 else if (dispIdMember
== 0xa1)
880 ok(pDispParams
->cArgs
== 2, "params.cArgs = %d\n", pDispParams
->cArgs
);
881 ok(pDispParams
->cNamedArgs
== 0, "params.cNamedArgs = %d\n", pDispParams
->cArgs
);
882 ok(pDispParams
->rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", pDispParams
->rgdispidNamedArgs
);
883 ok(V_VT(pDispParams
->rgvarg
) == VT_BSTR
, "V_VT(var) = %d\n", V_VT(pDispParams
->rgvarg
));
884 ok(V_I4(pDispParams
->rgvarg
) == 0xdeadcafe , "failed %p\n", V_BSTR(pDispParams
->rgvarg
));
885 ok(V_VT(pDispParams
->rgvarg
+1) == VT_I4
, "V_VT(var) = %d\n", V_VT(pDispParams
->rgvarg
+1));
886 ok(V_I4(pDispParams
->rgvarg
+1) == 0xdeadbeef, "failed %x\n", V_I4(pDispParams
->rgvarg
+1));
889 return ERROR_SUCCESS
;
892 static const IDispatchVtbl disp_vtbl
= {
897 Disp_GetTypeInfoCount
,
903 static HRESULT WINAPI
Enum_QueryInterface(
904 IEnumConnections
* This
,
910 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IEnumConnections
))
917 IUnknown_AddRef(This
);
921 trace("no interface\n");
922 return E_NOINTERFACE
;
925 static ULONG WINAPI
Enum_AddRef(IEnumConnections
* This
)
927 EnumCon
*iface
= (EnumCon
*)This
;
928 return InterlockedIncrement(&iface
->refCount
);
931 static ULONG WINAPI
Enum_Release(IEnumConnections
* This
)
933 EnumCon
*iface
= (EnumCon
*)This
;
936 ret
= InterlockedDecrement(&iface
->refCount
);
938 HeapFree(GetProcessHeap(),0,This
);
942 static HRESULT WINAPI
Enum_Next(
943 IEnumConnections
* This
,
948 EnumCon
*iface
= (EnumCon
*)This
;
950 if (cConnections
> 0 && iface
->idx
< iface
->pt
->sinkCount
)
952 rgcd
->pUnk
= iface
->pt
->sink
[iface
->idx
];
953 IUnknown_AddRef(iface
->pt
->sink
[iface
->idx
]);
964 static HRESULT WINAPI
Enum_Skip(
965 IEnumConnections
* This
,
971 static HRESULT WINAPI
Enum_Reset(
972 IEnumConnections
* This
)
977 static HRESULT WINAPI
Enum_Clone(
978 IEnumConnections
* This
,
979 IEnumConnections
**ppEnum
)
984 static const IEnumConnectionsVtbl enum_vtbl
= {
995 static HRESULT WINAPI
ConPt_QueryInterface(
996 IConnectionPoint
* This
,
1002 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IConnectionPoint
))
1009 IUnknown_AddRef(This
);
1013 trace("no interface\n");
1014 return E_NOINTERFACE
;
1017 static ULONG WINAPI
ConPt_AddRef(
1018 IConnectionPoint
* This
)
1020 ConPt
*iface
= (ConPt
*)This
;
1021 return InterlockedIncrement(&iface
->refCount
);
1024 static ULONG WINAPI
ConPt_Release(
1025 IConnectionPoint
* This
)
1027 ConPt
*iface
= (ConPt
*)This
;
1030 ret
= InterlockedDecrement(&iface
->refCount
);
1033 if (iface
->sinkCount
> 0)
1036 for (i
= 0; i
< iface
->sinkCount
; i
++)
1039 IUnknown_Release(iface
->sink
[i
]);
1041 HeapFree(GetProcessHeap(),0,iface
->sink
);
1043 HeapFree(GetProcessHeap(),0,This
);
1048 static HRESULT WINAPI
ConPt_GetConnectionInterface(
1049 IConnectionPoint
* This
,
1053 ConPt
*iface
= (ConPt
*)This
;
1060 memcpy(pIID
,&iface
->id
,sizeof(GUID
));
1064 static HRESULT WINAPI
ConPt_GetConnectionPointContainer(
1065 IConnectionPoint
* This
,
1066 IConnectionPointContainer
**ppCPC
)
1068 ConPt
*iface
= (ConPt
*)This
;
1070 *ppCPC
= (IConnectionPointContainer
*)iface
->container
;
1074 static HRESULT WINAPI
ConPt_Advise(
1075 IConnectionPoint
* This
,
1079 ConPt
*iface
= (ConPt
*)This
;
1081 if (iface
->sinkCount
== 0)
1082 iface
->sink
= HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown
*));
1084 iface
->sink
= HeapReAlloc(GetProcessHeap(),0,iface
->sink
,sizeof(IUnknown
*)*(iface
->sinkCount
+1));
1085 iface
->sink
[iface
->sinkCount
] = pUnkSink
;
1086 IUnknown_AddRef(pUnkSink
);
1088 *pdwCookie
= iface
->sinkCount
;
1092 static HRESULT WINAPI
ConPt_Unadvise(
1093 IConnectionPoint
* This
,
1096 ConPt
*iface
= (ConPt
*)This
;
1098 if (dwCookie
> iface
->sinkCount
)
1102 IUnknown_Release(iface
->sink
[dwCookie
-1]);
1103 iface
->sink
[dwCookie
-1] = NULL
;
1108 static HRESULT WINAPI
ConPt_EnumConnections(
1109 IConnectionPoint
* This
,
1110 IEnumConnections
**ppEnum
)
1114 ec
= HeapAlloc(GetProcessHeap(),0,sizeof(EnumCon
));
1115 ec
->vtbl
= &enum_vtbl
;
1117 ec
->pt
= (ConPt
*)This
;
1119 *ppEnum
= (IEnumConnections
*)ec
;
1124 static const IConnectionPointVtbl point_vtbl
= {
1125 ConPt_QueryInterface
,
1129 ConPt_GetConnectionInterface
,
1130 ConPt_GetConnectionPointContainer
,
1133 ConPt_EnumConnections
1136 static HRESULT WINAPI
EnumPt_QueryInterface(
1137 IEnumConnectionPoints
* This
,
1143 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IEnumConnectionPoints
))
1150 IUnknown_AddRef(This
);
1154 trace("no interface\n");
1155 return E_NOINTERFACE
;
1158 static ULONG WINAPI
EnumPt_AddRef(IEnumConnectionPoints
* This
)
1160 EnumPt
*iface
= (EnumPt
*)This
;
1161 return InterlockedIncrement(&iface
->refCount
);
1164 static ULONG WINAPI
EnumPt_Release(IEnumConnectionPoints
* This
)
1166 EnumPt
*iface
= (EnumPt
*)This
;
1169 ret
= InterlockedDecrement(&iface
->refCount
);
1171 HeapFree(GetProcessHeap(),0,This
);
1175 static HRESULT WINAPI
EnumPt_Next(
1176 IEnumConnectionPoints
* This
,
1178 IConnectionPoint
**rgcd
,
1181 EnumPt
*iface
= (EnumPt
*)This
;
1183 if (cConnections
> 0 && iface
->idx
< iface
->container
->ptCount
)
1185 *rgcd
= iface
->container
->pt
[iface
->idx
];
1186 IUnknown_AddRef(iface
->container
->pt
[iface
->idx
]);
1196 static HRESULT WINAPI
EnumPt_Skip(
1197 IEnumConnectionPoints
* This
,
1203 static HRESULT WINAPI
EnumPt_Reset(
1204 IEnumConnectionPoints
* This
)
1209 static HRESULT WINAPI
EnumPt_Clone(
1210 IEnumConnectionPoints
* This
,
1211 IEnumConnectionPoints
**ppEnumPt
)
1216 static const IEnumConnectionPointsVtbl enumpt_vtbl
= {
1218 EnumPt_QueryInterface
,
1227 static HRESULT WINAPI
Contain_QueryInterface(
1228 IConnectionPointContainer
* This
,
1234 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IConnectionPointContainer
))
1241 IUnknown_AddRef(This
);
1245 trace("no interface\n");
1246 return E_NOINTERFACE
;
1249 static ULONG WINAPI
Contain_AddRef(
1250 IConnectionPointContainer
* This
)
1252 Contain
*iface
= (Contain
*)This
;
1253 return InterlockedIncrement(&iface
->refCount
);
1256 static ULONG WINAPI
Contain_Release(
1257 IConnectionPointContainer
* This
)
1259 Contain
*iface
= (Contain
*)This
;
1262 ret
= InterlockedDecrement(&iface
->refCount
);
1265 if (iface
->ptCount
> 0)
1268 for (i
= 0; i
< iface
->ptCount
; i
++)
1269 IUnknown_Release(iface
->pt
[i
]);
1270 HeapFree(GetProcessHeap(),0,iface
->pt
);
1272 HeapFree(GetProcessHeap(),0,This
);
1277 static HRESULT WINAPI
Contain_EnumConnectionPoints(
1278 IConnectionPointContainer
* This
,
1279 IEnumConnectionPoints
**ppEnum
)
1283 ec
= HeapAlloc(GetProcessHeap(),0,sizeof(EnumPt
));
1284 ec
->vtbl
= &enumpt_vtbl
;
1287 ec
->container
= (Contain
*)This
;
1288 *ppEnum
= (IEnumConnectionPoints
*)ec
;
1293 static HRESULT WINAPI
Contain_FindConnectionPoint(
1294 IConnectionPointContainer
* This
,
1296 IConnectionPoint
**ppCP
)
1298 Contain
*iface
= (Contain
*)This
;
1301 if (!IsEqualIID(riid
, &IID_NULL
) || iface
->ptCount
==0)
1303 pt
= HeapAlloc(GetProcessHeap(),0,sizeof(ConPt
));
1304 pt
->vtbl
= &point_vtbl
;
1308 pt
->container
= iface
;
1309 pt
->id
= IID_IDispatch
;
1311 if (iface
->ptCount
== 0)
1312 iface
->pt
=HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown
*));
1314 iface
->pt
= HeapReAlloc(GetProcessHeap(),0,iface
->pt
,sizeof(IUnknown
*)*(iface
->ptCount
+1));
1315 iface
->pt
[iface
->ptCount
] = (IConnectionPoint
*)pt
;
1318 *ppCP
= (IConnectionPoint
*)pt
;
1322 *ppCP
= iface
->pt
[0];
1323 IUnknown_AddRef((IUnknown
*)*ppCP
);
1329 static const IConnectionPointContainerVtbl contain_vtbl
= {
1330 Contain_QueryInterface
,
1334 Contain_EnumConnectionPoints
,
1335 Contain_FindConnectionPoint
1338 static void test_IConnectionPoint(void)
1342 IConnectionPoint
*point
;
1345 DWORD cookie
= 0xffffffff;
1349 if (!pIConnectionPoint_SimpleInvoke
|| !pConnectToConnectionPoint
)
1351 win_skip("IConnectionPoint Apis not present\n");
1355 container
= HeapAlloc(GetProcessHeap(),0,sizeof(Contain
));
1356 container
->vtbl
= &contain_vtbl
;
1357 container
->refCount
= 1;
1358 container
->ptCount
= 0;
1359 container
->pt
= NULL
;
1361 dispatch
= HeapAlloc(GetProcessHeap(),0,sizeof(Disp
));
1362 dispatch
->vtbl
= &disp_vtbl
;
1363 dispatch
->refCount
= 1;
1365 rc
= pConnectToConnectionPoint((IUnknown
*)dispatch
, &IID_NULL
, TRUE
, (IUnknown
*)container
, &cookie
, &point
);
1366 ok(rc
== S_OK
, "pConnectToConnectionPoint failed with %x\n",rc
);
1367 ok(point
!= NULL
, "returned ConnectionPoint is NULL\n");
1368 ok(cookie
!= 0xffffffff, "invalid cookie returned\n");
1370 rc
= pIConnectionPoint_SimpleInvoke(point
,0xa0,NULL
);
1371 ok(rc
== S_OK
, "pConnectToConnectionPoint failed with %x\n",rc
);
1373 if (pSHPackDispParams
)
1375 memset(¶ms
, 0xc0, sizeof(params
));
1376 memset(vars
, 0xc0, sizeof(vars
));
1377 rc
= pSHPackDispParams(¶ms
, vars
, 2, VT_I4
, 0xdeadbeef, VT_BSTR
, 0xdeadcafe);
1378 ok(rc
== S_OK
, "SHPackDispParams failed: %08x\n", rc
);
1380 rc
= pIConnectionPoint_SimpleInvoke(point
,0xa1,¶ms
);
1381 ok(rc
== S_OK
, "pConnectToConnectionPoint failed with %x\n",rc
);
1384 win_skip("pSHPackDispParams not present\n");
1386 rc
= pConnectToConnectionPoint(NULL
, &IID_NULL
, FALSE
, (IUnknown
*)container
, &cookie
, NULL
);
1387 ok(rc
== S_OK
, "pConnectToConnectionPoint failed with %x\n",rc
);
1389 /* MSDN says this should be required but it crashs on XP
1390 IUnknown_Release(point);
1392 ref
= IUnknown_Release((IUnknown
*)container
);
1393 ok(ref
== 0, "leftover IConnectionPointContainer reference %i\n",ref
);
1394 ref
= IUnknown_Release((IUnknown
*)dispatch
);
1395 ok(ref
== 0, "leftover IDispatch reference %i\n",ref
);
1398 typedef struct _propbag
1400 const IPropertyBagVtbl
*vtbl
;
1406 static HRESULT WINAPI
Prop_QueryInterface(
1413 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IPropertyBag
))
1420 IUnknown_AddRef(This
);
1424 trace("no interface\n");
1425 return E_NOINTERFACE
;
1428 static ULONG WINAPI
Prop_AddRef(
1431 PropBag
*iface
= (PropBag
*)This
;
1432 return InterlockedIncrement(&iface
->refCount
);
1435 static ULONG WINAPI
Prop_Release(
1438 PropBag
*iface
= (PropBag
*)This
;
1441 ret
= InterlockedDecrement(&iface
->refCount
);
1443 HeapFree(GetProcessHeap(),0,This
);
1447 static HRESULT WINAPI
Prop_Read(
1449 LPCOLESTR pszPropName
,
1451 IErrorLog
*pErrorLog
)
1453 V_VT(pVar
) = VT_BLOB
|VT_BYREF
;
1454 V_BYREF(pVar
) = (LPVOID
)0xdeadcafe;
1458 static HRESULT WINAPI
Prop_Write(
1460 LPCOLESTR pszPropName
,
1467 static const IPropertyBagVtbl prop_vtbl
= {
1468 Prop_QueryInterface
,
1476 static void test_SHPropertyBag_ReadLONG(void)
1481 static const WCHAR szName1
[] = {'n','a','m','e','1',0};
1483 if (!pSHPropertyBag_ReadLONG
)
1485 win_skip("SHPropertyBag_ReadLONG not present\n");
1489 pb
= HeapAlloc(GetProcessHeap(),0,sizeof(PropBag
));
1491 pb
->vtbl
= &prop_vtbl
;
1494 rc
= pSHPropertyBag_ReadLONG(NULL
, szName1
, &out
);
1495 ok(rc
== E_INVALIDARG
|| broken(rc
== 0), "incorrect return %x\n",rc
);
1496 ok(out
== 0xfeedface, "value should not have changed\n");
1497 rc
= pSHPropertyBag_ReadLONG((IPropertyBag
*)pb
, NULL
, &out
);
1498 ok(rc
== E_INVALIDARG
|| broken(rc
== 0) || broken(rc
== 1), "incorrect return %x\n",rc
);
1499 ok(out
== 0xfeedface, "value should not have changed\n");
1500 rc
= pSHPropertyBag_ReadLONG((IPropertyBag
*)pb
, szName1
, NULL
);
1501 ok(rc
== E_INVALIDARG
|| broken(rc
== 0) || broken(rc
== 1), "incorrect return %x\n",rc
);
1502 ok(out
== 0xfeedface, "value should not have changed\n");
1503 rc
= pSHPropertyBag_ReadLONG((IPropertyBag
*)pb
, szName1
, &out
);
1504 ok(rc
== DISP_E_BADVARTYPE
|| broken(rc
== 0) || broken(rc
== 1), "incorrect return %x\n",rc
);
1505 ok(out
== 0xfeedface || broken(out
== 0xfeedfa00), "value should not have changed %x\n",out
);
1506 IUnknown_Release((IUnknown
*)pb
);
1511 static void test_SHSetWindowBits(void)
1514 DWORD style
, styleold
;
1517 if(!pSHSetWindowBits
)
1519 win_skip("SHSetWindowBits is not available\n");
1524 clsA
.lpfnWndProc
= DefWindowProcA
;
1525 clsA
.cbClsExtra
= 0;
1526 clsA
.cbWndExtra
= 0;
1527 clsA
.hInstance
= GetModuleHandleA(NULL
);
1529 clsA
.hCursor
= LoadCursorA(0, IDC_ARROW
);
1530 clsA
.hbrBackground
= NULL
;
1531 clsA
.lpszMenuName
= NULL
;
1532 clsA
.lpszClassName
= "Shlwapi test class";
1533 RegisterClassA(&clsA
);
1535 hwnd
= CreateWindowA("Shlwapi test class", "Test", WS_VISIBLE
, 0, 0, 100, 100,
1536 NULL
, NULL
, GetModuleHandle(NULL
), 0);
1537 ok(IsWindow(hwnd
), "failed to create window\n");
1540 SetLastError(0xdeadbeef);
1541 style
= pSHSetWindowBits(NULL
, GWL_STYLE
, 0, 0);
1542 ok(style
== 0, "expected 0 retval, got %d\n", style
);
1543 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
||
1544 broken(GetLastError() == 0xdeadbeef), /* Win9x/WinMe */
1545 "expected ERROR_INVALID_WINDOW_HANDLE, got %d\n", GetLastError());
1547 /* zero mask, zero flags */
1548 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1549 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, 0, 0);
1550 ok(styleold
== style
, "expected old style\n");
1551 ok(styleold
== GetWindowLongA(hwnd
, GWL_STYLE
), "expected to keep old style\n");
1554 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1555 ok(styleold
& WS_VISIBLE
, "expected WS_VISIBLE\n");
1556 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, WS_VISIBLE
, 0);
1558 ok(style
== styleold
, "expected previous style, got %x\n", style
);
1559 ok((GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
) == 0, "expected updated style\n");
1561 /* test mask, unset style bit used */
1562 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1563 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, WS_VISIBLE
, 0);
1564 ok(style
== styleold
, "expected previous style, got %x\n", style
);
1565 ok(styleold
== GetWindowLongA(hwnd
, GWL_STYLE
), "expected to keep old style\n");
1567 /* set back with flags */
1568 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1569 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, WS_VISIBLE
, WS_VISIBLE
);
1570 ok(style
== styleold
, "expected previous style, got %x\n", style
);
1571 ok(GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
, "expected updated style\n");
1573 /* reset and try to set without a mask */
1574 pSHSetWindowBits(hwnd
, GWL_STYLE
, WS_VISIBLE
, 0);
1575 ok((GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
) == 0, "expected updated style\n");
1576 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1577 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, 0, WS_VISIBLE
);
1578 ok(style
== styleold
, "expected previous style, got %x\n", style
);
1579 ok((GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
) == 0, "expected updated style\n");
1581 DestroyWindow(hwnd
);
1583 UnregisterClassA("Shlwapi test class", GetModuleHandleA(NULL
));
1586 static void test_SHFormatDateTimeA(void)
1588 FILETIME UNALIGNED filetime
;
1589 CHAR buff
[100], buff2
[100], buff3
[100];
1594 if(!pSHFormatDateTimeA
)
1596 win_skip("pSHFormatDateTimeA isn't available\n");
1602 /* crashes on native */
1603 ret
= pSHFormatDateTimeA(NULL
, NULL
, NULL
, 0);
1607 SystemTimeToFileTime(&st
, &filetime
);
1608 /* SHFormatDateTime expects input as utc */
1609 LocalFileTimeToFileTime(&filetime
, &filetime
);
1611 /* no way to get required buffer length here */
1612 SetLastError(0xdeadbeef);
1613 ret
= pSHFormatDateTimeA(&filetime
, NULL
, NULL
, 0);
1614 ok(ret
== 0, "got %d\n", ret
);
1615 ok(GetLastError() == 0xdeadbeef || broken(GetLastError() == ERROR_SUCCESS
/* Win7 */),
1616 "expected 0xdeadbeef, got %d\n", GetLastError());
1618 SetLastError(0xdeadbeef);
1619 buff
[0] = 'a'; buff
[1] = 0;
1620 ret
= pSHFormatDateTimeA(&filetime
, NULL
, buff
, 0);
1621 ok(ret
== 0, "got %d\n", ret
);
1622 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1623 ok(buff
[0] == 'a', "expected same string, got %s\n", buff
);
1625 /* flags needs to have FDTF_NOAUTOREADINGORDER for these tests to succeed on Vista+ */
1627 /* all combinations documented as invalid succeeded */
1628 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTTIME
| FDTF_LONGTIME
;
1629 SetLastError(0xdeadbeef);
1630 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1631 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1632 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1634 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTDATE
| FDTF_LONGDATE
;
1635 SetLastError(0xdeadbeef);
1636 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1637 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1638 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1640 flags
= FDTF_SHORTDATE
| FDTF_LTRDATE
| FDTF_RTLDATE
;
1641 SetLastError(0xdeadbeef);
1642 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1643 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1644 ok(GetLastError() == 0xdeadbeef ||
1645 broken(GetLastError() == ERROR_INVALID_FLAGS
), /* Win9x/WinMe */
1646 "expected 0xdeadbeef, got %d\n", GetLastError());
1648 /* now check returned strings */
1649 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTTIME
;
1650 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1651 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1652 ret
= GetTimeFormat(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff2
, sizeof(buff2
));
1653 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1654 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1656 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGTIME
;
1657 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1658 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1659 ret
= GetTimeFormat(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff2
, sizeof(buff2
));
1660 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1661 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1663 /* both time flags */
1664 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGTIME
| FDTF_SHORTTIME
;
1665 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1666 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1667 ret
= GetTimeFormat(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff2
, sizeof(buff2
));
1668 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1669 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1671 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTDATE
;
1672 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1673 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1674 ret
= GetDateFormat(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1675 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1676 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1678 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGDATE
;
1679 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1680 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1681 ret
= GetDateFormat(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1682 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1683 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1685 /* both date flags */
1686 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGDATE
| FDTF_SHORTDATE
;
1687 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1688 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1689 ret
= GetDateFormat(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1690 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1691 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1693 /* various combinations of date/time flags */
1694 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGDATE
| FDTF_SHORTTIME
;
1695 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1696 ok(ret
== lstrlenA(buff
)+1, "got %d, length %d\n", ret
, lstrlenA(buff
)+1);
1697 ret
= GetDateFormat(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1698 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1699 strcat(buff2
, ", ");
1700 ret
= GetTimeFormat(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff3
, sizeof(buff3
));
1701 ok(ret
== lstrlenA(buff3
)+1, "got %d\n", ret
);
1702 strcat(buff2
, buff3
);
1703 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1705 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGDATE
| FDTF_LONGTIME
;
1706 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1707 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1708 ret
= GetDateFormat(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1709 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1710 strcat(buff2
, ", ");
1711 ret
= GetTimeFormat(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff3
, sizeof(buff3
));
1712 ok(ret
== lstrlenA(buff3
)+1, "got %d\n", ret
);
1713 strcat(buff2
, buff3
);
1714 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1716 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTDATE
| FDTF_SHORTTIME
;
1717 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1718 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1719 ret
= GetDateFormat(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1720 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1722 ret
= GetTimeFormat(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff3
, sizeof(buff3
));
1723 ok(ret
== lstrlenA(buff3
)+1, "got %d\n", ret
);
1724 strcat(buff2
, buff3
);
1725 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1727 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTDATE
| FDTF_LONGTIME
;
1728 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1729 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1730 ret
= GetDateFormat(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1731 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1733 ret
= GetTimeFormat(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff3
, sizeof(buff3
));
1734 ok(ret
== lstrlenA(buff3
)+1, "got %d\n", ret
);
1735 strcat(buff2
, buff3
);
1736 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1739 static void test_SHFormatDateTimeW(void)
1741 FILETIME UNALIGNED filetime
;
1742 WCHAR buff
[100], buff2
[100], buff3
[100];
1746 static const WCHAR spaceW
[] = {' ',0};
1747 static const WCHAR commaW
[] = {',',' ',0};
1749 if(!pSHFormatDateTimeW
)
1751 win_skip("pSHFormatDateTimeW isn't available\n");
1757 /* crashes on native */
1758 ret
= pSHFormatDateTimeW(NULL
, NULL
, NULL
, 0);
1762 SystemTimeToFileTime(&st
, &filetime
);
1763 /* SHFormatDateTime expects input as utc */
1764 LocalFileTimeToFileTime(&filetime
, &filetime
);
1766 /* no way to get required buffer length here */
1767 SetLastError(0xdeadbeef);
1768 ret
= pSHFormatDateTimeW(&filetime
, NULL
, NULL
, 0);
1769 ok(ret
== 0, "got %d\n", ret
);
1770 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1772 SetLastError(0xdeadbeef);
1773 buff
[0] = 'a'; buff
[1] = 0;
1774 ret
= pSHFormatDateTimeW(&filetime
, NULL
, buff
, 0);
1775 ok(ret
== 0, "got %d\n", ret
);
1776 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1777 ok(buff
[0] == 'a', "expected same string\n");
1779 /* all combinations documented as invalid succeeded */
1780 flags
= FDTF_SHORTTIME
| FDTF_LONGTIME
;
1781 SetLastError(0xdeadbeef);
1782 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1783 ok(ret
== lstrlenW(buff
)+1, "got %d\n", ret
);
1784 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1786 flags
= FDTF_SHORTDATE
| FDTF_LONGDATE
;
1787 SetLastError(0xdeadbeef);
1788 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1789 ok(ret
== lstrlenW(buff
)+1, "got %d\n", ret
);
1790 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1792 flags
= FDTF_SHORTDATE
| FDTF_LTRDATE
| FDTF_RTLDATE
;
1793 SetLastError(0xdeadbeef);
1794 buff
[0] = 0; /* NT4 doesn't clear the buffer on failure */
1795 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1796 ok(ret
== lstrlenW(buff
)+1, "got %d\n", ret
);
1797 ok(GetLastError() == 0xdeadbeef ||
1798 broken(GetLastError() == ERROR_INVALID_FLAGS
), /* Win9x/WinMe/NT4 */
1799 "expected 0xdeadbeef, got %d\n", GetLastError());
1801 /* now check returned strings */
1802 flags
= FDTF_SHORTTIME
;
1803 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1804 ok(ret
== lstrlenW(buff
)+1, "got %d\n", ret
);
1805 SetLastError(0xdeadbeef);
1806 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1807 if (ret
== 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
1809 win_skip("Needed W-functions are not implemented\n");
1812 ok(ret
== lstrlenW(buff2
)+1, "got %d\n", ret
);
1813 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1815 flags
= FDTF_LONGTIME
;
1816 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1817 ok(ret
== lstrlenW(buff
)+1, "got %d\n", ret
);
1818 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1819 ok(ret
== lstrlenW(buff2
)+1, "got %d\n", ret
);
1820 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1822 /* both time flags */
1823 flags
= FDTF_LONGTIME
| FDTF_SHORTTIME
;
1824 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1825 ok(ret
== lstrlenW(buff
)+1, "got %d\n", ret
);
1826 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1827 ok(ret
== lstrlenW(buff2
)+1, "got %d\n", ret
);
1828 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal string\n");
1830 flags
= FDTF_SHORTDATE
;
1831 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1832 ok(ret
== lstrlenW(buff
)+1, "got %d\n", ret
);
1833 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1834 ok(ret
== lstrlenW(buff2
)+1, "got %d\n", ret
);
1835 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1837 flags
= FDTF_LONGDATE
;
1838 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1839 ok(ret
== lstrlenW(buff
)+1, "got %d\n", ret
);
1840 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1841 ok(ret
== lstrlenW(buff2
)+1, "got %d\n", ret
);
1842 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1844 /* both date flags */
1845 flags
= FDTF_LONGDATE
| FDTF_SHORTDATE
;
1846 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1847 ok(ret
== lstrlenW(buff
)+1, "got %d\n", ret
);
1848 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1849 ok(ret
== lstrlenW(buff2
)+1, "got %d\n", ret
);
1850 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1852 /* various combinations of date/time flags */
1853 flags
= FDTF_LONGDATE
| FDTF_SHORTTIME
;
1854 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1855 ok(ret
== lstrlenW(buff
)+1, "got %d, length %d\n", ret
, lstrlenW(buff
)+1);
1856 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1857 ok(ret
== lstrlenW(buff2
)+1, "got %d\n", ret
);
1858 lstrcatW(buff2
, commaW
);
1859 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff3
, sizeof(buff3
)/sizeof(WCHAR
));
1860 ok(ret
== lstrlenW(buff3
)+1, "got %d\n", ret
);
1861 lstrcatW(buff2
, buff3
);
1862 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1864 flags
= FDTF_LONGDATE
| FDTF_LONGTIME
;
1865 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1866 ok(ret
== lstrlenW(buff
)+1, "got %d\n", ret
);
1867 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1868 ok(ret
== lstrlenW(buff2
)+1, "got %d\n", ret
);
1869 lstrcatW(buff2
, commaW
);
1870 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff3
, sizeof(buff3
)/sizeof(WCHAR
));
1871 ok(ret
== lstrlenW(buff3
)+1, "got %d\n", ret
);
1872 lstrcatW(buff2
, buff3
);
1873 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1875 flags
= FDTF_SHORTDATE
| FDTF_SHORTTIME
;
1876 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1877 ok(ret
== lstrlenW(buff
)+1, "got %d\n", ret
);
1878 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1879 ok(ret
== lstrlenW(buff2
)+1, "got %d\n", ret
);
1880 lstrcatW(buff2
, spaceW
);
1881 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff3
, sizeof(buff3
)/sizeof(WCHAR
));
1882 ok(ret
== lstrlenW(buff3
)+1, "got %d\n", ret
);
1883 lstrcatW(buff2
, buff3
);
1884 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1886 flags
= FDTF_SHORTDATE
| FDTF_LONGTIME
;
1887 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1888 ok(ret
== lstrlenW(buff
)+1, "got %d\n", ret
);
1889 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1890 ok(ret
== lstrlenW(buff2
)+1, "got %d\n", ret
);
1891 lstrcatW(buff2
, spaceW
);
1892 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff3
, sizeof(buff3
)/sizeof(WCHAR
));
1893 ok(ret
== lstrlenW(buff3
)+1, "got %d\n", ret
);
1894 lstrcatW(buff2
, buff3
);
1895 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1898 static void test_SHGetObjectCompatFlags(void)
1900 struct compat_value
{
1905 struct compat_value values
[] = {
1906 { "OTNEEDSSFCACHE", 0x1 },
1907 { "NO_WEBVIEW", 0x2 },
1908 { "UNBINDABLE", 0x4 },
1910 { "NEEDSFILESYSANCESTOR", 0x10 },
1911 { "NOTAFILESYSTEM", 0x20 },
1912 { "CTXMENU_NOVERBS", 0x40 },
1913 { "CTXMENU_LIMITEDQI", 0x80 },
1914 { "COCREATESHELLFOLDERONLY", 0x100 },
1915 { "NEEDSSTORAGEANCESTOR", 0x200 },
1916 { "NOLEGACYWEBVIEW", 0x400 },
1917 { "CTXMENU_XPQCMFLAGS", 0x1000 },
1918 { "NOIPROPERTYSTORE", 0x2000 }
1921 static const char compat_path
[] = "Software\\Microsoft\\Windows\\CurrentVersion\\ShellCompatibility\\Objects";
1922 void *pColorAdjustLuma
= GetProcAddress(hShlwapi
, "ColorAdjustLuma");
1923 CHAR keyA
[39]; /* {CLSID} */
1928 if (!pSHGetObjectCompatFlags
)
1930 win_skip("SHGetObjectCompatFlags isn't available\n");
1934 if (pColorAdjustLuma
&& pColorAdjustLuma
== pSHGetObjectCompatFlags
) /* win2k */
1936 win_skip("Skipping SHGetObjectCompatFlags, same ordinal used for ColorAdjustLuma\n");
1941 ret
= pSHGetObjectCompatFlags(NULL
, NULL
);
1942 ok(ret
== 0, "got %d\n", ret
);
1944 ret
= RegOpenKeyA(HKEY_LOCAL_MACHINE
, compat_path
, &root
);
1945 if (ret
!= ERROR_SUCCESS
)
1947 skip("No compatibility class data found\n");
1951 for (i
= 0; RegEnumKeyA(root
, i
, keyA
, sizeof(keyA
)) == ERROR_SUCCESS
; i
++)
1955 if (RegOpenKeyA(root
, keyA
, &clsid_key
) == ERROR_SUCCESS
)
1958 DWORD expected
= 0, got
, length
= sizeof(valueA
);
1962 for (v
= 0; RegEnumValueA(clsid_key
, v
, valueA
, &length
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
; v
++)
1966 for (j
= 0; j
< sizeof(values
)/sizeof(struct compat_value
); j
++)
1967 if (lstrcmpA(values
[j
].nameA
, valueA
) == 0)
1969 expected
|= values
[j
].value
;
1973 length
= sizeof(valueA
);
1976 pGUIDFromStringA(keyA
, &clsid
);
1977 got
= pSHGetObjectCompatFlags(NULL
, &clsid
);
1978 ok(got
== expected
, "got 0x%08x, expected 0x%08x. Key %s\n", got
, expected
, keyA
);
1980 RegCloseKey(clsid_key
);
1988 const IOleCommandTargetVtbl
*lpVtbl
;
1990 } IOleCommandTargetImpl
;
1992 static const IOleCommandTargetVtbl IOleCommandTargetImpl_Vtbl
;
1994 static IOleCommandTarget
* IOleCommandTargetImpl_Construct(void)
1996 IOleCommandTargetImpl
*obj
;
1998 obj
= HeapAlloc(GetProcessHeap(), 0, sizeof(*obj
));
1999 obj
->lpVtbl
= &IOleCommandTargetImpl_Vtbl
;
2002 return (IOleCommandTarget
*)obj
;
2005 static HRESULT WINAPI
IOleCommandTargetImpl_QueryInterface(IOleCommandTarget
*iface
, REFIID riid
, void **ppvObj
)
2007 IOleCommandTargetImpl
*This
= (IOleCommandTargetImpl
*)iface
;
2009 if (IsEqualIID(riid
, &IID_IUnknown
) ||
2010 IsEqualIID(riid
, &IID_IOleCommandTarget
))
2017 IUnknown_AddRef(iface
);
2021 return E_NOINTERFACE
;
2024 static ULONG WINAPI
IOleCommandTargetImpl_AddRef(IOleCommandTarget
*iface
)
2026 IOleCommandTargetImpl
*This
= (IOleCommandTargetImpl
*)iface
;
2027 return InterlockedIncrement(&This
->ref
);
2030 static ULONG WINAPI
IOleCommandTargetImpl_Release(IOleCommandTarget
*iface
)
2032 IOleCommandTargetImpl
*This
= (IOleCommandTargetImpl
*)iface
;
2033 ULONG ref
= InterlockedDecrement(&This
->ref
);
2037 HeapFree(GetProcessHeap(), 0, This
);
2043 static HRESULT WINAPI
IOleCommandTargetImpl_QueryStatus(
2044 IOleCommandTarget
*iface
, const GUID
*group
, ULONG cCmds
, OLECMD prgCmds
[], OLECMDTEXT
*pCmdText
)
2049 static HRESULT WINAPI
IOleCommandTargetImpl_Exec(
2050 IOleCommandTarget
*iface
,
2051 const GUID
*CmdGroup
,
2057 add_call(&trace_got
, 3, CmdGroup
, (void*)(DWORD_PTR
)nCmdID
, (void*)(DWORD_PTR
)nCmdexecopt
, pvaIn
, pvaOut
);
2061 static const IOleCommandTargetVtbl IOleCommandTargetImpl_Vtbl
=
2063 IOleCommandTargetImpl_QueryInterface
,
2064 IOleCommandTargetImpl_AddRef
,
2065 IOleCommandTargetImpl_Release
,
2066 IOleCommandTargetImpl_QueryStatus
,
2067 IOleCommandTargetImpl_Exec
2071 const IServiceProviderVtbl
*lpVtbl
;
2073 } IServiceProviderImpl
;
2076 const IProfferServiceVtbl
*lpVtbl
;
2078 } IProfferServiceImpl
;
2081 static const IServiceProviderVtbl IServiceProviderImpl_Vtbl
;
2082 static const IProfferServiceVtbl IProfferServiceImpl_Vtbl
;
2084 static IServiceProvider
* IServiceProviderImpl_Construct(void)
2086 IServiceProviderImpl
*obj
;
2088 obj
= HeapAlloc(GetProcessHeap(), 0, sizeof(*obj
));
2089 obj
->lpVtbl
= &IServiceProviderImpl_Vtbl
;
2092 return (IServiceProvider
*)obj
;
2095 static IProfferService
* IProfferServiceImpl_Construct(void)
2097 IProfferServiceImpl
*obj
;
2099 obj
= HeapAlloc(GetProcessHeap(), 0, sizeof(*obj
));
2100 obj
->lpVtbl
= &IProfferServiceImpl_Vtbl
;
2103 return (IProfferService
*)obj
;
2106 static HRESULT WINAPI
IServiceProviderImpl_QueryInterface(IServiceProvider
*iface
, REFIID riid
, void **ppvObj
)
2108 IServiceProviderImpl
*This
= (IServiceProviderImpl
*)iface
;
2110 if (IsEqualIID(riid
, &IID_IUnknown
) ||
2111 IsEqualIID(riid
, &IID_IServiceProvider
))
2118 IUnknown_AddRef(iface
);
2119 /* native uses redefined IID_IServiceProvider symbol, so we can't compare pointers */
2120 if (IsEqualIID(riid
, &IID_IServiceProvider
))
2121 add_call(&trace_got
, 1, iface
, &IID_IServiceProvider
, 0, 0, 0);
2125 return E_NOINTERFACE
;
2128 static ULONG WINAPI
IServiceProviderImpl_AddRef(IServiceProvider
*iface
)
2130 IServiceProviderImpl
*This
= (IServiceProviderImpl
*)iface
;
2131 return InterlockedIncrement(&This
->ref
);
2134 static ULONG WINAPI
IServiceProviderImpl_Release(IServiceProvider
*iface
)
2136 IServiceProviderImpl
*This
= (IServiceProviderImpl
*)iface
;
2137 ULONG ref
= InterlockedDecrement(&This
->ref
);
2141 HeapFree(GetProcessHeap(), 0, This
);
2147 static HRESULT WINAPI
IServiceProviderImpl_QueryService(
2148 IServiceProvider
*iface
, REFGUID service
, REFIID riid
, void **ppv
)
2150 /* native uses redefined pointer for IID_IOleCommandTarget, not one from uuid.lib */
2151 if (IsEqualIID(riid
, &IID_IOleCommandTarget
))
2153 add_call(&trace_got
, 2, iface
, service
, &IID_IOleCommandTarget
, 0, 0);
2154 *ppv
= IOleCommandTargetImpl_Construct();
2156 if (IsEqualIID(riid
, &IID_IProfferService
))
2158 if (IsEqualIID(service
, &IID_IProfferService
))
2159 add_call(&trace_got
, 2, &IID_IProfferService
, &IID_IProfferService
, 0, 0, 0);
2160 *ppv
= IProfferServiceImpl_Construct();
2165 static const IServiceProviderVtbl IServiceProviderImpl_Vtbl
=
2167 IServiceProviderImpl_QueryInterface
,
2168 IServiceProviderImpl_AddRef
,
2169 IServiceProviderImpl_Release
,
2170 IServiceProviderImpl_QueryService
2173 static void test_IUnknown_QueryServiceExec(void)
2175 IServiceProvider
*provider
= IServiceProviderImpl_Construct();
2176 static const GUID dummy_serviceid
= { 0xdeadbeef };
2177 static const GUID dummy_groupid
= { 0xbeefbeef };
2178 call_trace_t trace_expected
;
2181 /* on <=W2K platforms same ordinal used for another export with different
2182 prototype, so skipping using this indirect condition */
2183 if (is_win2k_and_lower
)
2185 win_skip("IUnknown_QueryServiceExec is not available\n");
2189 /* null source pointer */
2190 hr
= pIUnknown_QueryServiceExec(NULL
, &dummy_serviceid
, &dummy_groupid
, 0, 0, 0, 0);
2191 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
2194 IUnknown_QueryServiceExec( ptr1, serviceid, groupid, arg1, arg2, arg3, arg4);
2195 -> IUnknown_QueryInterface( ptr1, &IID_IServiceProvider, &prov );
2196 -> IServiceProvider_QueryService( prov, serviceid, &IID_IOleCommandTarget, &obj );
2197 -> IOleCommandTarget_Exec( obj, groupid, arg1, arg2, arg3, arg4 );
2199 init_call_trace(&trace_expected
);
2201 add_call(&trace_expected
, 1, provider
, &IID_IServiceProvider
, 0, 0, 0);
2202 add_call(&trace_expected
, 2, provider
, &dummy_serviceid
, &IID_IOleCommandTarget
, 0, 0);
2203 add_call(&trace_expected
, 3, &dummy_groupid
, (void*)0x1, (void*)0x2, (void*)0x3, (void*)0x4);
2205 init_call_trace(&trace_got
);
2206 hr
= pIUnknown_QueryServiceExec((IUnknown
*)provider
, &dummy_serviceid
, &dummy_groupid
, 0x1, 0x2, (void*)0x3, (void*)0x4);
2207 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2209 ok_trace(&trace_expected
, &trace_got
);
2211 free_call_trace(&trace_expected
);
2212 free_call_trace(&trace_got
);
2214 IServiceProvider_Release(provider
);
2218 static HRESULT WINAPI
IProfferServiceImpl_QueryInterface(IProfferService
*iface
, REFIID riid
, void **ppvObj
)
2220 IProfferServiceImpl
*This
= (IProfferServiceImpl
*)iface
;
2222 if (IsEqualIID(riid
, &IID_IUnknown
) ||
2223 IsEqualIID(riid
, &IID_IProfferService
))
2227 else if (IsEqualIID(riid
, &IID_IServiceProvider
))
2229 *ppvObj
= IServiceProviderImpl_Construct();
2230 add_call(&trace_got
, 1, iface
, &IID_IServiceProvider
, 0, 0, 0);
2236 IUnknown_AddRef(iface
);
2240 return E_NOINTERFACE
;
2243 static ULONG WINAPI
IProfferServiceImpl_AddRef(IProfferService
*iface
)
2245 IProfferServiceImpl
*This
= (IProfferServiceImpl
*)iface
;
2246 return InterlockedIncrement(&This
->ref
);
2249 static ULONG WINAPI
IProfferServiceImpl_Release(IProfferService
*iface
)
2251 IProfferServiceImpl
*This
= (IProfferServiceImpl
*)iface
;
2252 ULONG ref
= InterlockedDecrement(&This
->ref
);
2256 HeapFree(GetProcessHeap(), 0, This
);
2262 static HRESULT WINAPI
IProfferServiceImpl_ProfferService(IProfferService
*iface
,
2263 REFGUID service
, IServiceProvider
*pService
, DWORD
*pCookie
)
2265 add_call(&trace_got
, 3, service
, pService
, pCookie
, 0, 0);
2269 static HRESULT WINAPI
IProfferServiceImpl_RevokeService(IProfferService
*iface
, DWORD cookie
)
2271 add_call(&trace_got
, 4, (void*)(DWORD_PTR
)cookie
, 0, 0, 0, 0);
2275 static const IProfferServiceVtbl IProfferServiceImpl_Vtbl
=
2277 IProfferServiceImpl_QueryInterface
,
2278 IProfferServiceImpl_AddRef
,
2279 IProfferServiceImpl_Release
,
2280 IProfferServiceImpl_ProfferService
,
2281 IProfferServiceImpl_RevokeService
2284 static void test_IUnknown_ProfferService(void)
2286 IServiceProvider
*provider
= IServiceProviderImpl_Construct();
2287 IProfferService
*proff
= IProfferServiceImpl_Construct();
2288 static const GUID dummy_serviceid
= { 0xdeadbeef };
2289 call_trace_t trace_expected
;
2293 /* on <=W2K platforms same ordinal used for another export with different
2294 prototype, so skipping using this indirect condition */
2295 if (is_win2k_and_lower
)
2297 win_skip("IUnknown_ProfferService is not available\n");
2301 /* null source pointer */
2302 hr
= pIUnknown_ProfferService(NULL
, &dummy_serviceid
, 0, 0);
2303 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
2306 IUnknown_ProfferService( ptr1, serviceid, arg1, arg2);
2307 -> IUnknown_QueryInterface( ptr1, &IID_IServiceProvider, &provider );
2308 -> IServiceProvider_QueryService( provider, &IID_IProfferService, &IID_IProfferService, &proffer );
2310 if (service pointer not null):
2311 -> IProfferService_ProfferService( proffer, serviceid, arg1, arg2 );
2313 -> IProfferService_RevokeService( proffer, *arg2 );
2315 init_call_trace(&trace_expected
);
2317 add_call(&trace_expected
, 1, proff
, &IID_IServiceProvider
, 0, 0, 0);
2318 add_call(&trace_expected
, 2, &IID_IProfferService
, &IID_IProfferService
, 0, 0, 0);
2319 add_call(&trace_expected
, 3, &dummy_serviceid
, provider
, &cookie
, 0, 0);
2321 init_call_trace(&trace_got
);
2322 hr
= pIUnknown_ProfferService((IUnknown
*)proff
, &dummy_serviceid
, provider
, &cookie
);
2323 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2325 ok_trace(&trace_expected
, &trace_got
);
2326 free_call_trace(&trace_got
);
2327 free_call_trace(&trace_expected
);
2329 /* same with ::Revoke path */
2330 init_call_trace(&trace_expected
);
2332 add_call(&trace_expected
, 1, proff
, &IID_IServiceProvider
, 0, 0, 0);
2333 add_call(&trace_expected
, 2, &IID_IProfferService
, &IID_IProfferService
, 0, 0, 0);
2334 add_call(&trace_expected
, 4, (void*)(DWORD_PTR
)cookie
, 0, 0, 0, 0);
2336 init_call_trace(&trace_got
);
2337 hr
= pIUnknown_ProfferService((IUnknown
*)proff
, &dummy_serviceid
, 0, &cookie
);
2338 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2339 ok_trace(&trace_expected
, &trace_got
);
2340 free_call_trace(&trace_got
);
2341 free_call_trace(&trace_expected
);
2343 IServiceProvider_Release(provider
);
2344 IProfferService_Release(proff
);
2347 static void test_SHCreateWorkerWindowA(void)
2355 if (is_win2k_and_lower
)
2357 win_skip("SHCreateWorkerWindowA not available\n");
2361 hwnd
= pSHCreateWorkerWindowA(0, NULL
, 0, 0, 0, 0);
2362 ok(hwnd
!= 0, "expected window\n");
2364 GetClassName(hwnd
, classA
, 20);
2365 ok(lstrcmpA(classA
, "WorkerA") == 0, "expected WorkerA class, got %s\n", classA
);
2367 ret
= GetWindowLongPtrA(hwnd
, 0);
2368 ok(ret
== 0, "got %ld\n", ret
);
2371 memset(&cliA
, 0, sizeof(cliA
));
2372 res
= GetClassInfoA(GetModuleHandle("shlwapi.dll"), "WorkerA", &cliA
);
2373 ok(res
, "failed to get class info\n");
2374 ok(cliA
.style
== 0, "got 0x%08x\n", cliA
.style
);
2375 ok(cliA
.cbClsExtra
== 0, "got %d\n", cliA
.cbClsExtra
);
2376 ok(cliA
.cbWndExtra
== sizeof(LONG_PTR
), "got %d\n", cliA
.cbWndExtra
);
2377 ok(cliA
.lpszMenuName
== 0, "got %s\n", cliA
.lpszMenuName
);
2379 DestroyWindow(hwnd
);
2381 /* set extra bytes */
2382 hwnd
= pSHCreateWorkerWindowA(0, NULL
, 0, 0, 0, 0xdeadbeef);
2383 ok(hwnd
!= 0, "expected window\n");
2385 GetClassName(hwnd
, classA
, 20);
2386 ok(lstrcmpA(classA
, "WorkerA") == 0, "expected WorkerA class, got %s\n", classA
);
2388 ret
= GetWindowLongPtrA(hwnd
, 0);
2389 ok(ret
== 0xdeadbeef, "got %ld\n", ret
);
2392 ret
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
2393 ok(ret
== WS_EX_WINDOWEDGE
||
2394 ret
== (WS_EX_WINDOWEDGE
|WS_EX_LAYOUTRTL
) /* systems with RTL locale */, "0x%08lx\n", ret
);
2396 DestroyWindow(hwnd
);
2398 hwnd
= pSHCreateWorkerWindowA(0, NULL
, WS_EX_TOOLWINDOW
, 0, 0, 0);
2399 ret
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
2400 ok(ret
== (WS_EX_WINDOWEDGE
|WS_EX_TOOLWINDOW
) ||
2401 ret
== (WS_EX_WINDOWEDGE
|WS_EX_TOOLWINDOW
|WS_EX_LAYOUTRTL
) /* systems with RTL locale */, "0x%08lx\n", ret
);
2402 DestroyWindow(hwnd
);
2405 static HRESULT WINAPI
SF_QueryInterface(IShellFolder
*iface
,
2406 REFIID riid
, void **ppv
)
2408 /* SHIShellFolder_EnumObjects doesn't QI the object for IShellFolder */
2409 ok(!IsEqualGUID(&IID_IShellFolder
, riid
),
2410 "Unexpected QI for IShellFolder\n");
2411 return E_NOINTERFACE
;
2414 static ULONG WINAPI
SF_AddRef(IShellFolder
*iface
)
2419 static ULONG WINAPI
SF_Release(IShellFolder
*iface
)
2424 static HRESULT WINAPI
SF_ParseDisplayName(IShellFolder
*iface
,
2425 HWND owner
, LPBC reserved
, LPOLESTR displayName
, ULONG
*eaten
,
2426 LPITEMIDLIST
*idl
, ULONG
*attr
)
2428 ok(0, "Didn't expect ParseDisplayName\n");
2432 static HRESULT WINAPI
SF_EnumObjects(IShellFolder
*iface
,
2433 HWND owner
, SHCONTF flags
, IEnumIDList
**enm
)
2435 *enm
= (IEnumIDList
*)0xcafebabe;
2439 static HRESULT WINAPI
SF_BindToObject(IShellFolder
*iface
,
2440 LPCITEMIDLIST idl
, LPBC reserved
, REFIID riid
, void **obj
)
2442 ok(0, "Didn't expect BindToObject\n");
2446 static HRESULT WINAPI
SF_BindToStorage(IShellFolder
*iface
,
2447 LPCITEMIDLIST idl
, LPBC reserved
, REFIID riid
, void **obj
)
2449 ok(0, "Didn't expect BindToStorage\n");
2453 static HRESULT WINAPI
SF_CompareIDs(IShellFolder
*iface
,
2454 LPARAM lparam
, LPCITEMIDLIST idl1
, LPCITEMIDLIST idl2
)
2456 ok(0, "Didn't expect CompareIDs\n");
2460 static HRESULT WINAPI
SF_CreateViewObject(IShellFolder
*iface
,
2461 HWND owner
, REFIID riid
, void **out
)
2463 ok(0, "Didn't expect CreateViewObject\n");
2467 static HRESULT WINAPI
SF_GetAttributesOf(IShellFolder
*iface
,
2468 UINT cidl
, LPCITEMIDLIST
*idl
, SFGAOF
*inOut
)
2470 ok(0, "Didn't expect GetAttributesOf\n");
2474 static HRESULT WINAPI
SF_GetUIObjectOf(IShellFolder
*iface
,
2475 HWND owner
, UINT cidl
, LPCITEMIDLIST
*idls
, REFIID riid
, UINT
*inOut
,
2478 ok(0, "Didn't expect GetUIObjectOf\n");
2482 static HRESULT WINAPI
SF_GetDisplayNameOf(IShellFolder
*iface
,
2483 LPCITEMIDLIST idl
, SHGDNF flags
, STRRET
*name
)
2485 ok(0, "Didn't expect GetDisplayNameOf\n");
2489 static HRESULT WINAPI
SF_SetNameOf(IShellFolder
*iface
,
2490 HWND hwnd
, LPCITEMIDLIST idl
, LPCOLESTR name
, SHGDNF flags
,
2491 LPITEMIDLIST
*idlOut
)
2493 ok(0, "Didn't expect SetNameOf\n");
2497 static IShellFolderVtbl ShellFolderVtbl
= {
2501 SF_ParseDisplayName
,
2506 SF_CreateViewObject
,
2509 SF_GetDisplayNameOf
,
2513 static IShellFolder ShellFolder
= { &ShellFolderVtbl
};
2515 static void test_SHIShellFolder_EnumObjects(void)
2519 IShellFolder
*folder
;
2521 if(!pSHIShellFolder_EnumObjects
|| is_win2k_and_lower
){
2522 win_skip("SHIShellFolder_EnumObjects not available\n");
2527 /* NULL object crashes on Windows */
2528 hres
= pSHIShellFolder_EnumObjects(NULL
, NULL
, 0, NULL
);
2531 /* SHIShellFolder_EnumObjects doesn't QI the object for IShellFolder */
2532 enm
= (IEnumIDList
*)0xdeadbeef;
2533 hres
= pSHIShellFolder_EnumObjects(&ShellFolder
, NULL
, 0, &enm
);
2534 ok(hres
== S_OK
, "SHIShellFolder_EnumObjects failed: 0x%08x\n", hres
);
2535 ok(enm
== (IEnumIDList
*)0xcafebabe, "Didn't get expected enumerator location, instead: %p\n", enm
);
2537 /* SHIShellFolder_EnumObjects isn't strict about the IShellFolder object */
2538 hres
= pSHGetDesktopFolder(&folder
);
2539 ok(hres
== S_OK
, "SHGetDesktopFolder failed: 0x%08x\n", hres
);
2542 hres
= pSHIShellFolder_EnumObjects(folder
, NULL
, 0, &enm
);
2543 ok(hres
== S_OK
, "SHIShellFolder_EnumObjects failed: 0x%08x\n", hres
);
2544 ok(enm
!= NULL
, "Didn't get an enumerator\n");
2546 IEnumIDList_Release(enm
);
2548 IShellFolder_Release(folder
);
2551 static void write_inifile(LPCWSTR filename
)
2556 static const char data
[] =
2559 "AnotherKey=asdf\r\n";
2561 file
= CreateFileW(filename
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
2562 if(file
== INVALID_HANDLE_VALUE
)
2565 WriteFile(file
, data
, sizeof(data
), &written
, NULL
);
2570 #define verify_inifile(f, e) r_verify_inifile(__LINE__, f, e)
2571 static void r_verify_inifile(unsigned l
, LPCWSTR filename
, LPCSTR exp
)
2577 file
= CreateFileW(filename
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, 0, NULL
);
2578 if(file
== INVALID_HANDLE_VALUE
)
2581 ReadFile(file
, buf
, sizeof(buf
) * sizeof(CHAR
), &read
, NULL
);
2586 ok_(__FILE__
,l
)(!strcmp(buf
, exp
), "Expected:\n%s\nGot:\n%s\n", exp
,
2590 static void test_SHGetIniString(void)
2593 WCHAR out
[64] = {0};
2595 static const WCHAR TestAppW
[] = {'T','e','s','t','A','p','p',0};
2596 static const WCHAR TestIniW
[] = {'C',':','\\','t','e','s','t','.','i','n','i',0};
2597 static const WCHAR AKeyW
[] = {'A','K','e','y',0};
2598 static const WCHAR AnotherKeyW
[] = {'A','n','o','t','h','e','r','K','e','y',0};
2599 static const WCHAR JunkKeyW
[] = {'J','u','n','k','K','e','y',0};
2601 if(!pSHGetIniStringW
|| is_win2k_and_lower
){
2602 win_skip("SHGetIniStringW is not available\n");
2606 write_inifile(TestIniW
);
2609 /* these crash on Windows */
2610 ret
= pSHGetIniStringW(NULL
, NULL
, NULL
, 0, NULL
);
2611 ret
= pSHGetIniStringW(NULL
, AKeyW
, out
, sizeof(out
), TestIniW
);
2612 ret
= pSHGetIniStringW(TestAppW
, AKeyW
, NULL
, sizeof(out
), TestIniW
);
2615 ret
= pSHGetIniStringW(TestAppW
, AKeyW
, out
, 0, TestIniW
);
2616 ok(ret
== 0, "SHGetIniStringW should have given 0, instead: %d\n", ret
);
2618 /* valid arguments */
2619 ret
= pSHGetIniStringW(TestAppW
, NULL
, out
, sizeof(out
), TestIniW
);
2620 ok(broken(ret
== 0) || /* win 98 */
2621 ret
== 4, "SHGetIniStringW should have given 4, instead: %d\n", ret
);
2622 ok(!lstrcmpW(out
, AKeyW
), "Expected %s, got: %s\n",
2623 wine_dbgstr_w(AKeyW
), wine_dbgstr_w(out
));
2625 ret
= pSHGetIniStringW(TestAppW
, AKeyW
, out
, sizeof(out
), TestIniW
);
2626 ok(broken(ret
== 0) || /* win 98 */
2627 ret
== 1, "SHGetIniStringW should have given 1, instead: %d\n", ret
);
2628 ok(broken(*out
== 0) || /*win 98 */
2629 !strcmp_wa(out
, "1"), "Expected L\"1\", got: %s\n", wine_dbgstr_w(out
));
2631 ret
= pSHGetIniStringW(TestAppW
, AnotherKeyW
, out
, sizeof(out
), TestIniW
);
2632 ok(broken(ret
== 0) || /* win 98 */
2633 ret
== 4, "SHGetIniStringW should have given 4, instead: %d\n", ret
);
2634 ok(broken(*out
== 0) || /* win 98 */
2635 !strcmp_wa(out
, "asdf"), "Expected L\"asdf\", got: %s\n", wine_dbgstr_w(out
));
2637 ret
= pSHGetIniStringW(TestAppW
, JunkKeyW
, out
, sizeof(out
), TestIniW
);
2638 ok(ret
== 0, "SHGetIniStringW should have given 0, instead: %d\n", ret
);
2639 ok(*out
== 0, "Expected L\"\", got: %s\n", wine_dbgstr_w(out
));
2641 DeleteFileW(TestIniW
);
2644 static void test_SHSetIniString(void)
2648 static const WCHAR TestAppW
[] = {'T','e','s','t','A','p','p',0};
2649 static const WCHAR AnotherAppW
[] = {'A','n','o','t','h','e','r','A','p','p',0};
2650 static const WCHAR TestIniW
[] = {'C',':','\\','t','e','s','t','.','i','n','i',0};
2651 static const WCHAR AKeyW
[] = {'A','K','e','y',0};
2652 static const WCHAR NewKeyW
[] = {'N','e','w','K','e','y',0};
2653 static const WCHAR AValueW
[] = {'A','V','a','l','u','e',0};
2655 if(!pSHSetIniStringW
|| is_win2k_and_lower
){
2656 win_skip("SHSetIniStringW is not available\n");
2660 write_inifile(TestIniW
);
2662 ret
= pSHSetIniStringW(TestAppW
, AKeyW
, AValueW
, TestIniW
);
2663 ok(ret
== TRUE
, "SHSetIniStringW should not have failed\n");
2664 todo_wine
/* wine sticks an extra \r\n at the end of the file */
2665 verify_inifile(TestIniW
, "[TestApp]\r\nAKey=AValue\r\nAnotherKey=asdf\r\n");
2667 ret
= pSHSetIniStringW(TestAppW
, AKeyW
, NULL
, TestIniW
);
2668 ok(ret
== TRUE
, "SHSetIniStringW should not have failed\n");
2669 verify_inifile(TestIniW
, "[TestApp]\r\nAnotherKey=asdf\r\n");
2671 ret
= pSHSetIniStringW(AnotherAppW
, NewKeyW
, AValueW
, TestIniW
);
2672 ok(ret
== TRUE
, "SHSetIniStringW should not have failed\n");
2673 verify_inifile(TestIniW
, "[TestApp]\r\nAnotherKey=asdf\r\n[AnotherApp]\r\nNewKey=AValue\r\n");
2675 ret
= pSHSetIniStringW(TestAppW
, NULL
, AValueW
, TestIniW
);
2676 ok(ret
== TRUE
, "SHSetIniStringW should not have failed\n");
2677 verify_inifile(TestIniW
, "[AnotherApp]\r\nNewKey=AValue\r\n");
2679 DeleteFileW(TestIniW
);
2682 enum _shellkey_flags
{
2683 SHKEY_Explorer
= 0x00,
2684 SHKEY_Root_HKCU
= 0x01
2687 static void test_SHGetShellKey(void)
2689 void *pPathBuildRootW
= GetProcAddress(hShlwapi
, "PathBuildRootW");
2693 if (!pSHGetShellKey
)
2695 win_skip("SHGetShellKey(ordinal 491) isn't available\n");
2700 if (pPathBuildRootW
&& pPathBuildRootW
== pSHGetShellKey
)
2702 win_skip("SHGetShellKey(ordinal 491) used for PathBuildRootW\n");
2706 if (is_win9x
|| is_win2k_and_lower
)
2708 win_skip("Ordinal 491 used for another call, skipping SHGetShellKey tests\n");
2712 /* marking broken cause latest Vista+ versions fail here */
2713 SetLastError(0xdeadbeef);
2714 hkey
= pSHGetShellKey(SHKEY_Explorer
, NULL
, FALSE
);
2715 ok(hkey
== NULL
|| broken(hkey
!= NULL
), "got %p\n", hkey
);
2719 ret
= RegOpenKeyExA(hkey
, "Shell Folders", 0, KEY_READ
, &hkey2
);
2720 ok(ret
== ERROR_SUCCESS
, "got %d\n", ret
);
2721 ok(hkey2
!= NULL
, "got %p\n", hkey2
);
2722 RegCloseKey( hkey2
);
2723 RegCloseKey( hkey
);
2726 hkey
= pSHGetShellKey(SHKEY_Explorer
| SHKEY_Root_HKCU
, NULL
, FALSE
);
2727 ok(hkey
!= NULL
, "got %p\n", hkey
);
2730 ret
= RegOpenKeyExA(hkey
, "Shell Folders", 0, KEY_READ
, &hkey2
);
2731 ok(ret
== ERROR_SUCCESS
, "got %d\n", ret
);
2732 ok(hkey2
!= NULL
, "got %p\n", hkey2
);
2733 RegCloseKey( hkey2
);
2735 RegCloseKey( hkey
);
2738 static void init_pointers(void)
2740 #define MAKEFUNC(f, ord) (p##f = (void*)GetProcAddress(hShlwapi, (LPSTR)(ord)))
2741 MAKEFUNC(SHAllocShared
, 7);
2742 MAKEFUNC(SHLockShared
, 8);
2743 MAKEFUNC(SHUnlockShared
, 9);
2744 MAKEFUNC(SHFreeShared
, 10);
2745 MAKEFUNC(GetAcceptLanguagesA
, 14);
2746 MAKEFUNC(SHSetWindowBits
, 165);
2747 MAKEFUNC(ConnectToConnectionPoint
, 168);
2748 MAKEFUNC(SHSearchMapInt
, 198);
2749 MAKEFUNC(SHCreateWorkerWindowA
, 257);
2750 MAKEFUNC(GUIDFromStringA
, 269);
2751 MAKEFUNC(SHPackDispParams
, 282);
2752 MAKEFUNC(IConnectionPoint_InvokeWithCancel
, 283);
2753 MAKEFUNC(IConnectionPoint_SimpleInvoke
, 284);
2754 MAKEFUNC(SHGetIniStringW
, 294);
2755 MAKEFUNC(SHSetIniStringW
, 295);
2756 MAKEFUNC(SHFormatDateTimeA
, 353);
2757 MAKEFUNC(SHFormatDateTimeW
, 354);
2758 MAKEFUNC(SHIShellFolder_EnumObjects
, 404);
2759 MAKEFUNC(SHGetObjectCompatFlags
, 476);
2760 MAKEFUNC(IUnknown_QueryServiceExec
, 484);
2761 MAKEFUNC(SHGetShellKey
, 491);
2762 MAKEFUNC(SHPropertyBag_ReadLONG
, 496);
2763 MAKEFUNC(IUnknown_ProfferService
, 514);
2769 hShlwapi
= GetModuleHandleA("shlwapi.dll");
2770 is_win2k_and_lower
= GetProcAddress(hShlwapi
, "StrChrNW") == 0;
2771 is_win9x
= GetProcAddress(hShlwapi
, (LPSTR
)99) == 0; /* StrCpyNXA */
2775 hmlang
= LoadLibraryA("mlang.dll");
2776 pLcidToRfc1766A
= (void *)GetProcAddress(hmlang
, "LcidToRfc1766A");
2778 hshell32
= LoadLibraryA("shell32.dll");
2779 pSHGetDesktopFolder
= (void *)GetProcAddress(hshell32
, "SHGetDesktopFolder");
2781 test_GetAcceptLanguagesA();
2782 test_SHSearchMapInt();
2783 test_alloc_shared();
2785 test_GetShellSecurityDescriptor();
2786 test_SHPackDispParams();
2787 test_IConnectionPoint();
2788 test_SHPropertyBag_ReadLONG();
2789 test_SHSetWindowBits();
2790 test_SHFormatDateTimeA();
2791 test_SHFormatDateTimeW();
2792 test_SHGetObjectCompatFlags();
2793 test_IUnknown_QueryServiceExec();
2794 test_IUnknown_ProfferService();
2795 test_SHCreateWorkerWindowA();
2796 test_SHIShellFolder_EnumObjects();
2797 test_SHGetIniString();
2798 test_SHSetIniString();
2799 test_SHGetShellKey();
2801 FreeLibrary(hshell32
);
2802 FreeLibrary(hmlang
);