1 /* Unit test suite for SHLWAPI ordinal functions
3 * Copyright 2004 Jon Griffiths
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "wine/test.h"
37 /* Function ptrs for ordinal calls */
38 static HMODULE hShlwapi
;
39 static BOOL is_win2k_and_lower
;
42 static int (WINAPI
*pSHSearchMapInt
)(const int*,const int*,int,int);
43 static HRESULT (WINAPI
*pGetAcceptLanguagesA
)(LPSTR
,LPDWORD
);
45 static HANDLE (WINAPI
*pSHAllocShared
)(LPCVOID
,DWORD
,DWORD
);
46 static LPVOID (WINAPI
*pSHLockShared
)(HANDLE
,DWORD
);
47 static BOOL (WINAPI
*pSHUnlockShared
)(LPVOID
);
48 static BOOL (WINAPI
*pSHFreeShared
)(HANDLE
,DWORD
);
49 static HRESULT(WINAPIV
*pSHPackDispParams
)(DISPPARAMS
*,VARIANTARG
*,UINT
,...);
50 static HRESULT(WINAPI
*pIConnectionPoint_SimpleInvoke
)(IConnectionPoint
*,DISPID
,DISPPARAMS
*);
51 static HRESULT(WINAPI
*pIConnectionPoint_InvokeWithCancel
)(IConnectionPoint
*,DISPID
,DISPPARAMS
*,DWORD
,DWORD
);
52 static HRESULT(WINAPI
*pConnectToConnectionPoint
)(IUnknown
*,REFIID
,BOOL
,IUnknown
*, LPDWORD
,IConnectionPoint
**);
53 static HRESULT(WINAPI
*pSHPropertyBag_ReadLONG
)(IPropertyBag
*,LPCWSTR
,LPLONG
);
54 static LONG (WINAPI
*pSHSetWindowBits
)(HWND
, INT
, UINT
, UINT
);
55 static INT (WINAPI
*pSHFormatDateTimeA
)(const FILETIME UNALIGNED
*, DWORD
*, LPSTR
, UINT
);
56 static INT (WINAPI
*pSHFormatDateTimeW
)(const FILETIME UNALIGNED
*, DWORD
*, LPWSTR
, UINT
);
57 static DWORD (WINAPI
*pSHGetObjectCompatFlags
)(IUnknown
*, const CLSID
*);
58 static BOOL (WINAPI
*pGUIDFromStringA
)(LPSTR
, CLSID
*);
59 static HRESULT (WINAPI
*pIUnknown_QueryServiceExec
)(IUnknown
*, REFIID
, const GUID
*, DWORD
, DWORD
, VARIANT
*, VARIANT
*);
60 static HRESULT (WINAPI
*pIUnknown_ProfferService
)(IUnknown
*, REFGUID
, IServiceProvider
*, DWORD
*);
61 static HWND (WINAPI
*pSHCreateWorkerWindowA
)(LONG
, HWND
, DWORD
, DWORD
, HMENU
, LONG_PTR
);
62 static HRESULT (WINAPI
*pSHIShellFolder_EnumObjects
)(LPSHELLFOLDER
, HWND
, SHCONTF
, IEnumIDList
**);
63 static DWORD (WINAPI
*pSHGetIniStringW
)(LPCWSTR
, LPCWSTR
, LPWSTR
, DWORD
, LPCWSTR
);
64 static BOOL (WINAPI
*pSHSetIniStringW
)(LPCWSTR
, LPCWSTR
, LPCWSTR
, LPCWSTR
);
65 static HKEY (WINAPI
*pSHGetShellKey
)(DWORD
, LPCWSTR
, BOOL
);
66 static HRESULT (WINAPI
*pSKGetValueW
)(DWORD
, LPCWSTR
, LPCWSTR
, DWORD
*, void*, DWORD
*);
67 static HRESULT (WINAPI
*pSKSetValueW
)(DWORD
, LPCWSTR
, LPCWSTR
, DWORD
, void*, DWORD
);
68 static HRESULT (WINAPI
*pSKDeleteValueW
)(DWORD
, LPCWSTR
, LPCWSTR
);
69 static HRESULT (WINAPI
*pSKAllocValueW
)(DWORD
, LPCWSTR
, LPCWSTR
, DWORD
*, void**, DWORD
*);
71 static HMODULE hmlang
;
72 static HRESULT (WINAPI
*pLcidToRfc1766A
)(LCID
, LPSTR
, INT
);
74 static HMODULE hshell32
;
75 static HRESULT (WINAPI
*pSHGetDesktopFolder
)(IShellFolder
**);
77 static const CHAR ie_international
[] = {
78 'S','o','f','t','w','a','r','e','\\',
79 'M','i','c','r','o','s','o','f','t','\\',
80 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
81 'I','n','t','e','r','n','a','t','i','o','n','a','l',0};
82 static const CHAR acceptlanguage
[] = {
83 'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0};
85 static int strcmp_wa(LPCWSTR strw
, const char *stra
)
88 WideCharToMultiByte(CP_ACP
, 0, strw
, -1, buf
, sizeof(buf
), NULL
, NULL
);
89 return lstrcmpA(stra
, buf
);
103 static void init_call_trace(call_trace_t
*ctrace
)
107 ctrace
->calls
= HeapAlloc(GetProcessHeap(), 0, sizeof(call_entry_t
) * ctrace
->alloc
);
110 static void free_call_trace(const call_trace_t
*ctrace
)
112 HeapFree(GetProcessHeap(), 0, ctrace
->calls
);
115 static void add_call(call_trace_t
*ctrace
, int id
, const void *arg0
,
116 const void *arg1
, const void *arg2
, const void *arg3
, const void *arg4
)
127 if (ctrace
->count
== ctrace
->alloc
)
130 ctrace
->calls
= HeapReAlloc(GetProcessHeap(),0, ctrace
->calls
, ctrace
->alloc
*sizeof(call_entry_t
));
133 ctrace
->calls
[ctrace
->count
++] = call
;
136 static void ok_trace_(call_trace_t
*texpected
, call_trace_t
*tgot
, int line
)
138 if (texpected
->count
== tgot
->count
)
142 for (i
= 0; i
< texpected
->count
; i
++)
144 call_entry_t
*expected
= &texpected
->calls
[i
];
145 call_entry_t
*got
= &tgot
->calls
[i
];
148 ok_(__FILE__
, line
)(expected
->id
== got
->id
, "got different ids %d: %d, %d\n", i
+1, expected
->id
, got
->id
);
150 for (j
= 0; j
< 5; j
++)
152 ok_(__FILE__
, line
)(expected
->args
[j
] == got
->args
[j
], "got different args[%d] for %d: %p, %p\n", j
, i
+1,
153 expected
->args
[j
], got
->args
[j
]);
158 ok_(__FILE__
, line
)(0, "traces length mismatch\n");
161 #define ok_trace(a, b) ok_trace_(a, b, __LINE__)
163 /* trace of actually made calls */
164 static call_trace_t trace_got
;
166 static void test_GetAcceptLanguagesA(void)
168 static LPCSTR table
[] = {"de,en-gb;q=0.7,en;q=0.3",
169 "de,en;q=0.3,en-gb;q=0.7", /* sorting is ignored */
170 "winetest", /* content is ignored */
180 LONG res_query
= ERROR_SUCCESS
;
183 DWORD maxlen
= sizeof(buffer
) - 2;
189 if (!pGetAcceptLanguagesA
) {
190 win_skip("GetAcceptLanguagesA is not available\n");
194 lcid
= GetUserDefaultLCID();
196 /* Get the original Value */
197 lres
= RegOpenKeyA(HKEY_CURRENT_USER
, ie_international
, &hroot
);
199 skip("RegOpenKey(%s) failed: %d\n", ie_international
, lres
);
202 len
= sizeof(original
);
204 res_query
= RegQueryValueExA(hroot
, acceptlanguage
, 0, NULL
, (PBYTE
)original
, &len
);
206 RegDeleteValue(hroot
, acceptlanguage
);
208 /* Some windows versions use "lang-COUNTRY" as default */
209 memset(language
, 0, sizeof(language
));
210 len
= GetLocaleInfoA(lcid
, LOCALE_SISO639LANGNAME
, language
, sizeof(language
));
213 lstrcat(language
, "-");
214 memset(buffer
, 0, sizeof(buffer
));
215 len
= GetLocaleInfoA(lcid
, LOCALE_SISO3166CTRYNAME
, buffer
, sizeof(buffer
) - len
- 1);
216 lstrcat(language
, buffer
);
220 /* LOCALE_SNAME has additional parts in some languages. Try only as last chance */
221 memset(language
, 0, sizeof(language
));
222 len
= GetLocaleInfoA(lcid
, LOCALE_SNAME
, language
, sizeof(language
));
225 /* get the default value */
227 memset(buffer
, '#', maxlen
);
229 hr
= pGetAcceptLanguagesA( buffer
, &len
);
232 win_skip("GetAcceptLanguagesA failed with 0x%x\n", hr
);
233 goto restore_original
;
236 if (lstrcmpA(buffer
, language
)) {
237 /* some windows versions use "lang" or "lang-country" as default */
239 if (pLcidToRfc1766A
) {
240 hr
= pLcidToRfc1766A(lcid
, language
, sizeof(language
));
241 ok(hr
== S_OK
, "LcidToRfc1766A returned 0x%x and %s\n", hr
, language
);
245 ok(!lstrcmpA(buffer
, language
),
246 "have '%s' (searching for '%s')\n", language
, buffer
);
248 if (lstrcmpA(buffer
, language
)) {
249 win_skip("no more ideas, how to build the default language '%s'\n", buffer
);
250 goto restore_original
;
253 trace("detected default: %s\n", language
);
254 while ((entry
= table
[i
])) {
256 exactsize
= lstrlenA(entry
);
258 lres
= RegSetValueExA(hroot
, acceptlanguage
, 0, REG_SZ
, (const BYTE
*) entry
, exactsize
+ 1);
259 ok(!lres
, "got %d for RegSetValueExA: %s\n", lres
, entry
);
261 /* len includes space for the terminating 0 before vista/w2k8 */
263 memset(buffer
, '#', maxlen
);
265 hr
= pGetAcceptLanguagesA( buffer
, &len
);
266 ok(((hr
== E_INVALIDARG
) && (len
== 0)) ||
268 ((len
== exactsize
) || (len
== exactsize
+1)) &&
269 !lstrcmpA(buffer
, entry
)),
270 "+2_#%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
273 memset(buffer
, '#', maxlen
);
275 hr
= pGetAcceptLanguagesA( buffer
, &len
);
276 ok(((hr
== E_INVALIDARG
) && (len
== 0)) ||
278 ((len
== exactsize
) || (len
== exactsize
+1)) &&
279 !lstrcmpA(buffer
, entry
)),
280 "+1_#%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
283 memset(buffer
, '#', maxlen
);
285 hr
= pGetAcceptLanguagesA( buffer
, &len
);
287 /* There is no space for the string in the registry.
288 When the buffer is large enough, the default language is returned
290 When the buffer is too small for that fallback, win7_32 and w2k8_64
291 and above fail with HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), but
292 recent os succeed and return a partial result while
293 older os succeed and overflow the buffer */
295 ok(((hr
== E_INVALIDARG
) && (len
== 0)) ||
296 (((hr
== S_OK
) && !lstrcmpA(buffer
, language
) && (len
== lstrlenA(language
))) ||
297 ((hr
== S_OK
) && !memcmp(buffer
, language
, len
)) ||
298 ((hr
== __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
)) && !len
)),
299 "==_#%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
303 memset(buffer
, '#', maxlen
);
305 hr
= pGetAcceptLanguagesA( buffer
, &len
);
306 ok(((hr
== E_INVALIDARG
) && (len
== 0)) ||
307 (((hr
== S_OK
) && !lstrcmpA(buffer
, language
) && (len
== lstrlenA(language
))) ||
308 ((hr
== S_OK
) && !memcmp(buffer
, language
, len
)) ||
309 ((hr
== __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
)) && !len
)),
310 "-1_#%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
314 memset(buffer
, '#', maxlen
);
316 hr
= pGetAcceptLanguagesA( buffer
, &len
);
317 ok(((hr
== E_INVALIDARG
) && (len
== 0)) ||
318 (((hr
== S_OK
) && !lstrcmpA(buffer
, language
) && (len
== lstrlenA(language
))) ||
319 ((hr
== S_OK
) && !memcmp(buffer
, language
, len
)) ||
320 ((hr
== __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
)) && !len
)),
321 "=1_#%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
324 hr
= pGetAcceptLanguagesA( NULL
, &len
);
326 /* w2k3 and below: E_FAIL and untouched len,
327 since w2k8: S_OK and needed size (excluding 0) */
328 ok( ((hr
== S_OK
) && (len
== exactsize
)) ||
329 ((hr
== E_FAIL
) && (len
== maxlen
)),
330 "NULL,max #%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
335 /* without a value in the registry, a default language is returned */
336 RegDeleteValue(hroot
, acceptlanguage
);
339 memset(buffer
, '#', maxlen
);
341 hr
= pGetAcceptLanguagesA( buffer
, &len
);
342 ok( ((hr
== S_OK
) && (len
== lstrlenA(language
))),
343 "max: got 0x%x with %d and %s (expected S_OK with %d and '%s'\n",
344 hr
, len
, buffer
, lstrlenA(language
), language
);
347 memset(buffer
, '#', maxlen
);
349 hr
= pGetAcceptLanguagesA( buffer
, &len
);
350 ok( (((hr
== S_OK
) || (hr
== E_INVALIDARG
)) && !memcmp(buffer
, language
, len
)) ||
351 ((hr
== __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
)) && !len
),
352 "=2: got 0x%x with %d and %s\n", hr
, len
, buffer
);
355 memset(buffer
, '#', maxlen
);
357 hr
= pGetAcceptLanguagesA( buffer
, &len
);
358 /* When the buffer is too small, win7_32 and w2k8_64 and above fail with
359 HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), other versions suceed
360 and return a partial 0 terminated result while other versions
361 fail with E_INVALIDARG and return a partial unterminated result */
362 ok( (((hr
== S_OK
) || (hr
== E_INVALIDARG
)) && !memcmp(buffer
, language
, len
)) ||
363 ((hr
== __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
)) && !len
),
364 "=1: got 0x%x with %d and %s\n", hr
, len
, buffer
);
367 memset(buffer
, '#', maxlen
);
369 hr
= pGetAcceptLanguagesA( buffer
, &len
);
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
);
374 memset(buffer
, '#', maxlen
);
376 hr
= pGetAcceptLanguagesA( buffer
, NULL
);
377 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
378 ok((hr
== E_FAIL
) || (hr
== E_INVALIDARG
),
379 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr
);
382 hr
= pGetAcceptLanguagesA( NULL
, NULL
);
383 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
384 ok((hr
== E_FAIL
) || (hr
== E_INVALIDARG
),
385 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr
);
389 len
= lstrlenA(original
);
390 lres
= RegSetValueExA(hroot
, acceptlanguage
, 0, REG_SZ
, (const BYTE
*) original
, len
? len
+ 1: 0);
391 ok(!lres
, "RegSetValueEx(%s) failed: %d\n", original
, lres
);
395 RegDeleteValue(hroot
, acceptlanguage
);
400 static void test_SHSearchMapInt(void)
402 int keys
[8], values
[8];
405 if (!pSHSearchMapInt
)
408 memset(keys
, 0, sizeof(keys
));
409 memset(values
, 0, sizeof(values
));
410 keys
[0] = 99; values
[0] = 101;
412 /* NULL key/value lists crash native, so skip testing them */
415 i
= pSHSearchMapInt(keys
, values
, 1, keys
[0]);
416 ok(i
== values
[0], "Len 1, expected %d, got %d\n", values
[0], i
);
418 /* Key doesn't exist */
419 i
= pSHSearchMapInt(keys
, values
, 1, 100);
420 ok(i
== -1, "Len 1 - bad key, expected -1, got %d\n", i
);
422 /* Len = 0 => not found */
423 i
= pSHSearchMapInt(keys
, values
, 0, keys
[0]);
424 ok(i
== -1, "Len 1 - passed len 0, expected -1, got %d\n", i
);
426 /* 2 elements, len = 1 */
427 keys
[1] = 98; values
[1] = 102;
428 i
= pSHSearchMapInt(keys
, values
, 1, keys
[1]);
429 ok(i
== -1, "Len 1 - array len 2, expected -1, got %d\n", i
);
431 /* 2 elements, len = 2 */
432 i
= pSHSearchMapInt(keys
, values
, 2, keys
[1]);
433 ok(i
== values
[1], "Len 2, expected %d, got %d\n", values
[1], i
);
435 /* Searches forward */
436 keys
[2] = 99; values
[2] = 103;
437 i
= pSHSearchMapInt(keys
, values
, 3, keys
[0]);
438 ok(i
== values
[0], "Len 3, expected %d, got %d\n", values
[0], i
);
441 static void test_alloc_shared(void)
449 procid
=GetCurrentProcessId();
450 hmem
=pSHAllocShared(NULL
,10,procid
);
451 ok(hmem
!=NULL
,"SHAllocShared(NULL...) failed: %u\n", GetLastError());
452 ret
= pSHFreeShared(hmem
, procid
);
453 ok( ret
, "SHFreeShared failed: %u\n", GetLastError());
456 hmem
=pSHAllocShared(&val
,4,procid
);
457 ok(hmem
!=NULL
,"SHAllocShared(NULL...) failed: %u\n", GetLastError());
459 p
=pSHLockShared(hmem
,procid
);
460 ok(p
!=NULL
,"SHLockShared failed: %u\n", GetLastError());
462 ok(*p
==val
,"Wrong value in shared memory: %d instead of %d\n",*p
,val
);
463 ret
= pSHUnlockShared(p
);
464 ok( ret
, "SHUnlockShared failed: %u\n", GetLastError());
466 ret
= pSHFreeShared(hmem
, procid
);
467 ok( ret
, "SHFreeShared failed: %u\n", GetLastError());
470 static void test_fdsa(void)
474 DWORD num_items
; /* Number of elements inserted */
475 void *mem
; /* Ptr to array */
476 DWORD blocks_alloced
; /* Number of elements allocated */
477 BYTE inc
; /* Number of elements to grow by when we need to expand */
478 BYTE block_size
; /* Size in bytes of an element */
479 BYTE flags
; /* Flags */
482 BOOL (WINAPI
*pFDSA_Initialize
)(DWORD block_size
, DWORD inc
, FDSA_info
*info
, void *mem
,
484 BOOL (WINAPI
*pFDSA_Destroy
)(FDSA_info
*info
);
485 DWORD (WINAPI
*pFDSA_InsertItem
)(FDSA_info
*info
, DWORD where
, const void *block
);
486 BOOL (WINAPI
*pFDSA_DeleteItem
)(FDSA_info
*info
, DWORD where
);
489 int block_size
= 10, init_blocks
= 4, inc
= 2;
493 pFDSA_Initialize
= (void *)GetProcAddress(hShlwapi
, (LPSTR
)208);
494 pFDSA_Destroy
= (void *)GetProcAddress(hShlwapi
, (LPSTR
)209);
495 pFDSA_InsertItem
= (void *)GetProcAddress(hShlwapi
, (LPSTR
)210);
496 pFDSA_DeleteItem
= (void *)GetProcAddress(hShlwapi
, (LPSTR
)211);
498 mem
= HeapAlloc(GetProcessHeap(), 0, block_size
* init_blocks
);
499 memset(&info
, 0, sizeof(info
));
501 ok(pFDSA_Initialize(block_size
, inc
, &info
, mem
, init_blocks
), "FDSA_Initialize rets FALSE\n");
502 ok(info
.num_items
== 0, "num_items = %d\n", info
.num_items
);
503 ok(info
.mem
== mem
, "mem = %p\n", info
.mem
);
504 ok(info
.blocks_alloced
== init_blocks
, "blocks_alloced = %d\n", info
.blocks_alloced
);
505 ok(info
.inc
== inc
, "inc = %d\n", info
.inc
);
506 ok(info
.block_size
== block_size
, "block_size = %d\n", info
.block_size
);
507 ok(info
.flags
== 0, "flags = %d\n", info
.flags
);
509 ret
= pFDSA_InsertItem(&info
, 1234, "1234567890");
510 ok(ret
== 0, "ret = %d\n", ret
);
511 ok(info
.num_items
== 1, "num_items = %d\n", info
.num_items
);
512 ok(info
.mem
== mem
, "mem = %p\n", info
.mem
);
513 ok(info
.blocks_alloced
== init_blocks
, "blocks_alloced = %d\n", info
.blocks_alloced
);
514 ok(info
.inc
== inc
, "inc = %d\n", info
.inc
);
515 ok(info
.block_size
== block_size
, "block_size = %d\n", info
.block_size
);
516 ok(info
.flags
== 0, "flags = %d\n", info
.flags
);
518 ret
= pFDSA_InsertItem(&info
, 1234, "abcdefghij");
519 ok(ret
== 1, "ret = %d\n", ret
);
521 ret
= pFDSA_InsertItem(&info
, 1, "klmnopqrst");
522 ok(ret
== 1, "ret = %d\n", ret
);
524 ret
= pFDSA_InsertItem(&info
, 0, "uvwxyzABCD");
525 ok(ret
== 0, "ret = %d\n", ret
);
526 ok(info
.mem
== mem
, "mem = %p\n", info
.mem
);
527 ok(info
.flags
== 0, "flags = %d\n", info
.flags
);
529 /* This next InsertItem will cause shlwapi to allocate its own mem buffer */
530 ret
= pFDSA_InsertItem(&info
, 0, "EFGHIJKLMN");
531 ok(ret
== 0, "ret = %d\n", ret
);
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
, "EFGHIJKLMNuvwxyzABCD1234567890klmnopqrstabcdefghij", 50), "mem %s\n", (char*)info
.mem
);
538 ok(pFDSA_DeleteItem(&info
, 2), "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
, "EFGHIJKLMNuvwxyzABCDklmnopqrstabcdefghij", 40), "mem %s\n", (char*)info
.mem
);
545 ok(pFDSA_DeleteItem(&info
, 3), "rets FALSE\n");
546 ok(info
.mem
!= mem
, "mem = %p\n", info
.mem
);
547 ok(info
.blocks_alloced
== init_blocks
+ inc
, "blocks_alloced = %d\n", info
.blocks_alloced
);
548 ok(info
.flags
== 0x1, "flags = %d\n", info
.flags
);
550 ok(!memcmp(info
.mem
, "EFGHIJKLMNuvwxyzABCDklmnopqrst", 30), "mem %s\n", (char*)info
.mem
);
552 ok(!pFDSA_DeleteItem(&info
, 4), "does not ret FALSE\n");
554 /* As shlwapi has allocated memory internally, Destroy will ret FALSE */
555 ok(!pFDSA_Destroy(&info
), "FDSA_Destroy does not ret FALSE\n");
558 /* When Initialize is called with inc = 0, set it to 1 */
559 ok(pFDSA_Initialize(block_size
, 0, &info
, mem
, init_blocks
), "FDSA_Initialize rets FALSE\n");
560 ok(info
.inc
== 1, "inc = %d\n", info
.inc
);
562 /* This time, because shlwapi hasn't had to allocate memory
563 internally, Destroy rets non-zero */
564 ok(pFDSA_Destroy(&info
), "FDSA_Destroy rets FALSE\n");
567 HeapFree(GetProcessHeap(), 0, mem
);
571 typedef struct SHELL_USER_SID
{
572 SID_IDENTIFIER_AUTHORITY sidAuthority
;
575 } SHELL_USER_SID
, *PSHELL_USER_SID
;
576 typedef struct SHELL_USER_PERMISSION
{
577 SHELL_USER_SID susID
;
582 DWORD dwInheritAccessMask
;
583 } SHELL_USER_PERMISSION
, *PSHELL_USER_PERMISSION
;
584 static void test_GetShellSecurityDescriptor(void)
586 SHELL_USER_PERMISSION supCurrentUserFull
= {
587 { {SECURITY_NULL_SID_AUTHORITY
}, 0, 0 },
588 ACCESS_ALLOWED_ACE_TYPE
, FALSE
,
590 #define MY_INHERITANCE 0xBE /* invalid value to proof behavior */
591 SHELL_USER_PERMISSION supEveryoneDenied
= {
592 { {SECURITY_WORLD_SID_AUTHORITY
}, SECURITY_WORLD_RID
, 0 },
593 ACCESS_DENIED_ACE_TYPE
, TRUE
,
594 GENERIC_WRITE
, MY_INHERITANCE
| 0xDEADBA00, GENERIC_READ
};
595 PSHELL_USER_PERMISSION rgsup
[2] = {
596 &supCurrentUserFull
, &supEveryoneDenied
,
598 SECURITY_DESCRIPTOR
* psd
;
599 SECURITY_DESCRIPTOR
* (WINAPI
*pGetShellSecurityDescriptor
)(PSHELL_USER_PERMISSION
*,int);
600 void *pChrCmpIW
= GetProcAddress(hShlwapi
, "ChrCmpIW");
602 pGetShellSecurityDescriptor
=(void*)GetProcAddress(hShlwapi
,(char*)475);
604 if(!pGetShellSecurityDescriptor
)
606 win_skip("GetShellSecurityDescriptor not available\n");
610 if(pChrCmpIW
&& pChrCmpIW
== pGetShellSecurityDescriptor
) /* win2k */
612 win_skip("Skipping for GetShellSecurityDescriptor, same ordinal used for ChrCmpIW\n");
616 psd
= pGetShellSecurityDescriptor(NULL
, 2);
618 broken(psd
==INVALID_HANDLE_VALUE
), /* IE5 */
619 "GetShellSecurityDescriptor should fail\n");
620 psd
= pGetShellSecurityDescriptor(rgsup
, 0);
621 ok(psd
==NULL
, "GetShellSecurityDescriptor should fail, got %p\n", psd
);
623 SetLastError(0xdeadbeef);
624 psd
= pGetShellSecurityDescriptor(rgsup
, 2);
625 if (psd
== NULL
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
627 /* The previous calls to GetShellSecurityDescriptor don't set the last error */
628 win_skip("GetShellSecurityDescriptor is not implemented\n");
631 if (psd
== INVALID_HANDLE_VALUE
)
633 win_skip("GetShellSecurityDescriptor is broken on IE5\n");
636 ok(psd
!=NULL
, "GetShellSecurityDescriptor failed\n");
639 BOOL bHasDacl
= FALSE
, bDefaulted
, ret
;
642 SECURITY_DESCRIPTOR_CONTROL control
;
644 ok(IsValidSecurityDescriptor(psd
), "returned value is not valid SD\n");
646 ret
= GetSecurityDescriptorControl(psd
, &control
, &dwRev
);
647 ok(ret
, "GetSecurityDescriptorControl failed with error %u\n", GetLastError());
648 ok(0 == (control
& SE_SELF_RELATIVE
), "SD should be absolute\n");
650 ret
= GetSecurityDescriptorDacl(psd
, &bHasDacl
, &pAcl
, &bDefaulted
);
651 ok(ret
, "GetSecurityDescriptorDacl failed with error %u\n", GetLastError());
653 ok(bHasDacl
, "SD has no DACL\n");
656 ok(!bDefaulted
, "DACL should not be defaulted\n");
658 ok(pAcl
!= NULL
, "NULL DACL!\n");
661 ACL_SIZE_INFORMATION asiSize
;
663 ok(IsValidAcl(pAcl
), "DACL is not valid\n");
665 ret
= GetAclInformation(pAcl
, &asiSize
, sizeof(asiSize
), AclSizeInformation
);
666 ok(ret
, "GetAclInformation failed with error %u\n", GetLastError());
668 ok(asiSize
.AceCount
== 3, "Incorrect number of ACEs: %d entries\n", asiSize
.AceCount
);
669 if (asiSize
.AceCount
== 3)
671 ACCESS_ALLOWED_ACE
*paaa
; /* will use for DENIED too */
673 ret
= GetAce(pAcl
, 0, (LPVOID
*)&paaa
);
674 ok(ret
, "GetAce failed with error %u\n", GetLastError());
675 ok(paaa
->Header
.AceType
== ACCESS_ALLOWED_ACE_TYPE
,
676 "Invalid ACE type %d\n", paaa
->Header
.AceType
);
677 ok(paaa
->Header
.AceFlags
== 0, "Invalid ACE flags %x\n", paaa
->Header
.AceFlags
);
678 ok(paaa
->Mask
== GENERIC_ALL
, "Invalid ACE mask %x\n", paaa
->Mask
);
680 ret
= GetAce(pAcl
, 1, (LPVOID
*)&paaa
);
681 ok(ret
, "GetAce failed with error %u\n", GetLastError());
682 ok(paaa
->Header
.AceType
== ACCESS_DENIED_ACE_TYPE
,
683 "Invalid ACE type %d\n", paaa
->Header
.AceType
);
684 /* first one of two ACEs generated from inheritable entry - without inheritance */
685 ok(paaa
->Header
.AceFlags
== 0, "Invalid ACE flags %x\n", paaa
->Header
.AceFlags
);
686 ok(paaa
->Mask
== GENERIC_WRITE
, "Invalid ACE mask %x\n", paaa
->Mask
);
688 ret
= GetAce(pAcl
, 2, (LPVOID
*)&paaa
);
689 ok(ret
, "GetAce failed with error %u\n", GetLastError());
690 ok(paaa
->Header
.AceType
== ACCESS_DENIED_ACE_TYPE
,
691 "Invalid ACE type %d\n", paaa
->Header
.AceType
);
692 /* second ACE - with inheritance */
693 ok(paaa
->Header
.AceFlags
== MY_INHERITANCE
,
694 "Invalid ACE flags %x\n", paaa
->Header
.AceFlags
);
695 ok(paaa
->Mask
== GENERIC_READ
, "Invalid ACE mask %x\n", paaa
->Mask
);
704 static void test_SHPackDispParams(void)
710 if(!pSHPackDispParams
)
711 win_skip("SHPackSidpParams not available\n");
713 memset(¶ms
, 0xc0, sizeof(params
));
714 memset(vars
, 0xc0, sizeof(vars
));
715 hres
= pSHPackDispParams(¶ms
, vars
, 1, VT_I4
, 0xdeadbeef);
716 ok(hres
== S_OK
, "SHPackDispParams failed: %08x\n", hres
);
717 ok(params
.cArgs
== 1, "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
== vars
, "params.rgvarg = %p\n", params
.rgvarg
);
721 ok(V_VT(vars
) == VT_I4
, "V_VT(var) = %d\n", V_VT(vars
));
722 ok(V_I4(vars
) == 0xdeadbeef, "failed %x\n", V_I4(vars
));
724 memset(¶ms
, 0xc0, sizeof(params
));
725 hres
= pSHPackDispParams(¶ms
, NULL
, 0, 0);
726 ok(hres
== S_OK
, "SHPackDispParams failed: %08x\n", hres
);
727 ok(params
.cArgs
== 0, "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
== NULL
, "params.rgvarg = %p\n", params
.rgvarg
);
732 memset(vars
, 0xc0, sizeof(vars
));
733 memset(¶ms
, 0xc0, sizeof(params
));
734 hres
= pSHPackDispParams(¶ms
, vars
, 4, VT_BSTR
, (void*)0xdeadbeef, VT_EMPTY
, 10,
735 VT_I4
, 100, VT_DISPATCH
, (void*)0xdeadbeef);
736 ok(hres
== S_OK
, "SHPackDispParams failed: %08x\n", hres
);
737 ok(params
.cArgs
== 4, "params.cArgs = %d\n", params
.cArgs
);
738 ok(params
.cNamedArgs
== 0, "params.cNamedArgs = %d\n", params
.cArgs
);
739 ok(params
.rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", params
.rgdispidNamedArgs
);
740 ok(params
.rgvarg
== vars
, "params.rgvarg = %p\n", params
.rgvarg
);
741 ok(V_VT(vars
) == VT_DISPATCH
, "V_VT(vars[0]) = %x\n", V_VT(vars
));
742 ok(V_I4(vars
) == 0xdeadbeef, "V_I4(vars[0]) = %x\n", V_I4(vars
));
743 ok(V_VT(vars
+1) == VT_I4
, "V_VT(vars[1]) = %d\n", V_VT(vars
+1));
744 ok(V_I4(vars
+1) == 100, "V_I4(vars[1]) = %x\n", V_I4(vars
+1));
745 ok(V_VT(vars
+2) == VT_I4
, "V_VT(vars[2]) = %d\n", V_VT(vars
+2));
746 ok(V_I4(vars
+2) == 10, "V_I4(vars[2]) = %x\n", V_I4(vars
+2));
747 ok(V_VT(vars
+3) == VT_BSTR
, "V_VT(vars[3]) = %d\n", V_VT(vars
+3));
748 ok(V_BSTR(vars
+3) == (void*)0xdeadbeef, "V_BSTR(vars[3]) = %p\n", V_BSTR(vars
+3));
753 IDispatch IDispatch_iface
;
757 static inline Disp
*impl_from_IDispatch(IDispatch
*iface
)
759 return CONTAINING_RECORD(iface
, Disp
, IDispatch_iface
);
762 typedef struct _contain
764 IConnectionPointContainer IConnectionPointContainer_iface
;
768 IConnectionPoint
**pt
;
771 static inline Contain
*impl_from_IConnectionPointContainer(IConnectionPointContainer
*iface
)
773 return CONTAINING_RECORD(iface
, Contain
, IConnectionPointContainer_iface
);
776 typedef struct _cntptn
778 IConnectionPoint IConnectionPoint_iface
;
787 static inline ConPt
*impl_from_IConnectionPoint(IConnectionPoint
*iface
)
789 return CONTAINING_RECORD(iface
, ConPt
, IConnectionPoint_iface
);
794 IEnumConnections IEnumConnections_iface
;
801 static inline EnumCon
*impl_from_IEnumConnections(IEnumConnections
*iface
)
803 return CONTAINING_RECORD(iface
, EnumCon
, IEnumConnections_iface
);
806 typedef struct _enumpt
808 IEnumConnectionPoints IEnumConnectionPoints_iface
;
815 static inline EnumPt
*impl_from_IEnumConnectionPoints(IEnumConnectionPoints
*iface
)
817 return CONTAINING_RECORD(iface
, EnumPt
, IEnumConnectionPoints_iface
);
821 static HRESULT WINAPI
Disp_QueryInterface(
828 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDispatch
))
835 IUnknown_AddRef(This
);
839 trace("no interface\n");
840 return E_NOINTERFACE
;
843 static ULONG WINAPI
Disp_AddRef(IDispatch
* This
)
845 Disp
*iface
= impl_from_IDispatch(This
);
846 return InterlockedIncrement(&iface
->refCount
);
849 static ULONG WINAPI
Disp_Release(IDispatch
* This
)
851 Disp
*iface
= impl_from_IDispatch(This
);
854 ret
= InterlockedDecrement(&iface
->refCount
);
856 HeapFree(GetProcessHeap(),0,This
);
860 static HRESULT WINAPI
Disp_GetTypeInfoCount(
864 return ERROR_SUCCESS
;
867 static HRESULT WINAPI
Disp_GetTypeInfo(
873 return ERROR_SUCCESS
;
876 static HRESULT WINAPI
Disp_GetIDsOfNames(
884 return ERROR_SUCCESS
;
887 static HRESULT WINAPI
Disp_Invoke(
893 DISPPARAMS
*pDispParams
,
895 EXCEPINFO
*pExcepInfo
,
898 trace("%p %x %p %x %x %p %p %p %p\n",This
,dispIdMember
,riid
,lcid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,puArgErr
);
900 ok(dispIdMember
== 0xa0 || dispIdMember
== 0xa1, "Unknown dispIdMember\n");
901 ok(pDispParams
!= NULL
, "Invoked with NULL pDispParams\n");
902 ok(wFlags
== DISPATCH_METHOD
, "Wrong flags %x\n",wFlags
);
903 ok(lcid
== 0,"Wrong lcid %x\n",lcid
);
904 if (dispIdMember
== 0xa0)
906 ok(pDispParams
->cArgs
== 0, "params.cArgs = %d\n", pDispParams
->cArgs
);
907 ok(pDispParams
->cNamedArgs
== 0, "params.cNamedArgs = %d\n", pDispParams
->cArgs
);
908 ok(pDispParams
->rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", pDispParams
->rgdispidNamedArgs
);
909 ok(pDispParams
->rgvarg
== NULL
, "params.rgvarg = %p\n", pDispParams
->rgvarg
);
911 else if (dispIdMember
== 0xa1)
913 ok(pDispParams
->cArgs
== 2, "params.cArgs = %d\n", pDispParams
->cArgs
);
914 ok(pDispParams
->cNamedArgs
== 0, "params.cNamedArgs = %d\n", pDispParams
->cArgs
);
915 ok(pDispParams
->rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", pDispParams
->rgdispidNamedArgs
);
916 ok(V_VT(pDispParams
->rgvarg
) == VT_BSTR
, "V_VT(var) = %d\n", V_VT(pDispParams
->rgvarg
));
917 ok(V_I4(pDispParams
->rgvarg
) == 0xdeadcafe , "failed %p\n", V_BSTR(pDispParams
->rgvarg
));
918 ok(V_VT(pDispParams
->rgvarg
+1) == VT_I4
, "V_VT(var) = %d\n", V_VT(pDispParams
->rgvarg
+1));
919 ok(V_I4(pDispParams
->rgvarg
+1) == 0xdeadbeef, "failed %x\n", V_I4(pDispParams
->rgvarg
+1));
922 return ERROR_SUCCESS
;
925 static const IDispatchVtbl disp_vtbl
= {
930 Disp_GetTypeInfoCount
,
936 static HRESULT WINAPI
Enum_QueryInterface(
937 IEnumConnections
* This
,
943 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IEnumConnections
))
950 IUnknown_AddRef(This
);
954 trace("no interface\n");
955 return E_NOINTERFACE
;
958 static ULONG WINAPI
Enum_AddRef(IEnumConnections
* This
)
960 EnumCon
*iface
= impl_from_IEnumConnections(This
);
961 return InterlockedIncrement(&iface
->refCount
);
964 static ULONG WINAPI
Enum_Release(IEnumConnections
* This
)
966 EnumCon
*iface
= impl_from_IEnumConnections(This
);
969 ret
= InterlockedDecrement(&iface
->refCount
);
971 HeapFree(GetProcessHeap(),0,This
);
975 static HRESULT WINAPI
Enum_Next(
976 IEnumConnections
* This
,
981 EnumCon
*iface
= impl_from_IEnumConnections(This
);
983 if (cConnections
> 0 && iface
->idx
< iface
->pt
->sinkCount
)
985 rgcd
->pUnk
= iface
->pt
->sink
[iface
->idx
];
986 IUnknown_AddRef(iface
->pt
->sink
[iface
->idx
]);
997 static HRESULT WINAPI
Enum_Skip(
998 IEnumConnections
* This
,
1004 static HRESULT WINAPI
Enum_Reset(
1005 IEnumConnections
* This
)
1010 static HRESULT WINAPI
Enum_Clone(
1011 IEnumConnections
* This
,
1012 IEnumConnections
**ppEnum
)
1017 static const IEnumConnectionsVtbl enum_vtbl
= {
1019 Enum_QueryInterface
,
1028 static HRESULT WINAPI
ConPt_QueryInterface(
1029 IConnectionPoint
* This
,
1035 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IConnectionPoint
))
1042 IUnknown_AddRef(This
);
1046 trace("no interface\n");
1047 return E_NOINTERFACE
;
1050 static ULONG WINAPI
ConPt_AddRef(
1051 IConnectionPoint
* This
)
1053 ConPt
*iface
= impl_from_IConnectionPoint(This
);
1054 return InterlockedIncrement(&iface
->refCount
);
1057 static ULONG WINAPI
ConPt_Release(
1058 IConnectionPoint
* This
)
1060 ConPt
*iface
= impl_from_IConnectionPoint(This
);
1063 ret
= InterlockedDecrement(&iface
->refCount
);
1066 if (iface
->sinkCount
> 0)
1069 for (i
= 0; i
< iface
->sinkCount
; i
++)
1072 IUnknown_Release(iface
->sink
[i
]);
1074 HeapFree(GetProcessHeap(),0,iface
->sink
);
1076 HeapFree(GetProcessHeap(),0,This
);
1081 static HRESULT WINAPI
ConPt_GetConnectionInterface(
1082 IConnectionPoint
* This
,
1086 ConPt
*iface
= impl_from_IConnectionPoint(This
);
1093 memcpy(pIID
,&iface
->id
,sizeof(GUID
));
1097 static HRESULT WINAPI
ConPt_GetConnectionPointContainer(
1098 IConnectionPoint
* This
,
1099 IConnectionPointContainer
**ppCPC
)
1101 ConPt
*iface
= impl_from_IConnectionPoint(This
);
1103 *ppCPC
= &iface
->container
->IConnectionPointContainer_iface
;
1107 static HRESULT WINAPI
ConPt_Advise(
1108 IConnectionPoint
* This
,
1112 ConPt
*iface
= impl_from_IConnectionPoint(This
);
1114 if (iface
->sinkCount
== 0)
1115 iface
->sink
= HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown
*));
1117 iface
->sink
= HeapReAlloc(GetProcessHeap(),0,iface
->sink
,sizeof(IUnknown
*)*(iface
->sinkCount
+1));
1118 iface
->sink
[iface
->sinkCount
] = pUnkSink
;
1119 IUnknown_AddRef(pUnkSink
);
1121 *pdwCookie
= iface
->sinkCount
;
1125 static HRESULT WINAPI
ConPt_Unadvise(
1126 IConnectionPoint
* This
,
1129 ConPt
*iface
= impl_from_IConnectionPoint(This
);
1131 if (dwCookie
> iface
->sinkCount
)
1135 IUnknown_Release(iface
->sink
[dwCookie
-1]);
1136 iface
->sink
[dwCookie
-1] = NULL
;
1141 static HRESULT WINAPI
ConPt_EnumConnections(
1142 IConnectionPoint
* This
,
1143 IEnumConnections
**ppEnum
)
1147 ec
= HeapAlloc(GetProcessHeap(),0,sizeof(EnumCon
));
1148 ec
->IEnumConnections_iface
.lpVtbl
= &enum_vtbl
;
1150 ec
->pt
= impl_from_IConnectionPoint(This
);
1152 *ppEnum
= &ec
->IEnumConnections_iface
;
1157 static const IConnectionPointVtbl point_vtbl
= {
1158 ConPt_QueryInterface
,
1162 ConPt_GetConnectionInterface
,
1163 ConPt_GetConnectionPointContainer
,
1166 ConPt_EnumConnections
1169 static HRESULT WINAPI
EnumPt_QueryInterface(
1170 IEnumConnectionPoints
* This
,
1176 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IEnumConnectionPoints
))
1183 IUnknown_AddRef(This
);
1187 trace("no interface\n");
1188 return E_NOINTERFACE
;
1191 static ULONG WINAPI
EnumPt_AddRef(IEnumConnectionPoints
* This
)
1193 EnumPt
*iface
= impl_from_IEnumConnectionPoints(This
);
1194 return InterlockedIncrement(&iface
->refCount
);
1197 static ULONG WINAPI
EnumPt_Release(IEnumConnectionPoints
* This
)
1199 EnumPt
*iface
= impl_from_IEnumConnectionPoints(This
);
1202 ret
= InterlockedDecrement(&iface
->refCount
);
1204 HeapFree(GetProcessHeap(),0,This
);
1208 static HRESULT WINAPI
EnumPt_Next(
1209 IEnumConnectionPoints
* This
,
1211 IConnectionPoint
**rgcd
,
1214 EnumPt
*iface
= impl_from_IEnumConnectionPoints(This
);
1216 if (cConnections
> 0 && iface
->idx
< iface
->container
->ptCount
)
1218 *rgcd
= iface
->container
->pt
[iface
->idx
];
1219 IUnknown_AddRef(iface
->container
->pt
[iface
->idx
]);
1229 static HRESULT WINAPI
EnumPt_Skip(
1230 IEnumConnectionPoints
* This
,
1236 static HRESULT WINAPI
EnumPt_Reset(
1237 IEnumConnectionPoints
* This
)
1242 static HRESULT WINAPI
EnumPt_Clone(
1243 IEnumConnectionPoints
* This
,
1244 IEnumConnectionPoints
**ppEnumPt
)
1249 static const IEnumConnectionPointsVtbl enumpt_vtbl
= {
1251 EnumPt_QueryInterface
,
1260 static HRESULT WINAPI
Contain_QueryInterface(
1261 IConnectionPointContainer
* This
,
1267 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IConnectionPointContainer
))
1274 IUnknown_AddRef(This
);
1278 trace("no interface\n");
1279 return E_NOINTERFACE
;
1282 static ULONG WINAPI
Contain_AddRef(
1283 IConnectionPointContainer
* This
)
1285 Contain
*iface
= impl_from_IConnectionPointContainer(This
);
1286 return InterlockedIncrement(&iface
->refCount
);
1289 static ULONG WINAPI
Contain_Release(
1290 IConnectionPointContainer
* This
)
1292 Contain
*iface
= impl_from_IConnectionPointContainer(This
);
1295 ret
= InterlockedDecrement(&iface
->refCount
);
1298 if (iface
->ptCount
> 0)
1301 for (i
= 0; i
< iface
->ptCount
; i
++)
1302 IUnknown_Release(iface
->pt
[i
]);
1303 HeapFree(GetProcessHeap(),0,iface
->pt
);
1305 HeapFree(GetProcessHeap(),0,This
);
1310 static HRESULT WINAPI
Contain_EnumConnectionPoints(
1311 IConnectionPointContainer
* This
,
1312 IEnumConnectionPoints
**ppEnum
)
1316 ec
= HeapAlloc(GetProcessHeap(),0,sizeof(EnumPt
));
1317 ec
->IEnumConnectionPoints_iface
.lpVtbl
= &enumpt_vtbl
;
1320 ec
->container
= impl_from_IConnectionPointContainer(This
);
1321 *ppEnum
= &ec
->IEnumConnectionPoints_iface
;
1326 static HRESULT WINAPI
Contain_FindConnectionPoint(
1327 IConnectionPointContainer
* This
,
1329 IConnectionPoint
**ppCP
)
1331 Contain
*iface
= impl_from_IConnectionPointContainer(This
);
1334 if (!IsEqualIID(riid
, &IID_NULL
) || iface
->ptCount
==0)
1336 pt
= HeapAlloc(GetProcessHeap(),0,sizeof(ConPt
));
1337 pt
->IConnectionPoint_iface
.lpVtbl
= &point_vtbl
;
1341 pt
->container
= iface
;
1342 pt
->id
= IID_IDispatch
;
1344 if (iface
->ptCount
== 0)
1345 iface
->pt
=HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown
*));
1347 iface
->pt
= HeapReAlloc(GetProcessHeap(),0,iface
->pt
,sizeof(IUnknown
*)*(iface
->ptCount
+1));
1348 iface
->pt
[iface
->ptCount
] = &pt
->IConnectionPoint_iface
;
1351 *ppCP
= &pt
->IConnectionPoint_iface
;
1355 *ppCP
= iface
->pt
[0];
1356 IUnknown_AddRef((IUnknown
*)*ppCP
);
1362 static const IConnectionPointContainerVtbl contain_vtbl
= {
1363 Contain_QueryInterface
,
1367 Contain_EnumConnectionPoints
,
1368 Contain_FindConnectionPoint
1371 static void test_IConnectionPoint(void)
1375 IConnectionPoint
*point
;
1378 DWORD cookie
= 0xffffffff;
1382 if (!pIConnectionPoint_SimpleInvoke
|| !pConnectToConnectionPoint
)
1384 win_skip("IConnectionPoint Apis not present\n");
1388 container
= HeapAlloc(GetProcessHeap(),0,sizeof(Contain
));
1389 container
->IConnectionPointContainer_iface
.lpVtbl
= &contain_vtbl
;
1390 container
->refCount
= 1;
1391 container
->ptCount
= 0;
1392 container
->pt
= NULL
;
1394 dispatch
= HeapAlloc(GetProcessHeap(),0,sizeof(Disp
));
1395 dispatch
->IDispatch_iface
.lpVtbl
= &disp_vtbl
;
1396 dispatch
->refCount
= 1;
1398 rc
= pConnectToConnectionPoint((IUnknown
*)dispatch
, &IID_NULL
, TRUE
, (IUnknown
*)container
, &cookie
, &point
);
1399 ok(rc
== S_OK
, "pConnectToConnectionPoint failed with %x\n",rc
);
1400 ok(point
!= NULL
, "returned ConnectionPoint is NULL\n");
1401 ok(cookie
!= 0xffffffff, "invalid cookie returned\n");
1403 rc
= pIConnectionPoint_SimpleInvoke(point
,0xa0,NULL
);
1404 ok(rc
== S_OK
, "pConnectToConnectionPoint failed with %x\n",rc
);
1406 if (pSHPackDispParams
)
1408 memset(¶ms
, 0xc0, sizeof(params
));
1409 memset(vars
, 0xc0, sizeof(vars
));
1410 rc
= pSHPackDispParams(¶ms
, vars
, 2, VT_I4
, 0xdeadbeef, VT_BSTR
, 0xdeadcafe);
1411 ok(rc
== S_OK
, "SHPackDispParams failed: %08x\n", rc
);
1413 rc
= pIConnectionPoint_SimpleInvoke(point
,0xa1,¶ms
);
1414 ok(rc
== S_OK
, "pConnectToConnectionPoint failed with %x\n",rc
);
1417 win_skip("pSHPackDispParams not present\n");
1419 rc
= pConnectToConnectionPoint(NULL
, &IID_NULL
, FALSE
, (IUnknown
*)container
, &cookie
, NULL
);
1420 ok(rc
== S_OK
, "pConnectToConnectionPoint failed with %x\n",rc
);
1422 /* MSDN says this should be required but it crashs on XP
1423 IUnknown_Release(point);
1425 ref
= IUnknown_Release((IUnknown
*)container
);
1426 ok(ref
== 0, "leftover IConnectionPointContainer reference %i\n",ref
);
1427 ref
= IUnknown_Release((IUnknown
*)dispatch
);
1428 ok(ref
== 0, "leftover IDispatch reference %i\n",ref
);
1431 typedef struct _propbag
1433 IPropertyBag IPropertyBag_iface
;
1438 static inline PropBag
*impl_from_IPropertyBag(IPropertyBag
*iface
)
1440 return CONTAINING_RECORD(iface
, PropBag
, IPropertyBag_iface
);
1444 static HRESULT WINAPI
Prop_QueryInterface(
1451 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IPropertyBag
))
1458 IUnknown_AddRef(This
);
1462 trace("no interface\n");
1463 return E_NOINTERFACE
;
1466 static ULONG WINAPI
Prop_AddRef(
1469 PropBag
*iface
= impl_from_IPropertyBag(This
);
1470 return InterlockedIncrement(&iface
->refCount
);
1473 static ULONG WINAPI
Prop_Release(
1476 PropBag
*iface
= impl_from_IPropertyBag(This
);
1479 ret
= InterlockedDecrement(&iface
->refCount
);
1481 HeapFree(GetProcessHeap(),0,This
);
1485 static HRESULT WINAPI
Prop_Read(
1487 LPCOLESTR pszPropName
,
1489 IErrorLog
*pErrorLog
)
1491 V_VT(pVar
) = VT_BLOB
|VT_BYREF
;
1492 V_BYREF(pVar
) = (LPVOID
)0xdeadcafe;
1496 static HRESULT WINAPI
Prop_Write(
1498 LPCOLESTR pszPropName
,
1505 static const IPropertyBagVtbl prop_vtbl
= {
1506 Prop_QueryInterface
,
1514 static void test_SHPropertyBag_ReadLONG(void)
1519 static const WCHAR szName1
[] = {'n','a','m','e','1',0};
1521 if (!pSHPropertyBag_ReadLONG
)
1523 win_skip("SHPropertyBag_ReadLONG not present\n");
1527 pb
= HeapAlloc(GetProcessHeap(),0,sizeof(PropBag
));
1529 pb
->IPropertyBag_iface
.lpVtbl
= &prop_vtbl
;
1532 rc
= pSHPropertyBag_ReadLONG(NULL
, szName1
, &out
);
1533 ok(rc
== E_INVALIDARG
|| broken(rc
== 0), "incorrect return %x\n",rc
);
1534 ok(out
== 0xfeedface, "value should not have changed\n");
1535 rc
= pSHPropertyBag_ReadLONG(&pb
->IPropertyBag_iface
, NULL
, &out
);
1536 ok(rc
== E_INVALIDARG
|| broken(rc
== 0) || broken(rc
== 1), "incorrect return %x\n",rc
);
1537 ok(out
== 0xfeedface, "value should not have changed\n");
1538 rc
= pSHPropertyBag_ReadLONG(&pb
->IPropertyBag_iface
, szName1
, NULL
);
1539 ok(rc
== E_INVALIDARG
|| broken(rc
== 0) || broken(rc
== 1), "incorrect return %x\n",rc
);
1540 ok(out
== 0xfeedface, "value should not have changed\n");
1541 rc
= pSHPropertyBag_ReadLONG(&pb
->IPropertyBag_iface
, szName1
, &out
);
1542 ok(rc
== DISP_E_BADVARTYPE
|| broken(rc
== 0) || broken(rc
== 1), "incorrect return %x\n",rc
);
1543 ok(out
== 0xfeedface || broken(out
== 0xfeedfa00), "value should not have changed %x\n",out
);
1544 IUnknown_Release((IUnknown
*)pb
);
1549 static void test_SHSetWindowBits(void)
1552 DWORD style
, styleold
;
1555 if(!pSHSetWindowBits
)
1557 win_skip("SHSetWindowBits is not available\n");
1562 clsA
.lpfnWndProc
= DefWindowProcA
;
1563 clsA
.cbClsExtra
= 0;
1564 clsA
.cbWndExtra
= 0;
1565 clsA
.hInstance
= GetModuleHandleA(NULL
);
1567 clsA
.hCursor
= LoadCursorA(0, IDC_ARROW
);
1568 clsA
.hbrBackground
= NULL
;
1569 clsA
.lpszMenuName
= NULL
;
1570 clsA
.lpszClassName
= "Shlwapi test class";
1571 RegisterClassA(&clsA
);
1573 hwnd
= CreateWindowA("Shlwapi test class", "Test", WS_VISIBLE
, 0, 0, 100, 100,
1574 NULL
, NULL
, GetModuleHandle(NULL
), 0);
1575 ok(IsWindow(hwnd
), "failed to create window\n");
1578 SetLastError(0xdeadbeef);
1579 style
= pSHSetWindowBits(NULL
, GWL_STYLE
, 0, 0);
1580 ok(style
== 0, "expected 0 retval, got %d\n", style
);
1581 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
||
1582 broken(GetLastError() == 0xdeadbeef), /* Win9x/WinMe */
1583 "expected ERROR_INVALID_WINDOW_HANDLE, got %d\n", GetLastError());
1585 /* zero mask, zero flags */
1586 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1587 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, 0, 0);
1588 ok(styleold
== style
, "expected old style\n");
1589 ok(styleold
== GetWindowLongA(hwnd
, GWL_STYLE
), "expected to keep old style\n");
1592 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1593 ok(styleold
& WS_VISIBLE
, "expected WS_VISIBLE\n");
1594 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, WS_VISIBLE
, 0);
1596 ok(style
== styleold
, "expected previous style, got %x\n", style
);
1597 ok((GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
) == 0, "expected updated style\n");
1599 /* test mask, unset style bit used */
1600 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1601 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, WS_VISIBLE
, 0);
1602 ok(style
== styleold
, "expected previous style, got %x\n", style
);
1603 ok(styleold
== GetWindowLongA(hwnd
, GWL_STYLE
), "expected to keep old style\n");
1605 /* set back with flags */
1606 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1607 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, WS_VISIBLE
, WS_VISIBLE
);
1608 ok(style
== styleold
, "expected previous style, got %x\n", style
);
1609 ok(GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
, "expected updated style\n");
1611 /* reset and try to set without a mask */
1612 pSHSetWindowBits(hwnd
, GWL_STYLE
, WS_VISIBLE
, 0);
1613 ok((GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
) == 0, "expected updated style\n");
1614 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1615 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, 0, WS_VISIBLE
);
1616 ok(style
== styleold
, "expected previous style, got %x\n", style
);
1617 ok((GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
) == 0, "expected updated style\n");
1619 DestroyWindow(hwnd
);
1621 UnregisterClassA("Shlwapi test class", GetModuleHandleA(NULL
));
1624 static void test_SHFormatDateTimeA(void)
1626 FILETIME UNALIGNED filetime
;
1627 CHAR buff
[100], buff2
[100], buff3
[100];
1632 if(!pSHFormatDateTimeA
)
1634 win_skip("pSHFormatDateTimeA isn't available\n");
1640 /* crashes on native */
1641 pSHFormatDateTimeA(NULL
, NULL
, NULL
, 0);
1645 SystemTimeToFileTime(&st
, &filetime
);
1646 /* SHFormatDateTime expects input as utc */
1647 LocalFileTimeToFileTime(&filetime
, &filetime
);
1649 /* no way to get required buffer length here */
1650 SetLastError(0xdeadbeef);
1651 ret
= pSHFormatDateTimeA(&filetime
, NULL
, NULL
, 0);
1652 ok(ret
== 0, "got %d\n", ret
);
1653 ok(GetLastError() == 0xdeadbeef || broken(GetLastError() == ERROR_SUCCESS
/* Win7 */),
1654 "expected 0xdeadbeef, got %d\n", GetLastError());
1656 SetLastError(0xdeadbeef);
1657 buff
[0] = 'a'; buff
[1] = 0;
1658 ret
= pSHFormatDateTimeA(&filetime
, NULL
, buff
, 0);
1659 ok(ret
== 0, "got %d\n", ret
);
1660 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1661 ok(buff
[0] == 'a', "expected same string, got %s\n", buff
);
1663 /* flags needs to have FDTF_NOAUTOREADINGORDER for these tests to succeed on Vista+ */
1665 /* all combinations documented as invalid succeeded */
1666 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTTIME
| FDTF_LONGTIME
;
1667 SetLastError(0xdeadbeef);
1668 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1669 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1670 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1672 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTDATE
| FDTF_LONGDATE
;
1673 SetLastError(0xdeadbeef);
1674 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1675 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1676 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1678 flags
= FDTF_SHORTDATE
| FDTF_LTRDATE
| FDTF_RTLDATE
;
1679 SetLastError(0xdeadbeef);
1680 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1681 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1682 ok(GetLastError() == 0xdeadbeef ||
1683 broken(GetLastError() == ERROR_INVALID_FLAGS
), /* Win9x/WinMe */
1684 "expected 0xdeadbeef, got %d\n", GetLastError());
1686 /* now check returned strings */
1687 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTTIME
;
1688 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1689 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1690 ret
= GetTimeFormat(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff2
, sizeof(buff2
));
1691 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1692 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1694 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGTIME
;
1695 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1696 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1697 ret
= GetTimeFormat(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff2
, sizeof(buff2
));
1698 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1699 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1701 /* both time flags */
1702 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGTIME
| FDTF_SHORTTIME
;
1703 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1704 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1705 ret
= GetTimeFormat(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff2
, sizeof(buff2
));
1706 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1707 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1709 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTDATE
;
1710 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1711 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1712 ret
= GetDateFormat(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1713 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1714 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1716 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGDATE
;
1717 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1718 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1719 ret
= GetDateFormat(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1720 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1721 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1723 /* both date flags */
1724 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGDATE
| FDTF_SHORTDATE
;
1725 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1726 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1727 ret
= GetDateFormat(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1728 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1729 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1731 /* various combinations of date/time flags */
1732 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGDATE
| FDTF_SHORTTIME
;
1733 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1734 ok(ret
== lstrlenA(buff
)+1, "got %d, length %d\n", ret
, lstrlenA(buff
)+1);
1735 ret
= GetTimeFormat(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff3
, sizeof(buff3
));
1736 ok(ret
== lstrlenA(buff3
)+1, "got %d\n", ret
);
1737 ok(lstrcmpA(buff3
, buff
+ lstrlenA(buff
) - lstrlenA(buff3
)) == 0,
1738 "expected (%s), got (%s) for time part\n",
1739 buff3
, buff
+ lstrlenA(buff
) - lstrlenA(buff3
));
1740 ret
= GetDateFormat(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1741 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1742 buff
[lstrlenA(buff2
)] = '\0';
1743 ok(lstrcmpA(buff2
, buff
) == 0, "expected (%s) got (%s) for date part\n",
1746 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGDATE
| FDTF_LONGTIME
;
1747 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1748 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1749 ret
= GetTimeFormat(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff3
, sizeof(buff3
));
1750 ok(ret
== lstrlenA(buff3
)+1, "got %d\n", ret
);
1751 ok(lstrcmpA(buff3
, buff
+ lstrlenA(buff
) - lstrlenA(buff3
)) == 0,
1752 "expected (%s), got (%s) for time part\n",
1753 buff3
, buff
+ lstrlenA(buff
) - lstrlenA(buff3
));
1754 ret
= GetDateFormat(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1755 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1756 buff
[lstrlenA(buff2
)] = '\0';
1757 ok(lstrcmpA(buff2
, buff
) == 0, "expected (%s) got (%s) for date part\n",
1760 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTDATE
| FDTF_SHORTTIME
;
1761 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1762 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1763 ret
= GetDateFormat(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1764 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1766 ret
= GetTimeFormat(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff3
, sizeof(buff3
));
1767 ok(ret
== lstrlenA(buff3
)+1, "got %d\n", ret
);
1768 strcat(buff2
, buff3
);
1769 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1771 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTDATE
| FDTF_LONGTIME
;
1772 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1773 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1774 ret
= GetDateFormat(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1775 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1777 ret
= GetTimeFormat(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff3
, sizeof(buff3
));
1778 ok(ret
== lstrlenA(buff3
)+1, "got %d\n", ret
);
1779 strcat(buff2
, buff3
);
1780 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1783 static void test_SHFormatDateTimeW(void)
1785 FILETIME UNALIGNED filetime
;
1786 WCHAR buff
[100], buff2
[100], buff3
[100], *p1
, *p2
;
1790 static const WCHAR spaceW
[] = {' ',0};
1791 #define UNICODE_LTR_MARK 0x200e
1793 if(!pSHFormatDateTimeW
)
1795 win_skip("pSHFormatDateTimeW isn't available\n");
1801 /* crashes on native */
1802 pSHFormatDateTimeW(NULL
, NULL
, NULL
, 0);
1806 SystemTimeToFileTime(&st
, &filetime
);
1807 /* SHFormatDateTime expects input as utc */
1808 LocalFileTimeToFileTime(&filetime
, &filetime
);
1810 /* no way to get required buffer length here */
1811 SetLastError(0xdeadbeef);
1812 ret
= pSHFormatDateTimeW(&filetime
, NULL
, NULL
, 0);
1813 ok(ret
== 0, "expected 0, got %d\n", ret
);
1814 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1816 SetLastError(0xdeadbeef);
1817 buff
[0] = 'a'; buff
[1] = 0;
1818 ret
= pSHFormatDateTimeW(&filetime
, NULL
, buff
, 0);
1819 ok(ret
== 0, "expected 0, got %d\n", ret
);
1820 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1821 ok(buff
[0] == 'a', "expected same string\n");
1823 /* all combinations documented as invalid succeeded */
1824 flags
= FDTF_SHORTTIME
| FDTF_LONGTIME
;
1825 SetLastError(0xdeadbeef);
1826 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1827 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1828 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1829 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1831 flags
= FDTF_SHORTDATE
| FDTF_LONGDATE
;
1832 SetLastError(0xdeadbeef);
1833 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1834 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1835 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1836 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1838 flags
= FDTF_SHORTDATE
| FDTF_LTRDATE
| FDTF_RTLDATE
;
1839 SetLastError(0xdeadbeef);
1840 buff
[0] = 0; /* NT4 doesn't clear the buffer on failure */
1841 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1842 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1843 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1844 ok(GetLastError() == 0xdeadbeef ||
1845 broken(GetLastError() == ERROR_INVALID_FLAGS
), /* Win9x/WinMe/NT4 */
1846 "expected 0xdeadbeef, got %d\n", GetLastError());
1848 /* now check returned strings */
1849 flags
= FDTF_SHORTTIME
;
1850 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1851 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1852 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1853 SetLastError(0xdeadbeef);
1854 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1855 if (ret
== 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
1857 win_skip("Needed W-functions are not implemented\n");
1860 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1861 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1863 flags
= FDTF_LONGTIME
;
1864 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1865 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1866 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1867 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1868 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1869 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1871 /* both time flags */
1872 flags
= FDTF_LONGTIME
| FDTF_SHORTTIME
;
1873 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1874 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1875 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1876 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1877 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1878 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal string\n");
1880 flags
= FDTF_SHORTDATE
;
1881 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1882 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1883 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1884 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1885 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1886 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1888 flags
= FDTF_LONGDATE
;
1889 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1890 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1891 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1892 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1893 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1894 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1896 /* both date flags */
1897 flags
= FDTF_LONGDATE
| FDTF_SHORTDATE
;
1898 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1899 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1900 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1901 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1902 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1903 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1905 /* various combinations of date/time flags */
1906 flags
= FDTF_LONGDATE
| FDTF_SHORTTIME
;
1907 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1908 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1909 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1910 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff3
, sizeof(buff3
)/sizeof(WCHAR
));
1911 ok(ret
== lstrlenW(buff3
)+1, "expected %d, got %d\n", lstrlenW(buff3
)+1, ret
);
1912 ok(lstrcmpW(buff3
, buff
+ lstrlenW(buff
) - lstrlenW(buff3
)) == 0,
1913 "expected (%s), got (%s) for time part\n",
1914 wine_dbgstr_w(buff3
), wine_dbgstr_w(buff
+ lstrlenW(buff
) - lstrlenW(buff3
)));
1915 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1916 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1921 while (*p1
== UNICODE_LTR_MARK
)
1923 while (*p2
== UNICODE_LTR_MARK
)
1929 ok(lstrcmpW(buff2
, buff
) == 0, "expected (%s) got (%s) for date part\n",
1930 wine_dbgstr_w(buff2
), wine_dbgstr_w(buff
));
1932 flags
= FDTF_LONGDATE
| FDTF_LONGTIME
;
1933 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1934 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1935 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1936 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff3
, sizeof(buff3
)/sizeof(WCHAR
));
1937 ok(ret
== lstrlenW(buff3
)+1, "expected %d, got %d\n", lstrlenW(buff3
)+1, ret
);
1938 ok(lstrcmpW(buff3
, buff
+ lstrlenW(buff
) - lstrlenW(buff3
)) == 0,
1939 "expected (%s), got (%s) for time part\n",
1940 wine_dbgstr_w(buff3
), wine_dbgstr_w(buff
+ lstrlenW(buff
) - lstrlenW(buff3
)));
1941 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1942 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1947 while (*p1
== UNICODE_LTR_MARK
)
1949 while (*p2
== UNICODE_LTR_MARK
)
1955 ok(lstrcmpW(buff2
, buff
) == 0, "expected (%s) got (%s) for date part\n",
1956 wine_dbgstr_w(buff2
), wine_dbgstr_w(buff
));
1958 flags
= FDTF_SHORTDATE
| FDTF_SHORTTIME
;
1959 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1960 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1961 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1962 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1963 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1964 lstrcatW(buff2
, spaceW
);
1965 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff3
, sizeof(buff3
)/sizeof(WCHAR
));
1966 ok(ret
== lstrlenW(buff3
)+1, "expected %d, got %d\n", lstrlenW(buff3
)+1, ret
);
1967 lstrcatW(buff2
, buff3
);
1968 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1970 flags
= FDTF_SHORTDATE
| FDTF_LONGTIME
;
1971 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1972 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1973 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1974 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1975 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1976 lstrcatW(buff2
, spaceW
);
1977 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff3
, sizeof(buff3
)/sizeof(WCHAR
));
1978 ok(ret
== lstrlenW(buff3
)+1, "expected %d, got %d\n", lstrlenW(buff3
)+1, ret
);
1979 lstrcatW(buff2
, buff3
);
1980 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1983 static void test_SHGetObjectCompatFlags(void)
1985 struct compat_value
{
1990 struct compat_value values
[] = {
1991 { "OTNEEDSSFCACHE", 0x1 },
1992 { "NO_WEBVIEW", 0x2 },
1993 { "UNBINDABLE", 0x4 },
1995 { "NEEDSFILESYSANCESTOR", 0x10 },
1996 { "NOTAFILESYSTEM", 0x20 },
1997 { "CTXMENU_NOVERBS", 0x40 },
1998 { "CTXMENU_LIMITEDQI", 0x80 },
1999 { "COCREATESHELLFOLDERONLY", 0x100 },
2000 { "NEEDSSTORAGEANCESTOR", 0x200 },
2001 { "NOLEGACYWEBVIEW", 0x400 },
2002 { "CTXMENU_XPQCMFLAGS", 0x1000 },
2003 { "NOIPROPERTYSTORE", 0x2000 }
2006 static const char compat_path
[] = "Software\\Microsoft\\Windows\\CurrentVersion\\ShellCompatibility\\Objects";
2007 void *pColorAdjustLuma
= GetProcAddress(hShlwapi
, "ColorAdjustLuma");
2008 CHAR keyA
[39]; /* {CLSID} */
2013 if (!pSHGetObjectCompatFlags
)
2015 win_skip("SHGetObjectCompatFlags isn't available\n");
2019 if (pColorAdjustLuma
&& pColorAdjustLuma
== pSHGetObjectCompatFlags
) /* win2k */
2021 win_skip("Skipping SHGetObjectCompatFlags, same ordinal used for ColorAdjustLuma\n");
2026 ret
= pSHGetObjectCompatFlags(NULL
, NULL
);
2027 ok(ret
== 0, "got %d\n", ret
);
2029 ret
= RegOpenKeyA(HKEY_LOCAL_MACHINE
, compat_path
, &root
);
2030 if (ret
!= ERROR_SUCCESS
)
2032 skip("No compatibility class data found\n");
2036 for (i
= 0; RegEnumKeyA(root
, i
, keyA
, sizeof(keyA
)) == ERROR_SUCCESS
; i
++)
2040 if (RegOpenKeyA(root
, keyA
, &clsid_key
) == ERROR_SUCCESS
)
2043 DWORD expected
= 0, got
, length
= sizeof(valueA
);
2047 for (v
= 0; RegEnumValueA(clsid_key
, v
, valueA
, &length
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
; v
++)
2051 for (j
= 0; j
< sizeof(values
)/sizeof(struct compat_value
); j
++)
2052 if (lstrcmpA(values
[j
].nameA
, valueA
) == 0)
2054 expected
|= values
[j
].value
;
2058 length
= sizeof(valueA
);
2061 pGUIDFromStringA(keyA
, &clsid
);
2062 got
= pSHGetObjectCompatFlags(NULL
, &clsid
);
2063 ok(got
== expected
, "got 0x%08x, expected 0x%08x. Key %s\n", got
, expected
, keyA
);
2065 RegCloseKey(clsid_key
);
2073 IOleCommandTarget IOleCommandTarget_iface
;
2075 } IOleCommandTargetImpl
;
2077 static inline IOleCommandTargetImpl
*impl_from_IOleCommandTarget(IOleCommandTarget
*iface
)
2079 return CONTAINING_RECORD(iface
, IOleCommandTargetImpl
, IOleCommandTarget_iface
);
2082 static const IOleCommandTargetVtbl IOleCommandTargetImpl_Vtbl
;
2084 static IOleCommandTarget
* IOleCommandTargetImpl_Construct(void)
2086 IOleCommandTargetImpl
*obj
;
2088 obj
= HeapAlloc(GetProcessHeap(), 0, sizeof(*obj
));
2089 obj
->IOleCommandTarget_iface
.lpVtbl
= &IOleCommandTargetImpl_Vtbl
;
2092 return &obj
->IOleCommandTarget_iface
;
2095 static HRESULT WINAPI
IOleCommandTargetImpl_QueryInterface(IOleCommandTarget
*iface
, REFIID riid
, void **ppvObj
)
2097 IOleCommandTargetImpl
*This
= impl_from_IOleCommandTarget(iface
);
2099 if (IsEqualIID(riid
, &IID_IUnknown
) ||
2100 IsEqualIID(riid
, &IID_IOleCommandTarget
))
2107 IUnknown_AddRef(iface
);
2111 return E_NOINTERFACE
;
2114 static ULONG WINAPI
IOleCommandTargetImpl_AddRef(IOleCommandTarget
*iface
)
2116 IOleCommandTargetImpl
*This
= impl_from_IOleCommandTarget(iface
);
2117 return InterlockedIncrement(&This
->ref
);
2120 static ULONG WINAPI
IOleCommandTargetImpl_Release(IOleCommandTarget
*iface
)
2122 IOleCommandTargetImpl
*This
= impl_from_IOleCommandTarget(iface
);
2123 ULONG ref
= InterlockedDecrement(&This
->ref
);
2127 HeapFree(GetProcessHeap(), 0, This
);
2133 static HRESULT WINAPI
IOleCommandTargetImpl_QueryStatus(
2134 IOleCommandTarget
*iface
, const GUID
*group
, ULONG cCmds
, OLECMD prgCmds
[], OLECMDTEXT
*pCmdText
)
2139 static HRESULT WINAPI
IOleCommandTargetImpl_Exec(
2140 IOleCommandTarget
*iface
,
2141 const GUID
*CmdGroup
,
2147 add_call(&trace_got
, 3, CmdGroup
, (void*)(DWORD_PTR
)nCmdID
, (void*)(DWORD_PTR
)nCmdexecopt
, pvaIn
, pvaOut
);
2151 static const IOleCommandTargetVtbl IOleCommandTargetImpl_Vtbl
=
2153 IOleCommandTargetImpl_QueryInterface
,
2154 IOleCommandTargetImpl_AddRef
,
2155 IOleCommandTargetImpl_Release
,
2156 IOleCommandTargetImpl_QueryStatus
,
2157 IOleCommandTargetImpl_Exec
2161 IServiceProvider IServiceProvider_iface
;
2163 } IServiceProviderImpl
;
2165 static inline IServiceProviderImpl
*impl_from_IServiceProvider(IServiceProvider
*iface
)
2167 return CONTAINING_RECORD(iface
, IServiceProviderImpl
, IServiceProvider_iface
);
2171 IProfferService IProfferService_iface
;
2173 } IProfferServiceImpl
;
2175 static inline IProfferServiceImpl
*impl_from_IProfferService(IProfferService
*iface
)
2177 return CONTAINING_RECORD(iface
, IProfferServiceImpl
, IProfferService_iface
);
2181 static const IServiceProviderVtbl IServiceProviderImpl_Vtbl
;
2182 static const IProfferServiceVtbl IProfferServiceImpl_Vtbl
;
2184 static IServiceProvider
* IServiceProviderImpl_Construct(void)
2186 IServiceProviderImpl
*obj
;
2188 obj
= HeapAlloc(GetProcessHeap(), 0, sizeof(*obj
));
2189 obj
->IServiceProvider_iface
.lpVtbl
= &IServiceProviderImpl_Vtbl
;
2192 return &obj
->IServiceProvider_iface
;
2195 static IProfferService
* IProfferServiceImpl_Construct(void)
2197 IProfferServiceImpl
*obj
;
2199 obj
= HeapAlloc(GetProcessHeap(), 0, sizeof(*obj
));
2200 obj
->IProfferService_iface
.lpVtbl
= &IProfferServiceImpl_Vtbl
;
2203 return &obj
->IProfferService_iface
;
2206 static HRESULT WINAPI
IServiceProviderImpl_QueryInterface(IServiceProvider
*iface
, REFIID riid
, void **ppvObj
)
2208 IServiceProviderImpl
*This
= impl_from_IServiceProvider(iface
);
2210 if (IsEqualIID(riid
, &IID_IUnknown
) ||
2211 IsEqualIID(riid
, &IID_IServiceProvider
))
2218 IUnknown_AddRef(iface
);
2219 /* native uses redefined IID_IServiceProvider symbol, so we can't compare pointers */
2220 if (IsEqualIID(riid
, &IID_IServiceProvider
))
2221 add_call(&trace_got
, 1, iface
, &IID_IServiceProvider
, 0, 0, 0);
2225 return E_NOINTERFACE
;
2228 static ULONG WINAPI
IServiceProviderImpl_AddRef(IServiceProvider
*iface
)
2230 IServiceProviderImpl
*This
= impl_from_IServiceProvider(iface
);
2231 return InterlockedIncrement(&This
->ref
);
2234 static ULONG WINAPI
IServiceProviderImpl_Release(IServiceProvider
*iface
)
2236 IServiceProviderImpl
*This
= impl_from_IServiceProvider(iface
);
2237 ULONG ref
= InterlockedDecrement(&This
->ref
);
2241 HeapFree(GetProcessHeap(), 0, This
);
2247 static HRESULT WINAPI
IServiceProviderImpl_QueryService(
2248 IServiceProvider
*iface
, REFGUID service
, REFIID riid
, void **ppv
)
2250 /* native uses redefined pointer for IID_IOleCommandTarget, not one from uuid.lib */
2251 if (IsEqualIID(riid
, &IID_IOleCommandTarget
))
2253 add_call(&trace_got
, 2, iface
, service
, &IID_IOleCommandTarget
, 0, 0);
2254 *ppv
= IOleCommandTargetImpl_Construct();
2256 if (IsEqualIID(riid
, &IID_IProfferService
))
2258 if (IsEqualIID(service
, &IID_IProfferService
))
2259 add_call(&trace_got
, 2, &IID_IProfferService
, &IID_IProfferService
, 0, 0, 0);
2260 *ppv
= IProfferServiceImpl_Construct();
2265 static const IServiceProviderVtbl IServiceProviderImpl_Vtbl
=
2267 IServiceProviderImpl_QueryInterface
,
2268 IServiceProviderImpl_AddRef
,
2269 IServiceProviderImpl_Release
,
2270 IServiceProviderImpl_QueryService
2273 static void test_IUnknown_QueryServiceExec(void)
2275 IServiceProvider
*provider
= IServiceProviderImpl_Construct();
2276 static const GUID dummy_serviceid
= { 0xdeadbeef };
2277 static const GUID dummy_groupid
= { 0xbeefbeef };
2278 call_trace_t trace_expected
;
2281 /* on <=W2K platforms same ordinal used for another export with different
2282 prototype, so skipping using this indirect condition */
2283 if (is_win2k_and_lower
)
2285 win_skip("IUnknown_QueryServiceExec is not available\n");
2289 /* null source pointer */
2290 hr
= pIUnknown_QueryServiceExec(NULL
, &dummy_serviceid
, &dummy_groupid
, 0, 0, 0, 0);
2291 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
2294 IUnknown_QueryServiceExec( ptr1, serviceid, groupid, arg1, arg2, arg3, arg4);
2295 -> IUnknown_QueryInterface( ptr1, &IID_IServiceProvider, &prov );
2296 -> IServiceProvider_QueryService( prov, serviceid, &IID_IOleCommandTarget, &obj );
2297 -> IOleCommandTarget_Exec( obj, groupid, arg1, arg2, arg3, arg4 );
2299 init_call_trace(&trace_expected
);
2301 add_call(&trace_expected
, 1, provider
, &IID_IServiceProvider
, 0, 0, 0);
2302 add_call(&trace_expected
, 2, provider
, &dummy_serviceid
, &IID_IOleCommandTarget
, 0, 0);
2303 add_call(&trace_expected
, 3, &dummy_groupid
, (void*)0x1, (void*)0x2, (void*)0x3, (void*)0x4);
2305 init_call_trace(&trace_got
);
2306 hr
= pIUnknown_QueryServiceExec((IUnknown
*)provider
, &dummy_serviceid
, &dummy_groupid
, 0x1, 0x2, (void*)0x3, (void*)0x4);
2307 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2309 ok_trace(&trace_expected
, &trace_got
);
2311 free_call_trace(&trace_expected
);
2312 free_call_trace(&trace_got
);
2314 IServiceProvider_Release(provider
);
2318 static HRESULT WINAPI
IProfferServiceImpl_QueryInterface(IProfferService
*iface
, REFIID riid
, void **ppvObj
)
2320 IProfferServiceImpl
*This
= impl_from_IProfferService(iface
);
2322 if (IsEqualIID(riid
, &IID_IUnknown
) ||
2323 IsEqualIID(riid
, &IID_IProfferService
))
2327 else if (IsEqualIID(riid
, &IID_IServiceProvider
))
2329 *ppvObj
= IServiceProviderImpl_Construct();
2330 add_call(&trace_got
, 1, iface
, &IID_IServiceProvider
, 0, 0, 0);
2336 IUnknown_AddRef(iface
);
2340 return E_NOINTERFACE
;
2343 static ULONG WINAPI
IProfferServiceImpl_AddRef(IProfferService
*iface
)
2345 IProfferServiceImpl
*This
= impl_from_IProfferService(iface
);
2346 return InterlockedIncrement(&This
->ref
);
2349 static ULONG WINAPI
IProfferServiceImpl_Release(IProfferService
*iface
)
2351 IProfferServiceImpl
*This
= impl_from_IProfferService(iface
);
2352 ULONG ref
= InterlockedDecrement(&This
->ref
);
2356 HeapFree(GetProcessHeap(), 0, This
);
2362 static HRESULT WINAPI
IProfferServiceImpl_ProfferService(IProfferService
*iface
,
2363 REFGUID service
, IServiceProvider
*pService
, DWORD
*pCookie
)
2365 *pCookie
= 0xdeadbeef;
2366 add_call(&trace_got
, 3, service
, pService
, pCookie
, 0, 0);
2370 static HRESULT WINAPI
IProfferServiceImpl_RevokeService(IProfferService
*iface
, DWORD cookie
)
2372 add_call(&trace_got
, 4, (void*)(DWORD_PTR
)cookie
, 0, 0, 0, 0);
2376 static const IProfferServiceVtbl IProfferServiceImpl_Vtbl
=
2378 IProfferServiceImpl_QueryInterface
,
2379 IProfferServiceImpl_AddRef
,
2380 IProfferServiceImpl_Release
,
2381 IProfferServiceImpl_ProfferService
,
2382 IProfferServiceImpl_RevokeService
2385 static void test_IUnknown_ProfferService(void)
2387 IServiceProvider
*provider
= IServiceProviderImpl_Construct();
2388 IProfferService
*proff
= IProfferServiceImpl_Construct();
2389 static const GUID dummy_serviceid
= { 0xdeadbeef };
2390 call_trace_t trace_expected
;
2394 /* on <=W2K platforms same ordinal used for another export with different
2395 prototype, so skipping using this indirect condition */
2396 if (is_win2k_and_lower
)
2398 win_skip("IUnknown_ProfferService is not available\n");
2402 /* null source pointer */
2403 hr
= pIUnknown_ProfferService(NULL
, &dummy_serviceid
, 0, 0);
2404 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
2407 IUnknown_ProfferService( ptr1, serviceid, arg1, arg2);
2408 -> IUnknown_QueryInterface( ptr1, &IID_IServiceProvider, &provider );
2409 -> IServiceProvider_QueryService( provider, &IID_IProfferService, &IID_IProfferService, &proffer );
2411 if (service pointer not null):
2412 -> IProfferService_ProfferService( proffer, serviceid, arg1, arg2 );
2414 -> IProfferService_RevokeService( proffer, *arg2 );
2416 init_call_trace(&trace_expected
);
2418 add_call(&trace_expected
, 1, proff
, &IID_IServiceProvider
, 0, 0, 0);
2419 add_call(&trace_expected
, 2, &IID_IProfferService
, &IID_IProfferService
, 0, 0, 0);
2420 add_call(&trace_expected
, 3, &dummy_serviceid
, provider
, &cookie
, 0, 0);
2422 init_call_trace(&trace_got
);
2424 hr
= pIUnknown_ProfferService((IUnknown
*)proff
, &dummy_serviceid
, provider
, &cookie
);
2425 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2426 ok(cookie
== 0xdeadbeef, "got %x\n", cookie
);
2428 ok_trace(&trace_expected
, &trace_got
);
2429 free_call_trace(&trace_got
);
2430 free_call_trace(&trace_expected
);
2432 /* same with ::Revoke path */
2433 init_call_trace(&trace_expected
);
2435 add_call(&trace_expected
, 1, proff
, &IID_IServiceProvider
, 0, 0, 0);
2436 add_call(&trace_expected
, 2, &IID_IProfferService
, &IID_IProfferService
, 0, 0, 0);
2437 add_call(&trace_expected
, 4, (void*)(DWORD_PTR
)cookie
, 0, 0, 0, 0);
2439 init_call_trace(&trace_got
);
2440 ok(cookie
!= 0, "got %x\n", cookie
);
2441 hr
= pIUnknown_ProfferService((IUnknown
*)proff
, &dummy_serviceid
, 0, &cookie
);
2442 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2443 ok(cookie
== 0, "got %x\n", cookie
);
2444 ok_trace(&trace_expected
, &trace_got
);
2445 free_call_trace(&trace_got
);
2446 free_call_trace(&trace_expected
);
2448 IServiceProvider_Release(provider
);
2449 IProfferService_Release(proff
);
2452 static void test_SHCreateWorkerWindowA(void)
2460 if (is_win2k_and_lower
)
2462 win_skip("SHCreateWorkerWindowA not available\n");
2466 hwnd
= pSHCreateWorkerWindowA(0, NULL
, 0, 0, 0, 0);
2467 ok(hwnd
!= 0, "expected window\n");
2469 GetClassName(hwnd
, classA
, 20);
2470 ok(lstrcmpA(classA
, "WorkerA") == 0, "expected WorkerA class, got %s\n", classA
);
2472 ret
= GetWindowLongPtrA(hwnd
, 0);
2473 ok(ret
== 0, "got %ld\n", ret
);
2476 memset(&cliA
, 0, sizeof(cliA
));
2477 res
= GetClassInfoA(GetModuleHandle("shlwapi.dll"), "WorkerA", &cliA
);
2478 ok(res
, "failed to get class info\n");
2479 ok(cliA
.style
== 0, "got 0x%08x\n", cliA
.style
);
2480 ok(cliA
.cbClsExtra
== 0, "got %d\n", cliA
.cbClsExtra
);
2481 ok(cliA
.cbWndExtra
== sizeof(LONG_PTR
), "got %d\n", cliA
.cbWndExtra
);
2482 ok(cliA
.lpszMenuName
== 0, "got %s\n", cliA
.lpszMenuName
);
2484 DestroyWindow(hwnd
);
2486 /* set extra bytes */
2487 hwnd
= pSHCreateWorkerWindowA(0, NULL
, 0, 0, 0, 0xdeadbeef);
2488 ok(hwnd
!= 0, "expected window\n");
2490 GetClassName(hwnd
, classA
, 20);
2491 ok(lstrcmpA(classA
, "WorkerA") == 0, "expected WorkerA class, got %s\n", classA
);
2493 ret
= GetWindowLongPtrA(hwnd
, 0);
2494 ok(ret
== 0xdeadbeef, "got %ld\n", ret
);
2497 ret
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
2498 ok(ret
== WS_EX_WINDOWEDGE
||
2499 ret
== (WS_EX_WINDOWEDGE
|WS_EX_LAYOUTRTL
) /* systems with RTL locale */, "0x%08lx\n", ret
);
2501 DestroyWindow(hwnd
);
2503 hwnd
= pSHCreateWorkerWindowA(0, NULL
, WS_EX_TOOLWINDOW
, 0, 0, 0);
2504 ret
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
2505 ok(ret
== (WS_EX_WINDOWEDGE
|WS_EX_TOOLWINDOW
) ||
2506 ret
== (WS_EX_WINDOWEDGE
|WS_EX_TOOLWINDOW
|WS_EX_LAYOUTRTL
) /* systems with RTL locale */, "0x%08lx\n", ret
);
2507 DestroyWindow(hwnd
);
2510 static HRESULT WINAPI
SF_QueryInterface(IShellFolder
*iface
,
2511 REFIID riid
, void **ppv
)
2513 /* SHIShellFolder_EnumObjects doesn't QI the object for IShellFolder */
2514 ok(!IsEqualGUID(&IID_IShellFolder
, riid
),
2515 "Unexpected QI for IShellFolder\n");
2516 return E_NOINTERFACE
;
2519 static ULONG WINAPI
SF_AddRef(IShellFolder
*iface
)
2524 static ULONG WINAPI
SF_Release(IShellFolder
*iface
)
2529 static HRESULT WINAPI
SF_ParseDisplayName(IShellFolder
*iface
,
2530 HWND owner
, LPBC reserved
, LPOLESTR displayName
, ULONG
*eaten
,
2531 LPITEMIDLIST
*idl
, ULONG
*attr
)
2533 ok(0, "Didn't expect ParseDisplayName\n");
2537 static HRESULT WINAPI
SF_EnumObjects(IShellFolder
*iface
,
2538 HWND owner
, SHCONTF flags
, IEnumIDList
**enm
)
2540 *enm
= (IEnumIDList
*)0xcafebabe;
2544 static HRESULT WINAPI
SF_BindToObject(IShellFolder
*iface
,
2545 LPCITEMIDLIST idl
, LPBC reserved
, REFIID riid
, void **obj
)
2547 ok(0, "Didn't expect BindToObject\n");
2551 static HRESULT WINAPI
SF_BindToStorage(IShellFolder
*iface
,
2552 LPCITEMIDLIST idl
, LPBC reserved
, REFIID riid
, void **obj
)
2554 ok(0, "Didn't expect BindToStorage\n");
2558 static HRESULT WINAPI
SF_CompareIDs(IShellFolder
*iface
,
2559 LPARAM lparam
, LPCITEMIDLIST idl1
, LPCITEMIDLIST idl2
)
2561 ok(0, "Didn't expect CompareIDs\n");
2565 static HRESULT WINAPI
SF_CreateViewObject(IShellFolder
*iface
,
2566 HWND owner
, REFIID riid
, void **out
)
2568 ok(0, "Didn't expect CreateViewObject\n");
2572 static HRESULT WINAPI
SF_GetAttributesOf(IShellFolder
*iface
,
2573 UINT cidl
, LPCITEMIDLIST
*idl
, SFGAOF
*inOut
)
2575 ok(0, "Didn't expect GetAttributesOf\n");
2579 static HRESULT WINAPI
SF_GetUIObjectOf(IShellFolder
*iface
,
2580 HWND owner
, UINT cidl
, LPCITEMIDLIST
*idls
, REFIID riid
, UINT
*inOut
,
2583 ok(0, "Didn't expect GetUIObjectOf\n");
2587 static HRESULT WINAPI
SF_GetDisplayNameOf(IShellFolder
*iface
,
2588 LPCITEMIDLIST idl
, SHGDNF flags
, STRRET
*name
)
2590 ok(0, "Didn't expect GetDisplayNameOf\n");
2594 static HRESULT WINAPI
SF_SetNameOf(IShellFolder
*iface
,
2595 HWND hwnd
, LPCITEMIDLIST idl
, LPCOLESTR name
, SHGDNF flags
,
2596 LPITEMIDLIST
*idlOut
)
2598 ok(0, "Didn't expect SetNameOf\n");
2602 static IShellFolderVtbl ShellFolderVtbl
= {
2606 SF_ParseDisplayName
,
2611 SF_CreateViewObject
,
2614 SF_GetDisplayNameOf
,
2618 static IShellFolder ShellFolder
= { &ShellFolderVtbl
};
2620 static void test_SHIShellFolder_EnumObjects(void)
2624 IShellFolder
*folder
;
2626 if(!pSHIShellFolder_EnumObjects
|| is_win2k_and_lower
){
2627 win_skip("SHIShellFolder_EnumObjects not available\n");
2632 /* NULL object crashes on Windows */
2633 pSHIShellFolder_EnumObjects(NULL
, NULL
, 0, NULL
);
2636 /* SHIShellFolder_EnumObjects doesn't QI the object for IShellFolder */
2637 enm
= (IEnumIDList
*)0xdeadbeef;
2638 hres
= pSHIShellFolder_EnumObjects(&ShellFolder
, NULL
, 0, &enm
);
2639 ok(hres
== S_OK
, "SHIShellFolder_EnumObjects failed: 0x%08x\n", hres
);
2640 ok(enm
== (IEnumIDList
*)0xcafebabe, "Didn't get expected enumerator location, instead: %p\n", enm
);
2642 /* SHIShellFolder_EnumObjects isn't strict about the IShellFolder object */
2643 hres
= pSHGetDesktopFolder(&folder
);
2644 ok(hres
== S_OK
, "SHGetDesktopFolder failed: 0x%08x\n", hres
);
2647 hres
= pSHIShellFolder_EnumObjects(folder
, NULL
, 0, &enm
);
2648 ok(hres
== S_OK
, "SHIShellFolder_EnumObjects failed: 0x%08x\n", hres
);
2649 ok(enm
!= NULL
, "Didn't get an enumerator\n");
2651 IEnumIDList_Release(enm
);
2653 IShellFolder_Release(folder
);
2656 static void write_inifile(LPCWSTR filename
)
2661 static const char data
[] =
2664 "AnotherKey=asdf\r\n";
2666 file
= CreateFileW(filename
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
2667 if(file
== INVALID_HANDLE_VALUE
)
2670 WriteFile(file
, data
, sizeof(data
), &written
, NULL
);
2675 #define verify_inifile(f, e) r_verify_inifile(__LINE__, f, e)
2676 static void r_verify_inifile(unsigned l
, LPCWSTR filename
, LPCSTR exp
)
2682 file
= CreateFileW(filename
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, 0, NULL
);
2683 if(file
== INVALID_HANDLE_VALUE
)
2686 ReadFile(file
, buf
, sizeof(buf
) * sizeof(CHAR
), &read
, NULL
);
2691 ok_(__FILE__
,l
)(!strcmp(buf
, exp
), "Expected:\n%s\nGot:\n%s\n", exp
,
2695 static void test_SHGetIniString(void)
2698 WCHAR out
[64] = {0};
2700 static const WCHAR TestAppW
[] = {'T','e','s','t','A','p','p',0};
2701 static const WCHAR TestIniW
[] = {'C',':','\\','t','e','s','t','.','i','n','i',0};
2702 static const WCHAR AKeyW
[] = {'A','K','e','y',0};
2703 static const WCHAR AnotherKeyW
[] = {'A','n','o','t','h','e','r','K','e','y',0};
2704 static const WCHAR JunkKeyW
[] = {'J','u','n','k','K','e','y',0};
2706 if(!pSHGetIniStringW
|| is_win2k_and_lower
){
2707 win_skip("SHGetIniStringW is not available\n");
2711 write_inifile(TestIniW
);
2714 /* these crash on Windows */
2715 pSHGetIniStringW(NULL
, NULL
, NULL
, 0, NULL
);
2716 pSHGetIniStringW(NULL
, AKeyW
, out
, sizeof(out
), TestIniW
);
2717 pSHGetIniStringW(TestAppW
, AKeyW
, NULL
, sizeof(out
), TestIniW
);
2720 ret
= pSHGetIniStringW(TestAppW
, AKeyW
, out
, 0, TestIniW
);
2721 ok(ret
== 0, "SHGetIniStringW should have given 0, instead: %d\n", ret
);
2723 /* valid arguments */
2724 ret
= pSHGetIniStringW(TestAppW
, NULL
, out
, sizeof(out
), TestIniW
);
2725 ok(broken(ret
== 0) || /* win 98 */
2726 ret
== 4, "SHGetIniStringW should have given 4, instead: %d\n", ret
);
2727 ok(!lstrcmpW(out
, AKeyW
), "Expected %s, got: %s\n",
2728 wine_dbgstr_w(AKeyW
), wine_dbgstr_w(out
));
2730 ret
= pSHGetIniStringW(TestAppW
, AKeyW
, out
, sizeof(out
), TestIniW
);
2731 ok(broken(ret
== 0) || /* win 98 */
2732 ret
== 1, "SHGetIniStringW should have given 1, instead: %d\n", ret
);
2733 ok(broken(*out
== 0) || /*win 98 */
2734 !strcmp_wa(out
, "1"), "Expected L\"1\", got: %s\n", wine_dbgstr_w(out
));
2736 ret
= pSHGetIniStringW(TestAppW
, AnotherKeyW
, out
, sizeof(out
), TestIniW
);
2737 ok(broken(ret
== 0) || /* win 98 */
2738 ret
== 4, "SHGetIniStringW should have given 4, instead: %d\n", ret
);
2739 ok(broken(*out
== 0) || /* win 98 */
2740 !strcmp_wa(out
, "asdf"), "Expected L\"asdf\", got: %s\n", wine_dbgstr_w(out
));
2742 ret
= pSHGetIniStringW(TestAppW
, JunkKeyW
, out
, sizeof(out
), TestIniW
);
2743 ok(ret
== 0, "SHGetIniStringW should have given 0, instead: %d\n", ret
);
2744 ok(*out
== 0, "Expected L\"\", got: %s\n", wine_dbgstr_w(out
));
2746 DeleteFileW(TestIniW
);
2749 static void test_SHSetIniString(void)
2753 static const WCHAR TestAppW
[] = {'T','e','s','t','A','p','p',0};
2754 static const WCHAR AnotherAppW
[] = {'A','n','o','t','h','e','r','A','p','p',0};
2755 static const WCHAR TestIniW
[] = {'C',':','\\','t','e','s','t','.','i','n','i',0};
2756 static const WCHAR AKeyW
[] = {'A','K','e','y',0};
2757 static const WCHAR NewKeyW
[] = {'N','e','w','K','e','y',0};
2758 static const WCHAR AValueW
[] = {'A','V','a','l','u','e',0};
2760 if(!pSHSetIniStringW
|| is_win2k_and_lower
){
2761 win_skip("SHSetIniStringW is not available\n");
2765 write_inifile(TestIniW
);
2767 ret
= pSHSetIniStringW(TestAppW
, AKeyW
, AValueW
, TestIniW
);
2768 ok(ret
== TRUE
, "SHSetIniStringW should not have failed\n");
2769 todo_wine
/* wine sticks an extra \r\n at the end of the file */
2770 verify_inifile(TestIniW
, "[TestApp]\r\nAKey=AValue\r\nAnotherKey=asdf\r\n");
2772 ret
= pSHSetIniStringW(TestAppW
, AKeyW
, NULL
, TestIniW
);
2773 ok(ret
== TRUE
, "SHSetIniStringW should not have failed\n");
2774 verify_inifile(TestIniW
, "[TestApp]\r\nAnotherKey=asdf\r\n");
2776 ret
= pSHSetIniStringW(AnotherAppW
, NewKeyW
, AValueW
, TestIniW
);
2777 ok(ret
== TRUE
, "SHSetIniStringW should not have failed\n");
2778 verify_inifile(TestIniW
, "[TestApp]\r\nAnotherKey=asdf\r\n[AnotherApp]\r\nNewKey=AValue\r\n");
2780 ret
= pSHSetIniStringW(TestAppW
, NULL
, AValueW
, TestIniW
);
2781 ok(ret
== TRUE
, "SHSetIniStringW should not have failed\n");
2782 verify_inifile(TestIniW
, "[AnotherApp]\r\nNewKey=AValue\r\n");
2784 DeleteFileW(TestIniW
);
2787 enum _shellkey_flags
{
2788 SHKEY_Root_HKCU
= 0x1,
2789 SHKEY_Root_HKLM
= 0x2,
2790 SHKEY_Key_Explorer
= 0x00,
2791 SHKEY_Key_Shell
= 0x10,
2792 SHKEY_Key_ShellNoRoam
= 0x20,
2793 SHKEY_Key_Classes
= 0x30,
2794 SHKEY_Subkey_Default
= 0x0000,
2795 SHKEY_Subkey_ResourceName
= 0x1000,
2796 SHKEY_Subkey_Handlers
= 0x2000,
2797 SHKEY_Subkey_Associations
= 0x3000,
2798 SHKEY_Subkey_Volatile
= 0x4000,
2799 SHKEY_Subkey_MUICache
= 0x5000,
2800 SHKEY_Subkey_FileExts
= 0x6000
2803 static void test_SHGetShellKey(void)
2805 static const WCHAR ShellFoldersW
[] = { 'S','h','e','l','l',' ','F','o','l','d','e','r','s',0 };
2806 static const WCHAR WineTestW
[] = { 'W','i','n','e','T','e','s','t',0 };
2808 void *pPathBuildRootW
= GetProcAddress(hShlwapi
, "PathBuildRootW");
2809 DWORD
*alloc_data
, data
, size
;
2813 if (!pSHGetShellKey
)
2815 win_skip("SHGetShellKey(ordinal 491) isn't available\n");
2820 if (pPathBuildRootW
&& pPathBuildRootW
== pSHGetShellKey
)
2822 win_skip("SHGetShellKey(ordinal 491) used for PathBuildRootW\n");
2826 if (is_win9x
|| is_win2k_and_lower
)
2828 win_skip("Ordinal 491 used for another call, skipping SHGetShellKey tests\n");
2832 /* Vista+ limits SHKEY enumeration values */
2833 SetLastError(0xdeadbeef);
2834 hkey
= pSHGetShellKey(SHKEY_Key_Explorer
, ShellFoldersW
, FALSE
);
2837 /* Tests not working on Vista+ */
2840 hkey
= pSHGetShellKey(SHKEY_Root_HKLM
|SHKEY_Key_Classes
, NULL
, FALSE
);
2841 ok(hkey
!= NULL
, "hkey = NULL\n");
2845 hkey
= pSHGetShellKey(SHKEY_Root_HKCU
|SHKEY_Key_Explorer
, ShellFoldersW
, FALSE
);
2846 ok(hkey
!= NULL
, "hkey = NULL\n");
2849 hkey
= pSHGetShellKey(SHKEY_Root_HKLM
|SHKEY_Key_Explorer
, ShellFoldersW
, FALSE
);
2850 ok(hkey
!= NULL
, "hkey = NULL\n");
2853 hkey
= pSHGetShellKey(SHKEY_Root_HKLM
, WineTestW
, FALSE
);
2854 ok(hkey
== NULL
, "hkey != NULL\n");
2856 hkey
= pSHGetShellKey(SHKEY_Root_HKLM
, WineTestW
, TRUE
);
2857 ok(hkey
!= NULL
, "Can't create key\n");
2860 hkey
= pSHGetShellKey(SHKEY_Root_HKLM
, NULL
, FALSE
);
2861 ok(hkey
!= NULL
, "Can't create key\n");
2862 ok(SUCCEEDED(RegDeleteKeyW(hkey
, WineTestW
)), "Can't delte key\n");
2865 if (!pSKGetValueW
|| !pSKSetValueW
|| !pSKDeleteValueW
|| !pSKAllocValueW
)
2867 win_skip("SKGetValueW, SKSetValueW, SKDeleteValueW or SKAllocValueW not available\n");
2871 hres
= pSKGetValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
, NULL
, &data
, &size
);
2872 ok(hres
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), "hres = %x\n", hres
);
2875 hres
= pSKSetValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
, REG_DWORD
, &data
, sizeof(DWORD
));
2876 ok(hres
== S_OK
, "hres = %x\n", hres
);
2879 hres
= pSKGetValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
, NULL
, NULL
, &size
);
2880 ok(hres
== S_OK
, "hres = %x\n", hres
);
2881 ok(size
== sizeof(DWORD
), "size = %d\n", size
);
2884 hres
= pSKGetValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
, NULL
, &data
, &size
);
2885 ok(hres
== S_OK
, "hres = %x\n", hres
);
2886 ok(size
== sizeof(DWORD
), "size = %d\n", size
);
2887 ok(data
== 1234, "data = %d\n", data
);
2889 hres
= pSKAllocValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
, NULL
, (void**)&alloc_data
, &size
);
2890 ok(hres
== S_OK
, "hres= %x\n", hres
);
2891 ok(size
== sizeof(DWORD
), "size = %d\n", size
);
2892 ok(*alloc_data
== 1234, "*alloc_data = %d\n", *alloc_data
);
2893 LocalFree(alloc_data
);
2895 hres
= pSKDeleteValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
);
2896 ok(hres
== S_OK
, "hres = %x\n", hres
);
2898 hres
= pSKDeleteValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
);
2899 ok(hres
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), "hres = %x\n", hres
);
2901 hres
= pSKGetValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
, NULL
, &data
, &size
);
2902 ok(hres
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), "hres = %x\n", hres
);
2904 hkey
= pSHGetShellKey(SHKEY_Root_HKLM
, NULL
, FALSE
);
2905 ok(hkey
!= NULL
, "Can't create key\n");
2906 ok(SUCCEEDED(RegDeleteKeyW(hkey
, WineTestW
)), "Can't delte key\n");
2910 static void init_pointers(void)
2912 #define MAKEFUNC(f, ord) (p##f = (void*)GetProcAddress(hShlwapi, (LPSTR)(ord)))
2913 MAKEFUNC(SHAllocShared
, 7);
2914 MAKEFUNC(SHLockShared
, 8);
2915 MAKEFUNC(SHUnlockShared
, 9);
2916 MAKEFUNC(SHFreeShared
, 10);
2917 MAKEFUNC(GetAcceptLanguagesA
, 14);
2918 MAKEFUNC(SHSetWindowBits
, 165);
2919 MAKEFUNC(ConnectToConnectionPoint
, 168);
2920 MAKEFUNC(SHSearchMapInt
, 198);
2921 MAKEFUNC(SHCreateWorkerWindowA
, 257);
2922 MAKEFUNC(GUIDFromStringA
, 269);
2923 MAKEFUNC(SHPackDispParams
, 282);
2924 MAKEFUNC(IConnectionPoint_InvokeWithCancel
, 283);
2925 MAKEFUNC(IConnectionPoint_SimpleInvoke
, 284);
2926 MAKEFUNC(SHGetIniStringW
, 294);
2927 MAKEFUNC(SHSetIniStringW
, 295);
2928 MAKEFUNC(SHFormatDateTimeA
, 353);
2929 MAKEFUNC(SHFormatDateTimeW
, 354);
2930 MAKEFUNC(SHIShellFolder_EnumObjects
, 404);
2931 MAKEFUNC(SHGetObjectCompatFlags
, 476);
2932 MAKEFUNC(IUnknown_QueryServiceExec
, 484);
2933 MAKEFUNC(SHGetShellKey
, 491);
2934 MAKEFUNC(SHPropertyBag_ReadLONG
, 496);
2935 MAKEFUNC(IUnknown_ProfferService
, 514);
2936 MAKEFUNC(SKGetValueW
, 516);
2937 MAKEFUNC(SKSetValueW
, 517);
2938 MAKEFUNC(SKDeleteValueW
, 518);
2939 MAKEFUNC(SKAllocValueW
, 519);
2945 hShlwapi
= GetModuleHandleA("shlwapi.dll");
2946 is_win2k_and_lower
= GetProcAddress(hShlwapi
, "StrChrNW") == 0;
2947 is_win9x
= GetProcAddress(hShlwapi
, (LPSTR
)99) == 0; /* StrCpyNXA */
2949 /* SHCreateStreamOnFileEx was introduced in shlwapi v6.0 */
2950 if(!GetProcAddress(hShlwapi
, "SHCreateStreamOnFileEx")){
2951 win_skip("Too old shlwapi version\n");
2957 hmlang
= LoadLibraryA("mlang.dll");
2958 pLcidToRfc1766A
= (void *)GetProcAddress(hmlang
, "LcidToRfc1766A");
2960 hshell32
= LoadLibraryA("shell32.dll");
2961 pSHGetDesktopFolder
= (void *)GetProcAddress(hshell32
, "SHGetDesktopFolder");
2963 test_GetAcceptLanguagesA();
2964 test_SHSearchMapInt();
2965 test_alloc_shared();
2967 test_GetShellSecurityDescriptor();
2968 test_SHPackDispParams();
2969 test_IConnectionPoint();
2970 test_SHPropertyBag_ReadLONG();
2971 test_SHSetWindowBits();
2972 test_SHFormatDateTimeA();
2973 test_SHFormatDateTimeW();
2974 test_SHGetObjectCompatFlags();
2975 test_IUnknown_QueryServiceExec();
2976 test_IUnknown_ProfferService();
2977 test_SHCreateWorkerWindowA();
2978 test_SHIShellFolder_EnumObjects();
2979 test_SHGetIniString();
2980 test_SHSetIniString();
2981 test_SHGetShellKey();
2983 FreeLibrary(hshell32
);
2984 FreeLibrary(hmlang
);