shlwapi: Implement IUnknown_QueryServiceExec with tests.
[wine/hacks.git] / dlls / shlwapi / tests / ordinal.c
blob2906f6985595b5982821f60aff77e13408d93b9a
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"
34 /* Function ptrs for ordinal calls */
35 static HMODULE hShlwapi;
36 static int (WINAPI *pSHSearchMapInt)(const int*,const int*,int,int);
37 static HRESULT (WINAPI *pGetAcceptLanguagesA)(LPSTR,LPDWORD);
39 static HANDLE (WINAPI *pSHAllocShared)(LPCVOID,DWORD,DWORD);
40 static LPVOID (WINAPI *pSHLockShared)(HANDLE,DWORD);
41 static BOOL (WINAPI *pSHUnlockShared)(LPVOID);
42 static BOOL (WINAPI *pSHFreeShared)(HANDLE,DWORD);
43 static HRESULT(WINAPIV *pSHPackDispParams)(DISPPARAMS*,VARIANTARG*,UINT,...);
44 static HRESULT(WINAPI *pIConnectionPoint_SimpleInvoke)(IConnectionPoint*,DISPID,DISPPARAMS*);
45 static HRESULT(WINAPI *pIConnectionPoint_InvokeWithCancel)(IConnectionPoint*,DISPID,DISPPARAMS*,DWORD,DWORD);
46 static HRESULT(WINAPI *pConnectToConnectionPoint)(IUnknown*,REFIID,BOOL,IUnknown*, LPDWORD,IConnectionPoint **);
47 static HRESULT(WINAPI *pSHPropertyBag_ReadLONG)(IPropertyBag *,LPCWSTR,LPLONG);
48 static LONG (WINAPI *pSHSetWindowBits)(HWND, INT, UINT, UINT);
49 static INT (WINAPI *pSHFormatDateTimeA)(const FILETIME UNALIGNED*, DWORD*, LPSTR, UINT);
50 static INT (WINAPI *pSHFormatDateTimeW)(const FILETIME UNALIGNED*, DWORD*, LPWSTR, UINT);
51 static DWORD (WINAPI *pSHGetObjectCompatFlags)(IUnknown*, const CLSID*);
52 static BOOL (WINAPI *pGUIDFromStringA)(LPSTR, CLSID *);
53 static HRESULT (WINAPI *pIUnknown_QueryServiceExec)(IUnknown*, REFIID, const GUID*, DWORD, DWORD, VARIANT*, VARIANT*);
55 static HMODULE hmlang;
56 static HRESULT (WINAPI *pLcidToRfc1766A)(LCID, LPSTR, INT);
58 static const CHAR ie_international[] = {
59 'S','o','f','t','w','a','r','e','\\',
60 'M','i','c','r','o','s','o','f','t','\\',
61 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
62 'I','n','t','e','r','n','a','t','i','o','n','a','l',0};
63 static const CHAR acceptlanguage[] = {
64 'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0};
66 typedef struct {
67 int id;
68 const void *args[5];
69 } call_entry_t;
71 typedef struct {
72 call_entry_t *calls;
73 int count;
74 int alloc;
75 } call_trace_t;
77 static void init_call_trace(call_trace_t *ctrace)
79 ctrace->alloc = 10;
80 ctrace->count = 0;
81 ctrace->calls = HeapAlloc(GetProcessHeap(), 0, sizeof(call_entry_t) * ctrace->alloc);
84 static void free_call_trace(const call_trace_t *ctrace)
86 HeapFree(GetProcessHeap(), 0, ctrace->calls);
89 static void add_call(call_trace_t *ctrace, int id, const void *arg0,
90 const void *arg1, const void *arg2, const void *arg3, const void *arg4)
92 call_entry_t call;
94 call.id = id;
95 call.args[0] = arg0;
96 call.args[1] = arg1;
97 call.args[2] = arg2;
98 call.args[3] = arg3;
99 call.args[4] = arg4;
101 if (ctrace->count == ctrace->alloc)
103 ctrace->alloc *= 2;
104 ctrace->calls = HeapReAlloc(GetProcessHeap(),0, ctrace->calls, ctrace->alloc*sizeof(call_entry_t));
107 ctrace->calls[ctrace->count++] = call;
110 static void test_GetAcceptLanguagesA(void)
112 static LPCSTR table[] = {"de,en-gb;q=0.7,en;q=0.3",
113 "de,en;q=0.3,en-gb;q=0.7", /* sorting is ignored */
114 "winetest", /* content is ignored */
115 "de-de,de;q=0.5",
116 "de",
117 NULL};
119 DWORD exactsize;
120 char original[512];
121 char language[32];
122 char buffer[64];
123 HKEY hroot = NULL;
124 LONG res_query = ERROR_SUCCESS;
125 LONG lres;
126 HRESULT hr;
127 DWORD maxlen = sizeof(buffer) - 2;
128 DWORD len;
129 LCID lcid;
130 LPCSTR entry;
131 INT i = 0;
133 if (!pGetAcceptLanguagesA) {
134 win_skip("GetAcceptLanguagesA is not available\n");
135 return;
138 lcid = GetUserDefaultLCID();
140 /* Get the original Value */
141 lres = RegOpenKeyA(HKEY_CURRENT_USER, ie_international, &hroot);
142 if (lres) {
143 skip("RegOpenKey(%s) failed: %d\n", ie_international, lres);
144 return;
146 len = sizeof(original);
147 original[0] = 0;
148 res_query = RegQueryValueExA(hroot, acceptlanguage, 0, NULL, (PBYTE)original, &len);
150 RegDeleteValue(hroot, acceptlanguage);
152 /* Some windows versions use "lang-COUNTRY" as default */
153 memset(language, 0, sizeof(language));
154 len = GetLocaleInfoA(lcid, LOCALE_SISO639LANGNAME, language, sizeof(language));
156 if (len) {
157 lstrcat(language, "-");
158 memset(buffer, 0, sizeof(buffer));
159 len = GetLocaleInfoA(lcid, LOCALE_SISO3166CTRYNAME, buffer, sizeof(buffer) - len - 1);
160 lstrcat(language, buffer);
162 else
164 /* LOCALE_SNAME has additional parts in some languages. Try only as last chance */
165 memset(language, 0, sizeof(language));
166 len = GetLocaleInfoA(lcid, LOCALE_SNAME, language, sizeof(language));
169 /* get the default value */
170 len = maxlen;
171 memset(buffer, '#', maxlen);
172 buffer[maxlen] = 0;
173 hr = pGetAcceptLanguagesA( buffer, &len);
175 if (hr != S_OK) {
176 win_skip("GetAcceptLanguagesA failed with 0x%x\n", hr);
177 goto restore_original;
180 if (lstrcmpA(buffer, language)) {
181 /* some windows versions use "lang" or "lang-country" as default */
182 language[0] = 0;
183 if (pLcidToRfc1766A) {
184 hr = pLcidToRfc1766A(lcid, language, sizeof(language));
185 ok(hr == S_OK, "LcidToRfc1766A returned 0x%x and %s\n", hr, language);
189 ok(!lstrcmpA(buffer, language),
190 "have '%s' (searching for '%s')\n", language, buffer);
192 if (lstrcmpA(buffer, language)) {
193 win_skip("no more ideas, how to build the default language '%s'\n", buffer);
194 goto restore_original;
197 trace("detected default: %s\n", language);
198 while ((entry = table[i])) {
200 exactsize = lstrlenA(entry);
202 lres = RegSetValueExA(hroot, acceptlanguage, 0, REG_SZ, (const BYTE *) entry, exactsize + 1);
203 ok(!lres, "got %d for RegSetValueExA: %s\n", lres, entry);
205 /* len includes space for the terminating 0 before vista/w2k8 */
206 len = exactsize + 2;
207 memset(buffer, '#', maxlen);
208 buffer[maxlen] = 0;
209 hr = pGetAcceptLanguagesA( buffer, &len);
210 ok(((hr == E_INVALIDARG) && (len == 0)) ||
211 (SUCCEEDED(hr) &&
212 ((len == exactsize) || (len == exactsize+1)) &&
213 !lstrcmpA(buffer, entry)),
214 "+2_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
216 len = exactsize + 1;
217 memset(buffer, '#', maxlen);
218 buffer[maxlen] = 0;
219 hr = pGetAcceptLanguagesA( buffer, &len);
220 ok(((hr == E_INVALIDARG) && (len == 0)) ||
221 (SUCCEEDED(hr) &&
222 ((len == exactsize) || (len == exactsize+1)) &&
223 !lstrcmpA(buffer, entry)),
224 "+1_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
226 len = exactsize;
227 memset(buffer, '#', maxlen);
228 buffer[maxlen] = 0;
229 hr = pGetAcceptLanguagesA( buffer, &len);
231 /* There is no space for the string in the registry.
232 When the buffer is large enough, the default language is returned
234 When the buffer is too small for that fallback, win7_32 and w2k8_64
235 and above fail with HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), but
236 recent os succeed and return a partial result while
237 older os succeed and overflow the buffer */
239 ok(((hr == E_INVALIDARG) && (len == 0)) ||
240 (((hr == S_OK) && !lstrcmpA(buffer, language) && (len == lstrlenA(language))) ||
241 ((hr == S_OK) && !memcmp(buffer, language, len)) ||
242 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len)),
243 "==_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
245 if (exactsize > 1) {
246 len = exactsize - 1;
247 memset(buffer, '#', maxlen);
248 buffer[maxlen] = 0;
249 hr = pGetAcceptLanguagesA( buffer, &len);
250 ok(((hr == E_INVALIDARG) && (len == 0)) ||
251 (((hr == S_OK) && !lstrcmpA(buffer, language) && (len == lstrlenA(language))) ||
252 ((hr == S_OK) && !memcmp(buffer, language, len)) ||
253 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len)),
254 "-1_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
257 len = 1;
258 memset(buffer, '#', maxlen);
259 buffer[maxlen] = 0;
260 hr = pGetAcceptLanguagesA( buffer, &len);
261 ok(((hr == E_INVALIDARG) && (len == 0)) ||
262 (((hr == S_OK) && !lstrcmpA(buffer, language) && (len == lstrlenA(language))) ||
263 ((hr == S_OK) && !memcmp(buffer, language, len)) ||
264 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len)),
265 "=1_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
267 len = maxlen;
268 hr = pGetAcceptLanguagesA( NULL, &len);
270 /* w2k3 and below: E_FAIL and untouched len,
271 since w2k8: S_OK and needed size (excluding 0) */
272 ok( ((hr == S_OK) && (len == exactsize)) ||
273 ((hr == E_FAIL) && (len == maxlen)),
274 "NULL,max #%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
276 i++;
279 /* without a value in the registry, a default language is returned */
280 RegDeleteValue(hroot, acceptlanguage);
282 len = maxlen;
283 memset(buffer, '#', maxlen);
284 buffer[maxlen] = 0;
285 hr = pGetAcceptLanguagesA( buffer, &len);
286 ok( ((hr == S_OK) && (len == lstrlenA(language))),
287 "max: got 0x%x with %d and %s (expected S_OK with %d and '%s'\n",
288 hr, len, buffer, lstrlenA(language), language);
290 len = 2;
291 memset(buffer, '#', maxlen);
292 buffer[maxlen] = 0;
293 hr = pGetAcceptLanguagesA( buffer, &len);
294 ok( (((hr == S_OK) || (hr == E_INVALIDARG)) && !memcmp(buffer, language, len)) ||
295 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len),
296 "=2: got 0x%x with %d and %s\n", hr, len, buffer);
298 len = 1;
299 memset(buffer, '#', maxlen);
300 buffer[maxlen] = 0;
301 hr = pGetAcceptLanguagesA( buffer, &len);
302 /* When the buffer is too small, win7_32 and w2k8_64 and above fail with
303 HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), other versions suceed
304 and return a partial 0 terminated result while other versions
305 fail with E_INVALIDARG and return a partial unterminated result */
306 ok( (((hr == S_OK) || (hr == E_INVALIDARG)) && !memcmp(buffer, language, len)) ||
307 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len),
308 "=1: got 0x%x with %d and %s\n", hr, len, buffer);
310 len = 0;
311 memset(buffer, '#', maxlen);
312 buffer[maxlen] = 0;
313 hr = pGetAcceptLanguagesA( buffer, &len);
314 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
315 ok((hr == E_FAIL) || (hr == E_INVALIDARG),
316 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr);
318 memset(buffer, '#', maxlen);
319 buffer[maxlen] = 0;
320 hr = pGetAcceptLanguagesA( buffer, NULL);
321 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
322 ok((hr == E_FAIL) || (hr == E_INVALIDARG),
323 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr);
326 hr = pGetAcceptLanguagesA( NULL, NULL);
327 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
328 ok((hr == E_FAIL) || (hr == E_INVALIDARG),
329 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr);
331 restore_original:
332 if (!res_query) {
333 len = lstrlenA(original);
334 lres = RegSetValueExA(hroot, acceptlanguage, 0, REG_SZ, (const BYTE *) original, len ? len + 1: 0);
335 ok(!lres, "RegSetValueEx(%s) failed: %d\n", original, lres);
337 else
339 RegDeleteValue(hroot, acceptlanguage);
341 RegCloseKey(hroot);
344 static void test_SHSearchMapInt(void)
346 int keys[8], values[8];
347 int i = 0;
349 if (!pSHSearchMapInt)
350 return;
352 memset(keys, 0, sizeof(keys));
353 memset(values, 0, sizeof(values));
354 keys[0] = 99; values[0] = 101;
356 /* NULL key/value lists crash native, so skip testing them */
358 /* 1 element */
359 i = pSHSearchMapInt(keys, values, 1, keys[0]);
360 ok(i == values[0], "Len 1, expected %d, got %d\n", values[0], i);
362 /* Key doesn't exist */
363 i = pSHSearchMapInt(keys, values, 1, 100);
364 ok(i == -1, "Len 1 - bad key, expected -1, got %d\n", i);
366 /* Len = 0 => not found */
367 i = pSHSearchMapInt(keys, values, 0, keys[0]);
368 ok(i == -1, "Len 1 - passed len 0, expected -1, got %d\n", i);
370 /* 2 elements, len = 1 */
371 keys[1] = 98; values[1] = 102;
372 i = pSHSearchMapInt(keys, values, 1, keys[1]);
373 ok(i == -1, "Len 1 - array len 2, expected -1, got %d\n", i);
375 /* 2 elements, len = 2 */
376 i = pSHSearchMapInt(keys, values, 2, keys[1]);
377 ok(i == values[1], "Len 2, expected %d, got %d\n", values[1], i);
379 /* Searches forward */
380 keys[2] = 99; values[2] = 103;
381 i = pSHSearchMapInt(keys, values, 3, keys[0]);
382 ok(i == values[0], "Len 3, expected %d, got %d\n", values[0], i);
385 static void test_alloc_shared(void)
387 DWORD procid;
388 HANDLE hmem;
389 int val;
390 int* p;
391 BOOL ret;
393 procid=GetCurrentProcessId();
394 hmem=pSHAllocShared(NULL,10,procid);
395 ok(hmem!=NULL,"SHAllocShared(NULL...) failed: %u\n", GetLastError());
396 ret = pSHFreeShared(hmem, procid);
397 ok( ret, "SHFreeShared failed: %u\n", GetLastError());
399 val=0x12345678;
400 hmem=pSHAllocShared(&val,4,procid);
401 ok(hmem!=NULL,"SHAllocShared(NULL...) failed: %u\n", GetLastError());
403 p=pSHLockShared(hmem,procid);
404 ok(p!=NULL,"SHLockShared failed: %u\n", GetLastError());
405 if (p!=NULL)
406 ok(*p==val,"Wrong value in shared memory: %d instead of %d\n",*p,val);
407 ret = pSHUnlockShared(p);
408 ok( ret, "SHUnlockShared failed: %u\n", GetLastError());
410 ret = pSHFreeShared(hmem, procid);
411 ok( ret, "SHFreeShared failed: %u\n", GetLastError());
414 static void test_fdsa(void)
416 typedef struct
418 DWORD num_items; /* Number of elements inserted */
419 void *mem; /* Ptr to array */
420 DWORD blocks_alloced; /* Number of elements allocated */
421 BYTE inc; /* Number of elements to grow by when we need to expand */
422 BYTE block_size; /* Size in bytes of an element */
423 BYTE flags; /* Flags */
424 } FDSA_info;
426 BOOL (WINAPI *pFDSA_Initialize)(DWORD block_size, DWORD inc, FDSA_info *info, void *mem,
427 DWORD init_blocks);
428 BOOL (WINAPI *pFDSA_Destroy)(FDSA_info *info);
429 DWORD (WINAPI *pFDSA_InsertItem)(FDSA_info *info, DWORD where, const void *block);
430 BOOL (WINAPI *pFDSA_DeleteItem)(FDSA_info *info, DWORD where);
432 FDSA_info info;
433 int block_size = 10, init_blocks = 4, inc = 2;
434 DWORD ret;
435 char *mem;
437 pFDSA_Initialize = (void *)GetProcAddress(hShlwapi, (LPSTR)208);
438 pFDSA_Destroy = (void *)GetProcAddress(hShlwapi, (LPSTR)209);
439 pFDSA_InsertItem = (void *)GetProcAddress(hShlwapi, (LPSTR)210);
440 pFDSA_DeleteItem = (void *)GetProcAddress(hShlwapi, (LPSTR)211);
442 mem = HeapAlloc(GetProcessHeap(), 0, block_size * init_blocks);
443 memset(&info, 0, sizeof(info));
445 ok(pFDSA_Initialize(block_size, inc, &info, mem, init_blocks), "FDSA_Initialize rets FALSE\n");
446 ok(info.num_items == 0, "num_items = %d\n", info.num_items);
447 ok(info.mem == mem, "mem = %p\n", info.mem);
448 ok(info.blocks_alloced == init_blocks, "blocks_alloced = %d\n", info.blocks_alloced);
449 ok(info.inc == inc, "inc = %d\n", info.inc);
450 ok(info.block_size == block_size, "block_size = %d\n", info.block_size);
451 ok(info.flags == 0, "flags = %d\n", info.flags);
453 ret = pFDSA_InsertItem(&info, 1234, "1234567890");
454 ok(ret == 0, "ret = %d\n", ret);
455 ok(info.num_items == 1, "num_items = %d\n", info.num_items);
456 ok(info.mem == mem, "mem = %p\n", info.mem);
457 ok(info.blocks_alloced == init_blocks, "blocks_alloced = %d\n", info.blocks_alloced);
458 ok(info.inc == inc, "inc = %d\n", info.inc);
459 ok(info.block_size == block_size, "block_size = %d\n", info.block_size);
460 ok(info.flags == 0, "flags = %d\n", info.flags);
462 ret = pFDSA_InsertItem(&info, 1234, "abcdefghij");
463 ok(ret == 1, "ret = %d\n", ret);
465 ret = pFDSA_InsertItem(&info, 1, "klmnopqrst");
466 ok(ret == 1, "ret = %d\n", ret);
468 ret = pFDSA_InsertItem(&info, 0, "uvwxyzABCD");
469 ok(ret == 0, "ret = %d\n", ret);
470 ok(info.mem == mem, "mem = %p\n", info.mem);
471 ok(info.flags == 0, "flags = %d\n", info.flags);
473 /* This next InsertItem will cause shlwapi to allocate its own mem buffer */
474 ret = pFDSA_InsertItem(&info, 0, "EFGHIJKLMN");
475 ok(ret == 0, "ret = %d\n", ret);
476 ok(info.mem != mem, "mem = %p\n", info.mem);
477 ok(info.blocks_alloced == init_blocks + inc, "blocks_alloced = %d\n", info.blocks_alloced);
478 ok(info.flags == 0x1, "flags = %d\n", info.flags);
480 ok(!memcmp(info.mem, "EFGHIJKLMNuvwxyzABCD1234567890klmnopqrstabcdefghij", 50), "mem %s\n", (char*)info.mem);
482 ok(pFDSA_DeleteItem(&info, 2), "rets FALSE\n");
483 ok(info.mem != mem, "mem = %p\n", info.mem);
484 ok(info.blocks_alloced == init_blocks + inc, "blocks_alloced = %d\n", info.blocks_alloced);
485 ok(info.flags == 0x1, "flags = %d\n", info.flags);
487 ok(!memcmp(info.mem, "EFGHIJKLMNuvwxyzABCDklmnopqrstabcdefghij", 40), "mem %s\n", (char*)info.mem);
489 ok(pFDSA_DeleteItem(&info, 3), "rets FALSE\n");
490 ok(info.mem != mem, "mem = %p\n", info.mem);
491 ok(info.blocks_alloced == init_blocks + inc, "blocks_alloced = %d\n", info.blocks_alloced);
492 ok(info.flags == 0x1, "flags = %d\n", info.flags);
494 ok(!memcmp(info.mem, "EFGHIJKLMNuvwxyzABCDklmnopqrst", 30), "mem %s\n", (char*)info.mem);
496 ok(!pFDSA_DeleteItem(&info, 4), "does not ret FALSE\n");
498 /* As shlwapi has allocated memory internally, Destroy will ret FALSE */
499 ok(!pFDSA_Destroy(&info), "FDSA_Destroy does not ret FALSE\n");
502 /* When Initialize is called with inc = 0, set it to 1 */
503 ok(pFDSA_Initialize(block_size, 0, &info, mem, init_blocks), "FDSA_Initialize rets FALSE\n");
504 ok(info.inc == 1, "inc = %d\n", info.inc);
506 /* This time, because shlwapi hasn't had to allocate memory
507 internally, Destroy rets non-zero */
508 ok(pFDSA_Destroy(&info), "FDSA_Destroy rets FALSE\n");
511 HeapFree(GetProcessHeap(), 0, mem);
515 typedef struct SHELL_USER_SID {
516 SID_IDENTIFIER_AUTHORITY sidAuthority;
517 DWORD dwUserGroupID;
518 DWORD dwUserID;
519 } SHELL_USER_SID, *PSHELL_USER_SID;
520 typedef struct SHELL_USER_PERMISSION {
521 SHELL_USER_SID susID;
522 DWORD dwAccessType;
523 BOOL fInherit;
524 DWORD dwAccessMask;
525 DWORD dwInheritMask;
526 DWORD dwInheritAccessMask;
527 } SHELL_USER_PERMISSION, *PSHELL_USER_PERMISSION;
528 static void test_GetShellSecurityDescriptor(void)
530 SHELL_USER_PERMISSION supCurrentUserFull = {
531 { {SECURITY_NULL_SID_AUTHORITY}, 0, 0 },
532 ACCESS_ALLOWED_ACE_TYPE, FALSE,
533 GENERIC_ALL, 0, 0 };
534 #define MY_INHERITANCE 0xBE /* invalid value to proof behavior */
535 SHELL_USER_PERMISSION supEveryoneDenied = {
536 { {SECURITY_WORLD_SID_AUTHORITY}, SECURITY_WORLD_RID, 0 },
537 ACCESS_DENIED_ACE_TYPE, TRUE,
538 GENERIC_WRITE, MY_INHERITANCE | 0xDEADBA00, GENERIC_READ };
539 PSHELL_USER_PERMISSION rgsup[2] = {
540 &supCurrentUserFull, &supEveryoneDenied,
542 SECURITY_DESCRIPTOR* psd;
543 SECURITY_DESCRIPTOR* (WINAPI*pGetShellSecurityDescriptor)(PSHELL_USER_PERMISSION*,int);
545 pGetShellSecurityDescriptor=(void*)GetProcAddress(hShlwapi,(char*)475);
547 if(!pGetShellSecurityDescriptor)
549 win_skip("GetShellSecurityDescriptor not available\n");
550 return;
553 psd = pGetShellSecurityDescriptor(NULL, 2);
554 ok(psd==NULL ||
555 broken(psd==INVALID_HANDLE_VALUE), /* IE5 */
556 "GetShellSecurityDescriptor should fail\n");
557 psd = pGetShellSecurityDescriptor(rgsup, 0);
558 ok(psd==NULL, "GetShellSecurityDescriptor should fail\n");
560 SetLastError(0xdeadbeef);
561 psd = pGetShellSecurityDescriptor(rgsup, 2);
562 if (psd == NULL && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
564 /* The previous calls to GetShellSecurityDescriptor don't set the last error */
565 win_skip("GetShellSecurityDescriptor is not implemented\n");
566 return;
568 if (psd==INVALID_HANDLE_VALUE)
570 win_skip("GetShellSecurityDescriptor is broken on IE5\n");
571 return;
573 ok(psd!=NULL, "GetShellSecurityDescriptor failed\n");
574 if (psd!=NULL)
576 BOOL bHasDacl = FALSE, bDefaulted;
577 PACL pAcl;
578 DWORD dwRev;
579 SECURITY_DESCRIPTOR_CONTROL control;
581 ok(IsValidSecurityDescriptor(psd), "returned value is not valid SD\n");
583 ok(GetSecurityDescriptorControl(psd, &control, &dwRev),
584 "GetSecurityDescriptorControl failed with error %u\n", GetLastError());
585 ok(0 == (control & SE_SELF_RELATIVE), "SD should be absolute\n");
587 ok(GetSecurityDescriptorDacl(psd, &bHasDacl, &pAcl, &bDefaulted),
588 "GetSecurityDescriptorDacl failed with error %u\n", GetLastError());
590 ok(bHasDacl, "SD has no DACL\n");
591 if (bHasDacl)
593 ok(!bDefaulted, "DACL should not be defaulted\n");
595 ok(pAcl != NULL, "NULL DACL!\n");
596 if (pAcl != NULL)
598 ACL_SIZE_INFORMATION asiSize;
600 ok(IsValidAcl(pAcl), "DACL is not valid\n");
602 ok(GetAclInformation(pAcl, &asiSize, sizeof(asiSize), AclSizeInformation),
603 "GetAclInformation failed with error %u\n", GetLastError());
605 ok(asiSize.AceCount == 3, "Incorrect number of ACEs: %d entries\n", asiSize.AceCount);
606 if (asiSize.AceCount == 3)
608 ACCESS_ALLOWED_ACE *paaa; /* will use for DENIED too */
610 ok(GetAce(pAcl, 0, (LPVOID*)&paaa), "GetAce failed with error %u\n", GetLastError());
611 ok(paaa->Header.AceType == ACCESS_ALLOWED_ACE_TYPE,
612 "Invalid ACE type %d\n", paaa->Header.AceType);
613 ok(paaa->Header.AceFlags == 0, "Invalid ACE flags %x\n", paaa->Header.AceFlags);
614 ok(paaa->Mask == GENERIC_ALL, "Invalid ACE mask %x\n", paaa->Mask);
616 ok(GetAce(pAcl, 1, (LPVOID*)&paaa), "GetAce failed with error %u\n", GetLastError());
617 ok(paaa->Header.AceType == ACCESS_DENIED_ACE_TYPE,
618 "Invalid ACE type %d\n", paaa->Header.AceType);
619 /* first one of two ACEs generated from inheritable entry - without inheritance */
620 ok(paaa->Header.AceFlags == 0, "Invalid ACE flags %x\n", paaa->Header.AceFlags);
621 ok(paaa->Mask == GENERIC_WRITE, "Invalid ACE mask %x\n", paaa->Mask);
623 ok(GetAce(pAcl, 2, (LPVOID*)&paaa), "GetAce failed with error %u\n", GetLastError());
624 ok(paaa->Header.AceType == ACCESS_DENIED_ACE_TYPE,
625 "Invalid ACE type %d\n", paaa->Header.AceType);
626 /* second ACE - with inheritance */
627 ok(paaa->Header.AceFlags == MY_INHERITANCE,
628 "Invalid ACE flags %x\n", paaa->Header.AceFlags);
629 ok(paaa->Mask == GENERIC_READ, "Invalid ACE mask %x\n", paaa->Mask);
634 LocalFree(psd);
638 static void test_SHPackDispParams(void)
640 DISPPARAMS params;
641 VARIANT vars[10];
642 HRESULT hres;
644 if(!pSHPackDispParams)
645 win_skip("SHPackSidpParams not available\n");
647 memset(&params, 0xc0, sizeof(params));
648 memset(vars, 0xc0, sizeof(vars));
649 hres = pSHPackDispParams(&params, vars, 1, VT_I4, 0xdeadbeef);
650 ok(hres == S_OK, "SHPackDispParams failed: %08x\n", hres);
651 ok(params.cArgs == 1, "params.cArgs = %d\n", params.cArgs);
652 ok(params.cNamedArgs == 0, "params.cNamedArgs = %d\n", params.cArgs);
653 ok(params.rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", params.rgdispidNamedArgs);
654 ok(params.rgvarg == vars, "params.rgvarg = %p\n", params.rgvarg);
655 ok(V_VT(vars) == VT_I4, "V_VT(var) = %d\n", V_VT(vars));
656 ok(V_I4(vars) == 0xdeadbeef, "failed %x\n", V_I4(vars));
658 memset(&params, 0xc0, sizeof(params));
659 hres = pSHPackDispParams(&params, NULL, 0, 0);
660 ok(hres == S_OK, "SHPackDispParams failed: %08x\n", hres);
661 ok(params.cArgs == 0, "params.cArgs = %d\n", params.cArgs);
662 ok(params.cNamedArgs == 0, "params.cNamedArgs = %d\n", params.cArgs);
663 ok(params.rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", params.rgdispidNamedArgs);
664 ok(params.rgvarg == NULL, "params.rgvarg = %p\n", params.rgvarg);
666 memset(vars, 0xc0, sizeof(vars));
667 memset(&params, 0xc0, sizeof(params));
668 hres = pSHPackDispParams(&params, vars, 4, VT_BSTR, (void*)0xdeadbeef, VT_EMPTY, 10,
669 VT_I4, 100, VT_DISPATCH, (void*)0xdeadbeef);
670 ok(hres == S_OK, "SHPackDispParams failed: %08x\n", hres);
671 ok(params.cArgs == 4, "params.cArgs = %d\n", params.cArgs);
672 ok(params.cNamedArgs == 0, "params.cNamedArgs = %d\n", params.cArgs);
673 ok(params.rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", params.rgdispidNamedArgs);
674 ok(params.rgvarg == vars, "params.rgvarg = %p\n", params.rgvarg);
675 ok(V_VT(vars) == VT_DISPATCH, "V_VT(vars[0]) = %x\n", V_VT(vars));
676 ok(V_I4(vars) == 0xdeadbeef, "V_I4(vars[0]) = %x\n", V_I4(vars));
677 ok(V_VT(vars+1) == VT_I4, "V_VT(vars[1]) = %d\n", V_VT(vars+1));
678 ok(V_I4(vars+1) == 100, "V_I4(vars[1]) = %x\n", V_I4(vars+1));
679 ok(V_VT(vars+2) == VT_I4, "V_VT(vars[2]) = %d\n", V_VT(vars+2));
680 ok(V_I4(vars+2) == 10, "V_I4(vars[2]) = %x\n", V_I4(vars+2));
681 ok(V_VT(vars+3) == VT_BSTR, "V_VT(vars[3]) = %d\n", V_VT(vars+3));
682 ok(V_BSTR(vars+3) == (void*)0xdeadbeef, "V_BSTR(vars[3]) = %p\n", V_BSTR(vars+3));
685 typedef struct _disp
687 const IDispatchVtbl *vtbl;
688 LONG refCount;
689 } Disp;
691 typedef struct _contain
693 const IConnectionPointContainerVtbl *vtbl;
694 LONG refCount;
696 UINT ptCount;
697 IConnectionPoint **pt;
698 } Contain;
700 typedef struct _cntptn
702 const IConnectionPointVtbl *vtbl;
703 LONG refCount;
705 Contain *container;
706 GUID id;
707 UINT sinkCount;
708 IUnknown **sink;
709 } ConPt;
711 typedef struct _enum
713 const IEnumConnectionsVtbl *vtbl;
714 LONG refCount;
716 UINT idx;
717 ConPt *pt;
718 } EnumCon;
720 typedef struct _enumpt
722 const IEnumConnectionPointsVtbl *vtbl;
723 LONG refCount;
725 int idx;
726 Contain *container;
727 } EnumPt;
730 static HRESULT WINAPI Disp_QueryInterface(
731 IDispatch* This,
732 REFIID riid,
733 void **ppvObject)
735 *ppvObject = NULL;
737 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch))
739 *ppvObject = This;
742 if (*ppvObject)
744 IUnknown_AddRef(This);
745 return S_OK;
748 trace("no interface\n");
749 return E_NOINTERFACE;
752 static ULONG WINAPI Disp_AddRef(IDispatch* This)
754 Disp *iface = (Disp*)This;
755 return InterlockedIncrement(&iface->refCount);
758 static ULONG WINAPI Disp_Release(IDispatch* This)
760 Disp *iface = (Disp*)This;
761 ULONG ret;
763 ret = InterlockedDecrement(&iface->refCount);
764 if (ret == 0)
765 HeapFree(GetProcessHeap(),0,This);
766 return ret;
769 static HRESULT WINAPI Disp_GetTypeInfoCount(
770 IDispatch* This,
771 UINT *pctinfo)
773 return ERROR_SUCCESS;
776 static HRESULT WINAPI Disp_GetTypeInfo(
777 IDispatch* This,
778 UINT iTInfo,
779 LCID lcid,
780 ITypeInfo **ppTInfo)
782 return ERROR_SUCCESS;
785 static HRESULT WINAPI Disp_GetIDsOfNames(
786 IDispatch* This,
787 REFIID riid,
788 LPOLESTR *rgszNames,
789 UINT cNames,
790 LCID lcid,
791 DISPID *rgDispId)
793 return ERROR_SUCCESS;
796 static HRESULT WINAPI Disp_Invoke(
797 IDispatch* This,
798 DISPID dispIdMember,
799 REFIID riid,
800 LCID lcid,
801 WORD wFlags,
802 DISPPARAMS *pDispParams,
803 VARIANT *pVarResult,
804 EXCEPINFO *pExcepInfo,
805 UINT *puArgErr)
807 trace("%p %x %p %x %x %p %p %p %p\n",This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr);
809 ok(dispIdMember == 0xa0 || dispIdMember == 0xa1, "Unknown dispIdMember\n");
810 ok(pDispParams != NULL, "Invoked with NULL pDispParams\n");
811 ok(wFlags == DISPATCH_METHOD, "Wrong flags %x\n",wFlags);
812 ok(lcid == 0,"Wrong lcid %x\n",lcid);
813 if (dispIdMember == 0xa0)
815 ok(pDispParams->cArgs == 0, "params.cArgs = %d\n", pDispParams->cArgs);
816 ok(pDispParams->cNamedArgs == 0, "params.cNamedArgs = %d\n", pDispParams->cArgs);
817 ok(pDispParams->rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", pDispParams->rgdispidNamedArgs);
818 ok(pDispParams->rgvarg == NULL, "params.rgvarg = %p\n", pDispParams->rgvarg);
820 else if (dispIdMember == 0xa1)
822 ok(pDispParams->cArgs == 2, "params.cArgs = %d\n", pDispParams->cArgs);
823 ok(pDispParams->cNamedArgs == 0, "params.cNamedArgs = %d\n", pDispParams->cArgs);
824 ok(pDispParams->rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", pDispParams->rgdispidNamedArgs);
825 ok(V_VT(pDispParams->rgvarg) == VT_BSTR, "V_VT(var) = %d\n", V_VT(pDispParams->rgvarg));
826 ok(V_I4(pDispParams->rgvarg) == 0xdeadcafe , "failed %p\n", V_BSTR(pDispParams->rgvarg));
827 ok(V_VT(pDispParams->rgvarg+1) == VT_I4, "V_VT(var) = %d\n", V_VT(pDispParams->rgvarg+1));
828 ok(V_I4(pDispParams->rgvarg+1) == 0xdeadbeef, "failed %x\n", V_I4(pDispParams->rgvarg+1));
831 return ERROR_SUCCESS;
834 static const IDispatchVtbl disp_vtbl = {
835 Disp_QueryInterface,
836 Disp_AddRef,
837 Disp_Release,
839 Disp_GetTypeInfoCount,
840 Disp_GetTypeInfo,
841 Disp_GetIDsOfNames,
842 Disp_Invoke
845 static HRESULT WINAPI Enum_QueryInterface(
846 IEnumConnections* This,
847 REFIID riid,
848 void **ppvObject)
850 *ppvObject = NULL;
852 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IEnumConnections))
854 *ppvObject = This;
857 if (*ppvObject)
859 IUnknown_AddRef(This);
860 return S_OK;
863 trace("no interface\n");
864 return E_NOINTERFACE;
867 static ULONG WINAPI Enum_AddRef(IEnumConnections* This)
869 EnumCon *iface = (EnumCon*)This;
870 return InterlockedIncrement(&iface->refCount);
873 static ULONG WINAPI Enum_Release(IEnumConnections* This)
875 EnumCon *iface = (EnumCon*)This;
876 ULONG ret;
878 ret = InterlockedDecrement(&iface->refCount);
879 if (ret == 0)
880 HeapFree(GetProcessHeap(),0,This);
881 return ret;
884 static HRESULT WINAPI Enum_Next(
885 IEnumConnections* This,
886 ULONG cConnections,
887 LPCONNECTDATA rgcd,
888 ULONG *pcFetched)
890 EnumCon *iface = (EnumCon*)This;
892 if (cConnections > 0 && iface->idx < iface->pt->sinkCount)
894 rgcd->pUnk = iface->pt->sink[iface->idx];
895 IUnknown_AddRef(iface->pt->sink[iface->idx]);
896 rgcd->dwCookie=0xff;
897 if (pcFetched)
898 *pcFetched = 1;
899 iface->idx++;
900 return S_OK;
903 return E_FAIL;
906 static HRESULT WINAPI Enum_Skip(
907 IEnumConnections* This,
908 ULONG cConnections)
910 return E_FAIL;
913 static HRESULT WINAPI Enum_Reset(
914 IEnumConnections* This)
916 return E_FAIL;
919 static HRESULT WINAPI Enum_Clone(
920 IEnumConnections* This,
921 IEnumConnections **ppEnum)
923 return E_FAIL;
926 static const IEnumConnectionsVtbl enum_vtbl = {
928 Enum_QueryInterface,
929 Enum_AddRef,
930 Enum_Release,
931 Enum_Next,
932 Enum_Skip,
933 Enum_Reset,
934 Enum_Clone
937 static HRESULT WINAPI ConPt_QueryInterface(
938 IConnectionPoint* This,
939 REFIID riid,
940 void **ppvObject)
942 *ppvObject = NULL;
944 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IConnectionPoint))
946 *ppvObject = This;
949 if (*ppvObject)
951 IUnknown_AddRef(This);
952 return S_OK;
955 trace("no interface\n");
956 return E_NOINTERFACE;
959 static ULONG WINAPI ConPt_AddRef(
960 IConnectionPoint* This)
962 ConPt *iface = (ConPt*)This;
963 return InterlockedIncrement(&iface->refCount);
966 static ULONG WINAPI ConPt_Release(
967 IConnectionPoint* This)
969 ConPt *iface = (ConPt*)This;
970 ULONG ret;
972 ret = InterlockedDecrement(&iface->refCount);
973 if (ret == 0)
975 if (iface->sinkCount > 0)
977 int i;
978 for (i = 0; i < iface->sinkCount; i++)
980 if (iface->sink[i])
981 IUnknown_Release(iface->sink[i]);
983 HeapFree(GetProcessHeap(),0,iface->sink);
985 HeapFree(GetProcessHeap(),0,This);
987 return ret;
990 static HRESULT WINAPI ConPt_GetConnectionInterface(
991 IConnectionPoint* This,
992 IID *pIID)
994 static int i = 0;
995 ConPt *iface = (ConPt*)This;
996 if (i==0)
998 i++;
999 return E_FAIL;
1001 else
1002 memcpy(pIID,&iface->id,sizeof(GUID));
1003 return S_OK;
1006 static HRESULT WINAPI ConPt_GetConnectionPointContainer(
1007 IConnectionPoint* This,
1008 IConnectionPointContainer **ppCPC)
1010 ConPt *iface = (ConPt*)This;
1012 *ppCPC = (IConnectionPointContainer*)iface->container;
1013 return S_OK;
1016 static HRESULT WINAPI ConPt_Advise(
1017 IConnectionPoint* This,
1018 IUnknown *pUnkSink,
1019 DWORD *pdwCookie)
1021 ConPt *iface = (ConPt*)This;
1023 if (iface->sinkCount == 0)
1024 iface->sink = HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown*));
1025 else
1026 iface->sink = HeapReAlloc(GetProcessHeap(),0,iface->sink,sizeof(IUnknown*)*(iface->sinkCount+1));
1027 iface->sink[iface->sinkCount] = pUnkSink;
1028 IUnknown_AddRef(pUnkSink);
1029 iface->sinkCount++;
1030 *pdwCookie = iface->sinkCount;
1031 return S_OK;
1034 static HRESULT WINAPI ConPt_Unadvise(
1035 IConnectionPoint* This,
1036 DWORD dwCookie)
1038 ConPt *iface = (ConPt*)This;
1040 if (dwCookie > iface->sinkCount)
1041 return E_FAIL;
1042 else
1044 IUnknown_Release(iface->sink[dwCookie-1]);
1045 iface->sink[dwCookie-1] = NULL;
1047 return S_OK;
1050 static HRESULT WINAPI ConPt_EnumConnections(
1051 IConnectionPoint* This,
1052 IEnumConnections **ppEnum)
1054 EnumCon *ec;
1056 ec = HeapAlloc(GetProcessHeap(),0,sizeof(EnumCon));
1057 ec->vtbl = &enum_vtbl;
1058 ec->refCount = 1;
1059 ec->pt = (ConPt*)This;
1060 ec->idx = 0;
1061 *ppEnum = (IEnumConnections*)ec;
1063 return S_OK;
1066 static const IConnectionPointVtbl point_vtbl = {
1067 ConPt_QueryInterface,
1068 ConPt_AddRef,
1069 ConPt_Release,
1071 ConPt_GetConnectionInterface,
1072 ConPt_GetConnectionPointContainer,
1073 ConPt_Advise,
1074 ConPt_Unadvise,
1075 ConPt_EnumConnections
1078 static HRESULT WINAPI EnumPt_QueryInterface(
1079 IEnumConnectionPoints* This,
1080 REFIID riid,
1081 void **ppvObject)
1083 *ppvObject = NULL;
1085 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IEnumConnectionPoints))
1087 *ppvObject = This;
1090 if (*ppvObject)
1092 IUnknown_AddRef(This);
1093 return S_OK;
1096 trace("no interface\n");
1097 return E_NOINTERFACE;
1100 static ULONG WINAPI EnumPt_AddRef(IEnumConnectionPoints* This)
1102 EnumPt *iface = (EnumPt*)This;
1103 return InterlockedIncrement(&iface->refCount);
1106 static ULONG WINAPI EnumPt_Release(IEnumConnectionPoints* This)
1108 EnumPt *iface = (EnumPt*)This;
1109 ULONG ret;
1111 ret = InterlockedDecrement(&iface->refCount);
1112 if (ret == 0)
1113 HeapFree(GetProcessHeap(),0,This);
1114 return ret;
1117 static HRESULT WINAPI EnumPt_Next(
1118 IEnumConnectionPoints* This,
1119 ULONG cConnections,
1120 IConnectionPoint **rgcd,
1121 ULONG *pcFetched)
1123 EnumPt *iface = (EnumPt*)This;
1125 if (cConnections > 0 && iface->idx < iface->container->ptCount)
1127 *rgcd = iface->container->pt[iface->idx];
1128 IUnknown_AddRef(iface->container->pt[iface->idx]);
1129 if (pcFetched)
1130 *pcFetched = 1;
1131 iface->idx++;
1132 return S_OK;
1135 return E_FAIL;
1138 static HRESULT WINAPI EnumPt_Skip(
1139 IEnumConnectionPoints* This,
1140 ULONG cConnections)
1142 return E_FAIL;
1145 static HRESULT WINAPI EnumPt_Reset(
1146 IEnumConnectionPoints* This)
1148 return E_FAIL;
1151 static HRESULT WINAPI EnumPt_Clone(
1152 IEnumConnectionPoints* This,
1153 IEnumConnectionPoints **ppEnumPt)
1155 return E_FAIL;
1158 static const IEnumConnectionPointsVtbl enumpt_vtbl = {
1160 EnumPt_QueryInterface,
1161 EnumPt_AddRef,
1162 EnumPt_Release,
1163 EnumPt_Next,
1164 EnumPt_Skip,
1165 EnumPt_Reset,
1166 EnumPt_Clone
1169 static HRESULT WINAPI Contain_QueryInterface(
1170 IConnectionPointContainer* This,
1171 REFIID riid,
1172 void **ppvObject)
1174 *ppvObject = NULL;
1176 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IConnectionPointContainer))
1178 *ppvObject = This;
1181 if (*ppvObject)
1183 IUnknown_AddRef(This);
1184 return S_OK;
1187 trace("no interface\n");
1188 return E_NOINTERFACE;
1191 static ULONG WINAPI Contain_AddRef(
1192 IConnectionPointContainer* This)
1194 Contain *iface = (Contain*)This;
1195 return InterlockedIncrement(&iface->refCount);
1198 static ULONG WINAPI Contain_Release(
1199 IConnectionPointContainer* This)
1201 Contain *iface = (Contain*)This;
1202 ULONG ret;
1204 ret = InterlockedDecrement(&iface->refCount);
1205 if (ret == 0)
1207 if (iface->ptCount > 0)
1209 int i;
1210 for (i = 0; i < iface->ptCount; i++)
1211 IUnknown_Release(iface->pt[i]);
1212 HeapFree(GetProcessHeap(),0,iface->pt);
1214 HeapFree(GetProcessHeap(),0,This);
1216 return ret;
1219 static HRESULT WINAPI Contain_EnumConnectionPoints(
1220 IConnectionPointContainer* This,
1221 IEnumConnectionPoints **ppEnum)
1223 EnumPt *ec;
1225 ec = HeapAlloc(GetProcessHeap(),0,sizeof(EnumPt));
1226 ec->vtbl = &enumpt_vtbl;
1227 ec->refCount = 1;
1228 ec->idx= 0;
1229 ec->container = (Contain*)This;
1230 *ppEnum = (IEnumConnectionPoints*)ec;
1232 return S_OK;
1235 static HRESULT WINAPI Contain_FindConnectionPoint(
1236 IConnectionPointContainer* This,
1237 REFIID riid,
1238 IConnectionPoint **ppCP)
1240 Contain *iface = (Contain*)This;
1241 ConPt *pt;
1243 if (!IsEqualIID(riid, &IID_NULL) || iface->ptCount ==0)
1245 pt = HeapAlloc(GetProcessHeap(),0,sizeof(ConPt));
1246 pt->vtbl = &point_vtbl;
1247 pt->refCount = 1;
1248 pt->sinkCount = 0;
1249 pt->sink = NULL;
1250 pt->container = iface;
1251 pt->id = IID_IDispatch;
1253 if (iface->ptCount == 0)
1254 iface->pt =HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown*));
1255 else
1256 iface->pt = HeapReAlloc(GetProcessHeap(),0,iface->pt,sizeof(IUnknown*)*(iface->ptCount+1));
1257 iface->pt[iface->ptCount] = (IConnectionPoint*)pt;
1258 iface->ptCount++;
1260 *ppCP = (IConnectionPoint*)pt;
1262 else
1264 *ppCP = iface->pt[0];
1265 IUnknown_AddRef((IUnknown*)*ppCP);
1268 return S_OK;
1271 static const IConnectionPointContainerVtbl contain_vtbl = {
1272 Contain_QueryInterface,
1273 Contain_AddRef,
1274 Contain_Release,
1276 Contain_EnumConnectionPoints,
1277 Contain_FindConnectionPoint
1280 static void test_IConnectionPoint(void)
1282 HRESULT rc;
1283 ULONG ref;
1284 IConnectionPoint *point;
1285 Contain *container;
1286 Disp *dispatch;
1287 DWORD cookie = 0xffffffff;
1288 DISPPARAMS params;
1289 VARIANT vars[10];
1291 if (!pIConnectionPoint_SimpleInvoke || !pConnectToConnectionPoint)
1293 win_skip("IConnectionPoint Apis not present\n");
1294 return;
1297 container = HeapAlloc(GetProcessHeap(),0,sizeof(Contain));
1298 container->vtbl = &contain_vtbl;
1299 container->refCount = 1;
1300 container->ptCount = 0;
1301 container->pt = NULL;
1303 dispatch = HeapAlloc(GetProcessHeap(),0,sizeof(Disp));
1304 dispatch->vtbl = &disp_vtbl;
1305 dispatch->refCount = 1;
1307 rc = pConnectToConnectionPoint((IUnknown*)dispatch, &IID_NULL, TRUE, (IUnknown*)container, &cookie, &point);
1308 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
1309 ok(point != NULL, "returned ConnectionPoint is NULL\n");
1310 ok(cookie != 0xffffffff, "invalid cookie returned\n");
1312 rc = pIConnectionPoint_SimpleInvoke(point,0xa0,NULL);
1313 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
1315 if (pSHPackDispParams)
1317 memset(&params, 0xc0, sizeof(params));
1318 memset(vars, 0xc0, sizeof(vars));
1319 rc = pSHPackDispParams(&params, vars, 2, VT_I4, 0xdeadbeef, VT_BSTR, 0xdeadcafe);
1320 ok(rc == S_OK, "SHPackDispParams failed: %08x\n", rc);
1322 rc = pIConnectionPoint_SimpleInvoke(point,0xa1,&params);
1323 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
1325 else
1326 win_skip("pSHPackDispParams not present\n");
1328 rc = pConnectToConnectionPoint(NULL, &IID_NULL, FALSE, (IUnknown*)container, &cookie, NULL);
1329 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
1331 /* MSDN says this should be required but it crashs on XP
1332 IUnknown_Release(point);
1334 ref = IUnknown_Release((IUnknown*)container);
1335 ok(ref == 0, "leftover IConnectionPointContainer reference %i\n",ref);
1336 ref = IUnknown_Release((IUnknown*)dispatch);
1337 ok(ref == 0, "leftover IDispatch reference %i\n",ref);
1340 typedef struct _propbag
1342 const IPropertyBagVtbl *vtbl;
1343 LONG refCount;
1345 } PropBag;
1348 static HRESULT WINAPI Prop_QueryInterface(
1349 IPropertyBag* This,
1350 REFIID riid,
1351 void **ppvObject)
1353 *ppvObject = NULL;
1355 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IPropertyBag))
1357 *ppvObject = This;
1360 if (*ppvObject)
1362 IUnknown_AddRef(This);
1363 return S_OK;
1366 trace("no interface\n");
1367 return E_NOINTERFACE;
1370 static ULONG WINAPI Prop_AddRef(
1371 IPropertyBag* This)
1373 PropBag *iface = (PropBag*)This;
1374 return InterlockedIncrement(&iface->refCount);
1377 static ULONG WINAPI Prop_Release(
1378 IPropertyBag* This)
1380 PropBag *iface = (PropBag*)This;
1381 ULONG ret;
1383 ret = InterlockedDecrement(&iface->refCount);
1384 if (ret == 0)
1385 HeapFree(GetProcessHeap(),0,This);
1386 return ret;
1389 static HRESULT WINAPI Prop_Read(
1390 IPropertyBag* This,
1391 LPCOLESTR pszPropName,
1392 VARIANT *pVar,
1393 IErrorLog *pErrorLog)
1395 V_VT(pVar) = VT_BLOB|VT_BYREF;
1396 V_BYREF(pVar) = (LPVOID)0xdeadcafe;
1397 return S_OK;
1400 static HRESULT WINAPI Prop_Write(
1401 IPropertyBag* This,
1402 LPCOLESTR pszPropName,
1403 VARIANT *pVar)
1405 return S_OK;
1409 static const IPropertyBagVtbl prop_vtbl = {
1410 Prop_QueryInterface,
1411 Prop_AddRef,
1412 Prop_Release,
1414 Prop_Read,
1415 Prop_Write
1418 static void test_SHPropertyBag_ReadLONG(void)
1420 PropBag *pb;
1421 HRESULT rc;
1422 LONG out;
1423 static const WCHAR szName1[] = {'n','a','m','e','1',0};
1425 if (!pSHPropertyBag_ReadLONG)
1427 win_skip("SHPropertyBag_ReadLONG not present\n");
1428 return;
1431 pb = HeapAlloc(GetProcessHeap(),0,sizeof(PropBag));
1432 pb->refCount = 1;
1433 pb->vtbl = &prop_vtbl;
1435 out = 0xfeedface;
1436 rc = pSHPropertyBag_ReadLONG(NULL, szName1, &out);
1437 ok(rc == E_INVALIDARG || broken(rc == 0), "incorrect return %x\n",rc);
1438 ok(out == 0xfeedface, "value should not have changed\n");
1439 rc = pSHPropertyBag_ReadLONG((IPropertyBag*)pb, NULL, &out);
1440 ok(rc == E_INVALIDARG || broken(rc == 0) || broken(rc == 1), "incorrect return %x\n",rc);
1441 ok(out == 0xfeedface, "value should not have changed\n");
1442 rc = pSHPropertyBag_ReadLONG((IPropertyBag*)pb, szName1, NULL);
1443 ok(rc == E_INVALIDARG || broken(rc == 0) || broken(rc == 1), "incorrect return %x\n",rc);
1444 ok(out == 0xfeedface, "value should not have changed\n");
1445 rc = pSHPropertyBag_ReadLONG((IPropertyBag*)pb, szName1, &out);
1446 ok(rc == DISP_E_BADVARTYPE || broken(rc == 0) || broken(rc == 1), "incorrect return %x\n",rc);
1447 ok(out == 0xfeedface || broken(out == 0xfeedfa00), "value should not have changed %x\n",out);
1448 IUnknown_Release((IUnknown*)pb);
1453 static void test_SHSetWindowBits(void)
1455 HWND hwnd;
1456 DWORD style, styleold;
1457 WNDCLASSA clsA;
1459 if(!pSHSetWindowBits)
1461 win_skip("SHSetWindowBits is not available\n");
1462 return;
1465 clsA.style = 0;
1466 clsA.lpfnWndProc = DefWindowProcA;
1467 clsA.cbClsExtra = 0;
1468 clsA.cbWndExtra = 0;
1469 clsA.hInstance = GetModuleHandleA(NULL);
1470 clsA.hIcon = 0;
1471 clsA.hCursor = LoadCursorA(0, IDC_ARROW);
1472 clsA.hbrBackground = NULL;
1473 clsA.lpszMenuName = NULL;
1474 clsA.lpszClassName = "Shlwapi test class";
1475 RegisterClassA(&clsA);
1477 hwnd = CreateWindowA("Shlwapi test class", "Test", WS_VISIBLE, 0, 0, 100, 100,
1478 NULL, NULL, GetModuleHandle(NULL), 0);
1479 ok(IsWindow(hwnd), "failed to create window\n");
1481 /* null window */
1482 SetLastError(0xdeadbeef);
1483 style = pSHSetWindowBits(NULL, GWL_STYLE, 0, 0);
1484 ok(style == 0, "expected 0 retval, got %d\n", style);
1485 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE ||
1486 broken(GetLastError() == 0xdeadbeef), /* Win9x/WinMe */
1487 "expected ERROR_INVALID_WINDOW_HANDLE, got %d\n", GetLastError());
1489 /* zero mask, zero flags */
1490 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1491 style = pSHSetWindowBits(hwnd, GWL_STYLE, 0, 0);
1492 ok(styleold == style, "expected old style\n");
1493 ok(styleold == GetWindowLongA(hwnd, GWL_STYLE), "expected to keep old style\n");
1495 /* test mask */
1496 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1497 ok(styleold & WS_VISIBLE, "expected WS_VISIBLE\n");
1498 style = pSHSetWindowBits(hwnd, GWL_STYLE, WS_VISIBLE, 0);
1500 ok(style == styleold, "expected previous style, got %x\n", style);
1501 ok((GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE) == 0, "expected updated style\n");
1503 /* test mask, unset style bit used */
1504 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1505 style = pSHSetWindowBits(hwnd, GWL_STYLE, WS_VISIBLE, 0);
1506 ok(style == styleold, "expected previous style, got %x\n", style);
1507 ok(styleold == GetWindowLongA(hwnd, GWL_STYLE), "expected to keep old style\n");
1509 /* set back with flags */
1510 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1511 style = pSHSetWindowBits(hwnd, GWL_STYLE, WS_VISIBLE, WS_VISIBLE);
1512 ok(style == styleold, "expected previous style, got %x\n", style);
1513 ok(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE, "expected updated style\n");
1515 /* reset and try to set without a mask */
1516 pSHSetWindowBits(hwnd, GWL_STYLE, WS_VISIBLE, 0);
1517 ok((GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE) == 0, "expected updated style\n");
1518 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1519 style = pSHSetWindowBits(hwnd, GWL_STYLE, 0, WS_VISIBLE);
1520 ok(style == styleold, "expected previous style, got %x\n", style);
1521 ok((GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE) == 0, "expected updated style\n");
1523 DestroyWindow(hwnd);
1525 UnregisterClassA("Shlwapi test class", GetModuleHandleA(NULL));
1528 static void test_SHFormatDateTimeA(void)
1530 FILETIME UNALIGNED filetime;
1531 CHAR buff[100], buff2[100], buff3[100];
1532 SYSTEMTIME st;
1533 DWORD flags;
1534 INT ret;
1536 if(!pSHFormatDateTimeA)
1538 win_skip("pSHFormatDateTimeA isn't available\n");
1539 return;
1542 if (0)
1544 /* crashes on native */
1545 ret = pSHFormatDateTimeA(NULL, NULL, NULL, 0);
1548 GetLocalTime(&st);
1549 SystemTimeToFileTime(&st, &filetime);
1550 /* SHFormatDateTime expects input as utc */
1551 LocalFileTimeToFileTime(&filetime, &filetime);
1553 /* no way to get required buffer length here */
1554 SetLastError(0xdeadbeef);
1555 ret = pSHFormatDateTimeA(&filetime, NULL, NULL, 0);
1556 ok(ret == 0, "got %d\n", ret);
1557 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1559 SetLastError(0xdeadbeef);
1560 buff[0] = 'a'; buff[1] = 0;
1561 ret = pSHFormatDateTimeA(&filetime, NULL, buff, 0);
1562 ok(ret == 0, "got %d\n", ret);
1563 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1564 ok(buff[0] == 'a', "expected same string, got %s\n", buff);
1566 /* flags needs to have FDTF_NOAUTOREADINGORDER for these tests to succeed on Vista+ */
1568 /* all combinations documented as invalid succeeded */
1569 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTTIME | FDTF_LONGTIME;
1570 SetLastError(0xdeadbeef);
1571 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1572 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1573 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1575 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTDATE | FDTF_LONGDATE;
1576 SetLastError(0xdeadbeef);
1577 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1578 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1579 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1581 flags = FDTF_SHORTDATE | FDTF_LTRDATE | FDTF_RTLDATE;
1582 SetLastError(0xdeadbeef);
1583 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1584 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1585 ok(GetLastError() == 0xdeadbeef ||
1586 broken(GetLastError() == ERROR_INVALID_FLAGS), /* Win9x/WinMe */
1587 "expected 0xdeadbeef, got %d\n", GetLastError());
1589 /* now check returned strings */
1590 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTTIME;
1591 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1592 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1593 ret = GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff2, sizeof(buff2));
1594 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1595 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1597 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGTIME;
1598 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1599 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1600 ret = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2));
1601 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1602 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1604 /* both time flags */
1605 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGTIME | FDTF_SHORTTIME;
1606 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1607 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1608 ret = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2));
1609 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1610 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1612 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTDATE;
1613 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1614 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1615 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2));
1616 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1617 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1619 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGDATE;
1620 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1621 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1622 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
1623 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1624 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1626 /* both date flags */
1627 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGDATE | FDTF_SHORTDATE;
1628 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1629 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1630 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
1631 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1632 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1634 /* various combinations of date/time flags */
1635 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGDATE | FDTF_SHORTTIME;
1636 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1637 ok(ret == lstrlenA(buff)+1, "got %d, length %d\n", ret, lstrlenA(buff)+1);
1638 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
1639 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1640 strcat(buff2, ", ");
1641 ret = GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3));
1642 ok(ret == lstrlenA(buff3)+1, "got %d\n", ret);
1643 strcat(buff2, buff3);
1644 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1646 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGDATE | FDTF_LONGTIME;
1647 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1648 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1649 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
1650 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1651 strcat(buff2, ", ");
1652 ret = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3));
1653 ok(ret == lstrlenA(buff3)+1, "got %d\n", ret);
1654 strcat(buff2, buff3);
1655 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1657 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTDATE | FDTF_SHORTTIME;
1658 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1659 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1660 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2));
1661 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1662 strcat(buff2, " ");
1663 ret = GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3));
1664 ok(ret == lstrlenA(buff3)+1, "got %d\n", ret);
1665 strcat(buff2, buff3);
1666 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1668 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTDATE | FDTF_LONGTIME;
1669 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1670 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1671 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2));
1672 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1673 strcat(buff2, " ");
1674 ret = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3));
1675 ok(ret == lstrlenA(buff3)+1, "got %d\n", ret);
1676 strcat(buff2, buff3);
1677 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1680 static void test_SHFormatDateTimeW(void)
1682 FILETIME UNALIGNED filetime;
1683 WCHAR buff[100], buff2[100], buff3[100];
1684 SYSTEMTIME st;
1685 DWORD flags;
1686 INT ret;
1687 static const WCHAR spaceW[] = {' ',0};
1688 static const WCHAR commaW[] = {',',' ',0};
1690 if(!pSHFormatDateTimeW)
1692 win_skip("pSHFormatDateTimeW isn't available\n");
1693 return;
1696 if (0)
1698 /* crashes on native */
1699 ret = pSHFormatDateTimeW(NULL, NULL, NULL, 0);
1702 GetLocalTime(&st);
1703 SystemTimeToFileTime(&st, &filetime);
1704 /* SHFormatDateTime expects input as utc */
1705 LocalFileTimeToFileTime(&filetime, &filetime);
1707 /* no way to get required buffer length here */
1708 SetLastError(0xdeadbeef);
1709 ret = pSHFormatDateTimeW(&filetime, NULL, NULL, 0);
1710 ok(ret == 0, "got %d\n", ret);
1711 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1713 SetLastError(0xdeadbeef);
1714 buff[0] = 'a'; buff[1] = 0;
1715 ret = pSHFormatDateTimeW(&filetime, NULL, buff, 0);
1716 ok(ret == 0, "got %d\n", ret);
1717 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1718 ok(buff[0] == 'a', "expected same string\n");
1720 /* all combinations documented as invalid succeeded */
1721 flags = FDTF_SHORTTIME | FDTF_LONGTIME;
1722 SetLastError(0xdeadbeef);
1723 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1724 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1725 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1727 flags = FDTF_SHORTDATE | FDTF_LONGDATE;
1728 SetLastError(0xdeadbeef);
1729 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1730 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1731 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1733 flags = FDTF_SHORTDATE | FDTF_LTRDATE | FDTF_RTLDATE;
1734 SetLastError(0xdeadbeef);
1735 buff[0] = 0; /* NT4 doesn't clear the buffer on failure */
1736 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1737 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1738 ok(GetLastError() == 0xdeadbeef ||
1739 broken(GetLastError() == ERROR_INVALID_FLAGS), /* Win9x/WinMe/NT4 */
1740 "expected 0xdeadbeef, got %d\n", GetLastError());
1742 /* now check returned strings */
1743 flags = FDTF_SHORTTIME;
1744 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1745 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1746 SetLastError(0xdeadbeef);
1747 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1748 if (ret == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1750 win_skip("Needed W-functions are not implemented\n");
1751 return;
1753 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1754 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1756 flags = FDTF_LONGTIME;
1757 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1758 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1759 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1760 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1761 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1763 /* both time flags */
1764 flags = FDTF_LONGTIME | FDTF_SHORTTIME;
1765 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1766 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1767 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1768 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1769 ok(lstrcmpW(buff, buff2) == 0, "expected equal string\n");
1771 flags = FDTF_SHORTDATE;
1772 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1773 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1774 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1775 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1776 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1778 flags = FDTF_LONGDATE;
1779 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1780 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1781 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1782 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1783 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1785 /* both date flags */
1786 flags = FDTF_LONGDATE | FDTF_SHORTDATE;
1787 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1788 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1789 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1790 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1791 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1793 /* various combinations of date/time flags */
1794 flags = FDTF_LONGDATE | FDTF_SHORTTIME;
1795 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1796 ok(ret == lstrlenW(buff)+1, "got %d, length %d\n", ret, lstrlenW(buff)+1);
1797 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1798 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1799 lstrcatW(buff2, commaW);
1800 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
1801 ok(ret == lstrlenW(buff3)+1, "got %d\n", ret);
1802 lstrcatW(buff2, buff3);
1803 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1805 flags = FDTF_LONGDATE | FDTF_LONGTIME;
1806 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1807 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1808 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1809 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1810 lstrcatW(buff2, commaW);
1811 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
1812 ok(ret == lstrlenW(buff3)+1, "got %d\n", ret);
1813 lstrcatW(buff2, buff3);
1814 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1816 flags = FDTF_SHORTDATE | FDTF_SHORTTIME;
1817 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1818 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1819 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1820 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1821 lstrcatW(buff2, spaceW);
1822 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
1823 ok(ret == lstrlenW(buff3)+1, "got %d\n", ret);
1824 lstrcatW(buff2, buff3);
1825 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1827 flags = FDTF_SHORTDATE | FDTF_LONGTIME;
1828 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1829 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1830 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1831 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1832 lstrcatW(buff2, spaceW);
1833 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
1834 ok(ret == lstrlenW(buff3)+1, "got %d\n", ret);
1835 lstrcatW(buff2, buff3);
1836 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1839 static void test_SHGetObjectCompatFlags(void)
1841 struct compat_value {
1842 CHAR nameA[30];
1843 DWORD value;
1846 struct compat_value values[] = {
1847 { "OTNEEDSSFCACHE", 0x1 },
1848 { "NO_WEBVIEW", 0x2 },
1849 { "UNBINDABLE", 0x4 },
1850 { "PINDLL", 0x8 },
1851 { "NEEDSFILESYSANCESTOR", 0x10 },
1852 { "NOTAFILESYSTEM", 0x20 },
1853 { "CTXMENU_NOVERBS", 0x40 },
1854 { "CTXMENU_LIMITEDQI", 0x80 },
1855 { "COCREATESHELLFOLDERONLY", 0x100 },
1856 { "NEEDSSTORAGEANCESTOR", 0x200 },
1857 { "NOLEGACYWEBVIEW", 0x400 },
1858 { "CTXMENU_XPQCMFLAGS", 0x1000 },
1859 { "NOIPROPERTYSTORE", 0x2000 }
1862 static const char compat_path[] = "Software\\Microsoft\\Windows\\CurrentVersion\\ShellCompatibility\\Objects";
1863 CHAR keyA[39]; /* {CLSID} */
1864 HKEY root;
1865 DWORD ret;
1866 int i;
1868 if (!pSHGetObjectCompatFlags)
1870 win_skip("SHGetObjectCompatFlags isn't available\n");
1871 return;
1874 /* null args */
1875 ret = pSHGetObjectCompatFlags(NULL, NULL);
1876 ok(ret == 0, "got %d\n", ret);
1878 ret = RegOpenKeyA(HKEY_LOCAL_MACHINE, compat_path, &root);
1879 if (ret != ERROR_SUCCESS)
1881 skip("No compatibility class data found\n");
1882 return;
1885 for (i = 0; RegEnumKeyA(root, i, keyA, sizeof(keyA)) == ERROR_SUCCESS; i++)
1887 HKEY clsid_key;
1889 if (RegOpenKeyA(root, keyA, &clsid_key) == ERROR_SUCCESS)
1891 CHAR valueA[30];
1892 DWORD expected = 0, got, length = sizeof(valueA);
1893 CLSID clsid;
1894 int v;
1896 for (v = 0; RegEnumValueA(clsid_key, v, valueA, &length, NULL, NULL, NULL, NULL) == ERROR_SUCCESS; v++)
1898 int j;
1900 for (j = 0; j < sizeof(values)/sizeof(struct compat_value); j++)
1901 if (lstrcmpA(values[j].nameA, valueA) == 0)
1903 expected |= values[j].value;
1904 break;
1907 length = sizeof(valueA);
1910 pGUIDFromStringA(keyA, &clsid);
1911 got = pSHGetObjectCompatFlags(NULL, &clsid);
1912 ok(got == expected, "got 0x%08x, expected 0x%08x. Key %s\n", got, expected, keyA);
1914 RegCloseKey(clsid_key);
1918 RegCloseKey(root);
1921 static call_trace_t IUnknown_QueryServiceExec_trace;
1923 typedef struct {
1924 const IOleCommandTargetVtbl *lpVtbl;
1925 LONG ref;
1926 } IOleCommandTargetImpl;
1928 static const IOleCommandTargetVtbl IOleCommandTargetImpl_Vtbl;
1930 IOleCommandTarget* IOleCommandTargetImpl_Construct(void)
1932 IOleCommandTargetImpl *obj;
1934 obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*obj));
1935 obj->lpVtbl = &IOleCommandTargetImpl_Vtbl;
1936 obj->ref = 1;
1938 return (IOleCommandTarget*)obj;
1941 static HRESULT WINAPI IOleCommandTargetImpl_QueryInterface(IOleCommandTarget *iface, REFIID riid, void **ppvObj)
1943 IOleCommandTargetImpl *This = (IOleCommandTargetImpl *)iface;
1945 if (IsEqualIID(riid, &IID_IUnknown) ||
1946 IsEqualIID(riid, &IID_IOleCommandTarget))
1948 *ppvObj = This;
1951 if(*ppvObj)
1953 IUnknown_AddRef(iface);
1954 return S_OK;
1957 return E_NOINTERFACE;
1960 static ULONG WINAPI IOleCommandTargetImpl_AddRef(IOleCommandTarget *iface)
1962 IOleCommandTargetImpl *This = (IOleCommandTargetImpl *)iface;
1963 return InterlockedIncrement(&This->ref);
1966 static ULONG WINAPI IOleCommandTargetImpl_Release(IOleCommandTarget *iface)
1968 IOleCommandTargetImpl *This = (IOleCommandTargetImpl *)iface;
1969 ULONG ref = InterlockedDecrement(&This->ref);
1971 if (!ref)
1973 HeapFree(GetProcessHeap(), 0, This);
1974 return 0;
1976 return ref;
1979 static HRESULT WINAPI IOleCommandTargetImpl_QueryStatus(
1980 IOleCommandTarget *iface, const GUID *group, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText)
1982 return E_NOTIMPL;
1985 static HRESULT WINAPI IOleCommandTargetImpl_Exec(
1986 IOleCommandTarget *iface,
1987 const GUID *CmdGroup,
1988 DWORD nCmdID,
1989 DWORD nCmdexecopt,
1990 VARIANT *pvaIn,
1991 VARIANT *pvaOut)
1993 add_call(&IUnknown_QueryServiceExec_trace, 3, CmdGroup, (void*)nCmdID, (void*)nCmdexecopt, pvaIn, pvaOut);
1994 return S_OK;
1997 static const IOleCommandTargetVtbl IOleCommandTargetImpl_Vtbl =
1999 IOleCommandTargetImpl_QueryInterface,
2000 IOleCommandTargetImpl_AddRef,
2001 IOleCommandTargetImpl_Release,
2002 IOleCommandTargetImpl_QueryStatus,
2003 IOleCommandTargetImpl_Exec
2006 typedef struct {
2007 const IServiceProviderVtbl *lpVtbl;
2008 LONG ref;
2009 } IServiceProviderImpl;
2011 static const IServiceProviderVtbl IServiceProviderImpl_Vtbl;
2013 IServiceProvider* IServiceProviderImpl_Construct(void)
2015 IServiceProviderImpl *obj;
2017 obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*obj));
2018 obj->lpVtbl = &IServiceProviderImpl_Vtbl;
2019 obj->ref = 1;
2021 return (IServiceProvider*)obj;
2024 static HRESULT WINAPI IServiceProviderImpl_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppvObj)
2026 IServiceProviderImpl *This = (IServiceProviderImpl *)iface;
2028 if (IsEqualIID(riid, &IID_IUnknown) ||
2029 IsEqualIID(riid, &IID_IServiceProvider))
2031 *ppvObj = This;
2034 if(*ppvObj)
2036 IUnknown_AddRef(iface);
2037 /* native uses redefined IID_IServiceProvider symbol, so we can't compare pointers */
2038 if (IsEqualIID(riid, &IID_IServiceProvider))
2039 add_call(&IUnknown_QueryServiceExec_trace, 1, iface, &IID_IServiceProvider, 0, 0, 0);
2040 return S_OK;
2043 return E_NOINTERFACE;
2046 static ULONG WINAPI IServiceProviderImpl_AddRef(IServiceProvider *iface)
2048 IServiceProviderImpl *This = (IServiceProviderImpl *)iface;
2049 return InterlockedIncrement(&This->ref);
2052 static ULONG WINAPI IServiceProviderImpl_Release(IServiceProvider *iface)
2054 IServiceProviderImpl *This = (IServiceProviderImpl *)iface;
2055 ULONG ref = InterlockedDecrement(&This->ref);
2057 if (!ref)
2059 HeapFree(GetProcessHeap(), 0, This);
2060 return 0;
2062 return ref;
2065 static HRESULT WINAPI IServiceProviderImpl_QueryService(
2066 IServiceProvider *iface, REFGUID service, REFIID riid, void **ppv)
2068 /* natve uses redefined pointer for IID_IOleCommandTarget, not one from uuid.lib */
2069 if (IsEqualIID(riid, &IID_IOleCommandTarget))
2070 add_call(&IUnknown_QueryServiceExec_trace, 2, iface, service, &IID_IOleCommandTarget, 0, 0);
2071 *ppv = IOleCommandTargetImpl_Construct();
2072 return S_OK;
2075 static const IServiceProviderVtbl IServiceProviderImpl_Vtbl =
2077 IServiceProviderImpl_QueryInterface,
2078 IServiceProviderImpl_AddRef,
2079 IServiceProviderImpl_Release,
2080 IServiceProviderImpl_QueryService
2083 static void test_IUnknown_QueryServiceExec(void)
2085 IServiceProvider *provider = IServiceProviderImpl_Construct();
2086 void *test_ptr = (void*)GetProcAddress(hShlwapi, "StrChrNW");
2087 static const GUID dummy_serviceid = { 0xdeadbeef };
2088 static const GUID dummy_groupid = { 0xbeefbeef };
2089 call_trace_t trace_expected;
2090 HRESULT hr;
2091 INT i;
2093 /* on <=W2K platforms same ordinal used for another export with different
2094 prototype, so skipping using this indirect condition */
2095 if (!test_ptr)
2097 win_skip("IUnknown_QueryServiceExec is not available\n");
2098 return;
2101 /* null source pointer */
2102 hr = pIUnknown_QueryServiceExec(NULL, &dummy_serviceid, &dummy_groupid, 0, 0, 0, 0);
2103 ok(hr == E_FAIL, "got 0x%08x\n", hr);
2105 /* expected trace:
2106 IUnknown_QueryServiceExec( ptr1, serviceid, groupid, arg1, arg2, arg3, arg4);
2107 -> IUnknown_QueryInterface( ptr1, &IID_IServiceProvider, &prov );
2108 -> IServiceProvider_QueryService( prov, serviceid, &IID_IOleCommandTarget, &obj );
2109 -> IOleCommandTarget_Exec( obj, groupid, arg1, arg2, arg3, arg4 );
2111 init_call_trace(&trace_expected);
2113 add_call(&trace_expected, 1, provider, &IID_IServiceProvider, 0, 0, 0);
2114 add_call(&trace_expected, 2, provider, &dummy_serviceid, &IID_IOleCommandTarget, 0, 0);
2115 add_call(&trace_expected, 3, &dummy_groupid, (void*)0x1, (void*)0x2, (void*)0x3, (void*)0x4);
2117 init_call_trace(&IUnknown_QueryServiceExec_trace);
2118 hr = pIUnknown_QueryServiceExec((IUnknown*)provider, &dummy_serviceid, &dummy_groupid, 0x1, 0x2, (void*)0x3, (void*)0x4);
2119 ok(hr == S_OK, "got 0x%08x\n", hr);
2121 if (trace_expected.count == IUnknown_QueryServiceExec_trace.count)
2123 /* compare */
2124 for (i = 0; i < trace_expected.count; i++)
2126 call_entry_t *expected = &trace_expected.calls[i];
2127 call_entry_t *got = &IUnknown_QueryServiceExec_trace.calls[i];
2128 INT j;
2130 ok(expected->id == got->id, "got different ids %d: %d, %d\n", i+1, expected->id, got->id);
2132 for (j = 0; j < 5; j++)
2134 ok(expected->args[j] == got->args[j], "got different args[%d] for %d: %p, %p\n", j, i+1,
2135 expected->args[j], got->args[j]);
2139 else
2140 ok(0, "traces length mismatch expected %d, got %d\n", trace_expected.count, IUnknown_QueryServiceExec_trace.count);
2142 free_call_trace(&trace_expected);
2143 free_call_trace(&IUnknown_QueryServiceExec_trace);
2145 IServiceProvider_Release(provider);
2148 static void init_pointers(void)
2150 #define MAKEFUNC(f, ord) (p##f = (void*)GetProcAddress(hShlwapi, (LPSTR)(ord)))
2151 MAKEFUNC(SHAllocShared, 7);
2152 MAKEFUNC(SHLockShared, 8);
2153 MAKEFUNC(SHUnlockShared, 9);
2154 MAKEFUNC(SHFreeShared, 10);
2155 MAKEFUNC(GetAcceptLanguagesA, 14);
2156 MAKEFUNC(SHSetWindowBits, 165);
2157 MAKEFUNC(ConnectToConnectionPoint, 168);
2158 MAKEFUNC(SHSearchMapInt, 198);
2159 MAKEFUNC(GUIDFromStringA, 269);
2160 MAKEFUNC(SHPackDispParams, 282);
2161 MAKEFUNC(IConnectionPoint_InvokeWithCancel, 283);
2162 MAKEFUNC(IConnectionPoint_SimpleInvoke, 284);
2163 MAKEFUNC(SHFormatDateTimeA, 353);
2164 MAKEFUNC(SHFormatDateTimeW, 354);
2165 MAKEFUNC(SHGetObjectCompatFlags, 476);
2166 MAKEFUNC(IUnknown_QueryServiceExec, 484);
2167 MAKEFUNC(SHPropertyBag_ReadLONG, 496);
2168 #undef MAKEFUNC
2171 START_TEST(ordinal)
2173 hShlwapi = GetModuleHandleA("shlwapi.dll");
2175 init_pointers();
2177 hmlang = LoadLibraryA("mlang.dll");
2178 pLcidToRfc1766A = (void *)GetProcAddress(hmlang, "LcidToRfc1766A");
2180 test_GetAcceptLanguagesA();
2181 test_SHSearchMapInt();
2182 test_alloc_shared();
2183 test_fdsa();
2184 test_GetShellSecurityDescriptor();
2185 test_SHPackDispParams();
2186 test_IConnectionPoint();
2187 test_SHPropertyBag_ReadLONG();
2188 test_SHSetWindowBits();
2189 test_SHFormatDateTimeA();
2190 test_SHFormatDateTimeW();
2191 test_SHGetObjectCompatFlags();
2192 test_IUnknown_QueryServiceExec();