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 RegDeleteValue(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 lstrcat(language
, "-");
221 memset(buffer
, 0, sizeof(buffer
));
222 len
= GetLocaleInfoA(lcid
, LOCALE_SISO3166CTRYNAME
, buffer
, sizeof(buffer
) - len
- 1);
223 lstrcat(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 and above fail with HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), but
299 recent os succeed and return a partial result while
300 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 "==_#%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
310 memset(buffer
, '#', maxlen
);
312 hr
= pGetAcceptLanguagesA( buffer
, &len
);
313 ok(((hr
== E_INVALIDARG
) && (len
== 0)) ||
314 (((hr
== S_OK
) && !lstrcmpA(buffer
, language
) && (len
== lstrlenA(language
))) ||
315 ((hr
== S_OK
) && !memcmp(buffer
, language
, len
)) ||
316 ((hr
== __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
)) && !len
)),
317 "-1_#%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
321 memset(buffer
, '#', maxlen
);
323 hr
= pGetAcceptLanguagesA( buffer
, &len
);
324 ok(((hr
== E_INVALIDARG
) && (len
== 0)) ||
325 (((hr
== S_OK
) && !lstrcmpA(buffer
, language
) && (len
== lstrlenA(language
))) ||
326 ((hr
== S_OK
) && !memcmp(buffer
, language
, len
)) ||
327 ((hr
== __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
)) && !len
)),
328 "=1_#%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
331 hr
= pGetAcceptLanguagesA( NULL
, &len
);
333 /* w2k3 and below: E_FAIL and untouched len,
334 since w2k8: S_OK and needed size (excluding 0) */
335 ok( ((hr
== S_OK
) && (len
== exactsize
)) ||
336 ((hr
== E_FAIL
) && (len
== maxlen
)),
337 "NULL,max #%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
342 /* without a value in the registry, a default language is returned */
343 RegDeleteValue(hroot
, acceptlanguage
);
346 memset(buffer
, '#', maxlen
);
348 hr
= pGetAcceptLanguagesA( buffer
, &len
);
349 ok( ((hr
== S_OK
) && (len
== lstrlenA(language
))),
350 "max: got 0x%x with %d and %s (expected S_OK with %d and '%s'\n",
351 hr
, len
, buffer
, lstrlenA(language
), language
);
354 memset(buffer
, '#', maxlen
);
356 hr
= pGetAcceptLanguagesA( buffer
, &len
);
357 ok( (((hr
== S_OK
) || (hr
== E_INVALIDARG
)) && !memcmp(buffer
, language
, len
)) ||
358 ((hr
== __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
)) && !len
),
359 "=2: got 0x%x with %d and %s\n", hr
, len
, buffer
);
362 memset(buffer
, '#', maxlen
);
364 hr
= pGetAcceptLanguagesA( buffer
, &len
);
365 /* When the buffer is too small, win7_32 and w2k8_64 and above fail with
366 HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), other versions succeed
367 and return a partial 0 terminated result while other versions
368 fail with E_INVALIDARG and return a partial unterminated result */
369 ok( (((hr
== S_OK
) || (hr
== E_INVALIDARG
)) && !memcmp(buffer
, language
, len
)) ||
370 ((hr
== __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
)) && !len
),
371 "=1: got 0x%x with %d and %s\n", hr
, len
, buffer
);
374 memset(buffer
, '#', maxlen
);
376 hr
= pGetAcceptLanguagesA( buffer
, &len
);
377 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
378 ok((hr
== E_FAIL
) || (hr
== E_INVALIDARG
),
379 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr
);
381 memset(buffer
, '#', maxlen
);
383 hr
= pGetAcceptLanguagesA( buffer
, NULL
);
384 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
385 ok((hr
== E_FAIL
) || (hr
== E_INVALIDARG
),
386 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr
);
389 hr
= pGetAcceptLanguagesA( NULL
, NULL
);
390 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
391 ok((hr
== E_FAIL
) || (hr
== E_INVALIDARG
),
392 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr
);
396 len
= lstrlenA(original
);
397 lres
= RegSetValueExA(hroot
, acceptlanguage
, 0, REG_SZ
, (const BYTE
*) original
, len
? len
+ 1: 0);
398 ok(!lres
, "RegSetValueEx(%s) failed: %d\n", original
, lres
);
402 RegDeleteValue(hroot
, acceptlanguage
);
407 static void test_SHSearchMapInt(void)
409 int keys
[8], values
[8];
412 if (!pSHSearchMapInt
)
415 memset(keys
, 0, sizeof(keys
));
416 memset(values
, 0, sizeof(values
));
417 keys
[0] = 99; values
[0] = 101;
419 /* NULL key/value lists crash native, so skip testing them */
422 i
= pSHSearchMapInt(keys
, values
, 1, keys
[0]);
423 ok(i
== values
[0], "Len 1, expected %d, got %d\n", values
[0], i
);
425 /* Key doesn't exist */
426 i
= pSHSearchMapInt(keys
, values
, 1, 100);
427 ok(i
== -1, "Len 1 - bad key, expected -1, got %d\n", i
);
429 /* Len = 0 => not found */
430 i
= pSHSearchMapInt(keys
, values
, 0, keys
[0]);
431 ok(i
== -1, "Len 1 - passed len 0, expected -1, got %d\n", i
);
433 /* 2 elements, len = 1 */
434 keys
[1] = 98; values
[1] = 102;
435 i
= pSHSearchMapInt(keys
, values
, 1, keys
[1]);
436 ok(i
== -1, "Len 1 - array len 2, expected -1, got %d\n", i
);
438 /* 2 elements, len = 2 */
439 i
= pSHSearchMapInt(keys
, values
, 2, keys
[1]);
440 ok(i
== values
[1], "Len 2, expected %d, got %d\n", values
[1], i
);
442 /* Searches forward */
443 keys
[2] = 99; values
[2] = 103;
444 i
= pSHSearchMapInt(keys
, values
, 3, keys
[0]);
445 ok(i
== values
[0], "Len 3, expected %d, got %d\n", values
[0], i
);
448 static void test_alloc_shared(void)
456 procid
=GetCurrentProcessId();
457 hmem
=pSHAllocShared(NULL
,10,procid
);
458 ok(hmem
!=NULL
,"SHAllocShared(NULL...) failed: %u\n", GetLastError());
459 ret
= pSHFreeShared(hmem
, procid
);
460 ok( ret
, "SHFreeShared failed: %u\n", GetLastError());
463 hmem
=pSHAllocShared(&val
,4,procid
);
464 ok(hmem
!=NULL
,"SHAllocShared(NULL...) failed: %u\n", GetLastError());
466 p
=pSHLockShared(hmem
,procid
);
467 ok(p
!=NULL
,"SHLockShared failed: %u\n", GetLastError());
469 ok(*p
==val
,"Wrong value in shared memory: %d instead of %d\n",*p
,val
);
470 ret
= pSHUnlockShared(p
);
471 ok( ret
, "SHUnlockShared failed: %u\n", GetLastError());
473 ret
= pSHFreeShared(hmem
, procid
);
474 ok( ret
, "SHFreeShared failed: %u\n", GetLastError());
477 static void test_fdsa(void)
481 DWORD num_items
; /* Number of elements inserted */
482 void *mem
; /* Ptr to array */
483 DWORD blocks_alloced
; /* Number of elements allocated */
484 BYTE inc
; /* Number of elements to grow by when we need to expand */
485 BYTE block_size
; /* Size in bytes of an element */
486 BYTE flags
; /* Flags */
489 BOOL (WINAPI
*pFDSA_Initialize
)(DWORD block_size
, DWORD inc
, FDSA_info
*info
, void *mem
,
491 BOOL (WINAPI
*pFDSA_Destroy
)(FDSA_info
*info
);
492 DWORD (WINAPI
*pFDSA_InsertItem
)(FDSA_info
*info
, DWORD where
, const void *block
);
493 BOOL (WINAPI
*pFDSA_DeleteItem
)(FDSA_info
*info
, DWORD where
);
496 int block_size
= 10, init_blocks
= 4, inc
= 2;
500 pFDSA_Initialize
= (void *)GetProcAddress(hShlwapi
, (LPSTR
)208);
501 pFDSA_Destroy
= (void *)GetProcAddress(hShlwapi
, (LPSTR
)209);
502 pFDSA_InsertItem
= (void *)GetProcAddress(hShlwapi
, (LPSTR
)210);
503 pFDSA_DeleteItem
= (void *)GetProcAddress(hShlwapi
, (LPSTR
)211);
505 mem
= HeapAlloc(GetProcessHeap(), 0, block_size
* init_blocks
);
506 memset(&info
, 0, sizeof(info
));
508 ok(pFDSA_Initialize(block_size
, inc
, &info
, mem
, init_blocks
), "FDSA_Initialize rets FALSE\n");
509 ok(info
.num_items
== 0, "num_items = %d\n", info
.num_items
);
510 ok(info
.mem
== mem
, "mem = %p\n", info
.mem
);
511 ok(info
.blocks_alloced
== init_blocks
, "blocks_alloced = %d\n", info
.blocks_alloced
);
512 ok(info
.inc
== inc
, "inc = %d\n", info
.inc
);
513 ok(info
.block_size
== block_size
, "block_size = %d\n", info
.block_size
);
514 ok(info
.flags
== 0, "flags = %d\n", info
.flags
);
516 ret
= pFDSA_InsertItem(&info
, 1234, "1234567890");
517 ok(ret
== 0, "ret = %d\n", ret
);
518 ok(info
.num_items
== 1, "num_items = %d\n", info
.num_items
);
519 ok(info
.mem
== mem
, "mem = %p\n", info
.mem
);
520 ok(info
.blocks_alloced
== init_blocks
, "blocks_alloced = %d\n", info
.blocks_alloced
);
521 ok(info
.inc
== inc
, "inc = %d\n", info
.inc
);
522 ok(info
.block_size
== block_size
, "block_size = %d\n", info
.block_size
);
523 ok(info
.flags
== 0, "flags = %d\n", info
.flags
);
525 ret
= pFDSA_InsertItem(&info
, 1234, "abcdefghij");
526 ok(ret
== 1, "ret = %d\n", ret
);
528 ret
= pFDSA_InsertItem(&info
, 1, "klmnopqrst");
529 ok(ret
== 1, "ret = %d\n", ret
);
531 ret
= pFDSA_InsertItem(&info
, 0, "uvwxyzABCD");
532 ok(ret
== 0, "ret = %d\n", ret
);
533 ok(info
.mem
== mem
, "mem = %p\n", info
.mem
);
534 ok(info
.flags
== 0, "flags = %d\n", info
.flags
);
536 /* This next InsertItem will cause shlwapi to allocate its own mem buffer */
537 ret
= pFDSA_InsertItem(&info
, 0, "EFGHIJKLMN");
538 ok(ret
== 0, "ret = %d\n", ret
);
539 ok(info
.mem
!= mem
, "mem = %p\n", info
.mem
);
540 ok(info
.blocks_alloced
== init_blocks
+ inc
, "blocks_alloced = %d\n", info
.blocks_alloced
);
541 ok(info
.flags
== 0x1, "flags = %d\n", info
.flags
);
543 ok(!memcmp(info
.mem
, "EFGHIJKLMNuvwxyzABCD1234567890klmnopqrstabcdefghij", 50), "mem %s\n", (char*)info
.mem
);
545 ok(pFDSA_DeleteItem(&info
, 2), "rets FALSE\n");
546 ok(info
.mem
!= mem
, "mem = %p\n", info
.mem
);
547 ok(info
.blocks_alloced
== init_blocks
+ inc
, "blocks_alloced = %d\n", info
.blocks_alloced
);
548 ok(info
.flags
== 0x1, "flags = %d\n", info
.flags
);
550 ok(!memcmp(info
.mem
, "EFGHIJKLMNuvwxyzABCDklmnopqrstabcdefghij", 40), "mem %s\n", (char*)info
.mem
);
552 ok(pFDSA_DeleteItem(&info
, 3), "rets FALSE\n");
553 ok(info
.mem
!= mem
, "mem = %p\n", info
.mem
);
554 ok(info
.blocks_alloced
== init_blocks
+ inc
, "blocks_alloced = %d\n", info
.blocks_alloced
);
555 ok(info
.flags
== 0x1, "flags = %d\n", info
.flags
);
557 ok(!memcmp(info
.mem
, "EFGHIJKLMNuvwxyzABCDklmnopqrst", 30), "mem %s\n", (char*)info
.mem
);
559 ok(!pFDSA_DeleteItem(&info
, 4), "does not ret FALSE\n");
561 /* As shlwapi has allocated memory internally, Destroy will ret FALSE */
562 ok(!pFDSA_Destroy(&info
), "FDSA_Destroy does not ret FALSE\n");
565 /* When Initialize is called with inc = 0, set it to 1 */
566 ok(pFDSA_Initialize(block_size
, 0, &info
, mem
, init_blocks
), "FDSA_Initialize rets FALSE\n");
567 ok(info
.inc
== 1, "inc = %d\n", info
.inc
);
569 /* This time, because shlwapi hasn't had to allocate memory
570 internally, Destroy rets non-zero */
571 ok(pFDSA_Destroy(&info
), "FDSA_Destroy rets FALSE\n");
574 HeapFree(GetProcessHeap(), 0, mem
);
578 typedef struct SHELL_USER_SID
{
579 SID_IDENTIFIER_AUTHORITY sidAuthority
;
582 } SHELL_USER_SID
, *PSHELL_USER_SID
;
583 typedef struct SHELL_USER_PERMISSION
{
584 SHELL_USER_SID susID
;
589 DWORD dwInheritAccessMask
;
590 } SHELL_USER_PERMISSION
, *PSHELL_USER_PERMISSION
;
591 static void test_GetShellSecurityDescriptor(void)
593 SHELL_USER_PERMISSION supCurrentUserFull
= {
594 { {SECURITY_NULL_SID_AUTHORITY
}, 0, 0 },
595 ACCESS_ALLOWED_ACE_TYPE
, FALSE
,
597 #define MY_INHERITANCE 0xBE /* invalid value to proof behavior */
598 SHELL_USER_PERMISSION supEveryoneDenied
= {
599 { {SECURITY_WORLD_SID_AUTHORITY
}, SECURITY_WORLD_RID
, 0 },
600 ACCESS_DENIED_ACE_TYPE
, TRUE
,
601 GENERIC_WRITE
, MY_INHERITANCE
| 0xDEADBA00, GENERIC_READ
};
602 PSHELL_USER_PERMISSION rgsup
[2] = {
603 &supCurrentUserFull
, &supEveryoneDenied
,
605 SECURITY_DESCRIPTOR
* psd
;
606 SECURITY_DESCRIPTOR
* (WINAPI
*pGetShellSecurityDescriptor
)(PSHELL_USER_PERMISSION
*,int);
607 void *pChrCmpIW
= GetProcAddress(hShlwapi
, "ChrCmpIW");
609 pGetShellSecurityDescriptor
=(void*)GetProcAddress(hShlwapi
,(char*)475);
611 if(!pGetShellSecurityDescriptor
)
613 win_skip("GetShellSecurityDescriptor not available\n");
617 if(pChrCmpIW
&& pChrCmpIW
== pGetShellSecurityDescriptor
) /* win2k */
619 win_skip("Skipping for GetShellSecurityDescriptor, same ordinal used for ChrCmpIW\n");
623 psd
= pGetShellSecurityDescriptor(NULL
, 2);
625 broken(psd
==INVALID_HANDLE_VALUE
), /* IE5 */
626 "GetShellSecurityDescriptor should fail\n");
627 psd
= pGetShellSecurityDescriptor(rgsup
, 0);
628 ok(psd
==NULL
, "GetShellSecurityDescriptor should fail, got %p\n", psd
);
630 SetLastError(0xdeadbeef);
631 psd
= pGetShellSecurityDescriptor(rgsup
, 2);
632 if (psd
== NULL
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
634 /* The previous calls to GetShellSecurityDescriptor don't set the last error */
635 win_skip("GetShellSecurityDescriptor is not implemented\n");
638 if (psd
== INVALID_HANDLE_VALUE
)
640 win_skip("GetShellSecurityDescriptor is broken on IE5\n");
643 ok(psd
!=NULL
, "GetShellSecurityDescriptor failed\n");
646 BOOL bHasDacl
= FALSE
, bDefaulted
, ret
;
649 SECURITY_DESCRIPTOR_CONTROL control
;
651 ok(IsValidSecurityDescriptor(psd
), "returned value is not valid SD\n");
653 ret
= GetSecurityDescriptorControl(psd
, &control
, &dwRev
);
654 ok(ret
, "GetSecurityDescriptorControl failed with error %u\n", GetLastError());
655 ok(0 == (control
& SE_SELF_RELATIVE
), "SD should be absolute\n");
657 ret
= GetSecurityDescriptorDacl(psd
, &bHasDacl
, &pAcl
, &bDefaulted
);
658 ok(ret
, "GetSecurityDescriptorDacl failed with error %u\n", GetLastError());
660 ok(bHasDacl
, "SD has no DACL\n");
663 ok(!bDefaulted
, "DACL should not be defaulted\n");
665 ok(pAcl
!= NULL
, "NULL DACL!\n");
668 ACL_SIZE_INFORMATION asiSize
;
670 ok(IsValidAcl(pAcl
), "DACL is not valid\n");
672 ret
= GetAclInformation(pAcl
, &asiSize
, sizeof(asiSize
), AclSizeInformation
);
673 ok(ret
, "GetAclInformation failed with error %u\n", GetLastError());
675 ok(asiSize
.AceCount
== 3, "Incorrect number of ACEs: %d entries\n", asiSize
.AceCount
);
676 if (asiSize
.AceCount
== 3)
678 ACCESS_ALLOWED_ACE
*paaa
; /* will use for DENIED too */
680 ret
= GetAce(pAcl
, 0, (LPVOID
*)&paaa
);
681 ok(ret
, "GetAce failed with error %u\n", GetLastError());
682 ok(paaa
->Header
.AceType
== ACCESS_ALLOWED_ACE_TYPE
,
683 "Invalid ACE type %d\n", paaa
->Header
.AceType
);
684 ok(paaa
->Header
.AceFlags
== 0, "Invalid ACE flags %x\n", paaa
->Header
.AceFlags
);
685 ok(paaa
->Mask
== GENERIC_ALL
, "Invalid ACE mask %x\n", paaa
->Mask
);
687 ret
= GetAce(pAcl
, 1, (LPVOID
*)&paaa
);
688 ok(ret
, "GetAce failed with error %u\n", GetLastError());
689 ok(paaa
->Header
.AceType
== ACCESS_DENIED_ACE_TYPE
,
690 "Invalid ACE type %d\n", paaa
->Header
.AceType
);
691 /* first one of two ACEs generated from inheritable entry - without inheritance */
692 ok(paaa
->Header
.AceFlags
== 0, "Invalid ACE flags %x\n", paaa
->Header
.AceFlags
);
693 ok(paaa
->Mask
== GENERIC_WRITE
, "Invalid ACE mask %x\n", paaa
->Mask
);
695 ret
= GetAce(pAcl
, 2, (LPVOID
*)&paaa
);
696 ok(ret
, "GetAce failed with error %u\n", GetLastError());
697 ok(paaa
->Header
.AceType
== ACCESS_DENIED_ACE_TYPE
,
698 "Invalid ACE type %d\n", paaa
->Header
.AceType
);
699 /* second ACE - with inheritance */
700 ok(paaa
->Header
.AceFlags
== MY_INHERITANCE
,
701 "Invalid ACE flags %x\n", paaa
->Header
.AceFlags
);
702 ok(paaa
->Mask
== GENERIC_READ
, "Invalid ACE mask %x\n", paaa
->Mask
);
711 static void test_SHPackDispParams(void)
717 if(!pSHPackDispParams
)
718 win_skip("SHPackSidpParams not available\n");
720 memset(¶ms
, 0xc0, sizeof(params
));
721 memset(vars
, 0xc0, sizeof(vars
));
722 hres
= pSHPackDispParams(¶ms
, vars
, 1, VT_I4
, 0xdeadbeef);
723 ok(hres
== S_OK
, "SHPackDispParams failed: %08x\n", hres
);
724 ok(params
.cArgs
== 1, "params.cArgs = %d\n", params
.cArgs
);
725 ok(params
.cNamedArgs
== 0, "params.cNamedArgs = %d\n", params
.cArgs
);
726 ok(params
.rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", params
.rgdispidNamedArgs
);
727 ok(params
.rgvarg
== vars
, "params.rgvarg = %p\n", params
.rgvarg
);
728 ok(V_VT(vars
) == VT_I4
, "V_VT(var) = %d\n", V_VT(vars
));
729 ok(V_I4(vars
) == 0xdeadbeef, "failed %x\n", V_I4(vars
));
731 memset(¶ms
, 0xc0, sizeof(params
));
732 hres
= pSHPackDispParams(¶ms
, NULL
, 0, 0);
733 ok(hres
== S_OK
, "SHPackDispParams failed: %08x\n", hres
);
734 ok(params
.cArgs
== 0, "params.cArgs = %d\n", params
.cArgs
);
735 ok(params
.cNamedArgs
== 0, "params.cNamedArgs = %d\n", params
.cArgs
);
736 ok(params
.rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", params
.rgdispidNamedArgs
);
737 ok(params
.rgvarg
== NULL
, "params.rgvarg = %p\n", params
.rgvarg
);
739 memset(vars
, 0xc0, sizeof(vars
));
740 memset(¶ms
, 0xc0, sizeof(params
));
741 hres
= pSHPackDispParams(¶ms
, vars
, 4, VT_BSTR
, (void*)0xdeadbeef, VT_EMPTY
, 10,
742 VT_I4
, 100, VT_DISPATCH
, (void*)0xdeadbeef);
743 ok(hres
== S_OK
, "SHPackDispParams failed: %08x\n", hres
);
744 ok(params
.cArgs
== 4, "params.cArgs = %d\n", params
.cArgs
);
745 ok(params
.cNamedArgs
== 0, "params.cNamedArgs = %d\n", params
.cArgs
);
746 ok(params
.rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", params
.rgdispidNamedArgs
);
747 ok(params
.rgvarg
== vars
, "params.rgvarg = %p\n", params
.rgvarg
);
748 ok(V_VT(vars
) == VT_DISPATCH
, "V_VT(vars[0]) = %x\n", V_VT(vars
));
749 ok(V_I4(vars
) == 0xdeadbeef, "V_I4(vars[0]) = %x\n", V_I4(vars
));
750 ok(V_VT(vars
+1) == VT_I4
, "V_VT(vars[1]) = %d\n", V_VT(vars
+1));
751 ok(V_I4(vars
+1) == 100, "V_I4(vars[1]) = %x\n", V_I4(vars
+1));
752 ok(V_VT(vars
+2) == VT_I4
, "V_VT(vars[2]) = %d\n", V_VT(vars
+2));
753 ok(V_I4(vars
+2) == 10, "V_I4(vars[2]) = %x\n", V_I4(vars
+2));
754 ok(V_VT(vars
+3) == VT_BSTR
, "V_VT(vars[3]) = %d\n", V_VT(vars
+3));
755 ok(V_BSTR(vars
+3) == (void*)0xdeadbeef, "V_BSTR(vars[3]) = %p\n", V_BSTR(vars
+3));
760 IDispatch IDispatch_iface
;
764 static inline Disp
*impl_from_IDispatch(IDispatch
*iface
)
766 return CONTAINING_RECORD(iface
, Disp
, IDispatch_iface
);
769 typedef struct _contain
771 IConnectionPointContainer IConnectionPointContainer_iface
;
775 IConnectionPoint
**pt
;
778 static inline Contain
*impl_from_IConnectionPointContainer(IConnectionPointContainer
*iface
)
780 return CONTAINING_RECORD(iface
, Contain
, IConnectionPointContainer_iface
);
783 typedef struct _cntptn
785 IConnectionPoint IConnectionPoint_iface
;
794 static inline ConPt
*impl_from_IConnectionPoint(IConnectionPoint
*iface
)
796 return CONTAINING_RECORD(iface
, ConPt
, IConnectionPoint_iface
);
801 IEnumConnections IEnumConnections_iface
;
808 static inline EnumCon
*impl_from_IEnumConnections(IEnumConnections
*iface
)
810 return CONTAINING_RECORD(iface
, EnumCon
, IEnumConnections_iface
);
813 typedef struct _enumpt
815 IEnumConnectionPoints IEnumConnectionPoints_iface
;
822 static inline EnumPt
*impl_from_IEnumConnectionPoints(IEnumConnectionPoints
*iface
)
824 return CONTAINING_RECORD(iface
, EnumPt
, IEnumConnectionPoints_iface
);
828 static HRESULT WINAPI
Disp_QueryInterface(
835 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDispatch
))
842 IDispatch_AddRef(This
);
846 trace("no interface\n");
847 return E_NOINTERFACE
;
850 static ULONG WINAPI
Disp_AddRef(IDispatch
* This
)
852 Disp
*iface
= impl_from_IDispatch(This
);
853 return InterlockedIncrement(&iface
->refCount
);
856 static ULONG WINAPI
Disp_Release(IDispatch
* This
)
858 Disp
*iface
= impl_from_IDispatch(This
);
861 ret
= InterlockedDecrement(&iface
->refCount
);
863 HeapFree(GetProcessHeap(),0,This
);
867 static HRESULT WINAPI
Disp_GetTypeInfoCount(
871 return ERROR_SUCCESS
;
874 static HRESULT WINAPI
Disp_GetTypeInfo(
880 return ERROR_SUCCESS
;
883 static HRESULT WINAPI
Disp_GetIDsOfNames(
891 return ERROR_SUCCESS
;
894 static HRESULT WINAPI
Disp_Invoke(
900 DISPPARAMS
*pDispParams
,
902 EXCEPINFO
*pExcepInfo
,
905 trace("%p %x %p %x %x %p %p %p %p\n",This
,dispIdMember
,riid
,lcid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,puArgErr
);
907 ok(dispIdMember
== 0xa0 || dispIdMember
== 0xa1, "Unknown dispIdMember\n");
908 ok(pDispParams
!= NULL
, "Invoked with NULL pDispParams\n");
909 ok(wFlags
== DISPATCH_METHOD
, "Wrong flags %x\n",wFlags
);
910 ok(lcid
== 0,"Wrong lcid %x\n",lcid
);
911 if (dispIdMember
== 0xa0)
913 ok(pDispParams
->cArgs
== 0, "params.cArgs = %d\n", pDispParams
->cArgs
);
914 ok(pDispParams
->cNamedArgs
== 0, "params.cNamedArgs = %d\n", pDispParams
->cArgs
);
915 ok(pDispParams
->rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", pDispParams
->rgdispidNamedArgs
);
916 ok(pDispParams
->rgvarg
== NULL
, "params.rgvarg = %p\n", pDispParams
->rgvarg
);
918 else if (dispIdMember
== 0xa1)
920 ok(pDispParams
->cArgs
== 2, "params.cArgs = %d\n", pDispParams
->cArgs
);
921 ok(pDispParams
->cNamedArgs
== 0, "params.cNamedArgs = %d\n", pDispParams
->cArgs
);
922 ok(pDispParams
->rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", pDispParams
->rgdispidNamedArgs
);
923 ok(V_VT(pDispParams
->rgvarg
) == VT_BSTR
, "V_VT(var) = %d\n", V_VT(pDispParams
->rgvarg
));
924 ok(V_I4(pDispParams
->rgvarg
) == 0xdeadcafe , "failed %p\n", V_BSTR(pDispParams
->rgvarg
));
925 ok(V_VT(pDispParams
->rgvarg
+1) == VT_I4
, "V_VT(var) = %d\n", V_VT(pDispParams
->rgvarg
+1));
926 ok(V_I4(pDispParams
->rgvarg
+1) == 0xdeadbeef, "failed %x\n", V_I4(pDispParams
->rgvarg
+1));
929 return ERROR_SUCCESS
;
932 static const IDispatchVtbl disp_vtbl
= {
937 Disp_GetTypeInfoCount
,
943 static HRESULT WINAPI
Enum_QueryInterface(
944 IEnumConnections
* This
,
950 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IEnumConnections
))
957 IEnumConnections_AddRef(This
);
961 trace("no interface\n");
962 return E_NOINTERFACE
;
965 static ULONG WINAPI
Enum_AddRef(IEnumConnections
* This
)
967 EnumCon
*iface
= impl_from_IEnumConnections(This
);
968 return InterlockedIncrement(&iface
->refCount
);
971 static ULONG WINAPI
Enum_Release(IEnumConnections
* This
)
973 EnumCon
*iface
= impl_from_IEnumConnections(This
);
976 ret
= InterlockedDecrement(&iface
->refCount
);
978 HeapFree(GetProcessHeap(),0,This
);
982 static HRESULT WINAPI
Enum_Next(
983 IEnumConnections
* This
,
988 EnumCon
*iface
= impl_from_IEnumConnections(This
);
990 if (cConnections
> 0 && iface
->idx
< iface
->pt
->sinkCount
)
992 rgcd
->pUnk
= iface
->pt
->sink
[iface
->idx
];
993 IUnknown_AddRef(iface
->pt
->sink
[iface
->idx
]);
1004 static HRESULT WINAPI
Enum_Skip(
1005 IEnumConnections
* This
,
1011 static HRESULT WINAPI
Enum_Reset(
1012 IEnumConnections
* This
)
1017 static HRESULT WINAPI
Enum_Clone(
1018 IEnumConnections
* This
,
1019 IEnumConnections
**ppEnum
)
1024 static const IEnumConnectionsVtbl enum_vtbl
= {
1026 Enum_QueryInterface
,
1035 static HRESULT WINAPI
ConPt_QueryInterface(
1036 IConnectionPoint
* This
,
1042 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IConnectionPoint
))
1049 IConnectionPoint_AddRef(This
);
1053 trace("no interface\n");
1054 return E_NOINTERFACE
;
1057 static ULONG WINAPI
ConPt_AddRef(
1058 IConnectionPoint
* This
)
1060 ConPt
*iface
= impl_from_IConnectionPoint(This
);
1061 return InterlockedIncrement(&iface
->refCount
);
1064 static ULONG WINAPI
ConPt_Release(
1065 IConnectionPoint
* This
)
1067 ConPt
*iface
= impl_from_IConnectionPoint(This
);
1070 ret
= InterlockedDecrement(&iface
->refCount
);
1073 if (iface
->sinkCount
> 0)
1076 for (i
= 0; i
< iface
->sinkCount
; i
++)
1079 IUnknown_Release(iface
->sink
[i
]);
1081 HeapFree(GetProcessHeap(),0,iface
->sink
);
1083 HeapFree(GetProcessHeap(),0,This
);
1088 static HRESULT WINAPI
ConPt_GetConnectionInterface(
1089 IConnectionPoint
* This
,
1093 ConPt
*iface
= impl_from_IConnectionPoint(This
);
1100 memcpy(pIID
,&iface
->id
,sizeof(GUID
));
1104 static HRESULT WINAPI
ConPt_GetConnectionPointContainer(
1105 IConnectionPoint
* This
,
1106 IConnectionPointContainer
**ppCPC
)
1108 ConPt
*iface
= impl_from_IConnectionPoint(This
);
1110 *ppCPC
= &iface
->container
->IConnectionPointContainer_iface
;
1114 static HRESULT WINAPI
ConPt_Advise(
1115 IConnectionPoint
* This
,
1119 ConPt
*iface
= impl_from_IConnectionPoint(This
);
1121 if (iface
->sinkCount
== 0)
1122 iface
->sink
= HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown
*));
1124 iface
->sink
= HeapReAlloc(GetProcessHeap(),0,iface
->sink
,sizeof(IUnknown
*)*(iface
->sinkCount
+1));
1125 iface
->sink
[iface
->sinkCount
] = pUnkSink
;
1126 IUnknown_AddRef(pUnkSink
);
1128 *pdwCookie
= iface
->sinkCount
;
1132 static HRESULT WINAPI
ConPt_Unadvise(
1133 IConnectionPoint
* This
,
1136 ConPt
*iface
= impl_from_IConnectionPoint(This
);
1138 if (dwCookie
> iface
->sinkCount
)
1142 IUnknown_Release(iface
->sink
[dwCookie
-1]);
1143 iface
->sink
[dwCookie
-1] = NULL
;
1148 static HRESULT WINAPI
ConPt_EnumConnections(
1149 IConnectionPoint
* This
,
1150 IEnumConnections
**ppEnum
)
1154 ec
= HeapAlloc(GetProcessHeap(),0,sizeof(EnumCon
));
1155 ec
->IEnumConnections_iface
.lpVtbl
= &enum_vtbl
;
1157 ec
->pt
= impl_from_IConnectionPoint(This
);
1159 *ppEnum
= &ec
->IEnumConnections_iface
;
1164 static const IConnectionPointVtbl point_vtbl
= {
1165 ConPt_QueryInterface
,
1169 ConPt_GetConnectionInterface
,
1170 ConPt_GetConnectionPointContainer
,
1173 ConPt_EnumConnections
1176 static HRESULT WINAPI
EnumPt_QueryInterface(
1177 IEnumConnectionPoints
* This
,
1183 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IEnumConnectionPoints
))
1190 IEnumConnectionPoints_AddRef(This
);
1194 trace("no interface\n");
1195 return E_NOINTERFACE
;
1198 static ULONG WINAPI
EnumPt_AddRef(IEnumConnectionPoints
* This
)
1200 EnumPt
*iface
= impl_from_IEnumConnectionPoints(This
);
1201 return InterlockedIncrement(&iface
->refCount
);
1204 static ULONG WINAPI
EnumPt_Release(IEnumConnectionPoints
* This
)
1206 EnumPt
*iface
= impl_from_IEnumConnectionPoints(This
);
1209 ret
= InterlockedDecrement(&iface
->refCount
);
1211 HeapFree(GetProcessHeap(),0,This
);
1215 static HRESULT WINAPI
EnumPt_Next(
1216 IEnumConnectionPoints
* This
,
1218 IConnectionPoint
**rgcd
,
1221 EnumPt
*iface
= impl_from_IEnumConnectionPoints(This
);
1223 if (cConnections
> 0 && iface
->idx
< iface
->container
->ptCount
)
1225 *rgcd
= iface
->container
->pt
[iface
->idx
];
1226 IConnectionPoint_AddRef(iface
->container
->pt
[iface
->idx
]);
1236 static HRESULT WINAPI
EnumPt_Skip(
1237 IEnumConnectionPoints
* This
,
1243 static HRESULT WINAPI
EnumPt_Reset(
1244 IEnumConnectionPoints
* This
)
1249 static HRESULT WINAPI
EnumPt_Clone(
1250 IEnumConnectionPoints
* This
,
1251 IEnumConnectionPoints
**ppEnumPt
)
1256 static const IEnumConnectionPointsVtbl enumpt_vtbl
= {
1258 EnumPt_QueryInterface
,
1267 static HRESULT WINAPI
Contain_QueryInterface(
1268 IConnectionPointContainer
* This
,
1274 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IConnectionPointContainer
))
1281 IConnectionPointContainer_AddRef(This
);
1285 trace("no interface\n");
1286 return E_NOINTERFACE
;
1289 static ULONG WINAPI
Contain_AddRef(
1290 IConnectionPointContainer
* This
)
1292 Contain
*iface
= impl_from_IConnectionPointContainer(This
);
1293 return InterlockedIncrement(&iface
->refCount
);
1296 static ULONG WINAPI
Contain_Release(
1297 IConnectionPointContainer
* This
)
1299 Contain
*iface
= impl_from_IConnectionPointContainer(This
);
1302 ret
= InterlockedDecrement(&iface
->refCount
);
1305 if (iface
->ptCount
> 0)
1308 for (i
= 0; i
< iface
->ptCount
; i
++)
1309 IConnectionPoint_Release(iface
->pt
[i
]);
1310 HeapFree(GetProcessHeap(),0,iface
->pt
);
1312 HeapFree(GetProcessHeap(),0,This
);
1317 static HRESULT WINAPI
Contain_EnumConnectionPoints(
1318 IConnectionPointContainer
* This
,
1319 IEnumConnectionPoints
**ppEnum
)
1323 ec
= HeapAlloc(GetProcessHeap(),0,sizeof(EnumPt
));
1324 ec
->IEnumConnectionPoints_iface
.lpVtbl
= &enumpt_vtbl
;
1327 ec
->container
= impl_from_IConnectionPointContainer(This
);
1328 *ppEnum
= &ec
->IEnumConnectionPoints_iface
;
1333 static HRESULT WINAPI
Contain_FindConnectionPoint(
1334 IConnectionPointContainer
* This
,
1336 IConnectionPoint
**ppCP
)
1338 Contain
*iface
= impl_from_IConnectionPointContainer(This
);
1341 if (!IsEqualIID(riid
, &IID_NULL
) || iface
->ptCount
==0)
1343 pt
= HeapAlloc(GetProcessHeap(),0,sizeof(ConPt
));
1344 pt
->IConnectionPoint_iface
.lpVtbl
= &point_vtbl
;
1348 pt
->container
= iface
;
1349 pt
->id
= IID_IDispatch
;
1351 if (iface
->ptCount
== 0)
1352 iface
->pt
=HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown
*));
1354 iface
->pt
= HeapReAlloc(GetProcessHeap(),0,iface
->pt
,sizeof(IUnknown
*)*(iface
->ptCount
+1));
1355 iface
->pt
[iface
->ptCount
] = &pt
->IConnectionPoint_iface
;
1358 *ppCP
= &pt
->IConnectionPoint_iface
;
1362 *ppCP
= iface
->pt
[0];
1363 IUnknown_AddRef((IUnknown
*)*ppCP
);
1369 static const IConnectionPointContainerVtbl contain_vtbl
= {
1370 Contain_QueryInterface
,
1374 Contain_EnumConnectionPoints
,
1375 Contain_FindConnectionPoint
1378 static void test_IConnectionPoint(void)
1382 IConnectionPoint
*point
;
1385 DWORD cookie
= 0xffffffff;
1389 if (!pIConnectionPoint_SimpleInvoke
|| !pConnectToConnectionPoint
)
1391 win_skip("IConnectionPoint Apis not present\n");
1395 container
= HeapAlloc(GetProcessHeap(),0,sizeof(Contain
));
1396 container
->IConnectionPointContainer_iface
.lpVtbl
= &contain_vtbl
;
1397 container
->refCount
= 1;
1398 container
->ptCount
= 0;
1399 container
->pt
= NULL
;
1401 dispatch
= HeapAlloc(GetProcessHeap(),0,sizeof(Disp
));
1402 dispatch
->IDispatch_iface
.lpVtbl
= &disp_vtbl
;
1403 dispatch
->refCount
= 1;
1405 rc
= pConnectToConnectionPoint((IUnknown
*)dispatch
, &IID_NULL
, TRUE
, (IUnknown
*)container
, &cookie
, &point
);
1406 ok(rc
== S_OK
, "pConnectToConnectionPoint failed with %x\n",rc
);
1407 ok(point
!= NULL
, "returned ConnectionPoint is NULL\n");
1408 ok(cookie
!= 0xffffffff, "invalid cookie returned\n");
1410 rc
= pIConnectionPoint_SimpleInvoke(point
,0xa0,NULL
);
1411 ok(rc
== S_OK
, "pConnectToConnectionPoint failed with %x\n",rc
);
1413 if (pSHPackDispParams
)
1415 memset(¶ms
, 0xc0, sizeof(params
));
1416 memset(vars
, 0xc0, sizeof(vars
));
1417 rc
= pSHPackDispParams(¶ms
, vars
, 2, VT_I4
, 0xdeadbeef, VT_BSTR
, 0xdeadcafe);
1418 ok(rc
== S_OK
, "SHPackDispParams failed: %08x\n", rc
);
1420 rc
= pIConnectionPoint_SimpleInvoke(point
,0xa1,¶ms
);
1421 ok(rc
== S_OK
, "pConnectToConnectionPoint failed with %x\n",rc
);
1424 win_skip("pSHPackDispParams not present\n");
1426 rc
= pConnectToConnectionPoint(NULL
, &IID_NULL
, FALSE
, (IUnknown
*)container
, &cookie
, NULL
);
1427 ok(rc
== S_OK
, "pConnectToConnectionPoint failed with %x\n",rc
);
1429 /* MSDN says this should be required but it crashs on XP
1430 IUnknown_Release(point);
1432 ref
= IUnknown_Release((IUnknown
*)container
);
1433 ok(ref
== 0, "leftover IConnectionPointContainer reference %i\n",ref
);
1434 ref
= IUnknown_Release((IUnknown
*)dispatch
);
1435 ok(ref
== 0, "leftover IDispatch reference %i\n",ref
);
1438 typedef struct _propbag
1440 IPropertyBag IPropertyBag_iface
;
1445 static inline PropBag
*impl_from_IPropertyBag(IPropertyBag
*iface
)
1447 return CONTAINING_RECORD(iface
, PropBag
, IPropertyBag_iface
);
1451 static HRESULT WINAPI
Prop_QueryInterface(
1458 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IPropertyBag
))
1465 IPropertyBag_AddRef(This
);
1469 trace("no interface\n");
1470 return E_NOINTERFACE
;
1473 static ULONG WINAPI
Prop_AddRef(
1476 PropBag
*iface
= impl_from_IPropertyBag(This
);
1477 return InterlockedIncrement(&iface
->refCount
);
1480 static ULONG WINAPI
Prop_Release(
1483 PropBag
*iface
= impl_from_IPropertyBag(This
);
1486 ret
= InterlockedDecrement(&iface
->refCount
);
1488 HeapFree(GetProcessHeap(),0,This
);
1492 static HRESULT WINAPI
Prop_Read(
1494 LPCOLESTR pszPropName
,
1496 IErrorLog
*pErrorLog
)
1498 V_VT(pVar
) = VT_BLOB
|VT_BYREF
;
1499 V_BYREF(pVar
) = (LPVOID
)0xdeadcafe;
1503 static HRESULT WINAPI
Prop_Write(
1505 LPCOLESTR pszPropName
,
1512 static const IPropertyBagVtbl prop_vtbl
= {
1513 Prop_QueryInterface
,
1521 static void test_SHPropertyBag_ReadLONG(void)
1526 static const WCHAR szName1
[] = {'n','a','m','e','1',0};
1528 if (!pSHPropertyBag_ReadLONG
)
1530 win_skip("SHPropertyBag_ReadLONG not present\n");
1534 pb
= HeapAlloc(GetProcessHeap(),0,sizeof(PropBag
));
1536 pb
->IPropertyBag_iface
.lpVtbl
= &prop_vtbl
;
1539 rc
= pSHPropertyBag_ReadLONG(NULL
, szName1
, &out
);
1540 ok(rc
== E_INVALIDARG
|| broken(rc
== 0), "incorrect return %x\n",rc
);
1541 ok(out
== 0xfeedface, "value should not have changed\n");
1542 rc
= pSHPropertyBag_ReadLONG(&pb
->IPropertyBag_iface
, NULL
, &out
);
1543 ok(rc
== E_INVALIDARG
|| broken(rc
== 0) || broken(rc
== 1), "incorrect return %x\n",rc
);
1544 ok(out
== 0xfeedface, "value should not have changed\n");
1545 rc
= pSHPropertyBag_ReadLONG(&pb
->IPropertyBag_iface
, szName1
, NULL
);
1546 ok(rc
== E_INVALIDARG
|| broken(rc
== 0) || broken(rc
== 1), "incorrect return %x\n",rc
);
1547 rc
= pSHPropertyBag_ReadLONG(&pb
->IPropertyBag_iface
, szName1
, &out
);
1548 ok(rc
== DISP_E_BADVARTYPE
|| broken(rc
== 0) || broken(rc
== 1), "incorrect return %x\n",rc
);
1549 ok(out
== 0xfeedface || broken(out
== 0xfeedfa00), "value should not have changed %x\n",out
);
1550 IUnknown_Release((IUnknown
*)pb
);
1555 static void test_SHSetWindowBits(void)
1558 DWORD style
, styleold
;
1561 if(!pSHSetWindowBits
)
1563 win_skip("SHSetWindowBits is not available\n");
1568 clsA
.lpfnWndProc
= DefWindowProcA
;
1569 clsA
.cbClsExtra
= 0;
1570 clsA
.cbWndExtra
= 0;
1571 clsA
.hInstance
= GetModuleHandleA(NULL
);
1573 clsA
.hCursor
= LoadCursorA(0, IDC_ARROW
);
1574 clsA
.hbrBackground
= NULL
;
1575 clsA
.lpszMenuName
= NULL
;
1576 clsA
.lpszClassName
= "Shlwapi test class";
1577 RegisterClassA(&clsA
);
1579 hwnd
= CreateWindowA("Shlwapi test class", "Test", WS_VISIBLE
, 0, 0, 100, 100,
1580 NULL
, NULL
, GetModuleHandle(NULL
), 0);
1581 ok(IsWindow(hwnd
), "failed to create window\n");
1584 SetLastError(0xdeadbeef);
1585 style
= pSHSetWindowBits(NULL
, GWL_STYLE
, 0, 0);
1586 ok(style
== 0, "expected 0 retval, got %d\n", style
);
1587 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
||
1588 broken(GetLastError() == 0xdeadbeef), /* Win9x/WinMe */
1589 "expected ERROR_INVALID_WINDOW_HANDLE, got %d\n", GetLastError());
1591 /* zero mask, zero flags */
1592 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1593 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, 0, 0);
1594 ok(styleold
== style
, "expected old style\n");
1595 ok(styleold
== GetWindowLongA(hwnd
, GWL_STYLE
), "expected to keep old style\n");
1598 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1599 ok(styleold
& WS_VISIBLE
, "expected WS_VISIBLE\n");
1600 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, WS_VISIBLE
, 0);
1602 ok(style
== styleold
, "expected previous style, got %x\n", style
);
1603 ok((GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
) == 0, "expected updated style\n");
1605 /* test mask, unset style bit used */
1606 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1607 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, WS_VISIBLE
, 0);
1608 ok(style
== styleold
, "expected previous style, got %x\n", style
);
1609 ok(styleold
== GetWindowLongA(hwnd
, GWL_STYLE
), "expected to keep old style\n");
1611 /* set back with flags */
1612 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1613 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, WS_VISIBLE
, WS_VISIBLE
);
1614 ok(style
== styleold
, "expected previous style, got %x\n", style
);
1615 ok(GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
, "expected updated style\n");
1617 /* reset and try to set without a mask */
1618 pSHSetWindowBits(hwnd
, GWL_STYLE
, WS_VISIBLE
, 0);
1619 ok((GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
) == 0, "expected updated style\n");
1620 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1621 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, 0, WS_VISIBLE
);
1622 ok(style
== styleold
, "expected previous style, got %x\n", style
);
1623 ok((GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
) == 0, "expected updated style\n");
1625 DestroyWindow(hwnd
);
1627 UnregisterClassA("Shlwapi test class", GetModuleHandleA(NULL
));
1630 static void test_SHFormatDateTimeA(void)
1632 FILETIME UNALIGNED filetime
;
1633 CHAR buff
[100], buff2
[100], buff3
[100];
1638 if(!pSHFormatDateTimeA
)
1640 win_skip("pSHFormatDateTimeA isn't available\n");
1646 /* crashes on native */
1647 pSHFormatDateTimeA(NULL
, NULL
, NULL
, 0);
1651 SystemTimeToFileTime(&st
, &filetime
);
1652 /* SHFormatDateTime expects input as utc */
1653 LocalFileTimeToFileTime(&filetime
, &filetime
);
1655 /* no way to get required buffer length here */
1656 SetLastError(0xdeadbeef);
1657 ret
= pSHFormatDateTimeA(&filetime
, NULL
, NULL
, 0);
1658 ok(ret
== 0, "got %d\n", ret
);
1659 ok(GetLastError() == 0xdeadbeef || broken(GetLastError() == ERROR_SUCCESS
/* Win7 */),
1660 "expected 0xdeadbeef, got %d\n", GetLastError());
1662 SetLastError(0xdeadbeef);
1663 buff
[0] = 'a'; buff
[1] = 0;
1664 ret
= pSHFormatDateTimeA(&filetime
, NULL
, buff
, 0);
1665 ok(ret
== 0, "got %d\n", ret
);
1666 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1667 ok(buff
[0] == 'a', "expected same string, got %s\n", buff
);
1669 /* flags needs to have FDTF_NOAUTOREADINGORDER for these tests to succeed on Vista+ */
1671 /* all combinations documented as invalid succeeded */
1672 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTTIME
| FDTF_LONGTIME
;
1673 SetLastError(0xdeadbeef);
1674 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1675 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1676 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1678 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTDATE
| FDTF_LONGDATE
;
1679 SetLastError(0xdeadbeef);
1680 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1681 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1682 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1684 flags
= FDTF_SHORTDATE
| FDTF_LTRDATE
| FDTF_RTLDATE
;
1685 SetLastError(0xdeadbeef);
1686 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1687 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1688 ok(GetLastError() == 0xdeadbeef ||
1689 broken(GetLastError() == ERROR_INVALID_FLAGS
), /* Win9x/WinMe */
1690 "expected 0xdeadbeef, got %d\n", GetLastError());
1692 /* now check returned strings */
1693 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTTIME
;
1694 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1695 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1696 ret
= GetTimeFormat(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff2
, sizeof(buff2
));
1697 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1698 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1700 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGTIME
;
1701 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1702 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1703 ret
= GetTimeFormat(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff2
, sizeof(buff2
));
1704 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1705 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1707 /* both time flags */
1708 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGTIME
| FDTF_SHORTTIME
;
1709 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1710 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1711 ret
= GetTimeFormat(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff2
, sizeof(buff2
));
1712 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1713 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1715 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTDATE
;
1716 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1717 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1718 ret
= GetDateFormat(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1719 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1720 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1722 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGDATE
;
1723 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1724 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1725 ret
= GetDateFormat(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1726 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1727 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1729 /* both date flags */
1730 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGDATE
| FDTF_SHORTDATE
;
1731 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1732 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1733 ret
= GetDateFormat(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1734 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1735 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1737 /* various combinations of date/time flags */
1738 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGDATE
| FDTF_SHORTTIME
;
1739 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1740 ok(ret
== lstrlenA(buff
)+1, "got %d, length %d\n", ret
, lstrlenA(buff
)+1);
1741 ret
= GetTimeFormat(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff3
, sizeof(buff3
));
1742 ok(ret
== lstrlenA(buff3
)+1, "got %d\n", ret
);
1743 ok(lstrcmpA(buff3
, buff
+ lstrlenA(buff
) - lstrlenA(buff3
)) == 0,
1744 "expected (%s), got (%s) for time part\n",
1745 buff3
, buff
+ lstrlenA(buff
) - lstrlenA(buff3
));
1746 ret
= GetDateFormat(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1747 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1748 buff
[lstrlenA(buff2
)] = '\0';
1749 ok(lstrcmpA(buff2
, buff
) == 0, "expected (%s) got (%s) for date part\n",
1752 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGDATE
| FDTF_LONGTIME
;
1753 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1754 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1755 ret
= GetTimeFormat(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff3
, sizeof(buff3
));
1756 ok(ret
== lstrlenA(buff3
)+1, "got %d\n", ret
);
1757 ok(lstrcmpA(buff3
, buff
+ lstrlenA(buff
) - lstrlenA(buff3
)) == 0,
1758 "expected (%s), got (%s) for time part\n",
1759 buff3
, buff
+ lstrlenA(buff
) - lstrlenA(buff3
));
1760 ret
= GetDateFormat(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1761 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1762 buff
[lstrlenA(buff2
)] = '\0';
1763 ok(lstrcmpA(buff2
, buff
) == 0, "expected (%s) got (%s) for date part\n",
1766 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTDATE
| FDTF_SHORTTIME
;
1767 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1768 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1769 ret
= GetDateFormat(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1770 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1772 ret
= GetTimeFormat(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff3
, sizeof(buff3
));
1773 ok(ret
== lstrlenA(buff3
)+1, "got %d\n", ret
);
1774 strcat(buff2
, buff3
);
1775 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1777 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTDATE
| FDTF_LONGTIME
;
1778 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1779 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1780 ret
= GetDateFormat(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1781 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1783 ret
= GetTimeFormat(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff3
, sizeof(buff3
));
1784 ok(ret
== lstrlenA(buff3
)+1, "got %d\n", ret
);
1785 strcat(buff2
, buff3
);
1786 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1789 static void test_SHFormatDateTimeW(void)
1791 FILETIME UNALIGNED filetime
;
1792 WCHAR buff
[100], buff2
[100], buff3
[100], *p1
, *p2
;
1796 static const WCHAR spaceW
[] = {' ',0};
1797 #define UNICODE_LTR_MARK 0x200e
1799 if(!pSHFormatDateTimeW
)
1801 win_skip("pSHFormatDateTimeW isn't available\n");
1807 /* crashes on native */
1808 pSHFormatDateTimeW(NULL
, NULL
, NULL
, 0);
1812 SystemTimeToFileTime(&st
, &filetime
);
1813 /* SHFormatDateTime expects input as utc */
1814 LocalFileTimeToFileTime(&filetime
, &filetime
);
1816 /* no way to get required buffer length here */
1817 SetLastError(0xdeadbeef);
1818 ret
= pSHFormatDateTimeW(&filetime
, NULL
, NULL
, 0);
1819 ok(ret
== 0, "expected 0, got %d\n", ret
);
1820 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1822 SetLastError(0xdeadbeef);
1823 buff
[0] = 'a'; buff
[1] = 0;
1824 ret
= pSHFormatDateTimeW(&filetime
, NULL
, buff
, 0);
1825 ok(ret
== 0, "expected 0, got %d\n", ret
);
1826 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1827 ok(buff
[0] == 'a', "expected same string\n");
1829 /* all combinations documented as invalid succeeded */
1830 flags
= FDTF_SHORTTIME
| FDTF_LONGTIME
;
1831 SetLastError(0xdeadbeef);
1832 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1833 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1834 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1835 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1837 flags
= FDTF_SHORTDATE
| FDTF_LONGDATE
;
1838 SetLastError(0xdeadbeef);
1839 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1840 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1841 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1842 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1844 flags
= FDTF_SHORTDATE
| FDTF_LTRDATE
| FDTF_RTLDATE
;
1845 SetLastError(0xdeadbeef);
1846 buff
[0] = 0; /* NT4 doesn't clear the buffer on failure */
1847 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1848 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1849 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1850 ok(GetLastError() == 0xdeadbeef ||
1851 broken(GetLastError() == ERROR_INVALID_FLAGS
), /* Win9x/WinMe/NT4 */
1852 "expected 0xdeadbeef, got %d\n", GetLastError());
1854 /* now check returned strings */
1855 flags
= FDTF_SHORTTIME
;
1856 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1857 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1858 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1859 SetLastError(0xdeadbeef);
1860 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1861 if (ret
== 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
1863 win_skip("Needed W-functions are not implemented\n");
1866 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1867 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1869 flags
= FDTF_LONGTIME
;
1870 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1871 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1872 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1873 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1874 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1875 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1877 /* both time flags */
1878 flags
= FDTF_LONGTIME
| FDTF_SHORTTIME
;
1879 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1880 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1881 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1882 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1883 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1884 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal string\n");
1886 flags
= FDTF_SHORTDATE
;
1887 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1888 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1889 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1890 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1891 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1892 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1894 flags
= FDTF_LONGDATE
;
1895 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1896 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1897 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1898 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1899 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1900 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1902 /* both date flags */
1903 flags
= FDTF_LONGDATE
| FDTF_SHORTDATE
;
1904 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1905 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1906 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1907 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1908 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1909 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1911 /* various combinations of date/time flags */
1912 flags
= FDTF_LONGDATE
| FDTF_SHORTTIME
;
1913 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1914 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1915 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1916 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff3
, sizeof(buff3
)/sizeof(WCHAR
));
1917 ok(ret
== lstrlenW(buff3
)+1, "expected %d, got %d\n", lstrlenW(buff3
)+1, ret
);
1918 ok(lstrcmpW(buff3
, buff
+ lstrlenW(buff
) - lstrlenW(buff3
)) == 0,
1919 "expected (%s), got (%s) for time part\n",
1920 wine_dbgstr_w(buff3
), wine_dbgstr_w(buff
+ lstrlenW(buff
) - lstrlenW(buff3
)));
1921 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1922 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1927 while (*p1
== UNICODE_LTR_MARK
)
1929 while (*p2
== UNICODE_LTR_MARK
)
1935 ok(lstrcmpW(buff2
, buff
) == 0, "expected (%s) got (%s) for date part\n",
1936 wine_dbgstr_w(buff2
), wine_dbgstr_w(buff
));
1938 flags
= FDTF_LONGDATE
| FDTF_LONGTIME
;
1939 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1940 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1941 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1942 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff3
, sizeof(buff3
)/sizeof(WCHAR
));
1943 ok(ret
== lstrlenW(buff3
)+1, "expected %d, got %d\n", lstrlenW(buff3
)+1, ret
);
1944 ok(lstrcmpW(buff3
, buff
+ lstrlenW(buff
) - lstrlenW(buff3
)) == 0,
1945 "expected (%s), got (%s) for time part\n",
1946 wine_dbgstr_w(buff3
), wine_dbgstr_w(buff
+ lstrlenW(buff
) - lstrlenW(buff3
)));
1947 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1948 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1953 while (*p1
== UNICODE_LTR_MARK
)
1955 while (*p2
== UNICODE_LTR_MARK
)
1961 ok(lstrcmpW(buff2
, buff
) == 0, "expected (%s) got (%s) for date part\n",
1962 wine_dbgstr_w(buff2
), wine_dbgstr_w(buff
));
1964 flags
= FDTF_SHORTDATE
| FDTF_SHORTTIME
;
1965 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1966 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1967 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1968 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1969 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1970 lstrcatW(buff2
, spaceW
);
1971 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff3
, sizeof(buff3
)/sizeof(WCHAR
));
1972 ok(ret
== lstrlenW(buff3
)+1, "expected %d, got %d\n", lstrlenW(buff3
)+1, ret
);
1973 lstrcatW(buff2
, buff3
);
1974 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1976 flags
= FDTF_SHORTDATE
| FDTF_LONGTIME
;
1977 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1978 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1979 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1980 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1981 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1982 lstrcatW(buff2
, spaceW
);
1983 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff3
, sizeof(buff3
)/sizeof(WCHAR
));
1984 ok(ret
== lstrlenW(buff3
)+1, "expected %d, got %d\n", lstrlenW(buff3
)+1, ret
);
1985 lstrcatW(buff2
, buff3
);
1986 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1989 static void test_SHGetObjectCompatFlags(void)
1991 struct compat_value
{
1996 struct compat_value values
[] = {
1997 { "OTNEEDSSFCACHE", 0x1 },
1998 { "NO_WEBVIEW", 0x2 },
1999 { "UNBINDABLE", 0x4 },
2001 { "NEEDSFILESYSANCESTOR", 0x10 },
2002 { "NOTAFILESYSTEM", 0x20 },
2003 { "CTXMENU_NOVERBS", 0x40 },
2004 { "CTXMENU_LIMITEDQI", 0x80 },
2005 { "COCREATESHELLFOLDERONLY", 0x100 },
2006 { "NEEDSSTORAGEANCESTOR", 0x200 },
2007 { "NOLEGACYWEBVIEW", 0x400 },
2008 { "CTXMENU_XPQCMFLAGS", 0x1000 },
2009 { "NOIPROPERTYSTORE", 0x2000 }
2012 static const char compat_path
[] = "Software\\Microsoft\\Windows\\CurrentVersion\\ShellCompatibility\\Objects";
2013 void *pColorAdjustLuma
= GetProcAddress(hShlwapi
, "ColorAdjustLuma");
2014 CHAR keyA
[39]; /* {CLSID} */
2019 if (!pSHGetObjectCompatFlags
)
2021 win_skip("SHGetObjectCompatFlags isn't available\n");
2025 if (pColorAdjustLuma
&& pColorAdjustLuma
== pSHGetObjectCompatFlags
) /* win2k */
2027 win_skip("Skipping SHGetObjectCompatFlags, same ordinal used for ColorAdjustLuma\n");
2032 ret
= pSHGetObjectCompatFlags(NULL
, NULL
);
2033 ok(ret
== 0, "got %d\n", ret
);
2035 ret
= RegOpenKeyA(HKEY_LOCAL_MACHINE
, compat_path
, &root
);
2036 if (ret
!= ERROR_SUCCESS
)
2038 skip("No compatibility class data found\n");
2042 for (i
= 0; RegEnumKeyA(root
, i
, keyA
, sizeof(keyA
)) == ERROR_SUCCESS
; i
++)
2046 if (RegOpenKeyA(root
, keyA
, &clsid_key
) == ERROR_SUCCESS
)
2049 DWORD expected
= 0, got
, length
= sizeof(valueA
);
2053 for (v
= 0; RegEnumValueA(clsid_key
, v
, valueA
, &length
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
; v
++)
2057 for (j
= 0; j
< sizeof(values
)/sizeof(struct compat_value
); j
++)
2058 if (lstrcmpA(values
[j
].nameA
, valueA
) == 0)
2060 expected
|= values
[j
].value
;
2064 length
= sizeof(valueA
);
2067 pGUIDFromStringA(keyA
, &clsid
);
2068 got
= pSHGetObjectCompatFlags(NULL
, &clsid
);
2069 ok(got
== expected
, "got 0x%08x, expected 0x%08x. Key %s\n", got
, expected
, keyA
);
2071 RegCloseKey(clsid_key
);
2079 IOleCommandTarget IOleCommandTarget_iface
;
2081 } IOleCommandTargetImpl
;
2083 static inline IOleCommandTargetImpl
*impl_from_IOleCommandTarget(IOleCommandTarget
*iface
)
2085 return CONTAINING_RECORD(iface
, IOleCommandTargetImpl
, IOleCommandTarget_iface
);
2088 static const IOleCommandTargetVtbl IOleCommandTargetImpl_Vtbl
;
2090 static IOleCommandTarget
* IOleCommandTargetImpl_Construct(void)
2092 IOleCommandTargetImpl
*obj
;
2094 obj
= HeapAlloc(GetProcessHeap(), 0, sizeof(*obj
));
2095 obj
->IOleCommandTarget_iface
.lpVtbl
= &IOleCommandTargetImpl_Vtbl
;
2098 return &obj
->IOleCommandTarget_iface
;
2101 static HRESULT WINAPI
IOleCommandTargetImpl_QueryInterface(IOleCommandTarget
*iface
, REFIID riid
, void **ppvObj
)
2103 IOleCommandTargetImpl
*This
= impl_from_IOleCommandTarget(iface
);
2105 if (IsEqualIID(riid
, &IID_IUnknown
) ||
2106 IsEqualIID(riid
, &IID_IOleCommandTarget
))
2113 IOleCommandTarget_AddRef(iface
);
2117 return E_NOINTERFACE
;
2120 static ULONG WINAPI
IOleCommandTargetImpl_AddRef(IOleCommandTarget
*iface
)
2122 IOleCommandTargetImpl
*This
= impl_from_IOleCommandTarget(iface
);
2123 return InterlockedIncrement(&This
->ref
);
2126 static ULONG WINAPI
IOleCommandTargetImpl_Release(IOleCommandTarget
*iface
)
2128 IOleCommandTargetImpl
*This
= impl_from_IOleCommandTarget(iface
);
2129 ULONG ref
= InterlockedDecrement(&This
->ref
);
2133 HeapFree(GetProcessHeap(), 0, This
);
2139 static HRESULT WINAPI
IOleCommandTargetImpl_QueryStatus(
2140 IOleCommandTarget
*iface
, const GUID
*group
, ULONG cCmds
, OLECMD prgCmds
[], OLECMDTEXT
*pCmdText
)
2145 static HRESULT WINAPI
IOleCommandTargetImpl_Exec(
2146 IOleCommandTarget
*iface
,
2147 const GUID
*CmdGroup
,
2153 add_call(&trace_got
, 3, CmdGroup
, (void*)(DWORD_PTR
)nCmdID
, (void*)(DWORD_PTR
)nCmdexecopt
, pvaIn
, pvaOut
);
2157 static const IOleCommandTargetVtbl IOleCommandTargetImpl_Vtbl
=
2159 IOleCommandTargetImpl_QueryInterface
,
2160 IOleCommandTargetImpl_AddRef
,
2161 IOleCommandTargetImpl_Release
,
2162 IOleCommandTargetImpl_QueryStatus
,
2163 IOleCommandTargetImpl_Exec
2167 IServiceProvider IServiceProvider_iface
;
2169 } IServiceProviderImpl
;
2171 static inline IServiceProviderImpl
*impl_from_IServiceProvider(IServiceProvider
*iface
)
2173 return CONTAINING_RECORD(iface
, IServiceProviderImpl
, IServiceProvider_iface
);
2177 IProfferService IProfferService_iface
;
2179 } IProfferServiceImpl
;
2181 static inline IProfferServiceImpl
*impl_from_IProfferService(IProfferService
*iface
)
2183 return CONTAINING_RECORD(iface
, IProfferServiceImpl
, IProfferService_iface
);
2187 static const IServiceProviderVtbl IServiceProviderImpl_Vtbl
;
2188 static const IProfferServiceVtbl IProfferServiceImpl_Vtbl
;
2190 static IServiceProvider
* IServiceProviderImpl_Construct(void)
2192 IServiceProviderImpl
*obj
;
2194 obj
= HeapAlloc(GetProcessHeap(), 0, sizeof(*obj
));
2195 obj
->IServiceProvider_iface
.lpVtbl
= &IServiceProviderImpl_Vtbl
;
2198 return &obj
->IServiceProvider_iface
;
2201 static IProfferService
* IProfferServiceImpl_Construct(void)
2203 IProfferServiceImpl
*obj
;
2205 obj
= HeapAlloc(GetProcessHeap(), 0, sizeof(*obj
));
2206 obj
->IProfferService_iface
.lpVtbl
= &IProfferServiceImpl_Vtbl
;
2209 return &obj
->IProfferService_iface
;
2212 static HRESULT WINAPI
IServiceProviderImpl_QueryInterface(IServiceProvider
*iface
, REFIID riid
, void **ppvObj
)
2214 IServiceProviderImpl
*This
= impl_from_IServiceProvider(iface
);
2216 if (IsEqualIID(riid
, &IID_IUnknown
) ||
2217 IsEqualIID(riid
, &IID_IServiceProvider
))
2224 IServiceProvider_AddRef(iface
);
2225 /* native uses redefined IID_IServiceProvider symbol, so we can't compare pointers */
2226 if (IsEqualIID(riid
, &IID_IServiceProvider
))
2227 add_call(&trace_got
, 1, iface
, &IID_IServiceProvider
, 0, 0, 0);
2231 return E_NOINTERFACE
;
2234 static ULONG WINAPI
IServiceProviderImpl_AddRef(IServiceProvider
*iface
)
2236 IServiceProviderImpl
*This
= impl_from_IServiceProvider(iface
);
2237 return InterlockedIncrement(&This
->ref
);
2240 static ULONG WINAPI
IServiceProviderImpl_Release(IServiceProvider
*iface
)
2242 IServiceProviderImpl
*This
= impl_from_IServiceProvider(iface
);
2243 ULONG ref
= InterlockedDecrement(&This
->ref
);
2247 HeapFree(GetProcessHeap(), 0, This
);
2253 static HRESULT WINAPI
IServiceProviderImpl_QueryService(
2254 IServiceProvider
*iface
, REFGUID service
, REFIID riid
, void **ppv
)
2256 /* native uses redefined pointer for IID_IOleCommandTarget, not one from uuid.lib */
2257 if (IsEqualIID(riid
, &IID_IOleCommandTarget
))
2259 add_call(&trace_got
, 2, iface
, service
, &IID_IOleCommandTarget
, 0, 0);
2260 *ppv
= IOleCommandTargetImpl_Construct();
2262 if (IsEqualIID(riid
, &IID_IProfferService
))
2264 if (IsEqualIID(service
, &IID_IProfferService
))
2265 add_call(&trace_got
, 2, &IID_IProfferService
, &IID_IProfferService
, 0, 0, 0);
2266 *ppv
= IProfferServiceImpl_Construct();
2271 static const IServiceProviderVtbl IServiceProviderImpl_Vtbl
=
2273 IServiceProviderImpl_QueryInterface
,
2274 IServiceProviderImpl_AddRef
,
2275 IServiceProviderImpl_Release
,
2276 IServiceProviderImpl_QueryService
2279 static void test_IUnknown_QueryServiceExec(void)
2281 IServiceProvider
*provider
= IServiceProviderImpl_Construct();
2282 static const GUID dummy_serviceid
= { 0xdeadbeef };
2283 static const GUID dummy_groupid
= { 0xbeefbeef };
2284 call_trace_t trace_expected
;
2287 /* on <=W2K platforms same ordinal used for another export with different
2288 prototype, so skipping using this indirect condition */
2289 if (is_win2k_and_lower
)
2291 win_skip("IUnknown_QueryServiceExec is not available\n");
2295 /* null source pointer */
2296 hr
= pIUnknown_QueryServiceExec(NULL
, &dummy_serviceid
, &dummy_groupid
, 0, 0, 0, 0);
2297 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
2300 IUnknown_QueryServiceExec( ptr1, serviceid, groupid, arg1, arg2, arg3, arg4);
2301 -> IUnknown_QueryInterface( ptr1, &IID_IServiceProvider, &prov );
2302 -> IServiceProvider_QueryService( prov, serviceid, &IID_IOleCommandTarget, &obj );
2303 -> IOleCommandTarget_Exec( obj, groupid, arg1, arg2, arg3, arg4 );
2305 init_call_trace(&trace_expected
);
2307 add_call(&trace_expected
, 1, provider
, &IID_IServiceProvider
, 0, 0, 0);
2308 add_call(&trace_expected
, 2, provider
, &dummy_serviceid
, &IID_IOleCommandTarget
, 0, 0);
2309 add_call(&trace_expected
, 3, &dummy_groupid
, (void*)0x1, (void*)0x2, (void*)0x3, (void*)0x4);
2311 init_call_trace(&trace_got
);
2312 hr
= pIUnknown_QueryServiceExec((IUnknown
*)provider
, &dummy_serviceid
, &dummy_groupid
, 0x1, 0x2, (void*)0x3, (void*)0x4);
2313 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2315 ok_trace(&trace_expected
, &trace_got
);
2317 free_call_trace(&trace_expected
);
2318 free_call_trace(&trace_got
);
2320 IServiceProvider_Release(provider
);
2324 static HRESULT WINAPI
IProfferServiceImpl_QueryInterface(IProfferService
*iface
, REFIID riid
, void **ppvObj
)
2326 IProfferServiceImpl
*This
= impl_from_IProfferService(iface
);
2328 if (IsEqualIID(riid
, &IID_IUnknown
) ||
2329 IsEqualIID(riid
, &IID_IProfferService
))
2333 else if (IsEqualIID(riid
, &IID_IServiceProvider
))
2335 *ppvObj
= IServiceProviderImpl_Construct();
2336 add_call(&trace_got
, 1, iface
, &IID_IServiceProvider
, 0, 0, 0);
2342 IProfferService_AddRef(iface
);
2346 return E_NOINTERFACE
;
2349 static ULONG WINAPI
IProfferServiceImpl_AddRef(IProfferService
*iface
)
2351 IProfferServiceImpl
*This
= impl_from_IProfferService(iface
);
2352 return InterlockedIncrement(&This
->ref
);
2355 static ULONG WINAPI
IProfferServiceImpl_Release(IProfferService
*iface
)
2357 IProfferServiceImpl
*This
= impl_from_IProfferService(iface
);
2358 ULONG ref
= InterlockedDecrement(&This
->ref
);
2362 HeapFree(GetProcessHeap(), 0, This
);
2368 static HRESULT WINAPI
IProfferServiceImpl_ProfferService(IProfferService
*iface
,
2369 REFGUID service
, IServiceProvider
*pService
, DWORD
*pCookie
)
2371 *pCookie
= 0xdeadbeef;
2372 add_call(&trace_got
, 3, service
, pService
, pCookie
, 0, 0);
2376 static HRESULT WINAPI
IProfferServiceImpl_RevokeService(IProfferService
*iface
, DWORD cookie
)
2378 add_call(&trace_got
, 4, (void*)(DWORD_PTR
)cookie
, 0, 0, 0, 0);
2382 static const IProfferServiceVtbl IProfferServiceImpl_Vtbl
=
2384 IProfferServiceImpl_QueryInterface
,
2385 IProfferServiceImpl_AddRef
,
2386 IProfferServiceImpl_Release
,
2387 IProfferServiceImpl_ProfferService
,
2388 IProfferServiceImpl_RevokeService
2391 static void test_IUnknown_ProfferService(void)
2393 IServiceProvider
*provider
= IServiceProviderImpl_Construct();
2394 IProfferService
*proff
= IProfferServiceImpl_Construct();
2395 static const GUID dummy_serviceid
= { 0xdeadbeef };
2396 call_trace_t trace_expected
;
2400 /* on <=W2K platforms same ordinal used for another export with different
2401 prototype, so skipping using this indirect condition */
2402 if (is_win2k_and_lower
)
2404 win_skip("IUnknown_ProfferService is not available\n");
2408 /* null source pointer */
2409 hr
= pIUnknown_ProfferService(NULL
, &dummy_serviceid
, 0, 0);
2410 ok(hr
== E_FAIL
, "got 0x%08x\n", hr
);
2413 IUnknown_ProfferService( ptr1, serviceid, arg1, arg2);
2414 -> IUnknown_QueryInterface( ptr1, &IID_IServiceProvider, &provider );
2415 -> IServiceProvider_QueryService( provider, &IID_IProfferService, &IID_IProfferService, &proffer );
2417 if (service pointer not null):
2418 -> IProfferService_ProfferService( proffer, serviceid, arg1, arg2 );
2420 -> IProfferService_RevokeService( proffer, *arg2 );
2422 init_call_trace(&trace_expected
);
2424 add_call(&trace_expected
, 1, proff
, &IID_IServiceProvider
, 0, 0, 0);
2425 add_call(&trace_expected
, 2, &IID_IProfferService
, &IID_IProfferService
, 0, 0, 0);
2426 add_call(&trace_expected
, 3, &dummy_serviceid
, provider
, &cookie
, 0, 0);
2428 init_call_trace(&trace_got
);
2430 hr
= pIUnknown_ProfferService((IUnknown
*)proff
, &dummy_serviceid
, provider
, &cookie
);
2431 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2432 ok(cookie
== 0xdeadbeef, "got %x\n", cookie
);
2434 ok_trace(&trace_expected
, &trace_got
);
2435 free_call_trace(&trace_got
);
2436 free_call_trace(&trace_expected
);
2438 /* same with ::Revoke path */
2439 init_call_trace(&trace_expected
);
2441 add_call(&trace_expected
, 1, proff
, &IID_IServiceProvider
, 0, 0, 0);
2442 add_call(&trace_expected
, 2, &IID_IProfferService
, &IID_IProfferService
, 0, 0, 0);
2443 add_call(&trace_expected
, 4, (void*)(DWORD_PTR
)cookie
, 0, 0, 0, 0);
2445 init_call_trace(&trace_got
);
2446 ok(cookie
!= 0, "got %x\n", cookie
);
2447 hr
= pIUnknown_ProfferService((IUnknown
*)proff
, &dummy_serviceid
, 0, &cookie
);
2448 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2449 ok(cookie
== 0, "got %x\n", cookie
);
2450 ok_trace(&trace_expected
, &trace_got
);
2451 free_call_trace(&trace_got
);
2452 free_call_trace(&trace_expected
);
2454 IServiceProvider_Release(provider
);
2455 IProfferService_Release(proff
);
2458 static void test_SHCreateWorkerWindowA(void)
2466 if (is_win2k_and_lower
)
2468 win_skip("SHCreateWorkerWindowA not available\n");
2472 hwnd
= pSHCreateWorkerWindowA(0, NULL
, 0, 0, 0, 0);
2473 ok(hwnd
!= 0, "expected window\n");
2475 GetClassName(hwnd
, classA
, 20);
2476 ok(lstrcmpA(classA
, "WorkerA") == 0, "expected WorkerA class, got %s\n", classA
);
2478 ret
= GetWindowLongPtrA(hwnd
, 0);
2479 ok(ret
== 0, "got %ld\n", ret
);
2482 memset(&cliA
, 0, sizeof(cliA
));
2483 res
= GetClassInfoA(GetModuleHandle("shlwapi.dll"), "WorkerA", &cliA
);
2484 ok(res
, "failed to get class info\n");
2485 ok(cliA
.style
== 0, "got 0x%08x\n", cliA
.style
);
2486 ok(cliA
.cbClsExtra
== 0, "got %d\n", cliA
.cbClsExtra
);
2487 ok(cliA
.cbWndExtra
== sizeof(LONG_PTR
), "got %d\n", cliA
.cbWndExtra
);
2488 ok(cliA
.lpszMenuName
== 0, "got %s\n", cliA
.lpszMenuName
);
2490 DestroyWindow(hwnd
);
2492 /* set extra bytes */
2493 hwnd
= pSHCreateWorkerWindowA(0, NULL
, 0, 0, 0, 0xdeadbeef);
2494 ok(hwnd
!= 0, "expected window\n");
2496 GetClassName(hwnd
, classA
, 20);
2497 ok(lstrcmpA(classA
, "WorkerA") == 0, "expected WorkerA class, got %s\n", classA
);
2499 ret
= GetWindowLongPtrA(hwnd
, 0);
2500 ok(ret
== 0xdeadbeef, "got %ld\n", ret
);
2503 ret
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
2504 ok(ret
== WS_EX_WINDOWEDGE
||
2505 ret
== (WS_EX_WINDOWEDGE
|WS_EX_LAYOUTRTL
) /* systems with RTL locale */, "0x%08lx\n", ret
);
2507 DestroyWindow(hwnd
);
2509 hwnd
= pSHCreateWorkerWindowA(0, NULL
, WS_EX_TOOLWINDOW
, 0, 0, 0);
2510 ret
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
2511 ok(ret
== (WS_EX_WINDOWEDGE
|WS_EX_TOOLWINDOW
) ||
2512 ret
== (WS_EX_WINDOWEDGE
|WS_EX_TOOLWINDOW
|WS_EX_LAYOUTRTL
) /* systems with RTL locale */, "0x%08lx\n", ret
);
2513 DestroyWindow(hwnd
);
2516 static HRESULT WINAPI
SF_QueryInterface(IShellFolder
*iface
,
2517 REFIID riid
, void **ppv
)
2519 /* SHIShellFolder_EnumObjects doesn't QI the object for IShellFolder */
2520 ok(!IsEqualGUID(&IID_IShellFolder
, riid
),
2521 "Unexpected QI for IShellFolder\n");
2522 return E_NOINTERFACE
;
2525 static ULONG WINAPI
SF_AddRef(IShellFolder
*iface
)
2530 static ULONG WINAPI
SF_Release(IShellFolder
*iface
)
2535 static HRESULT WINAPI
SF_ParseDisplayName(IShellFolder
*iface
,
2536 HWND owner
, LPBC reserved
, LPOLESTR displayName
, ULONG
*eaten
,
2537 LPITEMIDLIST
*idl
, ULONG
*attr
)
2539 ok(0, "Didn't expect ParseDisplayName\n");
2543 static HRESULT WINAPI
SF_EnumObjects(IShellFolder
*iface
,
2544 HWND owner
, SHCONTF flags
, IEnumIDList
**enm
)
2546 *enm
= (IEnumIDList
*)0xcafebabe;
2550 static HRESULT WINAPI
SF_BindToObject(IShellFolder
*iface
,
2551 LPCITEMIDLIST idl
, LPBC reserved
, REFIID riid
, void **obj
)
2553 ok(0, "Didn't expect BindToObject\n");
2557 static HRESULT WINAPI
SF_BindToStorage(IShellFolder
*iface
,
2558 LPCITEMIDLIST idl
, LPBC reserved
, REFIID riid
, void **obj
)
2560 ok(0, "Didn't expect BindToStorage\n");
2564 static HRESULT WINAPI
SF_CompareIDs(IShellFolder
*iface
,
2565 LPARAM lparam
, LPCITEMIDLIST idl1
, LPCITEMIDLIST idl2
)
2567 ok(0, "Didn't expect CompareIDs\n");
2571 static HRESULT WINAPI
SF_CreateViewObject(IShellFolder
*iface
,
2572 HWND owner
, REFIID riid
, void **out
)
2574 ok(0, "Didn't expect CreateViewObject\n");
2578 static HRESULT WINAPI
SF_GetAttributesOf(IShellFolder
*iface
,
2579 UINT cidl
, LPCITEMIDLIST
*idl
, SFGAOF
*inOut
)
2581 ok(0, "Didn't expect GetAttributesOf\n");
2585 static HRESULT WINAPI
SF_GetUIObjectOf(IShellFolder
*iface
,
2586 HWND owner
, UINT cidl
, LPCITEMIDLIST
*idls
, REFIID riid
, UINT
*inOut
,
2589 ok(0, "Didn't expect GetUIObjectOf\n");
2593 static HRESULT WINAPI
SF_GetDisplayNameOf(IShellFolder
*iface
,
2594 LPCITEMIDLIST idl
, SHGDNF flags
, STRRET
*name
)
2596 ok(0, "Didn't expect GetDisplayNameOf\n");
2600 static HRESULT WINAPI
SF_SetNameOf(IShellFolder
*iface
,
2601 HWND hwnd
, LPCITEMIDLIST idl
, LPCOLESTR name
, SHGDNF flags
,
2602 LPITEMIDLIST
*idlOut
)
2604 ok(0, "Didn't expect SetNameOf\n");
2608 static IShellFolderVtbl ShellFolderVtbl
= {
2612 SF_ParseDisplayName
,
2617 SF_CreateViewObject
,
2620 SF_GetDisplayNameOf
,
2624 static IShellFolder ShellFolder
= { &ShellFolderVtbl
};
2626 static void test_SHIShellFolder_EnumObjects(void)
2630 IShellFolder
*folder
;
2632 if(!pSHIShellFolder_EnumObjects
|| is_win2k_and_lower
){
2633 win_skip("SHIShellFolder_EnumObjects not available\n");
2638 /* NULL object crashes on Windows */
2639 pSHIShellFolder_EnumObjects(NULL
, NULL
, 0, NULL
);
2642 /* SHIShellFolder_EnumObjects doesn't QI the object for IShellFolder */
2643 enm
= (IEnumIDList
*)0xdeadbeef;
2644 hres
= pSHIShellFolder_EnumObjects(&ShellFolder
, NULL
, 0, &enm
);
2645 ok(hres
== S_OK
, "SHIShellFolder_EnumObjects failed: 0x%08x\n", hres
);
2646 ok(enm
== (IEnumIDList
*)0xcafebabe, "Didn't get expected enumerator location, instead: %p\n", enm
);
2648 /* SHIShellFolder_EnumObjects isn't strict about the IShellFolder object */
2649 hres
= pSHGetDesktopFolder(&folder
);
2650 ok(hres
== S_OK
, "SHGetDesktopFolder failed: 0x%08x\n", hres
);
2653 hres
= pSHIShellFolder_EnumObjects(folder
, NULL
, 0, &enm
);
2654 ok(hres
== S_OK
, "SHIShellFolder_EnumObjects failed: 0x%08x\n", hres
);
2655 ok(enm
!= NULL
, "Didn't get an enumerator\n");
2657 IEnumIDList_Release(enm
);
2659 IShellFolder_Release(folder
);
2662 static void write_inifile(LPCWSTR filename
)
2667 static const char data
[] =
2670 "AnotherKey=asdf\r\n";
2672 file
= CreateFileW(filename
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
2673 if(file
== INVALID_HANDLE_VALUE
)
2676 WriteFile(file
, data
, sizeof(data
), &written
, NULL
);
2681 #define verify_inifile(f, e) r_verify_inifile(__LINE__, f, e)
2682 static void r_verify_inifile(unsigned l
, LPCWSTR filename
, LPCSTR exp
)
2688 file
= CreateFileW(filename
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, 0, NULL
);
2689 if(file
== INVALID_HANDLE_VALUE
)
2692 ReadFile(file
, buf
, sizeof(buf
) * sizeof(CHAR
), &read
, NULL
);
2697 ok_(__FILE__
,l
)(!strcmp(buf
, exp
), "Expected:\n%s\nGot:\n%s\n", exp
,
2701 static void test_SHGetIniString(void)
2704 WCHAR out
[64] = {0};
2706 static const WCHAR TestAppW
[] = {'T','e','s','t','A','p','p',0};
2707 static const WCHAR TestIniW
[] = {'C',':','\\','t','e','s','t','.','i','n','i',0};
2708 static const WCHAR AKeyW
[] = {'A','K','e','y',0};
2709 static const WCHAR AnotherKeyW
[] = {'A','n','o','t','h','e','r','K','e','y',0};
2710 static const WCHAR JunkKeyW
[] = {'J','u','n','k','K','e','y',0};
2712 if(!pSHGetIniStringW
|| is_win2k_and_lower
){
2713 win_skip("SHGetIniStringW is not available\n");
2717 write_inifile(TestIniW
);
2720 /* these crash on Windows */
2721 pSHGetIniStringW(NULL
, NULL
, NULL
, 0, NULL
);
2722 pSHGetIniStringW(NULL
, AKeyW
, out
, sizeof(out
), TestIniW
);
2723 pSHGetIniStringW(TestAppW
, AKeyW
, NULL
, sizeof(out
), TestIniW
);
2726 ret
= pSHGetIniStringW(TestAppW
, AKeyW
, out
, 0, TestIniW
);
2727 ok(ret
== 0, "SHGetIniStringW should have given 0, instead: %d\n", ret
);
2729 /* valid arguments */
2730 ret
= pSHGetIniStringW(TestAppW
, NULL
, out
, sizeof(out
), TestIniW
);
2731 ok(broken(ret
== 0) || /* win 98 */
2732 ret
== 4, "SHGetIniStringW should have given 4, instead: %d\n", ret
);
2733 ok(!lstrcmpW(out
, AKeyW
), "Expected %s, got: %s\n",
2734 wine_dbgstr_w(AKeyW
), wine_dbgstr_w(out
));
2736 ret
= pSHGetIniStringW(TestAppW
, AKeyW
, out
, sizeof(out
), TestIniW
);
2737 ok(broken(ret
== 0) || /* win 98 */
2738 ret
== 1, "SHGetIniStringW should have given 1, instead: %d\n", ret
);
2739 ok(broken(*out
== 0) || /*win 98 */
2740 !strcmp_wa(out
, "1"), "Expected L\"1\", got: %s\n", wine_dbgstr_w(out
));
2742 ret
= pSHGetIniStringW(TestAppW
, AnotherKeyW
, out
, sizeof(out
), TestIniW
);
2743 ok(broken(ret
== 0) || /* win 98 */
2744 ret
== 4, "SHGetIniStringW should have given 4, instead: %d\n", ret
);
2745 ok(broken(*out
== 0) || /* win 98 */
2746 !strcmp_wa(out
, "asdf"), "Expected L\"asdf\", got: %s\n", wine_dbgstr_w(out
));
2748 ret
= pSHGetIniStringW(TestAppW
, JunkKeyW
, out
, sizeof(out
), TestIniW
);
2749 ok(ret
== 0, "SHGetIniStringW should have given 0, instead: %d\n", ret
);
2750 ok(*out
== 0, "Expected L\"\", got: %s\n", wine_dbgstr_w(out
));
2752 DeleteFileW(TestIniW
);
2755 static void test_SHSetIniString(void)
2759 static const WCHAR TestAppW
[] = {'T','e','s','t','A','p','p',0};
2760 static const WCHAR AnotherAppW
[] = {'A','n','o','t','h','e','r','A','p','p',0};
2761 static const WCHAR TestIniW
[] = {'C',':','\\','t','e','s','t','.','i','n','i',0};
2762 static const WCHAR AKeyW
[] = {'A','K','e','y',0};
2763 static const WCHAR NewKeyW
[] = {'N','e','w','K','e','y',0};
2764 static const WCHAR AValueW
[] = {'A','V','a','l','u','e',0};
2766 if(!pSHSetIniStringW
|| is_win2k_and_lower
){
2767 win_skip("SHSetIniStringW is not available\n");
2771 write_inifile(TestIniW
);
2773 ret
= pSHSetIniStringW(TestAppW
, AKeyW
, AValueW
, TestIniW
);
2774 ok(ret
== TRUE
, "SHSetIniStringW should not have failed\n");
2775 todo_wine
/* wine sticks an extra \r\n at the end of the file */
2776 verify_inifile(TestIniW
, "[TestApp]\r\nAKey=AValue\r\nAnotherKey=asdf\r\n");
2778 ret
= pSHSetIniStringW(TestAppW
, AKeyW
, NULL
, TestIniW
);
2779 ok(ret
== TRUE
, "SHSetIniStringW should not have failed\n");
2780 verify_inifile(TestIniW
, "[TestApp]\r\nAnotherKey=asdf\r\n");
2782 ret
= pSHSetIniStringW(AnotherAppW
, NewKeyW
, AValueW
, TestIniW
);
2783 ok(ret
== TRUE
, "SHSetIniStringW should not have failed\n");
2784 verify_inifile(TestIniW
, "[TestApp]\r\nAnotherKey=asdf\r\n[AnotherApp]\r\nNewKey=AValue\r\n");
2786 ret
= pSHSetIniStringW(TestAppW
, NULL
, AValueW
, TestIniW
);
2787 ok(ret
== TRUE
, "SHSetIniStringW should not have failed\n");
2788 verify_inifile(TestIniW
, "[AnotherApp]\r\nNewKey=AValue\r\n");
2790 DeleteFileW(TestIniW
);
2793 enum _shellkey_flags
{
2794 SHKEY_Root_HKCU
= 0x1,
2795 SHKEY_Root_HKLM
= 0x2,
2796 SHKEY_Key_Explorer
= 0x00,
2797 SHKEY_Key_Shell
= 0x10,
2798 SHKEY_Key_ShellNoRoam
= 0x20,
2799 SHKEY_Key_Classes
= 0x30,
2800 SHKEY_Subkey_Default
= 0x0000,
2801 SHKEY_Subkey_ResourceName
= 0x1000,
2802 SHKEY_Subkey_Handlers
= 0x2000,
2803 SHKEY_Subkey_Associations
= 0x3000,
2804 SHKEY_Subkey_Volatile
= 0x4000,
2805 SHKEY_Subkey_MUICache
= 0x5000,
2806 SHKEY_Subkey_FileExts
= 0x6000
2809 static void test_SHGetShellKey(void)
2811 static const WCHAR ShellFoldersW
[] = { 'S','h','e','l','l',' ','F','o','l','d','e','r','s',0 };
2812 static const WCHAR WineTestW
[] = { 'W','i','n','e','T','e','s','t',0 };
2814 void *pPathBuildRootW
= GetProcAddress(hShlwapi
, "PathBuildRootW");
2815 DWORD
*alloc_data
, data
, size
;
2819 if (!pSHGetShellKey
)
2821 win_skip("SHGetShellKey(ordinal 491) isn't available\n");
2826 if (pPathBuildRootW
&& pPathBuildRootW
== pSHGetShellKey
)
2828 win_skip("SHGetShellKey(ordinal 491) used for PathBuildRootW\n");
2832 if (is_win9x
|| is_win2k_and_lower
)
2834 win_skip("Ordinal 491 used for another call, skipping SHGetShellKey tests\n");
2838 /* Vista+ limits SHKEY enumeration values */
2839 SetLastError(0xdeadbeef);
2840 hkey
= pSHGetShellKey(SHKEY_Key_Explorer
, ShellFoldersW
, FALSE
);
2843 /* Tests not working on Vista+ */
2846 hkey
= pSHGetShellKey(SHKEY_Root_HKLM
|SHKEY_Key_Classes
, NULL
, FALSE
);
2847 ok(hkey
!= NULL
, "hkey = NULL\n");
2851 hkey
= pSHGetShellKey(SHKEY_Root_HKCU
|SHKEY_Key_Explorer
, ShellFoldersW
, FALSE
);
2852 ok(hkey
!= NULL
, "hkey = NULL\n");
2855 hkey
= pSHGetShellKey(SHKEY_Root_HKLM
|SHKEY_Key_Explorer
, ShellFoldersW
, FALSE
);
2856 ok(hkey
!= NULL
, "hkey = NULL\n");
2859 hkey
= pSHGetShellKey(SHKEY_Root_HKLM
, WineTestW
, FALSE
);
2860 ok(hkey
== NULL
, "hkey != NULL\n");
2862 hkey
= pSHGetShellKey(SHKEY_Root_HKLM
, NULL
, FALSE
);
2863 ok(hkey
!= NULL
, "Can't open key\n");
2864 ok(SUCCEEDED(RegDeleteKeyW(hkey
, WineTestW
)), "Can't delete key\n");
2867 hkey
= pSHGetShellKey(SHKEY_Root_HKLM
, WineTestW
, TRUE
);
2868 if (!hkey
&& GetLastError() == ERROR_ACCESS_DENIED
)
2870 skip("Not authorized to create keys\n");
2873 ok(hkey
!= NULL
, "Can't create key\n");
2876 if (!pSKGetValueW
|| !pSKSetValueW
|| !pSKDeleteValueW
|| !pSKAllocValueW
)
2878 win_skip("SKGetValueW, SKSetValueW, SKDeleteValueW or SKAllocValueW not available\n");
2882 size
= sizeof(data
);
2883 hres
= pSKGetValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
, NULL
, &data
, &size
);
2884 ok(hres
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), "hres = %x\n", hres
);
2887 hres
= pSKSetValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
, REG_DWORD
, &data
, sizeof(DWORD
));
2888 ok(hres
== S_OK
, "hres = %x\n", hres
);
2891 hres
= pSKGetValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
, NULL
, NULL
, &size
);
2892 ok(hres
== S_OK
, "hres = %x\n", hres
);
2893 ok(size
== sizeof(DWORD
), "size = %d\n", size
);
2896 hres
= pSKGetValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
, NULL
, &data
, &size
);
2897 ok(hres
== S_OK
, "hres = %x\n", hres
);
2898 ok(size
== sizeof(DWORD
), "size = %d\n", size
);
2899 ok(data
== 1234, "data = %d\n", data
);
2901 hres
= pSKAllocValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
, NULL
, (void**)&alloc_data
, &size
);
2902 ok(hres
== S_OK
, "hres= %x\n", hres
);
2903 ok(size
== sizeof(DWORD
), "size = %d\n", size
);
2904 if (SUCCEEDED(hres
))
2906 ok(*alloc_data
== 1234, "*alloc_data = %d\n", *alloc_data
);
2907 LocalFree(alloc_data
);
2910 hres
= pSKDeleteValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
);
2911 ok(hres
== S_OK
, "hres = %x\n", hres
);
2913 hres
= pSKDeleteValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
);
2914 ok(hres
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), "hres = %x\n", hres
);
2916 hres
= pSKGetValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
, NULL
, &data
, &size
);
2917 ok(hres
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), "hres = %x\n", hres
);
2919 hkey
= pSHGetShellKey(SHKEY_Root_HKLM
, NULL
, FALSE
);
2920 ok(hkey
!= NULL
, "Can't create key\n");
2921 ok(SUCCEEDED(RegDeleteKeyW(hkey
, WineTestW
)), "Can't delete key\n");
2925 static void init_pointers(void)
2927 #define MAKEFUNC(f, ord) (p##f = (void*)GetProcAddress(hShlwapi, (LPSTR)(ord)))
2928 MAKEFUNC(SHAllocShared
, 7);
2929 MAKEFUNC(SHLockShared
, 8);
2930 MAKEFUNC(SHUnlockShared
, 9);
2931 MAKEFUNC(SHFreeShared
, 10);
2932 MAKEFUNC(GetAcceptLanguagesA
, 14);
2933 MAKEFUNC(SHSetWindowBits
, 165);
2934 MAKEFUNC(SHSetParentHwnd
, 167);
2935 MAKEFUNC(ConnectToConnectionPoint
, 168);
2936 MAKEFUNC(SHSearchMapInt
, 198);
2937 MAKEFUNC(SHCreateWorkerWindowA
, 257);
2938 MAKEFUNC(GUIDFromStringA
, 269);
2939 MAKEFUNC(SHPackDispParams
, 282);
2940 MAKEFUNC(IConnectionPoint_InvokeWithCancel
, 283);
2941 MAKEFUNC(IConnectionPoint_SimpleInvoke
, 284);
2942 MAKEFUNC(SHGetIniStringW
, 294);
2943 MAKEFUNC(SHSetIniStringW
, 295);
2944 MAKEFUNC(SHFormatDateTimeA
, 353);
2945 MAKEFUNC(SHFormatDateTimeW
, 354);
2946 MAKEFUNC(SHIShellFolder_EnumObjects
, 404);
2947 MAKEFUNC(SHGetObjectCompatFlags
, 476);
2948 MAKEFUNC(IUnknown_QueryServiceExec
, 484);
2949 MAKEFUNC(SHGetShellKey
, 491);
2950 MAKEFUNC(SHPropertyBag_ReadLONG
, 496);
2951 MAKEFUNC(IUnknown_ProfferService
, 514);
2952 MAKEFUNC(SKGetValueW
, 516);
2953 MAKEFUNC(SKSetValueW
, 517);
2954 MAKEFUNC(SKDeleteValueW
, 518);
2955 MAKEFUNC(SKAllocValueW
, 519);
2959 static void test_SHSetParentHwnd(void)
2961 HWND hwnd
, hwnd2
, ret
;
2964 if (!pSHSetParentHwnd
)
2966 win_skip("SHSetParentHwnd not available\n");
2970 hwnd
= CreateWindowA("Button", "", WS_VISIBLE
, 0, 0, 10, 10, NULL
, NULL
, NULL
, NULL
);
2971 ok(hwnd
!= NULL
, "got %p\n", hwnd
);
2973 hwnd2
= CreateWindowA("Button", "", WS_VISIBLE
| WS_CHILD
, 0, 0, 10, 10, hwnd
, NULL
, NULL
, NULL
);
2974 ok(hwnd2
!= NULL
, "got %p\n", hwnd2
);
2977 ret
= pSHSetParentHwnd(NULL
, NULL
);
2978 ok(ret
== NULL
, "got %p\n", ret
);
2980 /* set to no parent while already no parent present */
2981 ret
= GetParent(hwnd
);
2982 ok(ret
== NULL
, "got %p\n", ret
);
2983 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
2984 ok((style
& (WS_POPUP
|WS_CHILD
)) == 0, "got style 0x%08x\n", style
);
2985 ret
= pSHSetParentHwnd(hwnd
, NULL
);
2986 ok(ret
== NULL
, "got %p\n", ret
);
2987 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
2988 ok((style
& (WS_POPUP
|WS_CHILD
)) == 0, "got style 0x%08x\n", style
);
2990 /* reset to null parent from not null */
2991 ret
= GetParent(hwnd2
);
2992 ok(ret
== hwnd
, "got %p\n", ret
);
2993 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
2994 ok((style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
, "got style 0x%08x\n", style
);
2995 ret
= pSHSetParentHwnd(hwnd2
, NULL
);
2996 ok(ret
== NULL
, "got %p\n", ret
);
2997 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
2998 ok((style
& (WS_POPUP
|WS_CHILD
)) == WS_POPUP
, "got style 0x%08x\n", style
);
2999 ret
= GetParent(hwnd2
);
3000 ok(ret
== NULL
, "got %p\n", ret
);
3002 /* set parent back */
3003 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
3004 SetWindowLongA(hwnd2
, GWL_STYLE
, style
& ~(WS_CHILD
|WS_POPUP
));
3005 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
3006 ok((style
& (WS_CHILD
|WS_POPUP
)) == 0, "got 0x%08x\n", style
);
3008 ret
= pSHSetParentHwnd(hwnd2
, hwnd
);
3009 todo_wine
ok(ret
== NULL
, "got %p\n", ret
);
3011 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
3012 ok((style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
, "got style 0x%08x\n", style
);
3013 ret
= GetParent(hwnd2
);
3014 ok(ret
== hwnd
, "got %p\n", ret
);
3016 /* try to set same parent again */
3018 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
3019 SetWindowLongA(hwnd2
, GWL_STYLE
, style
| WS_POPUP
);
3020 ret
= pSHSetParentHwnd(hwnd2
, hwnd
);
3021 todo_wine
ok(ret
== NULL
, "got %p\n", ret
);
3022 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
3023 ok((style
& (WS_CHILD
|WS_POPUP
)) == WS_CHILD
, "got 0x%08x\n", style
);
3024 ret
= GetParent(hwnd2
);
3025 ok(ret
== hwnd
, "got %p\n", ret
);
3027 /* without WS_POPUP */
3028 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
3029 SetWindowLongA(hwnd2
, GWL_STYLE
, style
| ~WS_POPUP
);
3030 ret
= pSHSetParentHwnd(hwnd2
, hwnd
);
3031 todo_wine
ok(ret
== hwnd
, "got %p\n", ret
);
3032 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
3033 ok((style
& (WS_CHILD
|WS_POPUP
)) == WS_CHILD
, "got 0x%08x\n", style
);
3034 ret
= GetParent(hwnd2
);
3035 ok(ret
== hwnd
, "got %p\n", ret
);
3037 DestroyWindow(hwnd
);
3038 DestroyWindow(hwnd2
);
3043 hShlwapi
= GetModuleHandleA("shlwapi.dll");
3044 is_win2k_and_lower
= GetProcAddress(hShlwapi
, "StrChrNW") == 0;
3045 is_win9x
= GetProcAddress(hShlwapi
, (LPSTR
)99) == 0; /* StrCpyNXA */
3047 /* SHCreateStreamOnFileEx was introduced in shlwapi v6.0 */
3048 if(!GetProcAddress(hShlwapi
, "SHCreateStreamOnFileEx")){
3049 win_skip("Too old shlwapi version\n");
3055 hmlang
= LoadLibraryA("mlang.dll");
3056 pLcidToRfc1766A
= (void *)GetProcAddress(hmlang
, "LcidToRfc1766A");
3058 hshell32
= LoadLibraryA("shell32.dll");
3059 pSHGetDesktopFolder
= (void *)GetProcAddress(hshell32
, "SHGetDesktopFolder");
3061 test_GetAcceptLanguagesA();
3062 test_SHSearchMapInt();
3063 test_alloc_shared();
3065 test_GetShellSecurityDescriptor();
3066 test_SHPackDispParams();
3067 test_IConnectionPoint();
3068 test_SHPropertyBag_ReadLONG();
3069 test_SHSetWindowBits();
3070 test_SHFormatDateTimeA();
3071 test_SHFormatDateTimeW();
3072 test_SHGetObjectCompatFlags();
3073 test_IUnknown_QueryServiceExec();
3074 test_IUnknown_ProfferService();
3075 test_SHCreateWorkerWindowA();
3076 test_SHIShellFolder_EnumObjects();
3077 test_SHGetIniString();
3078 test_SHSetIniString();
3079 test_SHGetShellKey();
3080 test_SHSetParentHwnd();
3082 FreeLibrary(hshell32
);
3083 FreeLibrary(hmlang
);