1 /* Unit test suite for SHLWAPI ordinal functions
3 * Copyright 2004 Jon Griffiths
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "wine/test.h"
36 /* Function ptrs for ordinal calls */
37 static HMODULE hShlwapi
;
38 static BOOL is_win2k_and_lower
;
40 static int (WINAPI
*pSHSearchMapInt
)(const int*,const int*,int,int);
41 static HRESULT (WINAPI
*pGetAcceptLanguagesA
)(LPSTR
,LPDWORD
);
43 static HANDLE (WINAPI
*pSHAllocShared
)(LPCVOID
,DWORD
,DWORD
);
44 static LPVOID (WINAPI
*pSHLockShared
)(HANDLE
,DWORD
);
45 static BOOL (WINAPI
*pSHUnlockShared
)(LPVOID
);
46 static BOOL (WINAPI
*pSHFreeShared
)(HANDLE
,DWORD
);
47 static HRESULT(WINAPIV
*pSHPackDispParams
)(DISPPARAMS
*,VARIANTARG
*,UINT
,...);
48 static HRESULT(WINAPI
*pIConnectionPoint_SimpleInvoke
)(IConnectionPoint
*,DISPID
,DISPPARAMS
*);
49 static HRESULT(WINAPI
*pIConnectionPoint_InvokeWithCancel
)(IConnectionPoint
*,DISPID
,DISPPARAMS
*,DWORD
,DWORD
);
50 static HRESULT(WINAPI
*pConnectToConnectionPoint
)(IUnknown
*,REFIID
,BOOL
,IUnknown
*, LPDWORD
,IConnectionPoint
**);
51 static HRESULT(WINAPI
*pSHPropertyBag_ReadLONG
)(IPropertyBag
*,LPCWSTR
,LPLONG
);
52 static LONG (WINAPI
*pSHSetWindowBits
)(HWND
, INT
, UINT
, UINT
);
53 static INT (WINAPI
*pSHFormatDateTimeA
)(const FILETIME UNALIGNED
*, DWORD
*, LPSTR
, UINT
);
54 static INT (WINAPI
*pSHFormatDateTimeW
)(const FILETIME UNALIGNED
*, DWORD
*, LPWSTR
, UINT
);
55 static DWORD (WINAPI
*pSHGetObjectCompatFlags
)(IUnknown
*, const CLSID
*);
56 static BOOL (WINAPI
*pGUIDFromStringA
)(LPSTR
, CLSID
*);
57 static HRESULT (WINAPI
*pIUnknown_QueryServiceExec
)(IUnknown
*, REFIID
, const GUID
*, DWORD
, DWORD
, VARIANT
*, VARIANT
*);
58 static HRESULT (WINAPI
*pIUnknown_ProfferService
)(IUnknown
*, REFGUID
, IServiceProvider
*, DWORD
*);
59 static HWND (WINAPI
*pSHCreateWorkerWindowA
)(LONG
, HWND
, DWORD
, DWORD
, HMENU
, LONG_PTR
);
60 static HRESULT (WINAPI
*pSHIShellFolder_EnumObjects
)(LPSHELLFOLDER
, HWND
, SHCONTF
, IEnumIDList
**);
61 static DWORD (WINAPI
*pSHGetIniStringW
)(LPCWSTR
, LPCWSTR
, LPWSTR
, DWORD
, LPCWSTR
);
62 static BOOL (WINAPI
*pSHSetIniStringW
)(LPCWSTR
, LPCWSTR
, LPCWSTR
, LPCWSTR
);
64 static HMODULE hmlang
;
65 static HRESULT (WINAPI
*pLcidToRfc1766A
)(LCID
, LPSTR
, INT
);
67 static HMODULE hshell32
;
68 static HRESULT (WINAPI
*pSHGetDesktopFolder
)(IShellFolder
**);
70 static const CHAR ie_international
[] = {
71 'S','o','f','t','w','a','r','e','\\',
72 'M','i','c','r','o','s','o','f','t','\\',
73 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
74 'I','n','t','e','r','n','a','t','i','o','n','a','l',0};
75 static const CHAR acceptlanguage
[] = {
76 'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0};
78 static int strcmp_wa(LPCWSTR strw
, const char *stra
)
81 WideCharToMultiByte(CP_ACP
, 0, strw
, -1, buf
, sizeof(buf
), NULL
, NULL
);
82 return lstrcmpA(stra
, buf
);
96 static void init_call_trace(call_trace_t
*ctrace
)
100 ctrace
->calls
= HeapAlloc(GetProcessHeap(), 0, sizeof(call_entry_t
) * ctrace
->alloc
);
103 static void free_call_trace(const call_trace_t
*ctrace
)
105 HeapFree(GetProcessHeap(), 0, ctrace
->calls
);
108 static void add_call(call_trace_t
*ctrace
, int id
, const void *arg0
,
109 const void *arg1
, const void *arg2
, const void *arg3
, const void *arg4
)
120 if (ctrace
->count
== ctrace
->alloc
)
123 ctrace
->calls
= HeapReAlloc(GetProcessHeap(),0, ctrace
->calls
, ctrace
->alloc
*sizeof(call_entry_t
));
126 ctrace
->calls
[ctrace
->count
++] = call
;
129 static void ok_trace_(call_trace_t
*texpected
, call_trace_t
*tgot
, int line
)
131 if (texpected
->count
== tgot
->count
)
135 for (i
= 0; i
< texpected
->count
; i
++)
137 call_entry_t
*expected
= &texpected
->calls
[i
];
138 call_entry_t
*got
= &tgot
->calls
[i
];
141 ok_(__FILE__
, line
)(expected
->id
== got
->id
, "got different ids %d: %d, %d\n", i
+1, expected
->id
, got
->id
);
143 for (j
= 0; j
< 5; j
++)
145 ok_(__FILE__
, line
)(expected
->args
[j
] == got
->args
[j
], "got different args[%d] for %d: %p, %p\n", j
, i
+1,
146 expected
->args
[j
], got
->args
[j
]);
151 ok_(__FILE__
, line
)(0, "traces length mismatch\n");
154 #define ok_trace(a, b) ok_trace_(a, b, __LINE__)
156 /* trace of actually made calls */
157 static call_trace_t trace_got
;
159 static void test_GetAcceptLanguagesA(void)
161 static LPCSTR table
[] = {"de,en-gb;q=0.7,en;q=0.3",
162 "de,en;q=0.3,en-gb;q=0.7", /* sorting is ignored */
163 "winetest", /* content is ignored */
173 LONG res_query
= ERROR_SUCCESS
;
176 DWORD maxlen
= sizeof(buffer
) - 2;
182 if (!pGetAcceptLanguagesA
) {
183 win_skip("GetAcceptLanguagesA is not available\n");
187 lcid
= GetUserDefaultLCID();
189 /* Get the original Value */
190 lres
= RegOpenKeyA(HKEY_CURRENT_USER
, ie_international
, &hroot
);
192 skip("RegOpenKey(%s) failed: %d\n", ie_international
, lres
);
195 len
= sizeof(original
);
197 res_query
= RegQueryValueExA(hroot
, acceptlanguage
, 0, NULL
, (PBYTE
)original
, &len
);
199 RegDeleteValue(hroot
, acceptlanguage
);
201 /* Some windows versions use "lang-COUNTRY" as default */
202 memset(language
, 0, sizeof(language
));
203 len
= GetLocaleInfoA(lcid
, LOCALE_SISO639LANGNAME
, language
, sizeof(language
));
206 lstrcat(language
, "-");
207 memset(buffer
, 0, sizeof(buffer
));
208 len
= GetLocaleInfoA(lcid
, LOCALE_SISO3166CTRYNAME
, buffer
, sizeof(buffer
) - len
- 1);
209 lstrcat(language
, buffer
);
213 /* LOCALE_SNAME has additional parts in some languages. Try only as last chance */
214 memset(language
, 0, sizeof(language
));
215 len
= GetLocaleInfoA(lcid
, LOCALE_SNAME
, language
, sizeof(language
));
218 /* get the default value */
220 memset(buffer
, '#', maxlen
);
222 hr
= pGetAcceptLanguagesA( buffer
, &len
);
225 win_skip("GetAcceptLanguagesA failed with 0x%x\n", hr
);
226 goto restore_original
;
229 if (lstrcmpA(buffer
, language
)) {
230 /* some windows versions use "lang" or "lang-country" as default */
232 if (pLcidToRfc1766A
) {
233 hr
= pLcidToRfc1766A(lcid
, language
, sizeof(language
));
234 ok(hr
== S_OK
, "LcidToRfc1766A returned 0x%x and %s\n", hr
, language
);
238 ok(!lstrcmpA(buffer
, language
),
239 "have '%s' (searching for '%s')\n", language
, buffer
);
241 if (lstrcmpA(buffer
, language
)) {
242 win_skip("no more ideas, how to build the default language '%s'\n", buffer
);
243 goto restore_original
;
246 trace("detected default: %s\n", language
);
247 while ((entry
= table
[i
])) {
249 exactsize
= lstrlenA(entry
);
251 lres
= RegSetValueExA(hroot
, acceptlanguage
, 0, REG_SZ
, (const BYTE
*) entry
, exactsize
+ 1);
252 ok(!lres
, "got %d for RegSetValueExA: %s\n", lres
, entry
);
254 /* len includes space for the terminating 0 before vista/w2k8 */
256 memset(buffer
, '#', maxlen
);
258 hr
= pGetAcceptLanguagesA( buffer
, &len
);
259 ok(((hr
== E_INVALIDARG
) && (len
== 0)) ||
261 ((len
== exactsize
) || (len
== exactsize
+1)) &&
262 !lstrcmpA(buffer
, entry
)),
263 "+2_#%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
266 memset(buffer
, '#', maxlen
);
268 hr
= pGetAcceptLanguagesA( buffer
, &len
);
269 ok(((hr
== E_INVALIDARG
) && (len
== 0)) ||
271 ((len
== exactsize
) || (len
== exactsize
+1)) &&
272 !lstrcmpA(buffer
, entry
)),
273 "+1_#%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
276 memset(buffer
, '#', maxlen
);
278 hr
= pGetAcceptLanguagesA( buffer
, &len
);
280 /* There is no space for the string in the registry.
281 When the buffer is large enough, the default language is returned
283 When the buffer is too small for that fallback, win7_32 and w2k8_64
284 and above fail with HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), but
285 recent os succeed and return a partial result while
286 older os succeed and overflow the buffer */
288 ok(((hr
== E_INVALIDARG
) && (len
== 0)) ||
289 (((hr
== S_OK
) && !lstrcmpA(buffer
, language
) && (len
== lstrlenA(language
))) ||
290 ((hr
== S_OK
) && !memcmp(buffer
, language
, len
)) ||
291 ((hr
== __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
)) && !len
)),
292 "==_#%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
296 memset(buffer
, '#', maxlen
);
298 hr
= pGetAcceptLanguagesA( buffer
, &len
);
299 ok(((hr
== E_INVALIDARG
) && (len
== 0)) ||
300 (((hr
== S_OK
) && !lstrcmpA(buffer
, language
) && (len
== lstrlenA(language
))) ||
301 ((hr
== S_OK
) && !memcmp(buffer
, language
, len
)) ||
302 ((hr
== __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
)) && !len
)),
303 "-1_#%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
307 memset(buffer
, '#', maxlen
);
309 hr
= pGetAcceptLanguagesA( buffer
, &len
);
310 ok(((hr
== E_INVALIDARG
) && (len
== 0)) ||
311 (((hr
== S_OK
) && !lstrcmpA(buffer
, language
) && (len
== lstrlenA(language
))) ||
312 ((hr
== S_OK
) && !memcmp(buffer
, language
, len
)) ||
313 ((hr
== __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
)) && !len
)),
314 "=1_#%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
317 hr
= pGetAcceptLanguagesA( NULL
, &len
);
319 /* w2k3 and below: E_FAIL and untouched len,
320 since w2k8: S_OK and needed size (excluding 0) */
321 ok( ((hr
== S_OK
) && (len
== exactsize
)) ||
322 ((hr
== E_FAIL
) && (len
== maxlen
)),
323 "NULL,max #%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
328 /* without a value in the registry, a default language is returned */
329 RegDeleteValue(hroot
, acceptlanguage
);
332 memset(buffer
, '#', maxlen
);
334 hr
= pGetAcceptLanguagesA( buffer
, &len
);
335 ok( ((hr
== S_OK
) && (len
== lstrlenA(language
))),
336 "max: got 0x%x with %d and %s (expected S_OK with %d and '%s'\n",
337 hr
, len
, buffer
, lstrlenA(language
), language
);
340 memset(buffer
, '#', maxlen
);
342 hr
= pGetAcceptLanguagesA( buffer
, &len
);
343 ok( (((hr
== S_OK
) || (hr
== E_INVALIDARG
)) && !memcmp(buffer
, language
, len
)) ||
344 ((hr
== __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
)) && !len
),
345 "=2: got 0x%x with %d and %s\n", hr
, len
, buffer
);
348 memset(buffer
, '#', maxlen
);
350 hr
= pGetAcceptLanguagesA( buffer
, &len
);
351 /* When the buffer is too small, win7_32 and w2k8_64 and above fail with
352 HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), other versions suceed
353 and return a partial 0 terminated result while other versions
354 fail with E_INVALIDARG and return a partial unterminated result */
355 ok( (((hr
== S_OK
) || (hr
== E_INVALIDARG
)) && !memcmp(buffer
, language
, len
)) ||
356 ((hr
== __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
)) && !len
),
357 "=1: got 0x%x with %d and %s\n", hr
, len
, buffer
);
360 memset(buffer
, '#', maxlen
);
362 hr
= pGetAcceptLanguagesA( buffer
, &len
);
363 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
364 ok((hr
== E_FAIL
) || (hr
== E_INVALIDARG
),
365 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr
);
367 memset(buffer
, '#', maxlen
);
369 hr
= pGetAcceptLanguagesA( buffer
, NULL
);
370 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
371 ok((hr
== E_FAIL
) || (hr
== E_INVALIDARG
),
372 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr
);
375 hr
= pGetAcceptLanguagesA( NULL
, NULL
);
376 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
377 ok((hr
== E_FAIL
) || (hr
== E_INVALIDARG
),
378 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr
);
382 len
= lstrlenA(original
);
383 lres
= RegSetValueExA(hroot
, acceptlanguage
, 0, REG_SZ
, (const BYTE
*) original
, len
? len
+ 1: 0);
384 ok(!lres
, "RegSetValueEx(%s) failed: %d\n", original
, lres
);
388 RegDeleteValue(hroot
, acceptlanguage
);
393 static void test_SHSearchMapInt(void)
395 int keys
[8], values
[8];
398 if (!pSHSearchMapInt
)
401 memset(keys
, 0, sizeof(keys
));
402 memset(values
, 0, sizeof(values
));
403 keys
[0] = 99; values
[0] = 101;
405 /* NULL key/value lists crash native, so skip testing them */
408 i
= pSHSearchMapInt(keys
, values
, 1, keys
[0]);
409 ok(i
== values
[0], "Len 1, expected %d, got %d\n", values
[0], i
);
411 /* Key doesn't exist */
412 i
= pSHSearchMapInt(keys
, values
, 1, 100);
413 ok(i
== -1, "Len 1 - bad key, expected -1, got %d\n", i
);
415 /* Len = 0 => not found */
416 i
= pSHSearchMapInt(keys
, values
, 0, keys
[0]);
417 ok(i
== -1, "Len 1 - passed len 0, expected -1, got %d\n", i
);
419 /* 2 elements, len = 1 */
420 keys
[1] = 98; values
[1] = 102;
421 i
= pSHSearchMapInt(keys
, values
, 1, keys
[1]);
422 ok(i
== -1, "Len 1 - array len 2, expected -1, got %d\n", i
);
424 /* 2 elements, len = 2 */
425 i
= pSHSearchMapInt(keys
, values
, 2, keys
[1]);
426 ok(i
== values
[1], "Len 2, expected %d, got %d\n", values
[1], i
);
428 /* Searches forward */
429 keys
[2] = 99; values
[2] = 103;
430 i
= pSHSearchMapInt(keys
, values
, 3, keys
[0]);
431 ok(i
== values
[0], "Len 3, expected %d, got %d\n", values
[0], i
);
434 static void test_alloc_shared(void)
442 procid
=GetCurrentProcessId();
443 hmem
=pSHAllocShared(NULL
,10,procid
);
444 ok(hmem
!=NULL
,"SHAllocShared(NULL...) failed: %u\n", GetLastError());
445 ret
= pSHFreeShared(hmem
, procid
);
446 ok( ret
, "SHFreeShared failed: %u\n", GetLastError());
449 hmem
=pSHAllocShared(&val
,4,procid
);
450 ok(hmem
!=NULL
,"SHAllocShared(NULL...) failed: %u\n", GetLastError());
452 p
=pSHLockShared(hmem
,procid
);
453 ok(p
!=NULL
,"SHLockShared failed: %u\n", GetLastError());
455 ok(*p
==val
,"Wrong value in shared memory: %d instead of %d\n",*p
,val
);
456 ret
= pSHUnlockShared(p
);
457 ok( ret
, "SHUnlockShared failed: %u\n", GetLastError());
459 ret
= pSHFreeShared(hmem
, procid
);
460 ok( ret
, "SHFreeShared failed: %u\n", GetLastError());
463 static void test_fdsa(void)
467 DWORD num_items
; /* Number of elements inserted */
468 void *mem
; /* Ptr to array */
469 DWORD blocks_alloced
; /* Number of elements allocated */
470 BYTE inc
; /* Number of elements to grow by when we need to expand */
471 BYTE block_size
; /* Size in bytes of an element */
472 BYTE flags
; /* Flags */
475 BOOL (WINAPI
*pFDSA_Initialize
)(DWORD block_size
, DWORD inc
, FDSA_info
*info
, void *mem
,
477 BOOL (WINAPI
*pFDSA_Destroy
)(FDSA_info
*info
);
478 DWORD (WINAPI
*pFDSA_InsertItem
)(FDSA_info
*info
, DWORD where
, const void *block
);
479 BOOL (WINAPI
*pFDSA_DeleteItem
)(FDSA_info
*info
, DWORD where
);
482 int block_size
= 10, init_blocks
= 4, inc
= 2;
486 pFDSA_Initialize
= (void *)GetProcAddress(hShlwapi
, (LPSTR
)208);
487 pFDSA_Destroy
= (void *)GetProcAddress(hShlwapi
, (LPSTR
)209);
488 pFDSA_InsertItem
= (void *)GetProcAddress(hShlwapi
, (LPSTR
)210);
489 pFDSA_DeleteItem
= (void *)GetProcAddress(hShlwapi
, (LPSTR
)211);
491 mem
= HeapAlloc(GetProcessHeap(), 0, block_size
* init_blocks
);
492 memset(&info
, 0, sizeof(info
));
494 ok(pFDSA_Initialize(block_size
, inc
, &info
, mem
, init_blocks
), "FDSA_Initialize rets FALSE\n");
495 ok(info
.num_items
== 0, "num_items = %d\n", info
.num_items
);
496 ok(info
.mem
== mem
, "mem = %p\n", info
.mem
);
497 ok(info
.blocks_alloced
== init_blocks
, "blocks_alloced = %d\n", info
.blocks_alloced
);
498 ok(info
.inc
== inc
, "inc = %d\n", info
.inc
);
499 ok(info
.block_size
== block_size
, "block_size = %d\n", info
.block_size
);
500 ok(info
.flags
== 0, "flags = %d\n", info
.flags
);
502 ret
= pFDSA_InsertItem(&info
, 1234, "1234567890");
503 ok(ret
== 0, "ret = %d\n", ret
);
504 ok(info
.num_items
== 1, "num_items = %d\n", info
.num_items
);
505 ok(info
.mem
== mem
, "mem = %p\n", info
.mem
);
506 ok(info
.blocks_alloced
== init_blocks
, "blocks_alloced = %d\n", info
.blocks_alloced
);
507 ok(info
.inc
== inc
, "inc = %d\n", info
.inc
);
508 ok(info
.block_size
== block_size
, "block_size = %d\n", info
.block_size
);
509 ok(info
.flags
== 0, "flags = %d\n", info
.flags
);
511 ret
= pFDSA_InsertItem(&info
, 1234, "abcdefghij");
512 ok(ret
== 1, "ret = %d\n", ret
);
514 ret
= pFDSA_InsertItem(&info
, 1, "klmnopqrst");
515 ok(ret
== 1, "ret = %d\n", ret
);
517 ret
= pFDSA_InsertItem(&info
, 0, "uvwxyzABCD");
518 ok(ret
== 0, "ret = %d\n", ret
);
519 ok(info
.mem
== mem
, "mem = %p\n", info
.mem
);
520 ok(info
.flags
== 0, "flags = %d\n", info
.flags
);
522 /* This next InsertItem will cause shlwapi to allocate its own mem buffer */
523 ret
= pFDSA_InsertItem(&info
, 0, "EFGHIJKLMN");
524 ok(ret
== 0, "ret = %d\n", ret
);
525 ok(info
.mem
!= mem
, "mem = %p\n", info
.mem
);
526 ok(info
.blocks_alloced
== init_blocks
+ inc
, "blocks_alloced = %d\n", info
.blocks_alloced
);
527 ok(info
.flags
== 0x1, "flags = %d\n", info
.flags
);
529 ok(!memcmp(info
.mem
, "EFGHIJKLMNuvwxyzABCD1234567890klmnopqrstabcdefghij", 50), "mem %s\n", (char*)info
.mem
);
531 ok(pFDSA_DeleteItem(&info
, 2), "rets FALSE\n");
532 ok(info
.mem
!= mem
, "mem = %p\n", info
.mem
);
533 ok(info
.blocks_alloced
== init_blocks
+ inc
, "blocks_alloced = %d\n", info
.blocks_alloced
);
534 ok(info
.flags
== 0x1, "flags = %d\n", info
.flags
);
536 ok(!memcmp(info
.mem
, "EFGHIJKLMNuvwxyzABCDklmnopqrstabcdefghij", 40), "mem %s\n", (char*)info
.mem
);
538 ok(pFDSA_DeleteItem(&info
, 3), "rets FALSE\n");
539 ok(info
.mem
!= mem
, "mem = %p\n", info
.mem
);
540 ok(info
.blocks_alloced
== init_blocks
+ inc
, "blocks_alloced = %d\n", info
.blocks_alloced
);
541 ok(info
.flags
== 0x1, "flags = %d\n", info
.flags
);
543 ok(!memcmp(info
.mem
, "EFGHIJKLMNuvwxyzABCDklmnopqrst", 30), "mem %s\n", (char*)info
.mem
);
545 ok(!pFDSA_DeleteItem(&info
, 4), "does not ret FALSE\n");
547 /* As shlwapi has allocated memory internally, Destroy will ret FALSE */
548 ok(!pFDSA_Destroy(&info
), "FDSA_Destroy does not ret FALSE\n");
551 /* When Initialize is called with inc = 0, set it to 1 */
552 ok(pFDSA_Initialize(block_size
, 0, &info
, mem
, init_blocks
), "FDSA_Initialize rets FALSE\n");
553 ok(info
.inc
== 1, "inc = %d\n", info
.inc
);
555 /* This time, because shlwapi hasn't had to allocate memory
556 internally, Destroy rets non-zero */
557 ok(pFDSA_Destroy(&info
), "FDSA_Destroy rets FALSE\n");
560 HeapFree(GetProcessHeap(), 0, mem
);
564 typedef struct SHELL_USER_SID
{
565 SID_IDENTIFIER_AUTHORITY sidAuthority
;
568 } SHELL_USER_SID
, *PSHELL_USER_SID
;
569 typedef struct SHELL_USER_PERMISSION
{
570 SHELL_USER_SID susID
;
575 DWORD dwInheritAccessMask
;
576 } SHELL_USER_PERMISSION
, *PSHELL_USER_PERMISSION
;
577 static void test_GetShellSecurityDescriptor(void)
579 SHELL_USER_PERMISSION supCurrentUserFull
= {
580 { {SECURITY_NULL_SID_AUTHORITY
}, 0, 0 },
581 ACCESS_ALLOWED_ACE_TYPE
, FALSE
,
583 #define MY_INHERITANCE 0xBE /* invalid value to proof behavior */
584 SHELL_USER_PERMISSION supEveryoneDenied
= {
585 { {SECURITY_WORLD_SID_AUTHORITY
}, SECURITY_WORLD_RID
, 0 },
586 ACCESS_DENIED_ACE_TYPE
, TRUE
,
587 GENERIC_WRITE
, MY_INHERITANCE
| 0xDEADBA00, GENERIC_READ
};
588 PSHELL_USER_PERMISSION rgsup
[2] = {
589 &supCurrentUserFull
, &supEveryoneDenied
,
591 SECURITY_DESCRIPTOR
* psd
;
592 SECURITY_DESCRIPTOR
* (WINAPI
*pGetShellSecurityDescriptor
)(PSHELL_USER_PERMISSION
*,int);
593 void *pChrCmpIW
= GetProcAddress(hShlwapi
, "ChrCmpIW");
595 pGetShellSecurityDescriptor
=(void*)GetProcAddress(hShlwapi
,(char*)475);
597 if(!pGetShellSecurityDescriptor
)
599 win_skip("GetShellSecurityDescriptor not available\n");
603 if(pChrCmpIW
&& pChrCmpIW
== pGetShellSecurityDescriptor
) /* win2k */
605 win_skip("Skipping for GetShellSecurityDescriptor, same ordinal used for ChrCmpIW\n");
609 psd
= pGetShellSecurityDescriptor(NULL
, 2);
611 broken(psd
==INVALID_HANDLE_VALUE
), /* IE5 */
612 "GetShellSecurityDescriptor should fail\n");
613 psd
= pGetShellSecurityDescriptor(rgsup
, 0);
614 ok(psd
==NULL
, "GetShellSecurityDescriptor should fail, got %p\n", psd
);
616 SetLastError(0xdeadbeef);
617 psd
= pGetShellSecurityDescriptor(rgsup
, 2);
618 if (psd
== NULL
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
620 /* The previous calls to GetShellSecurityDescriptor don't set the last error */
621 win_skip("GetShellSecurityDescriptor is not implemented\n");
624 if (psd
== INVALID_HANDLE_VALUE
)
626 win_skip("GetShellSecurityDescriptor is broken on IE5\n");
629 ok(psd
!=NULL
, "GetShellSecurityDescriptor failed\n");
632 BOOL bHasDacl
= FALSE
, bDefaulted
;
635 SECURITY_DESCRIPTOR_CONTROL control
;
637 ok(IsValidSecurityDescriptor(psd
), "returned value is not valid SD\n");
639 ok(GetSecurityDescriptorControl(psd
, &control
, &dwRev
),
640 "GetSecurityDescriptorControl failed with error %u\n", GetLastError());
641 ok(0 == (control
& SE_SELF_RELATIVE
), "SD should be absolute\n");
643 ok(GetSecurityDescriptorDacl(psd
, &bHasDacl
, &pAcl
, &bDefaulted
),
644 "GetSecurityDescriptorDacl failed with error %u\n", GetLastError());
646 ok(bHasDacl
, "SD has no DACL\n");
649 ok(!bDefaulted
, "DACL should not be defaulted\n");
651 ok(pAcl
!= NULL
, "NULL DACL!\n");
654 ACL_SIZE_INFORMATION asiSize
;
656 ok(IsValidAcl(pAcl
), "DACL is not valid\n");
658 ok(GetAclInformation(pAcl
, &asiSize
, sizeof(asiSize
), AclSizeInformation
),
659 "GetAclInformation failed with error %u\n", GetLastError());
661 ok(asiSize
.AceCount
== 3, "Incorrect number of ACEs: %d entries\n", asiSize
.AceCount
);
662 if (asiSize
.AceCount
== 3)
664 ACCESS_ALLOWED_ACE
*paaa
; /* will use for DENIED too */
666 ok(GetAce(pAcl
, 0, (LPVOID
*)&paaa
), "GetAce failed with error %u\n", GetLastError());
667 ok(paaa
->Header
.AceType
== ACCESS_ALLOWED_ACE_TYPE
,
668 "Invalid ACE type %d\n", paaa
->Header
.AceType
);
669 ok(paaa
->Header
.AceFlags
== 0, "Invalid ACE flags %x\n", paaa
->Header
.AceFlags
);
670 ok(paaa
->Mask
== GENERIC_ALL
, "Invalid ACE mask %x\n", paaa
->Mask
);
672 ok(GetAce(pAcl
, 1, (LPVOID
*)&paaa
), "GetAce failed with error %u\n", GetLastError());
673 ok(paaa
->Header
.AceType
== ACCESS_DENIED_ACE_TYPE
,
674 "Invalid ACE type %d\n", paaa
->Header
.AceType
);
675 /* first one of two ACEs generated from inheritable entry - without inheritance */
676 ok(paaa
->Header
.AceFlags
== 0, "Invalid ACE flags %x\n", paaa
->Header
.AceFlags
);
677 ok(paaa
->Mask
== GENERIC_WRITE
, "Invalid ACE mask %x\n", paaa
->Mask
);
679 ok(GetAce(pAcl
, 2, (LPVOID
*)&paaa
), "GetAce failed with error %u\n", GetLastError());
680 ok(paaa
->Header
.AceType
== ACCESS_DENIED_ACE_TYPE
,
681 "Invalid ACE type %d\n", paaa
->Header
.AceType
);
682 /* second ACE - with inheritance */
683 ok(paaa
->Header
.AceFlags
== MY_INHERITANCE
,
684 "Invalid ACE flags %x\n", paaa
->Header
.AceFlags
);
685 ok(paaa
->Mask
== GENERIC_READ
, "Invalid ACE mask %x\n", paaa
->Mask
);
694 static void test_SHPackDispParams(void)
700 if(!pSHPackDispParams
)
701 win_skip("SHPackSidpParams not available\n");
703 memset(¶ms
, 0xc0, sizeof(params
));
704 memset(vars
, 0xc0, sizeof(vars
));
705 hres
= pSHPackDispParams(¶ms
, vars
, 1, VT_I4
, 0xdeadbeef);
706 ok(hres
== S_OK
, "SHPackDispParams failed: %08x\n", hres
);
707 ok(params
.cArgs
== 1, "params.cArgs = %d\n", params
.cArgs
);
708 ok(params
.cNamedArgs
== 0, "params.cNamedArgs = %d\n", params
.cArgs
);
709 ok(params
.rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", params
.rgdispidNamedArgs
);
710 ok(params
.rgvarg
== vars
, "params.rgvarg = %p\n", params
.rgvarg
);
711 ok(V_VT(vars
) == VT_I4
, "V_VT(var) = %d\n", V_VT(vars
));
712 ok(V_I4(vars
) == 0xdeadbeef, "failed %x\n", V_I4(vars
));
714 memset(¶ms
, 0xc0, sizeof(params
));
715 hres
= pSHPackDispParams(¶ms
, NULL
, 0, 0);
716 ok(hres
== S_OK
, "SHPackDispParams failed: %08x\n", hres
);
717 ok(params
.cArgs
== 0, "params.cArgs = %d\n", params
.cArgs
);
718 ok(params
.cNamedArgs
== 0, "params.cNamedArgs = %d\n", params
.cArgs
);
719 ok(params
.rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", params
.rgdispidNamedArgs
);
720 ok(params
.rgvarg
== NULL
, "params.rgvarg = %p\n", params
.rgvarg
);
722 memset(vars
, 0xc0, sizeof(vars
));
723 memset(¶ms
, 0xc0, sizeof(params
));
724 hres
= pSHPackDispParams(¶ms
, vars
, 4, VT_BSTR
, (void*)0xdeadbeef, VT_EMPTY
, 10,
725 VT_I4
, 100, VT_DISPATCH
, (void*)0xdeadbeef);
726 ok(hres
== S_OK
, "SHPackDispParams failed: %08x\n", hres
);
727 ok(params
.cArgs
== 4, "params.cArgs = %d\n", params
.cArgs
);
728 ok(params
.cNamedArgs
== 0, "params.cNamedArgs = %d\n", params
.cArgs
);
729 ok(params
.rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", params
.rgdispidNamedArgs
);
730 ok(params
.rgvarg
== vars
, "params.rgvarg = %p\n", params
.rgvarg
);
731 ok(V_VT(vars
) == VT_DISPATCH
, "V_VT(vars[0]) = %x\n", V_VT(vars
));
732 ok(V_I4(vars
) == 0xdeadbeef, "V_I4(vars[0]) = %x\n", V_I4(vars
));
733 ok(V_VT(vars
+1) == VT_I4
, "V_VT(vars[1]) = %d\n", V_VT(vars
+1));
734 ok(V_I4(vars
+1) == 100, "V_I4(vars[1]) = %x\n", V_I4(vars
+1));
735 ok(V_VT(vars
+2) == VT_I4
, "V_VT(vars[2]) = %d\n", V_VT(vars
+2));
736 ok(V_I4(vars
+2) == 10, "V_I4(vars[2]) = %x\n", V_I4(vars
+2));
737 ok(V_VT(vars
+3) == VT_BSTR
, "V_VT(vars[3]) = %d\n", V_VT(vars
+3));
738 ok(V_BSTR(vars
+3) == (void*)0xdeadbeef, "V_BSTR(vars[3]) = %p\n", V_BSTR(vars
+3));
743 const IDispatchVtbl
*vtbl
;
747 typedef struct _contain
749 const IConnectionPointContainerVtbl
*vtbl
;
753 IConnectionPoint
**pt
;
756 typedef struct _cntptn
758 const IConnectionPointVtbl
*vtbl
;
769 const IEnumConnectionsVtbl
*vtbl
;
776 typedef struct _enumpt
778 const IEnumConnectionPointsVtbl
*vtbl
;
786 static HRESULT WINAPI
Disp_QueryInterface(
793 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDispatch
))
800 IUnknown_AddRef(This
);
804 trace("no interface\n");
805 return E_NOINTERFACE
;
808 static ULONG WINAPI
Disp_AddRef(IDispatch
* This
)
810 Disp
*iface
= (Disp
*)This
;
811 return InterlockedIncrement(&iface
->refCount
);
814 static ULONG WINAPI
Disp_Release(IDispatch
* This
)
816 Disp
*iface
= (Disp
*)This
;
819 ret
= InterlockedDecrement(&iface
->refCount
);
821 HeapFree(GetProcessHeap(),0,This
);
825 static HRESULT WINAPI
Disp_GetTypeInfoCount(
829 return ERROR_SUCCESS
;
832 static HRESULT WINAPI
Disp_GetTypeInfo(
838 return ERROR_SUCCESS
;
841 static HRESULT WINAPI
Disp_GetIDsOfNames(
849 return ERROR_SUCCESS
;
852 static HRESULT WINAPI
Disp_Invoke(
858 DISPPARAMS
*pDispParams
,
860 EXCEPINFO
*pExcepInfo
,
863 trace("%p %x %p %x %x %p %p %p %p\n",This
,dispIdMember
,riid
,lcid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,puArgErr
);
865 ok(dispIdMember
== 0xa0 || dispIdMember
== 0xa1, "Unknown dispIdMember\n");
866 ok(pDispParams
!= NULL
, "Invoked with NULL pDispParams\n");
867 ok(wFlags
== DISPATCH_METHOD
, "Wrong flags %x\n",wFlags
);
868 ok(lcid
== 0,"Wrong lcid %x\n",lcid
);
869 if (dispIdMember
== 0xa0)
871 ok(pDispParams
->cArgs
== 0, "params.cArgs = %d\n", pDispParams
->cArgs
);
872 ok(pDispParams
->cNamedArgs
== 0, "params.cNamedArgs = %d\n", pDispParams
->cArgs
);
873 ok(pDispParams
->rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", pDispParams
->rgdispidNamedArgs
);
874 ok(pDispParams
->rgvarg
== NULL
, "params.rgvarg = %p\n", pDispParams
->rgvarg
);
876 else if (dispIdMember
== 0xa1)
878 ok(pDispParams
->cArgs
== 2, "params.cArgs = %d\n", pDispParams
->cArgs
);
879 ok(pDispParams
->cNamedArgs
== 0, "params.cNamedArgs = %d\n", pDispParams
->cArgs
);
880 ok(pDispParams
->rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", pDispParams
->rgdispidNamedArgs
);
881 ok(V_VT(pDispParams
->rgvarg
) == VT_BSTR
, "V_VT(var) = %d\n", V_VT(pDispParams
->rgvarg
));
882 ok(V_I4(pDispParams
->rgvarg
) == 0xdeadcafe , "failed %p\n", V_BSTR(pDispParams
->rgvarg
));
883 ok(V_VT(pDispParams
->rgvarg
+1) == VT_I4
, "V_VT(var) = %d\n", V_VT(pDispParams
->rgvarg
+1));
884 ok(V_I4(pDispParams
->rgvarg
+1) == 0xdeadbeef, "failed %x\n", V_I4(pDispParams
->rgvarg
+1));
887 return ERROR_SUCCESS
;
890 static const IDispatchVtbl disp_vtbl
= {
895 Disp_GetTypeInfoCount
,
901 static HRESULT WINAPI
Enum_QueryInterface(
902 IEnumConnections
* This
,
908 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IEnumConnections
))
915 IUnknown_AddRef(This
);
919 trace("no interface\n");
920 return E_NOINTERFACE
;
923 static ULONG WINAPI
Enum_AddRef(IEnumConnections
* This
)
925 EnumCon
*iface
= (EnumCon
*)This
;
926 return InterlockedIncrement(&iface
->refCount
);
929 static ULONG WINAPI
Enum_Release(IEnumConnections
* This
)
931 EnumCon
*iface
= (EnumCon
*)This
;
934 ret
= InterlockedDecrement(&iface
->refCount
);
936 HeapFree(GetProcessHeap(),0,This
);
940 static HRESULT WINAPI
Enum_Next(
941 IEnumConnections
* This
,
946 EnumCon
*iface
= (EnumCon
*)This
;
948 if (cConnections
> 0 && iface
->idx
< iface
->pt
->sinkCount
)
950 rgcd
->pUnk
= iface
->pt
->sink
[iface
->idx
];
951 IUnknown_AddRef(iface
->pt
->sink
[iface
->idx
]);
962 static HRESULT WINAPI
Enum_Skip(
963 IEnumConnections
* This
,
969 static HRESULT WINAPI
Enum_Reset(
970 IEnumConnections
* This
)
975 static HRESULT WINAPI
Enum_Clone(
976 IEnumConnections
* This
,
977 IEnumConnections
**ppEnum
)
982 static const IEnumConnectionsVtbl enum_vtbl
= {
993 static HRESULT WINAPI
ConPt_QueryInterface(
994 IConnectionPoint
* This
,
1000 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IConnectionPoint
))
1007 IUnknown_AddRef(This
);
1011 trace("no interface\n");
1012 return E_NOINTERFACE
;
1015 static ULONG WINAPI
ConPt_AddRef(
1016 IConnectionPoint
* This
)
1018 ConPt
*iface
= (ConPt
*)This
;
1019 return InterlockedIncrement(&iface
->refCount
);
1022 static ULONG WINAPI
ConPt_Release(
1023 IConnectionPoint
* This
)
1025 ConPt
*iface
= (ConPt
*)This
;
1028 ret
= InterlockedDecrement(&iface
->refCount
);
1031 if (iface
->sinkCount
> 0)
1034 for (i
= 0; i
< iface
->sinkCount
; i
++)
1037 IUnknown_Release(iface
->sink
[i
]);
1039 HeapFree(GetProcessHeap(),0,iface
->sink
);
1041 HeapFree(GetProcessHeap(),0,This
);
1046 static HRESULT WINAPI
ConPt_GetConnectionInterface(
1047 IConnectionPoint
* This
,
1051 ConPt
*iface
= (ConPt
*)This
;
1058 memcpy(pIID
,&iface
->id
,sizeof(GUID
));
1062 static HRESULT WINAPI
ConPt_GetConnectionPointContainer(
1063 IConnectionPoint
* This
,
1064 IConnectionPointContainer
**ppCPC
)
1066 ConPt
*iface
= (ConPt
*)This
;
1068 *ppCPC
= (IConnectionPointContainer
*)iface
->container
;
1072 static HRESULT WINAPI
ConPt_Advise(
1073 IConnectionPoint
* This
,
1077 ConPt
*iface
= (ConPt
*)This
;
1079 if (iface
->sinkCount
== 0)
1080 iface
->sink
= HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown
*));
1082 iface
->sink
= HeapReAlloc(GetProcessHeap(),0,iface
->sink
,sizeof(IUnknown
*)*(iface
->sinkCount
+1));
1083 iface
->sink
[iface
->sinkCount
] = pUnkSink
;
1084 IUnknown_AddRef(pUnkSink
);
1086 *pdwCookie
= iface
->sinkCount
;
1090 static HRESULT WINAPI
ConPt_Unadvise(
1091 IConnectionPoint
* This
,
1094 ConPt
*iface
= (ConPt
*)This
;
1096 if (dwCookie
> iface
->sinkCount
)
1100 IUnknown_Release(iface
->sink
[dwCookie
-1]);
1101 iface
->sink
[dwCookie
-1] = NULL
;
1106 static HRESULT WINAPI
ConPt_EnumConnections(
1107 IConnectionPoint
* This
,
1108 IEnumConnections
**ppEnum
)
1112 ec
= HeapAlloc(GetProcessHeap(),0,sizeof(EnumCon
));
1113 ec
->vtbl
= &enum_vtbl
;
1115 ec
->pt
= (ConPt
*)This
;
1117 *ppEnum
= (IEnumConnections
*)ec
;
1122 static const IConnectionPointVtbl point_vtbl
= {
1123 ConPt_QueryInterface
,
1127 ConPt_GetConnectionInterface
,
1128 ConPt_GetConnectionPointContainer
,
1131 ConPt_EnumConnections
1134 static HRESULT WINAPI
EnumPt_QueryInterface(
1135 IEnumConnectionPoints
* This
,
1141 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IEnumConnectionPoints
))
1148 IUnknown_AddRef(This
);
1152 trace("no interface\n");
1153 return E_NOINTERFACE
;
1156 static ULONG WINAPI
EnumPt_AddRef(IEnumConnectionPoints
* This
)
1158 EnumPt
*iface
= (EnumPt
*)This
;
1159 return InterlockedIncrement(&iface
->refCount
);
1162 static ULONG WINAPI
EnumPt_Release(IEnumConnectionPoints
* This
)
1164 EnumPt
*iface
= (EnumPt
*)This
;
1167 ret
= InterlockedDecrement(&iface
->refCount
);
1169 HeapFree(GetProcessHeap(),0,This
);
1173 static HRESULT WINAPI
EnumPt_Next(
1174 IEnumConnectionPoints
* This
,
1176 IConnectionPoint
**rgcd
,
1179 EnumPt
*iface
= (EnumPt
*)This
;
1181 if (cConnections
> 0 && iface
->idx
< iface
->container
->ptCount
)
1183 *rgcd
= iface
->container
->pt
[iface
->idx
];
1184 IUnknown_AddRef(iface
->container
->pt
[iface
->idx
]);
1194 static HRESULT WINAPI
EnumPt_Skip(
1195 IEnumConnectionPoints
* This
,
1201 static HRESULT WINAPI
EnumPt_Reset(
1202 IEnumConnectionPoints
* This
)
1207 static HRESULT WINAPI
EnumPt_Clone(
1208 IEnumConnectionPoints
* This
,
1209 IEnumConnectionPoints
**ppEnumPt
)
1214 static const IEnumConnectionPointsVtbl enumpt_vtbl
= {
1216 EnumPt_QueryInterface
,
1225 static HRESULT WINAPI
Contain_QueryInterface(
1226 IConnectionPointContainer
* This
,
1232 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IConnectionPointContainer
))
1239 IUnknown_AddRef(This
);
1243 trace("no interface\n");
1244 return E_NOINTERFACE
;
1247 static ULONG WINAPI
Contain_AddRef(
1248 IConnectionPointContainer
* This
)
1250 Contain
*iface
= (Contain
*)This
;
1251 return InterlockedIncrement(&iface
->refCount
);
1254 static ULONG WINAPI
Contain_Release(
1255 IConnectionPointContainer
* This
)
1257 Contain
*iface
= (Contain
*)This
;
1260 ret
= InterlockedDecrement(&iface
->refCount
);
1263 if (iface
->ptCount
> 0)
1266 for (i
= 0; i
< iface
->ptCount
; i
++)
1267 IUnknown_Release(iface
->pt
[i
]);
1268 HeapFree(GetProcessHeap(),0,iface
->pt
);
1270 HeapFree(GetProcessHeap(),0,This
);
1275 static HRESULT WINAPI
Contain_EnumConnectionPoints(
1276 IConnectionPointContainer
* This
,
1277 IEnumConnectionPoints
**ppEnum
)
1281 ec
= HeapAlloc(GetProcessHeap(),0,sizeof(EnumPt
));
1282 ec
->vtbl
= &enumpt_vtbl
;
1285 ec
->container
= (Contain
*)This
;
1286 *ppEnum
= (IEnumConnectionPoints
*)ec
;
1291 static HRESULT WINAPI
Contain_FindConnectionPoint(
1292 IConnectionPointContainer
* This
,
1294 IConnectionPoint
**ppCP
)
1296 Contain
*iface
= (Contain
*)This
;
1299 if (!IsEqualIID(riid
, &IID_NULL
) || iface
->ptCount
==0)
1301 pt
= HeapAlloc(GetProcessHeap(),0,sizeof(ConPt
));
1302 pt
->vtbl
= &point_vtbl
;
1306 pt
->container
= iface
;
1307 pt
->id
= IID_IDispatch
;
1309 if (iface
->ptCount
== 0)
1310 iface
->pt
=HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown
*));
1312 iface
->pt
= HeapReAlloc(GetProcessHeap(),0,iface
->pt
,sizeof(IUnknown
*)*(iface
->ptCount
+1));
1313 iface
->pt
[iface
->ptCount
] = (IConnectionPoint
*)pt
;
1316 *ppCP
= (IConnectionPoint
*)pt
;
1320 *ppCP
= iface
->pt
[0];
1321 IUnknown_AddRef((IUnknown
*)*ppCP
);
1327 static const IConnectionPointContainerVtbl contain_vtbl
= {
1328 Contain_QueryInterface
,
1332 Contain_EnumConnectionPoints
,
1333 Contain_FindConnectionPoint
1336 static void test_IConnectionPoint(void)
1340 IConnectionPoint
*point
;
1343 DWORD cookie
= 0xffffffff;
1347 if (!pIConnectionPoint_SimpleInvoke
|| !pConnectToConnectionPoint
)
1349 win_skip("IConnectionPoint Apis not present\n");
1353 container
= HeapAlloc(GetProcessHeap(),0,sizeof(Contain
));
1354 container
->vtbl
= &contain_vtbl
;
1355 container
->refCount
= 1;
1356 container
->ptCount
= 0;
1357 container
->pt
= NULL
;
1359 dispatch
= HeapAlloc(GetProcessHeap(),0,sizeof(Disp
));
1360 dispatch
->vtbl
= &disp_vtbl
;
1361 dispatch
->refCount
= 1;
1363 rc
= pConnectToConnectionPoint((IUnknown
*)dispatch
, &IID_NULL
, TRUE
, (IUnknown
*)container
, &cookie
, &point
);
1364 ok(rc
== S_OK
, "pConnectToConnectionPoint failed with %x\n",rc
);
1365 ok(point
!= NULL
, "returned ConnectionPoint is NULL\n");
1366 ok(cookie
!= 0xffffffff, "invalid cookie returned\n");
1368 rc
= pIConnectionPoint_SimpleInvoke(point
,0xa0,NULL
);
1369 ok(rc
== S_OK
, "pConnectToConnectionPoint failed with %x\n",rc
);
1371 if (pSHPackDispParams
)
1373 memset(¶ms
, 0xc0, sizeof(params
));
1374 memset(vars
, 0xc0, sizeof(vars
));
1375 rc
= pSHPackDispParams(¶ms
, vars
, 2, VT_I4
, 0xdeadbeef, VT_BSTR
, 0xdeadcafe);
1376 ok(rc
== S_OK
, "SHPackDispParams failed: %08x\n", rc
);
1378 rc
= pIConnectionPoint_SimpleInvoke(point
,0xa1,¶ms
);
1379 ok(rc
== S_OK
, "pConnectToConnectionPoint failed with %x\n",rc
);
1382 win_skip("pSHPackDispParams not present\n");
1384 rc
= pConnectToConnectionPoint(NULL
, &IID_NULL
, FALSE
, (IUnknown
*)container
, &cookie
, NULL
);
1385 ok(rc
== S_OK
, "pConnectToConnectionPoint failed with %x\n",rc
);
1387 /* MSDN says this should be required but it crashs on XP
1388 IUnknown_Release(point);
1390 ref
= IUnknown_Release((IUnknown
*)container
);
1391 ok(ref
== 0, "leftover IConnectionPointContainer reference %i\n",ref
);
1392 ref
= IUnknown_Release((IUnknown
*)dispatch
);
1393 ok(ref
== 0, "leftover IDispatch reference %i\n",ref
);
1396 typedef struct _propbag
1398 const IPropertyBagVtbl
*vtbl
;
1404 static HRESULT WINAPI
Prop_QueryInterface(
1411 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IPropertyBag
))
1418 IUnknown_AddRef(This
);
1422 trace("no interface\n");
1423 return E_NOINTERFACE
;
1426 static ULONG WINAPI
Prop_AddRef(
1429 PropBag
*iface
= (PropBag
*)This
;
1430 return InterlockedIncrement(&iface
->refCount
);
1433 static ULONG WINAPI
Prop_Release(
1436 PropBag
*iface
= (PropBag
*)This
;
1439 ret
= InterlockedDecrement(&iface
->refCount
);
1441 HeapFree(GetProcessHeap(),0,This
);
1445 static HRESULT WINAPI
Prop_Read(
1447 LPCOLESTR pszPropName
,
1449 IErrorLog
*pErrorLog
)
1451 V_VT(pVar
) = VT_BLOB
|VT_BYREF
;
1452 V_BYREF(pVar
) = (LPVOID
)0xdeadcafe;
1456 static HRESULT WINAPI
Prop_Write(
1458 LPCOLESTR pszPropName
,
1465 static const IPropertyBagVtbl prop_vtbl
= {
1466 Prop_QueryInterface
,
1474 static void test_SHPropertyBag_ReadLONG(void)
1479 static const WCHAR szName1
[] = {'n','a','m','e','1',0};
1481 if (!pSHPropertyBag_ReadLONG
)
1483 win_skip("SHPropertyBag_ReadLONG not present\n");
1487 pb
= HeapAlloc(GetProcessHeap(),0,sizeof(PropBag
));
1489 pb
->vtbl
= &prop_vtbl
;
1492 rc
= pSHPropertyBag_ReadLONG(NULL
, szName1
, &out
);
1493 ok(rc
== E_INVALIDARG
|| broken(rc
== 0), "incorrect return %x\n",rc
);
1494 ok(out
== 0xfeedface, "value should not have changed\n");
1495 rc
= pSHPropertyBag_ReadLONG((IPropertyBag
*)pb
, NULL
, &out
);
1496 ok(rc
== E_INVALIDARG
|| broken(rc
== 0) || broken(rc
== 1), "incorrect return %x\n",rc
);
1497 ok(out
== 0xfeedface, "value should not have changed\n");
1498 rc
= pSHPropertyBag_ReadLONG((IPropertyBag
*)pb
, szName1
, NULL
);
1499 ok(rc
== E_INVALIDARG
|| broken(rc
== 0) || broken(rc
== 1), "incorrect return %x\n",rc
);
1500 ok(out
== 0xfeedface, "value should not have changed\n");
1501 rc
= pSHPropertyBag_ReadLONG((IPropertyBag
*)pb
, szName1
, &out
);
1502 ok(rc
== DISP_E_BADVARTYPE
|| broken(rc
== 0) || broken(rc
== 1), "incorrect return %x\n",rc
);
1503 ok(out
== 0xfeedface || broken(out
== 0xfeedfa00), "value should not have changed %x\n",out
);
1504 IUnknown_Release((IUnknown
*)pb
);
1509 static void test_SHSetWindowBits(void)
1512 DWORD style
, styleold
;
1515 if(!pSHSetWindowBits
)
1517 win_skip("SHSetWindowBits is not available\n");
1522 clsA
.lpfnWndProc
= DefWindowProcA
;
1523 clsA
.cbClsExtra
= 0;
1524 clsA
.cbWndExtra
= 0;
1525 clsA
.hInstance
= GetModuleHandleA(NULL
);
1527 clsA
.hCursor
= LoadCursorA(0, IDC_ARROW
);
1528 clsA
.hbrBackground
= NULL
;
1529 clsA
.lpszMenuName
= NULL
;
1530 clsA
.lpszClassName
= "Shlwapi test class";
1531 RegisterClassA(&clsA
);
1533 hwnd
= CreateWindowA("Shlwapi test class", "Test", WS_VISIBLE
, 0, 0, 100, 100,
1534 NULL
, NULL
, GetModuleHandle(NULL
), 0);
1535 ok(IsWindow(hwnd
), "failed to create window\n");
1538 SetLastError(0xdeadbeef);
1539 style
= pSHSetWindowBits(NULL
, GWL_STYLE
, 0, 0);
1540 ok(style
== 0, "expected 0 retval, got %d\n", style
);
1541 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
||
1542 broken(GetLastError() == 0xdeadbeef), /* Win9x/WinMe */
1543 "expected ERROR_INVALID_WINDOW_HANDLE, got %d\n", GetLastError());
1545 /* zero mask, zero flags */
1546 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1547 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, 0, 0);
1548 ok(styleold
== style
, "expected old style\n");
1549 ok(styleold
== GetWindowLongA(hwnd
, GWL_STYLE
), "expected to keep old style\n");
1552 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1553 ok(styleold
& WS_VISIBLE
, "expected WS_VISIBLE\n");
1554 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, WS_VISIBLE
, 0);
1556 ok(style
== styleold
, "expected previous style, got %x\n", style
);
1557 ok((GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
) == 0, "expected updated style\n");
1559 /* test mask, unset style bit used */
1560 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1561 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, WS_VISIBLE
, 0);
1562 ok(style
== styleold
, "expected previous style, got %x\n", style
);
1563 ok(styleold
== GetWindowLongA(hwnd
, GWL_STYLE
), "expected to keep old style\n");
1565 /* set back with flags */
1566 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1567 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, WS_VISIBLE
, WS_VISIBLE
);
1568 ok(style
== styleold
, "expected previous style, got %x\n", style
);
1569 ok(GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
, "expected updated style\n");
1571 /* reset and try to set without a mask */
1572 pSHSetWindowBits(hwnd
, GWL_STYLE
, WS_VISIBLE
, 0);
1573 ok((GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
) == 0, "expected updated style\n");
1574 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1575 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, 0, WS_VISIBLE
);
1576 ok(style
== styleold
, "expected previous style, got %x\n", style
);
1577 ok((GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
) == 0, "expected updated style\n");
1579 DestroyWindow(hwnd
);
1581 UnregisterClassA("Shlwapi test class", GetModuleHandleA(NULL
));
1584 static void test_SHFormatDateTimeA(void)
1586 FILETIME UNALIGNED filetime
;
1587 CHAR buff
[100], buff2
[100], buff3
[100];
1592 if(!pSHFormatDateTimeA
)
1594 win_skip("pSHFormatDateTimeA isn't available\n");
1600 /* crashes on native */
1601 ret
= pSHFormatDateTimeA(NULL
, NULL
, NULL
, 0);
1605 SystemTimeToFileTime(&st
, &filetime
);
1606 /* SHFormatDateTime expects input as utc */
1607 LocalFileTimeToFileTime(&filetime
, &filetime
);
1609 /* no way to get required buffer length here */
1610 SetLastError(0xdeadbeef);
1611 ret
= pSHFormatDateTimeA(&filetime
, NULL
, NULL
, 0);
1612 ok(ret
== 0, "got %d\n", ret
);
1613 ok(GetLastError() == 0xdeadbeef || broken(GetLastError() == ERROR_SUCCESS
/* Win7 */),
1614 "expected 0xdeadbeef, got %d\n", GetLastError());
1616 SetLastError(0xdeadbeef);
1617 buff
[0] = 'a'; buff
[1] = 0;
1618 ret
= pSHFormatDateTimeA(&filetime
, NULL
, buff
, 0);
1619 ok(ret
== 0, "got %d\n", ret
);
1620 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1621 ok(buff
[0] == 'a', "expected same string, got %s\n", buff
);
1623 /* flags needs to have FDTF_NOAUTOREADINGORDER for these tests to succeed on Vista+ */
1625 /* all combinations documented as invalid succeeded */
1626 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTTIME
| FDTF_LONGTIME
;
1627 SetLastError(0xdeadbeef);
1628 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1629 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1630 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1632 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTDATE
| FDTF_LONGDATE
;
1633 SetLastError(0xdeadbeef);
1634 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1635 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1636 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1638 flags
= FDTF_SHORTDATE
| FDTF_LTRDATE
| FDTF_RTLDATE
;
1639 SetLastError(0xdeadbeef);
1640 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1641 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1642 ok(GetLastError() == 0xdeadbeef ||
1643 broken(GetLastError() == ERROR_INVALID_FLAGS
), /* Win9x/WinMe */
1644 "expected 0xdeadbeef, got %d\n", GetLastError());
1646 /* now check returned strings */
1647 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTTIME
;
1648 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1649 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1650 ret
= GetTimeFormat(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff2
, sizeof(buff2
));
1651 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1652 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1654 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGTIME
;
1655 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1656 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1657 ret
= GetTimeFormat(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff2
, sizeof(buff2
));
1658 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1659 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1661 /* both time flags */
1662 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGTIME
| FDTF_SHORTTIME
;
1663 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1664 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1665 ret
= GetTimeFormat(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff2
, sizeof(buff2
));
1666 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1667 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1669 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTDATE
;
1670 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1671 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1672 ret
= GetDateFormat(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1673 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1674 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1676 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGDATE
;
1677 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1678 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1679 ret
= GetDateFormat(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1680 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1681 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1683 /* both date flags */
1684 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGDATE
| FDTF_SHORTDATE
;
1685 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1686 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1687 ret
= GetDateFormat(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1688 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1689 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1691 /* various combinations of date/time flags */
1692 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGDATE
| FDTF_SHORTTIME
;
1693 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1694 ok(ret
== lstrlenA(buff
)+1, "got %d, length %d\n", ret
, lstrlenA(buff
)+1);
1695 ret
= GetDateFormat(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1696 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1697 strcat(buff2
, ", ");
1698 ret
= GetTimeFormat(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff3
, sizeof(buff3
));
1699 ok(ret
== lstrlenA(buff3
)+1, "got %d\n", ret
);
1700 strcat(buff2
, buff3
);
1701 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1703 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGDATE
| FDTF_LONGTIME
;
1704 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1705 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1706 ret
= GetDateFormat(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1707 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1708 strcat(buff2
, ", ");
1709 ret
= GetTimeFormat(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff3
, sizeof(buff3
));
1710 ok(ret
== lstrlenA(buff3
)+1, "got %d\n", ret
);
1711 strcat(buff2
, buff3
);
1712 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1714 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTDATE
| FDTF_SHORTTIME
;
1715 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1716 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1717 ret
= GetDateFormat(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1718 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1720 ret
= GetTimeFormat(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff3
, sizeof(buff3
));
1721 ok(ret
== lstrlenA(buff3
)+1, "got %d\n", ret
);
1722 strcat(buff2
, buff3
);
1723 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1725 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTDATE
| FDTF_LONGTIME
;
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_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1729 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1731 ret
= GetTimeFormat(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff3
, sizeof(buff3
));
1732 ok(ret
== lstrlenA(buff3
)+1, "got %d\n", ret
);
1733 strcat(buff2
, buff3
);
1734 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1737 static void test_SHFormatDateTimeW(void)
1739 FILETIME UNALIGNED filetime
;
1740 WCHAR buff
[100], buff2
[100], buff3
[100];
1744 static const WCHAR spaceW
[] = {' ',0};
1745 static const WCHAR commaW
[] = {',',' ',0};
1747 if(!pSHFormatDateTimeW
)
1749 win_skip("pSHFormatDateTimeW isn't available\n");
1755 /* crashes on native */
1756 ret
= pSHFormatDateTimeW(NULL
, NULL
, NULL
, 0);
1760 SystemTimeToFileTime(&st
, &filetime
);
1761 /* SHFormatDateTime expects input as utc */
1762 LocalFileTimeToFileTime(&filetime
, &filetime
);
1764 /* no way to get required buffer length here */
1765 SetLastError(0xdeadbeef);
1766 ret
= pSHFormatDateTimeW(&filetime
, NULL
, NULL
, 0);
1767 ok(ret
== 0, "got %d\n", ret
);
1768 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1770 SetLastError(0xdeadbeef);
1771 buff
[0] = 'a'; buff
[1] = 0;
1772 ret
= pSHFormatDateTimeW(&filetime
, NULL
, buff
, 0);
1773 ok(ret
== 0, "got %d\n", ret
);
1774 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1775 ok(buff
[0] == 'a', "expected same string\n");
1777 /* all combinations documented as invalid succeeded */
1778 flags
= FDTF_SHORTTIME
| FDTF_LONGTIME
;
1779 SetLastError(0xdeadbeef);
1780 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1781 ok(ret
== lstrlenW(buff
)+1, "got %d\n", ret
);
1782 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1784 flags
= FDTF_SHORTDATE
| FDTF_LONGDATE
;
1785 SetLastError(0xdeadbeef);
1786 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1787 ok(ret
== lstrlenW(buff
)+1, "got %d\n", ret
);
1788 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1790 flags
= FDTF_SHORTDATE
| FDTF_LTRDATE
| FDTF_RTLDATE
;
1791 SetLastError(0xdeadbeef);
1792 buff
[0] = 0; /* NT4 doesn't clear the buffer on failure */
1793 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1794 ok(ret
== lstrlenW(buff
)+1, "got %d\n", ret
);
1795 ok(GetLastError() == 0xdeadbeef ||
1796 broken(GetLastError() == ERROR_INVALID_FLAGS
), /* Win9x/WinMe/NT4 */
1797 "expected 0xdeadbeef, got %d\n", GetLastError());
1799 /* now check returned strings */
1800 flags
= FDTF_SHORTTIME
;
1801 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1802 ok(ret
== lstrlenW(buff
)+1, "got %d\n", ret
);
1803 SetLastError(0xdeadbeef);
1804 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1805 if (ret
== 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
1807 win_skip("Needed W-functions are not implemented\n");
1810 ok(ret
== lstrlenW(buff2
)+1, "got %d\n", ret
);
1811 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1813 flags
= FDTF_LONGTIME
;
1814 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1815 ok(ret
== lstrlenW(buff
)+1, "got %d\n", ret
);
1816 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1817 ok(ret
== lstrlenW(buff2
)+1, "got %d\n", ret
);
1818 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1820 /* both time flags */
1821 flags
= FDTF_LONGTIME
| FDTF_SHORTTIME
;
1822 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1823 ok(ret
== lstrlenW(buff
)+1, "got %d\n", ret
);
1824 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1825 ok(ret
== lstrlenW(buff2
)+1, "got %d\n", ret
);
1826 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal string\n");
1828 flags
= FDTF_SHORTDATE
;
1829 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1830 ok(ret
== lstrlenW(buff
)+1, "got %d\n", ret
);
1831 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1832 ok(ret
== lstrlenW(buff2
)+1, "got %d\n", ret
);
1833 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1835 flags
= FDTF_LONGDATE
;
1836 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1837 ok(ret
== lstrlenW(buff
)+1, "got %d\n", ret
);
1838 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1839 ok(ret
== lstrlenW(buff2
)+1, "got %d\n", ret
);
1840 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1842 /* both date flags */
1843 flags
= FDTF_LONGDATE
| FDTF_SHORTDATE
;
1844 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1845 ok(ret
== lstrlenW(buff
)+1, "got %d\n", ret
);
1846 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1847 ok(ret
== lstrlenW(buff2
)+1, "got %d\n", ret
);
1848 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1850 /* various combinations of date/time flags */
1851 flags
= FDTF_LONGDATE
| FDTF_SHORTTIME
;
1852 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1853 ok(ret
== lstrlenW(buff
)+1, "got %d, length %d\n", ret
, lstrlenW(buff
)+1);
1854 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1855 ok(ret
== lstrlenW(buff2
)+1, "got %d\n", ret
);
1856 lstrcatW(buff2
, commaW
);
1857 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff3
, sizeof(buff3
)/sizeof(WCHAR
));
1858 ok(ret
== lstrlenW(buff3
)+1, "got %d\n", ret
);
1859 lstrcatW(buff2
, buff3
);
1860 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1862 flags
= FDTF_LONGDATE
| FDTF_LONGTIME
;
1863 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1864 ok(ret
== lstrlenW(buff
)+1, "got %d\n", ret
);
1865 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1866 ok(ret
== lstrlenW(buff2
)+1, "got %d\n", ret
);
1867 lstrcatW(buff2
, commaW
);
1868 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff3
, sizeof(buff3
)/sizeof(WCHAR
));
1869 ok(ret
== lstrlenW(buff3
)+1, "got %d\n", ret
);
1870 lstrcatW(buff2
, buff3
);
1871 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1873 flags
= FDTF_SHORTDATE
| FDTF_SHORTTIME
;
1874 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1875 ok(ret
== lstrlenW(buff
)+1, "got %d\n", ret
);
1876 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1877 ok(ret
== lstrlenW(buff2
)+1, "got %d\n", ret
);
1878 lstrcatW(buff2
, spaceW
);
1879 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff3
, sizeof(buff3
)/sizeof(WCHAR
));
1880 ok(ret
== lstrlenW(buff3
)+1, "got %d\n", ret
);
1881 lstrcatW(buff2
, buff3
);
1882 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1884 flags
= FDTF_SHORTDATE
| FDTF_LONGTIME
;
1885 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1886 ok(ret
== lstrlenW(buff
)+1, "got %d\n", ret
);
1887 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1888 ok(ret
== lstrlenW(buff2
)+1, "got %d\n", ret
);
1889 lstrcatW(buff2
, spaceW
);
1890 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff3
, sizeof(buff3
)/sizeof(WCHAR
));
1891 ok(ret
== lstrlenW(buff3
)+1, "got %d\n", ret
);
1892 lstrcatW(buff2
, buff3
);
1893 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1896 static void test_SHGetObjectCompatFlags(void)
1898 struct compat_value
{
1903 struct compat_value values
[] = {
1904 { "OTNEEDSSFCACHE", 0x1 },
1905 { "NO_WEBVIEW", 0x2 },
1906 { "UNBINDABLE", 0x4 },
1908 { "NEEDSFILESYSANCESTOR", 0x10 },
1909 { "NOTAFILESYSTEM", 0x20 },
1910 { "CTXMENU_NOVERBS", 0x40 },
1911 { "CTXMENU_LIMITEDQI", 0x80 },
1912 { "COCREATESHELLFOLDERONLY", 0x100 },
1913 { "NEEDSSTORAGEANCESTOR", 0x200 },
1914 { "NOLEGACYWEBVIEW", 0x400 },
1915 { "CTXMENU_XPQCMFLAGS", 0x1000 },
1916 { "NOIPROPERTYSTORE", 0x2000 }
1919 static const char compat_path
[] = "Software\\Microsoft\\Windows\\CurrentVersion\\ShellCompatibility\\Objects";
1920 void *pColorAdjustLuma
= GetProcAddress(hShlwapi
, "ColorAdjustLuma");
1921 CHAR keyA
[39]; /* {CLSID} */
1926 if (!pSHGetObjectCompatFlags
)
1928 win_skip("SHGetObjectCompatFlags isn't available\n");
1932 if (pColorAdjustLuma
&& pColorAdjustLuma
== pSHGetObjectCompatFlags
) /* win2k */
1934 win_skip("Skipping SHGetObjectCompatFlags, same ordinal used for ColorAdjustLuma\n");
1939 ret
= pSHGetObjectCompatFlags(NULL
, NULL
);
1940 ok(ret
== 0, "got %d\n", ret
);
1942 ret
= RegOpenKeyA(HKEY_LOCAL_MACHINE
, compat_path
, &root
);
1943 if (ret
!= ERROR_SUCCESS
)
1945 skip("No compatibility class data found\n");
1949 for (i
= 0; RegEnumKeyA(root
, i
, keyA
, sizeof(keyA
)) == ERROR_SUCCESS
; i
++)
1953 if (RegOpenKeyA(root
, keyA
, &clsid_key
) == ERROR_SUCCESS
)
1956 DWORD expected
= 0, got
, length
= sizeof(valueA
);
1960 for (v
= 0; RegEnumValueA(clsid_key
, v
, valueA
, &length
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
; v
++)
1964 for (j
= 0; j
< sizeof(values
)/sizeof(struct compat_value
); j
++)
1965 if (lstrcmpA(values
[j
].nameA
, valueA
) == 0)
1967 expected
|= values
[j
].value
;
1971 length
= sizeof(valueA
);
1974 pGUIDFromStringA(keyA
, &clsid
);
1975 got
= pSHGetObjectCompatFlags(NULL
, &clsid
);
1976 ok(got
== expected
, "got 0x%08x, expected 0x%08x. Key %s\n", got
, expected
, keyA
);
1978 RegCloseKey(clsid_key
);
1986 const IOleCommandTargetVtbl
*lpVtbl
;
1988 } IOleCommandTargetImpl
;
1990 static const IOleCommandTargetVtbl IOleCommandTargetImpl_Vtbl
;
1992 static IOleCommandTarget
* IOleCommandTargetImpl_Construct(void)
1994 IOleCommandTargetImpl
*obj
;
1996 obj
= HeapAlloc(GetProcessHeap(), 0, sizeof(*obj
));
1997 obj
->lpVtbl
= &IOleCommandTargetImpl_Vtbl
;
2000 return (IOleCommandTarget
*)obj
;
2003 static HRESULT WINAPI
IOleCommandTargetImpl_QueryInterface(IOleCommandTarget
*iface
, REFIID riid
, void **ppvObj
)
2005 IOleCommandTargetImpl
*This
= (IOleCommandTargetImpl
*)iface
;
2007 if (IsEqualIID(riid
, &IID_IUnknown
) ||
2008 IsEqualIID(riid
, &IID_IOleCommandTarget
))
2015 IUnknown_AddRef(iface
);
2019 return E_NOINTERFACE
;
2022 static ULONG WINAPI
IOleCommandTargetImpl_AddRef(IOleCommandTarget
*iface
)
2024 IOleCommandTargetImpl
*This
= (IOleCommandTargetImpl
*)iface
;
2025 return InterlockedIncrement(&This
->ref
);
2028 static ULONG WINAPI
IOleCommandTargetImpl_Release(IOleCommandTarget
*iface
)
2030 IOleCommandTargetImpl
*This
= (IOleCommandTargetImpl
*)iface
;
2031 ULONG ref
= InterlockedDecrement(&This
->ref
);
2035 HeapFree(GetProcessHeap(), 0, This
);
2041 static HRESULT WINAPI
IOleCommandTargetImpl_QueryStatus(
2042 IOleCommandTarget
*iface
, const GUID
*group
, ULONG cCmds
, OLECMD prgCmds
[], OLECMDTEXT
*pCmdText
)
2047 static HRESULT WINAPI
IOleCommandTargetImpl_Exec(
2048 IOleCommandTarget
*iface
,
2049 const GUID
*CmdGroup
,
2055 add_call(&trace_got
, 3, CmdGroup
, (void*)(DWORD_PTR
)nCmdID
, (void*)(DWORD_PTR
)nCmdexecopt
, pvaIn
, pvaOut
);
2059 static const IOleCommandTargetVtbl IOleCommandTargetImpl_Vtbl
=
2061 IOleCommandTargetImpl_QueryInterface
,
2062 IOleCommandTargetImpl_AddRef
,
2063 IOleCommandTargetImpl_Release
,
2064 IOleCommandTargetImpl_QueryStatus
,
2065 IOleCommandTargetImpl_Exec
2069 const IServiceProviderVtbl
*lpVtbl
;
2071 } IServiceProviderImpl
;
2074 const IProfferServiceVtbl
*lpVtbl
;
2076 } IProfferServiceImpl
;
2079 static const IServiceProviderVtbl IServiceProviderImpl_Vtbl
;
2080 static const IProfferServiceVtbl IProfferServiceImpl_Vtbl
;
2082 static IServiceProvider
* IServiceProviderImpl_Construct(void)
2084 IServiceProviderImpl
*obj
;
2086 obj
= HeapAlloc(GetProcessHeap(), 0, sizeof(*obj
));
2087 obj
->lpVtbl
= &IServiceProviderImpl_Vtbl
;
2090 return (IServiceProvider
*)obj
;
2093 static IProfferService
* IProfferServiceImpl_Construct(void)
2095 IProfferServiceImpl
*obj
;
2097 obj
= HeapAlloc(GetProcessHeap(), 0, sizeof(*obj
));
2098 obj
->lpVtbl
= &IProfferServiceImpl_Vtbl
;
2101 return (IProfferService
*)obj
;
2104 static HRESULT WINAPI
IServiceProviderImpl_QueryInterface(IServiceProvider
*iface
, REFIID riid
, void **ppvObj
)
2106 IServiceProviderImpl
*This
= (IServiceProviderImpl
*)iface
;
2108 if (IsEqualIID(riid
, &IID_IUnknown
) ||
2109 IsEqualIID(riid
, &IID_IServiceProvider
))
2116 IUnknown_AddRef(iface
);
2117 /* native uses redefined IID_IServiceProvider symbol, so we can't compare pointers */
2118 if (IsEqualIID(riid
, &IID_IServiceProvider
))
2119 add_call(&trace_got
, 1, iface
, &IID_IServiceProvider
, 0, 0, 0);
2123 return E_NOINTERFACE
;
2126 static ULONG WINAPI
IServiceProviderImpl_AddRef(IServiceProvider
*iface
)
2128 IServiceProviderImpl
*This
= (IServiceProviderImpl
*)iface
;
2129 return InterlockedIncrement(&This
->ref
);
2132 static ULONG WINAPI
IServiceProviderImpl_Release(IServiceProvider
*iface
)
2134 IServiceProviderImpl
*This
= (IServiceProviderImpl
*)iface
;
2135 ULONG ref
= InterlockedDecrement(&This
->ref
);
2139 HeapFree(GetProcessHeap(), 0, This
);
2145 static HRESULT WINAPI
IServiceProviderImpl_QueryService(
2146 IServiceProvider
*iface
, REFGUID service
, REFIID riid
, void **ppv
)
2148 /* native uses redefined pointer for IID_IOleCommandTarget, not one from uuid.lib */
2149 if (IsEqualIID(riid
, &IID_IOleCommandTarget
))
2151 add_call(&trace_got
, 2, iface
, service
, &IID_IOleCommandTarget
, 0, 0);
2152 *ppv
= IOleCommandTargetImpl_Construct();
2154 if (IsEqualIID(riid
, &IID_IProfferService
))
2156 if (IsEqualIID(service
, &IID_IProfferService
))
2157 add_call(&trace_got
, 2, &IID_IProfferService
, &IID_IProfferService
, 0, 0, 0);
2158 *ppv
= IProfferServiceImpl_Construct();
2163 static const IServiceProviderVtbl IServiceProviderImpl_Vtbl
=
2165 IServiceProviderImpl_QueryInterface
,
2166 IServiceProviderImpl_AddRef
,
2167 IServiceProviderImpl_Release
,
2168 IServiceProviderImpl_QueryService
2171 static void test_IUnknown_QueryServiceExec(void)
2173 IServiceProvider
*provider
= IServiceProviderImpl_Construct();
2174 static const GUID dummy_serviceid
= { 0xdeadbeef };
2175 static const GUID dummy_groupid
= { 0xbeefbeef };
2176 call_trace_t trace_expected
;
2179 /* on <=W2K platforms same ordinal used for another export with different
2180 prototype, so skipping using this indirect condition */
2181 if (is_win2k_and_lower
)
2183 win_skip("IUnknown_QueryServiceExec is not available\n");
2187 /* null source pointer */
2188 hr
= pIUnknown_QueryServiceExec(NULL
, &dummy_serviceid
, &dummy_groupid
, 0, 0, 0, 0);
2189 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
2192 IUnknown_QueryServiceExec( ptr1, serviceid, groupid, arg1, arg2, arg3, arg4);
2193 -> IUnknown_QueryInterface( ptr1, &IID_IServiceProvider, &prov );
2194 -> IServiceProvider_QueryService( prov, serviceid, &IID_IOleCommandTarget, &obj );
2195 -> IOleCommandTarget_Exec( obj, groupid, arg1, arg2, arg3, arg4 );
2197 init_call_trace(&trace_expected
);
2199 add_call(&trace_expected
, 1, provider
, &IID_IServiceProvider
, 0, 0, 0);
2200 add_call(&trace_expected
, 2, provider
, &dummy_serviceid
, &IID_IOleCommandTarget
, 0, 0);
2201 add_call(&trace_expected
, 3, &dummy_groupid
, (void*)0x1, (void*)0x2, (void*)0x3, (void*)0x4);
2203 init_call_trace(&trace_got
);
2204 hr
= pIUnknown_QueryServiceExec((IUnknown
*)provider
, &dummy_serviceid
, &dummy_groupid
, 0x1, 0x2, (void*)0x3, (void*)0x4);
2205 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2207 ok_trace(&trace_expected
, &trace_got
);
2209 free_call_trace(&trace_expected
);
2210 free_call_trace(&trace_got
);
2212 IServiceProvider_Release(provider
);
2216 static HRESULT WINAPI
IProfferServiceImpl_QueryInterface(IProfferService
*iface
, REFIID riid
, void **ppvObj
)
2218 IProfferServiceImpl
*This
= (IProfferServiceImpl
*)iface
;
2220 if (IsEqualIID(riid
, &IID_IUnknown
) ||
2221 IsEqualIID(riid
, &IID_IProfferService
))
2225 else if (IsEqualIID(riid
, &IID_IServiceProvider
))
2227 *ppvObj
= IServiceProviderImpl_Construct();
2228 add_call(&trace_got
, 1, iface
, &IID_IServiceProvider
, 0, 0, 0);
2234 IUnknown_AddRef(iface
);
2238 return E_NOINTERFACE
;
2241 static ULONG WINAPI
IProfferServiceImpl_AddRef(IProfferService
*iface
)
2243 IProfferServiceImpl
*This
= (IProfferServiceImpl
*)iface
;
2244 return InterlockedIncrement(&This
->ref
);
2247 static ULONG WINAPI
IProfferServiceImpl_Release(IProfferService
*iface
)
2249 IProfferServiceImpl
*This
= (IProfferServiceImpl
*)iface
;
2250 ULONG ref
= InterlockedDecrement(&This
->ref
);
2254 HeapFree(GetProcessHeap(), 0, This
);
2260 static HRESULT WINAPI
IProfferServiceImpl_ProfferService(IProfferService
*iface
,
2261 REFGUID service
, IServiceProvider
*pService
, DWORD
*pCookie
)
2263 add_call(&trace_got
, 3, service
, pService
, pCookie
, 0, 0);
2267 static HRESULT WINAPI
IProfferServiceImpl_RevokeService(IProfferService
*iface
, DWORD cookie
)
2269 add_call(&trace_got
, 4, (void*)(DWORD_PTR
)cookie
, 0, 0, 0, 0);
2273 static const IProfferServiceVtbl IProfferServiceImpl_Vtbl
=
2275 IProfferServiceImpl_QueryInterface
,
2276 IProfferServiceImpl_AddRef
,
2277 IProfferServiceImpl_Release
,
2278 IProfferServiceImpl_ProfferService
,
2279 IProfferServiceImpl_RevokeService
2282 static void test_IUnknown_ProfferService(void)
2284 IServiceProvider
*provider
= IServiceProviderImpl_Construct();
2285 IProfferService
*proff
= IProfferServiceImpl_Construct();
2286 static const GUID dummy_serviceid
= { 0xdeadbeef };
2287 call_trace_t trace_expected
;
2291 /* on <=W2K platforms same ordinal used for another export with different
2292 prototype, so skipping using this indirect condition */
2293 if (is_win2k_and_lower
)
2295 win_skip("IUnknown_ProfferService is not available\n");
2299 /* null source pointer */
2300 hr
= pIUnknown_ProfferService(NULL
, &dummy_serviceid
, 0, 0);
2301 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
2304 IUnknown_ProfferService( ptr1, serviceid, arg1, arg2);
2305 -> IUnknown_QueryInterface( ptr1, &IID_IServiceProvider, &provider );
2306 -> IServiceProvider_QueryService( provider, &IID_IProfferService, &IID_IProfferService, &proffer );
2308 if (service pointer not null):
2309 -> IProfferService_ProfferService( proffer, serviceid, arg1, arg2 );
2311 -> IProfferService_RevokeService( proffer, *arg2 );
2313 init_call_trace(&trace_expected
);
2315 add_call(&trace_expected
, 1, proff
, &IID_IServiceProvider
, 0, 0, 0);
2316 add_call(&trace_expected
, 2, &IID_IProfferService
, &IID_IProfferService
, 0, 0, 0);
2317 add_call(&trace_expected
, 3, &dummy_serviceid
, provider
, &cookie
, 0, 0);
2319 init_call_trace(&trace_got
);
2320 hr
= pIUnknown_ProfferService((IUnknown
*)proff
, &dummy_serviceid
, provider
, &cookie
);
2321 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2323 ok_trace(&trace_expected
, &trace_got
);
2324 free_call_trace(&trace_got
);
2325 free_call_trace(&trace_expected
);
2327 /* same with ::Revoke path */
2328 init_call_trace(&trace_expected
);
2330 add_call(&trace_expected
, 1, proff
, &IID_IServiceProvider
, 0, 0, 0);
2331 add_call(&trace_expected
, 2, &IID_IProfferService
, &IID_IProfferService
, 0, 0, 0);
2332 add_call(&trace_expected
, 4, (void*)(DWORD_PTR
)cookie
, 0, 0, 0, 0);
2334 init_call_trace(&trace_got
);
2335 hr
= pIUnknown_ProfferService((IUnknown
*)proff
, &dummy_serviceid
, 0, &cookie
);
2336 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2337 ok_trace(&trace_expected
, &trace_got
);
2338 free_call_trace(&trace_got
);
2339 free_call_trace(&trace_expected
);
2341 IServiceProvider_Release(provider
);
2342 IProfferService_Release(proff
);
2345 static void test_SHCreateWorkerWindowA(void)
2353 if (is_win2k_and_lower
)
2355 win_skip("SHCreateWorkerWindowA not available\n");
2359 hwnd
= pSHCreateWorkerWindowA(0, NULL
, 0, 0, 0, 0);
2360 ok(hwnd
!= 0, "expected window\n");
2362 GetClassName(hwnd
, classA
, 20);
2363 ok(lstrcmpA(classA
, "WorkerA") == 0, "expected WorkerA class, got %s\n", classA
);
2365 ret
= GetWindowLongPtrA(hwnd
, 0);
2366 ok(ret
== 0, "got %ld\n", ret
);
2369 memset(&cliA
, 0, sizeof(cliA
));
2370 res
= GetClassInfoA(GetModuleHandle("shlwapi.dll"), "WorkerA", &cliA
);
2371 ok(res
, "failed to get class info\n");
2372 ok(cliA
.style
== 0, "got 0x%08x\n", cliA
.style
);
2373 ok(cliA
.cbClsExtra
== 0, "got %d\n", cliA
.cbClsExtra
);
2374 ok(cliA
.cbWndExtra
== sizeof(LONG_PTR
), "got %d\n", cliA
.cbWndExtra
);
2375 ok(cliA
.lpszMenuName
== 0, "got %s\n", cliA
.lpszMenuName
);
2377 DestroyWindow(hwnd
);
2379 /* set extra bytes */
2380 hwnd
= pSHCreateWorkerWindowA(0, NULL
, 0, 0, 0, 0xdeadbeef);
2381 ok(hwnd
!= 0, "expected window\n");
2383 GetClassName(hwnd
, classA
, 20);
2384 ok(lstrcmpA(classA
, "WorkerA") == 0, "expected WorkerA class, got %s\n", classA
);
2386 ret
= GetWindowLongPtrA(hwnd
, 0);
2387 ok(ret
== 0xdeadbeef, "got %ld\n", ret
);
2390 ret
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
2391 ok(ret
== WS_EX_WINDOWEDGE
, "0x%08lx\n", ret
);
2393 DestroyWindow(hwnd
);
2395 hwnd
= pSHCreateWorkerWindowA(0, NULL
, WS_EX_TOOLWINDOW
, 0, 0, 0);
2396 ret
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
2397 ok(ret
== (WS_EX_WINDOWEDGE
|WS_EX_TOOLWINDOW
), "0x%08lx\n", ret
);
2398 DestroyWindow(hwnd
);
2401 static HRESULT WINAPI
SF_QueryInterface(IShellFolder
*iface
,
2402 REFIID riid
, void **ppv
)
2404 /* SHIShellFolder_EnumObjects doesn't QI the object for IShellFolder */
2405 ok(!IsEqualGUID(&IID_IShellFolder
, riid
),
2406 "Unexpected QI for IShellFolder\n");
2407 return E_NOINTERFACE
;
2410 static ULONG WINAPI
SF_AddRef(IShellFolder
*iface
)
2415 static ULONG WINAPI
SF_Release(IShellFolder
*iface
)
2420 static HRESULT WINAPI
SF_ParseDisplayName(IShellFolder
*iface
,
2421 HWND owner
, LPBC reserved
, LPOLESTR displayName
, ULONG
*eaten
,
2422 LPITEMIDLIST
*idl
, ULONG
*attr
)
2424 ok(0, "Didn't expect ParseDisplayName\n");
2428 static HRESULT WINAPI
SF_EnumObjects(IShellFolder
*iface
,
2429 HWND owner
, SHCONTF flags
, IEnumIDList
**enm
)
2431 *enm
= (IEnumIDList
*)0xcafebabe;
2435 static HRESULT WINAPI
SF_BindToObject(IShellFolder
*iface
,
2436 LPCITEMIDLIST idl
, LPBC reserved
, REFIID riid
, void **obj
)
2438 ok(0, "Didn't expect BindToObject\n");
2442 static HRESULT WINAPI
SF_BindToStorage(IShellFolder
*iface
,
2443 LPCITEMIDLIST idl
, LPBC reserved
, REFIID riid
, void **obj
)
2445 ok(0, "Didn't expect BindToStorage\n");
2449 static HRESULT WINAPI
SF_CompareIDs(IShellFolder
*iface
,
2450 LPARAM lparam
, LPCITEMIDLIST idl1
, LPCITEMIDLIST idl2
)
2452 ok(0, "Didn't expect CompareIDs\n");
2456 static HRESULT WINAPI
SF_CreateViewObject(IShellFolder
*iface
,
2457 HWND owner
, REFIID riid
, void **out
)
2459 ok(0, "Didn't expect CreateViewObject\n");
2463 static HRESULT WINAPI
SF_GetAttributesOf(IShellFolder
*iface
,
2464 UINT cidl
, LPCITEMIDLIST
*idl
, SFGAOF
*inOut
)
2466 ok(0, "Didn't expect GetAttributesOf\n");
2470 static HRESULT WINAPI
SF_GetUIObjectOf(IShellFolder
*iface
,
2471 HWND owner
, UINT cidl
, LPCITEMIDLIST
*idls
, REFIID riid
, UINT
*inOut
,
2474 ok(0, "Didn't expect GetUIObjectOf\n");
2478 static HRESULT WINAPI
SF_GetDisplayNameOf(IShellFolder
*iface
,
2479 LPCITEMIDLIST idl
, SHGDNF flags
, STRRET
*name
)
2481 ok(0, "Didn't expect GetDisplayNameOf\n");
2485 static HRESULT WINAPI
SF_SetNameOf(IShellFolder
*iface
,
2486 HWND hwnd
, LPCITEMIDLIST idl
, LPCOLESTR name
, SHGDNF flags
,
2487 LPITEMIDLIST
*idlOut
)
2489 ok(0, "Didn't expect SetNameOf\n");
2493 static IShellFolderVtbl ShellFolderVtbl
= {
2497 SF_ParseDisplayName
,
2502 SF_CreateViewObject
,
2505 SF_GetDisplayNameOf
,
2509 static IShellFolder ShellFolder
= { &ShellFolderVtbl
};
2511 static void test_SHIShellFolder_EnumObjects(void)
2515 IShellFolder
*folder
;
2517 if(!pSHIShellFolder_EnumObjects
|| is_win2k_and_lower
){
2518 win_skip("SHIShellFolder_EnumObjects not available\n");
2523 /* NULL object crashes on Windows */
2524 hres
= pSHIShellFolder_EnumObjects(NULL
, NULL
, 0, NULL
);
2527 /* SHIShellFolder_EnumObjects doesn't QI the object for IShellFolder */
2528 enm
= (IEnumIDList
*)0xdeadbeef;
2529 hres
= pSHIShellFolder_EnumObjects(&ShellFolder
, NULL
, 0, &enm
);
2530 ok(hres
== S_OK
, "SHIShellFolder_EnumObjects failed: 0x%08x\n", hres
);
2531 ok(enm
== (IEnumIDList
*)0xcafebabe, "Didn't get expected enumerator location, instead: %p\n", enm
);
2533 /* SHIShellFolder_EnumObjects isn't strict about the IShellFolder object */
2534 hres
= pSHGetDesktopFolder(&folder
);
2535 ok(hres
== S_OK
, "SHGetDesktopFolder failed: 0x%08x\n", hres
);
2538 hres
= pSHIShellFolder_EnumObjects(folder
, NULL
, 0, &enm
);
2539 ok(hres
== S_OK
, "SHIShellFolder_EnumObjects failed: 0x%08x\n", hres
);
2540 ok(enm
!= NULL
, "Didn't get an enumerator\n");
2542 IEnumIDList_Release(enm
);
2544 IShellFolder_Release(folder
);
2547 static void write_inifile(LPCWSTR filename
)
2552 static const char data
[] =
2555 "AnotherKey=asdf\r\n";
2557 file
= CreateFileW(filename
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
2558 if(file
== INVALID_HANDLE_VALUE
)
2561 WriteFile(file
, data
, sizeof(data
), &written
, NULL
);
2566 #define verify_inifile(f, e) r_verify_inifile(__LINE__, f, e)
2567 static void r_verify_inifile(unsigned l
, LPCWSTR filename
, LPCSTR exp
)
2573 file
= CreateFileW(filename
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, 0, NULL
);
2574 if(file
== INVALID_HANDLE_VALUE
)
2577 ReadFile(file
, buf
, sizeof(buf
) * sizeof(CHAR
), &read
, NULL
);
2582 ok_(__FILE__
,l
)(!strcmp(buf
, exp
), "Expected:\n%s\nGot:\n%s\n", exp
,
2586 static void test_SHGetIniString(void)
2589 WCHAR out
[64] = {0};
2591 static const WCHAR TestAppW
[] = {'T','e','s','t','A','p','p',0};
2592 static const WCHAR TestIniW
[] = {'C',':','\\','t','e','s','t','.','i','n','i',0};
2593 static const WCHAR AKeyW
[] = {'A','K','e','y',0};
2594 static const WCHAR AnotherKeyW
[] = {'A','n','o','t','h','e','r','K','e','y',0};
2595 static const WCHAR JunkKeyW
[] = {'J','u','n','k','K','e','y',0};
2597 if(!pSHGetIniStringW
|| is_win2k_and_lower
){
2598 win_skip("SHGetIniStringW is not available\n");
2602 write_inifile(TestIniW
);
2605 /* these crash on Windows */
2606 ret
= pSHGetIniStringW(NULL
, NULL
, NULL
, 0, NULL
);
2607 ret
= pSHGetIniStringW(NULL
, AKeyW
, out
, sizeof(out
), TestIniW
);
2608 ret
= pSHGetIniStringW(TestAppW
, AKeyW
, NULL
, sizeof(out
), TestIniW
);
2611 ret
= pSHGetIniStringW(TestAppW
, AKeyW
, out
, 0, TestIniW
);
2612 ok(ret
== 0, "SHGetIniStringW should have given 0, instead: %d\n", ret
);
2614 /* valid arguments */
2615 ret
= pSHGetIniStringW(TestAppW
, NULL
, out
, sizeof(out
), TestIniW
);
2616 ok(broken(ret
== 0) || /* win 98 */
2617 ret
== 4, "SHGetIniStringW should have given 4, instead: %d\n", ret
);
2618 ok(!lstrcmpW(out
, AKeyW
), "Expected %s, got: %s\n",
2619 wine_dbgstr_w(AKeyW
), wine_dbgstr_w(out
));
2621 ret
= pSHGetIniStringW(TestAppW
, AKeyW
, out
, sizeof(out
), TestIniW
);
2622 ok(broken(ret
== 0) || /* win 98 */
2623 ret
== 1, "SHGetIniStringW should have given 1, instead: %d\n", ret
);
2624 ok(broken(*out
== 0) || /*win 98 */
2625 !strcmp_wa(out
, "1"), "Expected L\"1\", got: %s\n", wine_dbgstr_w(out
));
2627 ret
= pSHGetIniStringW(TestAppW
, AnotherKeyW
, out
, sizeof(out
), TestIniW
);
2628 ok(broken(ret
== 0) || /* win 98 */
2629 ret
== 4, "SHGetIniStringW should have given 4, instead: %d\n", ret
);
2630 ok(broken(*out
== 0) || /* win 98 */
2631 !strcmp_wa(out
, "asdf"), "Expected L\"asdf\", got: %s\n", wine_dbgstr_w(out
));
2633 ret
= pSHGetIniStringW(TestAppW
, JunkKeyW
, out
, sizeof(out
), TestIniW
);
2634 ok(ret
== 0, "SHGetIniStringW should have given 0, instead: %d\n", ret
);
2635 ok(*out
== 0, "Expected L\"\", got: %s\n", wine_dbgstr_w(out
));
2637 DeleteFileW(TestIniW
);
2640 static void test_SHSetIniString(void)
2644 static const WCHAR TestAppW
[] = {'T','e','s','t','A','p','p',0};
2645 static const WCHAR AnotherAppW
[] = {'A','n','o','t','h','e','r','A','p','p',0};
2646 static const WCHAR TestIniW
[] = {'C',':','\\','t','e','s','t','.','i','n','i',0};
2647 static const WCHAR AKeyW
[] = {'A','K','e','y',0};
2648 static const WCHAR NewKeyW
[] = {'N','e','w','K','e','y',0};
2649 static const WCHAR AValueW
[] = {'A','V','a','l','u','e',0};
2651 if(!pSHSetIniStringW
|| is_win2k_and_lower
){
2652 win_skip("SHSetIniStringW is not available\n");
2656 write_inifile(TestIniW
);
2658 ret
= pSHSetIniStringW(TestAppW
, AKeyW
, AValueW
, TestIniW
);
2659 ok(ret
== TRUE
, "SHSetIniStringW should not have failed\n");
2660 todo_wine
/* wine sticks an extra \r\n at the end of the file */
2661 verify_inifile(TestIniW
, "[TestApp]\r\nAKey=AValue\r\nAnotherKey=asdf\r\n");
2663 ret
= pSHSetIniStringW(TestAppW
, AKeyW
, NULL
, TestIniW
);
2664 ok(ret
== TRUE
, "SHSetIniStringW should not have failed\n");
2665 verify_inifile(TestIniW
, "[TestApp]\r\nAnotherKey=asdf\r\n");
2667 ret
= pSHSetIniStringW(AnotherAppW
, NewKeyW
, AValueW
, TestIniW
);
2668 ok(ret
== TRUE
, "SHSetIniStringW should not have failed\n");
2669 verify_inifile(TestIniW
, "[TestApp]\r\nAnotherKey=asdf\r\n[AnotherApp]\r\nNewKey=AValue\r\n");
2671 ret
= pSHSetIniStringW(TestAppW
, NULL
, AValueW
, TestIniW
);
2672 ok(ret
== TRUE
, "SHSetIniStringW should not have failed\n");
2673 verify_inifile(TestIniW
, "[AnotherApp]\r\nNewKey=AValue\r\n");
2675 DeleteFileW(TestIniW
);
2678 static void init_pointers(void)
2680 #define MAKEFUNC(f, ord) (p##f = (void*)GetProcAddress(hShlwapi, (LPSTR)(ord)))
2681 MAKEFUNC(SHAllocShared
, 7);
2682 MAKEFUNC(SHLockShared
, 8);
2683 MAKEFUNC(SHUnlockShared
, 9);
2684 MAKEFUNC(SHFreeShared
, 10);
2685 MAKEFUNC(GetAcceptLanguagesA
, 14);
2686 MAKEFUNC(SHSetWindowBits
, 165);
2687 MAKEFUNC(ConnectToConnectionPoint
, 168);
2688 MAKEFUNC(SHSearchMapInt
, 198);
2689 MAKEFUNC(SHCreateWorkerWindowA
, 257);
2690 MAKEFUNC(GUIDFromStringA
, 269);
2691 MAKEFUNC(SHPackDispParams
, 282);
2692 MAKEFUNC(IConnectionPoint_InvokeWithCancel
, 283);
2693 MAKEFUNC(IConnectionPoint_SimpleInvoke
, 284);
2694 MAKEFUNC(SHGetIniStringW
, 294);
2695 MAKEFUNC(SHSetIniStringW
, 295);
2696 MAKEFUNC(SHFormatDateTimeA
, 353);
2697 MAKEFUNC(SHFormatDateTimeW
, 354);
2698 MAKEFUNC(SHIShellFolder_EnumObjects
, 404);
2699 MAKEFUNC(SHGetObjectCompatFlags
, 476);
2700 MAKEFUNC(IUnknown_QueryServiceExec
, 484);
2701 MAKEFUNC(SHPropertyBag_ReadLONG
, 496);
2702 MAKEFUNC(IUnknown_ProfferService
, 514);
2708 hShlwapi
= GetModuleHandleA("shlwapi.dll");
2709 is_win2k_and_lower
= GetProcAddress(hShlwapi
, "StrChrNW") == 0;
2713 hmlang
= LoadLibraryA("mlang.dll");
2714 pLcidToRfc1766A
= (void *)GetProcAddress(hmlang
, "LcidToRfc1766A");
2716 hshell32
= LoadLibraryA("shell32.dll");
2717 pSHGetDesktopFolder
= (void *)GetProcAddress(hshell32
, "SHGetDesktopFolder");
2719 test_GetAcceptLanguagesA();
2720 test_SHSearchMapInt();
2721 test_alloc_shared();
2723 test_GetShellSecurityDescriptor();
2724 test_SHPackDispParams();
2725 test_IConnectionPoint();
2726 test_SHPropertyBag_ReadLONG();
2727 test_SHSetWindowBits();
2728 test_SHFormatDateTimeA();
2729 test_SHFormatDateTimeW();
2730 test_SHGetObjectCompatFlags();
2731 test_IUnknown_QueryServiceExec();
2732 test_IUnknown_ProfferService();
2733 test_SHCreateWorkerWindowA();
2734 test_SHIShellFolder_EnumObjects();
2735 test_SHGetIniString();
2736 test_SHSetIniString();
2738 FreeLibrary(hshell32
);
2739 FreeLibrary(hmlang
);