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"
34 /* Function ptrs for ordinal calls */
35 static HMODULE hShlwapi
;
36 static int (WINAPI
*pSHSearchMapInt
)(const int*,const int*,int,int);
37 static HRESULT (WINAPI
*pGetAcceptLanguagesA
)(LPSTR
,LPDWORD
);
39 static HANDLE (WINAPI
*pSHAllocShared
)(LPCVOID
,DWORD
,DWORD
);
40 static LPVOID (WINAPI
*pSHLockShared
)(HANDLE
,DWORD
);
41 static BOOL (WINAPI
*pSHUnlockShared
)(LPVOID
);
42 static BOOL (WINAPI
*pSHFreeShared
)(HANDLE
,DWORD
);
43 static HRESULT(WINAPIV
*pSHPackDispParams
)(DISPPARAMS
*,VARIANTARG
*,UINT
,...);
44 static HRESULT(WINAPI
*pIConnectionPoint_SimpleInvoke
)(IConnectionPoint
*,DISPID
,DISPPARAMS
*);
45 static HRESULT(WINAPI
*pIConnectionPoint_InvokeWithCancel
)(IConnectionPoint
*,DISPID
,DISPPARAMS
*,DWORD
,DWORD
);
46 static HRESULT(WINAPI
*pConnectToConnectionPoint
)(IUnknown
*,REFIID
,BOOL
,IUnknown
*, LPDWORD
,IConnectionPoint
**);
47 static HRESULT(WINAPI
*pSHPropertyBag_ReadLONG
)(IPropertyBag
*,LPCWSTR
,LPLONG
);
48 static LONG (WINAPI
*pSHSetWindowBits
)(HWND
, INT
, UINT
, UINT
);
49 static INT (WINAPI
*pSHFormatDateTimeA
)(const FILETIME UNALIGNED
*, DWORD
*, LPSTR
, UINT
);
50 static INT (WINAPI
*pSHFormatDateTimeW
)(const FILETIME UNALIGNED
*, DWORD
*, LPWSTR
, UINT
);
51 static DWORD (WINAPI
*pSHGetObjectCompatFlags
)(IUnknown
*, const CLSID
*);
52 static BOOL (WINAPI
*pGUIDFromStringA
)(LPSTR
, CLSID
*);
53 static HRESULT (WINAPI
*pIUnknown_QueryServiceExec
)(IUnknown
*, REFIID
, const GUID
*, DWORD
, DWORD
, VARIANT
*, VARIANT
*);
55 static HMODULE hmlang
;
56 static HRESULT (WINAPI
*pLcidToRfc1766A
)(LCID
, LPSTR
, INT
);
58 static const CHAR ie_international
[] = {
59 'S','o','f','t','w','a','r','e','\\',
60 'M','i','c','r','o','s','o','f','t','\\',
61 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
62 'I','n','t','e','r','n','a','t','i','o','n','a','l',0};
63 static const CHAR acceptlanguage
[] = {
64 'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0};
77 static void init_call_trace(call_trace_t
*ctrace
)
81 ctrace
->calls
= HeapAlloc(GetProcessHeap(), 0, sizeof(call_entry_t
) * ctrace
->alloc
);
84 static void free_call_trace(const call_trace_t
*ctrace
)
86 HeapFree(GetProcessHeap(), 0, ctrace
->calls
);
89 static void add_call(call_trace_t
*ctrace
, int id
, const void *arg0
,
90 const void *arg1
, const void *arg2
, const void *arg3
, const void *arg4
)
101 if (ctrace
->count
== ctrace
->alloc
)
104 ctrace
->calls
= HeapReAlloc(GetProcessHeap(),0, ctrace
->calls
, ctrace
->alloc
*sizeof(call_entry_t
));
107 ctrace
->calls
[ctrace
->count
++] = call
;
110 static void test_GetAcceptLanguagesA(void)
112 static LPCSTR table
[] = {"de,en-gb;q=0.7,en;q=0.3",
113 "de,en;q=0.3,en-gb;q=0.7", /* sorting is ignored */
114 "winetest", /* content is ignored */
124 LONG res_query
= ERROR_SUCCESS
;
127 DWORD maxlen
= sizeof(buffer
) - 2;
133 if (!pGetAcceptLanguagesA
) {
134 win_skip("GetAcceptLanguagesA is not available\n");
138 lcid
= GetUserDefaultLCID();
140 /* Get the original Value */
141 lres
= RegOpenKeyA(HKEY_CURRENT_USER
, ie_international
, &hroot
);
143 skip("RegOpenKey(%s) failed: %d\n", ie_international
, lres
);
146 len
= sizeof(original
);
148 res_query
= RegQueryValueExA(hroot
, acceptlanguage
, 0, NULL
, (PBYTE
)original
, &len
);
150 RegDeleteValue(hroot
, acceptlanguage
);
152 /* Some windows versions use "lang-COUNTRY" as default */
153 memset(language
, 0, sizeof(language
));
154 len
= GetLocaleInfoA(lcid
, LOCALE_SISO639LANGNAME
, language
, sizeof(language
));
157 lstrcat(language
, "-");
158 memset(buffer
, 0, sizeof(buffer
));
159 len
= GetLocaleInfoA(lcid
, LOCALE_SISO3166CTRYNAME
, buffer
, sizeof(buffer
) - len
- 1);
160 lstrcat(language
, buffer
);
164 /* LOCALE_SNAME has additional parts in some languages. Try only as last chance */
165 memset(language
, 0, sizeof(language
));
166 len
= GetLocaleInfoA(lcid
, LOCALE_SNAME
, language
, sizeof(language
));
169 /* get the default value */
171 memset(buffer
, '#', maxlen
);
173 hr
= pGetAcceptLanguagesA( buffer
, &len
);
176 win_skip("GetAcceptLanguagesA failed with 0x%x\n", hr
);
177 goto restore_original
;
180 if (lstrcmpA(buffer
, language
)) {
181 /* some windows versions use "lang" or "lang-country" as default */
183 if (pLcidToRfc1766A
) {
184 hr
= pLcidToRfc1766A(lcid
, language
, sizeof(language
));
185 ok(hr
== S_OK
, "LcidToRfc1766A returned 0x%x and %s\n", hr
, language
);
189 ok(!lstrcmpA(buffer
, language
),
190 "have '%s' (searching for '%s')\n", language
, buffer
);
192 if (lstrcmpA(buffer
, language
)) {
193 win_skip("no more ideas, how to build the default language '%s'\n", buffer
);
194 goto restore_original
;
197 trace("detected default: %s\n", language
);
198 while ((entry
= table
[i
])) {
200 exactsize
= lstrlenA(entry
);
202 lres
= RegSetValueExA(hroot
, acceptlanguage
, 0, REG_SZ
, (const BYTE
*) entry
, exactsize
+ 1);
203 ok(!lres
, "got %d for RegSetValueExA: %s\n", lres
, entry
);
205 /* len includes space for the terminating 0 before vista/w2k8 */
207 memset(buffer
, '#', maxlen
);
209 hr
= pGetAcceptLanguagesA( buffer
, &len
);
210 ok(((hr
== E_INVALIDARG
) && (len
== 0)) ||
212 ((len
== exactsize
) || (len
== exactsize
+1)) &&
213 !lstrcmpA(buffer
, entry
)),
214 "+2_#%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
217 memset(buffer
, '#', maxlen
);
219 hr
= pGetAcceptLanguagesA( buffer
, &len
);
220 ok(((hr
== E_INVALIDARG
) && (len
== 0)) ||
222 ((len
== exactsize
) || (len
== exactsize
+1)) &&
223 !lstrcmpA(buffer
, entry
)),
224 "+1_#%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
227 memset(buffer
, '#', maxlen
);
229 hr
= pGetAcceptLanguagesA( buffer
, &len
);
231 /* There is no space for the string in the registry.
232 When the buffer is large enough, the default language is returned
234 When the buffer is too small for that fallback, win7_32 and w2k8_64
235 and above fail with HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), but
236 recent os succeed and return a partial result while
237 older os succeed and overflow the buffer */
239 ok(((hr
== E_INVALIDARG
) && (len
== 0)) ||
240 (((hr
== S_OK
) && !lstrcmpA(buffer
, language
) && (len
== lstrlenA(language
))) ||
241 ((hr
== S_OK
) && !memcmp(buffer
, language
, len
)) ||
242 ((hr
== __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
)) && !len
)),
243 "==_#%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
247 memset(buffer
, '#', maxlen
);
249 hr
= pGetAcceptLanguagesA( buffer
, &len
);
250 ok(((hr
== E_INVALIDARG
) && (len
== 0)) ||
251 (((hr
== S_OK
) && !lstrcmpA(buffer
, language
) && (len
== lstrlenA(language
))) ||
252 ((hr
== S_OK
) && !memcmp(buffer
, language
, len
)) ||
253 ((hr
== __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
)) && !len
)),
254 "-1_#%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
258 memset(buffer
, '#', maxlen
);
260 hr
= pGetAcceptLanguagesA( buffer
, &len
);
261 ok(((hr
== E_INVALIDARG
) && (len
== 0)) ||
262 (((hr
== S_OK
) && !lstrcmpA(buffer
, language
) && (len
== lstrlenA(language
))) ||
263 ((hr
== S_OK
) && !memcmp(buffer
, language
, len
)) ||
264 ((hr
== __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
)) && !len
)),
265 "=1_#%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
268 hr
= pGetAcceptLanguagesA( NULL
, &len
);
270 /* w2k3 and below: E_FAIL and untouched len,
271 since w2k8: S_OK and needed size (excluding 0) */
272 ok( ((hr
== S_OK
) && (len
== exactsize
)) ||
273 ((hr
== E_FAIL
) && (len
== maxlen
)),
274 "NULL,max #%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
279 /* without a value in the registry, a default language is returned */
280 RegDeleteValue(hroot
, acceptlanguage
);
283 memset(buffer
, '#', maxlen
);
285 hr
= pGetAcceptLanguagesA( buffer
, &len
);
286 ok( ((hr
== S_OK
) && (len
== lstrlenA(language
))),
287 "max: got 0x%x with %d and %s (expected S_OK with %d and '%s'\n",
288 hr
, len
, buffer
, lstrlenA(language
), language
);
291 memset(buffer
, '#', maxlen
);
293 hr
= pGetAcceptLanguagesA( buffer
, &len
);
294 ok( (((hr
== S_OK
) || (hr
== E_INVALIDARG
)) && !memcmp(buffer
, language
, len
)) ||
295 ((hr
== __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
)) && !len
),
296 "=2: got 0x%x with %d and %s\n", hr
, len
, buffer
);
299 memset(buffer
, '#', maxlen
);
301 hr
= pGetAcceptLanguagesA( buffer
, &len
);
302 /* When the buffer is too small, win7_32 and w2k8_64 and above fail with
303 HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), other versions suceed
304 and return a partial 0 terminated result while other versions
305 fail with E_INVALIDARG and return a partial unterminated result */
306 ok( (((hr
== S_OK
) || (hr
== E_INVALIDARG
)) && !memcmp(buffer
, language
, len
)) ||
307 ((hr
== __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
)) && !len
),
308 "=1: got 0x%x with %d and %s\n", hr
, len
, buffer
);
311 memset(buffer
, '#', maxlen
);
313 hr
= pGetAcceptLanguagesA( buffer
, &len
);
314 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
315 ok((hr
== E_FAIL
) || (hr
== E_INVALIDARG
),
316 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr
);
318 memset(buffer
, '#', maxlen
);
320 hr
= pGetAcceptLanguagesA( buffer
, NULL
);
321 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
322 ok((hr
== E_FAIL
) || (hr
== E_INVALIDARG
),
323 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr
);
326 hr
= pGetAcceptLanguagesA( NULL
, NULL
);
327 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
328 ok((hr
== E_FAIL
) || (hr
== E_INVALIDARG
),
329 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr
);
333 len
= lstrlenA(original
);
334 lres
= RegSetValueExA(hroot
, acceptlanguage
, 0, REG_SZ
, (const BYTE
*) original
, len
? len
+ 1: 0);
335 ok(!lres
, "RegSetValueEx(%s) failed: %d\n", original
, lres
);
339 RegDeleteValue(hroot
, acceptlanguage
);
344 static void test_SHSearchMapInt(void)
346 int keys
[8], values
[8];
349 if (!pSHSearchMapInt
)
352 memset(keys
, 0, sizeof(keys
));
353 memset(values
, 0, sizeof(values
));
354 keys
[0] = 99; values
[0] = 101;
356 /* NULL key/value lists crash native, so skip testing them */
359 i
= pSHSearchMapInt(keys
, values
, 1, keys
[0]);
360 ok(i
== values
[0], "Len 1, expected %d, got %d\n", values
[0], i
);
362 /* Key doesn't exist */
363 i
= pSHSearchMapInt(keys
, values
, 1, 100);
364 ok(i
== -1, "Len 1 - bad key, expected -1, got %d\n", i
);
366 /* Len = 0 => not found */
367 i
= pSHSearchMapInt(keys
, values
, 0, keys
[0]);
368 ok(i
== -1, "Len 1 - passed len 0, expected -1, got %d\n", i
);
370 /* 2 elements, len = 1 */
371 keys
[1] = 98; values
[1] = 102;
372 i
= pSHSearchMapInt(keys
, values
, 1, keys
[1]);
373 ok(i
== -1, "Len 1 - array len 2, expected -1, got %d\n", i
);
375 /* 2 elements, len = 2 */
376 i
= pSHSearchMapInt(keys
, values
, 2, keys
[1]);
377 ok(i
== values
[1], "Len 2, expected %d, got %d\n", values
[1], i
);
379 /* Searches forward */
380 keys
[2] = 99; values
[2] = 103;
381 i
= pSHSearchMapInt(keys
, values
, 3, keys
[0]);
382 ok(i
== values
[0], "Len 3, expected %d, got %d\n", values
[0], i
);
385 static void test_alloc_shared(void)
393 procid
=GetCurrentProcessId();
394 hmem
=pSHAllocShared(NULL
,10,procid
);
395 ok(hmem
!=NULL
,"SHAllocShared(NULL...) failed: %u\n", GetLastError());
396 ret
= pSHFreeShared(hmem
, procid
);
397 ok( ret
, "SHFreeShared failed: %u\n", GetLastError());
400 hmem
=pSHAllocShared(&val
,4,procid
);
401 ok(hmem
!=NULL
,"SHAllocShared(NULL...) failed: %u\n", GetLastError());
403 p
=pSHLockShared(hmem
,procid
);
404 ok(p
!=NULL
,"SHLockShared failed: %u\n", GetLastError());
406 ok(*p
==val
,"Wrong value in shared memory: %d instead of %d\n",*p
,val
);
407 ret
= pSHUnlockShared(p
);
408 ok( ret
, "SHUnlockShared failed: %u\n", GetLastError());
410 ret
= pSHFreeShared(hmem
, procid
);
411 ok( ret
, "SHFreeShared failed: %u\n", GetLastError());
414 static void test_fdsa(void)
418 DWORD num_items
; /* Number of elements inserted */
419 void *mem
; /* Ptr to array */
420 DWORD blocks_alloced
; /* Number of elements allocated */
421 BYTE inc
; /* Number of elements to grow by when we need to expand */
422 BYTE block_size
; /* Size in bytes of an element */
423 BYTE flags
; /* Flags */
426 BOOL (WINAPI
*pFDSA_Initialize
)(DWORD block_size
, DWORD inc
, FDSA_info
*info
, void *mem
,
428 BOOL (WINAPI
*pFDSA_Destroy
)(FDSA_info
*info
);
429 DWORD (WINAPI
*pFDSA_InsertItem
)(FDSA_info
*info
, DWORD where
, const void *block
);
430 BOOL (WINAPI
*pFDSA_DeleteItem
)(FDSA_info
*info
, DWORD where
);
433 int block_size
= 10, init_blocks
= 4, inc
= 2;
437 pFDSA_Initialize
= (void *)GetProcAddress(hShlwapi
, (LPSTR
)208);
438 pFDSA_Destroy
= (void *)GetProcAddress(hShlwapi
, (LPSTR
)209);
439 pFDSA_InsertItem
= (void *)GetProcAddress(hShlwapi
, (LPSTR
)210);
440 pFDSA_DeleteItem
= (void *)GetProcAddress(hShlwapi
, (LPSTR
)211);
442 mem
= HeapAlloc(GetProcessHeap(), 0, block_size
* init_blocks
);
443 memset(&info
, 0, sizeof(info
));
445 ok(pFDSA_Initialize(block_size
, inc
, &info
, mem
, init_blocks
), "FDSA_Initialize rets FALSE\n");
446 ok(info
.num_items
== 0, "num_items = %d\n", info
.num_items
);
447 ok(info
.mem
== mem
, "mem = %p\n", info
.mem
);
448 ok(info
.blocks_alloced
== init_blocks
, "blocks_alloced = %d\n", info
.blocks_alloced
);
449 ok(info
.inc
== inc
, "inc = %d\n", info
.inc
);
450 ok(info
.block_size
== block_size
, "block_size = %d\n", info
.block_size
);
451 ok(info
.flags
== 0, "flags = %d\n", info
.flags
);
453 ret
= pFDSA_InsertItem(&info
, 1234, "1234567890");
454 ok(ret
== 0, "ret = %d\n", ret
);
455 ok(info
.num_items
== 1, "num_items = %d\n", info
.num_items
);
456 ok(info
.mem
== mem
, "mem = %p\n", info
.mem
);
457 ok(info
.blocks_alloced
== init_blocks
, "blocks_alloced = %d\n", info
.blocks_alloced
);
458 ok(info
.inc
== inc
, "inc = %d\n", info
.inc
);
459 ok(info
.block_size
== block_size
, "block_size = %d\n", info
.block_size
);
460 ok(info
.flags
== 0, "flags = %d\n", info
.flags
);
462 ret
= pFDSA_InsertItem(&info
, 1234, "abcdefghij");
463 ok(ret
== 1, "ret = %d\n", ret
);
465 ret
= pFDSA_InsertItem(&info
, 1, "klmnopqrst");
466 ok(ret
== 1, "ret = %d\n", ret
);
468 ret
= pFDSA_InsertItem(&info
, 0, "uvwxyzABCD");
469 ok(ret
== 0, "ret = %d\n", ret
);
470 ok(info
.mem
== mem
, "mem = %p\n", info
.mem
);
471 ok(info
.flags
== 0, "flags = %d\n", info
.flags
);
473 /* This next InsertItem will cause shlwapi to allocate its own mem buffer */
474 ret
= pFDSA_InsertItem(&info
, 0, "EFGHIJKLMN");
475 ok(ret
== 0, "ret = %d\n", ret
);
476 ok(info
.mem
!= mem
, "mem = %p\n", info
.mem
);
477 ok(info
.blocks_alloced
== init_blocks
+ inc
, "blocks_alloced = %d\n", info
.blocks_alloced
);
478 ok(info
.flags
== 0x1, "flags = %d\n", info
.flags
);
480 ok(!memcmp(info
.mem
, "EFGHIJKLMNuvwxyzABCD1234567890klmnopqrstabcdefghij", 50), "mem %s\n", (char*)info
.mem
);
482 ok(pFDSA_DeleteItem(&info
, 2), "rets FALSE\n");
483 ok(info
.mem
!= mem
, "mem = %p\n", info
.mem
);
484 ok(info
.blocks_alloced
== init_blocks
+ inc
, "blocks_alloced = %d\n", info
.blocks_alloced
);
485 ok(info
.flags
== 0x1, "flags = %d\n", info
.flags
);
487 ok(!memcmp(info
.mem
, "EFGHIJKLMNuvwxyzABCDklmnopqrstabcdefghij", 40), "mem %s\n", (char*)info
.mem
);
489 ok(pFDSA_DeleteItem(&info
, 3), "rets FALSE\n");
490 ok(info
.mem
!= mem
, "mem = %p\n", info
.mem
);
491 ok(info
.blocks_alloced
== init_blocks
+ inc
, "blocks_alloced = %d\n", info
.blocks_alloced
);
492 ok(info
.flags
== 0x1, "flags = %d\n", info
.flags
);
494 ok(!memcmp(info
.mem
, "EFGHIJKLMNuvwxyzABCDklmnopqrst", 30), "mem %s\n", (char*)info
.mem
);
496 ok(!pFDSA_DeleteItem(&info
, 4), "does not ret FALSE\n");
498 /* As shlwapi has allocated memory internally, Destroy will ret FALSE */
499 ok(!pFDSA_Destroy(&info
), "FDSA_Destroy does not ret FALSE\n");
502 /* When Initialize is called with inc = 0, set it to 1 */
503 ok(pFDSA_Initialize(block_size
, 0, &info
, mem
, init_blocks
), "FDSA_Initialize rets FALSE\n");
504 ok(info
.inc
== 1, "inc = %d\n", info
.inc
);
506 /* This time, because shlwapi hasn't had to allocate memory
507 internally, Destroy rets non-zero */
508 ok(pFDSA_Destroy(&info
), "FDSA_Destroy rets FALSE\n");
511 HeapFree(GetProcessHeap(), 0, mem
);
515 typedef struct SHELL_USER_SID
{
516 SID_IDENTIFIER_AUTHORITY sidAuthority
;
519 } SHELL_USER_SID
, *PSHELL_USER_SID
;
520 typedef struct SHELL_USER_PERMISSION
{
521 SHELL_USER_SID susID
;
526 DWORD dwInheritAccessMask
;
527 } SHELL_USER_PERMISSION
, *PSHELL_USER_PERMISSION
;
528 static void test_GetShellSecurityDescriptor(void)
530 SHELL_USER_PERMISSION supCurrentUserFull
= {
531 { {SECURITY_NULL_SID_AUTHORITY
}, 0, 0 },
532 ACCESS_ALLOWED_ACE_TYPE
, FALSE
,
534 #define MY_INHERITANCE 0xBE /* invalid value to proof behavior */
535 SHELL_USER_PERMISSION supEveryoneDenied
= {
536 { {SECURITY_WORLD_SID_AUTHORITY
}, SECURITY_WORLD_RID
, 0 },
537 ACCESS_DENIED_ACE_TYPE
, TRUE
,
538 GENERIC_WRITE
, MY_INHERITANCE
| 0xDEADBA00, GENERIC_READ
};
539 PSHELL_USER_PERMISSION rgsup
[2] = {
540 &supCurrentUserFull
, &supEveryoneDenied
,
542 SECURITY_DESCRIPTOR
* psd
;
543 SECURITY_DESCRIPTOR
* (WINAPI
*pGetShellSecurityDescriptor
)(PSHELL_USER_PERMISSION
*,int);
545 pGetShellSecurityDescriptor
=(void*)GetProcAddress(hShlwapi
,(char*)475);
547 if(!pGetShellSecurityDescriptor
)
549 win_skip("GetShellSecurityDescriptor not available\n");
553 psd
= pGetShellSecurityDescriptor(NULL
, 2);
555 broken(psd
==INVALID_HANDLE_VALUE
), /* IE5 */
556 "GetShellSecurityDescriptor should fail\n");
557 psd
= pGetShellSecurityDescriptor(rgsup
, 0);
558 ok(psd
==NULL
, "GetShellSecurityDescriptor should fail\n");
560 SetLastError(0xdeadbeef);
561 psd
= pGetShellSecurityDescriptor(rgsup
, 2);
562 if (psd
== NULL
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
564 /* The previous calls to GetShellSecurityDescriptor don't set the last error */
565 win_skip("GetShellSecurityDescriptor is not implemented\n");
568 if (psd
==INVALID_HANDLE_VALUE
)
570 win_skip("GetShellSecurityDescriptor is broken on IE5\n");
573 ok(psd
!=NULL
, "GetShellSecurityDescriptor failed\n");
576 BOOL bHasDacl
= FALSE
, bDefaulted
;
579 SECURITY_DESCRIPTOR_CONTROL control
;
581 ok(IsValidSecurityDescriptor(psd
), "returned value is not valid SD\n");
583 ok(GetSecurityDescriptorControl(psd
, &control
, &dwRev
),
584 "GetSecurityDescriptorControl failed with error %u\n", GetLastError());
585 ok(0 == (control
& SE_SELF_RELATIVE
), "SD should be absolute\n");
587 ok(GetSecurityDescriptorDacl(psd
, &bHasDacl
, &pAcl
, &bDefaulted
),
588 "GetSecurityDescriptorDacl failed with error %u\n", GetLastError());
590 ok(bHasDacl
, "SD has no DACL\n");
593 ok(!bDefaulted
, "DACL should not be defaulted\n");
595 ok(pAcl
!= NULL
, "NULL DACL!\n");
598 ACL_SIZE_INFORMATION asiSize
;
600 ok(IsValidAcl(pAcl
), "DACL is not valid\n");
602 ok(GetAclInformation(pAcl
, &asiSize
, sizeof(asiSize
), AclSizeInformation
),
603 "GetAclInformation failed with error %u\n", GetLastError());
605 ok(asiSize
.AceCount
== 3, "Incorrect number of ACEs: %d entries\n", asiSize
.AceCount
);
606 if (asiSize
.AceCount
== 3)
608 ACCESS_ALLOWED_ACE
*paaa
; /* will use for DENIED too */
610 ok(GetAce(pAcl
, 0, (LPVOID
*)&paaa
), "GetAce failed with error %u\n", GetLastError());
611 ok(paaa
->Header
.AceType
== ACCESS_ALLOWED_ACE_TYPE
,
612 "Invalid ACE type %d\n", paaa
->Header
.AceType
);
613 ok(paaa
->Header
.AceFlags
== 0, "Invalid ACE flags %x\n", paaa
->Header
.AceFlags
);
614 ok(paaa
->Mask
== GENERIC_ALL
, "Invalid ACE mask %x\n", paaa
->Mask
);
616 ok(GetAce(pAcl
, 1, (LPVOID
*)&paaa
), "GetAce failed with error %u\n", GetLastError());
617 ok(paaa
->Header
.AceType
== ACCESS_DENIED_ACE_TYPE
,
618 "Invalid ACE type %d\n", paaa
->Header
.AceType
);
619 /* first one of two ACEs generated from inheritable entry - without inheritance */
620 ok(paaa
->Header
.AceFlags
== 0, "Invalid ACE flags %x\n", paaa
->Header
.AceFlags
);
621 ok(paaa
->Mask
== GENERIC_WRITE
, "Invalid ACE mask %x\n", paaa
->Mask
);
623 ok(GetAce(pAcl
, 2, (LPVOID
*)&paaa
), "GetAce failed with error %u\n", GetLastError());
624 ok(paaa
->Header
.AceType
== ACCESS_DENIED_ACE_TYPE
,
625 "Invalid ACE type %d\n", paaa
->Header
.AceType
);
626 /* second ACE - with inheritance */
627 ok(paaa
->Header
.AceFlags
== MY_INHERITANCE
,
628 "Invalid ACE flags %x\n", paaa
->Header
.AceFlags
);
629 ok(paaa
->Mask
== GENERIC_READ
, "Invalid ACE mask %x\n", paaa
->Mask
);
638 static void test_SHPackDispParams(void)
644 if(!pSHPackDispParams
)
645 win_skip("SHPackSidpParams not available\n");
647 memset(¶ms
, 0xc0, sizeof(params
));
648 memset(vars
, 0xc0, sizeof(vars
));
649 hres
= pSHPackDispParams(¶ms
, vars
, 1, VT_I4
, 0xdeadbeef);
650 ok(hres
== S_OK
, "SHPackDispParams failed: %08x\n", hres
);
651 ok(params
.cArgs
== 1, "params.cArgs = %d\n", params
.cArgs
);
652 ok(params
.cNamedArgs
== 0, "params.cNamedArgs = %d\n", params
.cArgs
);
653 ok(params
.rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", params
.rgdispidNamedArgs
);
654 ok(params
.rgvarg
== vars
, "params.rgvarg = %p\n", params
.rgvarg
);
655 ok(V_VT(vars
) == VT_I4
, "V_VT(var) = %d\n", V_VT(vars
));
656 ok(V_I4(vars
) == 0xdeadbeef, "failed %x\n", V_I4(vars
));
658 memset(¶ms
, 0xc0, sizeof(params
));
659 hres
= pSHPackDispParams(¶ms
, NULL
, 0, 0);
660 ok(hres
== S_OK
, "SHPackDispParams failed: %08x\n", hres
);
661 ok(params
.cArgs
== 0, "params.cArgs = %d\n", params
.cArgs
);
662 ok(params
.cNamedArgs
== 0, "params.cNamedArgs = %d\n", params
.cArgs
);
663 ok(params
.rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", params
.rgdispidNamedArgs
);
664 ok(params
.rgvarg
== NULL
, "params.rgvarg = %p\n", params
.rgvarg
);
666 memset(vars
, 0xc0, sizeof(vars
));
667 memset(¶ms
, 0xc0, sizeof(params
));
668 hres
= pSHPackDispParams(¶ms
, vars
, 4, VT_BSTR
, (void*)0xdeadbeef, VT_EMPTY
, 10,
669 VT_I4
, 100, VT_DISPATCH
, (void*)0xdeadbeef);
670 ok(hres
== S_OK
, "SHPackDispParams failed: %08x\n", hres
);
671 ok(params
.cArgs
== 4, "params.cArgs = %d\n", params
.cArgs
);
672 ok(params
.cNamedArgs
== 0, "params.cNamedArgs = %d\n", params
.cArgs
);
673 ok(params
.rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", params
.rgdispidNamedArgs
);
674 ok(params
.rgvarg
== vars
, "params.rgvarg = %p\n", params
.rgvarg
);
675 ok(V_VT(vars
) == VT_DISPATCH
, "V_VT(vars[0]) = %x\n", V_VT(vars
));
676 ok(V_I4(vars
) == 0xdeadbeef, "V_I4(vars[0]) = %x\n", V_I4(vars
));
677 ok(V_VT(vars
+1) == VT_I4
, "V_VT(vars[1]) = %d\n", V_VT(vars
+1));
678 ok(V_I4(vars
+1) == 100, "V_I4(vars[1]) = %x\n", V_I4(vars
+1));
679 ok(V_VT(vars
+2) == VT_I4
, "V_VT(vars[2]) = %d\n", V_VT(vars
+2));
680 ok(V_I4(vars
+2) == 10, "V_I4(vars[2]) = %x\n", V_I4(vars
+2));
681 ok(V_VT(vars
+3) == VT_BSTR
, "V_VT(vars[3]) = %d\n", V_VT(vars
+3));
682 ok(V_BSTR(vars
+3) == (void*)0xdeadbeef, "V_BSTR(vars[3]) = %p\n", V_BSTR(vars
+3));
687 const IDispatchVtbl
*vtbl
;
691 typedef struct _contain
693 const IConnectionPointContainerVtbl
*vtbl
;
697 IConnectionPoint
**pt
;
700 typedef struct _cntptn
702 const IConnectionPointVtbl
*vtbl
;
713 const IEnumConnectionsVtbl
*vtbl
;
720 typedef struct _enumpt
722 const IEnumConnectionPointsVtbl
*vtbl
;
730 static HRESULT WINAPI
Disp_QueryInterface(
737 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDispatch
))
744 IUnknown_AddRef(This
);
748 trace("no interface\n");
749 return E_NOINTERFACE
;
752 static ULONG WINAPI
Disp_AddRef(IDispatch
* This
)
754 Disp
*iface
= (Disp
*)This
;
755 return InterlockedIncrement(&iface
->refCount
);
758 static ULONG WINAPI
Disp_Release(IDispatch
* This
)
760 Disp
*iface
= (Disp
*)This
;
763 ret
= InterlockedDecrement(&iface
->refCount
);
765 HeapFree(GetProcessHeap(),0,This
);
769 static HRESULT WINAPI
Disp_GetTypeInfoCount(
773 return ERROR_SUCCESS
;
776 static HRESULT WINAPI
Disp_GetTypeInfo(
782 return ERROR_SUCCESS
;
785 static HRESULT WINAPI
Disp_GetIDsOfNames(
793 return ERROR_SUCCESS
;
796 static HRESULT WINAPI
Disp_Invoke(
802 DISPPARAMS
*pDispParams
,
804 EXCEPINFO
*pExcepInfo
,
807 trace("%p %x %p %x %x %p %p %p %p\n",This
,dispIdMember
,riid
,lcid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,puArgErr
);
809 ok(dispIdMember
== 0xa0 || dispIdMember
== 0xa1, "Unknown dispIdMember\n");
810 ok(pDispParams
!= NULL
, "Invoked with NULL pDispParams\n");
811 ok(wFlags
== DISPATCH_METHOD
, "Wrong flags %x\n",wFlags
);
812 ok(lcid
== 0,"Wrong lcid %x\n",lcid
);
813 if (dispIdMember
== 0xa0)
815 ok(pDispParams
->cArgs
== 0, "params.cArgs = %d\n", pDispParams
->cArgs
);
816 ok(pDispParams
->cNamedArgs
== 0, "params.cNamedArgs = %d\n", pDispParams
->cArgs
);
817 ok(pDispParams
->rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", pDispParams
->rgdispidNamedArgs
);
818 ok(pDispParams
->rgvarg
== NULL
, "params.rgvarg = %p\n", pDispParams
->rgvarg
);
820 else if (dispIdMember
== 0xa1)
822 ok(pDispParams
->cArgs
== 2, "params.cArgs = %d\n", pDispParams
->cArgs
);
823 ok(pDispParams
->cNamedArgs
== 0, "params.cNamedArgs = %d\n", pDispParams
->cArgs
);
824 ok(pDispParams
->rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", pDispParams
->rgdispidNamedArgs
);
825 ok(V_VT(pDispParams
->rgvarg
) == VT_BSTR
, "V_VT(var) = %d\n", V_VT(pDispParams
->rgvarg
));
826 ok(V_I4(pDispParams
->rgvarg
) == 0xdeadcafe , "failed %p\n", V_BSTR(pDispParams
->rgvarg
));
827 ok(V_VT(pDispParams
->rgvarg
+1) == VT_I4
, "V_VT(var) = %d\n", V_VT(pDispParams
->rgvarg
+1));
828 ok(V_I4(pDispParams
->rgvarg
+1) == 0xdeadbeef, "failed %x\n", V_I4(pDispParams
->rgvarg
+1));
831 return ERROR_SUCCESS
;
834 static const IDispatchVtbl disp_vtbl
= {
839 Disp_GetTypeInfoCount
,
845 static HRESULT WINAPI
Enum_QueryInterface(
846 IEnumConnections
* This
,
852 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IEnumConnections
))
859 IUnknown_AddRef(This
);
863 trace("no interface\n");
864 return E_NOINTERFACE
;
867 static ULONG WINAPI
Enum_AddRef(IEnumConnections
* This
)
869 EnumCon
*iface
= (EnumCon
*)This
;
870 return InterlockedIncrement(&iface
->refCount
);
873 static ULONG WINAPI
Enum_Release(IEnumConnections
* This
)
875 EnumCon
*iface
= (EnumCon
*)This
;
878 ret
= InterlockedDecrement(&iface
->refCount
);
880 HeapFree(GetProcessHeap(),0,This
);
884 static HRESULT WINAPI
Enum_Next(
885 IEnumConnections
* This
,
890 EnumCon
*iface
= (EnumCon
*)This
;
892 if (cConnections
> 0 && iface
->idx
< iface
->pt
->sinkCount
)
894 rgcd
->pUnk
= iface
->pt
->sink
[iface
->idx
];
895 IUnknown_AddRef(iface
->pt
->sink
[iface
->idx
]);
906 static HRESULT WINAPI
Enum_Skip(
907 IEnumConnections
* This
,
913 static HRESULT WINAPI
Enum_Reset(
914 IEnumConnections
* This
)
919 static HRESULT WINAPI
Enum_Clone(
920 IEnumConnections
* This
,
921 IEnumConnections
**ppEnum
)
926 static const IEnumConnectionsVtbl enum_vtbl
= {
937 static HRESULT WINAPI
ConPt_QueryInterface(
938 IConnectionPoint
* This
,
944 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IConnectionPoint
))
951 IUnknown_AddRef(This
);
955 trace("no interface\n");
956 return E_NOINTERFACE
;
959 static ULONG WINAPI
ConPt_AddRef(
960 IConnectionPoint
* This
)
962 ConPt
*iface
= (ConPt
*)This
;
963 return InterlockedIncrement(&iface
->refCount
);
966 static ULONG WINAPI
ConPt_Release(
967 IConnectionPoint
* This
)
969 ConPt
*iface
= (ConPt
*)This
;
972 ret
= InterlockedDecrement(&iface
->refCount
);
975 if (iface
->sinkCount
> 0)
978 for (i
= 0; i
< iface
->sinkCount
; i
++)
981 IUnknown_Release(iface
->sink
[i
]);
983 HeapFree(GetProcessHeap(),0,iface
->sink
);
985 HeapFree(GetProcessHeap(),0,This
);
990 static HRESULT WINAPI
ConPt_GetConnectionInterface(
991 IConnectionPoint
* This
,
995 ConPt
*iface
= (ConPt
*)This
;
1002 memcpy(pIID
,&iface
->id
,sizeof(GUID
));
1006 static HRESULT WINAPI
ConPt_GetConnectionPointContainer(
1007 IConnectionPoint
* This
,
1008 IConnectionPointContainer
**ppCPC
)
1010 ConPt
*iface
= (ConPt
*)This
;
1012 *ppCPC
= (IConnectionPointContainer
*)iface
->container
;
1016 static HRESULT WINAPI
ConPt_Advise(
1017 IConnectionPoint
* This
,
1021 ConPt
*iface
= (ConPt
*)This
;
1023 if (iface
->sinkCount
== 0)
1024 iface
->sink
= HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown
*));
1026 iface
->sink
= HeapReAlloc(GetProcessHeap(),0,iface
->sink
,sizeof(IUnknown
*)*(iface
->sinkCount
+1));
1027 iface
->sink
[iface
->sinkCount
] = pUnkSink
;
1028 IUnknown_AddRef(pUnkSink
);
1030 *pdwCookie
= iface
->sinkCount
;
1034 static HRESULT WINAPI
ConPt_Unadvise(
1035 IConnectionPoint
* This
,
1038 ConPt
*iface
= (ConPt
*)This
;
1040 if (dwCookie
> iface
->sinkCount
)
1044 IUnknown_Release(iface
->sink
[dwCookie
-1]);
1045 iface
->sink
[dwCookie
-1] = NULL
;
1050 static HRESULT WINAPI
ConPt_EnumConnections(
1051 IConnectionPoint
* This
,
1052 IEnumConnections
**ppEnum
)
1056 ec
= HeapAlloc(GetProcessHeap(),0,sizeof(EnumCon
));
1057 ec
->vtbl
= &enum_vtbl
;
1059 ec
->pt
= (ConPt
*)This
;
1061 *ppEnum
= (IEnumConnections
*)ec
;
1066 static const IConnectionPointVtbl point_vtbl
= {
1067 ConPt_QueryInterface
,
1071 ConPt_GetConnectionInterface
,
1072 ConPt_GetConnectionPointContainer
,
1075 ConPt_EnumConnections
1078 static HRESULT WINAPI
EnumPt_QueryInterface(
1079 IEnumConnectionPoints
* This
,
1085 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IEnumConnectionPoints
))
1092 IUnknown_AddRef(This
);
1096 trace("no interface\n");
1097 return E_NOINTERFACE
;
1100 static ULONG WINAPI
EnumPt_AddRef(IEnumConnectionPoints
* This
)
1102 EnumPt
*iface
= (EnumPt
*)This
;
1103 return InterlockedIncrement(&iface
->refCount
);
1106 static ULONG WINAPI
EnumPt_Release(IEnumConnectionPoints
* This
)
1108 EnumPt
*iface
= (EnumPt
*)This
;
1111 ret
= InterlockedDecrement(&iface
->refCount
);
1113 HeapFree(GetProcessHeap(),0,This
);
1117 static HRESULT WINAPI
EnumPt_Next(
1118 IEnumConnectionPoints
* This
,
1120 IConnectionPoint
**rgcd
,
1123 EnumPt
*iface
= (EnumPt
*)This
;
1125 if (cConnections
> 0 && iface
->idx
< iface
->container
->ptCount
)
1127 *rgcd
= iface
->container
->pt
[iface
->idx
];
1128 IUnknown_AddRef(iface
->container
->pt
[iface
->idx
]);
1138 static HRESULT WINAPI
EnumPt_Skip(
1139 IEnumConnectionPoints
* This
,
1145 static HRESULT WINAPI
EnumPt_Reset(
1146 IEnumConnectionPoints
* This
)
1151 static HRESULT WINAPI
EnumPt_Clone(
1152 IEnumConnectionPoints
* This
,
1153 IEnumConnectionPoints
**ppEnumPt
)
1158 static const IEnumConnectionPointsVtbl enumpt_vtbl
= {
1160 EnumPt_QueryInterface
,
1169 static HRESULT WINAPI
Contain_QueryInterface(
1170 IConnectionPointContainer
* This
,
1176 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IConnectionPointContainer
))
1183 IUnknown_AddRef(This
);
1187 trace("no interface\n");
1188 return E_NOINTERFACE
;
1191 static ULONG WINAPI
Contain_AddRef(
1192 IConnectionPointContainer
* This
)
1194 Contain
*iface
= (Contain
*)This
;
1195 return InterlockedIncrement(&iface
->refCount
);
1198 static ULONG WINAPI
Contain_Release(
1199 IConnectionPointContainer
* This
)
1201 Contain
*iface
= (Contain
*)This
;
1204 ret
= InterlockedDecrement(&iface
->refCount
);
1207 if (iface
->ptCount
> 0)
1210 for (i
= 0; i
< iface
->ptCount
; i
++)
1211 IUnknown_Release(iface
->pt
[i
]);
1212 HeapFree(GetProcessHeap(),0,iface
->pt
);
1214 HeapFree(GetProcessHeap(),0,This
);
1219 static HRESULT WINAPI
Contain_EnumConnectionPoints(
1220 IConnectionPointContainer
* This
,
1221 IEnumConnectionPoints
**ppEnum
)
1225 ec
= HeapAlloc(GetProcessHeap(),0,sizeof(EnumPt
));
1226 ec
->vtbl
= &enumpt_vtbl
;
1229 ec
->container
= (Contain
*)This
;
1230 *ppEnum
= (IEnumConnectionPoints
*)ec
;
1235 static HRESULT WINAPI
Contain_FindConnectionPoint(
1236 IConnectionPointContainer
* This
,
1238 IConnectionPoint
**ppCP
)
1240 Contain
*iface
= (Contain
*)This
;
1243 if (!IsEqualIID(riid
, &IID_NULL
) || iface
->ptCount
==0)
1245 pt
= HeapAlloc(GetProcessHeap(),0,sizeof(ConPt
));
1246 pt
->vtbl
= &point_vtbl
;
1250 pt
->container
= iface
;
1251 pt
->id
= IID_IDispatch
;
1253 if (iface
->ptCount
== 0)
1254 iface
->pt
=HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown
*));
1256 iface
->pt
= HeapReAlloc(GetProcessHeap(),0,iface
->pt
,sizeof(IUnknown
*)*(iface
->ptCount
+1));
1257 iface
->pt
[iface
->ptCount
] = (IConnectionPoint
*)pt
;
1260 *ppCP
= (IConnectionPoint
*)pt
;
1264 *ppCP
= iface
->pt
[0];
1265 IUnknown_AddRef((IUnknown
*)*ppCP
);
1271 static const IConnectionPointContainerVtbl contain_vtbl
= {
1272 Contain_QueryInterface
,
1276 Contain_EnumConnectionPoints
,
1277 Contain_FindConnectionPoint
1280 static void test_IConnectionPoint(void)
1284 IConnectionPoint
*point
;
1287 DWORD cookie
= 0xffffffff;
1291 if (!pIConnectionPoint_SimpleInvoke
|| !pConnectToConnectionPoint
)
1293 win_skip("IConnectionPoint Apis not present\n");
1297 container
= HeapAlloc(GetProcessHeap(),0,sizeof(Contain
));
1298 container
->vtbl
= &contain_vtbl
;
1299 container
->refCount
= 1;
1300 container
->ptCount
= 0;
1301 container
->pt
= NULL
;
1303 dispatch
= HeapAlloc(GetProcessHeap(),0,sizeof(Disp
));
1304 dispatch
->vtbl
= &disp_vtbl
;
1305 dispatch
->refCount
= 1;
1307 rc
= pConnectToConnectionPoint((IUnknown
*)dispatch
, &IID_NULL
, TRUE
, (IUnknown
*)container
, &cookie
, &point
);
1308 ok(rc
== S_OK
, "pConnectToConnectionPoint failed with %x\n",rc
);
1309 ok(point
!= NULL
, "returned ConnectionPoint is NULL\n");
1310 ok(cookie
!= 0xffffffff, "invalid cookie returned\n");
1312 rc
= pIConnectionPoint_SimpleInvoke(point
,0xa0,NULL
);
1313 ok(rc
== S_OK
, "pConnectToConnectionPoint failed with %x\n",rc
);
1315 if (pSHPackDispParams
)
1317 memset(¶ms
, 0xc0, sizeof(params
));
1318 memset(vars
, 0xc0, sizeof(vars
));
1319 rc
= pSHPackDispParams(¶ms
, vars
, 2, VT_I4
, 0xdeadbeef, VT_BSTR
, 0xdeadcafe);
1320 ok(rc
== S_OK
, "SHPackDispParams failed: %08x\n", rc
);
1322 rc
= pIConnectionPoint_SimpleInvoke(point
,0xa1,¶ms
);
1323 ok(rc
== S_OK
, "pConnectToConnectionPoint failed with %x\n",rc
);
1326 win_skip("pSHPackDispParams not present\n");
1328 rc
= pConnectToConnectionPoint(NULL
, &IID_NULL
, FALSE
, (IUnknown
*)container
, &cookie
, NULL
);
1329 ok(rc
== S_OK
, "pConnectToConnectionPoint failed with %x\n",rc
);
1331 /* MSDN says this should be required but it crashs on XP
1332 IUnknown_Release(point);
1334 ref
= IUnknown_Release((IUnknown
*)container
);
1335 ok(ref
== 0, "leftover IConnectionPointContainer reference %i\n",ref
);
1336 ref
= IUnknown_Release((IUnknown
*)dispatch
);
1337 ok(ref
== 0, "leftover IDispatch reference %i\n",ref
);
1340 typedef struct _propbag
1342 const IPropertyBagVtbl
*vtbl
;
1348 static HRESULT WINAPI
Prop_QueryInterface(
1355 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IPropertyBag
))
1362 IUnknown_AddRef(This
);
1366 trace("no interface\n");
1367 return E_NOINTERFACE
;
1370 static ULONG WINAPI
Prop_AddRef(
1373 PropBag
*iface
= (PropBag
*)This
;
1374 return InterlockedIncrement(&iface
->refCount
);
1377 static ULONG WINAPI
Prop_Release(
1380 PropBag
*iface
= (PropBag
*)This
;
1383 ret
= InterlockedDecrement(&iface
->refCount
);
1385 HeapFree(GetProcessHeap(),0,This
);
1389 static HRESULT WINAPI
Prop_Read(
1391 LPCOLESTR pszPropName
,
1393 IErrorLog
*pErrorLog
)
1395 V_VT(pVar
) = VT_BLOB
|VT_BYREF
;
1396 V_BYREF(pVar
) = (LPVOID
)0xdeadcafe;
1400 static HRESULT WINAPI
Prop_Write(
1402 LPCOLESTR pszPropName
,
1409 static const IPropertyBagVtbl prop_vtbl
= {
1410 Prop_QueryInterface
,
1418 static void test_SHPropertyBag_ReadLONG(void)
1423 static const WCHAR szName1
[] = {'n','a','m','e','1',0};
1425 if (!pSHPropertyBag_ReadLONG
)
1427 win_skip("SHPropertyBag_ReadLONG not present\n");
1431 pb
= HeapAlloc(GetProcessHeap(),0,sizeof(PropBag
));
1433 pb
->vtbl
= &prop_vtbl
;
1436 rc
= pSHPropertyBag_ReadLONG(NULL
, szName1
, &out
);
1437 ok(rc
== E_INVALIDARG
|| broken(rc
== 0), "incorrect return %x\n",rc
);
1438 ok(out
== 0xfeedface, "value should not have changed\n");
1439 rc
= pSHPropertyBag_ReadLONG((IPropertyBag
*)pb
, NULL
, &out
);
1440 ok(rc
== E_INVALIDARG
|| broken(rc
== 0) || broken(rc
== 1), "incorrect return %x\n",rc
);
1441 ok(out
== 0xfeedface, "value should not have changed\n");
1442 rc
= pSHPropertyBag_ReadLONG((IPropertyBag
*)pb
, szName1
, NULL
);
1443 ok(rc
== E_INVALIDARG
|| broken(rc
== 0) || broken(rc
== 1), "incorrect return %x\n",rc
);
1444 ok(out
== 0xfeedface, "value should not have changed\n");
1445 rc
= pSHPropertyBag_ReadLONG((IPropertyBag
*)pb
, szName1
, &out
);
1446 ok(rc
== DISP_E_BADVARTYPE
|| broken(rc
== 0) || broken(rc
== 1), "incorrect return %x\n",rc
);
1447 ok(out
== 0xfeedface || broken(out
== 0xfeedfa00), "value should not have changed %x\n",out
);
1448 IUnknown_Release((IUnknown
*)pb
);
1453 static void test_SHSetWindowBits(void)
1456 DWORD style
, styleold
;
1459 if(!pSHSetWindowBits
)
1461 win_skip("SHSetWindowBits is not available\n");
1466 clsA
.lpfnWndProc
= DefWindowProcA
;
1467 clsA
.cbClsExtra
= 0;
1468 clsA
.cbWndExtra
= 0;
1469 clsA
.hInstance
= GetModuleHandleA(NULL
);
1471 clsA
.hCursor
= LoadCursorA(0, IDC_ARROW
);
1472 clsA
.hbrBackground
= NULL
;
1473 clsA
.lpszMenuName
= NULL
;
1474 clsA
.lpszClassName
= "Shlwapi test class";
1475 RegisterClassA(&clsA
);
1477 hwnd
= CreateWindowA("Shlwapi test class", "Test", WS_VISIBLE
, 0, 0, 100, 100,
1478 NULL
, NULL
, GetModuleHandle(NULL
), 0);
1479 ok(IsWindow(hwnd
), "failed to create window\n");
1482 SetLastError(0xdeadbeef);
1483 style
= pSHSetWindowBits(NULL
, GWL_STYLE
, 0, 0);
1484 ok(style
== 0, "expected 0 retval, got %d\n", style
);
1485 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
||
1486 broken(GetLastError() == 0xdeadbeef), /* Win9x/WinMe */
1487 "expected ERROR_INVALID_WINDOW_HANDLE, got %d\n", GetLastError());
1489 /* zero mask, zero flags */
1490 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1491 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, 0, 0);
1492 ok(styleold
== style
, "expected old style\n");
1493 ok(styleold
== GetWindowLongA(hwnd
, GWL_STYLE
), "expected to keep old style\n");
1496 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1497 ok(styleold
& WS_VISIBLE
, "expected WS_VISIBLE\n");
1498 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, WS_VISIBLE
, 0);
1500 ok(style
== styleold
, "expected previous style, got %x\n", style
);
1501 ok((GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
) == 0, "expected updated style\n");
1503 /* test mask, unset style bit used */
1504 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1505 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, WS_VISIBLE
, 0);
1506 ok(style
== styleold
, "expected previous style, got %x\n", style
);
1507 ok(styleold
== GetWindowLongA(hwnd
, GWL_STYLE
), "expected to keep old style\n");
1509 /* set back with flags */
1510 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1511 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, WS_VISIBLE
, WS_VISIBLE
);
1512 ok(style
== styleold
, "expected previous style, got %x\n", style
);
1513 ok(GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
, "expected updated style\n");
1515 /* reset and try to set without a mask */
1516 pSHSetWindowBits(hwnd
, GWL_STYLE
, WS_VISIBLE
, 0);
1517 ok((GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
) == 0, "expected updated style\n");
1518 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1519 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, 0, WS_VISIBLE
);
1520 ok(style
== styleold
, "expected previous style, got %x\n", style
);
1521 ok((GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
) == 0, "expected updated style\n");
1523 DestroyWindow(hwnd
);
1525 UnregisterClassA("Shlwapi test class", GetModuleHandleA(NULL
));
1528 static void test_SHFormatDateTimeA(void)
1530 FILETIME UNALIGNED filetime
;
1531 CHAR buff
[100], buff2
[100], buff3
[100];
1536 if(!pSHFormatDateTimeA
)
1538 win_skip("pSHFormatDateTimeA isn't available\n");
1544 /* crashes on native */
1545 ret
= pSHFormatDateTimeA(NULL
, NULL
, NULL
, 0);
1549 SystemTimeToFileTime(&st
, &filetime
);
1550 /* SHFormatDateTime expects input as utc */
1551 LocalFileTimeToFileTime(&filetime
, &filetime
);
1553 /* no way to get required buffer length here */
1554 SetLastError(0xdeadbeef);
1555 ret
= pSHFormatDateTimeA(&filetime
, NULL
, NULL
, 0);
1556 ok(ret
== 0, "got %d\n", ret
);
1557 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1559 SetLastError(0xdeadbeef);
1560 buff
[0] = 'a'; buff
[1] = 0;
1561 ret
= pSHFormatDateTimeA(&filetime
, NULL
, buff
, 0);
1562 ok(ret
== 0, "got %d\n", ret
);
1563 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1564 ok(buff
[0] == 'a', "expected same string, got %s\n", buff
);
1566 /* flags needs to have FDTF_NOAUTOREADINGORDER for these tests to succeed on Vista+ */
1568 /* all combinations documented as invalid succeeded */
1569 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTTIME
| FDTF_LONGTIME
;
1570 SetLastError(0xdeadbeef);
1571 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1572 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1573 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1575 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTDATE
| FDTF_LONGDATE
;
1576 SetLastError(0xdeadbeef);
1577 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1578 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1579 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1581 flags
= FDTF_SHORTDATE
| FDTF_LTRDATE
| FDTF_RTLDATE
;
1582 SetLastError(0xdeadbeef);
1583 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1584 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1585 ok(GetLastError() == 0xdeadbeef ||
1586 broken(GetLastError() == ERROR_INVALID_FLAGS
), /* Win9x/WinMe */
1587 "expected 0xdeadbeef, got %d\n", GetLastError());
1589 /* now check returned strings */
1590 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTTIME
;
1591 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1592 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1593 ret
= GetTimeFormat(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff2
, sizeof(buff2
));
1594 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1595 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1597 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGTIME
;
1598 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1599 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1600 ret
= GetTimeFormat(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff2
, sizeof(buff2
));
1601 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1602 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1604 /* both time flags */
1605 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGTIME
| FDTF_SHORTTIME
;
1606 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1607 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1608 ret
= GetTimeFormat(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff2
, sizeof(buff2
));
1609 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1610 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1612 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTDATE
;
1613 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1614 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1615 ret
= GetDateFormat(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1616 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1617 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1619 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGDATE
;
1620 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1621 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1622 ret
= GetDateFormat(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1623 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1624 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1626 /* both date flags */
1627 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGDATE
| FDTF_SHORTDATE
;
1628 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1629 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1630 ret
= GetDateFormat(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1631 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1632 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1634 /* various combinations of date/time flags */
1635 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGDATE
| FDTF_SHORTTIME
;
1636 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1637 ok(ret
== lstrlenA(buff
)+1, "got %d, length %d\n", ret
, lstrlenA(buff
)+1);
1638 ret
= GetDateFormat(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1639 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1640 strcat(buff2
, ", ");
1641 ret
= GetTimeFormat(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff3
, sizeof(buff3
));
1642 ok(ret
== lstrlenA(buff3
)+1, "got %d\n", ret
);
1643 strcat(buff2
, buff3
);
1644 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1646 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGDATE
| FDTF_LONGTIME
;
1647 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1648 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1649 ret
= GetDateFormat(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1650 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1651 strcat(buff2
, ", ");
1652 ret
= GetTimeFormat(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff3
, sizeof(buff3
));
1653 ok(ret
== lstrlenA(buff3
)+1, "got %d\n", ret
);
1654 strcat(buff2
, buff3
);
1655 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1657 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTDATE
| FDTF_SHORTTIME
;
1658 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1659 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1660 ret
= GetDateFormat(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1661 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1663 ret
= GetTimeFormat(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff3
, sizeof(buff3
));
1664 ok(ret
== lstrlenA(buff3
)+1, "got %d\n", ret
);
1665 strcat(buff2
, buff3
);
1666 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1668 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTDATE
| FDTF_LONGTIME
;
1669 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1670 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1671 ret
= GetDateFormat(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1672 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1674 ret
= GetTimeFormat(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff3
, sizeof(buff3
));
1675 ok(ret
== lstrlenA(buff3
)+1, "got %d\n", ret
);
1676 strcat(buff2
, buff3
);
1677 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1680 static void test_SHFormatDateTimeW(void)
1682 FILETIME UNALIGNED filetime
;
1683 WCHAR buff
[100], buff2
[100], buff3
[100];
1687 static const WCHAR spaceW
[] = {' ',0};
1688 static const WCHAR commaW
[] = {',',' ',0};
1690 if(!pSHFormatDateTimeW
)
1692 win_skip("pSHFormatDateTimeW isn't available\n");
1698 /* crashes on native */
1699 ret
= pSHFormatDateTimeW(NULL
, NULL
, NULL
, 0);
1703 SystemTimeToFileTime(&st
, &filetime
);
1704 /* SHFormatDateTime expects input as utc */
1705 LocalFileTimeToFileTime(&filetime
, &filetime
);
1707 /* no way to get required buffer length here */
1708 SetLastError(0xdeadbeef);
1709 ret
= pSHFormatDateTimeW(&filetime
, NULL
, NULL
, 0);
1710 ok(ret
== 0, "got %d\n", ret
);
1711 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1713 SetLastError(0xdeadbeef);
1714 buff
[0] = 'a'; buff
[1] = 0;
1715 ret
= pSHFormatDateTimeW(&filetime
, NULL
, buff
, 0);
1716 ok(ret
== 0, "got %d\n", ret
);
1717 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1718 ok(buff
[0] == 'a', "expected same string\n");
1720 /* all combinations documented as invalid succeeded */
1721 flags
= FDTF_SHORTTIME
| FDTF_LONGTIME
;
1722 SetLastError(0xdeadbeef);
1723 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1724 ok(ret
== lstrlenW(buff
)+1, "got %d\n", ret
);
1725 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1727 flags
= FDTF_SHORTDATE
| FDTF_LONGDATE
;
1728 SetLastError(0xdeadbeef);
1729 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1730 ok(ret
== lstrlenW(buff
)+1, "got %d\n", ret
);
1731 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1733 flags
= FDTF_SHORTDATE
| FDTF_LTRDATE
| FDTF_RTLDATE
;
1734 SetLastError(0xdeadbeef);
1735 buff
[0] = 0; /* NT4 doesn't clear the buffer on failure */
1736 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1737 ok(ret
== lstrlenW(buff
)+1, "got %d\n", ret
);
1738 ok(GetLastError() == 0xdeadbeef ||
1739 broken(GetLastError() == ERROR_INVALID_FLAGS
), /* Win9x/WinMe/NT4 */
1740 "expected 0xdeadbeef, got %d\n", GetLastError());
1742 /* now check returned strings */
1743 flags
= FDTF_SHORTTIME
;
1744 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1745 ok(ret
== lstrlenW(buff
)+1, "got %d\n", ret
);
1746 SetLastError(0xdeadbeef);
1747 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1748 if (ret
== 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
1750 win_skip("Needed W-functions are not implemented\n");
1753 ok(ret
== lstrlenW(buff2
)+1, "got %d\n", ret
);
1754 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1756 flags
= FDTF_LONGTIME
;
1757 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1758 ok(ret
== lstrlenW(buff
)+1, "got %d\n", ret
);
1759 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1760 ok(ret
== lstrlenW(buff2
)+1, "got %d\n", ret
);
1761 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1763 /* both time flags */
1764 flags
= FDTF_LONGTIME
| FDTF_SHORTTIME
;
1765 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1766 ok(ret
== lstrlenW(buff
)+1, "got %d\n", ret
);
1767 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1768 ok(ret
== lstrlenW(buff2
)+1, "got %d\n", ret
);
1769 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal string\n");
1771 flags
= FDTF_SHORTDATE
;
1772 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1773 ok(ret
== lstrlenW(buff
)+1, "got %d\n", ret
);
1774 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1775 ok(ret
== lstrlenW(buff2
)+1, "got %d\n", ret
);
1776 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1778 flags
= FDTF_LONGDATE
;
1779 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1780 ok(ret
== lstrlenW(buff
)+1, "got %d\n", ret
);
1781 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1782 ok(ret
== lstrlenW(buff2
)+1, "got %d\n", ret
);
1783 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1785 /* both date flags */
1786 flags
= FDTF_LONGDATE
| FDTF_SHORTDATE
;
1787 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1788 ok(ret
== lstrlenW(buff
)+1, "got %d\n", ret
);
1789 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1790 ok(ret
== lstrlenW(buff2
)+1, "got %d\n", ret
);
1791 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1793 /* various combinations of date/time flags */
1794 flags
= FDTF_LONGDATE
| FDTF_SHORTTIME
;
1795 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1796 ok(ret
== lstrlenW(buff
)+1, "got %d, length %d\n", ret
, lstrlenW(buff
)+1);
1797 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1798 ok(ret
== lstrlenW(buff2
)+1, "got %d\n", ret
);
1799 lstrcatW(buff2
, commaW
);
1800 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff3
, sizeof(buff3
)/sizeof(WCHAR
));
1801 ok(ret
== lstrlenW(buff3
)+1, "got %d\n", ret
);
1802 lstrcatW(buff2
, buff3
);
1803 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1805 flags
= FDTF_LONGDATE
| FDTF_LONGTIME
;
1806 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1807 ok(ret
== lstrlenW(buff
)+1, "got %d\n", ret
);
1808 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1809 ok(ret
== lstrlenW(buff2
)+1, "got %d\n", ret
);
1810 lstrcatW(buff2
, commaW
);
1811 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff3
, sizeof(buff3
)/sizeof(WCHAR
));
1812 ok(ret
== lstrlenW(buff3
)+1, "got %d\n", ret
);
1813 lstrcatW(buff2
, buff3
);
1814 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1816 flags
= FDTF_SHORTDATE
| FDTF_SHORTTIME
;
1817 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1818 ok(ret
== lstrlenW(buff
)+1, "got %d\n", ret
);
1819 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1820 ok(ret
== lstrlenW(buff2
)+1, "got %d\n", ret
);
1821 lstrcatW(buff2
, spaceW
);
1822 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff3
, sizeof(buff3
)/sizeof(WCHAR
));
1823 ok(ret
== lstrlenW(buff3
)+1, "got %d\n", ret
);
1824 lstrcatW(buff2
, buff3
);
1825 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1827 flags
= FDTF_SHORTDATE
| FDTF_LONGTIME
;
1828 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1829 ok(ret
== lstrlenW(buff
)+1, "got %d\n", ret
);
1830 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1831 ok(ret
== lstrlenW(buff2
)+1, "got %d\n", ret
);
1832 lstrcatW(buff2
, spaceW
);
1833 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff3
, sizeof(buff3
)/sizeof(WCHAR
));
1834 ok(ret
== lstrlenW(buff3
)+1, "got %d\n", ret
);
1835 lstrcatW(buff2
, buff3
);
1836 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1839 static void test_SHGetObjectCompatFlags(void)
1841 struct compat_value
{
1846 struct compat_value values
[] = {
1847 { "OTNEEDSSFCACHE", 0x1 },
1848 { "NO_WEBVIEW", 0x2 },
1849 { "UNBINDABLE", 0x4 },
1851 { "NEEDSFILESYSANCESTOR", 0x10 },
1852 { "NOTAFILESYSTEM", 0x20 },
1853 { "CTXMENU_NOVERBS", 0x40 },
1854 { "CTXMENU_LIMITEDQI", 0x80 },
1855 { "COCREATESHELLFOLDERONLY", 0x100 },
1856 { "NEEDSSTORAGEANCESTOR", 0x200 },
1857 { "NOLEGACYWEBVIEW", 0x400 },
1858 { "CTXMENU_XPQCMFLAGS", 0x1000 },
1859 { "NOIPROPERTYSTORE", 0x2000 }
1862 static const char compat_path
[] = "Software\\Microsoft\\Windows\\CurrentVersion\\ShellCompatibility\\Objects";
1863 CHAR keyA
[39]; /* {CLSID} */
1868 if (!pSHGetObjectCompatFlags
)
1870 win_skip("SHGetObjectCompatFlags isn't available\n");
1875 ret
= pSHGetObjectCompatFlags(NULL
, NULL
);
1876 ok(ret
== 0, "got %d\n", ret
);
1878 ret
= RegOpenKeyA(HKEY_LOCAL_MACHINE
, compat_path
, &root
);
1879 if (ret
!= ERROR_SUCCESS
)
1881 skip("No compatibility class data found\n");
1885 for (i
= 0; RegEnumKeyA(root
, i
, keyA
, sizeof(keyA
)) == ERROR_SUCCESS
; i
++)
1889 if (RegOpenKeyA(root
, keyA
, &clsid_key
) == ERROR_SUCCESS
)
1892 DWORD expected
= 0, got
, length
= sizeof(valueA
);
1896 for (v
= 0; RegEnumValueA(clsid_key
, v
, valueA
, &length
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
; v
++)
1900 for (j
= 0; j
< sizeof(values
)/sizeof(struct compat_value
); j
++)
1901 if (lstrcmpA(values
[j
].nameA
, valueA
) == 0)
1903 expected
|= values
[j
].value
;
1907 length
= sizeof(valueA
);
1910 pGUIDFromStringA(keyA
, &clsid
);
1911 got
= pSHGetObjectCompatFlags(NULL
, &clsid
);
1912 ok(got
== expected
, "got 0x%08x, expected 0x%08x. Key %s\n", got
, expected
, keyA
);
1914 RegCloseKey(clsid_key
);
1921 static call_trace_t IUnknown_QueryServiceExec_trace
;
1924 const IOleCommandTargetVtbl
*lpVtbl
;
1926 } IOleCommandTargetImpl
;
1928 static const IOleCommandTargetVtbl IOleCommandTargetImpl_Vtbl
;
1930 IOleCommandTarget
* IOleCommandTargetImpl_Construct(void)
1932 IOleCommandTargetImpl
*obj
;
1934 obj
= HeapAlloc(GetProcessHeap(), 0, sizeof(*obj
));
1935 obj
->lpVtbl
= &IOleCommandTargetImpl_Vtbl
;
1938 return (IOleCommandTarget
*)obj
;
1941 static HRESULT WINAPI
IOleCommandTargetImpl_QueryInterface(IOleCommandTarget
*iface
, REFIID riid
, void **ppvObj
)
1943 IOleCommandTargetImpl
*This
= (IOleCommandTargetImpl
*)iface
;
1945 if (IsEqualIID(riid
, &IID_IUnknown
) ||
1946 IsEqualIID(riid
, &IID_IOleCommandTarget
))
1953 IUnknown_AddRef(iface
);
1957 return E_NOINTERFACE
;
1960 static ULONG WINAPI
IOleCommandTargetImpl_AddRef(IOleCommandTarget
*iface
)
1962 IOleCommandTargetImpl
*This
= (IOleCommandTargetImpl
*)iface
;
1963 return InterlockedIncrement(&This
->ref
);
1966 static ULONG WINAPI
IOleCommandTargetImpl_Release(IOleCommandTarget
*iface
)
1968 IOleCommandTargetImpl
*This
= (IOleCommandTargetImpl
*)iface
;
1969 ULONG ref
= InterlockedDecrement(&This
->ref
);
1973 HeapFree(GetProcessHeap(), 0, This
);
1979 static HRESULT WINAPI
IOleCommandTargetImpl_QueryStatus(
1980 IOleCommandTarget
*iface
, const GUID
*group
, ULONG cCmds
, OLECMD prgCmds
[], OLECMDTEXT
*pCmdText
)
1985 static HRESULT WINAPI
IOleCommandTargetImpl_Exec(
1986 IOleCommandTarget
*iface
,
1987 const GUID
*CmdGroup
,
1993 add_call(&IUnknown_QueryServiceExec_trace
, 3, CmdGroup
, (void*)nCmdID
, (void*)nCmdexecopt
, pvaIn
, pvaOut
);
1997 static const IOleCommandTargetVtbl IOleCommandTargetImpl_Vtbl
=
1999 IOleCommandTargetImpl_QueryInterface
,
2000 IOleCommandTargetImpl_AddRef
,
2001 IOleCommandTargetImpl_Release
,
2002 IOleCommandTargetImpl_QueryStatus
,
2003 IOleCommandTargetImpl_Exec
2007 const IServiceProviderVtbl
*lpVtbl
;
2009 } IServiceProviderImpl
;
2011 static const IServiceProviderVtbl IServiceProviderImpl_Vtbl
;
2013 IServiceProvider
* IServiceProviderImpl_Construct(void)
2015 IServiceProviderImpl
*obj
;
2017 obj
= HeapAlloc(GetProcessHeap(), 0, sizeof(*obj
));
2018 obj
->lpVtbl
= &IServiceProviderImpl_Vtbl
;
2021 return (IServiceProvider
*)obj
;
2024 static HRESULT WINAPI
IServiceProviderImpl_QueryInterface(IServiceProvider
*iface
, REFIID riid
, void **ppvObj
)
2026 IServiceProviderImpl
*This
= (IServiceProviderImpl
*)iface
;
2028 if (IsEqualIID(riid
, &IID_IUnknown
) ||
2029 IsEqualIID(riid
, &IID_IServiceProvider
))
2036 IUnknown_AddRef(iface
);
2037 /* native uses redefined IID_IServiceProvider symbol, so we can't compare pointers */
2038 if (IsEqualIID(riid
, &IID_IServiceProvider
))
2039 add_call(&IUnknown_QueryServiceExec_trace
, 1, iface
, &IID_IServiceProvider
, 0, 0, 0);
2043 return E_NOINTERFACE
;
2046 static ULONG WINAPI
IServiceProviderImpl_AddRef(IServiceProvider
*iface
)
2048 IServiceProviderImpl
*This
= (IServiceProviderImpl
*)iface
;
2049 return InterlockedIncrement(&This
->ref
);
2052 static ULONG WINAPI
IServiceProviderImpl_Release(IServiceProvider
*iface
)
2054 IServiceProviderImpl
*This
= (IServiceProviderImpl
*)iface
;
2055 ULONG ref
= InterlockedDecrement(&This
->ref
);
2059 HeapFree(GetProcessHeap(), 0, This
);
2065 static HRESULT WINAPI
IServiceProviderImpl_QueryService(
2066 IServiceProvider
*iface
, REFGUID service
, REFIID riid
, void **ppv
)
2068 /* natve uses redefined pointer for IID_IOleCommandTarget, not one from uuid.lib */
2069 if (IsEqualIID(riid
, &IID_IOleCommandTarget
))
2070 add_call(&IUnknown_QueryServiceExec_trace
, 2, iface
, service
, &IID_IOleCommandTarget
, 0, 0);
2071 *ppv
= IOleCommandTargetImpl_Construct();
2075 static const IServiceProviderVtbl IServiceProviderImpl_Vtbl
=
2077 IServiceProviderImpl_QueryInterface
,
2078 IServiceProviderImpl_AddRef
,
2079 IServiceProviderImpl_Release
,
2080 IServiceProviderImpl_QueryService
2083 static void test_IUnknown_QueryServiceExec(void)
2085 IServiceProvider
*provider
= IServiceProviderImpl_Construct();
2086 void *test_ptr
= (void*)GetProcAddress(hShlwapi
, "StrChrNW");
2087 static const GUID dummy_serviceid
= { 0xdeadbeef };
2088 static const GUID dummy_groupid
= { 0xbeefbeef };
2089 call_trace_t trace_expected
;
2093 /* on <=W2K platforms same ordinal used for another export with different
2094 prototype, so skipping using this indirect condition */
2097 win_skip("IUnknown_QueryServiceExec is not available\n");
2101 /* null source pointer */
2102 hr
= pIUnknown_QueryServiceExec(NULL
, &dummy_serviceid
, &dummy_groupid
, 0, 0, 0, 0);
2103 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
2106 IUnknown_QueryServiceExec( ptr1, serviceid, groupid, arg1, arg2, arg3, arg4);
2107 -> IUnknown_QueryInterface( ptr1, &IID_IServiceProvider, &prov );
2108 -> IServiceProvider_QueryService( prov, serviceid, &IID_IOleCommandTarget, &obj );
2109 -> IOleCommandTarget_Exec( obj, groupid, arg1, arg2, arg3, arg4 );
2111 init_call_trace(&trace_expected
);
2113 add_call(&trace_expected
, 1, provider
, &IID_IServiceProvider
, 0, 0, 0);
2114 add_call(&trace_expected
, 2, provider
, &dummy_serviceid
, &IID_IOleCommandTarget
, 0, 0);
2115 add_call(&trace_expected
, 3, &dummy_groupid
, (void*)0x1, (void*)0x2, (void*)0x3, (void*)0x4);
2117 init_call_trace(&IUnknown_QueryServiceExec_trace
);
2118 hr
= pIUnknown_QueryServiceExec((IUnknown
*)provider
, &dummy_serviceid
, &dummy_groupid
, 0x1, 0x2, (void*)0x3, (void*)0x4);
2119 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2121 if (trace_expected
.count
== IUnknown_QueryServiceExec_trace
.count
)
2124 for (i
= 0; i
< trace_expected
.count
; i
++)
2126 call_entry_t
*expected
= &trace_expected
.calls
[i
];
2127 call_entry_t
*got
= &IUnknown_QueryServiceExec_trace
.calls
[i
];
2130 ok(expected
->id
== got
->id
, "got different ids %d: %d, %d\n", i
+1, expected
->id
, got
->id
);
2132 for (j
= 0; j
< 5; j
++)
2134 ok(expected
->args
[j
] == got
->args
[j
], "got different args[%d] for %d: %p, %p\n", j
, i
+1,
2135 expected
->args
[j
], got
->args
[j
]);
2140 ok(0, "traces length mismatch expected %d, got %d\n", trace_expected
.count
, IUnknown_QueryServiceExec_trace
.count
);
2142 free_call_trace(&trace_expected
);
2143 free_call_trace(&IUnknown_QueryServiceExec_trace
);
2145 IServiceProvider_Release(provider
);
2148 static void init_pointers(void)
2150 #define MAKEFUNC(f, ord) (p##f = (void*)GetProcAddress(hShlwapi, (LPSTR)(ord)))
2151 MAKEFUNC(SHAllocShared
, 7);
2152 MAKEFUNC(SHLockShared
, 8);
2153 MAKEFUNC(SHUnlockShared
, 9);
2154 MAKEFUNC(SHFreeShared
, 10);
2155 MAKEFUNC(GetAcceptLanguagesA
, 14);
2156 MAKEFUNC(SHSetWindowBits
, 165);
2157 MAKEFUNC(ConnectToConnectionPoint
, 168);
2158 MAKEFUNC(SHSearchMapInt
, 198);
2159 MAKEFUNC(GUIDFromStringA
, 269);
2160 MAKEFUNC(SHPackDispParams
, 282);
2161 MAKEFUNC(IConnectionPoint_InvokeWithCancel
, 283);
2162 MAKEFUNC(IConnectionPoint_SimpleInvoke
, 284);
2163 MAKEFUNC(SHFormatDateTimeA
, 353);
2164 MAKEFUNC(SHFormatDateTimeW
, 354);
2165 MAKEFUNC(SHGetObjectCompatFlags
, 476);
2166 MAKEFUNC(IUnknown_QueryServiceExec
, 484);
2167 MAKEFUNC(SHPropertyBag_ReadLONG
, 496);
2173 hShlwapi
= GetModuleHandleA("shlwapi.dll");
2177 hmlang
= LoadLibraryA("mlang.dll");
2178 pLcidToRfc1766A
= (void *)GetProcAddress(hmlang
, "LcidToRfc1766A");
2180 test_GetAcceptLanguagesA();
2181 test_SHSearchMapInt();
2182 test_alloc_shared();
2184 test_GetShellSecurityDescriptor();
2185 test_SHPackDispParams();
2186 test_IConnectionPoint();
2187 test_SHPropertyBag_ReadLONG();
2188 test_SHSetWindowBits();
2189 test_SHFormatDateTimeA();
2190 test_SHFormatDateTimeW();
2191 test_SHGetObjectCompatFlags();
2192 test_IUnknown_QueryServiceExec();