1 /* Unit test suite for SHLWAPI ordinal functions
3 * Copyright 2004 Jon Griffiths
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "wine/test.h"
37 /* Function ptrs for ordinal calls */
38 static HMODULE hShlwapi
;
40 static int (WINAPI
*pSHSearchMapInt
)(const int*,const int*,int,int);
41 static HRESULT (WINAPI
*pGetAcceptLanguagesA
)(LPSTR
,LPDWORD
);
43 static HANDLE (WINAPI
*pSHAllocShared
)(LPCVOID
,DWORD
,DWORD
);
44 static LPVOID (WINAPI
*pSHLockShared
)(HANDLE
,DWORD
);
45 static BOOL (WINAPI
*pSHUnlockShared
)(LPVOID
);
46 static BOOL (WINAPI
*pSHFreeShared
)(HANDLE
,DWORD
);
47 static HANDLE (WINAPI
*pSHMapHandle
)(HANDLE
,DWORD
,DWORD
,DWORD
,DWORD
);
48 static HRESULT(WINAPIV
*pSHPackDispParams
)(DISPPARAMS
*,VARIANTARG
*,UINT
,...);
49 static HRESULT(WINAPI
*pIConnectionPoint_SimpleInvoke
)(IConnectionPoint
*,DISPID
,DISPPARAMS
*);
50 static HRESULT(WINAPI
*pIConnectionPoint_InvokeWithCancel
)(IConnectionPoint
*,DISPID
,DISPPARAMS
*,DWORD
,DWORD
);
51 static HRESULT(WINAPI
*pConnectToConnectionPoint
)(IUnknown
*,REFIID
,BOOL
,IUnknown
*, LPDWORD
,IConnectionPoint
**);
52 static HRESULT(WINAPI
*pSHPropertyBag_ReadLONG
)(IPropertyBag
*,LPCWSTR
,LPLONG
);
53 static LONG (WINAPI
*pSHSetWindowBits
)(HWND
, INT
, UINT
, UINT
);
54 static INT (WINAPI
*pSHFormatDateTimeA
)(const FILETIME UNALIGNED
*, DWORD
*, LPSTR
, UINT
);
55 static INT (WINAPI
*pSHFormatDateTimeW
)(const FILETIME UNALIGNED
*, DWORD
*, LPWSTR
, UINT
);
56 static DWORD (WINAPI
*pSHGetObjectCompatFlags
)(IUnknown
*, const CLSID
*);
57 static BOOL (WINAPI
*pGUIDFromStringA
)(LPSTR
, CLSID
*);
58 static HRESULT (WINAPI
*pIUnknown_QueryServiceExec
)(IUnknown
*, REFIID
, const GUID
*, DWORD
, DWORD
, VARIANT
*, VARIANT
*);
59 static HRESULT (WINAPI
*pIUnknown_ProfferService
)(IUnknown
*, REFGUID
, IServiceProvider
*, DWORD
*);
60 static HWND (WINAPI
*pSHCreateWorkerWindowA
)(LONG
, HWND
, DWORD
, DWORD
, HMENU
, LONG_PTR
);
61 static HRESULT (WINAPI
*pSHIShellFolder_EnumObjects
)(LPSHELLFOLDER
, HWND
, SHCONTF
, IEnumIDList
**);
62 static DWORD (WINAPI
*pSHGetIniStringW
)(LPCWSTR
, LPCWSTR
, LPWSTR
, DWORD
, LPCWSTR
);
63 static BOOL (WINAPI
*pSHSetIniStringW
)(LPCWSTR
, LPCWSTR
, LPCWSTR
, LPCWSTR
);
64 static HKEY (WINAPI
*pSHGetShellKey
)(DWORD
, LPCWSTR
, BOOL
);
65 static HRESULT (WINAPI
*pSKGetValueW
)(DWORD
, LPCWSTR
, LPCWSTR
, DWORD
*, void*, DWORD
*);
66 static HRESULT (WINAPI
*pSKSetValueW
)(DWORD
, LPCWSTR
, LPCWSTR
, DWORD
, void*, DWORD
);
67 static HRESULT (WINAPI
*pSKDeleteValueW
)(DWORD
, LPCWSTR
, LPCWSTR
);
68 static HRESULT (WINAPI
*pSKAllocValueW
)(DWORD
, LPCWSTR
, LPCWSTR
, DWORD
*, void**, DWORD
*);
69 static HWND (WINAPI
*pSHSetParentHwnd
)(HWND
, HWND
);
70 static HRESULT (WINAPI
*pIUnknown_GetClassID
)(IUnknown
*, CLSID
*);
71 static HRESULT (WINAPI
*pDllGetVersion
)(DLLVERSIONINFO2
*);
73 typedef struct SHELL_USER_SID
{
74 SID_IDENTIFIER_AUTHORITY sidAuthority
;
77 } SHELL_USER_SID
, *PSHELL_USER_SID
;
78 typedef struct SHELL_USER_PERMISSION
{
85 DWORD dwInheritAccessMask
;
86 } SHELL_USER_PERMISSION
, *PSHELL_USER_PERMISSION
;
88 static SECURITY_DESCRIPTOR
* (WINAPI
*pGetShellSecurityDescriptor
)(const SHELL_USER_PERMISSION
**,int);
90 static const CHAR ie_international
[] = {
91 'S','o','f','t','w','a','r','e','\\',
92 'M','i','c','r','o','s','o','f','t','\\',
93 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
94 'I','n','t','e','r','n','a','t','i','o','n','a','l',0};
95 static const CHAR acceptlanguage
[] = {
96 'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0};
109 static void init_call_trace(call_trace_t
*ctrace
)
113 ctrace
->calls
= HeapAlloc(GetProcessHeap(), 0, sizeof(call_entry_t
) * ctrace
->alloc
);
116 static void free_call_trace(const call_trace_t
*ctrace
)
118 HeapFree(GetProcessHeap(), 0, ctrace
->calls
);
121 static void add_call(call_trace_t
*ctrace
, int id
, const void *arg0
,
122 const void *arg1
, const void *arg2
, const void *arg3
, const void *arg4
)
133 if (ctrace
->count
== ctrace
->alloc
)
136 ctrace
->calls
= HeapReAlloc(GetProcessHeap(),0, ctrace
->calls
, ctrace
->alloc
*sizeof(call_entry_t
));
139 ctrace
->calls
[ctrace
->count
++] = call
;
142 static void ok_trace_(call_trace_t
*texpected
, call_trace_t
*tgot
, int line
)
144 if (texpected
->count
== tgot
->count
)
148 for (i
= 0; i
< texpected
->count
; i
++)
150 call_entry_t
*expected
= &texpected
->calls
[i
];
151 call_entry_t
*got
= &tgot
->calls
[i
];
154 ok_(__FILE__
, line
)(expected
->id
== got
->id
, "got different ids %d: %d, %d\n", i
+1, expected
->id
, got
->id
);
156 for (j
= 0; j
< 5; j
++)
158 ok_(__FILE__
, line
)(expected
->args
[j
] == got
->args
[j
], "got different args[%d] for %d: %p, %p\n", j
, i
+1,
159 expected
->args
[j
], got
->args
[j
]);
164 ok_(__FILE__
, line
)(0, "traces length mismatch\n");
167 #define ok_trace(a, b) ok_trace_(a, b, __LINE__)
169 /* trace of actually made calls */
170 static call_trace_t trace_got
;
172 static void test_GetAcceptLanguagesA(void)
174 static LPCSTR table
[] = {"de,en-gb;q=0.7,en;q=0.3",
175 "de,en;q=0.3,en-gb;q=0.7", /* sorting is ignored */
176 "winetest", /* content is ignored */
186 LONG res_query
= ERROR_SUCCESS
;
189 DWORD maxlen
= sizeof(buffer
) - 2;
195 lcid
= GetUserDefaultLCID();
197 /* Get the original Value */
198 lres
= RegOpenKeyA(HKEY_CURRENT_USER
, ie_international
, &hroot
);
200 skip("RegOpenKey(%s) failed: %ld\n", ie_international
, lres
);
203 len
= sizeof(original
);
205 res_query
= RegQueryValueExA(hroot
, acceptlanguage
, 0, NULL
, (PBYTE
)original
, &len
);
207 RegDeleteValueA(hroot
, acceptlanguage
);
209 /* Some windows versions use "lang-COUNTRY" as default */
210 memset(language
, 0, sizeof(language
));
211 len
= GetLocaleInfoA(lcid
, LOCALE_SISO639LANGNAME
, language
, sizeof(language
));
214 lstrcatA(language
, "-");
215 memset(buffer
, 0, sizeof(buffer
));
216 len
= GetLocaleInfoA(lcid
, LOCALE_SISO3166CTRYNAME
, buffer
, sizeof(buffer
) - len
- 1);
217 lstrcatA(language
, buffer
);
221 /* LOCALE_SNAME has additional parts in some languages. Try only as last chance */
222 memset(language
, 0, sizeof(language
));
223 len
= GetLocaleInfoA(lcid
, LOCALE_SNAME
, language
, sizeof(language
));
226 /* get the default value */
228 memset(buffer
, '#', maxlen
);
230 hr
= pGetAcceptLanguagesA( buffer
, &len
);
233 win_skip("GetAcceptLanguagesA failed with 0x%lx\n", hr
);
234 goto restore_original
;
237 if (lstrcmpA(buffer
, language
)) {
238 /* some windows versions use "lang" or "lang-country" as default */
240 hr
= LcidToRfc1766A(lcid
, language
, sizeof(language
));
241 ok(hr
== S_OK
, "LcidToRfc1766A returned 0x%lx and %s\n", hr
, language
);
244 ok(!lstrcmpA(buffer
, language
),
245 "have '%s' (searching for '%s')\n", language
, buffer
);
247 if (lstrcmpA(buffer
, language
)) {
248 win_skip("no more ideas, how to build the default language '%s'\n", buffer
);
249 goto restore_original
;
252 trace("detected default: %s\n", language
);
253 while ((entry
= table
[i
])) {
255 exactsize
= lstrlenA(entry
);
257 lres
= RegSetValueExA(hroot
, acceptlanguage
, 0, REG_SZ
, (const BYTE
*) entry
, exactsize
+ 1);
258 ok(!lres
, "got %ld for RegSetValueExA: %s\n", lres
, entry
);
260 /* len includes space for the terminating 0 before vista/w2k8 */
262 memset(buffer
, '#', maxlen
);
264 hr
= pGetAcceptLanguagesA( buffer
, &len
);
265 ok(((hr
== E_INVALIDARG
) && (len
== 0)) ||
267 ((len
== exactsize
) || (len
== exactsize
+1)) &&
268 !lstrcmpA(buffer
, entry
)),
269 "+2_#%d: got 0x%lx with %ld and %s\n", i
, hr
, len
, buffer
);
272 memset(buffer
, '#', maxlen
);
274 hr
= pGetAcceptLanguagesA( buffer
, &len
);
275 ok(((hr
== E_INVALIDARG
) && (len
== 0)) ||
277 ((len
== exactsize
) || (len
== exactsize
+1)) &&
278 !lstrcmpA(buffer
, entry
)),
279 "+1_#%d: got 0x%lx with %ld and %s\n", i
, hr
, len
, buffer
);
282 memset(buffer
, '#', maxlen
);
284 hr
= pGetAcceptLanguagesA( buffer
, &len
);
286 /* There is no space for the string in the registry.
287 When the buffer is large enough, the default language is returned
289 When the buffer is too small for that fallback, win7_32 and w2k8_64
290 fail with E_NOT_SUFFICIENT_BUFFER, win8 fails with HRESULT_FROM_WIN32(ERROR_MORE_DATA),
291 other versions succeed and return a partial result while older os succeed
292 and overflow the buffer */
294 ok(((hr
== E_INVALIDARG
) && (len
== 0)) ||
295 (((hr
== S_OK
) && !lstrcmpA(buffer
, language
) && (len
== lstrlenA(language
))) ||
296 ((hr
== S_OK
) && !memcmp(buffer
, language
, len
)) ||
297 ((hr
== E_NOT_SUFFICIENT_BUFFER
) && !len
) ||
298 ((hr
== __HRESULT_FROM_WIN32(ERROR_MORE_DATA
)) && len
== exactsize
)),
299 "==_#%d: got 0x%lx with %ld and %s\n", i
, hr
, len
, buffer
);
303 memset(buffer
, '#', maxlen
);
305 hr
= pGetAcceptLanguagesA( buffer
, &len
);
306 ok(((hr
== E_INVALIDARG
) && (len
== 0)) ||
307 (((hr
== S_OK
) && !lstrcmpA(buffer
, language
) && (len
== lstrlenA(language
))) ||
308 ((hr
== S_OK
) && !memcmp(buffer
, language
, len
)) ||
309 ((hr
== E_NOT_SUFFICIENT_BUFFER
) && !len
) ||
310 ((hr
== __HRESULT_FROM_WIN32(ERROR_MORE_DATA
)) && len
== exactsize
- 1)),
311 "-1_#%d: got 0x%lx with %ld and %s\n", i
, hr
, len
, buffer
);
315 memset(buffer
, '#', maxlen
);
317 hr
= pGetAcceptLanguagesA( buffer
, &len
);
318 ok(((hr
== E_INVALIDARG
) && (len
== 0)) ||
319 (((hr
== S_OK
) && !lstrcmpA(buffer
, language
) && (len
== lstrlenA(language
))) ||
320 ((hr
== S_OK
) && !memcmp(buffer
, language
, len
)) ||
321 ((hr
== E_NOT_SUFFICIENT_BUFFER
) && !len
) ||
322 ((hr
== __HRESULT_FROM_WIN32(ERROR_MORE_DATA
)) && len
== 1)),
323 "=1_#%d: got 0x%lx with %ld and %s\n", i
, hr
, len
, buffer
);
326 hr
= pGetAcceptLanguagesA( NULL
, &len
);
328 /* w2k3 and below: E_FAIL and untouched len,
329 since w2k8: S_OK and needed size (excluding 0), win8 S_OK and size including 0. */
330 ok( ((hr
== S_OK
) && ((len
== exactsize
) || (len
== exactsize
+ 1))) ||
331 ((hr
== E_FAIL
) && (len
== maxlen
)),
332 "NULL,max #%d: got 0x%lx with %ld and %s\n", i
, hr
, len
, buffer
);
337 /* without a value in the registry, a default language is returned */
338 RegDeleteValueA(hroot
, acceptlanguage
);
341 memset(buffer
, '#', maxlen
);
343 hr
= pGetAcceptLanguagesA( buffer
, &len
);
344 ok( ((hr
== S_OK
) && (len
== lstrlenA(language
))),
345 "max: got 0x%lx with %ld and %s (expected S_OK with %d and '%s'\n",
346 hr
, len
, buffer
, lstrlenA(language
), language
);
349 memset(buffer
, '#', maxlen
);
351 hr
= pGetAcceptLanguagesA( buffer
, &len
);
352 ok( (((hr
== S_OK
) || (hr
== E_INVALIDARG
)) && !memcmp(buffer
, language
, len
)) ||
353 ((hr
== E_NOT_SUFFICIENT_BUFFER
) && !len
) ||
354 ((hr
== __HRESULT_FROM_WIN32(ERROR_CANNOT_COPY
)) && !len
),
355 "=2: got 0x%lx with %ld and %s\n", hr
, len
, buffer
);
358 memset(buffer
, '#', maxlen
);
360 hr
= pGetAcceptLanguagesA( buffer
, &len
);
361 /* When the buffer is too small, win7_32 and w2k8_64 and above fail with
362 E_NOT_SUFFICIENT_BUFFER, win8 ERROR_CANNOT_COPY,
363 other versions succeed and return a partial 0 terminated result while other versions
364 fail with E_INVALIDARG and return a partial unterminated result */
365 ok( (((hr
== S_OK
) || (hr
== E_INVALIDARG
)) && !memcmp(buffer
, language
, len
)) ||
366 ((hr
== E_NOT_SUFFICIENT_BUFFER
) && !len
) ||
367 ((hr
== __HRESULT_FROM_WIN32(ERROR_CANNOT_COPY
)) && !len
),
368 "=1: got 0x%lx with %ld and %s\n", hr
, len
, buffer
);
371 memset(buffer
, '#', maxlen
);
373 hr
= pGetAcceptLanguagesA( buffer
, &len
);
374 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG, win8 ERROR_CANNOT_COPY */
375 ok((hr
== E_FAIL
) || (hr
== E_INVALIDARG
) || (hr
== __HRESULT_FROM_WIN32(ERROR_CANNOT_COPY
)),
378 memset(buffer
, '#', maxlen
);
380 hr
= pGetAcceptLanguagesA( buffer
, NULL
);
381 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
382 ok((hr
== E_FAIL
) || (hr
== E_INVALIDARG
),
383 "got 0x%lx (expected E_FAIL or E_INVALIDARG)\n", hr
);
386 hr
= pGetAcceptLanguagesA( NULL
, NULL
);
387 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
388 ok((hr
== E_FAIL
) || (hr
== E_INVALIDARG
),
389 "got 0x%lx (expected E_FAIL or E_INVALIDARG)\n", hr
);
393 len
= lstrlenA(original
);
394 lres
= RegSetValueExA(hroot
, acceptlanguage
, 0, REG_SZ
, (const BYTE
*) original
, len
? len
+ 1: 0);
395 ok(!lres
, "RegSetValueEx(%s) failed: %ld\n", original
, lres
);
399 RegDeleteValueA(hroot
, acceptlanguage
);
404 static void test_SHSearchMapInt(void)
406 int keys
[8], values
[8];
409 if (!pSHSearchMapInt
)
412 memset(keys
, 0, sizeof(keys
));
413 memset(values
, 0, sizeof(values
));
414 keys
[0] = 99; values
[0] = 101;
416 /* NULL key/value lists crash native, so skip testing them */
419 i
= pSHSearchMapInt(keys
, values
, 1, keys
[0]);
420 ok(i
== values
[0], "Len 1, expected %d, got %d\n", values
[0], i
);
422 /* Key doesn't exist */
423 i
= pSHSearchMapInt(keys
, values
, 1, 100);
424 ok(i
== -1, "Len 1 - bad key, expected -1, got %d\n", i
);
426 /* Len = 0 => not found */
427 i
= pSHSearchMapInt(keys
, values
, 0, keys
[0]);
428 ok(i
== -1, "Len 1 - passed len 0, expected -1, got %d\n", i
);
430 /* 2 elements, len = 1 */
431 keys
[1] = 98; values
[1] = 102;
432 i
= pSHSearchMapInt(keys
, values
, 1, keys
[1]);
433 ok(i
== -1, "Len 1 - array len 2, expected -1, got %d\n", i
);
435 /* 2 elements, len = 2 */
436 i
= pSHSearchMapInt(keys
, values
, 2, keys
[1]);
437 ok(i
== values
[1], "Len 2, expected %d, got %d\n", values
[1], i
);
439 /* Searches forward */
440 keys
[2] = 99; values
[2] = 103;
441 i
= pSHSearchMapInt(keys
, values
, 3, keys
[0]);
442 ok(i
== values
[0], "Len 3, expected %d, got %d\n", values
[0], i
);
451 static void test_alloc_shared(int argc
, char **argv
)
453 char cmdline
[MAX_PATH
];
454 PROCESS_INFORMATION pi
;
455 STARTUPINFOA si
= { 0 };
457 HANDLE hmem
, hmem2
= 0;
458 struct shared_struct val
, *p
;
461 procid
=GetCurrentProcessId();
462 hmem
=pSHAllocShared(NULL
,10,procid
);
463 ok(hmem
!=NULL
,"SHAllocShared(NULL...) failed: %lu\n", GetLastError());
464 ret
= pSHFreeShared(hmem
, procid
);
465 ok( ret
, "SHFreeShared failed: %lu\n", GetLastError());
467 val
.value
= 0x12345678;
469 hmem
= pSHAllocShared(&val
, sizeof(val
), procid
);
470 ok(hmem
!=NULL
,"SHAllocShared(NULL...) failed: %lu\n", GetLastError());
472 p
=pSHLockShared(hmem
,procid
);
473 ok(p
!=NULL
,"SHLockShared failed: %lu\n", GetLastError());
475 ok(p
->value
== 0x12345678, "Wrong value in shared memory: %ld instead of %d\n", p
->value
, 0x12345678);
476 ret
= pSHUnlockShared(p
);
477 ok( ret
, "SHUnlockShared failed: %lu\n", GetLastError());
479 sprintf(cmdline
, "%s %s %ld %p", argv
[0], argv
[1], procid
, hmem
);
480 ret
= CreateProcessA(NULL
, cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
481 ok(ret
, "could not create child process error: %lu\n", GetLastError());
484 wait_child_process(pi
.hProcess
);
485 CloseHandle(pi
.hThread
);
486 CloseHandle(pi
.hProcess
);
488 p
= pSHLockShared(hmem
, procid
);
489 ok(p
!= NULL
,"SHLockShared failed: %lu\n", GetLastError());
490 if (p
!= NULL
&& p
->value
!= 0x12345678)
492 ok(p
->value
== 0x12345679, "Wrong value in shared memory: %ld instead of %d\n", p
->value
, 0x12345679);
494 ok(hmem2
!= NULL
, "Expected handle in shared memory\n");
496 ret
= pSHUnlockShared(p
);
497 ok(ret
, "SHUnlockShared failed: %lu\n", GetLastError());
500 ret
= pSHFreeShared(hmem
, procid
);
501 ok( ret
, "SHFreeShared failed: %lu\n", GetLastError());
505 p
= pSHLockShared(hmem2
, procid
);
506 ok(p
!= NULL
,"SHLockShared failed: %lu\n", GetLastError());
508 ok(p
->value
== 0xDEADBEEF, "Wrong value in shared memory: %ld instead of %d\n", p
->value
, 0xDEADBEEF);
509 ret
= pSHUnlockShared(p
);
510 ok(ret
, "SHUnlockShared failed: %lu\n", GetLastError());
512 ret
= pSHFreeShared(hmem2
, procid
);
513 ok(ret
, "SHFreeShared failed: %lu\n", GetLastError());
516 SetLastError(0xdeadbeef);
517 ret
= pSHFreeShared(NULL
, procid
);
518 ok(ret
, "SHFreeShared failed: %lu\n", GetLastError());
519 ok(GetLastError() == 0xdeadbeef, "last error should not have changed, got %lu\n", GetLastError());
522 static void test_alloc_shared_remote(DWORD procid
, HANDLE hmem
)
524 struct shared_struct val
, *p
;
528 /* test directly accessing shared memory of a remote process */
529 p
= pSHLockShared(hmem
, procid
);
530 ok(p
!= NULL
|| broken(p
== NULL
) /* Windows 7/8 */, "SHLockShared failed: %lu\n", GetLastError());
533 win_skip("Subprocess failed to modify shared memory, skipping test\n");
537 ok(p
->value
== 0x12345678, "Wrong value in shared memory: %ld instead of %d\n", p
->value
, 0x12345678);
540 val
.value
= 0xDEADBEEF;
542 p
->handle
= pSHAllocShared(&val
, sizeof(val
), procid
);
543 ok(p
->handle
!= NULL
, "SHAllocShared failed: %lu\n", GetLastError());
545 ret
= pSHUnlockShared(p
);
546 ok(ret
, "SHUnlockShared failed: %lu\n", GetLastError());
548 /* test SHMapHandle */
549 SetLastError(0xdeadbeef);
550 hmem2
= pSHMapHandle(NULL
, procid
, GetCurrentProcessId(), 0, 0);
551 ok(hmem2
== NULL
, "expected NULL, got new handle\n");
552 ok(GetLastError() == 0xdeadbeef, "last error should not have changed, got %lu\n", GetLastError());
554 hmem2
= pSHMapHandle(hmem
, procid
, GetCurrentProcessId(), 0, 0);
556 /* It seems like Windows Vista/2008 uses a different internal implementation
557 * for shared memory, and calling SHMapHandle fails. */
558 ok(hmem2
!= NULL
|| broken(hmem2
== NULL
),
559 "SHMapHandle failed: %lu\n", GetLastError());
562 win_skip("Subprocess failed to map shared memory, skipping test\n");
566 p
= pSHLockShared(hmem2
, GetCurrentProcessId());
567 ok(p
!= NULL
, "SHLockShared failed: %lu\n", GetLastError());
570 ok(p
->value
== 0x12345679, "Wrong value in shared memory: %ld instead of %d\n", p
->value
, 0x12345679);
572 ret
= pSHUnlockShared(p
);
573 ok(ret
, "SHUnlockShared failed: %lu\n", GetLastError());
575 ret
= pSHFreeShared(hmem2
, GetCurrentProcessId());
576 ok(ret
, "SHFreeShared failed: %lu\n", GetLastError());
579 static void test_fdsa(void)
583 DWORD num_items
; /* Number of elements inserted */
584 void *mem
; /* Ptr to array */
585 DWORD blocks_alloced
; /* Number of elements allocated */
586 BYTE inc
; /* Number of elements to grow by when we need to expand */
587 BYTE block_size
; /* Size in bytes of an element */
588 BYTE flags
; /* Flags */
591 BOOL (WINAPI
*pFDSA_Initialize
)(DWORD block_size
, DWORD inc
, FDSA_info
*info
, void *mem
,
593 BOOL (WINAPI
*pFDSA_Destroy
)(FDSA_info
*info
);
594 DWORD (WINAPI
*pFDSA_InsertItem
)(FDSA_info
*info
, DWORD where
, const void *block
);
595 BOOL (WINAPI
*pFDSA_DeleteItem
)(FDSA_info
*info
, DWORD where
);
598 int block_size
= 10, init_blocks
= 4, inc
= 2;
602 pFDSA_Initialize
= (void *)GetProcAddress(hShlwapi
, (LPSTR
)208);
603 pFDSA_Destroy
= (void *)GetProcAddress(hShlwapi
, (LPSTR
)209);
604 pFDSA_InsertItem
= (void *)GetProcAddress(hShlwapi
, (LPSTR
)210);
605 pFDSA_DeleteItem
= (void *)GetProcAddress(hShlwapi
, (LPSTR
)211);
607 mem
= HeapAlloc(GetProcessHeap(), 0, block_size
* init_blocks
);
608 memset(&info
, 0, sizeof(info
));
610 ok(pFDSA_Initialize(block_size
, inc
, &info
, mem
, init_blocks
), "FDSA_Initialize rets FALSE\n");
611 ok(info
.num_items
== 0, "num_items = %ld\n", info
.num_items
);
612 ok(info
.mem
== mem
, "mem = %p\n", info
.mem
);
613 ok(info
.blocks_alloced
== init_blocks
, "blocks_alloced = %ld\n", info
.blocks_alloced
);
614 ok(info
.inc
== inc
, "inc = %d\n", info
.inc
);
615 ok(info
.block_size
== block_size
, "block_size = %d\n", info
.block_size
);
616 ok(info
.flags
== 0, "flags = %d\n", info
.flags
);
618 ret
= pFDSA_InsertItem(&info
, 1234, "1234567890");
619 ok(ret
== 0, "ret = %ld\n", ret
);
620 ok(info
.num_items
== 1, "num_items = %ld\n", info
.num_items
);
621 ok(info
.mem
== mem
, "mem = %p\n", info
.mem
);
622 ok(info
.blocks_alloced
== init_blocks
, "blocks_alloced = %ld\n", info
.blocks_alloced
);
623 ok(info
.inc
== inc
, "inc = %d\n", info
.inc
);
624 ok(info
.block_size
== block_size
, "block_size = %d\n", info
.block_size
);
625 ok(info
.flags
== 0, "flags = %d\n", info
.flags
);
627 ret
= pFDSA_InsertItem(&info
, 1234, "abcdefghij");
628 ok(ret
== 1, "ret = %ld\n", ret
);
630 ret
= pFDSA_InsertItem(&info
, 1, "klmnopqrst");
631 ok(ret
== 1, "ret = %ld\n", ret
);
633 ret
= pFDSA_InsertItem(&info
, 0, "uvwxyzABCD");
634 ok(ret
== 0, "ret = %ld\n", ret
);
635 ok(info
.mem
== mem
, "mem = %p\n", info
.mem
);
636 ok(info
.flags
== 0, "flags = %d\n", info
.flags
);
638 /* This next InsertItem will cause shlwapi to allocate its own mem buffer */
639 ret
= pFDSA_InsertItem(&info
, 0, "EFGHIJKLMN");
640 ok(ret
== 0, "ret = %ld\n", ret
);
641 ok(info
.mem
!= mem
, "mem = %p\n", info
.mem
);
642 ok(info
.blocks_alloced
== init_blocks
+ inc
, "blocks_alloced = %ld\n", info
.blocks_alloced
);
643 ok(info
.flags
== 0x1, "flags = %d\n", info
.flags
);
645 ok(!memcmp(info
.mem
, "EFGHIJKLMNuvwxyzABCD1234567890klmnopqrstabcdefghij", 50), "mem %s\n", (char*)info
.mem
);
647 ok(pFDSA_DeleteItem(&info
, 2), "rets FALSE\n");
648 ok(info
.mem
!= mem
, "mem = %p\n", info
.mem
);
649 ok(info
.blocks_alloced
== init_blocks
+ inc
, "blocks_alloced = %ld\n", info
.blocks_alloced
);
650 ok(info
.flags
== 0x1, "flags = %d\n", info
.flags
);
652 ok(!memcmp(info
.mem
, "EFGHIJKLMNuvwxyzABCDklmnopqrstabcdefghij", 40), "mem %s\n", (char*)info
.mem
);
654 ok(pFDSA_DeleteItem(&info
, 3), "rets FALSE\n");
655 ok(info
.mem
!= mem
, "mem = %p\n", info
.mem
);
656 ok(info
.blocks_alloced
== init_blocks
+ inc
, "blocks_alloced = %ld\n", info
.blocks_alloced
);
657 ok(info
.flags
== 0x1, "flags = %d\n", info
.flags
);
659 ok(!memcmp(info
.mem
, "EFGHIJKLMNuvwxyzABCDklmnopqrst", 30), "mem %s\n", (char*)info
.mem
);
661 ok(!pFDSA_DeleteItem(&info
, 4), "does not ret FALSE\n");
663 /* As shlwapi has allocated memory internally, Destroy will ret FALSE */
664 ok(!pFDSA_Destroy(&info
), "FDSA_Destroy does not ret FALSE\n");
667 /* When Initialize is called with inc = 0, set it to 1 */
668 ok(pFDSA_Initialize(block_size
, 0, &info
, mem
, init_blocks
), "FDSA_Initialize rets FALSE\n");
669 ok(info
.inc
== 1, "inc = %d\n", info
.inc
);
671 /* This time, because shlwapi hasn't had to allocate memory
672 internally, Destroy rets non-zero */
673 ok(pFDSA_Destroy(&info
), "FDSA_Destroy rets FALSE\n");
676 HeapFree(GetProcessHeap(), 0, mem
);
679 static void test_GetShellSecurityDescriptor(void)
681 static const SHELL_USER_PERMISSION supCurrentUserFull
= {
682 { {SECURITY_NULL_SID_AUTHORITY
}, 0, 0 },
683 ACCESS_ALLOWED_ACE_TYPE
, FALSE
,
685 #define MY_INHERITANCE 0xBE /* invalid value to proof behavior */
686 static const SHELL_USER_PERMISSION supEveryoneDenied
= {
687 { {SECURITY_WORLD_SID_AUTHORITY
}, SECURITY_WORLD_RID
, 0 },
688 ACCESS_DENIED_ACE_TYPE
, TRUE
,
689 GENERIC_WRITE
, MY_INHERITANCE
| 0xDEADBA00, GENERIC_READ
};
690 const SHELL_USER_PERMISSION
* rgsup
[2] = {
691 &supCurrentUserFull
, &supEveryoneDenied
,
693 SECURITY_DESCRIPTOR
* psd
;
695 if(!pGetShellSecurityDescriptor
) /* vista and later */
697 win_skip("GetShellSecurityDescriptor not available\n");
701 psd
= pGetShellSecurityDescriptor(NULL
, 2);
702 ok(psd
==NULL
, "GetShellSecurityDescriptor should fail\n");
703 psd
= pGetShellSecurityDescriptor(rgsup
, 0);
704 ok(psd
==NULL
, "GetShellSecurityDescriptor should fail, got %p\n", psd
);
706 SetLastError(0xdeadbeef);
707 psd
= pGetShellSecurityDescriptor(rgsup
, 2);
708 ok(psd
!=NULL
, "GetShellSecurityDescriptor failed\n");
711 BOOL bHasDacl
= FALSE
, bDefaulted
, ret
;
714 SECURITY_DESCRIPTOR_CONTROL control
;
716 ok(IsValidSecurityDescriptor(psd
), "returned value is not valid SD\n");
718 ret
= GetSecurityDescriptorControl(psd
, &control
, &dwRev
);
719 ok(ret
, "GetSecurityDescriptorControl failed with error %lu\n", GetLastError());
720 ok(0 == (control
& SE_SELF_RELATIVE
), "SD should be absolute\n");
722 ret
= GetSecurityDescriptorDacl(psd
, &bHasDacl
, &pAcl
, &bDefaulted
);
723 ok(ret
, "GetSecurityDescriptorDacl failed with error %lu\n", GetLastError());
725 ok(bHasDacl
, "SD has no DACL\n");
728 ok(!bDefaulted
, "DACL should not be defaulted\n");
730 ok(pAcl
!= NULL
, "NULL DACL!\n");
733 ACL_SIZE_INFORMATION asiSize
;
735 ok(IsValidAcl(pAcl
), "DACL is not valid\n");
737 ret
= GetAclInformation(pAcl
, &asiSize
, sizeof(asiSize
), AclSizeInformation
);
738 ok(ret
, "GetAclInformation failed with error %lu\n", GetLastError());
740 ok(asiSize
.AceCount
== 3, "Incorrect number of ACEs: %ld entries\n", asiSize
.AceCount
);
741 if (asiSize
.AceCount
== 3)
743 ACCESS_ALLOWED_ACE
*paaa
; /* will use for DENIED too */
745 ret
= GetAce(pAcl
, 0, (LPVOID
*)&paaa
);
746 ok(ret
, "GetAce failed with error %lu\n", GetLastError());
747 ok(paaa
->Header
.AceType
== ACCESS_ALLOWED_ACE_TYPE
,
748 "Invalid ACE type %d\n", paaa
->Header
.AceType
);
749 ok(paaa
->Header
.AceFlags
== 0, "Invalid ACE flags %x\n", paaa
->Header
.AceFlags
);
750 ok(paaa
->Mask
== GENERIC_ALL
, "Invalid ACE mask %lx\n", paaa
->Mask
);
752 ret
= GetAce(pAcl
, 1, (LPVOID
*)&paaa
);
753 ok(ret
, "GetAce failed with error %lu\n", GetLastError());
754 ok(paaa
->Header
.AceType
== ACCESS_DENIED_ACE_TYPE
,
755 "Invalid ACE type %d\n", paaa
->Header
.AceType
);
756 /* first one of two ACEs generated from inheritable entry - without inheritance */
757 ok(paaa
->Header
.AceFlags
== 0, "Invalid ACE flags %x\n", paaa
->Header
.AceFlags
);
758 ok(paaa
->Mask
== GENERIC_WRITE
, "Invalid ACE mask %lx\n", paaa
->Mask
);
760 ret
= GetAce(pAcl
, 2, (LPVOID
*)&paaa
);
761 ok(ret
, "GetAce failed with error %lu\n", GetLastError());
762 ok(paaa
->Header
.AceType
== ACCESS_DENIED_ACE_TYPE
,
763 "Invalid ACE type %d\n", paaa
->Header
.AceType
);
764 /* second ACE - with inheritance */
765 ok(paaa
->Header
.AceFlags
== MY_INHERITANCE
,
766 "Invalid ACE flags %x\n", paaa
->Header
.AceFlags
);
767 ok(paaa
->Mask
== GENERIC_READ
, "Invalid ACE mask %lx\n", paaa
->Mask
);
776 static void test_SHPackDispParams(void)
782 memset(¶ms
, 0xc0, sizeof(params
));
783 memset(vars
, 0xc0, sizeof(vars
));
784 hres
= pSHPackDispParams(¶ms
, vars
, 1, VT_I4
, 0xdeadbeef);
785 ok(hres
== S_OK
, "SHPackDispParams failed: %08lx\n", hres
);
786 ok(params
.cArgs
== 1, "params.cArgs = %d\n", params
.cArgs
);
787 ok(params
.cNamedArgs
== 0, "params.cNamedArgs = %d\n", params
.cArgs
);
788 ok(params
.rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", params
.rgdispidNamedArgs
);
789 ok(params
.rgvarg
== vars
, "params.rgvarg = %p\n", params
.rgvarg
);
790 ok(V_VT(vars
) == VT_I4
, "V_VT(var) = %d\n", V_VT(vars
));
791 ok(V_I4(vars
) == 0xdeadbeef, "failed %lx\n", V_I4(vars
));
793 memset(¶ms
, 0xc0, sizeof(params
));
794 hres
= pSHPackDispParams(¶ms
, NULL
, 0, 0);
795 ok(hres
== S_OK
, "SHPackDispParams failed: %08lx\n", hres
);
796 ok(params
.cArgs
== 0, "params.cArgs = %d\n", params
.cArgs
);
797 ok(params
.cNamedArgs
== 0, "params.cNamedArgs = %d\n", params
.cArgs
);
798 ok(params
.rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", params
.rgdispidNamedArgs
);
799 ok(params
.rgvarg
== NULL
, "params.rgvarg = %p\n", params
.rgvarg
);
801 memset(vars
, 0xc0, sizeof(vars
));
802 memset(¶ms
, 0xc0, sizeof(params
));
803 hres
= pSHPackDispParams(¶ms
, vars
, 4, VT_BSTR
, (void*)0xdeadbeef, VT_EMPTY
, 10,
804 VT_I4
, 100, VT_DISPATCH
, (void*)0xdeadbeef);
805 ok(hres
== S_OK
, "SHPackDispParams failed: %08lx\n", hres
);
806 ok(params
.cArgs
== 4, "params.cArgs = %d\n", params
.cArgs
);
807 ok(params
.cNamedArgs
== 0, "params.cNamedArgs = %d\n", params
.cArgs
);
808 ok(params
.rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", params
.rgdispidNamedArgs
);
809 ok(params
.rgvarg
== vars
, "params.rgvarg = %p\n", params
.rgvarg
);
810 ok(V_VT(vars
) == VT_DISPATCH
, "V_VT(vars[0]) = %x\n", V_VT(vars
));
811 ok(V_I4(vars
) == 0xdeadbeef, "V_I4(vars[0]) = %lx\n", V_I4(vars
));
812 ok(V_VT(vars
+1) == VT_I4
, "V_VT(vars[1]) = %d\n", V_VT(vars
+1));
813 ok(V_I4(vars
+1) == 100, "V_I4(vars[1]) = %lx\n", V_I4(vars
+1));
814 ok(V_VT(vars
+2) == VT_I4
, "V_VT(vars[2]) = %d\n", V_VT(vars
+2));
815 ok(V_I4(vars
+2) == 10, "V_I4(vars[2]) = %lx\n", V_I4(vars
+2));
816 ok(V_VT(vars
+3) == VT_BSTR
, "V_VT(vars[3]) = %d\n", V_VT(vars
+3));
817 ok(V_BSTR(vars
+3) == (void*)0xdeadbeef, "V_BSTR(vars[3]) = %p\n", V_BSTR(vars
+3));
822 IDispatch IDispatch_iface
;
826 static inline Disp
*impl_from_IDispatch(IDispatch
*iface
)
828 return CONTAINING_RECORD(iface
, Disp
, IDispatch_iface
);
831 typedef struct _contain
833 IConnectionPointContainer IConnectionPointContainer_iface
;
837 IConnectionPoint
**pt
;
840 static inline Contain
*impl_from_IConnectionPointContainer(IConnectionPointContainer
*iface
)
842 return CONTAINING_RECORD(iface
, Contain
, IConnectionPointContainer_iface
);
845 typedef struct _cntptn
847 IConnectionPoint IConnectionPoint_iface
;
856 static inline ConPt
*impl_from_IConnectionPoint(IConnectionPoint
*iface
)
858 return CONTAINING_RECORD(iface
, ConPt
, IConnectionPoint_iface
);
863 IEnumConnections IEnumConnections_iface
;
870 static inline EnumCon
*impl_from_IEnumConnections(IEnumConnections
*iface
)
872 return CONTAINING_RECORD(iface
, EnumCon
, IEnumConnections_iface
);
875 typedef struct _enumpt
877 IEnumConnectionPoints IEnumConnectionPoints_iface
;
884 static inline EnumPt
*impl_from_IEnumConnectionPoints(IEnumConnectionPoints
*iface
)
886 return CONTAINING_RECORD(iface
, EnumPt
, IEnumConnectionPoints_iface
);
890 static HRESULT WINAPI
Disp_QueryInterface(
897 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDispatch
))
904 IDispatch_AddRef(This
);
908 trace("no interface\n");
909 return E_NOINTERFACE
;
912 static ULONG WINAPI
Disp_AddRef(IDispatch
* This
)
914 Disp
*iface
= impl_from_IDispatch(This
);
915 return InterlockedIncrement(&iface
->refCount
);
918 static ULONG WINAPI
Disp_Release(IDispatch
* This
)
920 Disp
*iface
= impl_from_IDispatch(This
);
923 ret
= InterlockedDecrement(&iface
->refCount
);
925 HeapFree(GetProcessHeap(),0,This
);
929 static HRESULT WINAPI
Disp_GetTypeInfoCount(
933 return ERROR_SUCCESS
;
936 static HRESULT WINAPI
Disp_GetTypeInfo(
942 return ERROR_SUCCESS
;
945 static HRESULT WINAPI
Disp_GetIDsOfNames(
953 return ERROR_SUCCESS
;
956 static HRESULT WINAPI
Disp_Invoke(
962 DISPPARAMS
*pDispParams
,
964 EXCEPINFO
*pExcepInfo
,
967 trace("%p %lx %s %lx %x %p %p %p %p\n", This
, dispIdMember
, wine_dbgstr_guid(riid
), lcid
, wFlags
,
968 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
970 ok(dispIdMember
== 0xa0 || dispIdMember
== 0xa1, "Unknown dispIdMember\n");
971 ok(pDispParams
!= NULL
, "Invoked with NULL pDispParams\n");
972 ok(wFlags
== DISPATCH_METHOD
, "Wrong flags %x\n",wFlags
);
973 ok(lcid
== 0,"Wrong lcid %lx\n",lcid
);
974 if (dispIdMember
== 0xa0)
976 ok(pDispParams
->cArgs
== 0, "params.cArgs = %d\n", pDispParams
->cArgs
);
977 ok(pDispParams
->cNamedArgs
== 0, "params.cNamedArgs = %d\n", pDispParams
->cArgs
);
978 ok(pDispParams
->rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", pDispParams
->rgdispidNamedArgs
);
979 ok(pDispParams
->rgvarg
== NULL
, "params.rgvarg = %p\n", pDispParams
->rgvarg
);
981 else if (dispIdMember
== 0xa1)
983 ok(pDispParams
->cArgs
== 2, "params.cArgs = %d\n", pDispParams
->cArgs
);
984 ok(pDispParams
->cNamedArgs
== 0, "params.cNamedArgs = %d\n", pDispParams
->cArgs
);
985 ok(pDispParams
->rgdispidNamedArgs
== NULL
, "params.rgdispidNamedArgs = %p\n", pDispParams
->rgdispidNamedArgs
);
986 ok(V_VT(pDispParams
->rgvarg
) == VT_BSTR
, "V_VT(var) = %d\n", V_VT(pDispParams
->rgvarg
));
987 ok(V_I4(pDispParams
->rgvarg
) == 0xdeadcafe , "failed %p\n", V_BSTR(pDispParams
->rgvarg
));
988 ok(V_VT(pDispParams
->rgvarg
+1) == VT_I4
, "V_VT(var) = %d\n", V_VT(pDispParams
->rgvarg
+1));
989 ok(V_I4(pDispParams
->rgvarg
+1) == 0xdeadbeef, "failed %lx\n", V_I4(pDispParams
->rgvarg
+1));
992 return ERROR_SUCCESS
;
995 static const IDispatchVtbl disp_vtbl
= {
1000 Disp_GetTypeInfoCount
,
1006 static HRESULT WINAPI
Enum_QueryInterface(
1007 IEnumConnections
* This
,
1013 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IEnumConnections
))
1020 IEnumConnections_AddRef(This
);
1024 trace("no interface\n");
1025 return E_NOINTERFACE
;
1028 static ULONG WINAPI
Enum_AddRef(IEnumConnections
* This
)
1030 EnumCon
*iface
= impl_from_IEnumConnections(This
);
1031 return InterlockedIncrement(&iface
->refCount
);
1034 static ULONG WINAPI
Enum_Release(IEnumConnections
* This
)
1036 EnumCon
*iface
= impl_from_IEnumConnections(This
);
1039 ret
= InterlockedDecrement(&iface
->refCount
);
1041 HeapFree(GetProcessHeap(),0,This
);
1045 static HRESULT WINAPI
Enum_Next(
1046 IEnumConnections
* This
,
1051 EnumCon
*iface
= impl_from_IEnumConnections(This
);
1053 if (cConnections
> 0 && iface
->idx
< iface
->pt
->sinkCount
)
1055 rgcd
->pUnk
= iface
->pt
->sink
[iface
->idx
];
1056 IUnknown_AddRef(iface
->pt
->sink
[iface
->idx
]);
1057 rgcd
->dwCookie
=0xff;
1067 static HRESULT WINAPI
Enum_Skip(
1068 IEnumConnections
* This
,
1074 static HRESULT WINAPI
Enum_Reset(
1075 IEnumConnections
* This
)
1080 static HRESULT WINAPI
Enum_Clone(
1081 IEnumConnections
* This
,
1082 IEnumConnections
**ppEnum
)
1087 static const IEnumConnectionsVtbl enum_vtbl
= {
1089 Enum_QueryInterface
,
1098 static HRESULT WINAPI
ConPt_QueryInterface(
1099 IConnectionPoint
* This
,
1105 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IConnectionPoint
))
1112 IConnectionPoint_AddRef(This
);
1116 trace("no interface\n");
1117 return E_NOINTERFACE
;
1120 static ULONG WINAPI
ConPt_AddRef(
1121 IConnectionPoint
* This
)
1123 ConPt
*iface
= impl_from_IConnectionPoint(This
);
1124 return InterlockedIncrement(&iface
->refCount
);
1127 static ULONG WINAPI
ConPt_Release(
1128 IConnectionPoint
* This
)
1130 ConPt
*iface
= impl_from_IConnectionPoint(This
);
1133 ret
= InterlockedDecrement(&iface
->refCount
);
1136 if (iface
->sinkCount
> 0)
1139 for (i
= 0; i
< iface
->sinkCount
; i
++)
1142 IUnknown_Release(iface
->sink
[i
]);
1144 HeapFree(GetProcessHeap(),0,iface
->sink
);
1146 HeapFree(GetProcessHeap(),0,This
);
1151 static HRESULT WINAPI
ConPt_GetConnectionInterface(
1152 IConnectionPoint
* This
,
1156 ConPt
*iface
= impl_from_IConnectionPoint(This
);
1163 memcpy(pIID
,&iface
->id
,sizeof(GUID
));
1167 static HRESULT WINAPI
ConPt_GetConnectionPointContainer(
1168 IConnectionPoint
* This
,
1169 IConnectionPointContainer
**ppCPC
)
1171 ConPt
*iface
= impl_from_IConnectionPoint(This
);
1173 *ppCPC
= &iface
->container
->IConnectionPointContainer_iface
;
1177 static HRESULT WINAPI
ConPt_Advise(
1178 IConnectionPoint
* This
,
1182 ConPt
*iface
= impl_from_IConnectionPoint(This
);
1184 if (iface
->sinkCount
== 0)
1185 iface
->sink
= HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown
*));
1187 iface
->sink
= HeapReAlloc(GetProcessHeap(),0,iface
->sink
,sizeof(IUnknown
*)*(iface
->sinkCount
+1));
1188 iface
->sink
[iface
->sinkCount
] = pUnkSink
;
1189 IUnknown_AddRef(pUnkSink
);
1191 *pdwCookie
= iface
->sinkCount
;
1195 static HRESULT WINAPI
ConPt_Unadvise(
1196 IConnectionPoint
* This
,
1199 ConPt
*iface
= impl_from_IConnectionPoint(This
);
1201 if (dwCookie
> iface
->sinkCount
)
1205 IUnknown_Release(iface
->sink
[dwCookie
-1]);
1206 iface
->sink
[dwCookie
-1] = NULL
;
1211 static HRESULT WINAPI
ConPt_EnumConnections(
1212 IConnectionPoint
* This
,
1213 IEnumConnections
**ppEnum
)
1217 ec
= HeapAlloc(GetProcessHeap(),0,sizeof(EnumCon
));
1218 ec
->IEnumConnections_iface
.lpVtbl
= &enum_vtbl
;
1220 ec
->pt
= impl_from_IConnectionPoint(This
);
1222 *ppEnum
= &ec
->IEnumConnections_iface
;
1227 static const IConnectionPointVtbl point_vtbl
= {
1228 ConPt_QueryInterface
,
1232 ConPt_GetConnectionInterface
,
1233 ConPt_GetConnectionPointContainer
,
1236 ConPt_EnumConnections
1239 static HRESULT WINAPI
EnumPt_QueryInterface(
1240 IEnumConnectionPoints
* This
,
1246 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IEnumConnectionPoints
))
1253 IEnumConnectionPoints_AddRef(This
);
1257 trace("no interface\n");
1258 return E_NOINTERFACE
;
1261 static ULONG WINAPI
EnumPt_AddRef(IEnumConnectionPoints
* This
)
1263 EnumPt
*iface
= impl_from_IEnumConnectionPoints(This
);
1264 return InterlockedIncrement(&iface
->refCount
);
1267 static ULONG WINAPI
EnumPt_Release(IEnumConnectionPoints
* This
)
1269 EnumPt
*iface
= impl_from_IEnumConnectionPoints(This
);
1272 ret
= InterlockedDecrement(&iface
->refCount
);
1274 HeapFree(GetProcessHeap(),0,This
);
1278 static HRESULT WINAPI
EnumPt_Next(
1279 IEnumConnectionPoints
* This
,
1281 IConnectionPoint
**rgcd
,
1284 EnumPt
*iface
= impl_from_IEnumConnectionPoints(This
);
1286 if (cConnections
> 0 && iface
->idx
< iface
->container
->ptCount
)
1288 *rgcd
= iface
->container
->pt
[iface
->idx
];
1289 IConnectionPoint_AddRef(iface
->container
->pt
[iface
->idx
]);
1299 static HRESULT WINAPI
EnumPt_Skip(
1300 IEnumConnectionPoints
* This
,
1306 static HRESULT WINAPI
EnumPt_Reset(
1307 IEnumConnectionPoints
* This
)
1312 static HRESULT WINAPI
EnumPt_Clone(
1313 IEnumConnectionPoints
* This
,
1314 IEnumConnectionPoints
**ppEnumPt
)
1319 static const IEnumConnectionPointsVtbl enumpt_vtbl
= {
1321 EnumPt_QueryInterface
,
1330 static HRESULT WINAPI
Contain_QueryInterface(
1331 IConnectionPointContainer
* This
,
1337 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IConnectionPointContainer
))
1344 IConnectionPointContainer_AddRef(This
);
1348 trace("no interface\n");
1349 return E_NOINTERFACE
;
1352 static ULONG WINAPI
Contain_AddRef(
1353 IConnectionPointContainer
* This
)
1355 Contain
*iface
= impl_from_IConnectionPointContainer(This
);
1356 return InterlockedIncrement(&iface
->refCount
);
1359 static ULONG WINAPI
Contain_Release(
1360 IConnectionPointContainer
* This
)
1362 Contain
*iface
= impl_from_IConnectionPointContainer(This
);
1365 ret
= InterlockedDecrement(&iface
->refCount
);
1368 if (iface
->ptCount
> 0)
1371 for (i
= 0; i
< iface
->ptCount
; i
++)
1372 IConnectionPoint_Release(iface
->pt
[i
]);
1373 HeapFree(GetProcessHeap(),0,iface
->pt
);
1375 HeapFree(GetProcessHeap(),0,This
);
1380 static HRESULT WINAPI
Contain_EnumConnectionPoints(
1381 IConnectionPointContainer
* This
,
1382 IEnumConnectionPoints
**ppEnum
)
1386 ec
= HeapAlloc(GetProcessHeap(),0,sizeof(EnumPt
));
1387 ec
->IEnumConnectionPoints_iface
.lpVtbl
= &enumpt_vtbl
;
1390 ec
->container
= impl_from_IConnectionPointContainer(This
);
1391 *ppEnum
= &ec
->IEnumConnectionPoints_iface
;
1396 static HRESULT WINAPI
Contain_FindConnectionPoint(
1397 IConnectionPointContainer
* This
,
1399 IConnectionPoint
**ppCP
)
1401 Contain
*iface
= impl_from_IConnectionPointContainer(This
);
1404 if (!IsEqualIID(riid
, &IID_NULL
) || iface
->ptCount
==0)
1406 pt
= HeapAlloc(GetProcessHeap(),0,sizeof(ConPt
));
1407 pt
->IConnectionPoint_iface
.lpVtbl
= &point_vtbl
;
1411 pt
->container
= iface
;
1412 pt
->id
= IID_IDispatch
;
1414 if (iface
->ptCount
== 0)
1415 iface
->pt
=HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown
*));
1417 iface
->pt
= HeapReAlloc(GetProcessHeap(),0,iface
->pt
,sizeof(IUnknown
*)*(iface
->ptCount
+1));
1418 iface
->pt
[iface
->ptCount
] = &pt
->IConnectionPoint_iface
;
1421 *ppCP
= &pt
->IConnectionPoint_iface
;
1425 *ppCP
= iface
->pt
[0];
1426 IConnectionPoint_AddRef(*ppCP
);
1432 static const IConnectionPointContainerVtbl contain_vtbl
= {
1433 Contain_QueryInterface
,
1437 Contain_EnumConnectionPoints
,
1438 Contain_FindConnectionPoint
1441 static void test_IConnectionPoint(void)
1445 IConnectionPoint
*point
;
1448 DWORD cookie
= 0xffffffff;
1452 container
= HeapAlloc(GetProcessHeap(),0,sizeof(Contain
));
1453 container
->IConnectionPointContainer_iface
.lpVtbl
= &contain_vtbl
;
1454 container
->refCount
= 1;
1455 container
->ptCount
= 0;
1456 container
->pt
= NULL
;
1458 dispatch
= HeapAlloc(GetProcessHeap(),0,sizeof(Disp
));
1459 dispatch
->IDispatch_iface
.lpVtbl
= &disp_vtbl
;
1460 dispatch
->refCount
= 1;
1462 rc
= pConnectToConnectionPoint((IUnknown
*)&dispatch
->IDispatch_iface
, &IID_NULL
, TRUE
,
1463 (IUnknown
*)&container
->IConnectionPointContainer_iface
, &cookie
, &point
);
1464 ok(rc
== S_OK
, "pConnectToConnectionPoint failed with %lx\n",rc
);
1465 ok(point
!= NULL
, "returned ConnectionPoint is NULL\n");
1466 ok(cookie
!= 0xffffffff, "invalid cookie returned\n");
1468 rc
= pIConnectionPoint_SimpleInvoke(point
,0xa0,NULL
);
1469 ok(rc
== S_OK
, "pConnectToConnectionPoint failed with %lx\n",rc
);
1471 memset(¶ms
, 0xc0, sizeof(params
));
1472 memset(vars
, 0xc0, sizeof(vars
));
1473 rc
= pSHPackDispParams(¶ms
, vars
, 2, VT_I4
, 0xdeadbeef, VT_BSTR
, 0xdeadcafe);
1474 ok(rc
== S_OK
, "SHPackDispParams failed: %08lx\n", rc
);
1476 rc
= pIConnectionPoint_SimpleInvoke(point
,0xa1,¶ms
);
1477 ok(rc
== S_OK
, "pConnectToConnectionPoint failed with %lx\n",rc
);
1479 rc
= pConnectToConnectionPoint(NULL
, &IID_NULL
, FALSE
,
1480 (IUnknown
*)&container
->IConnectionPointContainer_iface
, &cookie
, NULL
);
1481 ok(rc
== S_OK
, "pConnectToConnectionPoint failed with %lx\n",rc
);
1483 /* MSDN says this should be required but it crashes on XP
1484 IUnknown_Release(point);
1486 ref
= IConnectionPointContainer_Release(&container
->IConnectionPointContainer_iface
);
1487 ok(ref
== 0, "leftover IConnectionPointContainer reference %li\n",ref
);
1488 ref
= IDispatch_Release(&dispatch
->IDispatch_iface
);
1489 ok(ref
== 0, "leftover IDispatch reference %li\n",ref
);
1492 typedef struct _propbag
1494 IPropertyBag IPropertyBag_iface
;
1499 static inline PropBag
*impl_from_IPropertyBag(IPropertyBag
*iface
)
1501 return CONTAINING_RECORD(iface
, PropBag
, IPropertyBag_iface
);
1505 static HRESULT WINAPI
Prop_QueryInterface(
1512 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IPropertyBag
))
1519 IPropertyBag_AddRef(This
);
1523 trace("no interface\n");
1524 return E_NOINTERFACE
;
1527 static ULONG WINAPI
Prop_AddRef(
1530 PropBag
*iface
= impl_from_IPropertyBag(This
);
1531 return InterlockedIncrement(&iface
->refCount
);
1534 static ULONG WINAPI
Prop_Release(
1537 PropBag
*iface
= impl_from_IPropertyBag(This
);
1540 ret
= InterlockedDecrement(&iface
->refCount
);
1542 HeapFree(GetProcessHeap(),0,This
);
1546 static HRESULT WINAPI
Prop_Read(
1548 LPCOLESTR pszPropName
,
1550 IErrorLog
*pErrorLog
)
1552 V_VT(pVar
) = VT_BLOB
|VT_BYREF
;
1553 V_BYREF(pVar
) = (LPVOID
)0xdeadcafe;
1557 static HRESULT WINAPI
Prop_Write(
1559 LPCOLESTR pszPropName
,
1566 static const IPropertyBagVtbl prop_vtbl
= {
1567 Prop_QueryInterface
,
1575 static void test_SHPropertyBag_ReadLONG(void)
1580 static const WCHAR szName1
[] = {'n','a','m','e','1',0};
1582 pb
= HeapAlloc(GetProcessHeap(),0,sizeof(PropBag
));
1584 pb
->IPropertyBag_iface
.lpVtbl
= &prop_vtbl
;
1587 rc
= pSHPropertyBag_ReadLONG(NULL
, szName1
, &out
);
1588 ok(rc
== E_INVALIDARG
|| broken(rc
== S_OK
), "incorrect return %lx\n",rc
);
1589 ok(out
== 0xfeedface, "value should not have changed\n");
1590 rc
= pSHPropertyBag_ReadLONG(&pb
->IPropertyBag_iface
, NULL
, &out
);
1591 ok(rc
== E_INVALIDARG
|| broken(rc
== S_OK
) || broken(rc
== S_FALSE
), "incorrect return %lx\n",rc
);
1592 ok(out
== 0xfeedface, "value should not have changed\n");
1593 rc
= pSHPropertyBag_ReadLONG(&pb
->IPropertyBag_iface
, szName1
, NULL
);
1594 ok(rc
== E_INVALIDARG
|| broken(rc
== S_OK
) || broken(rc
== S_FALSE
), "incorrect return %lx\n",rc
);
1595 rc
= pSHPropertyBag_ReadLONG(&pb
->IPropertyBag_iface
, szName1
, &out
);
1596 ok(rc
== DISP_E_BADVARTYPE
|| broken(rc
== S_OK
) || broken(rc
== S_FALSE
), "incorrect return %lx\n",rc
);
1597 ok(out
== 0xfeedface || broken(out
== 0xfeedfa00), "value should not have changed %lx\n",out
);
1598 IPropertyBag_Release(&pb
->IPropertyBag_iface
);
1601 static void test_SHSetWindowBits(void)
1604 DWORD style
, styleold
;
1608 clsA
.lpfnWndProc
= DefWindowProcA
;
1609 clsA
.cbClsExtra
= 0;
1610 clsA
.cbWndExtra
= 0;
1611 clsA
.hInstance
= GetModuleHandleA(NULL
);
1613 clsA
.hCursor
= LoadCursorA(0, (LPSTR
)IDC_ARROW
);
1614 clsA
.hbrBackground
= NULL
;
1615 clsA
.lpszMenuName
= NULL
;
1616 clsA
.lpszClassName
= "Shlwapi test class";
1617 RegisterClassA(&clsA
);
1619 hwnd
= CreateWindowA("Shlwapi test class", "Test", WS_VISIBLE
, 0, 0, 100, 100,
1620 NULL
, NULL
, GetModuleHandleA(NULL
), 0);
1621 ok(IsWindow(hwnd
), "failed to create window\n");
1624 SetLastError(0xdeadbeef);
1625 style
= pSHSetWindowBits(NULL
, GWL_STYLE
, 0, 0);
1626 ok(style
== 0, "expected 0 retval, got %ld\n", style
);
1627 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
,
1628 "expected ERROR_INVALID_WINDOW_HANDLE, got %ld\n", GetLastError());
1630 /* zero mask, zero flags */
1631 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1632 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, 0, 0);
1633 ok(styleold
== style
, "expected old style\n");
1634 ok(styleold
== GetWindowLongA(hwnd
, GWL_STYLE
), "expected to keep old style\n");
1637 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1638 ok(styleold
& WS_VISIBLE
, "expected WS_VISIBLE\n");
1639 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, WS_VISIBLE
, 0);
1641 ok(style
== styleold
, "expected previous style, got %lx\n", style
);
1642 ok((GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
) == 0, "expected updated style\n");
1644 /* test mask, unset style bit used */
1645 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1646 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, WS_VISIBLE
, 0);
1647 ok(style
== styleold
, "expected previous style, got %lx\n", style
);
1648 ok(styleold
== GetWindowLongA(hwnd
, GWL_STYLE
), "expected to keep old style\n");
1650 /* set back with flags */
1651 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1652 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, WS_VISIBLE
, WS_VISIBLE
);
1653 ok(style
== styleold
, "expected previous style, got %lx\n", style
);
1654 ok(GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
, "expected updated style\n");
1656 /* reset and try to set without a mask */
1657 pSHSetWindowBits(hwnd
, GWL_STYLE
, WS_VISIBLE
, 0);
1658 ok((GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
) == 0, "expected updated style\n");
1659 styleold
= GetWindowLongA(hwnd
, GWL_STYLE
);
1660 style
= pSHSetWindowBits(hwnd
, GWL_STYLE
, 0, WS_VISIBLE
);
1661 ok(style
== styleold
, "expected previous style, got %lx\n", style
);
1662 ok((GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
) == 0, "expected updated style\n");
1664 DestroyWindow(hwnd
);
1666 UnregisterClassA("Shlwapi test class", GetModuleHandleA(NULL
));
1669 static void test_SHFormatDateTimeA(void)
1671 FILETIME UNALIGNED filetime
;
1672 CHAR buff
[100], buff2
[100], buff3
[100];
1678 SystemTimeToFileTime(&st
, &filetime
);
1679 /* SHFormatDateTime expects input as utc */
1680 LocalFileTimeToFileTime(&filetime
, &filetime
);
1682 /* no way to get required buffer length here */
1683 ret
= pSHFormatDateTimeA(&filetime
, NULL
, NULL
, 0);
1684 ok(ret
== 0, "got %d\n", ret
);
1686 SetLastError(0xdeadbeef);
1687 buff
[0] = 'a'; buff
[1] = 0;
1688 ret
= pSHFormatDateTimeA(&filetime
, NULL
, buff
, 0);
1689 ok(ret
== 0, "got %d\n", ret
);
1690 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
1691 ok(buff
[0] == 'a', "expected same string, got %s\n", buff
);
1693 /* flags needs to have FDTF_NOAUTOREADINGORDER for these tests to succeed on Vista+ */
1695 /* all combinations documented as invalid succeeded */
1696 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTTIME
| FDTF_LONGTIME
;
1697 SetLastError(0xdeadbeef);
1698 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1699 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1700 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
1702 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTDATE
| FDTF_LONGDATE
;
1703 SetLastError(0xdeadbeef);
1704 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1705 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1706 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
1708 flags
= FDTF_SHORTDATE
| FDTF_LTRDATE
| FDTF_RTLDATE
;
1709 SetLastError(0xdeadbeef);
1710 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1711 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1712 ok(GetLastError() == 0xdeadbeef,
1713 "expected 0xdeadbeef, got %ld\n", GetLastError());
1715 flags
= FDTF_DEFAULT
;
1716 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1717 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1720 flags
= FDTF_SHORTDATE
| FDTF_SHORTTIME
;
1721 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff2
, sizeof(buff2
));
1722 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1723 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff
, buff2
);
1726 ret
= pSHFormatDateTimeA(&filetime
, NULL
, buff2
, sizeof(buff2
));
1727 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1728 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff
, buff2
);
1730 /* now check returned strings */
1731 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTTIME
;
1732 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1733 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1734 ret
= GetTimeFormatA(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
| LOCALE_USE_CP_ACP
, &st
, NULL
, buff2
, sizeof(buff2
));
1735 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1736 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1738 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGTIME
;
1739 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1740 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1741 ret
= GetTimeFormatA(LOCALE_USER_DEFAULT
, LOCALE_USE_CP_ACP
, &st
, NULL
, buff2
, sizeof(buff2
));
1742 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1743 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1745 /* both time flags */
1746 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGTIME
| FDTF_SHORTTIME
;
1747 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1748 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1749 ret
= GetTimeFormatA(LOCALE_USER_DEFAULT
, LOCALE_USE_CP_ACP
, &st
, NULL
, buff2
, sizeof(buff2
));
1750 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1751 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1753 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTDATE
;
1754 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1755 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1756 ret
= GetDateFormatA(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
| LOCALE_USE_CP_ACP
, &st
, NULL
, buff2
, sizeof(buff2
));
1757 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1758 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1760 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGDATE
;
1761 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1762 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1763 ret
= GetDateFormatA(LOCALE_USER_DEFAULT
, DATE_LONGDATE
| LOCALE_USE_CP_ACP
, &st
, NULL
, buff2
, sizeof(buff2
));
1764 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1765 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1767 /* both date flags */
1768 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGDATE
| FDTF_SHORTDATE
;
1769 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1770 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1771 ret
= GetDateFormatA(LOCALE_USER_DEFAULT
, DATE_LONGDATE
| LOCALE_USE_CP_ACP
, &st
, NULL
, buff2
, sizeof(buff2
));
1772 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1773 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1775 /* various combinations of date/time flags */
1776 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGDATE
| FDTF_SHORTTIME
;
1777 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1778 ok(ret
== lstrlenA(buff
)+1, "got %d, length %d\n", ret
, lstrlenA(buff
)+1);
1779 ret
= GetTimeFormatA(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
| LOCALE_USE_CP_ACP
, &st
, NULL
, buff3
, sizeof(buff3
));
1780 ok(ret
== lstrlenA(buff3
)+1, "got %d\n", ret
);
1781 ok(lstrcmpA(buff3
, buff
+ lstrlenA(buff
) - lstrlenA(buff3
)) == 0,
1782 "expected (%s), got (%s) for time part\n",
1783 buff3
, buff
+ lstrlenA(buff
) - lstrlenA(buff3
));
1784 ret
= GetDateFormatA(LOCALE_USER_DEFAULT
, DATE_LONGDATE
| LOCALE_USE_CP_ACP
, &st
, NULL
, buff2
, sizeof(buff2
));
1785 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1786 buff
[lstrlenA(buff2
)] = '\0';
1787 ok(lstrcmpA(buff2
, buff
) == 0, "expected (%s) got (%s) for date part\n",
1790 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_LONGDATE
| FDTF_LONGTIME
;
1791 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1792 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1793 ret
= GetTimeFormatA(LOCALE_USER_DEFAULT
, LOCALE_USE_CP_ACP
, &st
, NULL
, buff3
, sizeof(buff3
));
1794 ok(ret
== lstrlenA(buff3
)+1, "got %d\n", ret
);
1795 ok(lstrcmpA(buff3
, buff
+ lstrlenA(buff
) - lstrlenA(buff3
)) == 0,
1796 "expected (%s), got (%s) for time part\n",
1797 buff3
, buff
+ lstrlenA(buff
) - lstrlenA(buff3
));
1798 ret
= GetDateFormatA(LOCALE_USER_DEFAULT
, DATE_LONGDATE
| LOCALE_USE_CP_ACP
, &st
, NULL
, buff2
, sizeof(buff2
));
1799 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1800 buff
[lstrlenA(buff2
)] = '\0';
1801 ok(lstrcmpA(buff2
, buff
) == 0, "expected (%s) got (%s) for date part\n",
1804 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTDATE
| FDTF_SHORTTIME
;
1805 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1806 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1807 ret
= GetDateFormatA(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
| LOCALE_USE_CP_ACP
, &st
, NULL
, buff2
, sizeof(buff2
));
1808 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1810 ret
= GetTimeFormatA(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
| LOCALE_USE_CP_ACP
, &st
, NULL
, buff3
, sizeof(buff3
));
1811 ok(ret
== lstrlenA(buff3
)+1, "got %d\n", ret
);
1812 strcat(buff2
, buff3
);
1813 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1815 flags
= FDTF_NOAUTOREADINGORDER
| FDTF_SHORTDATE
| FDTF_LONGTIME
;
1816 ret
= pSHFormatDateTimeA(&filetime
, &flags
, buff
, sizeof(buff
));
1817 ok(ret
== lstrlenA(buff
)+1, "got %d\n", ret
);
1818 ret
= GetDateFormatA(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
| LOCALE_USE_CP_ACP
, &st
, NULL
, buff2
, sizeof(buff2
));
1819 ok(ret
== lstrlenA(buff2
)+1, "got %d\n", ret
);
1821 ret
= GetTimeFormatA(LOCALE_USER_DEFAULT
, LOCALE_USE_CP_ACP
, &st
, NULL
, buff3
, sizeof(buff3
));
1822 ok(ret
== lstrlenA(buff3
)+1, "got %d\n", ret
);
1823 strcat(buff2
, buff3
);
1824 ok(lstrcmpA(buff
, buff2
) == 0, "expected (%s), got (%s)\n", buff2
, buff
);
1827 static void test_SHFormatDateTimeW(void)
1829 FILETIME UNALIGNED filetime
;
1830 WCHAR buff
[100], buff2
[100], buff3
[100], *p1
, *p2
;
1834 static const WCHAR spaceW
[] = {' ',0};
1835 #define UNICODE_LTR_MARK 0x200e
1836 #define UNICODE_RTL_MARK 0x200f
1840 /* crashes on native */
1841 pSHFormatDateTimeW(NULL
, NULL
, NULL
, 0);
1845 SystemTimeToFileTime(&st
, &filetime
);
1846 /* SHFormatDateTime expects input as utc */
1847 LocalFileTimeToFileTime(&filetime
, &filetime
);
1849 /* no way to get required buffer length here */
1850 SetLastError(0xdeadbeef);
1851 ret
= pSHFormatDateTimeW(&filetime
, NULL
, NULL
, 0);
1852 ok(ret
== 0, "expected 0, got %d\n", ret
);
1853 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
1855 SetLastError(0xdeadbeef);
1856 buff
[0] = 'a'; buff
[1] = 0;
1857 ret
= pSHFormatDateTimeW(&filetime
, NULL
, buff
, 0);
1858 ok(ret
== 0, "expected 0, got %d\n", ret
);
1859 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
1860 ok(buff
[0] == 'a', "expected same string\n");
1862 /* all combinations documented as invalid succeeded */
1863 flags
= FDTF_SHORTTIME
| FDTF_LONGTIME
;
1864 SetLastError(0xdeadbeef);
1865 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, ARRAY_SIZE(buff
));
1866 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1867 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1868 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
1870 flags
= FDTF_SHORTDATE
| FDTF_LONGDATE
;
1871 SetLastError(0xdeadbeef);
1872 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, ARRAY_SIZE(buff
));
1873 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1874 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1875 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
1877 flags
= FDTF_SHORTDATE
| FDTF_LTRDATE
| FDTF_RTLDATE
;
1878 SetLastError(0xdeadbeef);
1879 buff
[0] = 0; /* NT4 doesn't clear the buffer on failure */
1880 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, ARRAY_SIZE(buff
));
1881 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1882 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1883 ok(GetLastError() == 0xdeadbeef,
1884 "expected 0xdeadbeef, got %ld\n", GetLastError());
1886 /* now check returned strings */
1887 flags
= FDTF_SHORTTIME
;
1888 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, ARRAY_SIZE(buff
));
1889 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1890 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1891 SetLastError(0xdeadbeef);
1892 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff2
, ARRAY_SIZE(buff2
));
1893 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1894 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1896 flags
= FDTF_LONGTIME
;
1897 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, ARRAY_SIZE(buff
));
1898 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1899 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1900 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff2
, ARRAY_SIZE(buff2
));
1901 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1902 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1904 /* both time flags */
1905 flags
= FDTF_LONGTIME
| FDTF_SHORTTIME
;
1906 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, ARRAY_SIZE(buff
));
1907 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1908 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1909 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff2
, ARRAY_SIZE(buff2
));
1910 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1911 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal string\n");
1913 flags
= FDTF_SHORTDATE
;
1914 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, ARRAY_SIZE(buff
));
1915 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1916 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1917 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, ARRAY_SIZE(buff2
));
1918 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1919 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1921 flags
= FDTF_LONGDATE
;
1922 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, ARRAY_SIZE(buff
));
1923 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1924 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1925 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, ARRAY_SIZE(buff2
));
1926 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1927 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1929 /* both date flags */
1930 flags
= FDTF_LONGDATE
| FDTF_SHORTDATE
;
1931 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, ARRAY_SIZE(buff
));
1932 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1933 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1934 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, ARRAY_SIZE(buff2
));
1935 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1936 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
1938 /* various combinations of date/time flags */
1939 flags
= FDTF_LONGDATE
| FDTF_SHORTTIME
;
1940 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, ARRAY_SIZE(buff
));
1941 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1942 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1943 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff3
, ARRAY_SIZE(buff3
));
1944 ok(ret
== lstrlenW(buff3
)+1, "expected %d, got %d\n", lstrlenW(buff3
)+1, ret
);
1945 ok(lstrcmpW(buff3
, buff
+ lstrlenW(buff
) - lstrlenW(buff3
)) == 0,
1946 "expected (%s), got (%s) for time part\n",
1947 wine_dbgstr_w(buff3
), wine_dbgstr_w(buff
+ lstrlenW(buff
) - lstrlenW(buff3
)));
1948 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, ARRAY_SIZE(buff2
));
1949 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1954 while (*p1
== UNICODE_LTR_MARK
|| *p1
== UNICODE_RTL_MARK
)
1956 while (*p2
== UNICODE_LTR_MARK
|| *p2
== UNICODE_RTL_MARK
)
1962 ok(lstrcmpW(buff2
, buff
) == 0, "expected (%s) got (%s) for date part\n",
1963 wine_dbgstr_w(buff2
), wine_dbgstr_w(buff
));
1965 flags
= FDTF_LONGDATE
| FDTF_LONGTIME
;
1966 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, ARRAY_SIZE(buff
));
1967 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1968 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1969 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff3
, ARRAY_SIZE(buff3
));
1970 ok(ret
== lstrlenW(buff3
)+1, "expected %d, got %d\n", lstrlenW(buff3
)+1, ret
);
1971 ok(lstrcmpW(buff3
, buff
+ lstrlenW(buff
) - lstrlenW(buff3
)) == 0,
1972 "expected (%s), got (%s) for time part\n",
1973 wine_dbgstr_w(buff3
), wine_dbgstr_w(buff
+ lstrlenW(buff
) - lstrlenW(buff3
)));
1974 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buff2
, ARRAY_SIZE(buff2
));
1975 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1980 while (*p1
== UNICODE_LTR_MARK
|| *p1
== UNICODE_RTL_MARK
)
1982 while (*p2
== UNICODE_LTR_MARK
|| *p2
== UNICODE_RTL_MARK
)
1988 ok(lstrcmpW(buff2
, buff
) == 0, "expected (%s) got (%s) for date part\n",
1989 wine_dbgstr_w(buff2
), wine_dbgstr_w(buff
));
1991 flags
= FDTF_SHORTDATE
| FDTF_SHORTTIME
;
1992 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, ARRAY_SIZE(buff
));
1993 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
1994 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
1995 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, ARRAY_SIZE(buff2
));
1996 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
1997 lstrcatW(buff2
, spaceW
);
1998 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, TIME_NOSECONDS
, &st
, NULL
, buff3
, ARRAY_SIZE(buff3
));
1999 ok(ret
== lstrlenW(buff3
)+1, "expected %d, got %d\n", lstrlenW(buff3
)+1, ret
);
2000 lstrcatW(buff2
, buff3
);
2001 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
2003 flags
= FDTF_SHORTDATE
| FDTF_LONGTIME
;
2004 ret
= pSHFormatDateTimeW(&filetime
, &flags
, buff
, ARRAY_SIZE(buff
));
2005 ok(ret
== lstrlenW(buff
)+1 || ret
== lstrlenW(buff
),
2006 "expected %d or %d, got %d\n", lstrlenW(buff
)+1, lstrlenW(buff
), ret
);
2007 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, NULL
, buff2
, ARRAY_SIZE(buff2
));
2008 ok(ret
== lstrlenW(buff2
)+1, "expected %d, got %d\n", lstrlenW(buff2
)+1, ret
);
2009 lstrcatW(buff2
, spaceW
);
2010 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buff3
, ARRAY_SIZE(buff3
));
2011 ok(ret
== lstrlenW(buff3
)+1, "expected %d, got %d\n", lstrlenW(buff3
)+1, ret
);
2012 lstrcatW(buff2
, buff3
);
2013 ok(lstrcmpW(buff
, buff2
) == 0, "expected equal strings\n");
2016 static void test_SHGetObjectCompatFlags(void)
2018 struct compat_value
{
2023 struct compat_value values
[] = {
2024 { "OTNEEDSSFCACHE", 0x1 },
2025 { "NO_WEBVIEW", 0x2 },
2026 { "UNBINDABLE", 0x4 },
2028 { "NEEDSFILESYSANCESTOR", 0x10 },
2029 { "NOTAFILESYSTEM", 0x20 },
2030 { "CTXMENU_NOVERBS", 0x40 },
2031 { "CTXMENU_LIMITEDQI", 0x80 },
2032 { "COCREATESHELLFOLDERONLY", 0x100 },
2033 { "NEEDSSTORAGEANCESTOR", 0x200 },
2034 { "NOLEGACYWEBVIEW", 0x400 },
2035 { "CTXMENU_XPQCMFLAGS", 0x1000 },
2036 { "NOIPROPERTYSTORE", 0x2000 }
2039 static const char compat_path
[] = "Software\\Microsoft\\Windows\\CurrentVersion\\ShellCompatibility\\Objects";
2040 CHAR keyA
[39]; /* {CLSID} */
2046 ret
= pSHGetObjectCompatFlags(NULL
, NULL
);
2047 ok(ret
== 0, "got %ld\n", ret
);
2049 ret
= RegOpenKeyA(HKEY_LOCAL_MACHINE
, compat_path
, &root
);
2050 if (ret
!= ERROR_SUCCESS
)
2052 skip("No compatibility class data found\n");
2056 for (i
= 0; RegEnumKeyA(root
, i
, keyA
, sizeof(keyA
)) == ERROR_SUCCESS
; i
++)
2060 if (RegOpenKeyA(root
, keyA
, &clsid_key
) == ERROR_SUCCESS
)
2063 DWORD expected
= 0, got
, length
= sizeof(valueA
);
2067 for (v
= 0; RegEnumValueA(clsid_key
, v
, valueA
, &length
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
; v
++)
2071 for (j
= 0; j
< ARRAY_SIZE(values
); j
++)
2072 if (lstrcmpA(values
[j
].nameA
, valueA
) == 0)
2074 expected
|= values
[j
].value
;
2078 length
= sizeof(valueA
);
2081 pGUIDFromStringA(keyA
, &clsid
);
2082 got
= pSHGetObjectCompatFlags(NULL
, &clsid
);
2083 ok(got
== expected
, "got 0x%08lx, expected 0x%08lx. Key %s\n", got
, expected
, keyA
);
2085 RegCloseKey(clsid_key
);
2093 IOleCommandTarget IOleCommandTarget_iface
;
2095 } IOleCommandTargetImpl
;
2097 static inline IOleCommandTargetImpl
*impl_from_IOleCommandTarget(IOleCommandTarget
*iface
)
2099 return CONTAINING_RECORD(iface
, IOleCommandTargetImpl
, IOleCommandTarget_iface
);
2102 static const IOleCommandTargetVtbl IOleCommandTargetImpl_Vtbl
;
2104 static IOleCommandTarget
* IOleCommandTargetImpl_Construct(void)
2106 IOleCommandTargetImpl
*obj
;
2108 obj
= HeapAlloc(GetProcessHeap(), 0, sizeof(*obj
));
2109 obj
->IOleCommandTarget_iface
.lpVtbl
= &IOleCommandTargetImpl_Vtbl
;
2112 return &obj
->IOleCommandTarget_iface
;
2115 static HRESULT WINAPI
IOleCommandTargetImpl_QueryInterface(IOleCommandTarget
*iface
, REFIID riid
, void **ppvObj
)
2117 IOleCommandTargetImpl
*This
= impl_from_IOleCommandTarget(iface
);
2119 if (IsEqualIID(riid
, &IID_IUnknown
) ||
2120 IsEqualIID(riid
, &IID_IOleCommandTarget
))
2127 IOleCommandTarget_AddRef(iface
);
2131 return E_NOINTERFACE
;
2134 static ULONG WINAPI
IOleCommandTargetImpl_AddRef(IOleCommandTarget
*iface
)
2136 IOleCommandTargetImpl
*This
= impl_from_IOleCommandTarget(iface
);
2137 return InterlockedIncrement(&This
->ref
);
2140 static ULONG WINAPI
IOleCommandTargetImpl_Release(IOleCommandTarget
*iface
)
2142 IOleCommandTargetImpl
*This
= impl_from_IOleCommandTarget(iface
);
2143 ULONG ref
= InterlockedDecrement(&This
->ref
);
2147 HeapFree(GetProcessHeap(), 0, This
);
2153 static HRESULT WINAPI
IOleCommandTargetImpl_QueryStatus(
2154 IOleCommandTarget
*iface
, const GUID
*group
, ULONG cCmds
, OLECMD prgCmds
[], OLECMDTEXT
*pCmdText
)
2159 static HRESULT WINAPI
IOleCommandTargetImpl_Exec(
2160 IOleCommandTarget
*iface
,
2161 const GUID
*CmdGroup
,
2167 add_call(&trace_got
, 3, CmdGroup
, (void*)(DWORD_PTR
)nCmdID
, (void*)(DWORD_PTR
)nCmdexecopt
, pvaIn
, pvaOut
);
2171 static const IOleCommandTargetVtbl IOleCommandTargetImpl_Vtbl
=
2173 IOleCommandTargetImpl_QueryInterface
,
2174 IOleCommandTargetImpl_AddRef
,
2175 IOleCommandTargetImpl_Release
,
2176 IOleCommandTargetImpl_QueryStatus
,
2177 IOleCommandTargetImpl_Exec
2181 IServiceProvider IServiceProvider_iface
;
2183 } IServiceProviderImpl
;
2185 static inline IServiceProviderImpl
*impl_from_IServiceProvider(IServiceProvider
*iface
)
2187 return CONTAINING_RECORD(iface
, IServiceProviderImpl
, IServiceProvider_iface
);
2191 IProfferService IProfferService_iface
;
2193 } IProfferServiceImpl
;
2195 static inline IProfferServiceImpl
*impl_from_IProfferService(IProfferService
*iface
)
2197 return CONTAINING_RECORD(iface
, IProfferServiceImpl
, IProfferService_iface
);
2201 static const IServiceProviderVtbl IServiceProviderImpl_Vtbl
;
2202 static const IProfferServiceVtbl IProfferServiceImpl_Vtbl
;
2204 static IServiceProvider
* IServiceProviderImpl_Construct(void)
2206 IServiceProviderImpl
*obj
;
2208 obj
= HeapAlloc(GetProcessHeap(), 0, sizeof(*obj
));
2209 obj
->IServiceProvider_iface
.lpVtbl
= &IServiceProviderImpl_Vtbl
;
2212 return &obj
->IServiceProvider_iface
;
2215 static IProfferService
* IProfferServiceImpl_Construct(void)
2217 IProfferServiceImpl
*obj
;
2219 obj
= HeapAlloc(GetProcessHeap(), 0, sizeof(*obj
));
2220 obj
->IProfferService_iface
.lpVtbl
= &IProfferServiceImpl_Vtbl
;
2223 return &obj
->IProfferService_iface
;
2226 static HRESULT WINAPI
IServiceProviderImpl_QueryInterface(IServiceProvider
*iface
, REFIID riid
, void **ppvObj
)
2228 IServiceProviderImpl
*This
= impl_from_IServiceProvider(iface
);
2230 if (IsEqualIID(riid
, &IID_IUnknown
) ||
2231 IsEqualIID(riid
, &IID_IServiceProvider
))
2238 IServiceProvider_AddRef(iface
);
2239 /* native uses redefined IID_IServiceProvider symbol, so we can't compare pointers */
2240 if (IsEqualIID(riid
, &IID_IServiceProvider
))
2241 add_call(&trace_got
, 1, iface
, &IID_IServiceProvider
, 0, 0, 0);
2245 return E_NOINTERFACE
;
2248 static ULONG WINAPI
IServiceProviderImpl_AddRef(IServiceProvider
*iface
)
2250 IServiceProviderImpl
*This
= impl_from_IServiceProvider(iface
);
2251 return InterlockedIncrement(&This
->ref
);
2254 static ULONG WINAPI
IServiceProviderImpl_Release(IServiceProvider
*iface
)
2256 IServiceProviderImpl
*This
= impl_from_IServiceProvider(iface
);
2257 ULONG ref
= InterlockedDecrement(&This
->ref
);
2261 HeapFree(GetProcessHeap(), 0, This
);
2267 static HRESULT WINAPI
IServiceProviderImpl_QueryService(
2268 IServiceProvider
*iface
, REFGUID service
, REFIID riid
, void **ppv
)
2270 /* native uses redefined pointer for IID_IOleCommandTarget, not one from uuid.lib */
2271 if (IsEqualIID(riid
, &IID_IOleCommandTarget
))
2273 add_call(&trace_got
, 2, iface
, service
, &IID_IOleCommandTarget
, 0, 0);
2274 *ppv
= IOleCommandTargetImpl_Construct();
2276 if (IsEqualIID(riid
, &IID_IProfferService
))
2278 if (IsEqualIID(service
, &IID_IProfferService
))
2279 add_call(&trace_got
, 2, &IID_IProfferService
, &IID_IProfferService
, 0, 0, 0);
2280 *ppv
= IProfferServiceImpl_Construct();
2285 static const IServiceProviderVtbl IServiceProviderImpl_Vtbl
=
2287 IServiceProviderImpl_QueryInterface
,
2288 IServiceProviderImpl_AddRef
,
2289 IServiceProviderImpl_Release
,
2290 IServiceProviderImpl_QueryService
2293 static void test_IUnknown_QueryServiceExec(void)
2295 IServiceProvider
*provider
;
2296 static const GUID dummy_serviceid
= { 0xdeadbeef };
2297 static const GUID dummy_groupid
= { 0xbeefbeef };
2298 call_trace_t trace_expected
;
2301 provider
= IServiceProviderImpl_Construct();
2303 /* null source pointer */
2304 hr
= pIUnknown_QueryServiceExec(NULL
, &dummy_serviceid
, &dummy_groupid
, 0, 0, 0, 0);
2306 hr
== E_NOTIMPL
, /* win 8 */
2307 "got 0x%08lx\n", hr
);
2310 IUnknown_QueryServiceExec( ptr1, serviceid, groupid, arg1, arg2, arg3, arg4);
2311 -> IUnknown_QueryInterface( ptr1, &IID_IServiceProvider, &prov );
2312 -> IServiceProvider_QueryService( prov, serviceid, &IID_IOleCommandTarget, &obj );
2313 -> IOleCommandTarget_Exec( obj, groupid, arg1, arg2, arg3, arg4 );
2315 init_call_trace(&trace_expected
);
2317 add_call(&trace_expected
, 1, provider
, &IID_IServiceProvider
, 0, 0, 0);
2318 add_call(&trace_expected
, 2, provider
, &dummy_serviceid
, &IID_IOleCommandTarget
, 0, 0);
2319 add_call(&trace_expected
, 3, &dummy_groupid
, (void*)0x1, (void*)0x2, (void*)0x3, (void*)0x4);
2321 init_call_trace(&trace_got
);
2322 hr
= pIUnknown_QueryServiceExec((IUnknown
*)provider
, &dummy_serviceid
, &dummy_groupid
, 0x1, 0x2, (void*)0x3, (void*)0x4);
2323 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
2325 ok_trace(&trace_expected
, &trace_got
);
2327 free_call_trace(&trace_expected
);
2328 free_call_trace(&trace_got
);
2330 IServiceProvider_Release(provider
);
2334 static HRESULT WINAPI
IProfferServiceImpl_QueryInterface(IProfferService
*iface
, REFIID riid
, void **ppvObj
)
2336 IProfferServiceImpl
*This
= impl_from_IProfferService(iface
);
2338 if (IsEqualIID(riid
, &IID_IUnknown
) ||
2339 IsEqualIID(riid
, &IID_IProfferService
))
2343 else if (IsEqualIID(riid
, &IID_IServiceProvider
))
2345 *ppvObj
= IServiceProviderImpl_Construct();
2346 add_call(&trace_got
, 1, iface
, &IID_IServiceProvider
, 0, 0, 0);
2352 IProfferService_AddRef(iface
);
2356 return E_NOINTERFACE
;
2359 static ULONG WINAPI
IProfferServiceImpl_AddRef(IProfferService
*iface
)
2361 IProfferServiceImpl
*This
= impl_from_IProfferService(iface
);
2362 return InterlockedIncrement(&This
->ref
);
2365 static ULONG WINAPI
IProfferServiceImpl_Release(IProfferService
*iface
)
2367 IProfferServiceImpl
*This
= impl_from_IProfferService(iface
);
2368 ULONG ref
= InterlockedDecrement(&This
->ref
);
2372 HeapFree(GetProcessHeap(), 0, This
);
2378 static HRESULT WINAPI
IProfferServiceImpl_ProfferService(IProfferService
*iface
,
2379 REFGUID service
, IServiceProvider
*pService
, DWORD
*pCookie
)
2381 *pCookie
= 0xdeadbeef;
2382 add_call(&trace_got
, 3, service
, pService
, pCookie
, 0, 0);
2386 static HRESULT WINAPI
IProfferServiceImpl_RevokeService(IProfferService
*iface
, DWORD cookie
)
2388 add_call(&trace_got
, 4, (void*)(DWORD_PTR
)cookie
, 0, 0, 0, 0);
2392 static const IProfferServiceVtbl IProfferServiceImpl_Vtbl
=
2394 IProfferServiceImpl_QueryInterface
,
2395 IProfferServiceImpl_AddRef
,
2396 IProfferServiceImpl_Release
,
2397 IProfferServiceImpl_ProfferService
,
2398 IProfferServiceImpl_RevokeService
2401 static void test_IUnknown_ProfferService(void)
2403 IServiceProvider
*provider
;
2404 IProfferService
*proff
;
2405 static const GUID dummy_serviceid
= { 0xdeadbeef };
2406 call_trace_t trace_expected
;
2410 provider
= IServiceProviderImpl_Construct();
2411 proff
= IProfferServiceImpl_Construct();
2413 /* null source pointer */
2414 hr
= pIUnknown_ProfferService(NULL
, &dummy_serviceid
, 0, 0);
2416 hr
== E_NOTIMPL
, /* win 8 */
2417 "got 0x%08lx\n", hr
);
2420 IUnknown_ProfferService( ptr1, serviceid, arg1, arg2);
2421 -> IUnknown_QueryInterface( ptr1, &IID_IServiceProvider, &provider );
2422 -> IServiceProvider_QueryService( provider, &IID_IProfferService, &IID_IProfferService, &proffer );
2424 if (service pointer not null):
2425 -> IProfferService_ProfferService( proffer, serviceid, arg1, arg2 );
2427 -> IProfferService_RevokeService( proffer, *arg2 );
2429 init_call_trace(&trace_expected
);
2431 add_call(&trace_expected
, 1, proff
, &IID_IServiceProvider
, 0, 0, 0);
2432 add_call(&trace_expected
, 2, &IID_IProfferService
, &IID_IProfferService
, 0, 0, 0);
2433 add_call(&trace_expected
, 3, &dummy_serviceid
, provider
, &cookie
, 0, 0);
2435 init_call_trace(&trace_got
);
2437 hr
= pIUnknown_ProfferService((IUnknown
*)proff
, &dummy_serviceid
, provider
, &cookie
);
2438 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
2439 ok(cookie
== 0xdeadbeef, "got %lx\n", cookie
);
2441 ok_trace(&trace_expected
, &trace_got
);
2442 free_call_trace(&trace_got
);
2443 free_call_trace(&trace_expected
);
2445 /* same with ::Revoke path */
2446 init_call_trace(&trace_expected
);
2448 add_call(&trace_expected
, 1, proff
, &IID_IServiceProvider
, 0, 0, 0);
2449 add_call(&trace_expected
, 2, &IID_IProfferService
, &IID_IProfferService
, 0, 0, 0);
2450 add_call(&trace_expected
, 4, (void*)(DWORD_PTR
)cookie
, 0, 0, 0, 0);
2452 init_call_trace(&trace_got
);
2453 ok(cookie
!= 0, "got %lx\n", cookie
);
2454 hr
= pIUnknown_ProfferService((IUnknown
*)proff
, &dummy_serviceid
, 0, &cookie
);
2455 ok(hr
== S_OK
, "got 0x%08lx\n", hr
);
2456 ok(cookie
== 0, "got %lx\n", cookie
);
2457 ok_trace(&trace_expected
, &trace_got
);
2458 free_call_trace(&trace_got
);
2459 free_call_trace(&trace_expected
);
2461 IServiceProvider_Release(provider
);
2462 IProfferService_Release(proff
);
2465 static void test_SHCreateWorkerWindowA(void)
2473 hwnd
= pSHCreateWorkerWindowA(0, NULL
, 0, 0, 0, 0);
2474 ok(hwnd
!= 0, "expected window\n");
2476 GetClassNameA(hwnd
, classA
, 20);
2477 ok(lstrcmpA(classA
, "WorkerA") == 0, "expected WorkerA class, got %s\n", classA
);
2479 ret
= GetWindowLongPtrA(hwnd
, 0);
2480 ok(ret
== 0, "got %Id\n", ret
);
2483 memset(&cliA
, 0, sizeof(cliA
));
2484 res
= GetClassInfoA(GetModuleHandleA("shlwapi.dll"), "WorkerA", &cliA
);
2485 ok(res
, "failed to get class info\n");
2486 ok(cliA
.style
== 0, "got 0x%08x\n", cliA
.style
);
2487 ok(cliA
.cbClsExtra
== 0, "got %d\n", cliA
.cbClsExtra
);
2488 ok(cliA
.cbWndExtra
== sizeof(LONG_PTR
), "got %d\n", cliA
.cbWndExtra
);
2489 ok(cliA
.lpszMenuName
== 0, "got %s\n", cliA
.lpszMenuName
);
2491 DestroyWindow(hwnd
);
2493 /* set extra bytes */
2494 hwnd
= pSHCreateWorkerWindowA(0, NULL
, 0, 0, 0, 0xdeadbeef);
2495 ok(hwnd
!= 0, "expected window\n");
2497 GetClassNameA(hwnd
, classA
, 20);
2498 ok(lstrcmpA(classA
, "WorkerA") == 0, "expected WorkerA class, got %s\n", classA
);
2500 ret
= GetWindowLongPtrA(hwnd
, 0);
2501 ok(ret
== 0xdeadbeef, "got %Id\n", ret
);
2504 ret
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
2505 ok(ret
== WS_EX_WINDOWEDGE
||
2506 ret
== (WS_EX_WINDOWEDGE
|WS_EX_LAYOUTRTL
) /* systems with RTL locale */, "0x%08Ix\n", ret
);
2508 DestroyWindow(hwnd
);
2510 hwnd
= pSHCreateWorkerWindowA(0, NULL
, WS_EX_TOOLWINDOW
, 0, 0, 0);
2511 ret
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
2512 ok(ret
== (WS_EX_WINDOWEDGE
|WS_EX_TOOLWINDOW
) ||
2513 ret
== (WS_EX_WINDOWEDGE
|WS_EX_TOOLWINDOW
|WS_EX_LAYOUTRTL
) /* systems with RTL locale */, "0x%08Ix\n", ret
);
2514 DestroyWindow(hwnd
);
2517 static HRESULT WINAPI
SF_QueryInterface(IShellFolder
*iface
,
2518 REFIID riid
, void **ppv
)
2520 /* SHIShellFolder_EnumObjects doesn't QI the object for IShellFolder */
2521 ok(!IsEqualGUID(&IID_IShellFolder
, riid
),
2522 "Unexpected QI for IShellFolder\n");
2523 return E_NOINTERFACE
;
2526 static ULONG WINAPI
SF_AddRef(IShellFolder
*iface
)
2531 static ULONG WINAPI
SF_Release(IShellFolder
*iface
)
2536 static HRESULT WINAPI
SF_ParseDisplayName(IShellFolder
*iface
,
2537 HWND owner
, LPBC reserved
, LPOLESTR displayName
, ULONG
*eaten
,
2538 LPITEMIDLIST
*idl
, ULONG
*attr
)
2540 ok(0, "Didn't expect ParseDisplayName\n");
2544 static HRESULT WINAPI
SF_EnumObjects(IShellFolder
*iface
,
2545 HWND owner
, SHCONTF flags
, IEnumIDList
**enm
)
2547 *enm
= (IEnumIDList
*)0xcafebabe;
2551 static HRESULT WINAPI
SF_BindToObject(IShellFolder
*iface
,
2552 LPCITEMIDLIST idl
, LPBC reserved
, REFIID riid
, void **obj
)
2554 ok(0, "Didn't expect BindToObject\n");
2558 static HRESULT WINAPI
SF_BindToStorage(IShellFolder
*iface
,
2559 LPCITEMIDLIST idl
, LPBC reserved
, REFIID riid
, void **obj
)
2561 ok(0, "Didn't expect BindToStorage\n");
2565 static HRESULT WINAPI
SF_CompareIDs(IShellFolder
*iface
,
2566 LPARAM lparam
, LPCITEMIDLIST idl1
, LPCITEMIDLIST idl2
)
2568 ok(0, "Didn't expect CompareIDs\n");
2572 static HRESULT WINAPI
SF_CreateViewObject(IShellFolder
*iface
,
2573 HWND owner
, REFIID riid
, void **out
)
2575 ok(0, "Didn't expect CreateViewObject\n");
2579 static HRESULT WINAPI
SF_GetAttributesOf(IShellFolder
*iface
,
2580 UINT cidl
, LPCITEMIDLIST
*idl
, SFGAOF
*inOut
)
2582 ok(0, "Didn't expect GetAttributesOf\n");
2586 static HRESULT WINAPI
SF_GetUIObjectOf(IShellFolder
*iface
,
2587 HWND owner
, UINT cidl
, LPCITEMIDLIST
*idls
, REFIID riid
, UINT
*inOut
,
2590 ok(0, "Didn't expect GetUIObjectOf\n");
2594 static HRESULT WINAPI
SF_GetDisplayNameOf(IShellFolder
*iface
,
2595 LPCITEMIDLIST idl
, SHGDNF flags
, STRRET
*name
)
2597 ok(0, "Didn't expect GetDisplayNameOf\n");
2601 static HRESULT WINAPI
SF_SetNameOf(IShellFolder
*iface
,
2602 HWND hwnd
, LPCITEMIDLIST idl
, LPCOLESTR name
, SHGDNF flags
,
2603 LPITEMIDLIST
*idlOut
)
2605 ok(0, "Didn't expect SetNameOf\n");
2609 static IShellFolderVtbl ShellFolderVtbl
= {
2613 SF_ParseDisplayName
,
2618 SF_CreateViewObject
,
2621 SF_GetDisplayNameOf
,
2625 static IShellFolder ShellFolder
= { &ShellFolderVtbl
};
2627 static void test_SHIShellFolder_EnumObjects(void)
2631 IShellFolder
*folder
;
2633 if(!pSHIShellFolder_EnumObjects
){ /* win7 and later */
2634 win_skip("SHIShellFolder_EnumObjects not available\n");
2639 /* NULL object crashes on Windows */
2640 pSHIShellFolder_EnumObjects(NULL
, NULL
, 0, NULL
);
2643 /* SHIShellFolder_EnumObjects doesn't QI the object for IShellFolder */
2644 enm
= (IEnumIDList
*)0xdeadbeef;
2645 hres
= pSHIShellFolder_EnumObjects(&ShellFolder
, NULL
, 0, &enm
);
2646 ok(hres
== S_OK
, "SHIShellFolder_EnumObjects failed: 0x%08lx\n", hres
);
2647 ok(enm
== (IEnumIDList
*)0xcafebabe, "Didn't get expected enumerator location, instead: %p\n", enm
);
2649 /* SHIShellFolder_EnumObjects isn't strict about the IShellFolder object */
2650 hres
= SHGetDesktopFolder(&folder
);
2651 ok(hres
== S_OK
, "SHGetDesktopFolder failed: 0x%08lx\n", hres
);
2654 hres
= pSHIShellFolder_EnumObjects(folder
, NULL
, 0, &enm
);
2655 ok(hres
== S_OK
, "SHIShellFolder_EnumObjects failed: 0x%08lx\n", hres
);
2656 ok(enm
!= NULL
, "Didn't get an enumerator\n");
2658 IEnumIDList_Release(enm
);
2660 IShellFolder_Release(folder
);
2663 static BOOL
write_inifile(LPCWSTR filename
)
2668 static const char data
[] =
2671 "AnotherKey=asdf\r\n";
2673 file
= CreateFileW(filename
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
2674 if(file
== INVALID_HANDLE_VALUE
) {
2675 win_skip("failed to create ini file at %s\n", wine_dbgstr_w(filename
));
2679 WriteFile(file
, data
, sizeof(data
), &written
, NULL
);
2686 #define verify_inifile(f, e) r_verify_inifile(__LINE__, f, e)
2687 static void r_verify_inifile(unsigned l
, LPCWSTR filename
, LPCSTR exp
)
2693 file
= CreateFileW(filename
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, 0, NULL
);
2695 if(file
== INVALID_HANDLE_VALUE
)
2698 ReadFile(file
, buf
, sizeof(buf
) * sizeof(CHAR
), &read
, NULL
);
2703 ok_(__FILE__
,l
)(!strcmp(buf
, exp
), "Expected:\n%s\nGot:\n%s\n", exp
,
2707 static void test_SHGetIniString(void)
2710 WCHAR out
[64] = {0};
2712 static const WCHAR TestAppW
[] = {'T','e','s','t','A','p','p',0};
2713 static const WCHAR AKeyW
[] = {'A','K','e','y',0};
2714 static const WCHAR AnotherKeyW
[] = {'A','n','o','t','h','e','r','K','e','y',0};
2715 static const WCHAR JunkKeyW
[] = {'J','u','n','k','K','e','y',0};
2716 static const WCHAR testpathW
[] = {'C',':','\\','t','e','s','t','.','i','n','i',0};
2717 WCHAR pathW
[MAX_PATH
];
2719 lstrcpyW(pathW
, testpathW
);
2721 if (!write_inifile(pathW
))
2725 /* these crash on Windows */
2726 pSHGetIniStringW(NULL
, NULL
, NULL
, 0, NULL
);
2727 pSHGetIniStringW(NULL
, AKeyW
, out
, ARRAY_SIZE(out
), pathW
);
2728 pSHGetIniStringW(TestAppW
, AKeyW
, NULL
, ARRAY_SIZE(out
), pathW
);
2731 ret
= pSHGetIniStringW(TestAppW
, AKeyW
, out
, 0, pathW
);
2732 ok(ret
== 0, "SHGetIniStringW should have given 0, instead: %ld\n", ret
);
2734 /* valid arguments */
2736 SetLastError(0xdeadbeef);
2737 ret
= pSHGetIniStringW(TestAppW
, NULL
, out
, ARRAY_SIZE(out
), pathW
);
2738 ok(ret
== 4, "SHGetIniStringW should have given 4, instead: %ld\n", ret
);
2739 ok(!lstrcmpW(out
, AKeyW
), "Expected %s, got: %s, %ld\n",
2740 wine_dbgstr_w(AKeyW
), wine_dbgstr_w(out
), GetLastError());
2742 ret
= pSHGetIniStringW(TestAppW
, AKeyW
, out
, ARRAY_SIZE(out
), pathW
);
2743 ok(ret
== 1, "SHGetIniStringW should have given 1, instead: %ld\n", ret
);
2744 ok(!lstrcmpW(out
, L
"1"), "Expected L\"1\", got: %s\n", wine_dbgstr_w(out
));
2746 ret
= pSHGetIniStringW(TestAppW
, AnotherKeyW
, out
, ARRAY_SIZE(out
), pathW
);
2747 ok(ret
== 4, "SHGetIniStringW should have given 4, instead: %ld\n", ret
);
2748 ok(!lstrcmpW(out
, L
"asdf"), "Expected L\"asdf\", got: %s\n", wine_dbgstr_w(out
));
2751 ret
= pSHGetIniStringW(TestAppW
, JunkKeyW
, out
, ARRAY_SIZE(out
), pathW
);
2752 ok(ret
== 0, "SHGetIniStringW should have given 0, instead: %ld\n", ret
);
2753 ok(*out
== 0, "Expected L\"\", got: %s\n", wine_dbgstr_w(out
));
2758 static void test_SHSetIniString(void)
2762 static const WCHAR TestAppW
[] = {'T','e','s','t','A','p','p',0};
2763 static const WCHAR AnotherAppW
[] = {'A','n','o','t','h','e','r','A','p','p',0};
2764 static const WCHAR TestIniW
[] = {'C',':','\\','t','e','s','t','.','i','n','i',0};
2765 static const WCHAR AKeyW
[] = {'A','K','e','y',0};
2766 static const WCHAR NewKeyW
[] = {'N','e','w','K','e','y',0};
2767 static const WCHAR AValueW
[] = {'A','V','a','l','u','e',0};
2769 if (!write_inifile(TestIniW
))
2772 ret
= pSHSetIniStringW(TestAppW
, AKeyW
, AValueW
, TestIniW
);
2773 ok(ret
== TRUE
, "SHSetIniStringW should not have failed\n");
2774 todo_wine
/* wine sticks an extra \r\n at the end of the file */
2775 verify_inifile(TestIniW
, "[TestApp]\r\nAKey=AValue\r\nAnotherKey=asdf\r\n");
2777 ret
= pSHSetIniStringW(TestAppW
, AKeyW
, NULL
, TestIniW
);
2778 ok(ret
== TRUE
, "SHSetIniStringW should not have failed\n");
2779 verify_inifile(TestIniW
, "[TestApp]\r\nAnotherKey=asdf\r\n");
2781 ret
= pSHSetIniStringW(AnotherAppW
, NewKeyW
, AValueW
, TestIniW
);
2782 ok(ret
== TRUE
, "SHSetIniStringW should not have failed\n");
2783 verify_inifile(TestIniW
, "[TestApp]\r\nAnotherKey=asdf\r\n[AnotherApp]\r\nNewKey=AValue\r\n");
2785 ret
= pSHSetIniStringW(TestAppW
, NULL
, AValueW
, TestIniW
);
2786 ok(ret
== TRUE
, "SHSetIniStringW should not have failed\n");
2787 verify_inifile(TestIniW
, "[AnotherApp]\r\nNewKey=AValue\r\n");
2789 DeleteFileW(TestIniW
);
2792 enum _shellkey_flags
{
2793 SHKEY_Root_HKCU
= 0x1,
2794 SHKEY_Root_HKLM
= 0x2,
2795 SHKEY_Key_Explorer
= 0x00,
2796 SHKEY_Key_Shell
= 0x10,
2797 SHKEY_Key_ShellNoRoam
= 0x20,
2798 SHKEY_Key_Classes
= 0x30,
2799 SHKEY_Subkey_Default
= 0x0000,
2800 SHKEY_Subkey_ResourceName
= 0x1000,
2801 SHKEY_Subkey_Handlers
= 0x2000,
2802 SHKEY_Subkey_Associations
= 0x3000,
2803 SHKEY_Subkey_Volatile
= 0x4000,
2804 SHKEY_Subkey_MUICache
= 0x5000,
2805 SHKEY_Subkey_FileExts
= 0x6000
2808 static void test_SHGetShellKey(void)
2810 static const WCHAR ShellFoldersW
[] = { 'S','h','e','l','l',' ','F','o','l','d','e','r','s',0 };
2811 static const WCHAR WineTestW
[] = { 'W','i','n','e','T','e','s','t',0 };
2813 DWORD
*alloc_data
, data
, size
;
2817 /* Vista+ limits SHKEY enumeration values */
2818 SetLastError(0xdeadbeef);
2819 hkey
= pSHGetShellKey(SHKEY_Key_Explorer
, ShellFoldersW
, FALSE
);
2822 /* Tests not working on Vista+ */
2825 hkey
= pSHGetShellKey(SHKEY_Root_HKLM
|SHKEY_Key_Classes
, NULL
, FALSE
);
2826 ok(hkey
!= NULL
, "hkey = NULL\n");
2830 hkey
= pSHGetShellKey(SHKEY_Root_HKCU
|SHKEY_Key_Explorer
, ShellFoldersW
, FALSE
);
2831 ok(hkey
!= NULL
, "hkey = NULL\n");
2834 hkey
= pSHGetShellKey(SHKEY_Root_HKLM
|SHKEY_Key_Explorer
, ShellFoldersW
, FALSE
);
2835 ok(hkey
!= NULL
, "hkey = NULL\n");
2838 hkey
= pSHGetShellKey(SHKEY_Root_HKLM
, WineTestW
, FALSE
);
2839 ok(hkey
== NULL
, "hkey != NULL\n");
2841 hkey
= pSHGetShellKey(SHKEY_Root_HKLM
, NULL
, FALSE
);
2842 ok(hkey
!= NULL
, "Can't open key\n");
2843 ok(SUCCEEDED(RegDeleteKeyW(hkey
, WineTestW
)), "Can't delete key\n");
2846 hkey
= pSHGetShellKey(SHKEY_Root_HKLM
, WineTestW
, TRUE
);
2847 if (!hkey
&& GetLastError() == ERROR_ACCESS_DENIED
)
2849 skip("Not authorized to create keys\n");
2852 ok(hkey
!= NULL
, "Can't create key\n");
2855 size
= sizeof(data
);
2856 hres
= pSKGetValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
, NULL
, &data
, &size
);
2857 ok(hres
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), "hres = %lx\n", hres
);
2860 hres
= pSKSetValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
, REG_DWORD
, &data
, sizeof(DWORD
));
2861 ok(hres
== S_OK
, "hres = %lx\n", hres
);
2864 hres
= pSKGetValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
, NULL
, NULL
, &size
);
2865 ok(hres
== S_OK
, "hres = %lx\n", hres
);
2866 ok(size
== sizeof(DWORD
), "size = %ld\n", size
);
2869 hres
= pSKGetValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
, NULL
, &data
, &size
);
2870 ok(hres
== S_OK
, "hres = %lx\n", hres
);
2871 ok(size
== sizeof(DWORD
), "size = %ld\n", size
);
2872 ok(data
== 1234, "data = %ld\n", data
);
2874 hres
= pSKAllocValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
, NULL
, (void**)&alloc_data
, &size
);
2875 ok(hres
== S_OK
, "hres= %lx\n", hres
);
2876 ok(size
== sizeof(DWORD
), "size = %ld\n", size
);
2877 if (SUCCEEDED(hres
))
2879 ok(*alloc_data
== 1234, "*alloc_data = %ld\n", *alloc_data
);
2880 LocalFree(alloc_data
);
2883 hres
= pSKDeleteValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
);
2884 ok(hres
== S_OK
, "hres = %lx\n", hres
);
2886 hres
= pSKDeleteValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
);
2887 ok(hres
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), "hres = %lx\n", hres
);
2889 hres
= pSKGetValueW(SHKEY_Root_HKLM
, WineTestW
, NULL
, NULL
, &data
, &size
);
2890 ok(hres
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), "hres = %lx\n", hres
);
2892 hkey
= pSHGetShellKey(SHKEY_Root_HKLM
, NULL
, FALSE
);
2893 ok(hkey
!= NULL
, "Can't create key\n");
2894 ok(SUCCEEDED(RegDeleteKeyW(hkey
, WineTestW
)), "Can't delete key\n");
2898 static void init_pointers(void)
2900 #define MAKEFUNC(f, ord) (p##f = (void*)GetProcAddress(hShlwapi, (LPSTR)(ord)))
2901 MAKEFUNC(SHAllocShared
, 7);
2902 MAKEFUNC(SHLockShared
, 8);
2903 MAKEFUNC(SHUnlockShared
, 9);
2904 MAKEFUNC(SHFreeShared
, 10);
2905 MAKEFUNC(SHMapHandle
, 11);
2906 MAKEFUNC(GetAcceptLanguagesA
, 14);
2907 MAKEFUNC(SHSetWindowBits
, 165);
2908 MAKEFUNC(SHSetParentHwnd
, 167);
2909 MAKEFUNC(ConnectToConnectionPoint
, 168);
2910 MAKEFUNC(IUnknown_GetClassID
, 175);
2911 MAKEFUNC(SHSearchMapInt
, 198);
2912 MAKEFUNC(SHCreateWorkerWindowA
, 257);
2913 MAKEFUNC(GUIDFromStringA
, 269);
2914 MAKEFUNC(SHPackDispParams
, 282);
2915 MAKEFUNC(IConnectionPoint_InvokeWithCancel
, 283);
2916 MAKEFUNC(IConnectionPoint_SimpleInvoke
, 284);
2917 MAKEFUNC(SHGetIniStringW
, 294);
2918 MAKEFUNC(SHSetIniStringW
, 295);
2919 MAKEFUNC(SHFormatDateTimeA
, 353);
2920 MAKEFUNC(SHFormatDateTimeW
, 354);
2921 MAKEFUNC(SHIShellFolder_EnumObjects
, 404);
2922 MAKEFUNC(GetShellSecurityDescriptor
, 475);
2923 MAKEFUNC(SHGetObjectCompatFlags
, 476);
2924 MAKEFUNC(IUnknown_QueryServiceExec
, 484);
2925 MAKEFUNC(SHGetShellKey
, 491);
2926 MAKEFUNC(SHPropertyBag_ReadLONG
, 496);
2927 MAKEFUNC(IUnknown_ProfferService
, 514);
2928 MAKEFUNC(SKGetValueW
, 516);
2929 MAKEFUNC(SKSetValueW
, 517);
2930 MAKEFUNC(SKDeleteValueW
, 518);
2931 MAKEFUNC(SKAllocValueW
, 519);
2934 pDllGetVersion
= (void*)GetProcAddress(hShlwapi
, "DllGetVersion");
2937 static void test_SHSetParentHwnd(void)
2939 HWND hwnd
, hwnd2
, ret
;
2942 hwnd
= CreateWindowA("Button", "", WS_VISIBLE
, 0, 0, 10, 10, NULL
, NULL
, NULL
, NULL
);
2943 ok(hwnd
!= NULL
, "got %p\n", hwnd
);
2945 hwnd2
= CreateWindowA("Button", "", WS_VISIBLE
| WS_CHILD
, 0, 0, 10, 10, hwnd
, NULL
, NULL
, NULL
);
2946 ok(hwnd2
!= NULL
, "got %p\n", hwnd2
);
2949 ret
= pSHSetParentHwnd(NULL
, NULL
);
2950 ok(ret
== NULL
, "got %p\n", ret
);
2952 /* set to no parent while already no parent present */
2953 ret
= GetParent(hwnd
);
2954 ok(ret
== NULL
, "got %p\n", ret
);
2955 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
2956 ok((style
& (WS_POPUP
|WS_CHILD
)) == 0, "got style 0x%08lx\n", style
);
2957 ret
= pSHSetParentHwnd(hwnd
, NULL
);
2958 ok(ret
== NULL
, "got %p\n", ret
);
2959 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
2960 ok((style
& (WS_POPUP
|WS_CHILD
)) == 0, "got style 0x%08lx\n", style
);
2962 /* reset to null parent from not null */
2963 ret
= GetParent(hwnd2
);
2964 ok(ret
== hwnd
, "got %p\n", ret
);
2965 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
2966 ok((style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
, "got style 0x%08lx\n", style
);
2967 ret
= pSHSetParentHwnd(hwnd2
, NULL
);
2968 ok(ret
== NULL
, "got %p\n", ret
);
2969 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
2970 ok((style
& (WS_POPUP
|WS_CHILD
)) == WS_POPUP
, "got style 0x%08lx\n", style
);
2971 ret
= GetParent(hwnd2
);
2972 ok(ret
== NULL
, "got %p\n", ret
);
2974 /* set parent back */
2975 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
2976 SetWindowLongA(hwnd2
, GWL_STYLE
, style
& ~(WS_CHILD
|WS_POPUP
));
2977 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
2978 ok((style
& (WS_CHILD
|WS_POPUP
)) == 0, "got 0x%08lx\n", style
);
2980 ret
= pSHSetParentHwnd(hwnd2
, hwnd
);
2981 todo_wine
ok(ret
== NULL
, "got %p\n", ret
);
2983 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
2984 ok((style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
, "got style 0x%08lx\n", style
);
2985 ret
= GetParent(hwnd2
);
2986 ok(ret
== hwnd
, "got %p\n", ret
);
2988 /* try to set same parent again */
2990 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
2991 SetWindowLongA(hwnd2
, GWL_STYLE
, style
| WS_POPUP
);
2992 ret
= pSHSetParentHwnd(hwnd2
, hwnd
);
2993 todo_wine
ok(ret
== NULL
, "got %p\n", ret
);
2994 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
2995 ok((style
& (WS_CHILD
|WS_POPUP
)) == WS_CHILD
, "got 0x%08lx\n", style
);
2996 ret
= GetParent(hwnd2
);
2997 ok(ret
== hwnd
, "got %p\n", ret
);
2999 /* without WS_POPUP */
3000 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
3001 SetWindowLongA(hwnd2
, GWL_STYLE
, style
| ~WS_POPUP
);
3002 ret
= pSHSetParentHwnd(hwnd2
, hwnd
);
3003 todo_wine
ok(ret
== hwnd
, "got %p\n", ret
);
3004 style
= GetWindowLongA(hwnd2
, GWL_STYLE
);
3005 ok((style
& (WS_CHILD
|WS_POPUP
)) == WS_CHILD
, "got 0x%08lx\n", style
);
3006 ret
= GetParent(hwnd2
);
3007 ok(ret
== hwnd
, "got %p\n", ret
);
3009 DestroyWindow(hwnd
);
3010 DestroyWindow(hwnd2
);
3013 static HRESULT WINAPI
testpersist_QI(IPersist
*iface
, REFIID riid
, void **obj
)
3015 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IPersist
)) {
3017 IPersist_AddRef(iface
);
3022 return E_NOINTERFACE
;
3025 static HRESULT WINAPI
testpersist_QI2(IPersist
*iface
, REFIID riid
, void **obj
)
3027 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IPersistFolder
)) {
3029 IPersist_AddRef(iface
);
3034 return E_NOINTERFACE
;
3037 static ULONG WINAPI
testpersist_AddRef(IPersist
*iface
)
3042 static ULONG WINAPI
testpersist_Release(IPersist
*iface
)
3047 static HRESULT WINAPI
testpersist_GetClassID(IPersist
*iface
, CLSID
*clsid
)
3049 memset(clsid
, 0xab, sizeof(*clsid
));
3053 static IPersistVtbl testpersistvtbl
= {
3056 testpersist_Release
,
3057 testpersist_GetClassID
3060 static IPersistVtbl testpersist2vtbl
= {
3063 testpersist_Release
,
3064 testpersist_GetClassID
3067 static IPersist testpersist
= { &testpersistvtbl
};
3068 static IPersist testpersist2
= { &testpersist2vtbl
};
3070 static void test_IUnknown_GetClassID(void)
3072 CLSID clsid
, clsid2
, clsid3
;
3075 if (0) /* crashes on native systems */
3076 hr
= pIUnknown_GetClassID(NULL
, NULL
);
3078 memset(&clsid
, 0xcc, sizeof(clsid
));
3079 memset(&clsid3
, 0xcc, sizeof(clsid3
));
3080 hr
= pIUnknown_GetClassID(NULL
, &clsid
);
3081 ok(hr
== E_FAIL
, "got 0x%08lx\n", hr
);
3082 ok(IsEqualCLSID(&clsid
, &CLSID_NULL
) || broken(IsEqualCLSID(&clsid
, &clsid3
)) /* win2k, winxp, win2k3 */,
3083 "got wrong clsid %s\n", wine_dbgstr_guid(&clsid
));
3085 memset(&clsid
, 0xcc, sizeof(clsid
));
3086 memset(&clsid2
, 0xab, sizeof(clsid2
));
3087 hr
= pIUnknown_GetClassID((IUnknown
*)&testpersist
, &clsid
);
3088 ok(hr
== 0x8fff2222, "got 0x%08lx\n", hr
);
3089 ok(IsEqualCLSID(&clsid
, &clsid2
) || broken(IsEqualCLSID(&clsid
, &clsid3
)) /* win2k3 */,
3090 "got wrong clsid %s\n", wine_dbgstr_guid(&clsid
));
3092 /* IPersistFolder is also supported */
3093 memset(&clsid
, 0xcc, sizeof(clsid
));
3094 memset(&clsid2
, 0xab, sizeof(clsid2
));
3095 memset(&clsid3
, 0xcc, sizeof(clsid3
));
3096 hr
= pIUnknown_GetClassID((IUnknown
*)&testpersist2
, &clsid
);
3097 ok(hr
== 0x8fff2222, "got 0x%08lx\n", hr
);
3098 ok(IsEqualCLSID(&clsid
, &clsid2
) || broken(IsEqualCLSID(&clsid
, &clsid3
)) /* win2k3 */,
3099 "got wrong clsid %s\n", wine_dbgstr_guid(&clsid
));
3102 static void test_DllGetVersion(void)
3106 hr
= pDllGetVersion(NULL
);
3107 ok(hr
== E_INVALIDARG
, "got 0x%08lx\n", hr
);
3115 hShlwapi
= GetModuleHandleA("shlwapi.dll");
3119 argc
= winetest_get_mainargs(&argv
);
3124 sscanf(argv
[2], "%ld", &procid
);
3125 sscanf(argv
[3], "%p", &hmem
);
3126 test_alloc_shared_remote(procid
, hmem
);
3130 test_GetAcceptLanguagesA();
3131 test_SHSearchMapInt();
3132 test_alloc_shared(argc
, argv
);
3134 test_GetShellSecurityDescriptor();
3135 test_SHPackDispParams();
3136 test_IConnectionPoint();
3137 test_SHPropertyBag_ReadLONG();
3138 test_SHSetWindowBits();
3139 test_SHFormatDateTimeA();
3140 test_SHFormatDateTimeW();
3141 test_SHGetObjectCompatFlags();
3142 test_IUnknown_QueryServiceExec();
3143 test_IUnknown_ProfferService();
3144 test_SHCreateWorkerWindowA();
3145 test_SHIShellFolder_EnumObjects();
3146 test_SHGetIniString();
3147 test_SHSetIniString();
3148 test_SHGetShellKey();
3149 test_SHSetParentHwnd();
3150 test_IUnknown_GetClassID();
3151 test_DllGetVersion();