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 HANDLE (WINAPI
*pSHMapHandle
)(HANDLE
,DWORD
,DWORD
,DWORD
,DWORD
);
56 static HRESULT(WINAPIV
*pSHPackDispParams
)(DISPPARAMS
*,VARIANTARG
*,UINT
,...);
57 static HRESULT(WINAPI
*pIConnectionPoint_SimpleInvoke
)(IConnectionPoint
*,DISPID
,DISPPARAMS
*);
58 static HRESULT(WINAPI
*pIConnectionPoint_InvokeWithCancel
)(IConnectionPoint
*,DISPID
,DISPPARAMS
*,DWORD
,DWORD
);
59 static HRESULT(WINAPI
*pConnectToConnectionPoint
)(IUnknown
*,REFIID
,BOOL
,IUnknown
*, LPDWORD
,IConnectionPoint
**);
60 static HRESULT(WINAPI
*pSHPropertyBag_ReadLONG
)(IPropertyBag
*,LPCWSTR
,LPLONG
);
61 static LONG (WINAPI
*pSHSetWindowBits
)(HWND
, INT
, UINT
, UINT
);
62 static INT (WINAPI
*pSHFormatDateTimeA
)(const FILETIME UNALIGNED
*, DWORD
*, LPSTR
, UINT
);
63 static INT (WINAPI
*pSHFormatDateTimeW
)(const FILETIME UNALIGNED
*, DWORD
*, LPWSTR
, UINT
);
64 static DWORD (WINAPI
*pSHGetObjectCompatFlags
)(IUnknown
*, const CLSID
*);
65 static BOOL (WINAPI
*pGUIDFromStringA
)(LPSTR
, CLSID
*);
66 static HRESULT (WINAPI
*pIUnknown_QueryServiceExec
)(IUnknown
*, REFIID
, const GUID
*, DWORD
, DWORD
, VARIANT
*, VARIANT
*);
67 static HRESULT (WINAPI
*pIUnknown_ProfferService
)(IUnknown
*, REFGUID
, IServiceProvider
*, DWORD
*);
68 static HWND (WINAPI
*pSHCreateWorkerWindowA
)(LONG
, HWND
, DWORD
, DWORD
, HMENU
, LONG_PTR
);
69 static HRESULT (WINAPI
*pSHIShellFolder_EnumObjects
)(LPSHELLFOLDER
, HWND
, SHCONTF
, IEnumIDList
**);
70 static DWORD (WINAPI
*pSHGetIniStringW
)(LPCWSTR
, LPCWSTR
, LPWSTR
, DWORD
, LPCWSTR
);
71 static BOOL (WINAPI
*pSHSetIniStringW
)(LPCWSTR
, LPCWSTR
, LPCWSTR
, LPCWSTR
);
72 static HKEY (WINAPI
*pSHGetShellKey
)(DWORD
, LPCWSTR
, BOOL
);
73 static HRESULT (WINAPI
*pSKGetValueW
)(DWORD
, LPCWSTR
, LPCWSTR
, DWORD
*, void*, DWORD
*);
74 static HRESULT (WINAPI
*pSKSetValueW
)(DWORD
, LPCWSTR
, LPCWSTR
, DWORD
, void*, DWORD
);
75 static HRESULT (WINAPI
*pSKDeleteValueW
)(DWORD
, LPCWSTR
, LPCWSTR
);
76 static HRESULT (WINAPI
*pSKAllocValueW
)(DWORD
, LPCWSTR
, LPCWSTR
, DWORD
*, void**, DWORD
*);
77 static HWND (WINAPI
*pSHSetParentHwnd
)(HWND
, HWND
);
79 static HMODULE hmlang
;
80 static HRESULT (WINAPI
*pLcidToRfc1766A
)(LCID
, LPSTR
, INT
);
82 static HMODULE hshell32
;
83 static HRESULT (WINAPI
*pSHGetDesktopFolder
)(IShellFolder
**);
85 static const CHAR ie_international
[] = {
86 'S','o','f','t','w','a','r','e','\\',
87 'M','i','c','r','o','s','o','f','t','\\',
88 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
89 'I','n','t','e','r','n','a','t','i','o','n','a','l',0};
90 static const CHAR acceptlanguage
[] = {
91 'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0};
93 static int strcmp_wa(LPCWSTR strw
, const char *stra
)
96 WideCharToMultiByte(CP_ACP
, 0, strw
, -1, buf
, sizeof(buf
), NULL
, NULL
);
97 return lstrcmpA(stra
, buf
);
111 static void init_call_trace(call_trace_t
*ctrace
)
115 ctrace
->calls
= HeapAlloc(GetProcessHeap(), 0, sizeof(call_entry_t
) * ctrace
->alloc
);
118 static void free_call_trace(const call_trace_t
*ctrace
)
120 HeapFree(GetProcessHeap(), 0, ctrace
->calls
);
123 static void add_call(call_trace_t
*ctrace
, int id
, const void *arg0
,
124 const void *arg1
, const void *arg2
, const void *arg3
, const void *arg4
)
135 if (ctrace
->count
== ctrace
->alloc
)
138 ctrace
->calls
= HeapReAlloc(GetProcessHeap(),0, ctrace
->calls
, ctrace
->alloc
*sizeof(call_entry_t
));
141 ctrace
->calls
[ctrace
->count
++] = call
;
144 static void ok_trace_(call_trace_t
*texpected
, call_trace_t
*tgot
, int line
)
146 if (texpected
->count
== tgot
->count
)
150 for (i
= 0; i
< texpected
->count
; i
++)
152 call_entry_t
*expected
= &texpected
->calls
[i
];
153 call_entry_t
*got
= &tgot
->calls
[i
];
156 ok_(__FILE__
, line
)(expected
->id
== got
->id
, "got different ids %d: %d, %d\n", i
+1, expected
->id
, got
->id
);
158 for (j
= 0; j
< 5; j
++)
160 ok_(__FILE__
, line
)(expected
->args
[j
] == got
->args
[j
], "got different args[%d] for %d: %p, %p\n", j
, i
+1,
161 expected
->args
[j
], got
->args
[j
]);
166 ok_(__FILE__
, line
)(0, "traces length mismatch\n");
169 #define ok_trace(a, b) ok_trace_(a, b, __LINE__)
171 /* trace of actually made calls */
172 static call_trace_t trace_got
;
174 static void test_GetAcceptLanguagesA(void)
176 static LPCSTR table
[] = {"de,en-gb;q=0.7,en;q=0.3",
177 "de,en;q=0.3,en-gb;q=0.7", /* sorting is ignored */
178 "winetest", /* content is ignored */
188 LONG res_query
= ERROR_SUCCESS
;
191 DWORD maxlen
= sizeof(buffer
) - 2;
197 if (!pGetAcceptLanguagesA
) {
198 win_skip("GetAcceptLanguagesA is not available\n");
202 lcid
= GetUserDefaultLCID();
204 /* Get the original Value */
205 lres
= RegOpenKeyA(HKEY_CURRENT_USER
, ie_international
, &hroot
);
207 skip("RegOpenKey(%s) failed: %d\n", ie_international
, lres
);
210 len
= sizeof(original
);
212 res_query
= RegQueryValueExA(hroot
, acceptlanguage
, 0, NULL
, (PBYTE
)original
, &len
);
214 RegDeleteValueA(hroot
, acceptlanguage
);
216 /* Some windows versions use "lang-COUNTRY" as default */
217 memset(language
, 0, sizeof(language
));
218 len
= GetLocaleInfoA(lcid
, LOCALE_SISO639LANGNAME
, language
, sizeof(language
));
221 lstrcatA(language
, "-");
222 memset(buffer
, 0, sizeof(buffer
));
223 len
= GetLocaleInfoA(lcid
, LOCALE_SISO3166CTRYNAME
, buffer
, sizeof(buffer
) - len
- 1);
224 lstrcatA(language
, buffer
);
228 /* LOCALE_SNAME has additional parts in some languages. Try only as last chance */
229 memset(language
, 0, sizeof(language
));
230 len
= GetLocaleInfoA(lcid
, LOCALE_SNAME
, language
, sizeof(language
));
233 /* get the default value */
235 memset(buffer
, '#', maxlen
);
237 hr
= pGetAcceptLanguagesA( buffer
, &len
);
240 win_skip("GetAcceptLanguagesA failed with 0x%x\n", hr
);
241 goto restore_original
;
244 if (lstrcmpA(buffer
, language
)) {
245 /* some windows versions use "lang" or "lang-country" as default */
247 if (pLcidToRfc1766A
) {
248 hr
= pLcidToRfc1766A(lcid
, language
, sizeof(language
));
249 ok(hr
== S_OK
, "LcidToRfc1766A returned 0x%x and %s\n", hr
, language
);
253 ok(!lstrcmpA(buffer
, language
),
254 "have '%s' (searching for '%s')\n", language
, buffer
);
256 if (lstrcmpA(buffer
, language
)) {
257 win_skip("no more ideas, how to build the default language '%s'\n", buffer
);
258 goto restore_original
;
261 trace("detected default: %s\n", language
);
262 while ((entry
= table
[i
])) {
264 exactsize
= lstrlenA(entry
);
266 lres
= RegSetValueExA(hroot
, acceptlanguage
, 0, REG_SZ
, (const BYTE
*) entry
, exactsize
+ 1);
267 ok(!lres
, "got %d for RegSetValueExA: %s\n", lres
, entry
);
269 /* len includes space for the terminating 0 before vista/w2k8 */
271 memset(buffer
, '#', maxlen
);
273 hr
= pGetAcceptLanguagesA( buffer
, &len
);
274 ok(((hr
== E_INVALIDARG
) && (len
== 0)) ||
276 ((len
== exactsize
) || (len
== exactsize
+1)) &&
277 !lstrcmpA(buffer
, entry
)),
278 "+2_#%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
281 memset(buffer
, '#', maxlen
);
283 hr
= pGetAcceptLanguagesA( buffer
, &len
);
284 ok(((hr
== E_INVALIDARG
) && (len
== 0)) ||
286 ((len
== exactsize
) || (len
== exactsize
+1)) &&
287 !lstrcmpA(buffer
, entry
)),
288 "+1_#%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
291 memset(buffer
, '#', maxlen
);
293 hr
= pGetAcceptLanguagesA( buffer
, &len
);
295 /* There is no space for the string in the registry.
296 When the buffer is large enough, the default language is returned
298 When the buffer is too small for that fallback, win7_32 and w2k8_64
299 fail with E_NOT_SUFFICIENT_BUFFER, win8 fails with HRESULT_FROM_WIN32(ERROR_MORE_DATA),
300 other versions succeed and return a partial result while older os succeed
301 and overflow the buffer */
303 ok(((hr
== E_INVALIDARG
) && (len
== 0)) ||
304 (((hr
== S_OK
) && !lstrcmpA(buffer
, language
) && (len
== lstrlenA(language
))) ||
305 ((hr
== S_OK
) && !memcmp(buffer
, language
, len
)) ||
306 ((hr
== E_NOT_SUFFICIENT_BUFFER
) && !len
) ||
307 ((hr
== __HRESULT_FROM_WIN32(ERROR_MORE_DATA
)) && len
== exactsize
)),
308 "==_#%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
312 memset(buffer
, '#', maxlen
);
314 hr
= pGetAcceptLanguagesA( buffer
, &len
);
315 ok(((hr
== E_INVALIDARG
) && (len
== 0)) ||
316 (((hr
== S_OK
) && !lstrcmpA(buffer
, language
) && (len
== lstrlenA(language
))) ||
317 ((hr
== S_OK
) && !memcmp(buffer
, language
, len
)) ||
318 ((hr
== E_NOT_SUFFICIENT_BUFFER
) && !len
) ||
319 ((hr
== __HRESULT_FROM_WIN32(ERROR_MORE_DATA
)) && len
== exactsize
- 1)),
320 "-1_#%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
324 memset(buffer
, '#', maxlen
);
326 hr
= pGetAcceptLanguagesA( buffer
, &len
);
327 ok(((hr
== E_INVALIDARG
) && (len
== 0)) ||
328 (((hr
== S_OK
) && !lstrcmpA(buffer
, language
) && (len
== lstrlenA(language
))) ||
329 ((hr
== S_OK
) && !memcmp(buffer
, language
, len
)) ||
330 ((hr
== E_NOT_SUFFICIENT_BUFFER
) && !len
) ||
331 ((hr
== __HRESULT_FROM_WIN32(ERROR_MORE_DATA
)) && len
== 1)),
332 "=1_#%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
335 hr
= pGetAcceptLanguagesA( NULL
, &len
);
337 /* w2k3 and below: E_FAIL and untouched len,
338 since w2k8: S_OK and needed size (excluding 0), win8 S_OK and size including 0. */
339 ok( ((hr
== S_OK
) && ((len
== exactsize
) || (len
== exactsize
+ 1))) ||
340 ((hr
== E_FAIL
) && (len
== maxlen
)),
341 "NULL,max #%d: got 0x%x with %d and %s\n", i
, hr
, len
, buffer
);
346 /* without a value in the registry, a default language is returned */
347 RegDeleteValueA(hroot
, acceptlanguage
);
350 memset(buffer
, '#', maxlen
);
352 hr
= pGetAcceptLanguagesA( buffer
, &len
);
353 ok( ((hr
== S_OK
) && (len
== lstrlenA(language
))),
354 "max: got 0x%x with %d and %s (expected S_OK with %d and '%s'\n",
355 hr
, len
, buffer
, lstrlenA(language
), language
);
358 memset(buffer
, '#', maxlen
);
360 hr
= pGetAcceptLanguagesA( buffer
, &len
);
361 ok( (((hr
== S_OK
) || (hr
== E_INVALIDARG
)) && !memcmp(buffer
, language
, len
)) ||
362 ((hr
== E_NOT_SUFFICIENT_BUFFER
) && !len
) ||
363 ((hr
== __HRESULT_FROM_WIN32(ERROR_CANNOT_COPY
)) && !len
),
364 "=2: got 0x%x with %d and %s\n", hr
, len
, buffer
);
367 memset(buffer
, '#', maxlen
);
369 hr
= pGetAcceptLanguagesA( buffer
, &len
);
370 /* When the buffer is too small, win7_32 and w2k8_64 and above fail with
371 E_NOT_SUFFICIENT_BUFFER, win8 ERROR_CANNOT_COPY,
372 other versions succeed and return a partial 0 terminated result while other versions
373 fail with E_INVALIDARG and return a partial unterminated result */
374 ok( (((hr
== S_OK
) || (hr
== E_INVALIDARG
)) && !memcmp(buffer
, language
, len
)) ||
375 ((hr
== E_NOT_SUFFICIENT_BUFFER
) && !len
) ||
376 ((hr
== __HRESULT_FROM_WIN32(ERROR_CANNOT_COPY
)) && !len
),
377 "=1: got 0x%x with %d and %s\n", hr
, len
, buffer
);
380 memset(buffer
, '#', maxlen
);
382 hr
= pGetAcceptLanguagesA( buffer
, &len
);
383 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG, win8 ERROR_CANNOT_COPY */
384 ok((hr
== E_FAIL
) || (hr
== E_INVALIDARG
) || (hr
== __HRESULT_FROM_WIN32(ERROR_CANNOT_COPY
)),
387 memset(buffer
, '#', maxlen
);
389 hr
= pGetAcceptLanguagesA( buffer
, 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
);
395 hr
= pGetAcceptLanguagesA( NULL
, NULL
);
396 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
397 ok((hr
== E_FAIL
) || (hr
== E_INVALIDARG
),
398 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr
);
402 len
= lstrlenA(original
);
403 lres
= RegSetValueExA(hroot
, acceptlanguage
, 0, REG_SZ
, (const BYTE
*) original
, len
? len
+ 1: 0);
404 ok(!lres
, "RegSetValueEx(%s) failed: %d\n", original
, lres
);
408 RegDeleteValueA(hroot
, acceptlanguage
);
413 static void test_SHSearchMapInt(void)
415 int keys
[8], values
[8];
418 if (!pSHSearchMapInt
)
421 memset(keys
, 0, sizeof(keys
));
422 memset(values
, 0, sizeof(values
));
423 keys
[0] = 99; values
[0] = 101;
425 /* NULL key/value lists crash native, so skip testing them */
428 i
= pSHSearchMapInt(keys
, values
, 1, keys
[0]);
429 ok(i
== values
[0], "Len 1, expected %d, got %d\n", values
[0], i
);
431 /* Key doesn't exist */
432 i
= pSHSearchMapInt(keys
, values
, 1, 100);
433 ok(i
== -1, "Len 1 - bad key, expected -1, got %d\n", i
);
435 /* Len = 0 => not found */
436 i
= pSHSearchMapInt(keys
, values
, 0, keys
[0]);
437 ok(i
== -1, "Len 1 - passed len 0, expected -1, got %d\n", i
);
439 /* 2 elements, len = 1 */
440 keys
[1] = 98; values
[1] = 102;
441 i
= pSHSearchMapInt(keys
, values
, 1, keys
[1]);
442 ok(i
== -1, "Len 1 - array len 2, expected -1, got %d\n", i
);
444 /* 2 elements, len = 2 */
445 i
= pSHSearchMapInt(keys
, values
, 2, keys
[1]);
446 ok(i
== values
[1], "Len 2, expected %d, got %d\n", values
[1], i
);
448 /* Searches forward */
449 keys
[2] = 99; values
[2] = 103;
450 i
= pSHSearchMapInt(keys
, values
, 3, keys
[0]);
451 ok(i
== values
[0], "Len 3, expected %d, got %d\n", values
[0], i
);
460 static void test_alloc_shared(int argc
, char **argv
)
462 char cmdline
[MAX_PATH
];
463 PROCESS_INFORMATION pi
;
464 STARTUPINFOA si
= { 0 };
466 HANDLE hmem
, hmem2
= 0;
467 struct shared_struct val
, *p
;
470 procid
=GetCurrentProcessId();
471 hmem
=pSHAllocShared(NULL
,10,procid
);
472 ok(hmem
!=NULL
,"SHAllocShared(NULL...) failed: %u\n", GetLastError());
473 ret
= pSHFreeShared(hmem
, procid
);
474 ok( ret
, "SHFreeShared failed: %u\n", GetLastError());
476 val
.value
= 0x12345678;
478 hmem
= pSHAllocShared(&val
, sizeof(val
), procid
);
479 ok(hmem
!=NULL
,"SHAllocShared(NULL...) failed: %u\n", GetLastError());
481 p
=pSHLockShared(hmem
,procid
);
482 ok(p
!=NULL
,"SHLockShared failed: %u\n", GetLastError());
484 ok(p
->value
== 0x12345678, "Wrong value in shared memory: %d instead of %d\n", p
->value
, 0x12345678);
485 ret
= pSHUnlockShared(p
);
486 ok( ret
, "SHUnlockShared failed: %u\n", GetLastError());
488 sprintf(cmdline
, "%s %s %d %p", argv
[0], argv
[1], procid
, hmem
);
489 ret
= CreateProcessA(NULL
, cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
490 ok(ret
, "could not create child process error: %u\n", GetLastError());
493 winetest_wait_child_process(pi
.hProcess
);
494 CloseHandle(pi
.hThread
);
495 CloseHandle(pi
.hProcess
);
497 p
= pSHLockShared(hmem
, procid
);
498 ok(p
!= NULL
,"SHLockShared failed: %u\n", GetLastError());
499 if (p
!= NULL
&& p
->value
!= 0x12345678)
501 ok(p
->value
== 0x12345679, "Wrong value in shared memory: %d instead of %d\n", p
->value
, 0x12345679);
503 ok(hmem2
!= NULL
, "Expected handle in shared memory\n");
505 ret
= pSHUnlockShared(p
);
506 ok(ret
, "SHUnlockShared failed: %u\n", GetLastError());
509 ret
= pSHFreeShared(hmem
, procid
);
510 ok( ret
, "SHFreeShared failed: %u\n", GetLastError());
514 p
= pSHLockShared(hmem2
, procid
);
515 ok(p
!= NULL
,"SHLockShared failed: %u\n", GetLastError());
517 ok(p
->value
== 0xDEADBEEF, "Wrong value in shared memory: %d instead of %d\n", p
->value
, 0xDEADBEEF);
518 ret
= pSHUnlockShared(p
);
519 ok(ret
, "SHUnlockShared failed: %u\n", GetLastError());
521 ret
= pSHFreeShared(hmem2
, procid
);
522 ok(ret
, "SHFreeShared failed: %u\n", GetLastError());
526 static void test_alloc_shared_remote(DWORD procid
, HANDLE hmem
)
528 struct shared_struct val
, *p
;
532 /* test directly accessing shared memory of a remote process */
533 p
= pSHLockShared(hmem
, procid
);
534 ok(p
!= NULL
|| broken(p
== NULL
) /* Windows 7/8 */, "SHLockShared failed: %u\n", GetLastError());
537 win_skip("Subprocess failed to modify shared memory, skipping test\n");
541 ok(p
->value
== 0x12345678, "Wrong value in shared memory: %d instead of %d\n", p
->value
, 0x12345678);
544 val
.value
= 0xDEADBEEF;
546 p
->handle
= pSHAllocShared(&val
, sizeof(val
), procid
);
547 ok(p
->handle
!= NULL
, "SHAllocShared failed: %u\n", GetLastError());
549 ret
= pSHUnlockShared(p
);
550 ok(ret
, "SHUnlockShared failed: %u\n", GetLastError());
552 /* test SHMapHandle */
553 hmem2
= pSHMapHandle(hmem
, procid
, GetCurrentProcessId(), 0, 0);
555 /* It seems like Windows Vista/2008 uses a different internal implementation
556 * for shared memory, and calling SHMapHandle fails with ERROR_INVALID_HANDLE. */
557 ok(hmem2
!= NULL
|| broken(hmem2
== NULL
&& GetLastError() == ERROR_INVALID_HANDLE
),
558 "SHMapHandle failed: %u\n", GetLastError());
559 if (hmem2
== NULL
&& GetLastError() == ERROR_INVALID_HANDLE
)
561 win_skip("Subprocess failed to map shared memory, skipping test\n");
565 p
= pSHLockShared(hmem2
, GetCurrentProcessId());
566 ok(p
!= NULL
, "SHLockShared failed: %u\n", GetLastError());
569 ok(p
->value
== 0x12345679, "Wrong value in shared memory: %d instead of %d\n", p
->value
, 0x12345679);
571 ret
= pSHUnlockShared(p
);
572 ok(ret
, "SHUnlockShared failed: %u\n", GetLastError());
574 ret
= pSHFreeShared(hmem2
, GetCurrentProcessId());
575 ok(ret
, "SHFreeShared failed: %u\n", GetLastError());
578 static void test_fdsa(void)
582 DWORD num_items
; /* Number of elements inserted */
583 void *mem
; /* Ptr to array */
584 DWORD blocks_alloced
; /* Number of elements allocated */
585 BYTE inc
; /* Number of elements to grow by when we need to expand */
586 BYTE block_size
; /* Size in bytes of an element */
587 BYTE flags
; /* Flags */
590 BOOL (WINAPI
*pFDSA_Initialize
)(DWORD block_size
, DWORD inc
, FDSA_info
*info
, void *mem
,
592 BOOL (WINAPI
*pFDSA_Destroy
)(FDSA_info
*info
);
593 DWORD (WINAPI
*pFDSA_InsertItem
)(FDSA_info
*info
, DWORD where
, const void *block
);
594 BOOL (WINAPI
*pFDSA_DeleteItem
)(FDSA_info
*info
, DWORD where
);
597 int block_size
= 10, init_blocks
= 4, inc
= 2;
601 pFDSA_Initialize
= (void *)GetProcAddress(hShlwapi
, (LPSTR
)208);
602 pFDSA_Destroy
= (void *)GetProcAddress(hShlwapi
, (LPSTR
)209);
603 pFDSA_InsertItem
= (void *)GetProcAddress(hShlwapi
, (LPSTR
)210);
604 pFDSA_DeleteItem
= (void *)GetProcAddress(hShlwapi
, (LPSTR
)211);
606 mem
= HeapAlloc(GetProcessHeap(), 0, block_size
* init_blocks
);
607 memset(&info
, 0, sizeof(info
));
609 ok(pFDSA_Initialize(block_size
, inc
, &info
, mem
, init_blocks
), "FDSA_Initialize rets FALSE\n");
610 ok(info
.num_items
== 0, "num_items = %d\n", info
.num_items
);
611 ok(info
.mem
== mem
, "mem = %p\n", info
.mem
);
612 ok(info
.blocks_alloced
== init_blocks
, "blocks_alloced = %d\n", info
.blocks_alloced
);
613 ok(info
.inc
== inc
, "inc = %d\n", info
.inc
);
614 ok(info
.block_size
== block_size
, "block_size = %d\n", info
.block_size
);
615 ok(info
.flags
== 0, "flags = %d\n", info
.flags
);
617 ret
= pFDSA_InsertItem(&info
, 1234, "1234567890");
618 ok(ret
== 0, "ret = %d\n", ret
);
619 ok(info
.num_items
== 1, "num_items = %d\n", info
.num_items
);
620 ok(info
.mem
== mem
, "mem = %p\n", info
.mem
);
621 ok(info
.blocks_alloced
== init_blocks
, "blocks_alloced = %d\n", info
.blocks_alloced
);
622 ok(info
.inc
== inc
, "inc = %d\n", info
.inc
);
623 ok(info
.block_size
== block_size
, "block_size = %d\n", info
.block_size
);
624 ok(info
.flags
== 0, "flags = %d\n", info
.flags
);
626 ret
= pFDSA_InsertItem(&info
, 1234, "abcdefghij");
627 ok(ret
== 1, "ret = %d\n", ret
);
629 ret
= pFDSA_InsertItem(&info
, 1, "klmnopqrst");
630 ok(ret
== 1, "ret = %d\n", ret
);
632 ret
= pFDSA_InsertItem(&info
, 0, "uvwxyzABCD");
633 ok(ret
== 0, "ret = %d\n", ret
);
634 ok(info
.mem
== mem
, "mem = %p\n", info
.mem
);
635 ok(info
.flags
== 0, "flags = %d\n", info
.flags
);
637 /* This next InsertItem will cause shlwapi to allocate its own mem buffer */
638 ret
= pFDSA_InsertItem(&info
, 0, "EFGHIJKLMN");
639 ok(ret
== 0, "ret = %d\n", ret
);
640 ok(info
.mem
!= mem
, "mem = %p\n", info
.mem
);
641 ok(info
.blocks_alloced
== init_blocks
+ inc
, "blocks_alloced = %d\n", info
.blocks_alloced
);
642 ok(info
.flags
== 0x1, "flags = %d\n", info
.flags
);
644 ok(!memcmp(info
.mem
, "EFGHIJKLMNuvwxyzABCD1234567890klmnopqrstabcdefghij", 50), "mem %s\n", (char*)info
.mem
);
646 ok(pFDSA_DeleteItem(&info
, 2), "rets FALSE\n");
647 ok(info
.mem
!= mem
, "mem = %p\n", info
.mem
);
648 ok(info
.blocks_alloced
== init_blocks
+ inc
, "blocks_alloced = %d\n", info
.blocks_alloced
);
649 ok(info
.flags
== 0x1, "flags = %d\n", info
.flags
);
651 ok(!memcmp(info
.mem
, "EFGHIJKLMNuvwxyzABCDklmnopqrstabcdefghij", 40), "mem %s\n", (char*)info
.mem
);
653 ok(pFDSA_DeleteItem(&info
, 3), "rets FALSE\n");
654 ok(info
.mem
!= mem
, "mem = %p\n", info
.mem
);
655 ok(info
.blocks_alloced
== init_blocks
+ inc
, "blocks_alloced = %d\n", info
.blocks_alloced
);
656 ok(info
.flags
== 0x1, "flags = %d\n", info
.flags
);
658 ok(!memcmp(info
.mem
, "EFGHIJKLMNuvwxyzABCDklmnopqrst", 30), "mem %s\n", (char*)info
.mem
);
660 ok(!pFDSA_DeleteItem(&info
, 4), "does not ret FALSE\n");
662 /* As shlwapi has allocated memory internally, Destroy will ret FALSE */
663 ok(!pFDSA_Destroy(&info
), "FDSA_Destroy does not ret FALSE\n");
666 /* When Initialize is called with inc = 0, set it to 1 */
667 ok(pFDSA_Initialize(block_size
, 0, &info
, mem
, init_blocks
), "FDSA_Initialize rets FALSE\n");
668 ok(info
.inc
== 1, "inc = %d\n", info
.inc
);
670 /* This time, because shlwapi hasn't had to allocate memory
671 internally, Destroy rets non-zero */
672 ok(pFDSA_Destroy(&info
), "FDSA_Destroy rets FALSE\n");
675 HeapFree(GetProcessHeap(), 0, mem
);
679 typedef struct SHELL_USER_SID
{
680 SID_IDENTIFIER_AUTHORITY sidAuthority
;
683 } SHELL_USER_SID
, *PSHELL_USER_SID
;
684 typedef struct SHELL_USER_PERMISSION
{
685 SHELL_USER_SID susID
;
690 DWORD dwInheritAccessMask
;
691 } SHELL_USER_PERMISSION
, *PSHELL_USER_PERMISSION
;
692 static void test_GetShellSecurityDescriptor(void)
694 SHELL_USER_PERMISSION supCurrentUserFull
= {
695 { {SECURITY_NULL_SID_AUTHORITY
}, 0, 0 },
696 ACCESS_ALLOWED_ACE_TYPE
, FALSE
,
698 #define MY_INHERITANCE 0xBE /* invalid value to proof behavior */
699 SHELL_USER_PERMISSION supEveryoneDenied
= {
700 { {SECURITY_WORLD_SID_AUTHORITY
}, SECURITY_WORLD_RID
, 0 },
701 ACCESS_DENIED_ACE_TYPE
, TRUE
,
702 GENERIC_WRITE
, MY_INHERITANCE
| 0xDEADBA00, GENERIC_READ
};
703 PSHELL_USER_PERMISSION rgsup
[2] = {
704 &supCurrentUserFull
, &supEveryoneDenied
,
706 SECURITY_DESCRIPTOR
* psd
;
707 SECURITY_DESCRIPTOR
* (WINAPI
*pGetShellSecurityDescriptor
)(PSHELL_USER_PERMISSION
*,int);
708 void *pChrCmpIW
= GetProcAddress(hShlwapi
, "ChrCmpIW");
710 pGetShellSecurityDescriptor
=(void*)GetProcAddress(hShlwapi
,(char*)475);
712 if(!pGetShellSecurityDescriptor
)
714 win_skip("GetShellSecurityDescriptor not available\n");
718 if(pChrCmpIW
&& pChrCmpIW
== pGetShellSecurityDescriptor
) /* win2k */
720 win_skip("Skipping for GetShellSecurityDescriptor, same ordinal used for ChrCmpIW\n");
724 psd
= pGetShellSecurityDescriptor(NULL
, 2);
726 broken(psd
==INVALID_HANDLE_VALUE
), /* IE5 */
727 "GetShellSecurityDescriptor should fail\n");
728 psd
= pGetShellSecurityDescriptor(rgsup
, 0);
729 ok(psd
==NULL
, "GetShellSecurityDescriptor should fail, got %p\n", psd
);
731 SetLastError(0xdeadbeef);
732 psd
= pGetShellSecurityDescriptor(rgsup
, 2);
733 if (psd
== NULL
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
735 /* The previous calls to GetShellSecurityDescriptor don't set the last error */
736 win_skip("GetShellSecurityDescriptor is not implemented\n");
739 if (psd
== INVALID_HANDLE_VALUE
)
741 win_skip("GetShellSecurityDescriptor is broken on IE5\n");
744 ok(psd
!=NULL
, "GetShellSecurityDescriptor failed\n");
747 BOOL bHasDacl
= FALSE
, bDefaulted
, ret
;
750 SECURITY_DESCRIPTOR_CONTROL control
;
752 ok(IsValidSecurityDescriptor(psd
), "returned value is not valid SD\n");
754 ret
= GetSecurityDescriptorControl(psd
, &control
, &dwRev
);
755 ok(ret
, "GetSecurityDescriptorControl failed with error %u\n", GetLastError());
756 ok(0 == (control
& SE_SELF_RELATIVE
), "SD should be absolute\n");
758 ret
= GetSecurityDescriptorDacl(psd
, &bHasDacl
, &pAcl
, &bDefaulted
);
759 ok(ret
, "GetSecurityDescriptorDacl failed with error %u\n", GetLastError());
761 ok(bHasDacl
, "SD has no DACL\n");
764 ok(!bDefaulted
, "DACL should not be defaulted\n");
766 ok(pAcl
!= NULL
, "NULL DACL!\n");
769 ACL_SIZE_INFORMATION asiSize
;
771 ok(IsValidAcl(pAcl
), "DACL is not valid\n");
773 ret
= GetAclInformation(pAcl
, &asiSize
, sizeof(asiSize
), AclSizeInformation
);
774 ok(ret
, "GetAclInformation failed with error %u\n", GetLastError());
776 ok(asiSize
.AceCount
== 3, "Incorrect number of ACEs: %d entries\n", asiSize
.AceCount
);
777 if (asiSize
.AceCount
== 3)
779 ACCESS_ALLOWED_ACE
*paaa
; /* will use for DENIED too */
781 ret
= GetAce(pAcl
, 0, (LPVOID
*)&paaa
);
782 ok(ret
, "GetAce failed with error %u\n", GetLastError());
783 ok(paaa
->Header
.AceType
== ACCESS_ALLOWED_ACE_TYPE
,
784 "Invalid ACE type %d\n", paaa
->Header
.AceType
);
785 ok(paaa
->Header
.AceFlags
== 0, "Invalid ACE flags %x\n", paaa
->Header
.AceFlags
);
786 ok(paaa
->Mask
== GENERIC_ALL
, "Invalid ACE mask %x\n", paaa
->Mask
);
788 ret
= GetAce(pAcl
, 1, (LPVOID
*)&paaa
);
789 ok(ret
, "GetAce failed with error %u\n", GetLastError());
790 ok(paaa
->Header
.AceType
== ACCESS_DENIED_ACE_TYPE
,
791 "Invalid ACE type %d\n", paaa
->Header
.AceType
);
792 /* first one of two ACEs generated from inheritable entry - without inheritance */
793 ok(paaa
->Header
.AceFlags
== 0, "Invalid ACE flags %x\n", paaa
->Header
.AceFlags
);
794 ok(paaa
->Mask
== GENERIC_WRITE
, "Invalid ACE mask %x\n", paaa
->Mask
);
796 ret
= GetAce(pAcl
, 2, (LPVOID
*)&paaa
);
797 ok(ret
, "GetAce failed with error %u\n", GetLastError());
798 ok(paaa
->Header
.AceType
== ACCESS_DENIED_ACE_TYPE
,
799 "Invalid ACE type %d\n", paaa
->Header
.AceType
);
800 /* second ACE - with inheritance */
801 ok(paaa
->Header
.AceFlags
== MY_INHERITANCE
,
802 "Invalid ACE flags %x\n", paaa
->Header
.AceFlags
);
803 ok(paaa
->Mask
== GENERIC_READ
, "Invalid ACE mask %x\n", paaa
->Mask
);
812 static void test_SHPackDispParams(void)
818 if(!pSHPackDispParams
)
819 win_skip("SHPackSidpParams not available\n");
821 memset(¶ms
, 0xc0, sizeof(params
));
822 memset(vars
, 0xc0, sizeof(vars
));
823 hres
= pSHPackDispParams(¶ms
, vars
, 1, VT_I4
, 0xdeadbeef);
824 ok(hres
== S_OK
, "SHPackDispParams failed: %08x\n", hres
);
825 ok(params
.cArgs
== 1, "params.cArgs = %d\n", params
.cArgs
);
826 ok(params
.cNamedArgs
== 0, "params.cNamedArgs = %d\n", params
.cArgs
);
827 ok(params
.rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", params
.rgdispidNamedArgs
);
828 ok(params
.rgvarg
== vars
, "params.rgvarg = %p\n", params
.rgvarg
);
829 ok(V_VT(vars
) == VT_I4
, "V_VT(var) = %d\n", V_VT(vars
));
830 ok(V_I4(vars
) == 0xdeadbeef, "failed %x\n", V_I4(vars
));
832 memset(¶ms
, 0xc0, sizeof(params
));
833 hres
= pSHPackDispParams(¶ms
, NULL
, 0, 0);
834 ok(hres
== S_OK
, "SHPackDispParams failed: %08x\n", hres
);
835 ok(params
.cArgs
== 0, "params.cArgs = %d\n", params
.cArgs
);
836 ok(params
.cNamedArgs
== 0, "params.cNamedArgs = %d\n", params
.cArgs
);
837 ok(params
.rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", params
.rgdispidNamedArgs
);
838 ok(params
.rgvarg
== NULL
, "params.rgvarg = %p\n", params
.rgvarg
);
840 memset(vars
, 0xc0, sizeof(vars
));
841 memset(¶ms
, 0xc0, sizeof(params
));
842 hres
= pSHPackDispParams(¶ms
, vars
, 4, VT_BSTR
, (void*)0xdeadbeef, VT_EMPTY
, 10,
843 VT_I4
, 100, VT_DISPATCH
, (void*)0xdeadbeef);
844 ok(hres
== S_OK
, "SHPackDispParams failed: %08x\n", hres
);
845 ok(params
.cArgs
== 4, "params.cArgs = %d\n", params
.cArgs
);
846 ok(params
.cNamedArgs
== 0, "params.cNamedArgs = %d\n", params
.cArgs
);
847 ok(params
.rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", params
.rgdispidNamedArgs
);
848 ok(params
.rgvarg
== vars
, "params.rgvarg = %p\n", params
.rgvarg
);
849 ok(V_VT(vars
) == VT_DISPATCH
, "V_VT(vars[0]) = %x\n", V_VT(vars
));
850 ok(V_I4(vars
) == 0xdeadbeef, "V_I4(vars[0]) = %x\n", V_I4(vars
));
851 ok(V_VT(vars
+1) == VT_I4
, "V_VT(vars[1]) = %d\n", V_VT(vars
+1));
852 ok(V_I4(vars
+1) == 100, "V_I4(vars[1]) = %x\n", V_I4(vars
+1));
853 ok(V_VT(vars
+2) == VT_I4
, "V_VT(vars[2]) = %d\n", V_VT(vars
+2));
854 ok(V_I4(vars
+2) == 10, "V_I4(vars[2]) = %x\n", V_I4(vars
+2));
855 ok(V_VT(vars
+3) == VT_BSTR
, "V_VT(vars[3]) = %d\n", V_VT(vars
+3));
856 ok(V_BSTR(vars
+3) == (void*)0xdeadbeef, "V_BSTR(vars[3]) = %p\n", V_BSTR(vars
+3));
861 IDispatch IDispatch_iface
;
865 static inline Disp
*impl_from_IDispatch(IDispatch
*iface
)
867 return CONTAINING_RECORD(iface
, Disp
, IDispatch_iface
);
870 typedef struct _contain
872 IConnectionPointContainer IConnectionPointContainer_iface
;
876 IConnectionPoint
**pt
;
879 static inline Contain
*impl_from_IConnectionPointContainer(IConnectionPointContainer
*iface
)
881 return CONTAINING_RECORD(iface
, Contain
, IConnectionPointContainer_iface
);
884 typedef struct _cntptn
886 IConnectionPoint IConnectionPoint_iface
;
895 static inline ConPt
*impl_from_IConnectionPoint(IConnectionPoint
*iface
)
897 return CONTAINING_RECORD(iface
, ConPt
, IConnectionPoint_iface
);
902 IEnumConnections IEnumConnections_iface
;
909 static inline EnumCon
*impl_from_IEnumConnections(IEnumConnections
*iface
)
911 return CONTAINING_RECORD(iface
, EnumCon
, IEnumConnections_iface
);
914 typedef struct _enumpt
916 IEnumConnectionPoints IEnumConnectionPoints_iface
;
923 static inline EnumPt
*impl_from_IEnumConnectionPoints(IEnumConnectionPoints
*iface
)
925 return CONTAINING_RECORD(iface
, EnumPt
, IEnumConnectionPoints_iface
);
929 static HRESULT WINAPI
Disp_QueryInterface(
936 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDispatch
))
943 IDispatch_AddRef(This
);
947 trace("no interface\n");
948 return E_NOINTERFACE
;
951 static ULONG WINAPI
Disp_AddRef(IDispatch
* This
)
953 Disp
*iface
= impl_from_IDispatch(This
);
954 return InterlockedIncrement(&iface
->refCount
);
957 static ULONG WINAPI
Disp_Release(IDispatch
* This
)
959 Disp
*iface
= impl_from_IDispatch(This
);
962 ret
= InterlockedDecrement(&iface
->refCount
);
964 HeapFree(GetProcessHeap(),0,This
);
968 static HRESULT WINAPI
Disp_GetTypeInfoCount(
972 return ERROR_SUCCESS
;
975 static HRESULT WINAPI
Disp_GetTypeInfo(
981 return ERROR_SUCCESS
;
984 static HRESULT WINAPI
Disp_GetIDsOfNames(
992 return ERROR_SUCCESS
;
995 static HRESULT WINAPI
Disp_Invoke(
1001 DISPPARAMS
*pDispParams
,
1002 VARIANT
*pVarResult
,
1003 EXCEPINFO
*pExcepInfo
,
1006 trace("%p %x %p %x %x %p %p %p %p\n",This
,dispIdMember
,riid
,lcid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,puArgErr
);
1008 ok(dispIdMember
== 0xa0 || dispIdMember
== 0xa1, "Unknown dispIdMember\n");
1009 ok(pDispParams
!= NULL
, "Invoked with NULL pDispParams\n");
1010 ok(wFlags
== DISPATCH_METHOD
, "Wrong flags %x\n",wFlags
);
1011 ok(lcid
== 0,"Wrong lcid %x\n",lcid
);
1012 if (dispIdMember
== 0xa0)
1014 ok(pDispParams
->cArgs
== 0, "params.cArgs = %d\n", pDispParams
->cArgs
);
1015 ok(pDispParams
->cNamedArgs
== 0, "params.cNamedArgs = %d\n", pDispParams
->cArgs
);
1016 ok(pDispParams
->rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", pDispParams
->rgdispidNamedArgs
);
1017 ok(pDispParams
->rgvarg
== NULL
, "params.rgvarg = %p\n", pDispParams
->rgvarg
);
1019 else if (dispIdMember
== 0xa1)
1021 ok(pDispParams
->cArgs
== 2, "params.cArgs = %d\n", pDispParams
->cArgs
);
1022 ok(pDispParams
->cNamedArgs
== 0, "params.cNamedArgs = %d\n", pDispParams
->cArgs
);
1023 ok(pDispParams
->rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", pDispParams
->rgdispidNamedArgs
);
1024 ok(V_VT(pDispParams
->rgvarg
) == VT_BSTR
, "V_VT(var) = %d\n", V_VT(pDispParams
->rgvarg
));
1025 ok(V_I4(pDispParams
->rgvarg
) == 0xdeadcafe , "failed %p\n", V_BSTR(pDispParams
->rgvarg
));
1026 ok(V_VT(pDispParams
->rgvarg
+1) == VT_I4
, "V_VT(var) = %d\n", V_VT(pDispParams
->rgvarg
+1));
1027 ok(V_I4(pDispParams
->rgvarg
+1) == 0xdeadbeef, "failed %x\n", V_I4(pDispParams
->rgvarg
+1));
1030 return ERROR_SUCCESS
;
1033 static const IDispatchVtbl disp_vtbl
= {
1034 Disp_QueryInterface
,
1038 Disp_GetTypeInfoCount
,
1044 static HRESULT WINAPI
Enum_QueryInterface(
1045 IEnumConnections
* This
,
1051 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IEnumConnections
))
1058 IEnumConnections_AddRef(This
);
1062 trace("no interface\n");
1063 return E_NOINTERFACE
;
1066 static ULONG WINAPI
Enum_AddRef(IEnumConnections
* This
)
1068 EnumCon
*iface
= impl_from_IEnumConnections(This
);
1069 return InterlockedIncrement(&iface
->refCount
);
1072 static ULONG WINAPI
Enum_Release(IEnumConnections
* This
)
1074 EnumCon
*iface
= impl_from_IEnumConnections(This
);
1077 ret
= InterlockedDecrement(&iface
->refCount
);
1079 HeapFree(GetProcessHeap(),0,This
);
1083 static HRESULT WINAPI
Enum_Next(
1084 IEnumConnections
* This
,
1089 EnumCon
*iface
= impl_from_IEnumConnections(This
);
1091 if (cConnections
> 0 && iface
->idx
< iface
->pt
->sinkCount
)
1093 rgcd
->pUnk
= iface
->pt
->sink
[iface
->idx
];
1094 IUnknown_AddRef(iface
->pt
->sink
[iface
->idx
]);
1095 rgcd
->dwCookie
=0xff;
1105 static HRESULT WINAPI
Enum_Skip(
1106 IEnumConnections
* This
,
1112 static HRESULT WINAPI
Enum_Reset(
1113 IEnumConnections
* This
)
1118 static HRESULT WINAPI
Enum_Clone(
1119 IEnumConnections
* This
,
1120 IEnumConnections
**ppEnum
)
1125 static const IEnumConnectionsVtbl enum_vtbl
= {
1127 Enum_QueryInterface
,
1136 static HRESULT WINAPI
ConPt_QueryInterface(
1137 IConnectionPoint
* This
,
1143 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IConnectionPoint
))
1150 IConnectionPoint_AddRef(This
);
1154 trace("no interface\n");
1155 return E_NOINTERFACE
;
1158 static ULONG WINAPI
ConPt_AddRef(
1159 IConnectionPoint
* This
)
1161 ConPt
*iface
= impl_from_IConnectionPoint(This
);
1162 return InterlockedIncrement(&iface
->refCount
);
1165 static ULONG WINAPI
ConPt_Release(
1166 IConnectionPoint
* This
)
1168 ConPt
*iface
= impl_from_IConnectionPoint(This
);
1171 ret
= InterlockedDecrement(&iface
->refCount
);
1174 if (iface
->sinkCount
> 0)
1177 for (i
= 0; i
< iface
->sinkCount
; i
++)
1180 IUnknown_Release(iface
->sink
[i
]);
1182 HeapFree(GetProcessHeap(),0,iface
->sink
);
1184 HeapFree(GetProcessHeap(),0,This
);
1189 static HRESULT WINAPI
ConPt_GetConnectionInterface(
1190 IConnectionPoint
* This
,
1194 ConPt
*iface
= impl_from_IConnectionPoint(This
);
1201 memcpy(pIID
,&iface
->id
,sizeof(GUID
));
1205 static HRESULT WINAPI
ConPt_GetConnectionPointContainer(
1206 IConnectionPoint
* This
,
1207 IConnectionPointContainer
**ppCPC
)
1209 ConPt
*iface
= impl_from_IConnectionPoint(This
);
1211 *ppCPC
= &iface
->container
->IConnectionPointContainer_iface
;
1215 static HRESULT WINAPI
ConPt_Advise(
1216 IConnectionPoint
* This
,
1220 ConPt
*iface
= impl_from_IConnectionPoint(This
);
1222 if (iface
->sinkCount
== 0)
1223 iface
->sink
= HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown
*));
1225 iface
->sink
= HeapReAlloc(GetProcessHeap(),0,iface
->sink
,sizeof(IUnknown
*)*(iface
->sinkCount
+1));
1226 iface
->sink
[iface
->sinkCount
] = pUnkSink
;
1227 IUnknown_AddRef(pUnkSink
);
1229 *pdwCookie
= iface
->sinkCount
;
1233 static HRESULT WINAPI
ConPt_Unadvise(
1234 IConnectionPoint
* This
,
1237 ConPt
*iface
= impl_from_IConnectionPoint(This
);
1239 if (dwCookie
> iface
->sinkCount
)
1243 IUnknown_Release(iface
->sink
[dwCookie
-1]);
1244 iface
->sink
[dwCookie
-1] = NULL
;
1249 static HRESULT WINAPI
ConPt_EnumConnections(
1250 IConnectionPoint
* This
,
1251 IEnumConnections
**ppEnum
)
1255 ec
= HeapAlloc(GetProcessHeap(),0,sizeof(EnumCon
));
1256 ec
->IEnumConnections_iface
.lpVtbl
= &enum_vtbl
;
1258 ec
->pt
= impl_from_IConnectionPoint(This
);
1260 *ppEnum
= &ec
->IEnumConnections_iface
;
1265 static const IConnectionPointVtbl point_vtbl
= {
1266 ConPt_QueryInterface
,
1270 ConPt_GetConnectionInterface
,
1271 ConPt_GetConnectionPointContainer
,
1274 ConPt_EnumConnections
1277 static HRESULT WINAPI
EnumPt_QueryInterface(
1278 IEnumConnectionPoints
* This
,
1284 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IEnumConnectionPoints
))
1291 IEnumConnectionPoints_AddRef(This
);
1295 trace("no interface\n");
1296 return E_NOINTERFACE
;
1299 static ULONG WINAPI
EnumPt_AddRef(IEnumConnectionPoints
* This
)
1301 EnumPt
*iface
= impl_from_IEnumConnectionPoints(This
);
1302 return InterlockedIncrement(&iface
->refCount
);
1305 static ULONG WINAPI
EnumPt_Release(IEnumConnectionPoints
* This
)
1307 EnumPt
*iface
= impl_from_IEnumConnectionPoints(This
);
1310 ret
= InterlockedDecrement(&iface
->refCount
);
1312 HeapFree(GetProcessHeap(),0,This
);
1316 static HRESULT WINAPI
EnumPt_Next(
1317 IEnumConnectionPoints
* This
,
1319 IConnectionPoint
**rgcd
,
1322 EnumPt
*iface
= impl_from_IEnumConnectionPoints(This
);
1324 if (cConnections
> 0 && iface
->idx
< iface
->container
->ptCount
)
1326 *rgcd
= iface
->container
->pt
[iface
->idx
];
1327 IConnectionPoint_AddRef(iface
->container
->pt
[iface
->idx
]);
1337 static HRESULT WINAPI
EnumPt_Skip(
1338 IEnumConnectionPoints
* This
,
1344 static HRESULT WINAPI
EnumPt_Reset(
1345 IEnumConnectionPoints
* This
)
1350 static HRESULT WINAPI
EnumPt_Clone(
1351 IEnumConnectionPoints
* This
,
1352 IEnumConnectionPoints
**ppEnumPt
)
1357 static const IEnumConnectionPointsVtbl enumpt_vtbl
= {
1359 EnumPt_QueryInterface
,
1368 static HRESULT WINAPI
Contain_QueryInterface(
1369 IConnectionPointContainer
* This
,
1375 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IConnectionPointContainer
))
1382 IConnectionPointContainer_AddRef(This
);
1386 trace("no interface\n");
1387 return E_NOINTERFACE
;
1390 static ULONG WINAPI
Contain_AddRef(
1391 IConnectionPointContainer
* This
)
1393 Contain
*iface
= impl_from_IConnectionPointContainer(This
);
1394 return InterlockedIncrement(&iface
->refCount
);
1397 static ULONG WINAPI
Contain_Release(
1398 IConnectionPointContainer
* This
)
1400 Contain
*iface
= impl_from_IConnectionPointContainer(This
);
1403 ret
= InterlockedDecrement(&iface
->refCount
);
1406 if (iface
->ptCount
> 0)
1409 for (i
= 0; i
< iface
->ptCount
; i
++)
1410 IConnectionPoint_Release(iface
->pt
[i
]);
1411 HeapFree(GetProcessHeap(),0,iface
->pt
);
1413 HeapFree(GetProcessHeap(),0,This
);
1418 static HRESULT WINAPI
Contain_EnumConnectionPoints(
1419 IConnectionPointContainer
* This
,
1420 IEnumConnectionPoints
**ppEnum
)
1424 ec
= HeapAlloc(GetProcessHeap(),0,sizeof(EnumPt
));
1425 ec
->IEnumConnectionPoints_iface
.lpVtbl
= &enumpt_vtbl
;
1428 ec
->container
= impl_from_IConnectionPointContainer(This
);
1429 *ppEnum
= &ec
->IEnumConnectionPoints_iface
;
1434 static HRESULT WINAPI
Contain_FindConnectionPoint(
1435 IConnectionPointContainer
* This
,
1437 IConnectionPoint
**ppCP
)
1439 Contain
*iface
= impl_from_IConnectionPointContainer(This
);
1442 if (!IsEqualIID(riid
, &IID_NULL
) || iface
->ptCount
==0)
1444 pt
= HeapAlloc(GetProcessHeap(),0,sizeof(ConPt
));
1445 pt
->IConnectionPoint_iface
.lpVtbl
= &point_vtbl
;
1449 pt
->container
= iface
;
1450 pt
->id
= IID_IDispatch
;
1452 if (iface
->ptCount
== 0)
1453 iface
->pt
=HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown
*));
1455 iface
->pt
= HeapReAlloc(GetProcessHeap(),0,iface
->pt
,sizeof(IUnknown
*)*(iface
->ptCount
+1));
1456 iface
->pt
[iface
->ptCount
] = &pt
->IConnectionPoint_iface
;
1459 *ppCP
= &pt
->IConnectionPoint_iface
;
1463 *ppCP
= iface
->pt
[0];
1464 IUnknown_AddRef((IUnknown
*)*ppCP
);
1470 static const IConnectionPointContainerVtbl contain_vtbl
= {
1471 Contain_QueryInterface
,
1475 Contain_EnumConnectionPoints
,
1476 Contain_FindConnectionPoint
1479 static void test_IConnectionPoint(void)
1483 IConnectionPoint
*point
;
1486 DWORD cookie
= 0xffffffff;
1490 if (!pIConnectionPoint_SimpleInvoke
|| !pConnectToConnectionPoint
)
1492 win_skip("IConnectionPoint Apis not present\n");
1496 container
= HeapAlloc(GetProcessHeap(),0,sizeof(Contain
));
1497 container
->IConnectionPointContainer_iface
.lpVtbl
= &contain_vtbl
;
1498 container
->refCount
= 1;
1499 container
->ptCount
= 0;
1500 container
->pt
= NULL
;
1502 dispatch
= HeapAlloc(GetProcessHeap(),0,sizeof(Disp
));
1503 dispatch
->IDispatch_iface
.lpVtbl
= &disp_vtbl
;
1504 dispatch
->refCount
= 1;
1506 rc
= pConnectToConnectionPoint((IUnknown
*)dispatch
, &IID_NULL
, TRUE
, (IUnknown
*)container
, &cookie
, &point
);
1507 ok(rc
== S_OK
, "pConnectToConnectionPoint failed with %x\n",rc
);
1508 ok(point
!= NULL
, "returned ConnectionPoint is NULL\n");
1509 ok(cookie
!= 0xffffffff, "invalid cookie returned\n");
1511 rc
= pIConnectionPoint_SimpleInvoke(point
,0xa0,NULL
);
1512 ok(rc
== S_OK
, "pConnectToConnectionPoint failed with %x\n",rc
);
1514 if (pSHPackDispParams
)
1516 memset(¶ms
, 0xc0, sizeof(params
));
1517 memset(vars
, 0xc0, sizeof(vars
));
1518 rc
= pSHPackDispParams(¶ms
, vars
, 2, VT_I4
, 0xdeadbeef, VT_BSTR
, 0xdeadcafe);
1519 ok(rc
== S_OK
, "SHPackDispParams failed: %08x\n", rc
);
1521 rc
= pIConnectionPoint_SimpleInvoke(point
,0xa1,¶ms
);
1522 ok(rc
== S_OK
, "pConnectToConnectionPoint failed with %x\n",rc
);
1525 win_skip("pSHPackDispParams not present\n");
1527 rc
= pConnectToConnectionPoint(NULL
, &IID_NULL
, FALSE
, (IUnknown
*)container
, &cookie
, NULL
);
1528 ok(rc
== S_OK
, "pConnectToConnectionPoint failed with %x\n",rc
);
1530 /* MSDN says this should be required but it crashs on XP
1531 IUnknown_Release(point);
1533 ref
= IUnknown_Release((IUnknown
*)container
);
1534 ok(ref
== 0, "leftover IConnectionPointContainer reference %i\n",ref
);
1535 ref
= IUnknown_Release((IUnknown
*)dispatch
);
1536 ok(ref
== 0, "leftover IDispatch reference %i\n",ref
);
1539 typedef struct _propbag
1541 IPropertyBag IPropertyBag_iface
;
1546 static inline PropBag
*impl_from_IPropertyBag(IPropertyBag
*iface
)
1548 return CONTAINING_RECORD(iface
, PropBag
, IPropertyBag_iface
);
1552 static HRESULT WINAPI
Prop_QueryInterface(
1559 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IPropertyBag
))
1566 IPropertyBag_AddRef(This
);
1570 trace("no interface\n");
1571 return E_NOINTERFACE
;
1574 static ULONG WINAPI
Prop_AddRef(
1577 PropBag
*iface
= impl_from_IPropertyBag(This
);
1578 return InterlockedIncrement(&iface
->refCount
);
1581 static ULONG WINAPI
Prop_Release(
1584 PropBag
*iface
= impl_from_IPropertyBag(This
);
1587 ret
= InterlockedDecrement(&iface
->refCount
);
1589 HeapFree(GetProcessHeap(),0,This
);
1593 static HRESULT WINAPI
Prop_Read(
1595 LPCOLESTR pszPropName
,
1597 IErrorLog
*pErrorLog
)
1599 V_VT(pVar
) = VT_BLOB
|VT_BYREF
;
1600 V_BYREF(pVar
) = (LPVOID
)0xdeadcafe;
1604 static HRESULT WINAPI
Prop_Write(
1606 LPCOLESTR pszPropName
,
1613 static const IPropertyBagVtbl prop_vtbl
= {
1614 Prop_QueryInterface
,
1622 static void test_SHPropertyBag_ReadLONG(void)
1627 static const WCHAR szName1
[] = {'n','a','m','e','1',0};
1629 if (!pSHPropertyBag_ReadLONG
)
1631 win_skip("SHPropertyBag_ReadLONG not present\n");
1635 pb
= HeapAlloc(GetProcessHeap(),0,sizeof(PropBag
));
1637 pb
->IPropertyBag_iface
.lpVtbl
= &prop_vtbl
;
1640 rc
= pSHPropertyBag_ReadLONG(NULL
, szName1
, &out
);
1641 ok(rc
== E_INVALIDARG
|| broken(rc
== 0), "incorrect return %x\n",rc
);
1642 ok(out
== 0xfeedface, "value should not have changed\n");
1643 rc
= pSHPropertyBag_ReadLONG(&pb
->IPropertyBag_iface
, NULL
, &out
);
1644 ok(rc
== E_INVALIDARG
|| broken(rc
== 0) || broken(rc
== 1), "incorrect return %x\n",rc
);
1645 ok(out
== 0xfeedface, "value should not have changed\n");
1646 rc
= pSHPropertyBag_ReadLONG(&pb
->IPropertyBag_iface
, szName1
, NULL
);
1647 ok(rc
== E_INVALIDARG
|| broken(rc
== 0) || broken(rc
== 1), "incorrect return %x\n",rc
);
1648 rc
= pSHPropertyBag_ReadLONG(&pb
->IPropertyBag_iface
, szName1
, &out
);
1649 ok(rc
== DISP_E_BADVARTYPE
|| broken(rc
== 0) || broken(rc
== 1), "incorrect return %x\n",rc
);
1650 ok(out
== 0xfeedface || broken(out
== 0xfeedfa00), "value should not have changed %x\n",out
);
1651 IUnknown_Release((IUnknown
*)pb
);
1656 static void test_SHSetWindowBits(void)
1659 DWORD style
, styleold
;
1662 if(!pSHSetWindowBits
)
1664 win_skip("SHSetWindowBits is not available\n");
1669 clsA
.lpfnWndProc
= DefWindowProcA
;
1670 clsA
.cbClsExtra
= 0;
1671 clsA
.cbWndExtra
= 0;
1672 clsA
.hInstance
= GetModuleHandleA(NULL
);
1674 clsA
.hCursor
= LoadCursorA(0, (LPSTR
)IDC_ARROW
);
1675 clsA
.hbrBackground
= NULL
;
1676 clsA
.lpszMenuName
= NULL
;
1677 clsA
.lpszClassName
= "Shlwapi test class";
1678 RegisterClassA(&clsA
);
1680 hwnd
= CreateWindowA("Shlwapi test class", "Test", WS_VISIBLE
, 0, 0, 100, 100,
1681 NULL
, NULL
, GetModuleHandleA(NULL
), 0);
1682 ok(IsWindow(hwnd
), "failed to create window\n");
1685 SetLastError(0xdeadbeef);
1686 style
= pSHSetWindowBits(NULL
, GWL_STYLE
, 0, 0);
1687 ok(style
== 0, "expected 0 retval, got %d\n", style
);
1688 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
||
1689 broken(GetLastError() == 0xdeadbeef), /* Win9x/WinMe */
1690 "expected ERROR_INVALID_WINDOW_HANDLE, got %d\n", GetLastError());
1692 /* zero mask, zero flags */
1693 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1694 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, 0, 0);
1695 ok(styleold
== style
, "expected old style\n");
1696 ok(styleold
== GetWindowLongA(hwnd
, GWL_STYLE
), "expected to keep old style\n");
1699 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1700 ok(styleold
& WS_VISIBLE
, "expected WS_VISIBLE\n");
1701 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, WS_VISIBLE
, 0);
1703 ok(style
== styleold
, "expected previous style, got %x\n", style
);
1704 ok((GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
) == 0, "expected updated style\n");
1706 /* test mask, unset style bit used */
1707 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1708 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, WS_VISIBLE
, 0);
1709 ok(style
== styleold
, "expected previous style, got %x\n", style
);
1710 ok(styleold
== GetWindowLongA(hwnd
, GWL_STYLE
), "expected to keep old style\n");
1712 /* set back with flags */
1713 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1714 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, WS_VISIBLE
, WS_VISIBLE
);
1715 ok(style
== styleold
, "expected previous style, got %x\n", style
);
1716 ok(GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
, "expected updated style\n");
1718 /* reset and try to set without a mask */
1719 pSHSetWindowBits(hwnd
, GWL_STYLE
, WS_VISIBLE
, 0);
1720 ok((GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
) == 0, "expected updated style\n");
1721 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1722 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, 0, WS_VISIBLE
);
1723 ok(style
== styleold
, "expected previous style, got %x\n", style
);
1724 ok((GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
) == 0, "expected updated style\n");
1726 DestroyWindow(hwnd
);
1728 UnregisterClassA("Shlwapi test class", GetModuleHandleA(NULL
));
1731 static void test_SHFormatDateTimeA(void)
1733 FILETIME UNALIGNED filetime
;
1734 CHAR buff
[100], buff2
[100], buff3
[100];
1739 if(!pSHFormatDateTimeA
)
1741 win_skip("pSHFormatDateTimeA isn't available\n");
1747 /* crashes on native */
1748 pSHFormatDateTimeA(NULL
, NULL
, NULL
, 0);
1752 SystemTimeToFileTime(&st
, &filetime
);
1753 /* SHFormatDateTime expects input as utc */
1754 LocalFileTimeToFileTime(&filetime
, &filetime
);
1756 /* no way to get required buffer length here */
1757 SetLastError(0xdeadbeef);
1758 ret
= pSHFormatDateTimeA(&filetime
, NULL
, NULL
, 0);
1759 ok(ret
== 0, "got %d\n", ret
);
1760 ok(GetLastError() == 0xdeadbeef || broken(GetLastError() == ERROR_SUCCESS
/* Win7 */),
1761 "expected 0xdeadbeef, got %d\n", GetLastError());
1763 SetLastError(0xdeadbeef);
1764 buff
[0] = 'a'; buff
[1] = 0;
1765 ret
= pSHFormatDateTimeA(&filetime
, NULL
, buff
, 0);
1766 ok(ret
== 0, "got %d\n", ret
);
1767 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1768 ok(buff
[0] == 'a', "expected same string, got %s\n", buff
);
1770 /* flags needs to have FDTF_NOAUTOREADINGORDER for these tests to succeed on Vista+ */
1772 /* all combinations documented as invalid succeeded */
1773 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTTIME
| FDTF_LONGTIME
;
1774 SetLastError(0xdeadbeef);
1775 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1776 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1777 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1779 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTDATE
| FDTF_LONGDATE
;
1780 SetLastError(0xdeadbeef);
1781 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1782 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1783 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1785 flags
= FDTF_SHORTDATE
| FDTF_LTRDATE
| FDTF_RTLDATE
;
1786 SetLastError(0xdeadbeef);
1787 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1788 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1789 ok(GetLastError() == 0xdeadbeef ||
1790 broken(GetLastError() == ERROR_INVALID_FLAGS
), /* Win9x/WinMe */
1791 "expected 0xdeadbeef, got %d\n", GetLastError());
1793 /* now check returned strings */
1794 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTTIME
;
1795 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1796 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1797 ret
= GetTimeFormatA(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff2
, sizeof(buff2
));
1798 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1799 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1801 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGTIME
;
1802 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1803 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1804 ret
= GetTimeFormatA(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff2
, sizeof(buff2
));
1805 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1806 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1808 /* both time flags */
1809 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGTIME
| FDTF_SHORTTIME
;
1810 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1811 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1812 ret
= GetTimeFormatA(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff2
, sizeof(buff2
));
1813 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1814 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1816 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTDATE
;
1817 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1818 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1819 ret
= GetDateFormatA(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1820 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1821 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1823 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGDATE
;
1824 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1825 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1826 ret
= GetDateFormatA(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1827 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1828 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1830 /* both date flags */
1831 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGDATE
| FDTF_SHORTDATE
;
1832 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1833 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1834 ret
= GetDateFormatA(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1835 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1836 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1838 /* various combinations of date/time flags */
1839 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGDATE
| FDTF_SHORTTIME
;
1840 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1841 ok(ret
== lstrlenA(buff
)+1, "got %d, length %d\n", ret
, lstrlenA(buff
)+1);
1842 ret
= GetTimeFormatA(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff3
, sizeof(buff3
));
1843 ok(ret
== lstrlenA(buff3
)+1, "got %d\n", ret
);
1844 ok(lstrcmpA(buff3
, buff
+ lstrlenA(buff
) - lstrlenA(buff3
)) == 0,
1845 "expected (%s), got (%s) for time part\n",
1846 buff3
, buff
+ lstrlenA(buff
) - lstrlenA(buff3
));
1847 ret
= GetDateFormatA(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1848 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1849 buff
[lstrlenA(buff2
)] = '\0';
1850 ok(lstrcmpA(buff2
, buff
) == 0, "expected (%s) got (%s) for date part\n",
1853 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGDATE
| FDTF_LONGTIME
;
1854 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1855 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1856 ret
= GetTimeFormatA(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff3
, sizeof(buff3
));
1857 ok(ret
== lstrlenA(buff3
)+1, "got %d\n", ret
);
1858 ok(lstrcmpA(buff3
, buff
+ lstrlenA(buff
) - lstrlenA(buff3
)) == 0,
1859 "expected (%s), got (%s) for time part\n",
1860 buff3
, buff
+ lstrlenA(buff
) - lstrlenA(buff3
));
1861 ret
= GetDateFormatA(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1862 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1863 buff
[lstrlenA(buff2
)] = '\0';
1864 ok(lstrcmpA(buff2
, buff
) == 0, "expected (%s) got (%s) for date part\n",
1867 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTDATE
| FDTF_SHORTTIME
;
1868 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1869 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1870 ret
= GetDateFormatA(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1871 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1873 ret
= GetTimeFormatA(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff3
, sizeof(buff3
));
1874 ok(ret
== lstrlenA(buff3
)+1, "got %d\n", ret
);
1875 strcat(buff2
, buff3
);
1876 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1878 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTDATE
| FDTF_LONGTIME
;
1879 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1880 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1881 ret
= GetDateFormatA(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
));
1882 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1884 ret
= GetTimeFormatA(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff3
, sizeof(buff3
));
1885 ok(ret
== lstrlenA(buff3
)+1, "got %d\n", ret
);
1886 strcat(buff2
, buff3
);
1887 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1890 static void test_SHFormatDateTimeW(void)
1892 FILETIME UNALIGNED filetime
;
1893 WCHAR buff
[100], buff2
[100], buff3
[100], *p1
, *p2
;
1897 static const WCHAR spaceW
[] = {' ',0};
1898 #define UNICODE_LTR_MARK 0x200e
1899 #define UNICODE_RTL_MARK 0x200f
1901 if(!pSHFormatDateTimeW
)
1903 win_skip("pSHFormatDateTimeW isn't available\n");
1909 /* crashes on native */
1910 pSHFormatDateTimeW(NULL
, NULL
, NULL
, 0);
1914 SystemTimeToFileTime(&st
, &filetime
);
1915 /* SHFormatDateTime expects input as utc */
1916 LocalFileTimeToFileTime(&filetime
, &filetime
);
1918 /* no way to get required buffer length here */
1919 SetLastError(0xdeadbeef);
1920 ret
= pSHFormatDateTimeW(&filetime
, NULL
, NULL
, 0);
1921 ok(ret
== 0, "expected 0, got %d\n", ret
);
1922 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1924 SetLastError(0xdeadbeef);
1925 buff
[0] = 'a'; buff
[1] = 0;
1926 ret
= pSHFormatDateTimeW(&filetime
, NULL
, buff
, 0);
1927 ok(ret
== 0, "expected 0, got %d\n", ret
);
1928 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1929 ok(buff
[0] == 'a', "expected same string\n");
1931 /* all combinations documented as invalid succeeded */
1932 flags
= FDTF_SHORTTIME
| FDTF_LONGTIME
;
1933 SetLastError(0xdeadbeef);
1934 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1935 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1936 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1937 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1939 flags
= FDTF_SHORTDATE
| FDTF_LONGDATE
;
1940 SetLastError(0xdeadbeef);
1941 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1942 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1943 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1944 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1946 flags
= FDTF_SHORTDATE
| FDTF_LTRDATE
| FDTF_RTLDATE
;
1947 SetLastError(0xdeadbeef);
1948 buff
[0] = 0; /* NT4 doesn't clear the buffer on failure */
1949 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1950 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1951 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1952 ok(GetLastError() == 0xdeadbeef ||
1953 broken(GetLastError() == ERROR_INVALID_FLAGS
), /* Win9x/WinMe/NT4 */
1954 "expected 0xdeadbeef, got %d\n", GetLastError());
1956 /* now check returned strings */
1957 flags
= FDTF_SHORTTIME
;
1958 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1959 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1960 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1961 SetLastError(0xdeadbeef);
1962 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1963 if (ret
== 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
1965 win_skip("Needed W-functions are not implemented\n");
1968 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1969 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1971 flags
= FDTF_LONGTIME
;
1972 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1973 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1974 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1975 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1976 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1977 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1979 /* both time flags */
1980 flags
= FDTF_LONGTIME
| FDTF_SHORTTIME
;
1981 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1982 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1983 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1984 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1985 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1986 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal string\n");
1988 flags
= FDTF_SHORTDATE
;
1989 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1990 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1991 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1992 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
1993 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1994 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1996 flags
= FDTF_LONGDATE
;
1997 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
1998 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1999 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
2000 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
2001 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
2002 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
2004 /* both date flags */
2005 flags
= FDTF_LONGDATE
| FDTF_SHORTDATE
;
2006 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
2007 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
2008 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
2009 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
2010 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
2011 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
2013 /* various combinations of date/time flags */
2014 flags
= FDTF_LONGDATE
| FDTF_SHORTTIME
;
2015 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
2016 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
2017 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
2018 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff3
, sizeof(buff3
)/sizeof(WCHAR
));
2019 ok(ret
== lstrlenW(buff3
)+1, "expected %d, got %d\n", lstrlenW(buff3
)+1, ret
);
2020 ok(lstrcmpW(buff3
, buff
+ lstrlenW(buff
) - lstrlenW(buff3
)) == 0,
2021 "expected (%s), got (%s) for time part\n",
2022 wine_dbgstr_w(buff3
), wine_dbgstr_w(buff
+ lstrlenW(buff
) - lstrlenW(buff3
)));
2023 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
2024 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
2029 while (*p1
== UNICODE_LTR_MARK
|| *p1
== UNICODE_RTL_MARK
)
2031 while (*p2
== UNICODE_LTR_MARK
|| *p2
== UNICODE_RTL_MARK
)
2037 ok(lstrcmpW(buff2
, buff
) == 0, "expected (%s) got (%s) for date part\n",
2038 wine_dbgstr_w(buff2
), wine_dbgstr_w(buff
));
2040 flags
= FDTF_LONGDATE
| FDTF_LONGTIME
;
2041 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
2042 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
2043 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
2044 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff3
, sizeof(buff3
)/sizeof(WCHAR
));
2045 ok(ret
== lstrlenW(buff3
)+1, "expected %d, got %d\n", lstrlenW(buff3
)+1, ret
);
2046 ok(lstrcmpW(buff3
, buff
+ lstrlenW(buff
) - lstrlenW(buff3
)) == 0,
2047 "expected (%s), got (%s) for time part\n",
2048 wine_dbgstr_w(buff3
), wine_dbgstr_w(buff
+ lstrlenW(buff
) - lstrlenW(buff3
)));
2049 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
2050 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
2055 while (*p1
== UNICODE_LTR_MARK
|| *p1
== UNICODE_RTL_MARK
)
2057 while (*p2
== UNICODE_LTR_MARK
|| *p2
== UNICODE_RTL_MARK
)
2063 ok(lstrcmpW(buff2
, buff
) == 0, "expected (%s) got (%s) for date part\n",
2064 wine_dbgstr_w(buff2
), wine_dbgstr_w(buff
));
2066 flags
= FDTF_SHORTDATE
| FDTF_SHORTTIME
;
2067 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
2068 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
2069 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
2070 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
2071 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
2072 lstrcatW(buff2
, spaceW
);
2073 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff3
, sizeof(buff3
)/sizeof(WCHAR
));
2074 ok(ret
== lstrlenW(buff3
)+1, "expected %d, got %d\n", lstrlenW(buff3
)+1, ret
);
2075 lstrcatW(buff2
, buff3
);
2076 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
2078 flags
= FDTF_SHORTDATE
| FDTF_LONGTIME
;
2079 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, sizeof(buff
)/sizeof(WCHAR
));
2080 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
2081 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
2082 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, sizeof(buff2
)/sizeof(WCHAR
));
2083 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
2084 lstrcatW(buff2
, spaceW
);
2085 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff3
, sizeof(buff3
)/sizeof(WCHAR
));
2086 ok(ret
== lstrlenW(buff3
)+1, "expected %d, got %d\n", lstrlenW(buff3
)+1, ret
);
2087 lstrcatW(buff2
, buff3
);
2088 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
2091 static void test_SHGetObjectCompatFlags(void)
2093 struct compat_value
{
2098 struct compat_value values
[] = {
2099 { "OTNEEDSSFCACHE", 0x1 },
2100 { "NO_WEBVIEW", 0x2 },
2101 { "UNBINDABLE", 0x4 },
2103 { "NEEDSFILESYSANCESTOR", 0x10 },
2104 { "NOTAFILESYSTEM", 0x20 },
2105 { "CTXMENU_NOVERBS", 0x40 },
2106 { "CTXMENU_LIMITEDQI", 0x80 },
2107 { "COCREATESHELLFOLDERONLY", 0x100 },
2108 { "NEEDSSTORAGEANCESTOR", 0x200 },
2109 { "NOLEGACYWEBVIEW", 0x400 },
2110 { "CTXMENU_XPQCMFLAGS", 0x1000 },
2111 { "NOIPROPERTYSTORE", 0x2000 }
2114 static const char compat_path
[] = "Software\\Microsoft\\Windows\\CurrentVersion\\ShellCompatibility\\Objects";
2115 void *pColorAdjustLuma
= GetProcAddress(hShlwapi
, "ColorAdjustLuma");
2116 CHAR keyA
[39]; /* {CLSID} */
2121 if (!pSHGetObjectCompatFlags
)
2123 win_skip("SHGetObjectCompatFlags isn't available\n");
2127 if (pColorAdjustLuma
&& pColorAdjustLuma
== pSHGetObjectCompatFlags
) /* win2k */
2129 win_skip("Skipping SHGetObjectCompatFlags, same ordinal used for ColorAdjustLuma\n");
2134 ret
= pSHGetObjectCompatFlags(NULL
, NULL
);
2135 ok(ret
== 0, "got %d\n", ret
);
2137 ret
= RegOpenKeyA(HKEY_LOCAL_MACHINE
, compat_path
, &root
);
2138 if (ret
!= ERROR_SUCCESS
)
2140 skip("No compatibility class data found\n");
2144 for (i
= 0; RegEnumKeyA(root
, i
, keyA
, sizeof(keyA
)) == ERROR_SUCCESS
; i
++)
2148 if (RegOpenKeyA(root
, keyA
, &clsid_key
) == ERROR_SUCCESS
)
2151 DWORD expected
= 0, got
, length
= sizeof(valueA
);
2155 for (v
= 0; RegEnumValueA(clsid_key
, v
, valueA
, &length
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
; v
++)
2159 for (j
= 0; j
< sizeof(values
)/sizeof(struct compat_value
); j
++)
2160 if (lstrcmpA(values
[j
].nameA
, valueA
) == 0)
2162 expected
|= values
[j
].value
;
2166 length
= sizeof(valueA
);
2169 pGUIDFromStringA(keyA
, &clsid
);
2170 got
= pSHGetObjectCompatFlags(NULL
, &clsid
);
2171 ok(got
== expected
, "got 0x%08x, expected 0x%08x. Key %s\n", got
, expected
, keyA
);
2173 RegCloseKey(clsid_key
);
2181 IOleCommandTarget IOleCommandTarget_iface
;
2183 } IOleCommandTargetImpl
;
2185 static inline IOleCommandTargetImpl
*impl_from_IOleCommandTarget(IOleCommandTarget
*iface
)
2187 return CONTAINING_RECORD(iface
, IOleCommandTargetImpl
, IOleCommandTarget_iface
);
2190 static const IOleCommandTargetVtbl IOleCommandTargetImpl_Vtbl
;
2192 static IOleCommandTarget
* IOleCommandTargetImpl_Construct(void)
2194 IOleCommandTargetImpl
*obj
;
2196 obj
= HeapAlloc(GetProcessHeap(), 0, sizeof(*obj
));
2197 obj
->IOleCommandTarget_iface
.lpVtbl
= &IOleCommandTargetImpl_Vtbl
;
2200 return &obj
->IOleCommandTarget_iface
;
2203 static HRESULT WINAPI
IOleCommandTargetImpl_QueryInterface(IOleCommandTarget
*iface
, REFIID riid
, void **ppvObj
)
2205 IOleCommandTargetImpl
*This
= impl_from_IOleCommandTarget(iface
);
2207 if (IsEqualIID(riid
, &IID_IUnknown
) ||
2208 IsEqualIID(riid
, &IID_IOleCommandTarget
))
2215 IOleCommandTarget_AddRef(iface
);
2219 return E_NOINTERFACE
;
2222 static ULONG WINAPI
IOleCommandTargetImpl_AddRef(IOleCommandTarget
*iface
)
2224 IOleCommandTargetImpl
*This
= impl_from_IOleCommandTarget(iface
);
2225 return InterlockedIncrement(&This
->ref
);
2228 static ULONG WINAPI
IOleCommandTargetImpl_Release(IOleCommandTarget
*iface
)
2230 IOleCommandTargetImpl
*This
= impl_from_IOleCommandTarget(iface
);
2231 ULONG ref
= InterlockedDecrement(&This
->ref
);
2235 HeapFree(GetProcessHeap(), 0, This
);
2241 static HRESULT WINAPI
IOleCommandTargetImpl_QueryStatus(
2242 IOleCommandTarget
*iface
, const GUID
*group
, ULONG cCmds
, OLECMD prgCmds
[], OLECMDTEXT
*pCmdText
)
2247 static HRESULT WINAPI
IOleCommandTargetImpl_Exec(
2248 IOleCommandTarget
*iface
,
2249 const GUID
*CmdGroup
,
2255 add_call(&trace_got
, 3, CmdGroup
, (void*)(DWORD_PTR
)nCmdID
, (void*)(DWORD_PTR
)nCmdexecopt
, pvaIn
, pvaOut
);
2259 static const IOleCommandTargetVtbl IOleCommandTargetImpl_Vtbl
=
2261 IOleCommandTargetImpl_QueryInterface
,
2262 IOleCommandTargetImpl_AddRef
,
2263 IOleCommandTargetImpl_Release
,
2264 IOleCommandTargetImpl_QueryStatus
,
2265 IOleCommandTargetImpl_Exec
2269 IServiceProvider IServiceProvider_iface
;
2271 } IServiceProviderImpl
;
2273 static inline IServiceProviderImpl
*impl_from_IServiceProvider(IServiceProvider
*iface
)
2275 return CONTAINING_RECORD(iface
, IServiceProviderImpl
, IServiceProvider_iface
);
2279 IProfferService IProfferService_iface
;
2281 } IProfferServiceImpl
;
2283 static inline IProfferServiceImpl
*impl_from_IProfferService(IProfferService
*iface
)
2285 return CONTAINING_RECORD(iface
, IProfferServiceImpl
, IProfferService_iface
);
2289 static const IServiceProviderVtbl IServiceProviderImpl_Vtbl
;
2290 static const IProfferServiceVtbl IProfferServiceImpl_Vtbl
;
2292 static IServiceProvider
* IServiceProviderImpl_Construct(void)
2294 IServiceProviderImpl
*obj
;
2296 obj
= HeapAlloc(GetProcessHeap(), 0, sizeof(*obj
));
2297 obj
->IServiceProvider_iface
.lpVtbl
= &IServiceProviderImpl_Vtbl
;
2300 return &obj
->IServiceProvider_iface
;
2303 static IProfferService
* IProfferServiceImpl_Construct(void)
2305 IProfferServiceImpl
*obj
;
2307 obj
= HeapAlloc(GetProcessHeap(), 0, sizeof(*obj
));
2308 obj
->IProfferService_iface
.lpVtbl
= &IProfferServiceImpl_Vtbl
;
2311 return &obj
->IProfferService_iface
;
2314 static HRESULT WINAPI
IServiceProviderImpl_QueryInterface(IServiceProvider
*iface
, REFIID riid
, void **ppvObj
)
2316 IServiceProviderImpl
*This
= impl_from_IServiceProvider(iface
);
2318 if (IsEqualIID(riid
, &IID_IUnknown
) ||
2319 IsEqualIID(riid
, &IID_IServiceProvider
))
2326 IServiceProvider_AddRef(iface
);
2327 /* native uses redefined IID_IServiceProvider symbol, so we can't compare pointers */
2328 if (IsEqualIID(riid
, &IID_IServiceProvider
))
2329 add_call(&trace_got
, 1, iface
, &IID_IServiceProvider
, 0, 0, 0);
2333 return E_NOINTERFACE
;
2336 static ULONG WINAPI
IServiceProviderImpl_AddRef(IServiceProvider
*iface
)
2338 IServiceProviderImpl
*This
= impl_from_IServiceProvider(iface
);
2339 return InterlockedIncrement(&This
->ref
);
2342 static ULONG WINAPI
IServiceProviderImpl_Release(IServiceProvider
*iface
)
2344 IServiceProviderImpl
*This
= impl_from_IServiceProvider(iface
);
2345 ULONG ref
= InterlockedDecrement(&This
->ref
);
2349 HeapFree(GetProcessHeap(), 0, This
);
2355 static HRESULT WINAPI
IServiceProviderImpl_QueryService(
2356 IServiceProvider
*iface
, REFGUID service
, REFIID riid
, void **ppv
)
2358 /* native uses redefined pointer for IID_IOleCommandTarget, not one from uuid.lib */
2359 if (IsEqualIID(riid
, &IID_IOleCommandTarget
))
2361 add_call(&trace_got
, 2, iface
, service
, &IID_IOleCommandTarget
, 0, 0);
2362 *ppv
= IOleCommandTargetImpl_Construct();
2364 if (IsEqualIID(riid
, &IID_IProfferService
))
2366 if (IsEqualIID(service
, &IID_IProfferService
))
2367 add_call(&trace_got
, 2, &IID_IProfferService
, &IID_IProfferService
, 0, 0, 0);
2368 *ppv
= IProfferServiceImpl_Construct();
2373 static const IServiceProviderVtbl IServiceProviderImpl_Vtbl
=
2375 IServiceProviderImpl_QueryInterface
,
2376 IServiceProviderImpl_AddRef
,
2377 IServiceProviderImpl_Release
,
2378 IServiceProviderImpl_QueryService
2381 static void test_IUnknown_QueryServiceExec(void)
2383 IServiceProvider
*provider
;
2384 static const GUID dummy_serviceid
= { 0xdeadbeef };
2385 static const GUID dummy_groupid
= { 0xbeefbeef };
2386 call_trace_t trace_expected
;
2389 /* on <=W2K platforms same ordinal used for another export with different
2390 prototype, so skipping using this indirect condition */
2391 if (is_win2k_and_lower
)
2393 win_skip("IUnknown_QueryServiceExec is not available\n");
2397 provider
= IServiceProviderImpl_Construct();
2399 /* null source pointer */
2400 hr
= pIUnknown_QueryServiceExec(NULL
, &dummy_serviceid
, &dummy_groupid
, 0, 0, 0, 0);
2402 hr
== E_NOTIMPL
, /* win 8 */
2403 "got 0x%08x\n", hr
);
2406 IUnknown_QueryServiceExec( ptr1, serviceid, groupid, arg1, arg2, arg3, arg4);
2407 -> IUnknown_QueryInterface( ptr1, &IID_IServiceProvider, &prov );
2408 -> IServiceProvider_QueryService( prov, serviceid, &IID_IOleCommandTarget, &obj );
2409 -> IOleCommandTarget_Exec( obj, groupid, arg1, arg2, arg3, arg4 );
2411 init_call_trace(&trace_expected
);
2413 add_call(&trace_expected
, 1, provider
, &IID_IServiceProvider
, 0, 0, 0);
2414 add_call(&trace_expected
, 2, provider
, &dummy_serviceid
, &IID_IOleCommandTarget
, 0, 0);
2415 add_call(&trace_expected
, 3, &dummy_groupid
, (void*)0x1, (void*)0x2, (void*)0x3, (void*)0x4);
2417 init_call_trace(&trace_got
);
2418 hr
= pIUnknown_QueryServiceExec((IUnknown
*)provider
, &dummy_serviceid
, &dummy_groupid
, 0x1, 0x2, (void*)0x3, (void*)0x4);
2419 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2421 ok_trace(&trace_expected
, &trace_got
);
2423 free_call_trace(&trace_expected
);
2424 free_call_trace(&trace_got
);
2426 IServiceProvider_Release(provider
);
2430 static HRESULT WINAPI
IProfferServiceImpl_QueryInterface(IProfferService
*iface
, REFIID riid
, void **ppvObj
)
2432 IProfferServiceImpl
*This
= impl_from_IProfferService(iface
);
2434 if (IsEqualIID(riid
, &IID_IUnknown
) ||
2435 IsEqualIID(riid
, &IID_IProfferService
))
2439 else if (IsEqualIID(riid
, &IID_IServiceProvider
))
2441 *ppvObj
= IServiceProviderImpl_Construct();
2442 add_call(&trace_got
, 1, iface
, &IID_IServiceProvider
, 0, 0, 0);
2448 IProfferService_AddRef(iface
);
2452 return E_NOINTERFACE
;
2455 static ULONG WINAPI
IProfferServiceImpl_AddRef(IProfferService
*iface
)
2457 IProfferServiceImpl
*This
= impl_from_IProfferService(iface
);
2458 return InterlockedIncrement(&This
->ref
);
2461 static ULONG WINAPI
IProfferServiceImpl_Release(IProfferService
*iface
)
2463 IProfferServiceImpl
*This
= impl_from_IProfferService(iface
);
2464 ULONG ref
= InterlockedDecrement(&This
->ref
);
2468 HeapFree(GetProcessHeap(), 0, This
);
2474 static HRESULT WINAPI
IProfferServiceImpl_ProfferService(IProfferService
*iface
,
2475 REFGUID service
, IServiceProvider
*pService
, DWORD
*pCookie
)
2477 *pCookie
= 0xdeadbeef;
2478 add_call(&trace_got
, 3, service
, pService
, pCookie
, 0, 0);
2482 static HRESULT WINAPI
IProfferServiceImpl_RevokeService(IProfferService
*iface
, DWORD cookie
)
2484 add_call(&trace_got
, 4, (void*)(DWORD_PTR
)cookie
, 0, 0, 0, 0);
2488 static const IProfferServiceVtbl IProfferServiceImpl_Vtbl
=
2490 IProfferServiceImpl_QueryInterface
,
2491 IProfferServiceImpl_AddRef
,
2492 IProfferServiceImpl_Release
,
2493 IProfferServiceImpl_ProfferService
,
2494 IProfferServiceImpl_RevokeService
2497 static void test_IUnknown_ProfferService(void)
2499 IServiceProvider
*provider
;
2500 IProfferService
*proff
;
2501 static const GUID dummy_serviceid
= { 0xdeadbeef };
2502 call_trace_t trace_expected
;
2506 /* on <=W2K platforms same ordinal used for another export with different
2507 prototype, so skipping using this indirect condition */
2508 if (is_win2k_and_lower
)
2510 win_skip("IUnknown_ProfferService is not available\n");
2514 provider
= IServiceProviderImpl_Construct();
2515 proff
= IProfferServiceImpl_Construct();
2517 /* null source pointer */
2518 hr
= pIUnknown_ProfferService(NULL
, &dummy_serviceid
, 0, 0);
2520 hr
== E_NOTIMPL
, /* win 8 */
2521 "got 0x%08x\n", hr
);
2524 IUnknown_ProfferService( ptr1, serviceid, arg1, arg2);
2525 -> IUnknown_QueryInterface( ptr1, &IID_IServiceProvider, &provider );
2526 -> IServiceProvider_QueryService( provider, &IID_IProfferService, &IID_IProfferService, &proffer );
2528 if (service pointer not null):
2529 -> IProfferService_ProfferService( proffer, serviceid, arg1, arg2 );
2531 -> IProfferService_RevokeService( proffer, *arg2 );
2533 init_call_trace(&trace_expected
);
2535 add_call(&trace_expected
, 1, proff
, &IID_IServiceProvider
, 0, 0, 0);
2536 add_call(&trace_expected
, 2, &IID_IProfferService
, &IID_IProfferService
, 0, 0, 0);
2537 add_call(&trace_expected
, 3, &dummy_serviceid
, provider
, &cookie
, 0, 0);
2539 init_call_trace(&trace_got
);
2541 hr
= pIUnknown_ProfferService((IUnknown
*)proff
, &dummy_serviceid
, provider
, &cookie
);
2542 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2543 ok(cookie
== 0xdeadbeef, "got %x\n", cookie
);
2545 ok_trace(&trace_expected
, &trace_got
);
2546 free_call_trace(&trace_got
);
2547 free_call_trace(&trace_expected
);
2549 /* same with ::Revoke path */
2550 init_call_trace(&trace_expected
);
2552 add_call(&trace_expected
, 1, proff
, &IID_IServiceProvider
, 0, 0, 0);
2553 add_call(&trace_expected
, 2, &IID_IProfferService
, &IID_IProfferService
, 0, 0, 0);
2554 add_call(&trace_expected
, 4, (void*)(DWORD_PTR
)cookie
, 0, 0, 0, 0);
2556 init_call_trace(&trace_got
);
2557 ok(cookie
!= 0, "got %x\n", cookie
);
2558 hr
= pIUnknown_ProfferService((IUnknown
*)proff
, &dummy_serviceid
, 0, &cookie
);
2559 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2560 ok(cookie
== 0, "got %x\n", cookie
);
2561 ok_trace(&trace_expected
, &trace_got
);
2562 free_call_trace(&trace_got
);
2563 free_call_trace(&trace_expected
);
2565 IServiceProvider_Release(provider
);
2566 IProfferService_Release(proff
);
2569 static void test_SHCreateWorkerWindowA(void)
2577 if (is_win2k_and_lower
)
2579 win_skip("SHCreateWorkerWindowA not available\n");
2583 hwnd
= pSHCreateWorkerWindowA(0, NULL
, 0, 0, 0, 0);
2584 ok(hwnd
!= 0, "expected window\n");
2586 GetClassNameA(hwnd
, classA
, 20);
2587 ok(lstrcmpA(classA
, "WorkerA") == 0, "expected WorkerA class, got %s\n", classA
);
2589 ret
= GetWindowLongPtrA(hwnd
, 0);
2590 ok(ret
== 0, "got %ld\n", ret
);
2593 memset(&cliA
, 0, sizeof(cliA
));
2594 res
= GetClassInfoA(GetModuleHandleA("shlwapi.dll"), "WorkerA", &cliA
);
2595 ok(res
, "failed to get class info\n");
2596 ok(cliA
.style
== 0, "got 0x%08x\n", cliA
.style
);
2597 ok(cliA
.cbClsExtra
== 0, "got %d\n", cliA
.cbClsExtra
);
2598 ok(cliA
.cbWndExtra
== sizeof(LONG_PTR
), "got %d\n", cliA
.cbWndExtra
);
2599 ok(cliA
.lpszMenuName
== 0, "got %s\n", cliA
.lpszMenuName
);
2601 DestroyWindow(hwnd
);
2603 /* set extra bytes */
2604 hwnd
= pSHCreateWorkerWindowA(0, NULL
, 0, 0, 0, 0xdeadbeef);
2605 ok(hwnd
!= 0, "expected window\n");
2607 GetClassNameA(hwnd
, classA
, 20);
2608 ok(lstrcmpA(classA
, "WorkerA") == 0, "expected WorkerA class, got %s\n", classA
);
2610 ret
= GetWindowLongPtrA(hwnd
, 0);
2611 ok(ret
== 0xdeadbeef, "got %ld\n", ret
);
2614 ret
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
2615 ok(ret
== WS_EX_WINDOWEDGE
||
2616 ret
== (WS_EX_WINDOWEDGE
|WS_EX_LAYOUTRTL
) /* systems with RTL locale */, "0x%08lx\n", ret
);
2618 DestroyWindow(hwnd
);
2620 hwnd
= pSHCreateWorkerWindowA(0, NULL
, WS_EX_TOOLWINDOW
, 0, 0, 0);
2621 ret
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
2622 ok(ret
== (WS_EX_WINDOWEDGE
|WS_EX_TOOLWINDOW
) ||
2623 ret
== (WS_EX_WINDOWEDGE
|WS_EX_TOOLWINDOW
|WS_EX_LAYOUTRTL
) /* systems with RTL locale */, "0x%08lx\n", ret
);
2624 DestroyWindow(hwnd
);
2627 static HRESULT WINAPI
SF_QueryInterface(IShellFolder
*iface
,
2628 REFIID riid
, void **ppv
)
2630 /* SHIShellFolder_EnumObjects doesn't QI the object for IShellFolder */
2631 ok(!IsEqualGUID(&IID_IShellFolder
, riid
),
2632 "Unexpected QI for IShellFolder\n");
2633 return E_NOINTERFACE
;
2636 static ULONG WINAPI
SF_AddRef(IShellFolder
*iface
)
2641 static ULONG WINAPI
SF_Release(IShellFolder
*iface
)
2646 static HRESULT WINAPI
SF_ParseDisplayName(IShellFolder
*iface
,
2647 HWND owner
, LPBC reserved
, LPOLESTR displayName
, ULONG
*eaten
,
2648 LPITEMIDLIST
*idl
, ULONG
*attr
)
2650 ok(0, "Didn't expect ParseDisplayName\n");
2654 static HRESULT WINAPI
SF_EnumObjects(IShellFolder
*iface
,
2655 HWND owner
, SHCONTF flags
, IEnumIDList
**enm
)
2657 *enm
= (IEnumIDList
*)0xcafebabe;
2661 static HRESULT WINAPI
SF_BindToObject(IShellFolder
*iface
,
2662 LPCITEMIDLIST idl
, LPBC reserved
, REFIID riid
, void **obj
)
2664 ok(0, "Didn't expect BindToObject\n");
2668 static HRESULT WINAPI
SF_BindToStorage(IShellFolder
*iface
,
2669 LPCITEMIDLIST idl
, LPBC reserved
, REFIID riid
, void **obj
)
2671 ok(0, "Didn't expect BindToStorage\n");
2675 static HRESULT WINAPI
SF_CompareIDs(IShellFolder
*iface
,
2676 LPARAM lparam
, LPCITEMIDLIST idl1
, LPCITEMIDLIST idl2
)
2678 ok(0, "Didn't expect CompareIDs\n");
2682 static HRESULT WINAPI
SF_CreateViewObject(IShellFolder
*iface
,
2683 HWND owner
, REFIID riid
, void **out
)
2685 ok(0, "Didn't expect CreateViewObject\n");
2689 static HRESULT WINAPI
SF_GetAttributesOf(IShellFolder
*iface
,
2690 UINT cidl
, LPCITEMIDLIST
*idl
, SFGAOF
*inOut
)
2692 ok(0, "Didn't expect GetAttributesOf\n");
2696 static HRESULT WINAPI
SF_GetUIObjectOf(IShellFolder
*iface
,
2697 HWND owner
, UINT cidl
, LPCITEMIDLIST
*idls
, REFIID riid
, UINT
*inOut
,
2700 ok(0, "Didn't expect GetUIObjectOf\n");
2704 static HRESULT WINAPI
SF_GetDisplayNameOf(IShellFolder
*iface
,
2705 LPCITEMIDLIST idl
, SHGDNF flags
, STRRET
*name
)
2707 ok(0, "Didn't expect GetDisplayNameOf\n");
2711 static HRESULT WINAPI
SF_SetNameOf(IShellFolder
*iface
,
2712 HWND hwnd
, LPCITEMIDLIST idl
, LPCOLESTR name
, SHGDNF flags
,
2713 LPITEMIDLIST
*idlOut
)
2715 ok(0, "Didn't expect SetNameOf\n");
2719 static IShellFolderVtbl ShellFolderVtbl
= {
2723 SF_ParseDisplayName
,
2728 SF_CreateViewObject
,
2731 SF_GetDisplayNameOf
,
2735 static IShellFolder ShellFolder
= { &ShellFolderVtbl
};
2737 static void test_SHIShellFolder_EnumObjects(void)
2741 IShellFolder
*folder
;
2743 if(!pSHIShellFolder_EnumObjects
|| is_win2k_and_lower
){
2744 win_skip("SHIShellFolder_EnumObjects not available\n");
2749 /* NULL object crashes on Windows */
2750 pSHIShellFolder_EnumObjects(NULL
, NULL
, 0, NULL
);
2753 /* SHIShellFolder_EnumObjects doesn't QI the object for IShellFolder */
2754 enm
= (IEnumIDList
*)0xdeadbeef;
2755 hres
= pSHIShellFolder_EnumObjects(&ShellFolder
, NULL
, 0, &enm
);
2756 ok(hres
== S_OK
, "SHIShellFolder_EnumObjects failed: 0x%08x\n", hres
);
2757 ok(enm
== (IEnumIDList
*)0xcafebabe, "Didn't get expected enumerator location, instead: %p\n", enm
);
2759 /* SHIShellFolder_EnumObjects isn't strict about the IShellFolder object */
2760 hres
= pSHGetDesktopFolder(&folder
);
2761 ok(hres
== S_OK
, "SHGetDesktopFolder failed: 0x%08x\n", hres
);
2764 hres
= pSHIShellFolder_EnumObjects(folder
, NULL
, 0, &enm
);
2765 ok(hres
== S_OK
, "SHIShellFolder_EnumObjects failed: 0x%08x\n", hres
);
2766 ok(enm
!= NULL
, "Didn't get an enumerator\n");
2768 IEnumIDList_Release(enm
);
2770 IShellFolder_Release(folder
);
2773 static BOOL
write_inifile(LPCWSTR filename
)
2778 static const char data
[] =
2781 "AnotherKey=asdf\r\n";
2783 file
= CreateFileW(filename
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
2784 if(file
== INVALID_HANDLE_VALUE
) {
2785 win_skip("failed to create ini file at %s\n", wine_dbgstr_w(filename
));
2789 WriteFile(file
, data
, sizeof(data
), &written
, NULL
);
2796 #define verify_inifile(f, e) r_verify_inifile(__LINE__, f, e)
2797 static void r_verify_inifile(unsigned l
, LPCWSTR filename
, LPCSTR exp
)
2803 file
= CreateFileW(filename
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, 0, NULL
);
2805 if(file
== INVALID_HANDLE_VALUE
)
2808 ReadFile(file
, buf
, sizeof(buf
) * sizeof(CHAR
), &read
, NULL
);
2813 ok_(__FILE__
,l
)(!strcmp(buf
, exp
), "Expected:\n%s\nGot:\n%s\n", exp
,
2817 static void test_SHGetIniString(void)
2820 WCHAR out
[64] = {0};
2822 static const WCHAR TestAppW
[] = {'T','e','s','t','A','p','p',0};
2823 static const WCHAR AKeyW
[] = {'A','K','e','y',0};
2824 static const WCHAR AnotherKeyW
[] = {'A','n','o','t','h','e','r','K','e','y',0};
2825 static const WCHAR JunkKeyW
[] = {'J','u','n','k','K','e','y',0};
2826 static const WCHAR testpathW
[] = {'C',':','\\','t','e','s','t','.','i','n','i',0};
2827 WCHAR pathW
[MAX_PATH
];
2829 if(!pSHGetIniStringW
|| is_win2k_and_lower
){
2830 win_skip("SHGetIniStringW is not available\n");
2834 lstrcpyW(pathW
, testpathW
);
2836 if (!write_inifile(pathW
))
2840 /* these crash on Windows */
2841 pSHGetIniStringW(NULL
, NULL
, NULL
, 0, NULL
);
2842 pSHGetIniStringW(NULL
, AKeyW
, out
, sizeof(out
), pathW
);
2843 pSHGetIniStringW(TestAppW
, AKeyW
, NULL
, sizeof(out
), pathW
);
2846 ret
= pSHGetIniStringW(TestAppW
, AKeyW
, out
, 0, pathW
);
2847 ok(ret
== 0, "SHGetIniStringW should have given 0, instead: %d\n", ret
);
2849 /* valid arguments */
2851 SetLastError(0xdeadbeef);
2852 ret
= pSHGetIniStringW(TestAppW
, NULL
, out
, sizeof(out
), pathW
);
2853 ok(ret
== 4, "SHGetIniStringW should have given 4, instead: %d\n", ret
);
2854 ok(!lstrcmpW(out
, AKeyW
), "Expected %s, got: %s, %d\n",
2855 wine_dbgstr_w(AKeyW
), wine_dbgstr_w(out
), GetLastError());
2857 ret
= pSHGetIniStringW(TestAppW
, AKeyW
, out
, sizeof(out
), pathW
);
2858 ok(ret
== 1, "SHGetIniStringW should have given 1, instead: %d\n", ret
);
2859 ok(!strcmp_wa(out
, "1"), "Expected L\"1\", got: %s\n", wine_dbgstr_w(out
));
2861 ret
= pSHGetIniStringW(TestAppW
, AnotherKeyW
, out
, sizeof(out
), pathW
);
2862 ok(ret
== 4, "SHGetIniStringW should have given 4, instead: %d\n", ret
);
2863 ok(!strcmp_wa(out
, "asdf"), "Expected L\"asdf\", got: %s\n", wine_dbgstr_w(out
));
2866 ret
= pSHGetIniStringW(TestAppW
, JunkKeyW
, out
, sizeof(out
), pathW
);
2867 ok(ret
== 0, "SHGetIniStringW should have given 0, instead: %d\n", ret
);
2868 ok(*out
== 0, "Expected L\"\", got: %s\n", wine_dbgstr_w(out
));
2873 static void test_SHSetIniString(void)
2877 static const WCHAR TestAppW
[] = {'T','e','s','t','A','p','p',0};
2878 static const WCHAR AnotherAppW
[] = {'A','n','o','t','h','e','r','A','p','p',0};
2879 static const WCHAR TestIniW
[] = {'C',':','\\','t','e','s','t','.','i','n','i',0};
2880 static const WCHAR AKeyW
[] = {'A','K','e','y',0};
2881 static const WCHAR NewKeyW
[] = {'N','e','w','K','e','y',0};
2882 static const WCHAR AValueW
[] = {'A','V','a','l','u','e',0};
2884 if(!pSHSetIniStringW
|| is_win2k_and_lower
){
2885 win_skip("SHSetIniStringW is not available\n");
2889 if (!write_inifile(TestIniW
))
2892 ret
= pSHSetIniStringW(TestAppW
, AKeyW
, AValueW
, TestIniW
);
2893 ok(ret
== TRUE
, "SHSetIniStringW should not have failed\n");
2894 todo_wine
/* wine sticks an extra \r\n at the end of the file */
2895 verify_inifile(TestIniW
, "[TestApp]\r\nAKey=AValue\r\nAnotherKey=asdf\r\n");
2897 ret
= pSHSetIniStringW(TestAppW
, AKeyW
, NULL
, TestIniW
);
2898 ok(ret
== TRUE
, "SHSetIniStringW should not have failed\n");
2899 verify_inifile(TestIniW
, "[TestApp]\r\nAnotherKey=asdf\r\n");
2901 ret
= pSHSetIniStringW(AnotherAppW
, NewKeyW
, AValueW
, TestIniW
);
2902 ok(ret
== TRUE
, "SHSetIniStringW should not have failed\n");
2903 verify_inifile(TestIniW
, "[TestApp]\r\nAnotherKey=asdf\r\n[AnotherApp]\r\nNewKey=AValue\r\n");
2905 ret
= pSHSetIniStringW(TestAppW
, NULL
, AValueW
, TestIniW
);
2906 ok(ret
== TRUE
, "SHSetIniStringW should not have failed\n");
2907 verify_inifile(TestIniW
, "[AnotherApp]\r\nNewKey=AValue\r\n");
2909 DeleteFileW(TestIniW
);
2912 enum _shellkey_flags
{
2913 SHKEY_Root_HKCU
= 0x1,
2914 SHKEY_Root_HKLM
= 0x2,
2915 SHKEY_Key_Explorer
= 0x00,
2916 SHKEY_Key_Shell
= 0x10,
2917 SHKEY_Key_ShellNoRoam
= 0x20,
2918 SHKEY_Key_Classes
= 0x30,
2919 SHKEY_Subkey_Default
= 0x0000,
2920 SHKEY_Subkey_ResourceName
= 0x1000,
2921 SHKEY_Subkey_Handlers
= 0x2000,
2922 SHKEY_Subkey_Associations
= 0x3000,
2923 SHKEY_Subkey_Volatile
= 0x4000,
2924 SHKEY_Subkey_MUICache
= 0x5000,
2925 SHKEY_Subkey_FileExts
= 0x6000
2928 static void test_SHGetShellKey(void)
2930 static const WCHAR ShellFoldersW
[] = { 'S','h','e','l','l',' ','F','o','l','d','e','r','s',0 };
2931 static const WCHAR WineTestW
[] = { 'W','i','n','e','T','e','s','t',0 };
2933 void *pPathBuildRootW
= GetProcAddress(hShlwapi
, "PathBuildRootW");
2934 DWORD
*alloc_data
, data
, size
;
2938 if (!pSHGetShellKey
)
2940 win_skip("SHGetShellKey(ordinal 491) isn't available\n");
2945 if (pPathBuildRootW
&& pPathBuildRootW
== pSHGetShellKey
)
2947 win_skip("SHGetShellKey(ordinal 491) used for PathBuildRootW\n");
2951 if (is_win9x
|| is_win2k_and_lower
)
2953 win_skip("Ordinal 491 used for another call, skipping SHGetShellKey tests\n");
2957 /* Vista+ limits SHKEY enumeration values */
2958 SetLastError(0xdeadbeef);
2959 hkey
= pSHGetShellKey(SHKEY_Key_Explorer
, ShellFoldersW
, FALSE
);
2962 /* Tests not working on Vista+ */
2965 hkey
= pSHGetShellKey(SHKEY_Root_HKLM
|SHKEY_Key_Classes
, NULL
, FALSE
);
2966 ok(hkey
!= NULL
, "hkey = NULL\n");
2970 hkey
= pSHGetShellKey(SHKEY_Root_HKCU
|SHKEY_Key_Explorer
, ShellFoldersW
, FALSE
);
2971 ok(hkey
!= NULL
, "hkey = NULL\n");
2974 hkey
= pSHGetShellKey(SHKEY_Root_HKLM
|SHKEY_Key_Explorer
, ShellFoldersW
, FALSE
);
2975 ok(hkey
!= NULL
, "hkey = NULL\n");
2978 hkey
= pSHGetShellKey(SHKEY_Root_HKLM
, WineTestW
, FALSE
);
2979 ok(hkey
== NULL
, "hkey != NULL\n");
2981 hkey
= pSHGetShellKey(SHKEY_Root_HKLM
, NULL
, FALSE
);
2982 ok(hkey
!= NULL
, "Can't open key\n");
2983 ok(SUCCEEDED(RegDeleteKeyW(hkey
, WineTestW
)), "Can't delete key\n");
2986 hkey
= pSHGetShellKey(SHKEY_Root_HKLM
, WineTestW
, TRUE
);
2987 if (!hkey
&& GetLastError() == ERROR_ACCESS_DENIED
)
2989 skip("Not authorized to create keys\n");
2992 ok(hkey
!= NULL
, "Can't create key\n");
2995 if (!pSKGetValueW
|| !pSKSetValueW
|| !pSKDeleteValueW
|| !pSKAllocValueW
)
2997 win_skip("SKGetValueW, SKSetValueW, SKDeleteValueW or SKAllocValueW not available\n");
3001 size
= sizeof(data
);
3002 hres
= pSKGetValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
, NULL
, &data
, &size
);
3003 ok(hres
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), "hres = %x\n", hres
);
3006 hres
= pSKSetValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
, REG_DWORD
, &data
, sizeof(DWORD
));
3007 ok(hres
== S_OK
, "hres = %x\n", hres
);
3010 hres
= pSKGetValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
, NULL
, NULL
, &size
);
3011 ok(hres
== S_OK
, "hres = %x\n", hres
);
3012 ok(size
== sizeof(DWORD
), "size = %d\n", size
);
3015 hres
= pSKGetValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
, NULL
, &data
, &size
);
3016 ok(hres
== S_OK
, "hres = %x\n", hres
);
3017 ok(size
== sizeof(DWORD
), "size = %d\n", size
);
3018 ok(data
== 1234, "data = %d\n", data
);
3020 hres
= pSKAllocValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
, NULL
, (void**)&alloc_data
, &size
);
3021 ok(hres
== S_OK
, "hres= %x\n", hres
);
3022 ok(size
== sizeof(DWORD
), "size = %d\n", size
);
3023 if (SUCCEEDED(hres
))
3025 ok(*alloc_data
== 1234, "*alloc_data = %d\n", *alloc_data
);
3026 LocalFree(alloc_data
);
3029 hres
= pSKDeleteValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
);
3030 ok(hres
== S_OK
, "hres = %x\n", hres
);
3032 hres
= pSKDeleteValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
);
3033 ok(hres
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), "hres = %x\n", hres
);
3035 hres
= pSKGetValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
, NULL
, &data
, &size
);
3036 ok(hres
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), "hres = %x\n", hres
);
3038 hkey
= pSHGetShellKey(SHKEY_Root_HKLM
, NULL
, FALSE
);
3039 ok(hkey
!= NULL
, "Can't create key\n");
3040 ok(SUCCEEDED(RegDeleteKeyW(hkey
, WineTestW
)), "Can't delete key\n");
3044 static void init_pointers(void)
3046 #define MAKEFUNC(f, ord) (p##f = (void*)GetProcAddress(hShlwapi, (LPSTR)(ord)))
3047 MAKEFUNC(SHAllocShared
, 7);
3048 MAKEFUNC(SHLockShared
, 8);
3049 MAKEFUNC(SHUnlockShared
, 9);
3050 MAKEFUNC(SHFreeShared
, 10);
3051 MAKEFUNC(SHMapHandle
, 11);
3052 MAKEFUNC(GetAcceptLanguagesA
, 14);
3053 MAKEFUNC(SHSetWindowBits
, 165);
3054 MAKEFUNC(SHSetParentHwnd
, 167);
3055 MAKEFUNC(ConnectToConnectionPoint
, 168);
3056 MAKEFUNC(SHSearchMapInt
, 198);
3057 MAKEFUNC(SHCreateWorkerWindowA
, 257);
3058 MAKEFUNC(GUIDFromStringA
, 269);
3059 MAKEFUNC(SHPackDispParams
, 282);
3060 MAKEFUNC(IConnectionPoint_InvokeWithCancel
, 283);
3061 MAKEFUNC(IConnectionPoint_SimpleInvoke
, 284);
3062 MAKEFUNC(SHGetIniStringW
, 294);
3063 MAKEFUNC(SHSetIniStringW
, 295);
3064 MAKEFUNC(SHFormatDateTimeA
, 353);
3065 MAKEFUNC(SHFormatDateTimeW
, 354);
3066 MAKEFUNC(SHIShellFolder_EnumObjects
, 404);
3067 MAKEFUNC(SHGetObjectCompatFlags
, 476);
3068 MAKEFUNC(IUnknown_QueryServiceExec
, 484);
3069 MAKEFUNC(SHGetShellKey
, 491);
3070 MAKEFUNC(SHPropertyBag_ReadLONG
, 496);
3071 MAKEFUNC(IUnknown_ProfferService
, 514);
3072 MAKEFUNC(SKGetValueW
, 516);
3073 MAKEFUNC(SKSetValueW
, 517);
3074 MAKEFUNC(SKDeleteValueW
, 518);
3075 MAKEFUNC(SKAllocValueW
, 519);
3079 static void test_SHSetParentHwnd(void)
3081 HWND hwnd
, hwnd2
, ret
;
3084 if (!pSHSetParentHwnd
)
3086 win_skip("SHSetParentHwnd not available\n");
3090 hwnd
= CreateWindowA("Button", "", WS_VISIBLE
, 0, 0, 10, 10, NULL
, NULL
, NULL
, NULL
);
3091 ok(hwnd
!= NULL
, "got %p\n", hwnd
);
3093 hwnd2
= CreateWindowA("Button", "", WS_VISIBLE
| WS_CHILD
, 0, 0, 10, 10, hwnd
, NULL
, NULL
, NULL
);
3094 ok(hwnd2
!= NULL
, "got %p\n", hwnd2
);
3097 ret
= pSHSetParentHwnd(NULL
, NULL
);
3098 ok(ret
== NULL
, "got %p\n", ret
);
3100 /* set to no parent while already no parent present */
3101 ret
= GetParent(hwnd
);
3102 ok(ret
== NULL
, "got %p\n", ret
);
3103 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
3104 ok((style
& (WS_POPUP
|WS_CHILD
)) == 0, "got style 0x%08x\n", style
);
3105 ret
= pSHSetParentHwnd(hwnd
, NULL
);
3106 ok(ret
== NULL
, "got %p\n", ret
);
3107 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
3108 ok((style
& (WS_POPUP
|WS_CHILD
)) == 0, "got style 0x%08x\n", style
);
3110 /* reset to null parent from not null */
3111 ret
= GetParent(hwnd2
);
3112 ok(ret
== hwnd
, "got %p\n", ret
);
3113 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
3114 ok((style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
, "got style 0x%08x\n", style
);
3115 ret
= pSHSetParentHwnd(hwnd2
, NULL
);
3116 ok(ret
== NULL
, "got %p\n", ret
);
3117 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
3118 ok((style
& (WS_POPUP
|WS_CHILD
)) == WS_POPUP
, "got style 0x%08x\n", style
);
3119 ret
= GetParent(hwnd2
);
3120 ok(ret
== NULL
, "got %p\n", ret
);
3122 /* set parent back */
3123 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
3124 SetWindowLongA(hwnd2
, GWL_STYLE
, style
& ~(WS_CHILD
|WS_POPUP
));
3125 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
3126 ok((style
& (WS_CHILD
|WS_POPUP
)) == 0, "got 0x%08x\n", style
);
3128 ret
= pSHSetParentHwnd(hwnd2
, hwnd
);
3129 todo_wine
ok(ret
== NULL
, "got %p\n", ret
);
3131 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
3132 ok((style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
, "got style 0x%08x\n", style
);
3133 ret
= GetParent(hwnd2
);
3134 ok(ret
== hwnd
, "got %p\n", ret
);
3136 /* try to set same parent again */
3138 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
3139 SetWindowLongA(hwnd2
, GWL_STYLE
, style
| WS_POPUP
);
3140 ret
= pSHSetParentHwnd(hwnd2
, hwnd
);
3141 todo_wine
ok(ret
== NULL
, "got %p\n", ret
);
3142 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
3143 ok((style
& (WS_CHILD
|WS_POPUP
)) == WS_CHILD
, "got 0x%08x\n", style
);
3144 ret
= GetParent(hwnd2
);
3145 ok(ret
== hwnd
, "got %p\n", ret
);
3147 /* without WS_POPUP */
3148 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
3149 SetWindowLongA(hwnd2
, GWL_STYLE
, style
| ~WS_POPUP
);
3150 ret
= pSHSetParentHwnd(hwnd2
, hwnd
);
3151 todo_wine
ok(ret
== hwnd
, "got %p\n", ret
);
3152 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
3153 ok((style
& (WS_CHILD
|WS_POPUP
)) == WS_CHILD
, "got 0x%08x\n", style
);
3154 ret
= GetParent(hwnd2
);
3155 ok(ret
== hwnd
, "got %p\n", ret
);
3157 DestroyWindow(hwnd
);
3158 DestroyWindow(hwnd2
);
3166 hShlwapi
= GetModuleHandleA("shlwapi.dll");
3167 is_win2k_and_lower
= GetProcAddress(hShlwapi
, "StrChrNW") == 0;
3168 is_win9x
= GetProcAddress(hShlwapi
, (LPSTR
)99) == 0; /* StrCpyNXA */
3170 /* SHCreateStreamOnFileEx was introduced in shlwapi v6.0 */
3171 if(!GetProcAddress(hShlwapi
, "SHCreateStreamOnFileEx")){
3172 win_skip("Too old shlwapi version\n");
3178 argc
= winetest_get_mainargs(&argv
);
3183 sscanf(argv
[2], "%d", &procid
);
3184 sscanf(argv
[3], "%p", &hmem
);
3185 test_alloc_shared_remote(procid
, hmem
);
3189 hmlang
= LoadLibraryA("mlang.dll");
3190 pLcidToRfc1766A
= (void *)GetProcAddress(hmlang
, "LcidToRfc1766A");
3192 hshell32
= LoadLibraryA("shell32.dll");
3193 pSHGetDesktopFolder
= (void *)GetProcAddress(hshell32
, "SHGetDesktopFolder");
3195 test_GetAcceptLanguagesA();
3196 test_SHSearchMapInt();
3197 test_alloc_shared(argc
, argv
);
3199 test_GetShellSecurityDescriptor();
3200 test_SHPackDispParams();
3201 test_IConnectionPoint();
3202 test_SHPropertyBag_ReadLONG();
3203 test_SHSetWindowBits();
3204 test_SHFormatDateTimeA();
3205 test_SHFormatDateTimeW();
3206 test_SHGetObjectCompatFlags();
3207 test_IUnknown_QueryServiceExec();
3208 test_IUnknown_ProfferService();
3209 test_SHCreateWorkerWindowA();
3210 test_SHIShellFolder_EnumObjects();
3211 test_SHGetIniString();
3212 test_SHSetIniString();
3213 test_SHGetShellKey();
3214 test_SHSetParentHwnd();
3216 FreeLibrary(hshell32
);
3217 FreeLibrary(hmlang
);