advapi32: Make rpcrt4 a delayed import to work around circular dependencies with...
[wine/testsucceed.git] / dlls / shlwapi / tests / ordinal.c
blobcfc25e116c7d35642af46de2c5e55cc3ac5f401e
1 /* Unit test suite for SHLWAPI ordinal functions
3 * Copyright 2004 Jon Griffiths
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include <stdio.h>
22 #define COBJMACROS
23 #include "wine/test.h"
24 #include "winbase.h"
25 #include "winerror.h"
26 #include "winuser.h"
27 #include "ole2.h"
28 #include "oaidl.h"
29 #include "ocidl.h"
30 #include "mlang.h"
31 #include "shlwapi.h"
32 #include "docobj.h"
33 #include "shobjidl.h"
35 /* Function ptrs for ordinal calls */
36 static HMODULE hShlwapi;
37 static BOOL is_win2k_and_lower;
39 static int (WINAPI *pSHSearchMapInt)(const int*,const int*,int,int);
40 static HRESULT (WINAPI *pGetAcceptLanguagesA)(LPSTR,LPDWORD);
42 static HANDLE (WINAPI *pSHAllocShared)(LPCVOID,DWORD,DWORD);
43 static LPVOID (WINAPI *pSHLockShared)(HANDLE,DWORD);
44 static BOOL (WINAPI *pSHUnlockShared)(LPVOID);
45 static BOOL (WINAPI *pSHFreeShared)(HANDLE,DWORD);
46 static HRESULT(WINAPIV *pSHPackDispParams)(DISPPARAMS*,VARIANTARG*,UINT,...);
47 static HRESULT(WINAPI *pIConnectionPoint_SimpleInvoke)(IConnectionPoint*,DISPID,DISPPARAMS*);
48 static HRESULT(WINAPI *pIConnectionPoint_InvokeWithCancel)(IConnectionPoint*,DISPID,DISPPARAMS*,DWORD,DWORD);
49 static HRESULT(WINAPI *pConnectToConnectionPoint)(IUnknown*,REFIID,BOOL,IUnknown*, LPDWORD,IConnectionPoint **);
50 static HRESULT(WINAPI *pSHPropertyBag_ReadLONG)(IPropertyBag *,LPCWSTR,LPLONG);
51 static LONG (WINAPI *pSHSetWindowBits)(HWND, INT, UINT, UINT);
52 static INT (WINAPI *pSHFormatDateTimeA)(const FILETIME UNALIGNED*, DWORD*, LPSTR, UINT);
53 static INT (WINAPI *pSHFormatDateTimeW)(const FILETIME UNALIGNED*, DWORD*, LPWSTR, UINT);
54 static DWORD (WINAPI *pSHGetObjectCompatFlags)(IUnknown*, const CLSID*);
55 static BOOL (WINAPI *pGUIDFromStringA)(LPSTR, CLSID *);
56 static HRESULT (WINAPI *pIUnknown_QueryServiceExec)(IUnknown*, REFIID, const GUID*, DWORD, DWORD, VARIANT*, VARIANT*);
57 static HRESULT (WINAPI *pIUnknown_ProfferService)(IUnknown*, REFGUID, IServiceProvider*, DWORD*);
58 static HWND (WINAPI *pSHCreateWorkerWindowA)(LONG, HWND, DWORD, DWORD, HMENU, LONG_PTR);
60 static HMODULE hmlang;
61 static HRESULT (WINAPI *pLcidToRfc1766A)(LCID, LPSTR, INT);
63 static const CHAR ie_international[] = {
64 'S','o','f','t','w','a','r','e','\\',
65 'M','i','c','r','o','s','o','f','t','\\',
66 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
67 'I','n','t','e','r','n','a','t','i','o','n','a','l',0};
68 static const CHAR acceptlanguage[] = {
69 'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0};
71 typedef struct {
72 int id;
73 const void *args[5];
74 } call_entry_t;
76 typedef struct {
77 call_entry_t *calls;
78 int count;
79 int alloc;
80 } call_trace_t;
82 static void init_call_trace(call_trace_t *ctrace)
84 ctrace->alloc = 10;
85 ctrace->count = 0;
86 ctrace->calls = HeapAlloc(GetProcessHeap(), 0, sizeof(call_entry_t) * ctrace->alloc);
89 static void free_call_trace(const call_trace_t *ctrace)
91 HeapFree(GetProcessHeap(), 0, ctrace->calls);
94 static void add_call(call_trace_t *ctrace, int id, const void *arg0,
95 const void *arg1, const void *arg2, const void *arg3, const void *arg4)
97 call_entry_t call;
99 call.id = id;
100 call.args[0] = arg0;
101 call.args[1] = arg1;
102 call.args[2] = arg2;
103 call.args[3] = arg3;
104 call.args[4] = arg4;
106 if (ctrace->count == ctrace->alloc)
108 ctrace->alloc *= 2;
109 ctrace->calls = HeapReAlloc(GetProcessHeap(),0, ctrace->calls, ctrace->alloc*sizeof(call_entry_t));
112 ctrace->calls[ctrace->count++] = call;
115 static void ok_trace_(call_trace_t *texpected, call_trace_t *tgot, int line)
117 if (texpected->count == tgot->count)
119 INT i;
120 /* compare */
121 for (i = 0; i < texpected->count; i++)
123 call_entry_t *expected = &texpected->calls[i];
124 call_entry_t *got = &tgot->calls[i];
125 INT j;
127 ok_(__FILE__, line)(expected->id == got->id, "got different ids %d: %d, %d\n", i+1, expected->id, got->id);
129 for (j = 0; j < 5; j++)
131 ok_(__FILE__, line)(expected->args[j] == got->args[j], "got different args[%d] for %d: %p, %p\n", j, i+1,
132 expected->args[j], got->args[j]);
136 else
137 ok_(__FILE__, line)(0, "traces length mismatch\n");
140 #define ok_trace(a, b) ok_trace_(a, b, __LINE__)
142 /* trace of actually made calls */
143 static call_trace_t trace_got;
145 static void test_GetAcceptLanguagesA(void)
147 static LPCSTR table[] = {"de,en-gb;q=0.7,en;q=0.3",
148 "de,en;q=0.3,en-gb;q=0.7", /* sorting is ignored */
149 "winetest", /* content is ignored */
150 "de-de,de;q=0.5",
151 "de",
152 NULL};
154 DWORD exactsize;
155 char original[512];
156 char language[32];
157 char buffer[64];
158 HKEY hroot = NULL;
159 LONG res_query = ERROR_SUCCESS;
160 LONG lres;
161 HRESULT hr;
162 DWORD maxlen = sizeof(buffer) - 2;
163 DWORD len;
164 LCID lcid;
165 LPCSTR entry;
166 INT i = 0;
168 if (!pGetAcceptLanguagesA) {
169 win_skip("GetAcceptLanguagesA is not available\n");
170 return;
173 lcid = GetUserDefaultLCID();
175 /* Get the original Value */
176 lres = RegOpenKeyA(HKEY_CURRENT_USER, ie_international, &hroot);
177 if (lres) {
178 skip("RegOpenKey(%s) failed: %d\n", ie_international, lres);
179 return;
181 len = sizeof(original);
182 original[0] = 0;
183 res_query = RegQueryValueExA(hroot, acceptlanguage, 0, NULL, (PBYTE)original, &len);
185 RegDeleteValue(hroot, acceptlanguage);
187 /* Some windows versions use "lang-COUNTRY" as default */
188 memset(language, 0, sizeof(language));
189 len = GetLocaleInfoA(lcid, LOCALE_SISO639LANGNAME, language, sizeof(language));
191 if (len) {
192 lstrcat(language, "-");
193 memset(buffer, 0, sizeof(buffer));
194 len = GetLocaleInfoA(lcid, LOCALE_SISO3166CTRYNAME, buffer, sizeof(buffer) - len - 1);
195 lstrcat(language, buffer);
197 else
199 /* LOCALE_SNAME has additional parts in some languages. Try only as last chance */
200 memset(language, 0, sizeof(language));
201 len = GetLocaleInfoA(lcid, LOCALE_SNAME, language, sizeof(language));
204 /* get the default value */
205 len = maxlen;
206 memset(buffer, '#', maxlen);
207 buffer[maxlen] = 0;
208 hr = pGetAcceptLanguagesA( buffer, &len);
210 if (hr != S_OK) {
211 win_skip("GetAcceptLanguagesA failed with 0x%x\n", hr);
212 goto restore_original;
215 if (lstrcmpA(buffer, language)) {
216 /* some windows versions use "lang" or "lang-country" as default */
217 language[0] = 0;
218 if (pLcidToRfc1766A) {
219 hr = pLcidToRfc1766A(lcid, language, sizeof(language));
220 ok(hr == S_OK, "LcidToRfc1766A returned 0x%x and %s\n", hr, language);
224 ok(!lstrcmpA(buffer, language),
225 "have '%s' (searching for '%s')\n", language, buffer);
227 if (lstrcmpA(buffer, language)) {
228 win_skip("no more ideas, how to build the default language '%s'\n", buffer);
229 goto restore_original;
232 trace("detected default: %s\n", language);
233 while ((entry = table[i])) {
235 exactsize = lstrlenA(entry);
237 lres = RegSetValueExA(hroot, acceptlanguage, 0, REG_SZ, (const BYTE *) entry, exactsize + 1);
238 ok(!lres, "got %d for RegSetValueExA: %s\n", lres, entry);
240 /* len includes space for the terminating 0 before vista/w2k8 */
241 len = exactsize + 2;
242 memset(buffer, '#', maxlen);
243 buffer[maxlen] = 0;
244 hr = pGetAcceptLanguagesA( buffer, &len);
245 ok(((hr == E_INVALIDARG) && (len == 0)) ||
246 (SUCCEEDED(hr) &&
247 ((len == exactsize) || (len == exactsize+1)) &&
248 !lstrcmpA(buffer, entry)),
249 "+2_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
251 len = exactsize + 1;
252 memset(buffer, '#', maxlen);
253 buffer[maxlen] = 0;
254 hr = pGetAcceptLanguagesA( buffer, &len);
255 ok(((hr == E_INVALIDARG) && (len == 0)) ||
256 (SUCCEEDED(hr) &&
257 ((len == exactsize) || (len == exactsize+1)) &&
258 !lstrcmpA(buffer, entry)),
259 "+1_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
261 len = exactsize;
262 memset(buffer, '#', maxlen);
263 buffer[maxlen] = 0;
264 hr = pGetAcceptLanguagesA( buffer, &len);
266 /* There is no space for the string in the registry.
267 When the buffer is large enough, the default language is returned
269 When the buffer is too small for that fallback, win7_32 and w2k8_64
270 and above fail with HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), but
271 recent os succeed and return a partial result while
272 older os succeed and overflow the buffer */
274 ok(((hr == E_INVALIDARG) && (len == 0)) ||
275 (((hr == S_OK) && !lstrcmpA(buffer, language) && (len == lstrlenA(language))) ||
276 ((hr == S_OK) && !memcmp(buffer, language, len)) ||
277 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len)),
278 "==_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
280 if (exactsize > 1) {
281 len = exactsize - 1;
282 memset(buffer, '#', maxlen);
283 buffer[maxlen] = 0;
284 hr = pGetAcceptLanguagesA( buffer, &len);
285 ok(((hr == E_INVALIDARG) && (len == 0)) ||
286 (((hr == S_OK) && !lstrcmpA(buffer, language) && (len == lstrlenA(language))) ||
287 ((hr == S_OK) && !memcmp(buffer, language, len)) ||
288 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len)),
289 "-1_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
292 len = 1;
293 memset(buffer, '#', maxlen);
294 buffer[maxlen] = 0;
295 hr = pGetAcceptLanguagesA( buffer, &len);
296 ok(((hr == E_INVALIDARG) && (len == 0)) ||
297 (((hr == S_OK) && !lstrcmpA(buffer, language) && (len == lstrlenA(language))) ||
298 ((hr == S_OK) && !memcmp(buffer, language, len)) ||
299 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len)),
300 "=1_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
302 len = maxlen;
303 hr = pGetAcceptLanguagesA( NULL, &len);
305 /* w2k3 and below: E_FAIL and untouched len,
306 since w2k8: S_OK and needed size (excluding 0) */
307 ok( ((hr == S_OK) && (len == exactsize)) ||
308 ((hr == E_FAIL) && (len == maxlen)),
309 "NULL,max #%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
311 i++;
314 /* without a value in the registry, a default language is returned */
315 RegDeleteValue(hroot, acceptlanguage);
317 len = maxlen;
318 memset(buffer, '#', maxlen);
319 buffer[maxlen] = 0;
320 hr = pGetAcceptLanguagesA( buffer, &len);
321 ok( ((hr == S_OK) && (len == lstrlenA(language))),
322 "max: got 0x%x with %d and %s (expected S_OK with %d and '%s'\n",
323 hr, len, buffer, lstrlenA(language), language);
325 len = 2;
326 memset(buffer, '#', maxlen);
327 buffer[maxlen] = 0;
328 hr = pGetAcceptLanguagesA( buffer, &len);
329 ok( (((hr == S_OK) || (hr == E_INVALIDARG)) && !memcmp(buffer, language, len)) ||
330 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len),
331 "=2: got 0x%x with %d and %s\n", hr, len, buffer);
333 len = 1;
334 memset(buffer, '#', maxlen);
335 buffer[maxlen] = 0;
336 hr = pGetAcceptLanguagesA( buffer, &len);
337 /* When the buffer is too small, win7_32 and w2k8_64 and above fail with
338 HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), other versions suceed
339 and return a partial 0 terminated result while other versions
340 fail with E_INVALIDARG and return a partial unterminated result */
341 ok( (((hr == S_OK) || (hr == E_INVALIDARG)) && !memcmp(buffer, language, len)) ||
342 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len),
343 "=1: got 0x%x with %d and %s\n", hr, len, buffer);
345 len = 0;
346 memset(buffer, '#', maxlen);
347 buffer[maxlen] = 0;
348 hr = pGetAcceptLanguagesA( buffer, &len);
349 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
350 ok((hr == E_FAIL) || (hr == E_INVALIDARG),
351 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr);
353 memset(buffer, '#', maxlen);
354 buffer[maxlen] = 0;
355 hr = pGetAcceptLanguagesA( buffer, NULL);
356 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
357 ok((hr == E_FAIL) || (hr == E_INVALIDARG),
358 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr);
361 hr = pGetAcceptLanguagesA( NULL, NULL);
362 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
363 ok((hr == E_FAIL) || (hr == E_INVALIDARG),
364 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr);
366 restore_original:
367 if (!res_query) {
368 len = lstrlenA(original);
369 lres = RegSetValueExA(hroot, acceptlanguage, 0, REG_SZ, (const BYTE *) original, len ? len + 1: 0);
370 ok(!lres, "RegSetValueEx(%s) failed: %d\n", original, lres);
372 else
374 RegDeleteValue(hroot, acceptlanguage);
376 RegCloseKey(hroot);
379 static void test_SHSearchMapInt(void)
381 int keys[8], values[8];
382 int i = 0;
384 if (!pSHSearchMapInt)
385 return;
387 memset(keys, 0, sizeof(keys));
388 memset(values, 0, sizeof(values));
389 keys[0] = 99; values[0] = 101;
391 /* NULL key/value lists crash native, so skip testing them */
393 /* 1 element */
394 i = pSHSearchMapInt(keys, values, 1, keys[0]);
395 ok(i == values[0], "Len 1, expected %d, got %d\n", values[0], i);
397 /* Key doesn't exist */
398 i = pSHSearchMapInt(keys, values, 1, 100);
399 ok(i == -1, "Len 1 - bad key, expected -1, got %d\n", i);
401 /* Len = 0 => not found */
402 i = pSHSearchMapInt(keys, values, 0, keys[0]);
403 ok(i == -1, "Len 1 - passed len 0, expected -1, got %d\n", i);
405 /* 2 elements, len = 1 */
406 keys[1] = 98; values[1] = 102;
407 i = pSHSearchMapInt(keys, values, 1, keys[1]);
408 ok(i == -1, "Len 1 - array len 2, expected -1, got %d\n", i);
410 /* 2 elements, len = 2 */
411 i = pSHSearchMapInt(keys, values, 2, keys[1]);
412 ok(i == values[1], "Len 2, expected %d, got %d\n", values[1], i);
414 /* Searches forward */
415 keys[2] = 99; values[2] = 103;
416 i = pSHSearchMapInt(keys, values, 3, keys[0]);
417 ok(i == values[0], "Len 3, expected %d, got %d\n", values[0], i);
420 static void test_alloc_shared(void)
422 DWORD procid;
423 HANDLE hmem;
424 int val;
425 int* p;
426 BOOL ret;
428 procid=GetCurrentProcessId();
429 hmem=pSHAllocShared(NULL,10,procid);
430 ok(hmem!=NULL,"SHAllocShared(NULL...) failed: %u\n", GetLastError());
431 ret = pSHFreeShared(hmem, procid);
432 ok( ret, "SHFreeShared failed: %u\n", GetLastError());
434 val=0x12345678;
435 hmem=pSHAllocShared(&val,4,procid);
436 ok(hmem!=NULL,"SHAllocShared(NULL...) failed: %u\n", GetLastError());
438 p=pSHLockShared(hmem,procid);
439 ok(p!=NULL,"SHLockShared failed: %u\n", GetLastError());
440 if (p!=NULL)
441 ok(*p==val,"Wrong value in shared memory: %d instead of %d\n",*p,val);
442 ret = pSHUnlockShared(p);
443 ok( ret, "SHUnlockShared failed: %u\n", GetLastError());
445 ret = pSHFreeShared(hmem, procid);
446 ok( ret, "SHFreeShared failed: %u\n", GetLastError());
449 static void test_fdsa(void)
451 typedef struct
453 DWORD num_items; /* Number of elements inserted */
454 void *mem; /* Ptr to array */
455 DWORD blocks_alloced; /* Number of elements allocated */
456 BYTE inc; /* Number of elements to grow by when we need to expand */
457 BYTE block_size; /* Size in bytes of an element */
458 BYTE flags; /* Flags */
459 } FDSA_info;
461 BOOL (WINAPI *pFDSA_Initialize)(DWORD block_size, DWORD inc, FDSA_info *info, void *mem,
462 DWORD init_blocks);
463 BOOL (WINAPI *pFDSA_Destroy)(FDSA_info *info);
464 DWORD (WINAPI *pFDSA_InsertItem)(FDSA_info *info, DWORD where, const void *block);
465 BOOL (WINAPI *pFDSA_DeleteItem)(FDSA_info *info, DWORD where);
467 FDSA_info info;
468 int block_size = 10, init_blocks = 4, inc = 2;
469 DWORD ret;
470 char *mem;
472 pFDSA_Initialize = (void *)GetProcAddress(hShlwapi, (LPSTR)208);
473 pFDSA_Destroy = (void *)GetProcAddress(hShlwapi, (LPSTR)209);
474 pFDSA_InsertItem = (void *)GetProcAddress(hShlwapi, (LPSTR)210);
475 pFDSA_DeleteItem = (void *)GetProcAddress(hShlwapi, (LPSTR)211);
477 mem = HeapAlloc(GetProcessHeap(), 0, block_size * init_blocks);
478 memset(&info, 0, sizeof(info));
480 ok(pFDSA_Initialize(block_size, inc, &info, mem, init_blocks), "FDSA_Initialize rets FALSE\n");
481 ok(info.num_items == 0, "num_items = %d\n", info.num_items);
482 ok(info.mem == mem, "mem = %p\n", info.mem);
483 ok(info.blocks_alloced == init_blocks, "blocks_alloced = %d\n", info.blocks_alloced);
484 ok(info.inc == inc, "inc = %d\n", info.inc);
485 ok(info.block_size == block_size, "block_size = %d\n", info.block_size);
486 ok(info.flags == 0, "flags = %d\n", info.flags);
488 ret = pFDSA_InsertItem(&info, 1234, "1234567890");
489 ok(ret == 0, "ret = %d\n", ret);
490 ok(info.num_items == 1, "num_items = %d\n", info.num_items);
491 ok(info.mem == mem, "mem = %p\n", info.mem);
492 ok(info.blocks_alloced == init_blocks, "blocks_alloced = %d\n", info.blocks_alloced);
493 ok(info.inc == inc, "inc = %d\n", info.inc);
494 ok(info.block_size == block_size, "block_size = %d\n", info.block_size);
495 ok(info.flags == 0, "flags = %d\n", info.flags);
497 ret = pFDSA_InsertItem(&info, 1234, "abcdefghij");
498 ok(ret == 1, "ret = %d\n", ret);
500 ret = pFDSA_InsertItem(&info, 1, "klmnopqrst");
501 ok(ret == 1, "ret = %d\n", ret);
503 ret = pFDSA_InsertItem(&info, 0, "uvwxyzABCD");
504 ok(ret == 0, "ret = %d\n", ret);
505 ok(info.mem == mem, "mem = %p\n", info.mem);
506 ok(info.flags == 0, "flags = %d\n", info.flags);
508 /* This next InsertItem will cause shlwapi to allocate its own mem buffer */
509 ret = pFDSA_InsertItem(&info, 0, "EFGHIJKLMN");
510 ok(ret == 0, "ret = %d\n", ret);
511 ok(info.mem != mem, "mem = %p\n", info.mem);
512 ok(info.blocks_alloced == init_blocks + inc, "blocks_alloced = %d\n", info.blocks_alloced);
513 ok(info.flags == 0x1, "flags = %d\n", info.flags);
515 ok(!memcmp(info.mem, "EFGHIJKLMNuvwxyzABCD1234567890klmnopqrstabcdefghij", 50), "mem %s\n", (char*)info.mem);
517 ok(pFDSA_DeleteItem(&info, 2), "rets FALSE\n");
518 ok(info.mem != mem, "mem = %p\n", info.mem);
519 ok(info.blocks_alloced == init_blocks + inc, "blocks_alloced = %d\n", info.blocks_alloced);
520 ok(info.flags == 0x1, "flags = %d\n", info.flags);
522 ok(!memcmp(info.mem, "EFGHIJKLMNuvwxyzABCDklmnopqrstabcdefghij", 40), "mem %s\n", (char*)info.mem);
524 ok(pFDSA_DeleteItem(&info, 3), "rets FALSE\n");
525 ok(info.mem != mem, "mem = %p\n", info.mem);
526 ok(info.blocks_alloced == init_blocks + inc, "blocks_alloced = %d\n", info.blocks_alloced);
527 ok(info.flags == 0x1, "flags = %d\n", info.flags);
529 ok(!memcmp(info.mem, "EFGHIJKLMNuvwxyzABCDklmnopqrst", 30), "mem %s\n", (char*)info.mem);
531 ok(!pFDSA_DeleteItem(&info, 4), "does not ret FALSE\n");
533 /* As shlwapi has allocated memory internally, Destroy will ret FALSE */
534 ok(!pFDSA_Destroy(&info), "FDSA_Destroy does not ret FALSE\n");
537 /* When Initialize is called with inc = 0, set it to 1 */
538 ok(pFDSA_Initialize(block_size, 0, &info, mem, init_blocks), "FDSA_Initialize rets FALSE\n");
539 ok(info.inc == 1, "inc = %d\n", info.inc);
541 /* This time, because shlwapi hasn't had to allocate memory
542 internally, Destroy rets non-zero */
543 ok(pFDSA_Destroy(&info), "FDSA_Destroy rets FALSE\n");
546 HeapFree(GetProcessHeap(), 0, mem);
550 typedef struct SHELL_USER_SID {
551 SID_IDENTIFIER_AUTHORITY sidAuthority;
552 DWORD dwUserGroupID;
553 DWORD dwUserID;
554 } SHELL_USER_SID, *PSHELL_USER_SID;
555 typedef struct SHELL_USER_PERMISSION {
556 SHELL_USER_SID susID;
557 DWORD dwAccessType;
558 BOOL fInherit;
559 DWORD dwAccessMask;
560 DWORD dwInheritMask;
561 DWORD dwInheritAccessMask;
562 } SHELL_USER_PERMISSION, *PSHELL_USER_PERMISSION;
563 static void test_GetShellSecurityDescriptor(void)
565 SHELL_USER_PERMISSION supCurrentUserFull = {
566 { {SECURITY_NULL_SID_AUTHORITY}, 0, 0 },
567 ACCESS_ALLOWED_ACE_TYPE, FALSE,
568 GENERIC_ALL, 0, 0 };
569 #define MY_INHERITANCE 0xBE /* invalid value to proof behavior */
570 SHELL_USER_PERMISSION supEveryoneDenied = {
571 { {SECURITY_WORLD_SID_AUTHORITY}, SECURITY_WORLD_RID, 0 },
572 ACCESS_DENIED_ACE_TYPE, TRUE,
573 GENERIC_WRITE, MY_INHERITANCE | 0xDEADBA00, GENERIC_READ };
574 PSHELL_USER_PERMISSION rgsup[2] = {
575 &supCurrentUserFull, &supEveryoneDenied,
577 SECURITY_DESCRIPTOR* psd;
578 SECURITY_DESCRIPTOR* (WINAPI*pGetShellSecurityDescriptor)(PSHELL_USER_PERMISSION*,int);
580 pGetShellSecurityDescriptor=(void*)GetProcAddress(hShlwapi,(char*)475);
582 if(!pGetShellSecurityDescriptor)
584 win_skip("GetShellSecurityDescriptor not available\n");
585 return;
588 psd = pGetShellSecurityDescriptor(NULL, 2);
589 ok(psd==NULL ||
590 broken(psd==INVALID_HANDLE_VALUE), /* IE5 */
591 "GetShellSecurityDescriptor should fail\n");
592 psd = pGetShellSecurityDescriptor(rgsup, 0);
593 ok(psd==NULL, "GetShellSecurityDescriptor should fail\n");
595 SetLastError(0xdeadbeef);
596 psd = pGetShellSecurityDescriptor(rgsup, 2);
597 if (psd == NULL && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
599 /* The previous calls to GetShellSecurityDescriptor don't set the last error */
600 win_skip("GetShellSecurityDescriptor is not implemented\n");
601 return;
603 if (psd==INVALID_HANDLE_VALUE)
605 win_skip("GetShellSecurityDescriptor is broken on IE5\n");
606 return;
608 ok(psd!=NULL, "GetShellSecurityDescriptor failed\n");
609 if (psd!=NULL)
611 BOOL bHasDacl = FALSE, bDefaulted;
612 PACL pAcl;
613 DWORD dwRev;
614 SECURITY_DESCRIPTOR_CONTROL control;
616 ok(IsValidSecurityDescriptor(psd), "returned value is not valid SD\n");
618 ok(GetSecurityDescriptorControl(psd, &control, &dwRev),
619 "GetSecurityDescriptorControl failed with error %u\n", GetLastError());
620 ok(0 == (control & SE_SELF_RELATIVE), "SD should be absolute\n");
622 ok(GetSecurityDescriptorDacl(psd, &bHasDacl, &pAcl, &bDefaulted),
623 "GetSecurityDescriptorDacl failed with error %u\n", GetLastError());
625 ok(bHasDacl, "SD has no DACL\n");
626 if (bHasDacl)
628 ok(!bDefaulted, "DACL should not be defaulted\n");
630 ok(pAcl != NULL, "NULL DACL!\n");
631 if (pAcl != NULL)
633 ACL_SIZE_INFORMATION asiSize;
635 ok(IsValidAcl(pAcl), "DACL is not valid\n");
637 ok(GetAclInformation(pAcl, &asiSize, sizeof(asiSize), AclSizeInformation),
638 "GetAclInformation failed with error %u\n", GetLastError());
640 ok(asiSize.AceCount == 3, "Incorrect number of ACEs: %d entries\n", asiSize.AceCount);
641 if (asiSize.AceCount == 3)
643 ACCESS_ALLOWED_ACE *paaa; /* will use for DENIED too */
645 ok(GetAce(pAcl, 0, (LPVOID*)&paaa), "GetAce failed with error %u\n", GetLastError());
646 ok(paaa->Header.AceType == ACCESS_ALLOWED_ACE_TYPE,
647 "Invalid ACE type %d\n", paaa->Header.AceType);
648 ok(paaa->Header.AceFlags == 0, "Invalid ACE flags %x\n", paaa->Header.AceFlags);
649 ok(paaa->Mask == GENERIC_ALL, "Invalid ACE mask %x\n", paaa->Mask);
651 ok(GetAce(pAcl, 1, (LPVOID*)&paaa), "GetAce failed with error %u\n", GetLastError());
652 ok(paaa->Header.AceType == ACCESS_DENIED_ACE_TYPE,
653 "Invalid ACE type %d\n", paaa->Header.AceType);
654 /* first one of two ACEs generated from inheritable entry - without inheritance */
655 ok(paaa->Header.AceFlags == 0, "Invalid ACE flags %x\n", paaa->Header.AceFlags);
656 ok(paaa->Mask == GENERIC_WRITE, "Invalid ACE mask %x\n", paaa->Mask);
658 ok(GetAce(pAcl, 2, (LPVOID*)&paaa), "GetAce failed with error %u\n", GetLastError());
659 ok(paaa->Header.AceType == ACCESS_DENIED_ACE_TYPE,
660 "Invalid ACE type %d\n", paaa->Header.AceType);
661 /* second ACE - with inheritance */
662 ok(paaa->Header.AceFlags == MY_INHERITANCE,
663 "Invalid ACE flags %x\n", paaa->Header.AceFlags);
664 ok(paaa->Mask == GENERIC_READ, "Invalid ACE mask %x\n", paaa->Mask);
669 LocalFree(psd);
673 static void test_SHPackDispParams(void)
675 DISPPARAMS params;
676 VARIANT vars[10];
677 HRESULT hres;
679 if(!pSHPackDispParams)
680 win_skip("SHPackSidpParams not available\n");
682 memset(&params, 0xc0, sizeof(params));
683 memset(vars, 0xc0, sizeof(vars));
684 hres = pSHPackDispParams(&params, vars, 1, VT_I4, 0xdeadbeef);
685 ok(hres == S_OK, "SHPackDispParams failed: %08x\n", hres);
686 ok(params.cArgs == 1, "params.cArgs = %d\n", params.cArgs);
687 ok(params.cNamedArgs == 0, "params.cNamedArgs = %d\n", params.cArgs);
688 ok(params.rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", params.rgdispidNamedArgs);
689 ok(params.rgvarg == vars, "params.rgvarg = %p\n", params.rgvarg);
690 ok(V_VT(vars) == VT_I4, "V_VT(var) = %d\n", V_VT(vars));
691 ok(V_I4(vars) == 0xdeadbeef, "failed %x\n", V_I4(vars));
693 memset(&params, 0xc0, sizeof(params));
694 hres = pSHPackDispParams(&params, NULL, 0, 0);
695 ok(hres == S_OK, "SHPackDispParams failed: %08x\n", hres);
696 ok(params.cArgs == 0, "params.cArgs = %d\n", params.cArgs);
697 ok(params.cNamedArgs == 0, "params.cNamedArgs = %d\n", params.cArgs);
698 ok(params.rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", params.rgdispidNamedArgs);
699 ok(params.rgvarg == NULL, "params.rgvarg = %p\n", params.rgvarg);
701 memset(vars, 0xc0, sizeof(vars));
702 memset(&params, 0xc0, sizeof(params));
703 hres = pSHPackDispParams(&params, vars, 4, VT_BSTR, (void*)0xdeadbeef, VT_EMPTY, 10,
704 VT_I4, 100, VT_DISPATCH, (void*)0xdeadbeef);
705 ok(hres == S_OK, "SHPackDispParams failed: %08x\n", hres);
706 ok(params.cArgs == 4, "params.cArgs = %d\n", params.cArgs);
707 ok(params.cNamedArgs == 0, "params.cNamedArgs = %d\n", params.cArgs);
708 ok(params.rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", params.rgdispidNamedArgs);
709 ok(params.rgvarg == vars, "params.rgvarg = %p\n", params.rgvarg);
710 ok(V_VT(vars) == VT_DISPATCH, "V_VT(vars[0]) = %x\n", V_VT(vars));
711 ok(V_I4(vars) == 0xdeadbeef, "V_I4(vars[0]) = %x\n", V_I4(vars));
712 ok(V_VT(vars+1) == VT_I4, "V_VT(vars[1]) = %d\n", V_VT(vars+1));
713 ok(V_I4(vars+1) == 100, "V_I4(vars[1]) = %x\n", V_I4(vars+1));
714 ok(V_VT(vars+2) == VT_I4, "V_VT(vars[2]) = %d\n", V_VT(vars+2));
715 ok(V_I4(vars+2) == 10, "V_I4(vars[2]) = %x\n", V_I4(vars+2));
716 ok(V_VT(vars+3) == VT_BSTR, "V_VT(vars[3]) = %d\n", V_VT(vars+3));
717 ok(V_BSTR(vars+3) == (void*)0xdeadbeef, "V_BSTR(vars[3]) = %p\n", V_BSTR(vars+3));
720 typedef struct _disp
722 const IDispatchVtbl *vtbl;
723 LONG refCount;
724 } Disp;
726 typedef struct _contain
728 const IConnectionPointContainerVtbl *vtbl;
729 LONG refCount;
731 UINT ptCount;
732 IConnectionPoint **pt;
733 } Contain;
735 typedef struct _cntptn
737 const IConnectionPointVtbl *vtbl;
738 LONG refCount;
740 Contain *container;
741 GUID id;
742 UINT sinkCount;
743 IUnknown **sink;
744 } ConPt;
746 typedef struct _enum
748 const IEnumConnectionsVtbl *vtbl;
749 LONG refCount;
751 UINT idx;
752 ConPt *pt;
753 } EnumCon;
755 typedef struct _enumpt
757 const IEnumConnectionPointsVtbl *vtbl;
758 LONG refCount;
760 int idx;
761 Contain *container;
762 } EnumPt;
765 static HRESULT WINAPI Disp_QueryInterface(
766 IDispatch* This,
767 REFIID riid,
768 void **ppvObject)
770 *ppvObject = NULL;
772 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch))
774 *ppvObject = This;
777 if (*ppvObject)
779 IUnknown_AddRef(This);
780 return S_OK;
783 trace("no interface\n");
784 return E_NOINTERFACE;
787 static ULONG WINAPI Disp_AddRef(IDispatch* This)
789 Disp *iface = (Disp*)This;
790 return InterlockedIncrement(&iface->refCount);
793 static ULONG WINAPI Disp_Release(IDispatch* This)
795 Disp *iface = (Disp*)This;
796 ULONG ret;
798 ret = InterlockedDecrement(&iface->refCount);
799 if (ret == 0)
800 HeapFree(GetProcessHeap(),0,This);
801 return ret;
804 static HRESULT WINAPI Disp_GetTypeInfoCount(
805 IDispatch* This,
806 UINT *pctinfo)
808 return ERROR_SUCCESS;
811 static HRESULT WINAPI Disp_GetTypeInfo(
812 IDispatch* This,
813 UINT iTInfo,
814 LCID lcid,
815 ITypeInfo **ppTInfo)
817 return ERROR_SUCCESS;
820 static HRESULT WINAPI Disp_GetIDsOfNames(
821 IDispatch* This,
822 REFIID riid,
823 LPOLESTR *rgszNames,
824 UINT cNames,
825 LCID lcid,
826 DISPID *rgDispId)
828 return ERROR_SUCCESS;
831 static HRESULT WINAPI Disp_Invoke(
832 IDispatch* This,
833 DISPID dispIdMember,
834 REFIID riid,
835 LCID lcid,
836 WORD wFlags,
837 DISPPARAMS *pDispParams,
838 VARIANT *pVarResult,
839 EXCEPINFO *pExcepInfo,
840 UINT *puArgErr)
842 trace("%p %x %p %x %x %p %p %p %p\n",This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr);
844 ok(dispIdMember == 0xa0 || dispIdMember == 0xa1, "Unknown dispIdMember\n");
845 ok(pDispParams != NULL, "Invoked with NULL pDispParams\n");
846 ok(wFlags == DISPATCH_METHOD, "Wrong flags %x\n",wFlags);
847 ok(lcid == 0,"Wrong lcid %x\n",lcid);
848 if (dispIdMember == 0xa0)
850 ok(pDispParams->cArgs == 0, "params.cArgs = %d\n", pDispParams->cArgs);
851 ok(pDispParams->cNamedArgs == 0, "params.cNamedArgs = %d\n", pDispParams->cArgs);
852 ok(pDispParams->rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", pDispParams->rgdispidNamedArgs);
853 ok(pDispParams->rgvarg == NULL, "params.rgvarg = %p\n", pDispParams->rgvarg);
855 else if (dispIdMember == 0xa1)
857 ok(pDispParams->cArgs == 2, "params.cArgs = %d\n", pDispParams->cArgs);
858 ok(pDispParams->cNamedArgs == 0, "params.cNamedArgs = %d\n", pDispParams->cArgs);
859 ok(pDispParams->rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", pDispParams->rgdispidNamedArgs);
860 ok(V_VT(pDispParams->rgvarg) == VT_BSTR, "V_VT(var) = %d\n", V_VT(pDispParams->rgvarg));
861 ok(V_I4(pDispParams->rgvarg) == 0xdeadcafe , "failed %p\n", V_BSTR(pDispParams->rgvarg));
862 ok(V_VT(pDispParams->rgvarg+1) == VT_I4, "V_VT(var) = %d\n", V_VT(pDispParams->rgvarg+1));
863 ok(V_I4(pDispParams->rgvarg+1) == 0xdeadbeef, "failed %x\n", V_I4(pDispParams->rgvarg+1));
866 return ERROR_SUCCESS;
869 static const IDispatchVtbl disp_vtbl = {
870 Disp_QueryInterface,
871 Disp_AddRef,
872 Disp_Release,
874 Disp_GetTypeInfoCount,
875 Disp_GetTypeInfo,
876 Disp_GetIDsOfNames,
877 Disp_Invoke
880 static HRESULT WINAPI Enum_QueryInterface(
881 IEnumConnections* This,
882 REFIID riid,
883 void **ppvObject)
885 *ppvObject = NULL;
887 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IEnumConnections))
889 *ppvObject = This;
892 if (*ppvObject)
894 IUnknown_AddRef(This);
895 return S_OK;
898 trace("no interface\n");
899 return E_NOINTERFACE;
902 static ULONG WINAPI Enum_AddRef(IEnumConnections* This)
904 EnumCon *iface = (EnumCon*)This;
905 return InterlockedIncrement(&iface->refCount);
908 static ULONG WINAPI Enum_Release(IEnumConnections* This)
910 EnumCon *iface = (EnumCon*)This;
911 ULONG ret;
913 ret = InterlockedDecrement(&iface->refCount);
914 if (ret == 0)
915 HeapFree(GetProcessHeap(),0,This);
916 return ret;
919 static HRESULT WINAPI Enum_Next(
920 IEnumConnections* This,
921 ULONG cConnections,
922 LPCONNECTDATA rgcd,
923 ULONG *pcFetched)
925 EnumCon *iface = (EnumCon*)This;
927 if (cConnections > 0 && iface->idx < iface->pt->sinkCount)
929 rgcd->pUnk = iface->pt->sink[iface->idx];
930 IUnknown_AddRef(iface->pt->sink[iface->idx]);
931 rgcd->dwCookie=0xff;
932 if (pcFetched)
933 *pcFetched = 1;
934 iface->idx++;
935 return S_OK;
938 return E_FAIL;
941 static HRESULT WINAPI Enum_Skip(
942 IEnumConnections* This,
943 ULONG cConnections)
945 return E_FAIL;
948 static HRESULT WINAPI Enum_Reset(
949 IEnumConnections* This)
951 return E_FAIL;
954 static HRESULT WINAPI Enum_Clone(
955 IEnumConnections* This,
956 IEnumConnections **ppEnum)
958 return E_FAIL;
961 static const IEnumConnectionsVtbl enum_vtbl = {
963 Enum_QueryInterface,
964 Enum_AddRef,
965 Enum_Release,
966 Enum_Next,
967 Enum_Skip,
968 Enum_Reset,
969 Enum_Clone
972 static HRESULT WINAPI ConPt_QueryInterface(
973 IConnectionPoint* This,
974 REFIID riid,
975 void **ppvObject)
977 *ppvObject = NULL;
979 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IConnectionPoint))
981 *ppvObject = This;
984 if (*ppvObject)
986 IUnknown_AddRef(This);
987 return S_OK;
990 trace("no interface\n");
991 return E_NOINTERFACE;
994 static ULONG WINAPI ConPt_AddRef(
995 IConnectionPoint* This)
997 ConPt *iface = (ConPt*)This;
998 return InterlockedIncrement(&iface->refCount);
1001 static ULONG WINAPI ConPt_Release(
1002 IConnectionPoint* This)
1004 ConPt *iface = (ConPt*)This;
1005 ULONG ret;
1007 ret = InterlockedDecrement(&iface->refCount);
1008 if (ret == 0)
1010 if (iface->sinkCount > 0)
1012 int i;
1013 for (i = 0; i < iface->sinkCount; i++)
1015 if (iface->sink[i])
1016 IUnknown_Release(iface->sink[i]);
1018 HeapFree(GetProcessHeap(),0,iface->sink);
1020 HeapFree(GetProcessHeap(),0,This);
1022 return ret;
1025 static HRESULT WINAPI ConPt_GetConnectionInterface(
1026 IConnectionPoint* This,
1027 IID *pIID)
1029 static int i = 0;
1030 ConPt *iface = (ConPt*)This;
1031 if (i==0)
1033 i++;
1034 return E_FAIL;
1036 else
1037 memcpy(pIID,&iface->id,sizeof(GUID));
1038 return S_OK;
1041 static HRESULT WINAPI ConPt_GetConnectionPointContainer(
1042 IConnectionPoint* This,
1043 IConnectionPointContainer **ppCPC)
1045 ConPt *iface = (ConPt*)This;
1047 *ppCPC = (IConnectionPointContainer*)iface->container;
1048 return S_OK;
1051 static HRESULT WINAPI ConPt_Advise(
1052 IConnectionPoint* This,
1053 IUnknown *pUnkSink,
1054 DWORD *pdwCookie)
1056 ConPt *iface = (ConPt*)This;
1058 if (iface->sinkCount == 0)
1059 iface->sink = HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown*));
1060 else
1061 iface->sink = HeapReAlloc(GetProcessHeap(),0,iface->sink,sizeof(IUnknown*)*(iface->sinkCount+1));
1062 iface->sink[iface->sinkCount] = pUnkSink;
1063 IUnknown_AddRef(pUnkSink);
1064 iface->sinkCount++;
1065 *pdwCookie = iface->sinkCount;
1066 return S_OK;
1069 static HRESULT WINAPI ConPt_Unadvise(
1070 IConnectionPoint* This,
1071 DWORD dwCookie)
1073 ConPt *iface = (ConPt*)This;
1075 if (dwCookie > iface->sinkCount)
1076 return E_FAIL;
1077 else
1079 IUnknown_Release(iface->sink[dwCookie-1]);
1080 iface->sink[dwCookie-1] = NULL;
1082 return S_OK;
1085 static HRESULT WINAPI ConPt_EnumConnections(
1086 IConnectionPoint* This,
1087 IEnumConnections **ppEnum)
1089 EnumCon *ec;
1091 ec = HeapAlloc(GetProcessHeap(),0,sizeof(EnumCon));
1092 ec->vtbl = &enum_vtbl;
1093 ec->refCount = 1;
1094 ec->pt = (ConPt*)This;
1095 ec->idx = 0;
1096 *ppEnum = (IEnumConnections*)ec;
1098 return S_OK;
1101 static const IConnectionPointVtbl point_vtbl = {
1102 ConPt_QueryInterface,
1103 ConPt_AddRef,
1104 ConPt_Release,
1106 ConPt_GetConnectionInterface,
1107 ConPt_GetConnectionPointContainer,
1108 ConPt_Advise,
1109 ConPt_Unadvise,
1110 ConPt_EnumConnections
1113 static HRESULT WINAPI EnumPt_QueryInterface(
1114 IEnumConnectionPoints* This,
1115 REFIID riid,
1116 void **ppvObject)
1118 *ppvObject = NULL;
1120 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IEnumConnectionPoints))
1122 *ppvObject = This;
1125 if (*ppvObject)
1127 IUnknown_AddRef(This);
1128 return S_OK;
1131 trace("no interface\n");
1132 return E_NOINTERFACE;
1135 static ULONG WINAPI EnumPt_AddRef(IEnumConnectionPoints* This)
1137 EnumPt *iface = (EnumPt*)This;
1138 return InterlockedIncrement(&iface->refCount);
1141 static ULONG WINAPI EnumPt_Release(IEnumConnectionPoints* This)
1143 EnumPt *iface = (EnumPt*)This;
1144 ULONG ret;
1146 ret = InterlockedDecrement(&iface->refCount);
1147 if (ret == 0)
1148 HeapFree(GetProcessHeap(),0,This);
1149 return ret;
1152 static HRESULT WINAPI EnumPt_Next(
1153 IEnumConnectionPoints* This,
1154 ULONG cConnections,
1155 IConnectionPoint **rgcd,
1156 ULONG *pcFetched)
1158 EnumPt *iface = (EnumPt*)This;
1160 if (cConnections > 0 && iface->idx < iface->container->ptCount)
1162 *rgcd = iface->container->pt[iface->idx];
1163 IUnknown_AddRef(iface->container->pt[iface->idx]);
1164 if (pcFetched)
1165 *pcFetched = 1;
1166 iface->idx++;
1167 return S_OK;
1170 return E_FAIL;
1173 static HRESULT WINAPI EnumPt_Skip(
1174 IEnumConnectionPoints* This,
1175 ULONG cConnections)
1177 return E_FAIL;
1180 static HRESULT WINAPI EnumPt_Reset(
1181 IEnumConnectionPoints* This)
1183 return E_FAIL;
1186 static HRESULT WINAPI EnumPt_Clone(
1187 IEnumConnectionPoints* This,
1188 IEnumConnectionPoints **ppEnumPt)
1190 return E_FAIL;
1193 static const IEnumConnectionPointsVtbl enumpt_vtbl = {
1195 EnumPt_QueryInterface,
1196 EnumPt_AddRef,
1197 EnumPt_Release,
1198 EnumPt_Next,
1199 EnumPt_Skip,
1200 EnumPt_Reset,
1201 EnumPt_Clone
1204 static HRESULT WINAPI Contain_QueryInterface(
1205 IConnectionPointContainer* This,
1206 REFIID riid,
1207 void **ppvObject)
1209 *ppvObject = NULL;
1211 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IConnectionPointContainer))
1213 *ppvObject = This;
1216 if (*ppvObject)
1218 IUnknown_AddRef(This);
1219 return S_OK;
1222 trace("no interface\n");
1223 return E_NOINTERFACE;
1226 static ULONG WINAPI Contain_AddRef(
1227 IConnectionPointContainer* This)
1229 Contain *iface = (Contain*)This;
1230 return InterlockedIncrement(&iface->refCount);
1233 static ULONG WINAPI Contain_Release(
1234 IConnectionPointContainer* This)
1236 Contain *iface = (Contain*)This;
1237 ULONG ret;
1239 ret = InterlockedDecrement(&iface->refCount);
1240 if (ret == 0)
1242 if (iface->ptCount > 0)
1244 int i;
1245 for (i = 0; i < iface->ptCount; i++)
1246 IUnknown_Release(iface->pt[i]);
1247 HeapFree(GetProcessHeap(),0,iface->pt);
1249 HeapFree(GetProcessHeap(),0,This);
1251 return ret;
1254 static HRESULT WINAPI Contain_EnumConnectionPoints(
1255 IConnectionPointContainer* This,
1256 IEnumConnectionPoints **ppEnum)
1258 EnumPt *ec;
1260 ec = HeapAlloc(GetProcessHeap(),0,sizeof(EnumPt));
1261 ec->vtbl = &enumpt_vtbl;
1262 ec->refCount = 1;
1263 ec->idx= 0;
1264 ec->container = (Contain*)This;
1265 *ppEnum = (IEnumConnectionPoints*)ec;
1267 return S_OK;
1270 static HRESULT WINAPI Contain_FindConnectionPoint(
1271 IConnectionPointContainer* This,
1272 REFIID riid,
1273 IConnectionPoint **ppCP)
1275 Contain *iface = (Contain*)This;
1276 ConPt *pt;
1278 if (!IsEqualIID(riid, &IID_NULL) || iface->ptCount ==0)
1280 pt = HeapAlloc(GetProcessHeap(),0,sizeof(ConPt));
1281 pt->vtbl = &point_vtbl;
1282 pt->refCount = 1;
1283 pt->sinkCount = 0;
1284 pt->sink = NULL;
1285 pt->container = iface;
1286 pt->id = IID_IDispatch;
1288 if (iface->ptCount == 0)
1289 iface->pt =HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown*));
1290 else
1291 iface->pt = HeapReAlloc(GetProcessHeap(),0,iface->pt,sizeof(IUnknown*)*(iface->ptCount+1));
1292 iface->pt[iface->ptCount] = (IConnectionPoint*)pt;
1293 iface->ptCount++;
1295 *ppCP = (IConnectionPoint*)pt;
1297 else
1299 *ppCP = iface->pt[0];
1300 IUnknown_AddRef((IUnknown*)*ppCP);
1303 return S_OK;
1306 static const IConnectionPointContainerVtbl contain_vtbl = {
1307 Contain_QueryInterface,
1308 Contain_AddRef,
1309 Contain_Release,
1311 Contain_EnumConnectionPoints,
1312 Contain_FindConnectionPoint
1315 static void test_IConnectionPoint(void)
1317 HRESULT rc;
1318 ULONG ref;
1319 IConnectionPoint *point;
1320 Contain *container;
1321 Disp *dispatch;
1322 DWORD cookie = 0xffffffff;
1323 DISPPARAMS params;
1324 VARIANT vars[10];
1326 if (!pIConnectionPoint_SimpleInvoke || !pConnectToConnectionPoint)
1328 win_skip("IConnectionPoint Apis not present\n");
1329 return;
1332 container = HeapAlloc(GetProcessHeap(),0,sizeof(Contain));
1333 container->vtbl = &contain_vtbl;
1334 container->refCount = 1;
1335 container->ptCount = 0;
1336 container->pt = NULL;
1338 dispatch = HeapAlloc(GetProcessHeap(),0,sizeof(Disp));
1339 dispatch->vtbl = &disp_vtbl;
1340 dispatch->refCount = 1;
1342 rc = pConnectToConnectionPoint((IUnknown*)dispatch, &IID_NULL, TRUE, (IUnknown*)container, &cookie, &point);
1343 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
1344 ok(point != NULL, "returned ConnectionPoint is NULL\n");
1345 ok(cookie != 0xffffffff, "invalid cookie returned\n");
1347 rc = pIConnectionPoint_SimpleInvoke(point,0xa0,NULL);
1348 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
1350 if (pSHPackDispParams)
1352 memset(&params, 0xc0, sizeof(params));
1353 memset(vars, 0xc0, sizeof(vars));
1354 rc = pSHPackDispParams(&params, vars, 2, VT_I4, 0xdeadbeef, VT_BSTR, 0xdeadcafe);
1355 ok(rc == S_OK, "SHPackDispParams failed: %08x\n", rc);
1357 rc = pIConnectionPoint_SimpleInvoke(point,0xa1,&params);
1358 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
1360 else
1361 win_skip("pSHPackDispParams not present\n");
1363 rc = pConnectToConnectionPoint(NULL, &IID_NULL, FALSE, (IUnknown*)container, &cookie, NULL);
1364 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
1366 /* MSDN says this should be required but it crashs on XP
1367 IUnknown_Release(point);
1369 ref = IUnknown_Release((IUnknown*)container);
1370 ok(ref == 0, "leftover IConnectionPointContainer reference %i\n",ref);
1371 ref = IUnknown_Release((IUnknown*)dispatch);
1372 ok(ref == 0, "leftover IDispatch reference %i\n",ref);
1375 typedef struct _propbag
1377 const IPropertyBagVtbl *vtbl;
1378 LONG refCount;
1380 } PropBag;
1383 static HRESULT WINAPI Prop_QueryInterface(
1384 IPropertyBag* This,
1385 REFIID riid,
1386 void **ppvObject)
1388 *ppvObject = NULL;
1390 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IPropertyBag))
1392 *ppvObject = This;
1395 if (*ppvObject)
1397 IUnknown_AddRef(This);
1398 return S_OK;
1401 trace("no interface\n");
1402 return E_NOINTERFACE;
1405 static ULONG WINAPI Prop_AddRef(
1406 IPropertyBag* This)
1408 PropBag *iface = (PropBag*)This;
1409 return InterlockedIncrement(&iface->refCount);
1412 static ULONG WINAPI Prop_Release(
1413 IPropertyBag* This)
1415 PropBag *iface = (PropBag*)This;
1416 ULONG ret;
1418 ret = InterlockedDecrement(&iface->refCount);
1419 if (ret == 0)
1420 HeapFree(GetProcessHeap(),0,This);
1421 return ret;
1424 static HRESULT WINAPI Prop_Read(
1425 IPropertyBag* This,
1426 LPCOLESTR pszPropName,
1427 VARIANT *pVar,
1428 IErrorLog *pErrorLog)
1430 V_VT(pVar) = VT_BLOB|VT_BYREF;
1431 V_BYREF(pVar) = (LPVOID)0xdeadcafe;
1432 return S_OK;
1435 static HRESULT WINAPI Prop_Write(
1436 IPropertyBag* This,
1437 LPCOLESTR pszPropName,
1438 VARIANT *pVar)
1440 return S_OK;
1444 static const IPropertyBagVtbl prop_vtbl = {
1445 Prop_QueryInterface,
1446 Prop_AddRef,
1447 Prop_Release,
1449 Prop_Read,
1450 Prop_Write
1453 static void test_SHPropertyBag_ReadLONG(void)
1455 PropBag *pb;
1456 HRESULT rc;
1457 LONG out;
1458 static const WCHAR szName1[] = {'n','a','m','e','1',0};
1460 if (!pSHPropertyBag_ReadLONG)
1462 win_skip("SHPropertyBag_ReadLONG not present\n");
1463 return;
1466 pb = HeapAlloc(GetProcessHeap(),0,sizeof(PropBag));
1467 pb->refCount = 1;
1468 pb->vtbl = &prop_vtbl;
1470 out = 0xfeedface;
1471 rc = pSHPropertyBag_ReadLONG(NULL, szName1, &out);
1472 ok(rc == E_INVALIDARG || broken(rc == 0), "incorrect return %x\n",rc);
1473 ok(out == 0xfeedface, "value should not have changed\n");
1474 rc = pSHPropertyBag_ReadLONG((IPropertyBag*)pb, NULL, &out);
1475 ok(rc == E_INVALIDARG || broken(rc == 0) || broken(rc == 1), "incorrect return %x\n",rc);
1476 ok(out == 0xfeedface, "value should not have changed\n");
1477 rc = pSHPropertyBag_ReadLONG((IPropertyBag*)pb, szName1, NULL);
1478 ok(rc == E_INVALIDARG || broken(rc == 0) || broken(rc == 1), "incorrect return %x\n",rc);
1479 ok(out == 0xfeedface, "value should not have changed\n");
1480 rc = pSHPropertyBag_ReadLONG((IPropertyBag*)pb, szName1, &out);
1481 ok(rc == DISP_E_BADVARTYPE || broken(rc == 0) || broken(rc == 1), "incorrect return %x\n",rc);
1482 ok(out == 0xfeedface || broken(out == 0xfeedfa00), "value should not have changed %x\n",out);
1483 IUnknown_Release((IUnknown*)pb);
1488 static void test_SHSetWindowBits(void)
1490 HWND hwnd;
1491 DWORD style, styleold;
1492 WNDCLASSA clsA;
1494 if(!pSHSetWindowBits)
1496 win_skip("SHSetWindowBits is not available\n");
1497 return;
1500 clsA.style = 0;
1501 clsA.lpfnWndProc = DefWindowProcA;
1502 clsA.cbClsExtra = 0;
1503 clsA.cbWndExtra = 0;
1504 clsA.hInstance = GetModuleHandleA(NULL);
1505 clsA.hIcon = 0;
1506 clsA.hCursor = LoadCursorA(0, IDC_ARROW);
1507 clsA.hbrBackground = NULL;
1508 clsA.lpszMenuName = NULL;
1509 clsA.lpszClassName = "Shlwapi test class";
1510 RegisterClassA(&clsA);
1512 hwnd = CreateWindowA("Shlwapi test class", "Test", WS_VISIBLE, 0, 0, 100, 100,
1513 NULL, NULL, GetModuleHandle(NULL), 0);
1514 ok(IsWindow(hwnd), "failed to create window\n");
1516 /* null window */
1517 SetLastError(0xdeadbeef);
1518 style = pSHSetWindowBits(NULL, GWL_STYLE, 0, 0);
1519 ok(style == 0, "expected 0 retval, got %d\n", style);
1520 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE ||
1521 broken(GetLastError() == 0xdeadbeef), /* Win9x/WinMe */
1522 "expected ERROR_INVALID_WINDOW_HANDLE, got %d\n", GetLastError());
1524 /* zero mask, zero flags */
1525 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1526 style = pSHSetWindowBits(hwnd, GWL_STYLE, 0, 0);
1527 ok(styleold == style, "expected old style\n");
1528 ok(styleold == GetWindowLongA(hwnd, GWL_STYLE), "expected to keep old style\n");
1530 /* test mask */
1531 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1532 ok(styleold & WS_VISIBLE, "expected WS_VISIBLE\n");
1533 style = pSHSetWindowBits(hwnd, GWL_STYLE, WS_VISIBLE, 0);
1535 ok(style == styleold, "expected previous style, got %x\n", style);
1536 ok((GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE) == 0, "expected updated style\n");
1538 /* test mask, unset style bit used */
1539 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1540 style = pSHSetWindowBits(hwnd, GWL_STYLE, WS_VISIBLE, 0);
1541 ok(style == styleold, "expected previous style, got %x\n", style);
1542 ok(styleold == GetWindowLongA(hwnd, GWL_STYLE), "expected to keep old style\n");
1544 /* set back with flags */
1545 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1546 style = pSHSetWindowBits(hwnd, GWL_STYLE, WS_VISIBLE, WS_VISIBLE);
1547 ok(style == styleold, "expected previous style, got %x\n", style);
1548 ok(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE, "expected updated style\n");
1550 /* reset and try to set without a mask */
1551 pSHSetWindowBits(hwnd, GWL_STYLE, WS_VISIBLE, 0);
1552 ok((GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE) == 0, "expected updated style\n");
1553 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1554 style = pSHSetWindowBits(hwnd, GWL_STYLE, 0, WS_VISIBLE);
1555 ok(style == styleold, "expected previous style, got %x\n", style);
1556 ok((GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE) == 0, "expected updated style\n");
1558 DestroyWindow(hwnd);
1560 UnregisterClassA("Shlwapi test class", GetModuleHandleA(NULL));
1563 static void test_SHFormatDateTimeA(void)
1565 FILETIME UNALIGNED filetime;
1566 CHAR buff[100], buff2[100], buff3[100];
1567 SYSTEMTIME st;
1568 DWORD flags;
1569 INT ret;
1571 if(!pSHFormatDateTimeA)
1573 win_skip("pSHFormatDateTimeA isn't available\n");
1574 return;
1577 if (0)
1579 /* crashes on native */
1580 ret = pSHFormatDateTimeA(NULL, NULL, NULL, 0);
1583 GetLocalTime(&st);
1584 SystemTimeToFileTime(&st, &filetime);
1585 /* SHFormatDateTime expects input as utc */
1586 LocalFileTimeToFileTime(&filetime, &filetime);
1588 /* no way to get required buffer length here */
1589 SetLastError(0xdeadbeef);
1590 ret = pSHFormatDateTimeA(&filetime, NULL, NULL, 0);
1591 ok(ret == 0, "got %d\n", ret);
1592 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1594 SetLastError(0xdeadbeef);
1595 buff[0] = 'a'; buff[1] = 0;
1596 ret = pSHFormatDateTimeA(&filetime, NULL, buff, 0);
1597 ok(ret == 0, "got %d\n", ret);
1598 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1599 ok(buff[0] == 'a', "expected same string, got %s\n", buff);
1601 /* flags needs to have FDTF_NOAUTOREADINGORDER for these tests to succeed on Vista+ */
1603 /* all combinations documented as invalid succeeded */
1604 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTTIME | FDTF_LONGTIME;
1605 SetLastError(0xdeadbeef);
1606 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1607 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1608 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1610 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTDATE | FDTF_LONGDATE;
1611 SetLastError(0xdeadbeef);
1612 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1613 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1614 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1616 flags = FDTF_SHORTDATE | FDTF_LTRDATE | FDTF_RTLDATE;
1617 SetLastError(0xdeadbeef);
1618 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1619 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1620 ok(GetLastError() == 0xdeadbeef ||
1621 broken(GetLastError() == ERROR_INVALID_FLAGS), /* Win9x/WinMe */
1622 "expected 0xdeadbeef, got %d\n", GetLastError());
1624 /* now check returned strings */
1625 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTTIME;
1626 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1627 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1628 ret = GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff2, sizeof(buff2));
1629 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1630 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1632 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGTIME;
1633 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1634 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1635 ret = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2));
1636 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1637 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1639 /* both time flags */
1640 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGTIME | FDTF_SHORTTIME;
1641 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1642 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1643 ret = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2));
1644 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1645 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1647 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTDATE;
1648 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1649 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1650 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2));
1651 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1652 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1654 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGDATE;
1655 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1656 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1657 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
1658 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1659 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1661 /* both date flags */
1662 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGDATE | FDTF_SHORTDATE;
1663 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1664 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1665 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
1666 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1667 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1669 /* various combinations of date/time flags */
1670 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGDATE | FDTF_SHORTTIME;
1671 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1672 ok(ret == lstrlenA(buff)+1, "got %d, length %d\n", ret, lstrlenA(buff)+1);
1673 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
1674 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1675 strcat(buff2, ", ");
1676 ret = GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3));
1677 ok(ret == lstrlenA(buff3)+1, "got %d\n", ret);
1678 strcat(buff2, buff3);
1679 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1681 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGDATE | FDTF_LONGTIME;
1682 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1683 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1684 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
1685 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1686 strcat(buff2, ", ");
1687 ret = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3));
1688 ok(ret == lstrlenA(buff3)+1, "got %d\n", ret);
1689 strcat(buff2, buff3);
1690 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1692 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTDATE | FDTF_SHORTTIME;
1693 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1694 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1695 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2));
1696 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1697 strcat(buff2, " ");
1698 ret = GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3));
1699 ok(ret == lstrlenA(buff3)+1, "got %d\n", ret);
1700 strcat(buff2, buff3);
1701 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1703 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTDATE | FDTF_LONGTIME;
1704 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1705 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1706 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2));
1707 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1708 strcat(buff2, " ");
1709 ret = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3));
1710 ok(ret == lstrlenA(buff3)+1, "got %d\n", ret);
1711 strcat(buff2, buff3);
1712 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1715 static void test_SHFormatDateTimeW(void)
1717 FILETIME UNALIGNED filetime;
1718 WCHAR buff[100], buff2[100], buff3[100];
1719 SYSTEMTIME st;
1720 DWORD flags;
1721 INT ret;
1722 static const WCHAR spaceW[] = {' ',0};
1723 static const WCHAR commaW[] = {',',' ',0};
1725 if(!pSHFormatDateTimeW)
1727 win_skip("pSHFormatDateTimeW isn't available\n");
1728 return;
1731 if (0)
1733 /* crashes on native */
1734 ret = pSHFormatDateTimeW(NULL, NULL, NULL, 0);
1737 GetLocalTime(&st);
1738 SystemTimeToFileTime(&st, &filetime);
1739 /* SHFormatDateTime expects input as utc */
1740 LocalFileTimeToFileTime(&filetime, &filetime);
1742 /* no way to get required buffer length here */
1743 SetLastError(0xdeadbeef);
1744 ret = pSHFormatDateTimeW(&filetime, NULL, NULL, 0);
1745 ok(ret == 0, "got %d\n", ret);
1746 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1748 SetLastError(0xdeadbeef);
1749 buff[0] = 'a'; buff[1] = 0;
1750 ret = pSHFormatDateTimeW(&filetime, NULL, buff, 0);
1751 ok(ret == 0, "got %d\n", ret);
1752 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1753 ok(buff[0] == 'a', "expected same string\n");
1755 /* all combinations documented as invalid succeeded */
1756 flags = FDTF_SHORTTIME | FDTF_LONGTIME;
1757 SetLastError(0xdeadbeef);
1758 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1759 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1760 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1762 flags = FDTF_SHORTDATE | FDTF_LONGDATE;
1763 SetLastError(0xdeadbeef);
1764 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1765 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1766 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1768 flags = FDTF_SHORTDATE | FDTF_LTRDATE | FDTF_RTLDATE;
1769 SetLastError(0xdeadbeef);
1770 buff[0] = 0; /* NT4 doesn't clear the buffer on failure */
1771 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1772 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1773 ok(GetLastError() == 0xdeadbeef ||
1774 broken(GetLastError() == ERROR_INVALID_FLAGS), /* Win9x/WinMe/NT4 */
1775 "expected 0xdeadbeef, got %d\n", GetLastError());
1777 /* now check returned strings */
1778 flags = FDTF_SHORTTIME;
1779 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1780 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1781 SetLastError(0xdeadbeef);
1782 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1783 if (ret == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1785 win_skip("Needed W-functions are not implemented\n");
1786 return;
1788 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1789 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1791 flags = FDTF_LONGTIME;
1792 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1793 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1794 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1795 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1796 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1798 /* both time flags */
1799 flags = FDTF_LONGTIME | FDTF_SHORTTIME;
1800 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1801 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1802 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1803 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1804 ok(lstrcmpW(buff, buff2) == 0, "expected equal string\n");
1806 flags = FDTF_SHORTDATE;
1807 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1808 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1809 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1810 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1811 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1813 flags = FDTF_LONGDATE;
1814 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1815 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1816 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1817 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1818 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1820 /* both date flags */
1821 flags = FDTF_LONGDATE | FDTF_SHORTDATE;
1822 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1823 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1824 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1825 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1826 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1828 /* various combinations of date/time flags */
1829 flags = FDTF_LONGDATE | FDTF_SHORTTIME;
1830 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1831 ok(ret == lstrlenW(buff)+1, "got %d, length %d\n", ret, lstrlenW(buff)+1);
1832 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1833 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1834 lstrcatW(buff2, commaW);
1835 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
1836 ok(ret == lstrlenW(buff3)+1, "got %d\n", ret);
1837 lstrcatW(buff2, buff3);
1838 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1840 flags = FDTF_LONGDATE | FDTF_LONGTIME;
1841 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1842 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1843 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1844 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1845 lstrcatW(buff2, commaW);
1846 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
1847 ok(ret == lstrlenW(buff3)+1, "got %d\n", ret);
1848 lstrcatW(buff2, buff3);
1849 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1851 flags = FDTF_SHORTDATE | FDTF_SHORTTIME;
1852 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1853 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1854 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1855 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1856 lstrcatW(buff2, spaceW);
1857 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
1858 ok(ret == lstrlenW(buff3)+1, "got %d\n", ret);
1859 lstrcatW(buff2, buff3);
1860 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1862 flags = FDTF_SHORTDATE | FDTF_LONGTIME;
1863 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1864 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1865 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1866 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1867 lstrcatW(buff2, spaceW);
1868 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
1869 ok(ret == lstrlenW(buff3)+1, "got %d\n", ret);
1870 lstrcatW(buff2, buff3);
1871 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1874 static void test_SHGetObjectCompatFlags(void)
1876 struct compat_value {
1877 CHAR nameA[30];
1878 DWORD value;
1881 struct compat_value values[] = {
1882 { "OTNEEDSSFCACHE", 0x1 },
1883 { "NO_WEBVIEW", 0x2 },
1884 { "UNBINDABLE", 0x4 },
1885 { "PINDLL", 0x8 },
1886 { "NEEDSFILESYSANCESTOR", 0x10 },
1887 { "NOTAFILESYSTEM", 0x20 },
1888 { "CTXMENU_NOVERBS", 0x40 },
1889 { "CTXMENU_LIMITEDQI", 0x80 },
1890 { "COCREATESHELLFOLDERONLY", 0x100 },
1891 { "NEEDSSTORAGEANCESTOR", 0x200 },
1892 { "NOLEGACYWEBVIEW", 0x400 },
1893 { "CTXMENU_XPQCMFLAGS", 0x1000 },
1894 { "NOIPROPERTYSTORE", 0x2000 }
1897 static const char compat_path[] = "Software\\Microsoft\\Windows\\CurrentVersion\\ShellCompatibility\\Objects";
1898 CHAR keyA[39]; /* {CLSID} */
1899 HKEY root;
1900 DWORD ret;
1901 int i;
1903 if (!pSHGetObjectCompatFlags)
1905 win_skip("SHGetObjectCompatFlags isn't available\n");
1906 return;
1909 /* null args */
1910 ret = pSHGetObjectCompatFlags(NULL, NULL);
1911 ok(ret == 0, "got %d\n", ret);
1913 ret = RegOpenKeyA(HKEY_LOCAL_MACHINE, compat_path, &root);
1914 if (ret != ERROR_SUCCESS)
1916 skip("No compatibility class data found\n");
1917 return;
1920 for (i = 0; RegEnumKeyA(root, i, keyA, sizeof(keyA)) == ERROR_SUCCESS; i++)
1922 HKEY clsid_key;
1924 if (RegOpenKeyA(root, keyA, &clsid_key) == ERROR_SUCCESS)
1926 CHAR valueA[30];
1927 DWORD expected = 0, got, length = sizeof(valueA);
1928 CLSID clsid;
1929 int v;
1931 for (v = 0; RegEnumValueA(clsid_key, v, valueA, &length, NULL, NULL, NULL, NULL) == ERROR_SUCCESS; v++)
1933 int j;
1935 for (j = 0; j < sizeof(values)/sizeof(struct compat_value); j++)
1936 if (lstrcmpA(values[j].nameA, valueA) == 0)
1938 expected |= values[j].value;
1939 break;
1942 length = sizeof(valueA);
1945 pGUIDFromStringA(keyA, &clsid);
1946 got = pSHGetObjectCompatFlags(NULL, &clsid);
1947 ok(got == expected, "got 0x%08x, expected 0x%08x. Key %s\n", got, expected, keyA);
1949 RegCloseKey(clsid_key);
1953 RegCloseKey(root);
1956 typedef struct {
1957 const IOleCommandTargetVtbl *lpVtbl;
1958 LONG ref;
1959 } IOleCommandTargetImpl;
1961 static const IOleCommandTargetVtbl IOleCommandTargetImpl_Vtbl;
1963 IOleCommandTarget* IOleCommandTargetImpl_Construct(void)
1965 IOleCommandTargetImpl *obj;
1967 obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*obj));
1968 obj->lpVtbl = &IOleCommandTargetImpl_Vtbl;
1969 obj->ref = 1;
1971 return (IOleCommandTarget*)obj;
1974 static HRESULT WINAPI IOleCommandTargetImpl_QueryInterface(IOleCommandTarget *iface, REFIID riid, void **ppvObj)
1976 IOleCommandTargetImpl *This = (IOleCommandTargetImpl *)iface;
1978 if (IsEqualIID(riid, &IID_IUnknown) ||
1979 IsEqualIID(riid, &IID_IOleCommandTarget))
1981 *ppvObj = This;
1984 if(*ppvObj)
1986 IUnknown_AddRef(iface);
1987 return S_OK;
1990 return E_NOINTERFACE;
1993 static ULONG WINAPI IOleCommandTargetImpl_AddRef(IOleCommandTarget *iface)
1995 IOleCommandTargetImpl *This = (IOleCommandTargetImpl *)iface;
1996 return InterlockedIncrement(&This->ref);
1999 static ULONG WINAPI IOleCommandTargetImpl_Release(IOleCommandTarget *iface)
2001 IOleCommandTargetImpl *This = (IOleCommandTargetImpl *)iface;
2002 ULONG ref = InterlockedDecrement(&This->ref);
2004 if (!ref)
2006 HeapFree(GetProcessHeap(), 0, This);
2007 return 0;
2009 return ref;
2012 static HRESULT WINAPI IOleCommandTargetImpl_QueryStatus(
2013 IOleCommandTarget *iface, const GUID *group, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText)
2015 return E_NOTIMPL;
2018 static HRESULT WINAPI IOleCommandTargetImpl_Exec(
2019 IOleCommandTarget *iface,
2020 const GUID *CmdGroup,
2021 DWORD nCmdID,
2022 DWORD nCmdexecopt,
2023 VARIANT *pvaIn,
2024 VARIANT *pvaOut)
2026 add_call(&trace_got, 3, CmdGroup, (void*)(DWORD_PTR)nCmdID, (void*)(DWORD_PTR)nCmdexecopt, pvaIn, pvaOut);
2027 return S_OK;
2030 static const IOleCommandTargetVtbl IOleCommandTargetImpl_Vtbl =
2032 IOleCommandTargetImpl_QueryInterface,
2033 IOleCommandTargetImpl_AddRef,
2034 IOleCommandTargetImpl_Release,
2035 IOleCommandTargetImpl_QueryStatus,
2036 IOleCommandTargetImpl_Exec
2039 typedef struct {
2040 const IServiceProviderVtbl *lpVtbl;
2041 LONG ref;
2042 } IServiceProviderImpl;
2044 typedef struct {
2045 const IProfferServiceVtbl *lpVtbl;
2046 LONG ref;
2047 } IProfferServiceImpl;
2050 static const IServiceProviderVtbl IServiceProviderImpl_Vtbl;
2051 static const IProfferServiceVtbl IProfferServiceImpl_Vtbl;
2053 IServiceProvider* IServiceProviderImpl_Construct(void)
2055 IServiceProviderImpl *obj;
2057 obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*obj));
2058 obj->lpVtbl = &IServiceProviderImpl_Vtbl;
2059 obj->ref = 1;
2061 return (IServiceProvider*)obj;
2064 IProfferService* IProfferServiceImpl_Construct(void)
2066 IProfferServiceImpl *obj;
2068 obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*obj));
2069 obj->lpVtbl = &IProfferServiceImpl_Vtbl;
2070 obj->ref = 1;
2072 return (IProfferService*)obj;
2075 static HRESULT WINAPI IServiceProviderImpl_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppvObj)
2077 IServiceProviderImpl *This = (IServiceProviderImpl *)iface;
2079 if (IsEqualIID(riid, &IID_IUnknown) ||
2080 IsEqualIID(riid, &IID_IServiceProvider))
2082 *ppvObj = This;
2085 if(*ppvObj)
2087 IUnknown_AddRef(iface);
2088 /* native uses redefined IID_IServiceProvider symbol, so we can't compare pointers */
2089 if (IsEqualIID(riid, &IID_IServiceProvider))
2090 add_call(&trace_got, 1, iface, &IID_IServiceProvider, 0, 0, 0);
2091 return S_OK;
2094 return E_NOINTERFACE;
2097 static ULONG WINAPI IServiceProviderImpl_AddRef(IServiceProvider *iface)
2099 IServiceProviderImpl *This = (IServiceProviderImpl *)iface;
2100 return InterlockedIncrement(&This->ref);
2103 static ULONG WINAPI IServiceProviderImpl_Release(IServiceProvider *iface)
2105 IServiceProviderImpl *This = (IServiceProviderImpl *)iface;
2106 ULONG ref = InterlockedDecrement(&This->ref);
2108 if (!ref)
2110 HeapFree(GetProcessHeap(), 0, This);
2111 return 0;
2113 return ref;
2116 static HRESULT WINAPI IServiceProviderImpl_QueryService(
2117 IServiceProvider *iface, REFGUID service, REFIID riid, void **ppv)
2119 /* native uses redefined pointer for IID_IOleCommandTarget, not one from uuid.lib */
2120 if (IsEqualIID(riid, &IID_IOleCommandTarget))
2122 add_call(&trace_got, 2, iface, service, &IID_IOleCommandTarget, 0, 0);
2123 *ppv = IOleCommandTargetImpl_Construct();
2125 if (IsEqualIID(riid, &IID_IProfferService))
2127 if (IsEqualIID(service, &IID_IProfferService))
2128 add_call(&trace_got, 2, &IID_IProfferService, &IID_IProfferService, 0, 0, 0);
2129 *ppv = IProfferServiceImpl_Construct();
2131 return S_OK;
2134 static const IServiceProviderVtbl IServiceProviderImpl_Vtbl =
2136 IServiceProviderImpl_QueryInterface,
2137 IServiceProviderImpl_AddRef,
2138 IServiceProviderImpl_Release,
2139 IServiceProviderImpl_QueryService
2142 static void test_IUnknown_QueryServiceExec(void)
2144 IServiceProvider *provider = IServiceProviderImpl_Construct();
2145 static const GUID dummy_serviceid = { 0xdeadbeef };
2146 static const GUID dummy_groupid = { 0xbeefbeef };
2147 call_trace_t trace_expected;
2148 HRESULT hr;
2150 /* on <=W2K platforms same ordinal used for another export with different
2151 prototype, so skipping using this indirect condition */
2152 if (is_win2k_and_lower)
2154 win_skip("IUnknown_QueryServiceExec is not available\n");
2155 return;
2158 /* null source pointer */
2159 hr = pIUnknown_QueryServiceExec(NULL, &dummy_serviceid, &dummy_groupid, 0, 0, 0, 0);
2160 ok(hr == E_FAIL, "got 0x%08x\n", hr);
2162 /* expected trace:
2163 IUnknown_QueryServiceExec( ptr1, serviceid, groupid, arg1, arg2, arg3, arg4);
2164 -> IUnknown_QueryInterface( ptr1, &IID_IServiceProvider, &prov );
2165 -> IServiceProvider_QueryService( prov, serviceid, &IID_IOleCommandTarget, &obj );
2166 -> IOleCommandTarget_Exec( obj, groupid, arg1, arg2, arg3, arg4 );
2168 init_call_trace(&trace_expected);
2170 add_call(&trace_expected, 1, provider, &IID_IServiceProvider, 0, 0, 0);
2171 add_call(&trace_expected, 2, provider, &dummy_serviceid, &IID_IOleCommandTarget, 0, 0);
2172 add_call(&trace_expected, 3, &dummy_groupid, (void*)0x1, (void*)0x2, (void*)0x3, (void*)0x4);
2174 init_call_trace(&trace_got);
2175 hr = pIUnknown_QueryServiceExec((IUnknown*)provider, &dummy_serviceid, &dummy_groupid, 0x1, 0x2, (void*)0x3, (void*)0x4);
2176 ok(hr == S_OK, "got 0x%08x\n", hr);
2178 ok_trace(&trace_expected, &trace_got);
2180 free_call_trace(&trace_expected);
2181 free_call_trace(&trace_got);
2183 IServiceProvider_Release(provider);
2187 static HRESULT WINAPI IProfferServiceImpl_QueryInterface(IProfferService *iface, REFIID riid, void **ppvObj)
2189 IProfferServiceImpl *This = (IProfferServiceImpl *)iface;
2191 if (IsEqualIID(riid, &IID_IUnknown) ||
2192 IsEqualIID(riid, &IID_IProfferService))
2194 *ppvObj = This;
2196 else if (IsEqualIID(riid, &IID_IServiceProvider))
2198 *ppvObj = IServiceProviderImpl_Construct();
2199 add_call(&trace_got, 1, iface, &IID_IServiceProvider, 0, 0, 0);
2200 return S_OK;
2203 if(*ppvObj)
2205 IUnknown_AddRef(iface);
2206 return S_OK;
2209 return E_NOINTERFACE;
2212 static ULONG WINAPI IProfferServiceImpl_AddRef(IProfferService *iface)
2214 IProfferServiceImpl *This = (IProfferServiceImpl *)iface;
2215 return InterlockedIncrement(&This->ref);
2218 static ULONG WINAPI IProfferServiceImpl_Release(IProfferService *iface)
2220 IProfferServiceImpl *This = (IProfferServiceImpl *)iface;
2221 ULONG ref = InterlockedDecrement(&This->ref);
2223 if (!ref)
2225 HeapFree(GetProcessHeap(), 0, This);
2226 return 0;
2228 return ref;
2231 static HRESULT WINAPI IProfferServiceImpl_ProfferService(IProfferService *iface,
2232 REFGUID service, IServiceProvider *pService, DWORD *pCookie)
2234 add_call(&trace_got, 3, service, pService, pCookie, 0, 0);
2235 return S_OK;
2238 static HRESULT WINAPI IProfferServiceImpl_RevokeService(IProfferService *iface, DWORD cookie)
2240 add_call(&trace_got, 4, (void*)(DWORD_PTR)cookie, 0, 0, 0, 0);
2241 return S_OK;
2244 static const IProfferServiceVtbl IProfferServiceImpl_Vtbl =
2246 IProfferServiceImpl_QueryInterface,
2247 IProfferServiceImpl_AddRef,
2248 IProfferServiceImpl_Release,
2249 IProfferServiceImpl_ProfferService,
2250 IProfferServiceImpl_RevokeService
2253 static void test_IUnknown_ProfferService(void)
2255 IServiceProvider *provider = IServiceProviderImpl_Construct();
2256 IProfferService *proff = IProfferServiceImpl_Construct();
2257 static const GUID dummy_serviceid = { 0xdeadbeef };
2258 call_trace_t trace_expected;
2259 HRESULT hr;
2260 DWORD cookie;
2262 /* on <=W2K platforms same ordinal used for another export with different
2263 prototype, so skipping using this indirect condition */
2264 if (is_win2k_and_lower)
2266 win_skip("IUnknown_ProfferService is not available\n");
2267 return;
2270 /* null source pointer */
2271 hr = pIUnknown_ProfferService(NULL, &dummy_serviceid, 0, 0);
2272 ok(hr == E_FAIL, "got 0x%08x\n", hr);
2274 /* expected trace:
2275 IUnknown_ProfferService( ptr1, serviceid, arg1, arg2);
2276 -> IUnknown_QueryInterface( ptr1, &IID_IServiceProvider, &provider );
2277 -> IServiceProvider_QueryService( provider, &IID_IProfferService, &IID_IProfferService, &proffer );
2279 if (service pointer not null):
2280 -> IProfferService_ProfferService( proffer, serviceid, arg1, arg2 );
2281 else
2282 -> IProfferService_RevokeService( proffer, *arg2 );
2284 init_call_trace(&trace_expected);
2286 add_call(&trace_expected, 1, proff, &IID_IServiceProvider, 0, 0, 0);
2287 add_call(&trace_expected, 2, &IID_IProfferService, &IID_IProfferService, 0, 0, 0);
2288 add_call(&trace_expected, 3, &dummy_serviceid, provider, &cookie, 0, 0);
2290 init_call_trace(&trace_got);
2291 hr = pIUnknown_ProfferService((IUnknown*)proff, &dummy_serviceid, provider, &cookie);
2292 ok(hr == S_OK, "got 0x%08x\n", hr);
2294 ok_trace(&trace_expected, &trace_got);
2295 free_call_trace(&trace_got);
2296 free_call_trace(&trace_expected);
2298 /* same with ::Revoke path */
2299 init_call_trace(&trace_expected);
2301 add_call(&trace_expected, 1, proff, &IID_IServiceProvider, 0, 0, 0);
2302 add_call(&trace_expected, 2, &IID_IProfferService, &IID_IProfferService, 0, 0, 0);
2303 add_call(&trace_expected, 4, (void*)(DWORD_PTR)cookie, 0, 0, 0, 0);
2305 init_call_trace(&trace_got);
2306 hr = pIUnknown_ProfferService((IUnknown*)proff, &dummy_serviceid, 0, &cookie);
2307 ok(hr == S_OK, "got 0x%08x\n", hr);
2308 ok_trace(&trace_expected, &trace_got);
2309 free_call_trace(&trace_got);
2310 free_call_trace(&trace_expected);
2312 IServiceProvider_Release(provider);
2313 IProfferService_Release(proff);
2316 static void test_SHCreateWorkerWindowA(void)
2318 WNDCLASSA cliA;
2319 char classA[20];
2320 HWND hwnd;
2321 LONG_PTR ret;
2322 BOOL res;
2324 if (is_win2k_and_lower)
2326 win_skip("SHCreateWorkerWindowA not available\n");
2327 return;
2330 hwnd = pSHCreateWorkerWindowA(0, NULL, 0, 0, 0, 0);
2331 ok(hwnd != 0, "expected window\n");
2333 GetClassName(hwnd, classA, 20);
2334 ok(lstrcmpA(classA, "WorkerA") == 0, "expected WorkerA class, got %s\n", classA);
2336 ret = GetWindowLongPtrA(hwnd, 0);
2337 ok(ret == 0, "got %ld\n", ret);
2339 /* class info */
2340 memset(&cliA, 0, sizeof(cliA));
2341 res = GetClassInfoA(GetModuleHandle("shlwapi.dll"), "WorkerA", &cliA);
2342 ok(res, "failed to get class info\n");
2343 ok(cliA.style == 0, "got 0x%08x\n", cliA.style);
2344 ok(cliA.cbClsExtra == 0, "got %d\n", cliA.cbClsExtra);
2345 ok(cliA.cbWndExtra == sizeof(LONG_PTR), "got %d\n", cliA.cbWndExtra);
2346 ok(cliA.lpszMenuName == 0, "got %s\n", cliA.lpszMenuName);
2348 DestroyWindow(hwnd);
2350 /* set extra bytes */
2351 hwnd = pSHCreateWorkerWindowA(0, NULL, 0, 0, 0, 0xdeadbeef);
2352 ok(hwnd != 0, "expected window\n");
2354 GetClassName(hwnd, classA, 20);
2355 ok(lstrcmpA(classA, "WorkerA") == 0, "expected WorkerA class, got %s\n", classA);
2357 ret = GetWindowLongPtrA(hwnd, 0);
2358 ok(ret == 0xdeadbeef, "got %ld\n", ret);
2360 /* test exstyle */
2361 ret = GetWindowLongA(hwnd, GWL_EXSTYLE);
2362 ok(ret == WS_EX_WINDOWEDGE, "0x%08lx\n", ret);
2364 DestroyWindow(hwnd);
2366 hwnd = pSHCreateWorkerWindowA(0, NULL, WS_EX_TOOLWINDOW, 0, 0, 0);
2367 ret = GetWindowLongA(hwnd, GWL_EXSTYLE);
2368 ok(ret == (WS_EX_WINDOWEDGE|WS_EX_TOOLWINDOW), "0x%08lx\n", ret);
2369 DestroyWindow(hwnd);
2372 static void init_pointers(void)
2374 #define MAKEFUNC(f, ord) (p##f = (void*)GetProcAddress(hShlwapi, (LPSTR)(ord)))
2375 MAKEFUNC(SHAllocShared, 7);
2376 MAKEFUNC(SHLockShared, 8);
2377 MAKEFUNC(SHUnlockShared, 9);
2378 MAKEFUNC(SHFreeShared, 10);
2379 MAKEFUNC(GetAcceptLanguagesA, 14);
2380 MAKEFUNC(SHSetWindowBits, 165);
2381 MAKEFUNC(ConnectToConnectionPoint, 168);
2382 MAKEFUNC(SHSearchMapInt, 198);
2383 MAKEFUNC(SHCreateWorkerWindowA, 257);
2384 MAKEFUNC(GUIDFromStringA, 269);
2385 MAKEFUNC(SHPackDispParams, 282);
2386 MAKEFUNC(IConnectionPoint_InvokeWithCancel, 283);
2387 MAKEFUNC(IConnectionPoint_SimpleInvoke, 284);
2388 MAKEFUNC(SHFormatDateTimeA, 353);
2389 MAKEFUNC(SHFormatDateTimeW, 354);
2390 MAKEFUNC(SHGetObjectCompatFlags, 476);
2391 MAKEFUNC(IUnknown_QueryServiceExec, 484);
2392 MAKEFUNC(SHPropertyBag_ReadLONG, 496);
2393 MAKEFUNC(IUnknown_ProfferService, 514);
2394 #undef MAKEFUNC
2397 START_TEST(ordinal)
2399 hShlwapi = GetModuleHandleA("shlwapi.dll");
2400 is_win2k_and_lower = GetProcAddress(hShlwapi, "StrChrNW") == 0;
2402 init_pointers();
2404 hmlang = LoadLibraryA("mlang.dll");
2405 pLcidToRfc1766A = (void *)GetProcAddress(hmlang, "LcidToRfc1766A");
2407 test_GetAcceptLanguagesA();
2408 test_SHSearchMapInt();
2409 test_alloc_shared();
2410 test_fdsa();
2411 test_GetShellSecurityDescriptor();
2412 test_SHPackDispParams();
2413 test_IConnectionPoint();
2414 test_SHPropertyBag_ReadLONG();
2415 test_SHSetWindowBits();
2416 test_SHFormatDateTimeA();
2417 test_SHFormatDateTimeW();
2418 test_SHGetObjectCompatFlags();
2419 test_IUnknown_QueryServiceExec();
2420 test_IUnknown_ProfferService();
2421 test_SHCreateWorkerWindowA();