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
20 #define WIN32_NO_STATUS
22 #define COM_NO_WINDOWS_H
28 #include <wine/test.h>
29 //#include "winbase.h"
32 //#include "winerror.h"
33 //#include "winuser.h"
43 /* Function ptrs for ordinal calls */
44 static HMODULE hShlwapi
;
45 static BOOL is_win2k_and_lower
;
48 static int (WINAPI
*pSHSearchMapInt
)(const int*,const int*,int,int);
49 static HRESULT (WINAPI
*pGetAcceptLanguagesA
)(LPSTR
,LPDWORD
);
51 static HANDLE (WINAPI
*pSHAllocShared
)(LPCVOID
,DWORD
,DWORD
);
52 static LPVOID (WINAPI
*pSHLockShared
)(HANDLE
,DWORD
);
53 static BOOL (WINAPI
*pSHUnlockShared
)(LPVOID
);
54 static BOOL (WINAPI
*pSHFreeShared
)(HANDLE
,DWORD
);
55 static HRESULT(WINAPIV
*pSHPackDispParams
)(DISPPARAMS
*,VARIANTARG
*,UINT
,...);
56 static HRESULT(WINAPI
*pIConnectionPoint_SimpleInvoke
)(IConnectionPoint
*,DISPID
,DISPPARAMS
*);
57 static HRESULT(WINAPI
*pIConnectionPoint_InvokeWithCancel
)(IConnectionPoint
*,DISPID
,DISPPARAMS
*,DWORD
,DWORD
);
58 static HRESULT(WINAPI
*pConnectToConnectionPoint
)(IUnknown
*,REFIID
,BOOL
,IUnknown
*, LPDWORD
,IConnectionPoint
**);
59 static HRESULT(WINAPI
*pSHPropertyBag_ReadLONG
)(IPropertyBag
*,LPCWSTR
,LPLONG
);
60 static LONG (WINAPI
*pSHSetWindowBits
)(HWND
, INT
, UINT
, UINT
);
61 static INT (WINAPI
*pSHFormatDateTimeA
)(const FILETIME UNALIGNED
*, DWORD
*, LPSTR
, UINT
);
62 static INT (WINAPI
*pSHFormatDateTimeW
)(const FILETIME UNALIGNED
*, DWORD
*, LPWSTR
, UINT
);
63 static DWORD (WINAPI
*pSHGetObjectCompatFlags
)(IUnknown
*, const CLSID
*);
64 static BOOL (WINAPI
*pGUIDFromStringA
)(LPSTR
, CLSID
*);
65 static HRESULT (WINAPI
*pIUnknown_QueryServiceExec
)(IUnknown
*, REFIID
, const GUID
*, DWORD
, DWORD
, VARIANT
*, VARIANT
*);
66 static HRESULT (WINAPI
*pIUnknown_ProfferService
)(IUnknown
*, REFGUID
, IServiceProvider
*, DWORD
*);
67 static HWND (WINAPI
*pSHCreateWorkerWindowA
)(LONG
, HWND
, DWORD
, DWORD
, HMENU
, LONG_PTR
);
68 static HRESULT (WINAPI
*pSHIShellFolder_EnumObjects
)(LPSHELLFOLDER
, HWND
, SHCONTF
, IEnumIDList
**);
69 static DWORD (WINAPI
*pSHGetIniStringW
)(LPCWSTR
, LPCWSTR
, LPWSTR
, DWORD
, LPCWSTR
);
70 static BOOL (WINAPI
*pSHSetIniStringW
)(LPCWSTR
, LPCWSTR
, LPCWSTR
, LPCWSTR
);
71 static HKEY (WINAPI
*pSHGetShellKey
)(DWORD
, LPCWSTR
, BOOL
);
72 static HRESULT (WINAPI
*pSKGetValueW
)(DWORD
, LPCWSTR
, LPCWSTR
, DWORD
*, void*, DWORD
*);
73 static HRESULT (WINAPI
*pSKSetValueW
)(DWORD
, LPCWSTR
, LPCWSTR
, DWORD
, void*, DWORD
);
74 static HRESULT (WINAPI
*pSKDeleteValueW
)(DWORD
, LPCWSTR
, LPCWSTR
);
75 static HRESULT (WINAPI
*pSKAllocValueW
)(DWORD
, LPCWSTR
, LPCWSTR
, DWORD
*, void**, DWORD
*);
76 static HWND (WINAPI
*pSHSetParentHwnd
)(HWND
, HWND
);
78 static HMODULE hmlang
;
79 static HRESULT (WINAPI
*pLcidToRfc1766A
)(LCID
, LPSTR
, INT
);
81 static HMODULE hshell32
;
82 static HRESULT (WINAPI
*pSHGetDesktopFolder
)(IShellFolder
**);
84 static const CHAR ie_international
[] = {
85 'S','o','f','t','w','a','r','e','\\',
86 'M','i','c','r','o','s','o','f','t','\\',
87 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
88 'I','n','t','e','r','n','a','t','i','o','n','a','l',0};
89 static const CHAR acceptlanguage
[] = {
90 'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0};
92 static int strcmp_wa(LPCWSTR strw
, const char *stra
)
95 WideCharToMultiByte(CP_ACP
, 0, strw
, -1, buf
, sizeof(buf
), NULL
, NULL
);
96 return lstrcmpA(stra
, buf
);
110 static void init_call_trace(call_trace_t
*ctrace
)
114 ctrace
->calls
= HeapAlloc(GetProcessHeap(), 0, sizeof(call_entry_t
) * ctrace
->alloc
);
117 static void free_call_trace(const call_trace_t
*ctrace
)
119 HeapFree(GetProcessHeap(), 0, ctrace
->calls
);
122 static void add_call(call_trace_t
*ctrace
, int id
, const void *arg0
,
123 const void *arg1
, const void *arg2
, const void *arg3
, const void *arg4
)
134 if (ctrace
->count
== ctrace
->alloc
)
137 ctrace
->calls
= HeapReAlloc(GetProcessHeap(),0, ctrace
->calls
, ctrace
->alloc
*sizeof(call_entry_t
));
140 ctrace
->calls
[ctrace
->count
++] = call
;
143 static void ok_trace_(call_trace_t
*texpected
, call_trace_t
*tgot
, int line
)
145 if (texpected
->count
== tgot
->count
)
149 for (i
= 0; i
< texpected
->count
; i
++)
151 call_entry_t
*expected
= &texpected
->calls
[i
];
152 call_entry_t
*got
= &tgot
->calls
[i
];
155 ok_(__FILE__
, line
)(expected
->id
== got
->id
, "got different ids %d: %d, %d\n", i
+1, expected
->id
, got
->id
);
157 for (j
= 0; j
< 5; j
++)
159 ok_(__FILE__
, line
)(expected
->args
[j
] == got
->args
[j
], "got different args[%d] for %d: %p, %p\n", j
, i
+1,
160 expected
->args
[j
], got
->args
[j
]);
165 ok_(__FILE__
, line
)(0, "traces length mismatch\n");
168 #define ok_trace(a, b) ok_trace_(a, b, __LINE__)
170 /* trace of actually made calls */
171 static call_trace_t trace_got
;
173 static void test_GetAcceptLanguagesA(void)
175 static LPCSTR table
[] = {"de,en-gb;q=0.7,en;q=0.3",
176 "de,en;q=0.3,en-gb;q=0.7", /* sorting is ignored */
177 "winetest", /* content is ignored */
187 LONG res_query
= ERROR_SUCCESS
;
190 DWORD maxlen
= sizeof(buffer
) - 2;
196 if (!pGetAcceptLanguagesA
) {
197 win_skip("GetAcceptLanguagesA is not available\n");
201 lcid
= GetUserDefaultLCID();
203 /* Get the original Value */
204 lres
= RegOpenKeyA(HKEY_CURRENT_USER
, ie_international
, &hroot
);
206 skip("RegOpenKey(%s) failed: %d\n", ie_international
, lres
);
209 len
= sizeof(original
);
211 res_query
= RegQueryValueExA(hroot
, acceptlanguage
, 0, NULL
, (PBYTE
)original
, &len
);
213 RegDeleteValueA(hroot
, acceptlanguage
);
215 /* Some windows versions use "lang-COUNTRY" as default */
216 memset(language
, 0, sizeof(language
));
217 len
= GetLocaleInfoA(lcid
, LOCALE_SISO639LANGNAME
, language
, sizeof(language
));
220 lstrcatA(language
, "-");
221 memset(buffer
, 0, sizeof(buffer
));
222 len
= GetLocaleInfoA(lcid
, LOCALE_SISO3166CTRYNAME
, buffer
, sizeof(buffer
) - len
- 1);
223 lstrcatA(language
, buffer
);
227 /* LOCALE_SNAME has additional parts in some languages. Try only as last chance */
228 memset(language
, 0, sizeof(language
));
229 len
= GetLocaleInfoA(lcid
, LOCALE_SNAME
, language
, sizeof(language
));
232 /* get the default value */
234 memset(buffer
, '#', maxlen
);
236 hr
= pGetAcceptLanguagesA( buffer
, &len
);
239 win_skip("GetAcceptLanguagesA failed with 0x%x\n", hr
);
240 goto restore_original
;
243 if (lstrcmpA(buffer
, language
)) {
244 /* some windows versions use "lang" or "lang-country" as default */
246 if (pLcidToRfc1766A
) {
247 hr
= pLcidToRfc1766A(lcid
, language
, sizeof(language
));
248 ok(hr
== S_OK
, "LcidToRfc1766A returned 0x%x and %s\n", hr
, language
);
252 ok(!lstrcmpA(buffer
, language
),
253 "have '%s' (searching for '%s')\n", language
, buffer
);
255 if (lstrcmpA(buffer
, language
)) {
256 win_skip("no more ideas, how to build the default language '%s'\n", buffer
);
257 goto restore_original
;
260 trace("detected default: %s\n", language
);
261 while ((entry
= table
[i
])) {
263 exactsize
= lstrlenA(entry
);
265 lres
= RegSetValueExA(hroot
, acceptlanguage
, 0, REG_SZ
, (const BYTE
*) entry
, exactsize
+ 1);
266 ok(!lres
, "got %d for RegSetValueExA: %s\n", lres
, entry
);
268 /* len includes space for the terminating 0 before vista/w2k8 */
270 memset(buffer
, '#', maxlen
);
272 hr
= pGetAcceptLanguagesA( buffer
, &len
);
273 ok(((hr
== E_INVALIDARG
) && (len
== 0)) ||
275 ((len
== exactsize
) || (len
== exactsize
+1)) &&
276 !lstrcmpA(buffer
, entry
)),
277 "+2_#%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
280 memset(buffer
, '#', maxlen
);
282 hr
= pGetAcceptLanguagesA( buffer
, &len
);
283 ok(((hr
== E_INVALIDARG
) && (len
== 0)) ||
285 ((len
== exactsize
) || (len
== exactsize
+1)) &&
286 !lstrcmpA(buffer
, entry
)),
287 "+1_#%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
290 memset(buffer
, '#', maxlen
);
292 hr
= pGetAcceptLanguagesA( buffer
, &len
);
294 /* There is no space for the string in the registry.
295 When the buffer is large enough, the default language is returned
297 When the buffer is too small for that fallback, win7_32 and w2k8_64
298 fail with HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), win8 fails
299 with HRESULT_FROM_WIN32(ERROR_MORE_DATA), other versions succeed and
300 return a partial result while older os succeed and overflow the buffer */
302 ok(((hr
== E_INVALIDARG
) && (len
== 0)) ||
303 (((hr
== S_OK
) && !lstrcmpA(buffer
, language
) && (len
== lstrlenA(language
))) ||
304 ((hr
== S_OK
) && !memcmp(buffer
, language
, len
)) ||
305 ((hr
== __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
)) && !len
) ||
306 ((hr
== __HRESULT_FROM_WIN32(ERROR_MORE_DATA
)) && len
== exactsize
)),
307 "==_#%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
311 memset(buffer
, '#', maxlen
);
313 hr
= pGetAcceptLanguagesA( buffer
, &len
);
314 ok(((hr
== E_INVALIDARG
) && (len
== 0)) ||
315 (((hr
== S_OK
) && !lstrcmpA(buffer
, language
) && (len
== lstrlenA(language
))) ||
316 ((hr
== S_OK
) && !memcmp(buffer
, language
, len
)) ||
317 ((hr
== __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
)) && !len
) ||
318 ((hr
== __HRESULT_FROM_WIN32(ERROR_MORE_DATA
)) && len
== exactsize
- 1)),
319 "-1_#%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
323 memset(buffer
, '#', maxlen
);
325 hr
= pGetAcceptLanguagesA( buffer
, &len
);
326 ok(((hr
== E_INVALIDARG
) && (len
== 0)) ||
327 (((hr
== S_OK
) && !lstrcmpA(buffer
, language
) && (len
== lstrlenA(language
))) ||
328 ((hr
== S_OK
) && !memcmp(buffer
, language
, len
)) ||
329 ((hr
== __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
)) && !len
) ||
330 ((hr
== __HRESULT_FROM_WIN32(ERROR_MORE_DATA
)) && len
== 1)),
331 "=1_#%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
334 hr
= pGetAcceptLanguagesA( NULL
, &len
);
336 /* w2k3 and below: E_FAIL and untouched len,
337 since w2k8: S_OK and needed size (excluding 0), win8 S_OK and size including 0. */
338 ok( ((hr
== S_OK
) && ((len
== exactsize
) || (len
== exactsize
+ 1))) ||
339 ((hr
== E_FAIL
) && (len
== maxlen
)),
340 "NULL,max #%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
345 /* without a value in the registry, a default language is returned */
346 RegDeleteValueA(hroot
, acceptlanguage
);
349 memset(buffer
, '#', maxlen
);
351 hr
= pGetAcceptLanguagesA( buffer
, &len
);
352 ok( ((hr
== S_OK
) && (len
== lstrlenA(language
))),
353 "max: got 0x%x with %d and %s (expected S_OK with %d and '%s'\n",
354 hr
, len
, buffer
, lstrlenA(language
), language
);
357 memset(buffer
, '#', maxlen
);
359 hr
= pGetAcceptLanguagesA( buffer
, &len
);
360 ok( (((hr
== S_OK
) || (hr
== E_INVALIDARG
)) && !memcmp(buffer
, language
, len
)) ||
361 ((hr
== __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
)) && !len
) ||
362 ((hr
== __HRESULT_FROM_WIN32(ERROR_CANNOT_COPY
)) && !len
),
363 "=2: got 0x%x with %d and %s\n", hr
, len
, buffer
);
366 memset(buffer
, '#', maxlen
);
368 hr
= pGetAcceptLanguagesA( buffer
, &len
);
369 /* When the buffer is too small, win7_32 and w2k8_64 and above fail with
370 HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), win8 ERROR_CANNOT_COPY,
371 other versions succeed and return a partial 0 terminated result while other versions
372 fail with E_INVALIDARG and return a partial unterminated result */
373 ok( (((hr
== S_OK
) || (hr
== E_INVALIDARG
)) && !memcmp(buffer
, language
, len
)) ||
374 ((hr
== __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
)) && !len
) ||
375 ((hr
== __HRESULT_FROM_WIN32(ERROR_CANNOT_COPY
)) && !len
),
376 "=1: got 0x%x with %d and %s\n", hr
, len
, buffer
);
379 memset(buffer
, '#', maxlen
);
381 hr
= pGetAcceptLanguagesA( buffer
, &len
);
382 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG, win8 ERROR_CANNOT_COPY */
383 ok((hr
== E_FAIL
) || (hr
== E_INVALIDARG
) || (hr
== __HRESULT_FROM_WIN32(ERROR_CANNOT_COPY
)),
386 memset(buffer
, '#', maxlen
);
388 hr
= pGetAcceptLanguagesA( buffer
, NULL
);
389 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
390 ok((hr
== E_FAIL
) || (hr
== E_INVALIDARG
),
391 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr
);
394 hr
= pGetAcceptLanguagesA( NULL
, NULL
);
395 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
396 ok((hr
== E_FAIL
) || (hr
== E_INVALIDARG
),
397 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr
);
401 len
= lstrlenA(original
);
402 lres
= RegSetValueExA(hroot
, acceptlanguage
, 0, REG_SZ
, (const BYTE
*) original
, len
? len
+ 1: 0);
403 ok(!lres
, "RegSetValueEx(%s) failed: %d\n", original
, lres
);
407 RegDeleteValueA(hroot
, acceptlanguage
);
412 static void test_SHSearchMapInt(void)
414 int keys
[8], values
[8];
417 if (!pSHSearchMapInt
)
420 memset(keys
, 0, sizeof(keys
));
421 memset(values
, 0, sizeof(values
));
422 keys
[0] = 99; values
[0] = 101;
424 /* NULL key/value lists crash native, so skip testing them */
427 i
= pSHSearchMapInt(keys
, values
, 1, keys
[0]);
428 ok(i
== values
[0], "Len 1, expected %d, got %d\n", values
[0], i
);
430 /* Key doesn't exist */
431 i
= pSHSearchMapInt(keys
, values
, 1, 100);
432 ok(i
== -1, "Len 1 - bad key, expected -1, got %d\n", i
);
434 /* Len = 0 => not found */
435 i
= pSHSearchMapInt(keys
, values
, 0, keys
[0]);
436 ok(i
== -1, "Len 1 - passed len 0, expected -1, got %d\n", i
);
438 /* 2 elements, len = 1 */
439 keys
[1] = 98; values
[1] = 102;
440 i
= pSHSearchMapInt(keys
, values
, 1, keys
[1]);
441 ok(i
== -1, "Len 1 - array len 2, expected -1, got %d\n", i
);
443 /* 2 elements, len = 2 */
444 i
= pSHSearchMapInt(keys
, values
, 2, keys
[1]);
445 ok(i
== values
[1], "Len 2, expected %d, got %d\n", values
[1], i
);
447 /* Searches forward */
448 keys
[2] = 99; values
[2] = 103;
449 i
= pSHSearchMapInt(keys
, values
, 3, keys
[0]);
450 ok(i
== values
[0], "Len 3, expected %d, got %d\n", values
[0], i
);
453 static void test_alloc_shared(void)
461 procid
=GetCurrentProcessId();
462 hmem
=pSHAllocShared(NULL
,10,procid
);
463 ok(hmem
!=NULL
,"SHAllocShared(NULL...) failed: %u\n", GetLastError());
464 ret
= pSHFreeShared(hmem
, procid
);
465 ok( ret
, "SHFreeShared failed: %u\n", GetLastError());
468 hmem
=pSHAllocShared(&val
,4,procid
);
469 ok(hmem
!=NULL
,"SHAllocShared(NULL...) failed: %u\n", GetLastError());
471 p
=pSHLockShared(hmem
,procid
);
472 ok(p
!=NULL
,"SHLockShared failed: %u\n", GetLastError());
474 ok(*p
==val
,"Wrong value in shared memory: %d instead of %d\n",*p
,val
);
475 ret
= pSHUnlockShared(p
);
476 ok( ret
, "SHUnlockShared failed: %u\n", GetLastError());
478 ret
= pSHFreeShared(hmem
, procid
);
479 ok( ret
, "SHFreeShared failed: %u\n", GetLastError());
482 static void test_fdsa(void)
486 DWORD num_items
; /* Number of elements inserted */
487 void *mem
; /* Ptr to array */
488 DWORD blocks_alloced
; /* Number of elements allocated */
489 BYTE inc
; /* Number of elements to grow by when we need to expand */
490 BYTE block_size
; /* Size in bytes of an element */
491 BYTE flags
; /* Flags */
494 BOOL (WINAPI
*pFDSA_Initialize
)(DWORD block_size
, DWORD inc
, FDSA_info
*info
, void *mem
,
496 BOOL (WINAPI
*pFDSA_Destroy
)(FDSA_info
*info
);
497 DWORD (WINAPI
*pFDSA_InsertItem
)(FDSA_info
*info
, DWORD where
, const void *block
);
498 BOOL (WINAPI
*pFDSA_DeleteItem
)(FDSA_info
*info
, DWORD where
);
501 int block_size
= 10, init_blocks
= 4, inc
= 2;
505 pFDSA_Initialize
= (void *)GetProcAddress(hShlwapi
, (LPSTR
)208);
506 pFDSA_Destroy
= (void *)GetProcAddress(hShlwapi
, (LPSTR
)209);
507 pFDSA_InsertItem
= (void *)GetProcAddress(hShlwapi
, (LPSTR
)210);
508 pFDSA_DeleteItem
= (void *)GetProcAddress(hShlwapi
, (LPSTR
)211);
510 mem
= HeapAlloc(GetProcessHeap(), 0, block_size
* init_blocks
);
511 memset(&info
, 0, sizeof(info
));
513 ok(pFDSA_Initialize(block_size
, inc
, &info
, mem
, init_blocks
), "FDSA_Initialize rets FALSE\n");
514 ok(info
.num_items
== 0, "num_items = %d\n", info
.num_items
);
515 ok(info
.mem
== mem
, "mem = %p\n", info
.mem
);
516 ok(info
.blocks_alloced
== init_blocks
, "blocks_alloced = %d\n", info
.blocks_alloced
);
517 ok(info
.inc
== inc
, "inc = %d\n", info
.inc
);
518 ok(info
.block_size
== block_size
, "block_size = %d\n", info
.block_size
);
519 ok(info
.flags
== 0, "flags = %d\n", info
.flags
);
521 ret
= pFDSA_InsertItem(&info
, 1234, "1234567890");
522 ok(ret
== 0, "ret = %d\n", ret
);
523 ok(info
.num_items
== 1, "num_items = %d\n", info
.num_items
);
524 ok(info
.mem
== mem
, "mem = %p\n", info
.mem
);
525 ok(info
.blocks_alloced
== init_blocks
, "blocks_alloced = %d\n", info
.blocks_alloced
);
526 ok(info
.inc
== inc
, "inc = %d\n", info
.inc
);
527 ok(info
.block_size
== block_size
, "block_size = %d\n", info
.block_size
);
528 ok(info
.flags
== 0, "flags = %d\n", info
.flags
);
530 ret
= pFDSA_InsertItem(&info
, 1234, "abcdefghij");
531 ok(ret
== 1, "ret = %d\n", ret
);
533 ret
= pFDSA_InsertItem(&info
, 1, "klmnopqrst");
534 ok(ret
== 1, "ret = %d\n", ret
);
536 ret
= pFDSA_InsertItem(&info
, 0, "uvwxyzABCD");
537 ok(ret
== 0, "ret = %d\n", ret
);
538 ok(info
.mem
== mem
, "mem = %p\n", info
.mem
);
539 ok(info
.flags
== 0, "flags = %d\n", info
.flags
);
541 /* This next InsertItem will cause shlwapi to allocate its own mem buffer */
542 ret
= pFDSA_InsertItem(&info
, 0, "EFGHIJKLMN");
543 ok(ret
== 0, "ret = %d\n", ret
);
544 ok(info
.mem
!= mem
, "mem = %p\n", info
.mem
);
545 ok(info
.blocks_alloced
== init_blocks
+ inc
, "blocks_alloced = %d\n", info
.blocks_alloced
);
546 ok(info
.flags
== 0x1, "flags = %d\n", info
.flags
);
548 ok(!memcmp(info
.mem
, "EFGHIJKLMNuvwxyzABCD1234567890klmnopqrstabcdefghij", 50), "mem %s\n", (char*)info
.mem
);
550 ok(pFDSA_DeleteItem(&info
, 2), "rets FALSE\n");
551 ok(info
.mem
!= mem
, "mem = %p\n", info
.mem
);
552 ok(info
.blocks_alloced
== init_blocks
+ inc
, "blocks_alloced = %d\n", info
.blocks_alloced
);
553 ok(info
.flags
== 0x1, "flags = %d\n", info
.flags
);
555 ok(!memcmp(info
.mem
, "EFGHIJKLMNuvwxyzABCDklmnopqrstabcdefghij", 40), "mem %s\n", (char*)info
.mem
);
557 ok(pFDSA_DeleteItem(&info
, 3), "rets FALSE\n");
558 ok(info
.mem
!= mem
, "mem = %p\n", info
.mem
);
559 ok(info
.blocks_alloced
== init_blocks
+ inc
, "blocks_alloced = %d\n", info
.blocks_alloced
);
560 ok(info
.flags
== 0x1, "flags = %d\n", info
.flags
);
562 ok(!memcmp(info
.mem
, "EFGHIJKLMNuvwxyzABCDklmnopqrst", 30), "mem %s\n", (char*)info
.mem
);
564 ok(!pFDSA_DeleteItem(&info
, 4), "does not ret FALSE\n");
566 /* As shlwapi has allocated memory internally, Destroy will ret FALSE */
567 ok(!pFDSA_Destroy(&info
), "FDSA_Destroy does not ret FALSE\n");
570 /* When Initialize is called with inc = 0, set it to 1 */
571 ok(pFDSA_Initialize(block_size
, 0, &info
, mem
, init_blocks
), "FDSA_Initialize rets FALSE\n");
572 ok(info
.inc
== 1, "inc = %d\n", info
.inc
);
574 /* This time, because shlwapi hasn't had to allocate memory
575 internally, Destroy rets non-zero */
576 ok(pFDSA_Destroy(&info
), "FDSA_Destroy rets FALSE\n");
579 HeapFree(GetProcessHeap(), 0, mem
);
583 typedef struct SHELL_USER_SID
{
584 SID_IDENTIFIER_AUTHORITY sidAuthority
;
587 } SHELL_USER_SID
, *PSHELL_USER_SID
;
588 typedef struct SHELL_USER_PERMISSION
{
589 SHELL_USER_SID susID
;
594 DWORD dwInheritAccessMask
;
595 } SHELL_USER_PERMISSION
, *PSHELL_USER_PERMISSION
;
596 static void test_GetShellSecurityDescriptor(void)
598 SHELL_USER_PERMISSION supCurrentUserFull
= {
599 { {SECURITY_NULL_SID_AUTHORITY
}, 0, 0 },
600 ACCESS_ALLOWED_ACE_TYPE
, FALSE
,
602 #define MY_INHERITANCE 0xBE /* invalid value to proof behavior */
603 SHELL_USER_PERMISSION supEveryoneDenied
= {
604 { {SECURITY_WORLD_SID_AUTHORITY
}, SECURITY_WORLD_RID
, 0 },
605 ACCESS_DENIED_ACE_TYPE
, TRUE
,
606 GENERIC_WRITE
, MY_INHERITANCE
| 0xDEADBA00, GENERIC_READ
};
607 PSHELL_USER_PERMISSION rgsup
[2] = {
608 &supCurrentUserFull
, &supEveryoneDenied
,
610 SECURITY_DESCRIPTOR
* psd
;
611 SECURITY_DESCRIPTOR
* (WINAPI
*pGetShellSecurityDescriptor
)(PSHELL_USER_PERMISSION
*,int);
612 void *pChrCmpIW
= GetProcAddress(hShlwapi
, "ChrCmpIW");
614 pGetShellSecurityDescriptor
=(void*)GetProcAddress(hShlwapi
,(char*)475);
616 if(!pGetShellSecurityDescriptor
)
618 win_skip("GetShellSecurityDescriptor not available\n");
622 if(pChrCmpIW
&& pChrCmpIW
== pGetShellSecurityDescriptor
) /* win2k */
624 win_skip("Skipping for GetShellSecurityDescriptor, same ordinal used for ChrCmpIW\n");
628 psd
= pGetShellSecurityDescriptor(NULL
, 2);
630 broken(psd
==INVALID_HANDLE_VALUE
), /* IE5 */
631 "GetShellSecurityDescriptor should fail\n");
632 psd
= pGetShellSecurityDescriptor(rgsup
, 0);
633 ok(psd
==NULL
, "GetShellSecurityDescriptor should fail, got %p\n", psd
);
635 SetLastError(0xdeadbeef);
636 psd
= pGetShellSecurityDescriptor(rgsup
, 2);
637 if (psd
== NULL
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
639 /* The previous calls to GetShellSecurityDescriptor don't set the last error */
640 win_skip("GetShellSecurityDescriptor is not implemented\n");
643 if (psd
== INVALID_HANDLE_VALUE
)
645 win_skip("GetShellSecurityDescriptor is broken on IE5\n");
648 ok(psd
!=NULL
, "GetShellSecurityDescriptor failed\n");
651 BOOL bHasDacl
= FALSE
, bDefaulted
, ret
;
654 SECURITY_DESCRIPTOR_CONTROL control
;
656 ok(IsValidSecurityDescriptor(psd
), "returned value is not valid SD\n");
658 ret
= GetSecurityDescriptorControl(psd
, &control
, &dwRev
);
659 ok(ret
, "GetSecurityDescriptorControl failed with error %u\n", GetLastError());
660 ok(0 == (control
& SE_SELF_RELATIVE
), "SD should be absolute\n");
662 ret
= GetSecurityDescriptorDacl(psd
, &bHasDacl
, &pAcl
, &bDefaulted
);
663 ok(ret
, "GetSecurityDescriptorDacl failed with error %u\n", GetLastError());
665 ok(bHasDacl
, "SD has no DACL\n");
668 ok(!bDefaulted
, "DACL should not be defaulted\n");
670 ok(pAcl
!= NULL
, "NULL DACL!\n");
673 ACL_SIZE_INFORMATION asiSize
;
675 ok(IsValidAcl(pAcl
), "DACL is not valid\n");
677 ret
= GetAclInformation(pAcl
, &asiSize
, sizeof(asiSize
), AclSizeInformation
);
678 ok(ret
, "GetAclInformation failed with error %u\n", GetLastError());
680 ok(asiSize
.AceCount
== 3, "Incorrect number of ACEs: %d entries\n", asiSize
.AceCount
);
681 if (asiSize
.AceCount
== 3)
683 ACCESS_ALLOWED_ACE
*paaa
; /* will use for DENIED too */
685 ret
= GetAce(pAcl
, 0, (LPVOID
*)&paaa
);
686 ok(ret
, "GetAce failed with error %u\n", GetLastError());
687 ok(paaa
->Header
.AceType
== ACCESS_ALLOWED_ACE_TYPE
,
688 "Invalid ACE type %d\n", paaa
->Header
.AceType
);
689 ok(paaa
->Header
.AceFlags
== 0, "Invalid ACE flags %x\n", paaa
->Header
.AceFlags
);
690 ok(paaa
->Mask
== GENERIC_ALL
, "Invalid ACE mask %x\n", paaa
->Mask
);
692 ret
= GetAce(pAcl
, 1, (LPVOID
*)&paaa
);
693 ok(ret
, "GetAce failed with error %u\n", GetLastError());
694 ok(paaa
->Header
.AceType
== ACCESS_DENIED_ACE_TYPE
,
695 "Invalid ACE type %d\n", paaa
->Header
.AceType
);
696 /* first one of two ACEs generated from inheritable entry - without inheritance */
697 ok(paaa
->Header
.AceFlags
== 0, "Invalid ACE flags %x\n", paaa
->Header
.AceFlags
);
698 ok(paaa
->Mask
== GENERIC_WRITE
, "Invalid ACE mask %x\n", paaa
->Mask
);
700 ret
= GetAce(pAcl
, 2, (LPVOID
*)&paaa
);
701 ok(ret
, "GetAce failed with error %u\n", GetLastError());
702 ok(paaa
->Header
.AceType
== ACCESS_DENIED_ACE_TYPE
,
703 "Invalid ACE type %d\n", paaa
->Header
.AceType
);
704 /* second ACE - with inheritance */
705 ok(paaa
->Header
.AceFlags
== MY_INHERITANCE
,
706 "Invalid ACE flags %x\n", paaa
->Header
.AceFlags
);
707 ok(paaa
->Mask
== GENERIC_READ
, "Invalid ACE mask %x\n", paaa
->Mask
);
716 static void test_SHPackDispParams(void)
722 if(!pSHPackDispParams
)
723 win_skip("SHPackSidpParams not available\n");
725 memset(¶ms
, 0xc0, sizeof(params
));
726 memset(vars
, 0xc0, sizeof(vars
));
727 hres
= pSHPackDispParams(¶ms
, vars
, 1, VT_I4
, 0xdeadbeef);
728 ok(hres
== S_OK
, "SHPackDispParams failed: %08x\n", hres
);
729 ok(params
.cArgs
== 1, "params.cArgs = %d\n", params
.cArgs
);
730 ok(params
.cNamedArgs
== 0, "params.cNamedArgs = %d\n", params
.cArgs
);
731 ok(params
.rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", params
.rgdispidNamedArgs
);
732 ok(params
.rgvarg
== vars
, "params.rgvarg = %p\n", params
.rgvarg
);
733 ok(V_VT(vars
) == VT_I4
, "V_VT(var) = %d\n", V_VT(vars
));
734 ok(V_I4(vars
) == 0xdeadbeef, "failed %x\n", V_I4(vars
));
736 memset(¶ms
, 0xc0, sizeof(params
));
737 hres
= pSHPackDispParams(¶ms
, NULL
, 0, 0);
738 ok(hres
== S_OK
, "SHPackDispParams failed: %08x\n", hres
);
739 ok(params
.cArgs
== 0, "params.cArgs = %d\n", params
.cArgs
);
740 ok(params
.cNamedArgs
== 0, "params.cNamedArgs = %d\n", params
.cArgs
);
741 ok(params
.rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", params
.rgdispidNamedArgs
);
742 ok(params
.rgvarg
== NULL
, "params.rgvarg = %p\n", params
.rgvarg
);
744 memset(vars
, 0xc0, sizeof(vars
));
745 memset(¶ms
, 0xc0, sizeof(params
));
746 hres
= pSHPackDispParams(¶ms
, vars
, 4, VT_BSTR
, (void*)0xdeadbeef, VT_EMPTY
, 10,
747 VT_I4
, 100, VT_DISPATCH
, (void*)0xdeadbeef);
748 ok(hres
== S_OK
, "SHPackDispParams failed: %08x\n", hres
);
749 ok(params
.cArgs
== 4, "params.cArgs = %d\n", params
.cArgs
);
750 ok(params
.cNamedArgs
== 0, "params.cNamedArgs = %d\n", params
.cArgs
);
751 ok(params
.rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", params
.rgdispidNamedArgs
);
752 ok(params
.rgvarg
== vars
, "params.rgvarg = %p\n", params
.rgvarg
);
753 ok(V_VT(vars
) == VT_DISPATCH
, "V_VT(vars[0]) = %x\n", V_VT(vars
));
754 ok(V_I4(vars
) == 0xdeadbeef, "V_I4(vars[0]) = %x\n", V_I4(vars
));
755 ok(V_VT(vars
+1) == VT_I4
, "V_VT(vars[1]) = %d\n", V_VT(vars
+1));
756 ok(V_I4(vars
+1) == 100, "V_I4(vars[1]) = %x\n", V_I4(vars
+1));
757 ok(V_VT(vars
+2) == VT_I4
, "V_VT(vars[2]) = %d\n", V_VT(vars
+2));
758 ok(V_I4(vars
+2) == 10, "V_I4(vars[2]) = %x\n", V_I4(vars
+2));
759 ok(V_VT(vars
+3) == VT_BSTR
, "V_VT(vars[3]) = %d\n", V_VT(vars
+3));
760 ok(V_BSTR(vars
+3) == (void*)0xdeadbeef, "V_BSTR(vars[3]) = %p\n", V_BSTR(vars
+3));
765 IDispatch IDispatch_iface
;
769 static inline Disp
*impl_from_IDispatch(IDispatch
*iface
)
771 return CONTAINING_RECORD(iface
, Disp
, IDispatch_iface
);
774 typedef struct _contain
776 IConnectionPointContainer IConnectionPointContainer_iface
;
780 IConnectionPoint
**pt
;
783 static inline Contain
*impl_from_IConnectionPointContainer(IConnectionPointContainer
*iface
)
785 return CONTAINING_RECORD(iface
, Contain
, IConnectionPointContainer_iface
);
788 typedef struct _cntptn
790 IConnectionPoint IConnectionPoint_iface
;
799 static inline ConPt
*impl_from_IConnectionPoint(IConnectionPoint
*iface
)
801 return CONTAINING_RECORD(iface
, ConPt
, IConnectionPoint_iface
);
806 IEnumConnections IEnumConnections_iface
;
813 static inline EnumCon
*impl_from_IEnumConnections(IEnumConnections
*iface
)
815 return CONTAINING_RECORD(iface
, EnumCon
, IEnumConnections_iface
);
818 typedef struct _enumpt
820 IEnumConnectionPoints IEnumConnectionPoints_iface
;
827 static inline EnumPt
*impl_from_IEnumConnectionPoints(IEnumConnectionPoints
*iface
)
829 return CONTAINING_RECORD(iface
, EnumPt
, IEnumConnectionPoints_iface
);
833 static HRESULT WINAPI
Disp_QueryInterface(
840 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDispatch
))
847 IDispatch_AddRef(This
);
851 trace("no interface\n");
852 return E_NOINTERFACE
;
855 static ULONG WINAPI
Disp_AddRef(IDispatch
* This
)
857 Disp
*iface
= impl_from_IDispatch(This
);
858 return InterlockedIncrement(&iface
->refCount
);
861 static ULONG WINAPI
Disp_Release(IDispatch
* This
)
863 Disp
*iface
= impl_from_IDispatch(This
);
866 ret
= InterlockedDecrement(&iface
->refCount
);
868 HeapFree(GetProcessHeap(),0,This
);
872 static HRESULT WINAPI
Disp_GetTypeInfoCount(
876 return ERROR_SUCCESS
;
879 static HRESULT WINAPI
Disp_GetTypeInfo(
885 return ERROR_SUCCESS
;
888 static HRESULT WINAPI
Disp_GetIDsOfNames(
896 return ERROR_SUCCESS
;
899 static HRESULT WINAPI
Disp_Invoke(
905 DISPPARAMS
*pDispParams
,
907 EXCEPINFO
*pExcepInfo
,
910 trace("%p %x %p %x %x %p %p %p %p\n",This
,dispIdMember
,riid
,lcid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,puArgErr
);
912 ok(dispIdMember
== 0xa0 || dispIdMember
== 0xa1, "Unknown dispIdMember\n");
913 ok(pDispParams
!= NULL
, "Invoked with NULL pDispParams\n");
914 ok(wFlags
== DISPATCH_METHOD
, "Wrong flags %x\n",wFlags
);
915 ok(lcid
== 0,"Wrong lcid %x\n",lcid
);
916 if (dispIdMember
== 0xa0)
918 ok(pDispParams
->cArgs
== 0, "params.cArgs = %d\n", pDispParams
->cArgs
);
919 ok(pDispParams
->cNamedArgs
== 0, "params.cNamedArgs = %d\n", pDispParams
->cArgs
);
920 ok(pDispParams
->rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", pDispParams
->rgdispidNamedArgs
);
921 ok(pDispParams
->rgvarg
== NULL
, "params.rgvarg = %p\n", pDispParams
->rgvarg
);
923 else if (dispIdMember
== 0xa1)
925 ok(pDispParams
->cArgs
== 2, "params.cArgs = %d\n", pDispParams
->cArgs
);
926 ok(pDispParams
->cNamedArgs
== 0, "params.cNamedArgs = %d\n", pDispParams
->cArgs
);
927 ok(pDispParams
->rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", pDispParams
->rgdispidNamedArgs
);
928 ok(V_VT(pDispParams
->rgvarg
) == VT_BSTR
, "V_VT(var) = %d\n", V_VT(pDispParams
->rgvarg
));
929 ok(V_I4(pDispParams
->rgvarg
) == 0xdeadcafe , "failed %p\n", V_BSTR(pDispParams
->rgvarg
));
930 ok(V_VT(pDispParams
->rgvarg
+1) == VT_I4
, "V_VT(var) = %d\n", V_VT(pDispParams
->rgvarg
+1));
931 ok(V_I4(pDispParams
->rgvarg
+1) == 0xdeadbeef, "failed %x\n", V_I4(pDispParams
->rgvarg
+1));
934 return ERROR_SUCCESS
;
937 static const IDispatchVtbl disp_vtbl
= {
942 Disp_GetTypeInfoCount
,
948 static HRESULT WINAPI
Enum_QueryInterface(
949 IEnumConnections
* This
,
955 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IEnumConnections
))
962 IEnumConnections_AddRef(This
);
966 trace("no interface\n");
967 return E_NOINTERFACE
;
970 static ULONG WINAPI
Enum_AddRef(IEnumConnections
* This
)
972 EnumCon
*iface
= impl_from_IEnumConnections(This
);
973 return InterlockedIncrement(&iface
->refCount
);
976 static ULONG WINAPI
Enum_Release(IEnumConnections
* This
)
978 EnumCon
*iface
= impl_from_IEnumConnections(This
);
981 ret
= InterlockedDecrement(&iface
->refCount
);
983 HeapFree(GetProcessHeap(),0,This
);
987 static HRESULT WINAPI
Enum_Next(
988 IEnumConnections
* This
,
993 EnumCon
*iface
= impl_from_IEnumConnections(This
);
995 if (cConnections
> 0 && iface
->idx
< iface
->pt
->sinkCount
)
997 rgcd
->pUnk
= iface
->pt
->sink
[iface
->idx
];
998 IUnknown_AddRef(iface
->pt
->sink
[iface
->idx
]);
1009 static HRESULT WINAPI
Enum_Skip(
1010 IEnumConnections
* This
,
1016 static HRESULT WINAPI
Enum_Reset(
1017 IEnumConnections
* This
)
1022 static HRESULT WINAPI
Enum_Clone(
1023 IEnumConnections
* This
,
1024 IEnumConnections
**ppEnum
)
1029 static const IEnumConnectionsVtbl enum_vtbl
= {
1031 Enum_QueryInterface
,
1040 static HRESULT WINAPI
ConPt_QueryInterface(
1041 IConnectionPoint
* This
,
1047 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IConnectionPoint
))
1054 IConnectionPoint_AddRef(This
);
1058 trace("no interface\n");
1059 return E_NOINTERFACE
;
1062 static ULONG WINAPI
ConPt_AddRef(
1063 IConnectionPoint
* This
)
1065 ConPt
*iface
= impl_from_IConnectionPoint(This
);
1066 return InterlockedIncrement(&iface
->refCount
);
1069 static ULONG WINAPI
ConPt_Release(
1070 IConnectionPoint
* This
)
1072 ConPt
*iface
= impl_from_IConnectionPoint(This
);
1075 ret
= InterlockedDecrement(&iface
->refCount
);
1078 if (iface
->sinkCount
> 0)
1081 for (i
= 0; i
< iface
->sinkCount
; i
++)
1084 IUnknown_Release(iface
->sink
[i
]);
1086 HeapFree(GetProcessHeap(),0,iface
->sink
);
1088 HeapFree(GetProcessHeap(),0,This
);
1093 static HRESULT WINAPI
ConPt_GetConnectionInterface(
1094 IConnectionPoint
* This
,
1098 ConPt
*iface
= impl_from_IConnectionPoint(This
);
1105 memcpy(pIID
,&iface
->id
,sizeof(GUID
));
1109 static HRESULT WINAPI
ConPt_GetConnectionPointContainer(
1110 IConnectionPoint
* This
,
1111 IConnectionPointContainer
**ppCPC
)
1113 ConPt
*iface
= impl_from_IConnectionPoint(This
);
1115 *ppCPC
= &iface
->container
->IConnectionPointContainer_iface
;
1119 static HRESULT WINAPI
ConPt_Advise(
1120 IConnectionPoint
* This
,
1124 ConPt
*iface
= impl_from_IConnectionPoint(This
);
1126 if (iface
->sinkCount
== 0)
1127 iface
->sink
= HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown
*));
1129 iface
->sink
= HeapReAlloc(GetProcessHeap(),0,iface
->sink
,sizeof(IUnknown
*)*(iface
->sinkCount
+1));
1130 iface
->sink
[iface
->sinkCount
] = pUnkSink
;
1131 IUnknown_AddRef(pUnkSink
);
1133 *pdwCookie
= iface
->sinkCount
;
1137 static HRESULT WINAPI
ConPt_Unadvise(
1138 IConnectionPoint
* This
,
1141 ConPt
*iface
= impl_from_IConnectionPoint(This
);
1143 if (dwCookie
> iface
->sinkCount
)
1147 IUnknown_Release(iface
->sink
[dwCookie
-1]);
1148 iface
->sink
[dwCookie
-1] = NULL
;
1153 static HRESULT WINAPI
ConPt_EnumConnections(
1154 IConnectionPoint
* This
,
1155 IEnumConnections
**ppEnum
)
1159 ec
= HeapAlloc(GetProcessHeap(),0,sizeof(EnumCon
));
1160 ec
->IEnumConnections_iface
.lpVtbl
= &enum_vtbl
;
1162 ec
->pt
= impl_from_IConnectionPoint(This
);
1164 *ppEnum
= &ec
->IEnumConnections_iface
;
1169 static const IConnectionPointVtbl point_vtbl
= {
1170 ConPt_QueryInterface
,
1174 ConPt_GetConnectionInterface
,
1175 ConPt_GetConnectionPointContainer
,
1178 ConPt_EnumConnections
1181 static HRESULT WINAPI
EnumPt_QueryInterface(
1182 IEnumConnectionPoints
* This
,
1188 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IEnumConnectionPoints
))
1195 IEnumConnectionPoints_AddRef(This
);
1199 trace("no interface\n");
1200 return E_NOINTERFACE
;
1203 static ULONG WINAPI
EnumPt_AddRef(IEnumConnectionPoints
* This
)
1205 EnumPt
*iface
= impl_from_IEnumConnectionPoints(This
);
1206 return InterlockedIncrement(&iface
->refCount
);
1209 static ULONG WINAPI
EnumPt_Release(IEnumConnectionPoints
* This
)
1211 EnumPt
*iface
= impl_from_IEnumConnectionPoints(This
);
1214 ret
= InterlockedDecrement(&iface
->refCount
);
1216 HeapFree(GetProcessHeap(),0,This
);
1220 static HRESULT WINAPI
EnumPt_Next(
1221 IEnumConnectionPoints
* This
,
1223 IConnectionPoint
**rgcd
,
1226 EnumPt
*iface
= impl_from_IEnumConnectionPoints(This
);
1228 if (cConnections
> 0 && iface
->idx
< iface
->container
->ptCount
)
1230 *rgcd
= iface
->container
->pt
[iface
->idx
];
1231 IConnectionPoint_AddRef(iface
->container
->pt
[iface
->idx
]);
1241 static HRESULT WINAPI
EnumPt_Skip(
1242 IEnumConnectionPoints
* This
,
1248 static HRESULT WINAPI
EnumPt_Reset(
1249 IEnumConnectionPoints
* This
)
1254 static HRESULT WINAPI
EnumPt_Clone(
1255 IEnumConnectionPoints
* This
,
1256 IEnumConnectionPoints
**ppEnumPt
)
1261 static const IEnumConnectionPointsVtbl enumpt_vtbl
= {
1263 EnumPt_QueryInterface
,
1272 static HRESULT WINAPI
Contain_QueryInterface(
1273 IConnectionPointContainer
* This
,
1279 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IConnectionPointContainer
))
1286 IConnectionPointContainer_AddRef(This
);
1290 trace("no interface\n");
1291 return E_NOINTERFACE
;
1294 static ULONG WINAPI
Contain_AddRef(
1295 IConnectionPointContainer
* This
)
1297 Contain
*iface
= impl_from_IConnectionPointContainer(This
);
1298 return InterlockedIncrement(&iface
->refCount
);
1301 static ULONG WINAPI
Contain_Release(
1302 IConnectionPointContainer
* This
)
1304 Contain
*iface
= impl_from_IConnectionPointContainer(This
);
1307 ret
= InterlockedDecrement(&iface
->refCount
);
1310 if (iface
->ptCount
> 0)
1313 for (i
= 0; i
< iface
->ptCount
; i
++)
1314 IConnectionPoint_Release(iface
->pt
[i
]);
1315 HeapFree(GetProcessHeap(),0,iface
->pt
);
1317 HeapFree(GetProcessHeap(),0,This
);
1322 static HRESULT WINAPI
Contain_EnumConnectionPoints(
1323 IConnectionPointContainer
* This
,
1324 IEnumConnectionPoints
**ppEnum
)
1328 ec
= HeapAlloc(GetProcessHeap(),0,sizeof(EnumPt
));
1329 ec
->IEnumConnectionPoints_iface
.lpVtbl
= &enumpt_vtbl
;
1332 ec
->container
= impl_from_IConnectionPointContainer(This
);
1333 *ppEnum
= &ec
->IEnumConnectionPoints_iface
;
1338 static HRESULT WINAPI
Contain_FindConnectionPoint(
1339 IConnectionPointContainer
* This
,
1341 IConnectionPoint
**ppCP
)
1343 Contain
*iface
= impl_from_IConnectionPointContainer(This
);
1346 if (!IsEqualIID(riid
, &IID_NULL
) || iface
->ptCount
==0)
1348 pt
= HeapAlloc(GetProcessHeap(),0,sizeof(ConPt
));
1349 pt
->IConnectionPoint_iface
.lpVtbl
= &point_vtbl
;
1353 pt
->container
= iface
;
1354 pt
->id
= IID_IDispatch
;
1356 if (iface
->ptCount
== 0)
1357 iface
->pt
=HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown
*));
1359 iface
->pt
= HeapReAlloc(GetProcessHeap(),0,iface
->pt
,sizeof(IUnknown
*)*(iface
->ptCount
+1));
1360 iface
->pt
[iface
->ptCount
] = &pt
->IConnectionPoint_iface
;
1363 *ppCP
= &pt
->IConnectionPoint_iface
;
1367 *ppCP
= iface
->pt
[0];
1368 IUnknown_AddRef((IUnknown
*)*ppCP
);
1374 static const IConnectionPointContainerVtbl contain_vtbl
= {
1375 Contain_QueryInterface
,
1379 Contain_EnumConnectionPoints
,
1380 Contain_FindConnectionPoint
1383 static void test_IConnectionPoint(void)
1387 IConnectionPoint
*point
;
1390 DWORD cookie
= 0xffffffff;
1394 if (!pIConnectionPoint_SimpleInvoke
|| !pConnectToConnectionPoint
)
1396 win_skip("IConnectionPoint Apis not present\n");
1400 container
= HeapAlloc(GetProcessHeap(),0,sizeof(Contain
));
1401 container
->IConnectionPointContainer_iface
.lpVtbl
= &contain_vtbl
;
1402 container
->refCount
= 1;
1403 container
->ptCount
= 0;
1404 container
->pt
= NULL
;
1406 dispatch
= HeapAlloc(GetProcessHeap(),0,sizeof(Disp
));
1407 dispatch
->IDispatch_iface
.lpVtbl
= &disp_vtbl
;
1408 dispatch
->refCount
= 1;
1410 rc
= pConnectToConnectionPoint((IUnknown
*)dispatch
, &IID_NULL
, TRUE
, (IUnknown
*)container
, &cookie
, &point
);
1411 ok(rc
== S_OK
, "pConnectToConnectionPoint failed with %x\n",rc
);
1412 ok(point
!= NULL
, "returned ConnectionPoint is NULL\n");
1413 ok(cookie
!= 0xffffffff, "invalid cookie returned\n");
1415 rc
= pIConnectionPoint_SimpleInvoke(point
,0xa0,NULL
);
1416 ok(rc
== S_OK
, "pConnectToConnectionPoint failed with %x\n",rc
);
1418 if (pSHPackDispParams
)
1420 memset(¶ms
, 0xc0, sizeof(params
));
1421 memset(vars
, 0xc0, sizeof(vars
));
1422 rc
= pSHPackDispParams(¶ms
, vars
, 2, VT_I4
, 0xdeadbeef, VT_BSTR
, 0xdeadcafe);
1423 ok(rc
== S_OK
, "SHPackDispParams failed: %08x\n", rc
);
1425 rc
= pIConnectionPoint_SimpleInvoke(point
,0xa1,¶ms
);
1426 ok(rc
== S_OK
, "pConnectToConnectionPoint failed with %x\n",rc
);
1429 win_skip("pSHPackDispParams not present\n");
1431 rc
= pConnectToConnectionPoint(NULL
, &IID_NULL
, FALSE
, (IUnknown
*)container
, &cookie
, NULL
);
1432 ok(rc
== S_OK
, "pConnectToConnectionPoint failed with %x\n",rc
);
1434 /* MSDN says this should be required but it crashs on XP
1435 IUnknown_Release(point);
1437 ref
= IUnknown_Release((IUnknown
*)container
);
1438 ok(ref
== 0, "leftover IConnectionPointContainer reference %i\n",ref
);
1439 ref
= IUnknown_Release((IUnknown
*)dispatch
);
1440 ok(ref
== 0, "leftover IDispatch reference %i\n",ref
);
1443 typedef struct _propbag
1445 IPropertyBag IPropertyBag_iface
;
1450 static inline PropBag
*impl_from_IPropertyBag(IPropertyBag
*iface
)
1452 return CONTAINING_RECORD(iface
, PropBag
, IPropertyBag_iface
);
1456 static HRESULT WINAPI
Prop_QueryInterface(
1463 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IPropertyBag
))
1470 IPropertyBag_AddRef(This
);
1474 trace("no interface\n");
1475 return E_NOINTERFACE
;
1478 static ULONG WINAPI
Prop_AddRef(
1481 PropBag
*iface
= impl_from_IPropertyBag(This
);
1482 return InterlockedIncrement(&iface
->refCount
);
1485 static ULONG WINAPI
Prop_Release(
1488 PropBag
*iface
= impl_from_IPropertyBag(This
);
1491 ret
= InterlockedDecrement(&iface
->refCount
);
1493 HeapFree(GetProcessHeap(),0,This
);
1497 static HRESULT WINAPI
Prop_Read(
1499 LPCOLESTR pszPropName
,
1501 IErrorLog
*pErrorLog
)
1503 V_VT(pVar
) = VT_BLOB
|VT_BYREF
;
1504 V_BYREF(pVar
) = (LPVOID
)0xdeadcafe;
1508 static HRESULT WINAPI
Prop_Write(
1510 LPCOLESTR pszPropName
,
1517 static const IPropertyBagVtbl prop_vtbl
= {
1518 Prop_QueryInterface
,
1526 static void test_SHPropertyBag_ReadLONG(void)
1531 static const WCHAR szName1
[] = {'n','a','m','e','1',0};
1533 if (!pSHPropertyBag_ReadLONG
)
1535 win_skip("SHPropertyBag_ReadLONG not present\n");
1539 pb
= HeapAlloc(GetProcessHeap(),0,sizeof(PropBag
));
1541 pb
->IPropertyBag_iface
.lpVtbl
= &prop_vtbl
;
1544 rc
= pSHPropertyBag_ReadLONG(NULL
, szName1
, &out
);
1545 ok(rc
== E_INVALIDARG
|| broken(rc
== 0), "incorrect return %x\n",rc
);
1546 ok(out
== 0xfeedface, "value should not have changed\n");
1547 rc
= pSHPropertyBag_ReadLONG(&pb
->IPropertyBag_iface
, NULL
, &out
);
1548 ok(rc
== E_INVALIDARG
|| broken(rc
== 0) || broken(rc
== 1), "incorrect return %x\n",rc
);
1549 ok(out
== 0xfeedface, "value should not have changed\n");
1550 rc
= pSHPropertyBag_ReadLONG(&pb
->IPropertyBag_iface
, szName1
, NULL
);
1551 ok(rc
== E_INVALIDARG
|| broken(rc
== 0) || broken(rc
== 1), "incorrect return %x\n",rc
);
1552 rc
= pSHPropertyBag_ReadLONG(&pb
->IPropertyBag_iface
, szName1
, &out
);
1553 ok(rc
== DISP_E_BADVARTYPE
|| broken(rc
== 0) || broken(rc
== 1), "incorrect return %x\n",rc
);
1554 ok(out
== 0xfeedface || broken(out
== 0xfeedfa00), "value should not have changed %x\n",out
);
1555 IUnknown_Release((IUnknown
*)pb
);
1560 static void test_SHSetWindowBits(void)
1563 DWORD style
, styleold
;
1566 if(!pSHSetWindowBits
)
1568 win_skip("SHSetWindowBits is not available\n");
1573 clsA
.lpfnWndProc
= DefWindowProcA
;
1574 clsA
.cbClsExtra
= 0;
1575 clsA
.cbWndExtra
= 0;
1576 clsA
.hInstance
= GetModuleHandleA(NULL
);
1578 clsA
.hCursor
= LoadCursorA(0, (LPSTR
)IDC_ARROW
);
1579 clsA
.hbrBackground
= NULL
;
1580 clsA
.lpszMenuName
= NULL
;
1581 clsA
.lpszClassName
= "Shlwapi test class";
1582 RegisterClassA(&clsA
);
1584 hwnd
= CreateWindowA("Shlwapi test class", "Test", WS_VISIBLE
, 0, 0, 100, 100,
1585 NULL
, NULL
, GetModuleHandleA(NULL
), 0);
1586 ok(IsWindow(hwnd
), "failed to create window\n");
1589 SetLastError(0xdeadbeef);
1590 style
= pSHSetWindowBits(NULL
, GWL_STYLE
, 0, 0);
1591 ok(style
== 0, "expected 0 retval, got %d\n", style
);
1592 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
||
1593 broken(GetLastError() == 0xdeadbeef), /* Win9x/WinMe */
1594 "expected ERROR_INVALID_WINDOW_HANDLE, got %d\n", GetLastError());
1596 /* zero mask, zero flags */
1597 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1598 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, 0, 0);
1599 ok(styleold
== style
, "expected old style\n");
1600 ok(styleold
== GetWindowLongA(hwnd
, GWL_STYLE
), "expected to keep old style\n");
1603 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1604 ok(styleold
& WS_VISIBLE
, "expected WS_VISIBLE\n");
1605 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, WS_VISIBLE
, 0);
1607 ok(style
== styleold
, "expected previous style, got %x\n", style
);
1608 ok((GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
) == 0, "expected updated style\n");
1610 /* test mask, unset style bit used */
1611 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1612 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, WS_VISIBLE
, 0);
1613 ok(style
== styleold
, "expected previous style, got %x\n", style
);
1614 ok(styleold
== GetWindowLongA(hwnd
, GWL_STYLE
), "expected to keep old style\n");
1616 /* set back with flags */
1617 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1618 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, WS_VISIBLE
, WS_VISIBLE
);
1619 ok(style
== styleold
, "expected previous style, got %x\n", style
);
1620 ok(GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
, "expected updated style\n");
1622 /* reset and try to set without a mask */
1623 pSHSetWindowBits(hwnd
, GWL_STYLE
, WS_VISIBLE
, 0);
1624 ok((GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
) == 0, "expected updated style\n");
1625 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1626 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, 0, WS_VISIBLE
);
1627 ok(style
== styleold
, "expected previous style, got %x\n", style
);
1628 ok((GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
) == 0, "expected updated style\n");
1630 DestroyWindow(hwnd
);
1632 UnregisterClassA("Shlwapi test class", GetModuleHandleA(NULL
));
1635 static void test_SHFormatDateTimeA(void)
1637 FILETIME UNALIGNED filetime
;
1638 CHAR buff
[100], buff2
[100], buff3
[100];
1643 if(!pSHFormatDateTimeA
)
1645 win_skip("pSHFormatDateTimeA isn't available\n");
1651 /* crashes on native */
1652 pSHFormatDateTimeA(NULL
, NULL
, NULL
, 0);
1656 SystemTimeToFileTime(&st
, &filetime
);
1657 /* SHFormatDateTime expects input as utc */
1658 LocalFileTimeToFileTime(&filetime
, &filetime
);
1660 /* no way to get required buffer length here */
1661 SetLastError(0xdeadbeef);
1662 ret
= pSHFormatDateTimeA(&filetime
, NULL
, NULL
, 0);
1663 ok(ret
== 0, "got %d\n", ret
);
1664 ok(GetLastError() == 0xdeadbeef || broken(GetLastError() == ERROR_SUCCESS
/* Win7 */),
1665 "expected 0xdeadbeef, got %d\n", GetLastError());
1667 SetLastError(0xdeadbeef);
1668 buff
[0] = 'a'; buff
[1] = 0;
1669 ret
= pSHFormatDateTimeA(&filetime
, NULL
, buff
, 0);
1670 ok(ret
== 0, "got %d\n", ret
);
1671 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1672 ok(buff
[0] == 'a', "expected same string, got %s\n", buff
);
1674 /* flags needs to have FDTF_NOAUTOREADINGORDER for these tests to succeed on Vista+ */
1676 /* all combinations documented as invalid succeeded */
1677 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTTIME
| FDTF_LONGTIME
;
1678 SetLastError(0xdeadbeef);
1679 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1680 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1681 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1683 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTDATE
| FDTF_LONGDATE
;
1684 SetLastError(0xdeadbeef);
1685 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1686 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1687 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1689 flags
= FDTF_SHORTDATE
| FDTF_LTRDATE
| FDTF_RTLDATE
;
1690 SetLastError(0xdeadbeef);
1691 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1692 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1693 ok(GetLastError() == 0xdeadbeef ||
1694 broken(GetLastError() == ERROR_INVALID_FLAGS
), /* Win9x/WinMe */
1695 "expected 0xdeadbeef, got %d\n", GetLastError());
1697 /* now check returned strings */
1698 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTTIME
;
1699 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1700 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1701 ret
= GetTimeFormatA(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff2
, sizeof(buff2
));
1702 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1703 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1705 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGTIME
;
1706 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1707 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1708 ret
= GetTimeFormatA(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff2
, sizeof(buff2
));
1709 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1710 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1712 /* both time flags */
1713 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGTIME
| FDTF_SHORTTIME
;
1714 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1715 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1716 ret
= GetTimeFormatA(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff2
, sizeof(buff2
));
1717 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1718 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1720 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTDATE
;
1721 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1722 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1723 ret
= GetDateFormatA(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1724 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1725 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1727 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGDATE
;
1728 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1729 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1730 ret
= GetDateFormatA(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1731 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1732 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1734 /* both date flags */
1735 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGDATE
| FDTF_SHORTDATE
;
1736 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1737 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1738 ret
= GetDateFormatA(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1739 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1740 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1742 /* various combinations of date/time flags */
1743 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGDATE
| FDTF_SHORTTIME
;
1744 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1745 ok(ret
== lstrlenA(buff
)+1, "got %d, length %d\n", ret
, lstrlenA(buff
)+1);
1746 ret
= GetTimeFormatA(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff3
, sizeof(buff3
));
1747 ok(ret
== lstrlenA(buff3
)+1, "got %d\n", ret
);
1748 ok(lstrcmpA(buff3
, buff
+ lstrlenA(buff
) - lstrlenA(buff3
)) == 0,
1749 "expected (%s), got (%s) for time part\n",
1750 buff3
, buff
+ lstrlenA(buff
) - lstrlenA(buff3
));
1751 ret
= GetDateFormatA(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1752 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1753 buff
[lstrlenA(buff2
)] = '\0';
1754 ok(lstrcmpA(buff2
, buff
) == 0, "expected (%s) got (%s) for date part\n",
1757 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGDATE
| FDTF_LONGTIME
;
1758 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1759 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1760 ret
= GetTimeFormatA(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff3
, sizeof(buff3
));
1761 ok(ret
== lstrlenA(buff3
)+1, "got %d\n", ret
);
1762 ok(lstrcmpA(buff3
, buff
+ lstrlenA(buff
) - lstrlenA(buff3
)) == 0,
1763 "expected (%s), got (%s) for time part\n",
1764 buff3
, buff
+ lstrlenA(buff
) - lstrlenA(buff3
));
1765 ret
= GetDateFormatA(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1766 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1767 buff
[lstrlenA(buff2
)] = '\0';
1768 ok(lstrcmpA(buff2
, buff
) == 0, "expected (%s) got (%s) for date part\n",
1771 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTDATE
| FDTF_SHORTTIME
;
1772 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1773 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1774 ret
= GetDateFormatA(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1775 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1777 ret
= GetTimeFormatA(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &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
);
1782 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTDATE
| FDTF_LONGTIME
;
1783 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1784 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1785 ret
= GetDateFormatA(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1786 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1788 ret
= GetTimeFormatA(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff3
, sizeof(buff3
));
1789 ok(ret
== lstrlenA(buff3
)+1, "got %d\n", ret
);
1790 strcat(buff2
, buff3
);
1791 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1794 static void test_SHFormatDateTimeW(void)
1796 FILETIME UNALIGNED filetime
;
1797 WCHAR buff
[100], buff2
[100], buff3
[100], *p1
, *p2
;
1801 static const WCHAR spaceW
[] = {' ',0};
1802 #define UNICODE_LTR_MARK 0x200e
1803 #define UNICODE_RTL_MARK 0x200f
1805 if(!pSHFormatDateTimeW
)
1807 win_skip("pSHFormatDateTimeW isn't available\n");
1813 /* crashes on native */
1814 pSHFormatDateTimeW(NULL
, NULL
, NULL
, 0);
1818 SystemTimeToFileTime(&st
, &filetime
);
1819 /* SHFormatDateTime expects input as utc */
1820 LocalFileTimeToFileTime(&filetime
, &filetime
);
1822 /* no way to get required buffer length here */
1823 SetLastError(0xdeadbeef);
1824 ret
= pSHFormatDateTimeW(&filetime
, NULL
, NULL
, 0);
1825 ok(ret
== 0, "expected 0, got %d\n", ret
);
1826 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1828 SetLastError(0xdeadbeef);
1829 buff
[0] = 'a'; buff
[1] = 0;
1830 ret
= pSHFormatDateTimeW(&filetime
, NULL
, buff
, 0);
1831 ok(ret
== 0, "expected 0, got %d\n", ret
);
1832 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1833 ok(buff
[0] == 'a', "expected same string\n");
1835 /* all combinations documented as invalid succeeded */
1836 flags
= FDTF_SHORTTIME
| FDTF_LONGTIME
;
1837 SetLastError(0xdeadbeef);
1838 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1839 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1840 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1841 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1843 flags
= FDTF_SHORTDATE
| FDTF_LONGDATE
;
1844 SetLastError(0xdeadbeef);
1845 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1846 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1847 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1848 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1850 flags
= FDTF_SHORTDATE
| FDTF_LTRDATE
| FDTF_RTLDATE
;
1851 SetLastError(0xdeadbeef);
1852 buff
[0] = 0; /* NT4 doesn't clear the buffer on failure */
1853 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1854 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1855 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1856 ok(GetLastError() == 0xdeadbeef ||
1857 broken(GetLastError() == ERROR_INVALID_FLAGS
), /* Win9x/WinMe/NT4 */
1858 "expected 0xdeadbeef, got %d\n", GetLastError());
1860 /* now check returned strings */
1861 flags
= FDTF_SHORTTIME
;
1862 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1863 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1864 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1865 SetLastError(0xdeadbeef);
1866 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1867 if (ret
== 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
1869 win_skip("Needed W-functions are not implemented\n");
1872 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1873 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1875 flags
= FDTF_LONGTIME
;
1876 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1877 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1878 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1879 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1880 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1881 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1883 /* both time flags */
1884 flags
= FDTF_LONGTIME
| FDTF_SHORTTIME
;
1885 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1886 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1887 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1888 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1889 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1890 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal string\n");
1892 flags
= FDTF_SHORTDATE
;
1893 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1894 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1895 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1896 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1897 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1898 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1900 flags
= FDTF_LONGDATE
;
1901 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1902 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1903 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1904 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1905 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1906 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1908 /* both date flags */
1909 flags
= FDTF_LONGDATE
| FDTF_SHORTDATE
;
1910 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1911 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1912 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1913 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1914 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1915 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1917 /* various combinations of date/time flags */
1918 flags
= FDTF_LONGDATE
| FDTF_SHORTTIME
;
1919 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1920 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1921 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1922 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff3
, sizeof(buff3
)/sizeof(WCHAR
));
1923 ok(ret
== lstrlenW(buff3
)+1, "expected %d, got %d\n", lstrlenW(buff3
)+1, ret
);
1924 ok(lstrcmpW(buff3
, buff
+ lstrlenW(buff
) - lstrlenW(buff3
)) == 0,
1925 "expected (%s), got (%s) for time part\n",
1926 wine_dbgstr_w(buff3
), wine_dbgstr_w(buff
+ lstrlenW(buff
) - lstrlenW(buff3
)));
1927 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1928 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1933 while (*p1
== UNICODE_LTR_MARK
|| *p1
== UNICODE_RTL_MARK
)
1935 while (*p2
== UNICODE_LTR_MARK
|| *p2
== UNICODE_RTL_MARK
)
1941 ok(lstrcmpW(buff2
, buff
) == 0, "expected (%s) got (%s) for date part\n",
1942 wine_dbgstr_w(buff2
), wine_dbgstr_w(buff
));
1944 flags
= FDTF_LONGDATE
| FDTF_LONGTIME
;
1945 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1946 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1947 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1948 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff3
, sizeof(buff3
)/sizeof(WCHAR
));
1949 ok(ret
== lstrlenW(buff3
)+1, "expected %d, got %d\n", lstrlenW(buff3
)+1, ret
);
1950 ok(lstrcmpW(buff3
, buff
+ lstrlenW(buff
) - lstrlenW(buff3
)) == 0,
1951 "expected (%s), got (%s) for time part\n",
1952 wine_dbgstr_w(buff3
), wine_dbgstr_w(buff
+ lstrlenW(buff
) - lstrlenW(buff3
)));
1953 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1954 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1959 while (*p1
== UNICODE_LTR_MARK
|| *p1
== UNICODE_RTL_MARK
)
1961 while (*p2
== UNICODE_LTR_MARK
|| *p2
== UNICODE_RTL_MARK
)
1967 ok(lstrcmpW(buff2
, buff
) == 0, "expected (%s) got (%s) for date part\n",
1968 wine_dbgstr_w(buff2
), wine_dbgstr_w(buff
));
1970 flags
= FDTF_SHORTDATE
| FDTF_SHORTTIME
;
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
, TIME_NOSECONDS
, &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");
1982 flags
= FDTF_SHORTDATE
| FDTF_LONGTIME
;
1983 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1984 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1985 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1986 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1987 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1988 lstrcatW(buff2
, spaceW
);
1989 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff3
, sizeof(buff3
)/sizeof(WCHAR
));
1990 ok(ret
== lstrlenW(buff3
)+1, "expected %d, got %d\n", lstrlenW(buff3
)+1, ret
);
1991 lstrcatW(buff2
, buff3
);
1992 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1995 static void test_SHGetObjectCompatFlags(void)
1997 struct compat_value
{
2002 struct compat_value values
[] = {
2003 { "OTNEEDSSFCACHE", 0x1 },
2004 { "NO_WEBVIEW", 0x2 },
2005 { "UNBINDABLE", 0x4 },
2007 { "NEEDSFILESYSANCESTOR", 0x10 },
2008 { "NOTAFILESYSTEM", 0x20 },
2009 { "CTXMENU_NOVERBS", 0x40 },
2010 { "CTXMENU_LIMITEDQI", 0x80 },
2011 { "COCREATESHELLFOLDERONLY", 0x100 },
2012 { "NEEDSSTORAGEANCESTOR", 0x200 },
2013 { "NOLEGACYWEBVIEW", 0x400 },
2014 { "CTXMENU_XPQCMFLAGS", 0x1000 },
2015 { "NOIPROPERTYSTORE", 0x2000 }
2018 static const char compat_path
[] = "Software\\Microsoft\\Windows\\CurrentVersion\\ShellCompatibility\\Objects";
2019 void *pColorAdjustLuma
= GetProcAddress(hShlwapi
, "ColorAdjustLuma");
2020 CHAR keyA
[39]; /* {CLSID} */
2025 if (!pSHGetObjectCompatFlags
)
2027 win_skip("SHGetObjectCompatFlags isn't available\n");
2031 if (pColorAdjustLuma
&& pColorAdjustLuma
== pSHGetObjectCompatFlags
) /* win2k */
2033 win_skip("Skipping SHGetObjectCompatFlags, same ordinal used for ColorAdjustLuma\n");
2038 ret
= pSHGetObjectCompatFlags(NULL
, NULL
);
2039 ok(ret
== 0, "got %d\n", ret
);
2041 ret
= RegOpenKeyA(HKEY_LOCAL_MACHINE
, compat_path
, &root
);
2042 if (ret
!= ERROR_SUCCESS
)
2044 skip("No compatibility class data found\n");
2048 for (i
= 0; RegEnumKeyA(root
, i
, keyA
, sizeof(keyA
)) == ERROR_SUCCESS
; i
++)
2052 if (RegOpenKeyA(root
, keyA
, &clsid_key
) == ERROR_SUCCESS
)
2055 DWORD expected
= 0, got
, length
= sizeof(valueA
);
2059 for (v
= 0; RegEnumValueA(clsid_key
, v
, valueA
, &length
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
; v
++)
2063 for (j
= 0; j
< sizeof(values
)/sizeof(struct compat_value
); j
++)
2064 if (lstrcmpA(values
[j
].nameA
, valueA
) == 0)
2066 expected
|= values
[j
].value
;
2070 length
= sizeof(valueA
);
2073 pGUIDFromStringA(keyA
, &clsid
);
2074 got
= pSHGetObjectCompatFlags(NULL
, &clsid
);
2075 ok(got
== expected
, "got 0x%08x, expected 0x%08x. Key %s\n", got
, expected
, keyA
);
2077 RegCloseKey(clsid_key
);
2085 IOleCommandTarget IOleCommandTarget_iface
;
2087 } IOleCommandTargetImpl
;
2089 static inline IOleCommandTargetImpl
*impl_from_IOleCommandTarget(IOleCommandTarget
*iface
)
2091 return CONTAINING_RECORD(iface
, IOleCommandTargetImpl
, IOleCommandTarget_iface
);
2094 static const IOleCommandTargetVtbl IOleCommandTargetImpl_Vtbl
;
2096 static IOleCommandTarget
* IOleCommandTargetImpl_Construct(void)
2098 IOleCommandTargetImpl
*obj
;
2100 obj
= HeapAlloc(GetProcessHeap(), 0, sizeof(*obj
));
2101 obj
->IOleCommandTarget_iface
.lpVtbl
= &IOleCommandTargetImpl_Vtbl
;
2104 return &obj
->IOleCommandTarget_iface
;
2107 static HRESULT WINAPI
IOleCommandTargetImpl_QueryInterface(IOleCommandTarget
*iface
, REFIID riid
, void **ppvObj
)
2109 IOleCommandTargetImpl
*This
= impl_from_IOleCommandTarget(iface
);
2111 if (IsEqualIID(riid
, &IID_IUnknown
) ||
2112 IsEqualIID(riid
, &IID_IOleCommandTarget
))
2119 IOleCommandTarget_AddRef(iface
);
2123 return E_NOINTERFACE
;
2126 static ULONG WINAPI
IOleCommandTargetImpl_AddRef(IOleCommandTarget
*iface
)
2128 IOleCommandTargetImpl
*This
= impl_from_IOleCommandTarget(iface
);
2129 return InterlockedIncrement(&This
->ref
);
2132 static ULONG WINAPI
IOleCommandTargetImpl_Release(IOleCommandTarget
*iface
)
2134 IOleCommandTargetImpl
*This
= impl_from_IOleCommandTarget(iface
);
2135 ULONG ref
= InterlockedDecrement(&This
->ref
);
2139 HeapFree(GetProcessHeap(), 0, This
);
2145 static HRESULT WINAPI
IOleCommandTargetImpl_QueryStatus(
2146 IOleCommandTarget
*iface
, const GUID
*group
, ULONG cCmds
, OLECMD prgCmds
[], OLECMDTEXT
*pCmdText
)
2151 static HRESULT WINAPI
IOleCommandTargetImpl_Exec(
2152 IOleCommandTarget
*iface
,
2153 const GUID
*CmdGroup
,
2159 add_call(&trace_got
, 3, CmdGroup
, (void*)(DWORD_PTR
)nCmdID
, (void*)(DWORD_PTR
)nCmdexecopt
, pvaIn
, pvaOut
);
2163 static const IOleCommandTargetVtbl IOleCommandTargetImpl_Vtbl
=
2165 IOleCommandTargetImpl_QueryInterface
,
2166 IOleCommandTargetImpl_AddRef
,
2167 IOleCommandTargetImpl_Release
,
2168 IOleCommandTargetImpl_QueryStatus
,
2169 IOleCommandTargetImpl_Exec
2173 IServiceProvider IServiceProvider_iface
;
2175 } IServiceProviderImpl
;
2177 static inline IServiceProviderImpl
*impl_from_IServiceProvider(IServiceProvider
*iface
)
2179 return CONTAINING_RECORD(iface
, IServiceProviderImpl
, IServiceProvider_iface
);
2183 IProfferService IProfferService_iface
;
2185 } IProfferServiceImpl
;
2187 static inline IProfferServiceImpl
*impl_from_IProfferService(IProfferService
*iface
)
2189 return CONTAINING_RECORD(iface
, IProfferServiceImpl
, IProfferService_iface
);
2193 static const IServiceProviderVtbl IServiceProviderImpl_Vtbl
;
2194 static const IProfferServiceVtbl IProfferServiceImpl_Vtbl
;
2196 static IServiceProvider
* IServiceProviderImpl_Construct(void)
2198 IServiceProviderImpl
*obj
;
2200 obj
= HeapAlloc(GetProcessHeap(), 0, sizeof(*obj
));
2201 obj
->IServiceProvider_iface
.lpVtbl
= &IServiceProviderImpl_Vtbl
;
2204 return &obj
->IServiceProvider_iface
;
2207 static IProfferService
* IProfferServiceImpl_Construct(void)
2209 IProfferServiceImpl
*obj
;
2211 obj
= HeapAlloc(GetProcessHeap(), 0, sizeof(*obj
));
2212 obj
->IProfferService_iface
.lpVtbl
= &IProfferServiceImpl_Vtbl
;
2215 return &obj
->IProfferService_iface
;
2218 static HRESULT WINAPI
IServiceProviderImpl_QueryInterface(IServiceProvider
*iface
, REFIID riid
, void **ppvObj
)
2220 IServiceProviderImpl
*This
= impl_from_IServiceProvider(iface
);
2222 if (IsEqualIID(riid
, &IID_IUnknown
) ||
2223 IsEqualIID(riid
, &IID_IServiceProvider
))
2230 IServiceProvider_AddRef(iface
);
2231 /* native uses redefined IID_IServiceProvider symbol, so we can't compare pointers */
2232 if (IsEqualIID(riid
, &IID_IServiceProvider
))
2233 add_call(&trace_got
, 1, iface
, &IID_IServiceProvider
, 0, 0, 0);
2237 return E_NOINTERFACE
;
2240 static ULONG WINAPI
IServiceProviderImpl_AddRef(IServiceProvider
*iface
)
2242 IServiceProviderImpl
*This
= impl_from_IServiceProvider(iface
);
2243 return InterlockedIncrement(&This
->ref
);
2246 static ULONG WINAPI
IServiceProviderImpl_Release(IServiceProvider
*iface
)
2248 IServiceProviderImpl
*This
= impl_from_IServiceProvider(iface
);
2249 ULONG ref
= InterlockedDecrement(&This
->ref
);
2253 HeapFree(GetProcessHeap(), 0, This
);
2259 static HRESULT WINAPI
IServiceProviderImpl_QueryService(
2260 IServiceProvider
*iface
, REFGUID service
, REFIID riid
, void **ppv
)
2262 /* native uses redefined pointer for IID_IOleCommandTarget, not one from uuid.lib */
2263 if (IsEqualIID(riid
, &IID_IOleCommandTarget
))
2265 add_call(&trace_got
, 2, iface
, service
, &IID_IOleCommandTarget
, 0, 0);
2266 *ppv
= IOleCommandTargetImpl_Construct();
2268 if (IsEqualIID(riid
, &IID_IProfferService
))
2270 if (IsEqualIID(service
, &IID_IProfferService
))
2271 add_call(&trace_got
, 2, &IID_IProfferService
, &IID_IProfferService
, 0, 0, 0);
2272 *ppv
= IProfferServiceImpl_Construct();
2277 static const IServiceProviderVtbl IServiceProviderImpl_Vtbl
=
2279 IServiceProviderImpl_QueryInterface
,
2280 IServiceProviderImpl_AddRef
,
2281 IServiceProviderImpl_Release
,
2282 IServiceProviderImpl_QueryService
2285 static void test_IUnknown_QueryServiceExec(void)
2287 IServiceProvider
*provider
;
2288 static const GUID dummy_serviceid
= { 0xdeadbeef };
2289 static const GUID dummy_groupid
= { 0xbeefbeef };
2290 call_trace_t trace_expected
;
2293 /* on <=W2K platforms same ordinal used for another export with different
2294 prototype, so skipping using this indirect condition */
2295 if (is_win2k_and_lower
)
2297 win_skip("IUnknown_QueryServiceExec is not available\n");
2301 provider
= IServiceProviderImpl_Construct();
2303 /* null source pointer */
2304 hr
= pIUnknown_QueryServiceExec(NULL
, &dummy_serviceid
, &dummy_groupid
, 0, 0, 0, 0);
2306 hr
== E_NOTIMPL
, /* win 8 */
2307 "got 0x%08x\n", hr
);
2310 IUnknown_QueryServiceExec( ptr1, serviceid, groupid, arg1, arg2, arg3, arg4);
2311 -> IUnknown_QueryInterface( ptr1, &IID_IServiceProvider, &prov );
2312 -> IServiceProvider_QueryService( prov, serviceid, &IID_IOleCommandTarget, &obj );
2313 -> IOleCommandTarget_Exec( obj, groupid, arg1, arg2, arg3, arg4 );
2315 init_call_trace(&trace_expected
);
2317 add_call(&trace_expected
, 1, provider
, &IID_IServiceProvider
, 0, 0, 0);
2318 add_call(&trace_expected
, 2, provider
, &dummy_serviceid
, &IID_IOleCommandTarget
, 0, 0);
2319 add_call(&trace_expected
, 3, &dummy_groupid
, (void*)0x1, (void*)0x2, (void*)0x3, (void*)0x4);
2321 init_call_trace(&trace_got
);
2322 hr
= pIUnknown_QueryServiceExec((IUnknown
*)provider
, &dummy_serviceid
, &dummy_groupid
, 0x1, 0x2, (void*)0x3, (void*)0x4);
2323 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2325 ok_trace(&trace_expected
, &trace_got
);
2327 free_call_trace(&trace_expected
);
2328 free_call_trace(&trace_got
);
2330 IServiceProvider_Release(provider
);
2334 static HRESULT WINAPI
IProfferServiceImpl_QueryInterface(IProfferService
*iface
, REFIID riid
, void **ppvObj
)
2336 IProfferServiceImpl
*This
= impl_from_IProfferService(iface
);
2338 if (IsEqualIID(riid
, &IID_IUnknown
) ||
2339 IsEqualIID(riid
, &IID_IProfferService
))
2343 else if (IsEqualIID(riid
, &IID_IServiceProvider
))
2345 *ppvObj
= IServiceProviderImpl_Construct();
2346 add_call(&trace_got
, 1, iface
, &IID_IServiceProvider
, 0, 0, 0);
2352 IProfferService_AddRef(iface
);
2356 return E_NOINTERFACE
;
2359 static ULONG WINAPI
IProfferServiceImpl_AddRef(IProfferService
*iface
)
2361 IProfferServiceImpl
*This
= impl_from_IProfferService(iface
);
2362 return InterlockedIncrement(&This
->ref
);
2365 static ULONG WINAPI
IProfferServiceImpl_Release(IProfferService
*iface
)
2367 IProfferServiceImpl
*This
= impl_from_IProfferService(iface
);
2368 ULONG ref
= InterlockedDecrement(&This
->ref
);
2372 HeapFree(GetProcessHeap(), 0, This
);
2378 static HRESULT WINAPI
IProfferServiceImpl_ProfferService(IProfferService
*iface
,
2379 REFGUID service
, IServiceProvider
*pService
, DWORD
*pCookie
)
2381 *pCookie
= 0xdeadbeef;
2382 add_call(&trace_got
, 3, service
, pService
, pCookie
, 0, 0);
2386 static HRESULT WINAPI
IProfferServiceImpl_RevokeService(IProfferService
*iface
, DWORD cookie
)
2388 add_call(&trace_got
, 4, (void*)(DWORD_PTR
)cookie
, 0, 0, 0, 0);
2392 static const IProfferServiceVtbl IProfferServiceImpl_Vtbl
=
2394 IProfferServiceImpl_QueryInterface
,
2395 IProfferServiceImpl_AddRef
,
2396 IProfferServiceImpl_Release
,
2397 IProfferServiceImpl_ProfferService
,
2398 IProfferServiceImpl_RevokeService
2401 static void test_IUnknown_ProfferService(void)
2403 IServiceProvider
*provider
;
2404 IProfferService
*proff
;
2405 static const GUID dummy_serviceid
= { 0xdeadbeef };
2406 call_trace_t trace_expected
;
2410 /* on <=W2K platforms same ordinal used for another export with different
2411 prototype, so skipping using this indirect condition */
2412 if (is_win2k_and_lower
)
2414 win_skip("IUnknown_ProfferService is not available\n");
2418 provider
= IServiceProviderImpl_Construct();
2419 proff
= IProfferServiceImpl_Construct();
2421 /* null source pointer */
2422 hr
= pIUnknown_ProfferService(NULL
, &dummy_serviceid
, 0, 0);
2424 hr
== E_NOTIMPL
, /* win 8 */
2425 "got 0x%08x\n", hr
);
2428 IUnknown_ProfferService( ptr1, serviceid, arg1, arg2);
2429 -> IUnknown_QueryInterface( ptr1, &IID_IServiceProvider, &provider );
2430 -> IServiceProvider_QueryService( provider, &IID_IProfferService, &IID_IProfferService, &proffer );
2432 if (service pointer not null):
2433 -> IProfferService_ProfferService( proffer, serviceid, arg1, arg2 );
2435 -> IProfferService_RevokeService( proffer, *arg2 );
2437 init_call_trace(&trace_expected
);
2439 add_call(&trace_expected
, 1, proff
, &IID_IServiceProvider
, 0, 0, 0);
2440 add_call(&trace_expected
, 2, &IID_IProfferService
, &IID_IProfferService
, 0, 0, 0);
2441 add_call(&trace_expected
, 3, &dummy_serviceid
, provider
, &cookie
, 0, 0);
2443 init_call_trace(&trace_got
);
2445 hr
= pIUnknown_ProfferService((IUnknown
*)proff
, &dummy_serviceid
, provider
, &cookie
);
2446 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2447 ok(cookie
== 0xdeadbeef, "got %x\n", cookie
);
2449 ok_trace(&trace_expected
, &trace_got
);
2450 free_call_trace(&trace_got
);
2451 free_call_trace(&trace_expected
);
2453 /* same with ::Revoke path */
2454 init_call_trace(&trace_expected
);
2456 add_call(&trace_expected
, 1, proff
, &IID_IServiceProvider
, 0, 0, 0);
2457 add_call(&trace_expected
, 2, &IID_IProfferService
, &IID_IProfferService
, 0, 0, 0);
2458 add_call(&trace_expected
, 4, (void*)(DWORD_PTR
)cookie
, 0, 0, 0, 0);
2460 init_call_trace(&trace_got
);
2461 ok(cookie
!= 0, "got %x\n", cookie
);
2462 hr
= pIUnknown_ProfferService((IUnknown
*)proff
, &dummy_serviceid
, 0, &cookie
);
2463 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2464 ok(cookie
== 0, "got %x\n", cookie
);
2465 ok_trace(&trace_expected
, &trace_got
);
2466 free_call_trace(&trace_got
);
2467 free_call_trace(&trace_expected
);
2469 IServiceProvider_Release(provider
);
2470 IProfferService_Release(proff
);
2473 static void test_SHCreateWorkerWindowA(void)
2481 if (is_win2k_and_lower
)
2483 win_skip("SHCreateWorkerWindowA not available\n");
2487 hwnd
= pSHCreateWorkerWindowA(0, NULL
, 0, 0, 0, 0);
2488 ok(hwnd
!= 0, "expected window\n");
2490 GetClassNameA(hwnd
, classA
, 20);
2491 ok(lstrcmpA(classA
, "WorkerA") == 0, "expected WorkerA class, got %s\n", classA
);
2493 ret
= GetWindowLongPtrA(hwnd
, 0);
2494 ok(ret
== 0, "got %ld\n", ret
);
2497 memset(&cliA
, 0, sizeof(cliA
));
2498 res
= GetClassInfoA(GetModuleHandleA("shlwapi.dll"), "WorkerA", &cliA
);
2499 ok(res
, "failed to get class info\n");
2500 ok(cliA
.style
== 0, "got 0x%08x\n", cliA
.style
);
2501 ok(cliA
.cbClsExtra
== 0, "got %d\n", cliA
.cbClsExtra
);
2502 ok(cliA
.cbWndExtra
== sizeof(LONG_PTR
), "got %d\n", cliA
.cbWndExtra
);
2503 ok(cliA
.lpszMenuName
== 0, "got %s\n", cliA
.lpszMenuName
);
2505 DestroyWindow(hwnd
);
2507 /* set extra bytes */
2508 hwnd
= pSHCreateWorkerWindowA(0, NULL
, 0, 0, 0, 0xdeadbeef);
2509 ok(hwnd
!= 0, "expected window\n");
2511 GetClassNameA(hwnd
, classA
, 20);
2512 ok(lstrcmpA(classA
, "WorkerA") == 0, "expected WorkerA class, got %s\n", classA
);
2514 ret
= GetWindowLongPtrA(hwnd
, 0);
2515 ok(ret
== 0xdeadbeef, "got %ld\n", ret
);
2518 ret
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
2519 ok(ret
== WS_EX_WINDOWEDGE
||
2520 ret
== (WS_EX_WINDOWEDGE
|WS_EX_LAYOUTRTL
) /* systems with RTL locale */, "0x%08lx\n", ret
);
2522 DestroyWindow(hwnd
);
2524 hwnd
= pSHCreateWorkerWindowA(0, NULL
, WS_EX_TOOLWINDOW
, 0, 0, 0);
2525 ret
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
2526 ok(ret
== (WS_EX_WINDOWEDGE
|WS_EX_TOOLWINDOW
) ||
2527 ret
== (WS_EX_WINDOWEDGE
|WS_EX_TOOLWINDOW
|WS_EX_LAYOUTRTL
) /* systems with RTL locale */, "0x%08lx\n", ret
);
2528 DestroyWindow(hwnd
);
2531 static HRESULT WINAPI
SF_QueryInterface(IShellFolder
*iface
,
2532 REFIID riid
, void **ppv
)
2534 /* SHIShellFolder_EnumObjects doesn't QI the object for IShellFolder */
2535 ok(!IsEqualGUID(&IID_IShellFolder
, riid
),
2536 "Unexpected QI for IShellFolder\n");
2537 return E_NOINTERFACE
;
2540 static ULONG WINAPI
SF_AddRef(IShellFolder
*iface
)
2545 static ULONG WINAPI
SF_Release(IShellFolder
*iface
)
2550 static HRESULT WINAPI
SF_ParseDisplayName(IShellFolder
*iface
,
2551 HWND owner
, LPBC reserved
, LPOLESTR displayName
, ULONG
*eaten
,
2552 LPITEMIDLIST
*idl
, ULONG
*attr
)
2554 ok(0, "Didn't expect ParseDisplayName\n");
2558 static HRESULT WINAPI
SF_EnumObjects(IShellFolder
*iface
,
2559 HWND owner
, SHCONTF flags
, IEnumIDList
**enm
)
2561 *enm
= (IEnumIDList
*)0xcafebabe;
2565 static HRESULT WINAPI
SF_BindToObject(IShellFolder
*iface
,
2566 LPCITEMIDLIST idl
, LPBC reserved
, REFIID riid
, void **obj
)
2568 ok(0, "Didn't expect BindToObject\n");
2572 static HRESULT WINAPI
SF_BindToStorage(IShellFolder
*iface
,
2573 LPCITEMIDLIST idl
, LPBC reserved
, REFIID riid
, void **obj
)
2575 ok(0, "Didn't expect BindToStorage\n");
2579 static HRESULT WINAPI
SF_CompareIDs(IShellFolder
*iface
,
2580 LPARAM lparam
, LPCITEMIDLIST idl1
, LPCITEMIDLIST idl2
)
2582 ok(0, "Didn't expect CompareIDs\n");
2586 static HRESULT WINAPI
SF_CreateViewObject(IShellFolder
*iface
,
2587 HWND owner
, REFIID riid
, void **out
)
2589 ok(0, "Didn't expect CreateViewObject\n");
2593 static HRESULT WINAPI
SF_GetAttributesOf(IShellFolder
*iface
,
2594 UINT cidl
, LPCITEMIDLIST
*idl
, SFGAOF
*inOut
)
2596 ok(0, "Didn't expect GetAttributesOf\n");
2600 static HRESULT WINAPI
SF_GetUIObjectOf(IShellFolder
*iface
,
2601 HWND owner
, UINT cidl
, LPCITEMIDLIST
*idls
, REFIID riid
, UINT
*inOut
,
2604 ok(0, "Didn't expect GetUIObjectOf\n");
2608 static HRESULT WINAPI
SF_GetDisplayNameOf(IShellFolder
*iface
,
2609 LPCITEMIDLIST idl
, SHGDNF flags
, STRRET
*name
)
2611 ok(0, "Didn't expect GetDisplayNameOf\n");
2615 static HRESULT WINAPI
SF_SetNameOf(IShellFolder
*iface
,
2616 HWND hwnd
, LPCITEMIDLIST idl
, LPCOLESTR name
, SHGDNF flags
,
2617 LPITEMIDLIST
*idlOut
)
2619 ok(0, "Didn't expect SetNameOf\n");
2623 static IShellFolderVtbl ShellFolderVtbl
= {
2627 SF_ParseDisplayName
,
2632 SF_CreateViewObject
,
2635 SF_GetDisplayNameOf
,
2639 static IShellFolder ShellFolder
= { &ShellFolderVtbl
};
2641 static void test_SHIShellFolder_EnumObjects(void)
2645 IShellFolder
*folder
;
2647 if(!pSHIShellFolder_EnumObjects
|| is_win2k_and_lower
){
2648 win_skip("SHIShellFolder_EnumObjects not available\n");
2653 /* NULL object crashes on Windows */
2654 pSHIShellFolder_EnumObjects(NULL
, NULL
, 0, NULL
);
2657 /* SHIShellFolder_EnumObjects doesn't QI the object for IShellFolder */
2658 enm
= (IEnumIDList
*)0xdeadbeef;
2659 hres
= pSHIShellFolder_EnumObjects(&ShellFolder
, NULL
, 0, &enm
);
2660 ok(hres
== S_OK
, "SHIShellFolder_EnumObjects failed: 0x%08x\n", hres
);
2661 ok(enm
== (IEnumIDList
*)0xcafebabe, "Didn't get expected enumerator location, instead: %p\n", enm
);
2663 /* SHIShellFolder_EnumObjects isn't strict about the IShellFolder object */
2664 hres
= pSHGetDesktopFolder(&folder
);
2665 ok(hres
== S_OK
, "SHGetDesktopFolder failed: 0x%08x\n", hres
);
2668 hres
= pSHIShellFolder_EnumObjects(folder
, NULL
, 0, &enm
);
2669 ok(hres
== S_OK
, "SHIShellFolder_EnumObjects failed: 0x%08x\n", hres
);
2670 ok(enm
!= NULL
, "Didn't get an enumerator\n");
2672 IEnumIDList_Release(enm
);
2674 IShellFolder_Release(folder
);
2677 static BOOL
write_inifile(LPCWSTR filename
)
2682 static const char data
[] =
2685 "AnotherKey=asdf\r\n";
2687 file
= CreateFileW(filename
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
2688 if(file
== INVALID_HANDLE_VALUE
) {
2689 win_skip("failed to create ini file at %s\n", wine_dbgstr_w(filename
));
2693 WriteFile(file
, data
, sizeof(data
), &written
, NULL
);
2700 #define verify_inifile(f, e) r_verify_inifile(__LINE__, f, e)
2701 static void r_verify_inifile(unsigned l
, LPCWSTR filename
, LPCSTR exp
)
2707 file
= CreateFileW(filename
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, 0, NULL
);
2709 if(file
== INVALID_HANDLE_VALUE
)
2712 ReadFile(file
, buf
, sizeof(buf
) * sizeof(CHAR
), &read
, NULL
);
2717 ok_(__FILE__
,l
)(!strcmp(buf
, exp
), "Expected:\n%s\nGot:\n%s\n", exp
,
2721 static void test_SHGetIniString(void)
2724 WCHAR out
[64] = {0};
2726 static const WCHAR TestAppW
[] = {'T','e','s','t','A','p','p',0};
2727 static const WCHAR AKeyW
[] = {'A','K','e','y',0};
2728 static const WCHAR AnotherKeyW
[] = {'A','n','o','t','h','e','r','K','e','y',0};
2729 static const WCHAR JunkKeyW
[] = {'J','u','n','k','K','e','y',0};
2730 static const WCHAR testpathW
[] = {'C',':','\\','t','e','s','t','.','i','n','i',0};
2731 WCHAR pathW
[MAX_PATH
];
2733 if(!pSHGetIniStringW
|| is_win2k_and_lower
){
2734 win_skip("SHGetIniStringW is not available\n");
2738 lstrcpyW(pathW
, testpathW
);
2740 if (!write_inifile(pathW
))
2744 /* these crash on Windows */
2745 pSHGetIniStringW(NULL
, NULL
, NULL
, 0, NULL
);
2746 pSHGetIniStringW(NULL
, AKeyW
, out
, sizeof(out
), pathW
);
2747 pSHGetIniStringW(TestAppW
, AKeyW
, NULL
, sizeof(out
), pathW
);
2750 ret
= pSHGetIniStringW(TestAppW
, AKeyW
, out
, 0, pathW
);
2751 ok(ret
== 0, "SHGetIniStringW should have given 0, instead: %d\n", ret
);
2753 /* valid arguments */
2755 SetLastError(0xdeadbeef);
2756 ret
= pSHGetIniStringW(TestAppW
, NULL
, out
, sizeof(out
), pathW
);
2757 ok(ret
== 4, "SHGetIniStringW should have given 4, instead: %d\n", ret
);
2758 ok(!lstrcmpW(out
, AKeyW
), "Expected %s, got: %s, %d\n",
2759 wine_dbgstr_w(AKeyW
), wine_dbgstr_w(out
), GetLastError());
2761 ret
= pSHGetIniStringW(TestAppW
, AKeyW
, out
, sizeof(out
), pathW
);
2762 ok(ret
== 1, "SHGetIniStringW should have given 1, instead: %d\n", ret
);
2763 ok(!strcmp_wa(out
, "1"), "Expected L\"1\", got: %s\n", wine_dbgstr_w(out
));
2765 ret
= pSHGetIniStringW(TestAppW
, AnotherKeyW
, out
, sizeof(out
), pathW
);
2766 ok(ret
== 4, "SHGetIniStringW should have given 4, instead: %d\n", ret
);
2767 ok(!strcmp_wa(out
, "asdf"), "Expected L\"asdf\", got: %s\n", wine_dbgstr_w(out
));
2770 ret
= pSHGetIniStringW(TestAppW
, JunkKeyW
, out
, sizeof(out
), pathW
);
2771 ok(ret
== 0, "SHGetIniStringW should have given 0, instead: %d\n", ret
);
2772 ok(*out
== 0, "Expected L\"\", got: %s\n", wine_dbgstr_w(out
));
2777 static void test_SHSetIniString(void)
2781 static const WCHAR TestAppW
[] = {'T','e','s','t','A','p','p',0};
2782 static const WCHAR AnotherAppW
[] = {'A','n','o','t','h','e','r','A','p','p',0};
2783 static const WCHAR TestIniW
[] = {'C',':','\\','t','e','s','t','.','i','n','i',0};
2784 static const WCHAR AKeyW
[] = {'A','K','e','y',0};
2785 static const WCHAR NewKeyW
[] = {'N','e','w','K','e','y',0};
2786 static const WCHAR AValueW
[] = {'A','V','a','l','u','e',0};
2788 if(!pSHSetIniStringW
|| is_win2k_and_lower
){
2789 win_skip("SHSetIniStringW is not available\n");
2793 if (!write_inifile(TestIniW
))
2796 ret
= pSHSetIniStringW(TestAppW
, AKeyW
, AValueW
, TestIniW
);
2797 ok(ret
== TRUE
, "SHSetIniStringW should not have failed\n");
2798 todo_wine
/* wine sticks an extra \r\n at the end of the file */
2799 verify_inifile(TestIniW
, "[TestApp]\r\nAKey=AValue\r\nAnotherKey=asdf\r\n");
2801 ret
= pSHSetIniStringW(TestAppW
, AKeyW
, NULL
, TestIniW
);
2802 ok(ret
== TRUE
, "SHSetIniStringW should not have failed\n");
2803 verify_inifile(TestIniW
, "[TestApp]\r\nAnotherKey=asdf\r\n");
2805 ret
= pSHSetIniStringW(AnotherAppW
, NewKeyW
, AValueW
, TestIniW
);
2806 ok(ret
== TRUE
, "SHSetIniStringW should not have failed\n");
2807 verify_inifile(TestIniW
, "[TestApp]\r\nAnotherKey=asdf\r\n[AnotherApp]\r\nNewKey=AValue\r\n");
2809 ret
= pSHSetIniStringW(TestAppW
, NULL
, AValueW
, TestIniW
);
2810 ok(ret
== TRUE
, "SHSetIniStringW should not have failed\n");
2811 verify_inifile(TestIniW
, "[AnotherApp]\r\nNewKey=AValue\r\n");
2813 DeleteFileW(TestIniW
);
2816 enum _shellkey_flags
{
2817 SHKEY_Root_HKCU
= 0x1,
2818 SHKEY_Root_HKLM
= 0x2,
2819 SHKEY_Key_Explorer
= 0x00,
2820 SHKEY_Key_Shell
= 0x10,
2821 SHKEY_Key_ShellNoRoam
= 0x20,
2822 SHKEY_Key_Classes
= 0x30,
2823 SHKEY_Subkey_Default
= 0x0000,
2824 SHKEY_Subkey_ResourceName
= 0x1000,
2825 SHKEY_Subkey_Handlers
= 0x2000,
2826 SHKEY_Subkey_Associations
= 0x3000,
2827 SHKEY_Subkey_Volatile
= 0x4000,
2828 SHKEY_Subkey_MUICache
= 0x5000,
2829 SHKEY_Subkey_FileExts
= 0x6000
2832 static void test_SHGetShellKey(void)
2834 static const WCHAR ShellFoldersW
[] = { 'S','h','e','l','l',' ','F','o','l','d','e','r','s',0 };
2835 static const WCHAR WineTestW
[] = { 'W','i','n','e','T','e','s','t',0 };
2837 void *pPathBuildRootW
= GetProcAddress(hShlwapi
, "PathBuildRootW");
2838 DWORD
*alloc_data
, data
, size
;
2842 if (!pSHGetShellKey
)
2844 win_skip("SHGetShellKey(ordinal 491) isn't available\n");
2849 if (pPathBuildRootW
&& pPathBuildRootW
== pSHGetShellKey
)
2851 win_skip("SHGetShellKey(ordinal 491) used for PathBuildRootW\n");
2855 if (is_win9x
|| is_win2k_and_lower
)
2857 win_skip("Ordinal 491 used for another call, skipping SHGetShellKey tests\n");
2861 /* Vista+ limits SHKEY enumeration values */
2862 SetLastError(0xdeadbeef);
2863 hkey
= pSHGetShellKey(SHKEY_Key_Explorer
, ShellFoldersW
, FALSE
);
2866 /* Tests not working on Vista+ */
2869 hkey
= pSHGetShellKey(SHKEY_Root_HKLM
|SHKEY_Key_Classes
, NULL
, FALSE
);
2870 ok(hkey
!= NULL
, "hkey = NULL\n");
2874 hkey
= pSHGetShellKey(SHKEY_Root_HKCU
|SHKEY_Key_Explorer
, ShellFoldersW
, FALSE
);
2875 ok(hkey
!= NULL
, "hkey = NULL\n");
2878 hkey
= pSHGetShellKey(SHKEY_Root_HKLM
|SHKEY_Key_Explorer
, ShellFoldersW
, FALSE
);
2879 ok(hkey
!= NULL
, "hkey = NULL\n");
2882 hkey
= pSHGetShellKey(SHKEY_Root_HKLM
, WineTestW
, FALSE
);
2883 ok(hkey
== NULL
, "hkey != NULL\n");
2885 hkey
= pSHGetShellKey(SHKEY_Root_HKLM
, NULL
, FALSE
);
2886 ok(hkey
!= NULL
, "Can't open key\n");
2887 ok(SUCCEEDED(RegDeleteKeyW(hkey
, WineTestW
)), "Can't delete key\n");
2890 hkey
= pSHGetShellKey(SHKEY_Root_HKLM
, WineTestW
, TRUE
);
2891 if (!hkey
&& GetLastError() == ERROR_ACCESS_DENIED
)
2893 skip("Not authorized to create keys\n");
2896 ok(hkey
!= NULL
, "Can't create key\n");
2899 if (!pSKGetValueW
|| !pSKSetValueW
|| !pSKDeleteValueW
|| !pSKAllocValueW
)
2901 win_skip("SKGetValueW, SKSetValueW, SKDeleteValueW or SKAllocValueW not available\n");
2905 size
= sizeof(data
);
2906 hres
= pSKGetValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
, NULL
, &data
, &size
);
2907 ok(hres
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), "hres = %x\n", hres
);
2910 hres
= pSKSetValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
, REG_DWORD
, &data
, sizeof(DWORD
));
2911 ok(hres
== S_OK
, "hres = %x\n", hres
);
2914 hres
= pSKGetValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
, NULL
, NULL
, &size
);
2915 ok(hres
== S_OK
, "hres = %x\n", hres
);
2916 ok(size
== sizeof(DWORD
), "size = %d\n", size
);
2919 hres
= pSKGetValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
, NULL
, &data
, &size
);
2920 ok(hres
== S_OK
, "hres = %x\n", hres
);
2921 ok(size
== sizeof(DWORD
), "size = %d\n", size
);
2922 ok(data
== 1234, "data = %d\n", data
);
2924 hres
= pSKAllocValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
, NULL
, (void**)&alloc_data
, &size
);
2925 ok(hres
== S_OK
, "hres= %x\n", hres
);
2926 ok(size
== sizeof(DWORD
), "size = %d\n", size
);
2927 if (SUCCEEDED(hres
))
2929 ok(*alloc_data
== 1234, "*alloc_data = %d\n", *alloc_data
);
2930 LocalFree(alloc_data
);
2933 hres
= pSKDeleteValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
);
2934 ok(hres
== S_OK
, "hres = %x\n", hres
);
2936 hres
= pSKDeleteValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
);
2937 ok(hres
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), "hres = %x\n", hres
);
2939 hres
= pSKGetValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
, NULL
, &data
, &size
);
2940 ok(hres
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), "hres = %x\n", hres
);
2942 hkey
= pSHGetShellKey(SHKEY_Root_HKLM
, NULL
, FALSE
);
2943 ok(hkey
!= NULL
, "Can't create key\n");
2944 ok(SUCCEEDED(RegDeleteKeyW(hkey
, WineTestW
)), "Can't delete key\n");
2948 static void init_pointers(void)
2950 #define MAKEFUNC(f, ord) (p##f = (void*)GetProcAddress(hShlwapi, (LPSTR)(ord)))
2951 MAKEFUNC(SHAllocShared
, 7);
2952 MAKEFUNC(SHLockShared
, 8);
2953 MAKEFUNC(SHUnlockShared
, 9);
2954 MAKEFUNC(SHFreeShared
, 10);
2955 MAKEFUNC(GetAcceptLanguagesA
, 14);
2956 MAKEFUNC(SHSetWindowBits
, 165);
2957 MAKEFUNC(SHSetParentHwnd
, 167);
2958 MAKEFUNC(ConnectToConnectionPoint
, 168);
2959 MAKEFUNC(SHSearchMapInt
, 198);
2960 MAKEFUNC(SHCreateWorkerWindowA
, 257);
2961 MAKEFUNC(GUIDFromStringA
, 269);
2962 MAKEFUNC(SHPackDispParams
, 282);
2963 MAKEFUNC(IConnectionPoint_InvokeWithCancel
, 283);
2964 MAKEFUNC(IConnectionPoint_SimpleInvoke
, 284);
2965 MAKEFUNC(SHGetIniStringW
, 294);
2966 MAKEFUNC(SHSetIniStringW
, 295);
2967 MAKEFUNC(SHFormatDateTimeA
, 353);
2968 MAKEFUNC(SHFormatDateTimeW
, 354);
2969 MAKEFUNC(SHIShellFolder_EnumObjects
, 404);
2970 MAKEFUNC(SHGetObjectCompatFlags
, 476);
2971 MAKEFUNC(IUnknown_QueryServiceExec
, 484);
2972 MAKEFUNC(SHGetShellKey
, 491);
2973 MAKEFUNC(SHPropertyBag_ReadLONG
, 496);
2974 MAKEFUNC(IUnknown_ProfferService
, 514);
2975 MAKEFUNC(SKGetValueW
, 516);
2976 MAKEFUNC(SKSetValueW
, 517);
2977 MAKEFUNC(SKDeleteValueW
, 518);
2978 MAKEFUNC(SKAllocValueW
, 519);
2982 static void test_SHSetParentHwnd(void)
2984 HWND hwnd
, hwnd2
, ret
;
2987 if (!pSHSetParentHwnd
)
2989 win_skip("SHSetParentHwnd not available\n");
2993 hwnd
= CreateWindowA("Button", "", WS_VISIBLE
, 0, 0, 10, 10, NULL
, NULL
, NULL
, NULL
);
2994 ok(hwnd
!= NULL
, "got %p\n", hwnd
);
2996 hwnd2
= CreateWindowA("Button", "", WS_VISIBLE
| WS_CHILD
, 0, 0, 10, 10, hwnd
, NULL
, NULL
, NULL
);
2997 ok(hwnd2
!= NULL
, "got %p\n", hwnd2
);
3000 ret
= pSHSetParentHwnd(NULL
, NULL
);
3001 ok(ret
== NULL
, "got %p\n", ret
);
3003 /* set to no parent while already no parent present */
3004 ret
= GetParent(hwnd
);
3005 ok(ret
== NULL
, "got %p\n", ret
);
3006 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
3007 ok((style
& (WS_POPUP
|WS_CHILD
)) == 0, "got style 0x%08x\n", style
);
3008 ret
= pSHSetParentHwnd(hwnd
, NULL
);
3009 ok(ret
== NULL
, "got %p\n", ret
);
3010 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
3011 ok((style
& (WS_POPUP
|WS_CHILD
)) == 0, "got style 0x%08x\n", style
);
3013 /* reset to null parent from not null */
3014 ret
= GetParent(hwnd2
);
3015 ok(ret
== hwnd
, "got %p\n", ret
);
3016 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
3017 ok((style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
, "got style 0x%08x\n", style
);
3018 ret
= pSHSetParentHwnd(hwnd2
, NULL
);
3019 ok(ret
== NULL
, "got %p\n", ret
);
3020 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
3021 ok((style
& (WS_POPUP
|WS_CHILD
)) == WS_POPUP
, "got style 0x%08x\n", style
);
3022 ret
= GetParent(hwnd2
);
3023 ok(ret
== NULL
, "got %p\n", ret
);
3025 /* set parent back */
3026 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
3027 SetWindowLongA(hwnd2
, GWL_STYLE
, style
& ~(WS_CHILD
|WS_POPUP
));
3028 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
3029 ok((style
& (WS_CHILD
|WS_POPUP
)) == 0, "got 0x%08x\n", style
);
3031 ret
= pSHSetParentHwnd(hwnd2
, hwnd
);
3032 todo_wine
ok(ret
== NULL
, "got %p\n", ret
);
3034 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
3035 ok((style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
, "got style 0x%08x\n", style
);
3036 ret
= GetParent(hwnd2
);
3037 ok(ret
== hwnd
, "got %p\n", ret
);
3039 /* try to set same parent again */
3041 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
3042 SetWindowLongA(hwnd2
, GWL_STYLE
, style
| WS_POPUP
);
3043 ret
= pSHSetParentHwnd(hwnd2
, hwnd
);
3044 todo_wine
ok(ret
== NULL
, "got %p\n", ret
);
3045 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
3046 ok((style
& (WS_CHILD
|WS_POPUP
)) == WS_CHILD
, "got 0x%08x\n", style
);
3047 ret
= GetParent(hwnd2
);
3048 ok(ret
== hwnd
, "got %p\n", ret
);
3050 /* without WS_POPUP */
3051 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
3052 SetWindowLongA(hwnd2
, GWL_STYLE
, style
| ~WS_POPUP
);
3053 ret
= pSHSetParentHwnd(hwnd2
, hwnd
);
3054 todo_wine
ok(ret
== hwnd
, "got %p\n", ret
);
3055 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
3056 ok((style
& (WS_CHILD
|WS_POPUP
)) == WS_CHILD
, "got 0x%08x\n", style
);
3057 ret
= GetParent(hwnd2
);
3058 ok(ret
== hwnd
, "got %p\n", ret
);
3060 DestroyWindow(hwnd
);
3061 DestroyWindow(hwnd2
);
3066 hShlwapi
= GetModuleHandleA("shlwapi.dll");
3067 is_win2k_and_lower
= GetProcAddress(hShlwapi
, "StrChrNW") == 0;
3068 is_win9x
= GetProcAddress(hShlwapi
, (LPSTR
)99) == 0; /* StrCpyNXA */
3070 /* SHCreateStreamOnFileEx was introduced in shlwapi v6.0 */
3071 if(!GetProcAddress(hShlwapi
, "SHCreateStreamOnFileEx")){
3072 win_skip("Too old shlwapi version\n");
3078 hmlang
= LoadLibraryA("mlang.dll");
3079 pLcidToRfc1766A
= (void *)GetProcAddress(hmlang
, "LcidToRfc1766A");
3081 hshell32
= LoadLibraryA("shell32.dll");
3082 pSHGetDesktopFolder
= (void *)GetProcAddress(hshell32
, "SHGetDesktopFolder");
3084 test_GetAcceptLanguagesA();
3085 test_SHSearchMapInt();
3086 test_alloc_shared();
3088 test_GetShellSecurityDescriptor();
3089 test_SHPackDispParams();
3090 test_IConnectionPoint();
3091 test_SHPropertyBag_ReadLONG();
3092 test_SHSetWindowBits();
3093 test_SHFormatDateTimeA();
3094 test_SHFormatDateTimeW();
3095 test_SHGetObjectCompatFlags();
3096 test_IUnknown_QueryServiceExec();
3097 test_IUnknown_ProfferService();
3098 test_SHCreateWorkerWindowA();
3099 test_SHIShellFolder_EnumObjects();
3100 test_SHGetIniString();
3101 test_SHSetIniString();
3102 test_SHGetShellKey();
3103 test_SHSetParentHwnd();
3105 FreeLibrary(hshell32
);
3106 FreeLibrary(hmlang
);