shlwapi: Partially implement SHGetObjectCompatFlags with tests.
[wine/wine-gecko.git] / dlls / shlwapi / tests / ordinal.c
blob223aac405b281f6b59d1bc5677b5a7ce098ed295
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"
33 /* Function ptrs for ordinal calls */
34 static HMODULE hShlwapi;
35 static int (WINAPI *pSHSearchMapInt)(const int*,const int*,int,int);
36 static HRESULT (WINAPI *pGetAcceptLanguagesA)(LPSTR,LPDWORD);
38 static HANDLE (WINAPI *pSHAllocShared)(LPCVOID,DWORD,DWORD);
39 static LPVOID (WINAPI *pSHLockShared)(HANDLE,DWORD);
40 static BOOL (WINAPI *pSHUnlockShared)(LPVOID);
41 static BOOL (WINAPI *pSHFreeShared)(HANDLE,DWORD);
42 static HRESULT(WINAPIV *pSHPackDispParams)(DISPPARAMS*,VARIANTARG*,UINT,...);
43 static HRESULT(WINAPI *pIConnectionPoint_SimpleInvoke)(IConnectionPoint*,DISPID,DISPPARAMS*);
44 static HRESULT(WINAPI *pIConnectionPoint_InvokeWithCancel)(IConnectionPoint*,DISPID,DISPPARAMS*,DWORD,DWORD);
45 static HRESULT(WINAPI *pConnectToConnectionPoint)(IUnknown*,REFIID,BOOL,IUnknown*, LPDWORD,IConnectionPoint **);
46 static HRESULT(WINAPI *pSHPropertyBag_ReadLONG)(IPropertyBag *,LPCWSTR,LPLONG);
47 static LONG (WINAPI *pSHSetWindowBits)(HWND, INT, UINT, UINT);
48 static INT (WINAPI *pSHFormatDateTimeA)(const FILETIME UNALIGNED*, DWORD*, LPSTR, UINT);
49 static INT (WINAPI *pSHFormatDateTimeW)(const FILETIME UNALIGNED*, DWORD*, LPWSTR, UINT);
50 static DWORD (WINAPI *pSHGetObjectCompatFlags)(IUnknown*, const CLSID*);
51 static BOOL (WINAPI *pGUIDFromStringA)(LPSTR, CLSID *);
53 static HMODULE hmlang;
54 static HRESULT (WINAPI *pLcidToRfc1766A)(LCID, LPSTR, INT);
56 static const CHAR ie_international[] = {
57 'S','o','f','t','w','a','r','e','\\',
58 'M','i','c','r','o','s','o','f','t','\\',
59 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
60 'I','n','t','e','r','n','a','t','i','o','n','a','l',0};
61 static const CHAR acceptlanguage[] = {
62 'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0};
65 static void test_GetAcceptLanguagesA(void)
67 static LPCSTR table[] = {"de,en-gb;q=0.7,en;q=0.3",
68 "de,en;q=0.3,en-gb;q=0.7", /* sorting is ignored */
69 "winetest", /* content is ignored */
70 "de-de,de;q=0.5",
71 "de",
72 NULL};
74 DWORD exactsize;
75 char original[512];
76 char language[32];
77 char buffer[64];
78 HKEY hroot = NULL;
79 LONG res_query = ERROR_SUCCESS;
80 LONG lres;
81 HRESULT hr;
82 DWORD maxlen = sizeof(buffer) - 2;
83 DWORD len;
84 LCID lcid;
85 LPCSTR entry;
86 INT i = 0;
88 if (!pGetAcceptLanguagesA) {
89 win_skip("GetAcceptLanguagesA is not available\n");
90 return;
93 lcid = GetUserDefaultLCID();
95 /* Get the original Value */
96 lres = RegOpenKeyA(HKEY_CURRENT_USER, ie_international, &hroot);
97 if (lres) {
98 skip("RegOpenKey(%s) failed: %d\n", ie_international, lres);
99 return;
101 len = sizeof(original);
102 original[0] = 0;
103 res_query = RegQueryValueExA(hroot, acceptlanguage, 0, NULL, (PBYTE)original, &len);
105 RegDeleteValue(hroot, acceptlanguage);
107 /* Some windows versions use "lang-COUNTRY" as default */
108 memset(language, 0, sizeof(language));
109 len = GetLocaleInfoA(lcid, LOCALE_SISO639LANGNAME, language, sizeof(language));
111 if (len) {
112 lstrcat(language, "-");
113 memset(buffer, 0, sizeof(buffer));
114 len = GetLocaleInfoA(lcid, LOCALE_SISO3166CTRYNAME, buffer, sizeof(buffer) - len - 1);
115 lstrcat(language, buffer);
117 else
119 /* LOCALE_SNAME has additional parts in some languages. Try only as last chance */
120 memset(language, 0, sizeof(language));
121 len = GetLocaleInfoA(lcid, LOCALE_SNAME, language, sizeof(language));
124 /* get the default value */
125 len = maxlen;
126 memset(buffer, '#', maxlen);
127 buffer[maxlen] = 0;
128 hr = pGetAcceptLanguagesA( buffer, &len);
130 if (hr != S_OK) {
131 win_skip("GetAcceptLanguagesA failed with 0x%x\n", hr);
132 goto restore_original;
135 if (lstrcmpA(buffer, language)) {
136 /* some windows versions use "lang" or "lang-country" as default */
137 language[0] = 0;
138 if (pLcidToRfc1766A) {
139 hr = pLcidToRfc1766A(lcid, language, sizeof(language));
140 ok(hr == S_OK, "LcidToRfc1766A returned 0x%x and %s\n", hr, language);
144 ok(!lstrcmpA(buffer, language),
145 "have '%s' (searching for '%s')\n", language, buffer);
147 if (lstrcmpA(buffer, language)) {
148 win_skip("no more ideas, how to build the default language '%s'\n", buffer);
149 goto restore_original;
152 trace("detected default: %s\n", language);
153 while ((entry = table[i])) {
155 exactsize = lstrlenA(entry);
157 lres = RegSetValueExA(hroot, acceptlanguage, 0, REG_SZ, (const BYTE *) entry, exactsize + 1);
158 ok(!lres, "got %d for RegSetValueExA: %s\n", lres, entry);
160 /* len includes space for the terminating 0 before vista/w2k8 */
161 len = exactsize + 2;
162 memset(buffer, '#', maxlen);
163 buffer[maxlen] = 0;
164 hr = pGetAcceptLanguagesA( buffer, &len);
165 ok(((hr == E_INVALIDARG) && (len == 0)) ||
166 (SUCCEEDED(hr) &&
167 ((len == exactsize) || (len == exactsize+1)) &&
168 !lstrcmpA(buffer, entry)),
169 "+2_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
171 len = exactsize + 1;
172 memset(buffer, '#', maxlen);
173 buffer[maxlen] = 0;
174 hr = pGetAcceptLanguagesA( buffer, &len);
175 ok(((hr == E_INVALIDARG) && (len == 0)) ||
176 (SUCCEEDED(hr) &&
177 ((len == exactsize) || (len == exactsize+1)) &&
178 !lstrcmpA(buffer, entry)),
179 "+1_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
181 len = exactsize;
182 memset(buffer, '#', maxlen);
183 buffer[maxlen] = 0;
184 hr = pGetAcceptLanguagesA( buffer, &len);
186 /* There is no space for the string in the registry.
187 When the buffer is large enough, the default language is returned
189 When the buffer is to small for that fallback, win7_32 and w2k8_64
190 and above fail with HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), but
191 recent os succeed and return a partial result while
192 older os succeed and overflow the buffer */
194 ok(((hr == E_INVALIDARG) && (len == 0)) ||
195 (((hr == S_OK) && !lstrcmpA(buffer, language) && (len == lstrlenA(language))) ||
196 ((hr == S_OK) && !memcmp(buffer, language, len)) ||
197 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len)),
198 "==_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
200 if (exactsize > 1) {
201 len = exactsize - 1;
202 memset(buffer, '#', maxlen);
203 buffer[maxlen] = 0;
204 hr = pGetAcceptLanguagesA( buffer, &len);
205 ok(((hr == E_INVALIDARG) && (len == 0)) ||
206 (((hr == S_OK) && !lstrcmpA(buffer, language) && (len == lstrlenA(language))) ||
207 ((hr == S_OK) && !memcmp(buffer, language, len)) ||
208 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len)),
209 "-1_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
212 len = 1;
213 memset(buffer, '#', maxlen);
214 buffer[maxlen] = 0;
215 hr = pGetAcceptLanguagesA( buffer, &len);
216 ok(((hr == E_INVALIDARG) && (len == 0)) ||
217 (((hr == S_OK) && !lstrcmpA(buffer, language) && (len == lstrlenA(language))) ||
218 ((hr == S_OK) && !memcmp(buffer, language, len)) ||
219 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len)),
220 "=1_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
222 len = maxlen;
223 hr = pGetAcceptLanguagesA( NULL, &len);
225 /* w2k3 and below: E_FAIL and untouched len,
226 since w2k8: S_OK and needed size (excluding 0) */
227 ok( ((hr == S_OK) && (len == exactsize)) ||
228 ((hr == E_FAIL) && (len == maxlen)),
229 "NULL,max #%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
231 i++;
234 /* without a value in the registry, a default language is returned */
235 RegDeleteValue(hroot, acceptlanguage);
237 len = maxlen;
238 memset(buffer, '#', maxlen);
239 buffer[maxlen] = 0;
240 hr = pGetAcceptLanguagesA( buffer, &len);
241 ok( ((hr == S_OK) && (len == lstrlenA(language))),
242 "max: got 0x%x with %d and %s (expected S_OK with %d and '%s'\n",
243 hr, len, buffer, lstrlenA(language), language);
245 len = 2;
246 memset(buffer, '#', maxlen);
247 buffer[maxlen] = 0;
248 hr = pGetAcceptLanguagesA( buffer, &len);
249 ok( (((hr == S_OK) || (hr == E_INVALIDARG)) && !memcmp(buffer, language, len)) ||
250 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len),
251 "=2: got 0x%x with %d and %s\n", hr, len, buffer);
253 len = 1;
254 memset(buffer, '#', maxlen);
255 buffer[maxlen] = 0;
256 hr = pGetAcceptLanguagesA( buffer, &len);
257 /* When the buffer is to small, win7_32 and w2k8_64 and above fail with
258 HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), other versions suceed
259 and return a partial 0 terminated result while other versions
260 fail with E_INVALIDARG and return a partial unterminated result */
261 ok( (((hr == S_OK) || (hr == E_INVALIDARG)) && !memcmp(buffer, language, len)) ||
262 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len),
263 "=1: got 0x%x with %d and %s\n", hr, len, buffer);
265 len = 0;
266 memset(buffer, '#', maxlen);
267 buffer[maxlen] = 0;
268 hr = pGetAcceptLanguagesA( buffer, &len);
269 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
270 ok((hr == E_FAIL) || (hr == E_INVALIDARG),
271 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr);
273 memset(buffer, '#', maxlen);
274 buffer[maxlen] = 0;
275 hr = pGetAcceptLanguagesA( buffer, NULL);
276 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
277 ok((hr == E_FAIL) || (hr == E_INVALIDARG),
278 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr);
281 hr = pGetAcceptLanguagesA( NULL, NULL);
282 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
283 ok((hr == E_FAIL) || (hr == E_INVALIDARG),
284 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr);
286 restore_original:
287 if (!res_query) {
288 len = lstrlenA(original);
289 lres = RegSetValueExA(hroot, acceptlanguage, 0, REG_SZ, (const BYTE *) original, len ? len + 1: 0);
290 ok(!lres, "RegSetValueEx(%s) failed: %d\n", original, lres);
292 else
294 RegDeleteValue(hroot, acceptlanguage);
296 RegCloseKey(hroot);
299 static void test_SHSearchMapInt(void)
301 int keys[8], values[8];
302 int i = 0;
304 if (!pSHSearchMapInt)
305 return;
307 memset(keys, 0, sizeof(keys));
308 memset(values, 0, sizeof(values));
309 keys[0] = 99; values[0] = 101;
311 /* NULL key/value lists crash native, so skip testing them */
313 /* 1 element */
314 i = pSHSearchMapInt(keys, values, 1, keys[0]);
315 ok(i == values[0], "Len 1, expected %d, got %d\n", values[0], i);
317 /* Key doesn't exist */
318 i = pSHSearchMapInt(keys, values, 1, 100);
319 ok(i == -1, "Len 1 - bad key, expected -1, got %d\n", i);
321 /* Len = 0 => not found */
322 i = pSHSearchMapInt(keys, values, 0, keys[0]);
323 ok(i == -1, "Len 1 - passed len 0, expected -1, got %d\n", i);
325 /* 2 elements, len = 1 */
326 keys[1] = 98; values[1] = 102;
327 i = pSHSearchMapInt(keys, values, 1, keys[1]);
328 ok(i == -1, "Len 1 - array len 2, expected -1, got %d\n", i);
330 /* 2 elements, len = 2 */
331 i = pSHSearchMapInt(keys, values, 2, keys[1]);
332 ok(i == values[1], "Len 2, expected %d, got %d\n", values[1], i);
334 /* Searches forward */
335 keys[2] = 99; values[2] = 103;
336 i = pSHSearchMapInt(keys, values, 3, keys[0]);
337 ok(i == values[0], "Len 3, expected %d, got %d\n", values[0], i);
340 static void test_alloc_shared(void)
342 DWORD procid;
343 HANDLE hmem;
344 int val;
345 int* p;
346 BOOL ret;
348 procid=GetCurrentProcessId();
349 hmem=pSHAllocShared(NULL,10,procid);
350 ok(hmem!=NULL,"SHAllocShared(NULL...) failed: %u\n", GetLastError());
351 ret = pSHFreeShared(hmem, procid);
352 ok( ret, "SHFreeShared failed: %u\n", GetLastError());
354 val=0x12345678;
355 hmem=pSHAllocShared(&val,4,procid);
356 ok(hmem!=NULL,"SHAllocShared(NULL...) failed: %u\n", GetLastError());
358 p=pSHLockShared(hmem,procid);
359 ok(p!=NULL,"SHLockShared failed: %u\n", GetLastError());
360 if (p!=NULL)
361 ok(*p==val,"Wrong value in shared memory: %d instead of %d\n",*p,val);
362 ret = pSHUnlockShared(p);
363 ok( ret, "SHUnlockShared failed: %u\n", GetLastError());
365 ret = pSHFreeShared(hmem, procid);
366 ok( ret, "SHFreeShared failed: %u\n", GetLastError());
369 static void test_fdsa(void)
371 typedef struct
373 DWORD num_items; /* Number of elements inserted */
374 void *mem; /* Ptr to array */
375 DWORD blocks_alloced; /* Number of elements allocated */
376 BYTE inc; /* Number of elements to grow by when we need to expand */
377 BYTE block_size; /* Size in bytes of an element */
378 BYTE flags; /* Flags */
379 } FDSA_info;
381 BOOL (WINAPI *pFDSA_Initialize)(DWORD block_size, DWORD inc, FDSA_info *info, void *mem,
382 DWORD init_blocks);
383 BOOL (WINAPI *pFDSA_Destroy)(FDSA_info *info);
384 DWORD (WINAPI *pFDSA_InsertItem)(FDSA_info *info, DWORD where, const void *block);
385 BOOL (WINAPI *pFDSA_DeleteItem)(FDSA_info *info, DWORD where);
387 FDSA_info info;
388 int block_size = 10, init_blocks = 4, inc = 2;
389 DWORD ret;
390 char *mem;
392 pFDSA_Initialize = (void *)GetProcAddress(hShlwapi, (LPSTR)208);
393 pFDSA_Destroy = (void *)GetProcAddress(hShlwapi, (LPSTR)209);
394 pFDSA_InsertItem = (void *)GetProcAddress(hShlwapi, (LPSTR)210);
395 pFDSA_DeleteItem = (void *)GetProcAddress(hShlwapi, (LPSTR)211);
397 mem = HeapAlloc(GetProcessHeap(), 0, block_size * init_blocks);
398 memset(&info, 0, sizeof(info));
400 ok(pFDSA_Initialize(block_size, inc, &info, mem, init_blocks), "FDSA_Initialize rets FALSE\n");
401 ok(info.num_items == 0, "num_items = %d\n", info.num_items);
402 ok(info.mem == mem, "mem = %p\n", info.mem);
403 ok(info.blocks_alloced == init_blocks, "blocks_alloced = %d\n", info.blocks_alloced);
404 ok(info.inc == inc, "inc = %d\n", info.inc);
405 ok(info.block_size == block_size, "block_size = %d\n", info.block_size);
406 ok(info.flags == 0, "flags = %d\n", info.flags);
408 ret = pFDSA_InsertItem(&info, 1234, "1234567890");
409 ok(ret == 0, "ret = %d\n", ret);
410 ok(info.num_items == 1, "num_items = %d\n", info.num_items);
411 ok(info.mem == mem, "mem = %p\n", info.mem);
412 ok(info.blocks_alloced == init_blocks, "blocks_alloced = %d\n", info.blocks_alloced);
413 ok(info.inc == inc, "inc = %d\n", info.inc);
414 ok(info.block_size == block_size, "block_size = %d\n", info.block_size);
415 ok(info.flags == 0, "flags = %d\n", info.flags);
417 ret = pFDSA_InsertItem(&info, 1234, "abcdefghij");
418 ok(ret == 1, "ret = %d\n", ret);
420 ret = pFDSA_InsertItem(&info, 1, "klmnopqrst");
421 ok(ret == 1, "ret = %d\n", ret);
423 ret = pFDSA_InsertItem(&info, 0, "uvwxyzABCD");
424 ok(ret == 0, "ret = %d\n", ret);
425 ok(info.mem == mem, "mem = %p\n", info.mem);
426 ok(info.flags == 0, "flags = %d\n", info.flags);
428 /* This next InsertItem will cause shlwapi to allocate its own mem buffer */
429 ret = pFDSA_InsertItem(&info, 0, "EFGHIJKLMN");
430 ok(ret == 0, "ret = %d\n", ret);
431 ok(info.mem != mem, "mem = %p\n", info.mem);
432 ok(info.blocks_alloced == init_blocks + inc, "blocks_alloced = %d\n", info.blocks_alloced);
433 ok(info.flags == 0x1, "flags = %d\n", info.flags);
435 ok(!memcmp(info.mem, "EFGHIJKLMNuvwxyzABCD1234567890klmnopqrstabcdefghij", 50), "mem %s\n", (char*)info.mem);
437 ok(pFDSA_DeleteItem(&info, 2), "rets FALSE\n");
438 ok(info.mem != mem, "mem = %p\n", info.mem);
439 ok(info.blocks_alloced == init_blocks + inc, "blocks_alloced = %d\n", info.blocks_alloced);
440 ok(info.flags == 0x1, "flags = %d\n", info.flags);
442 ok(!memcmp(info.mem, "EFGHIJKLMNuvwxyzABCDklmnopqrstabcdefghij", 40), "mem %s\n", (char*)info.mem);
444 ok(pFDSA_DeleteItem(&info, 3), "rets FALSE\n");
445 ok(info.mem != mem, "mem = %p\n", info.mem);
446 ok(info.blocks_alloced == init_blocks + inc, "blocks_alloced = %d\n", info.blocks_alloced);
447 ok(info.flags == 0x1, "flags = %d\n", info.flags);
449 ok(!memcmp(info.mem, "EFGHIJKLMNuvwxyzABCDklmnopqrst", 30), "mem %s\n", (char*)info.mem);
451 ok(!pFDSA_DeleteItem(&info, 4), "does not ret FALSE\n");
453 /* As shlwapi has allocated memory internally, Destroy will ret FALSE */
454 ok(!pFDSA_Destroy(&info), "FDSA_Destroy does not ret FALSE\n");
457 /* When Initialize is called with inc = 0, set it to 1 */
458 ok(pFDSA_Initialize(block_size, 0, &info, mem, init_blocks), "FDSA_Initialize rets FALSE\n");
459 ok(info.inc == 1, "inc = %d\n", info.inc);
461 /* This time, because shlwapi hasn't had to allocate memory
462 internally, Destroy rets non-zero */
463 ok(pFDSA_Destroy(&info), "FDSA_Destroy rets FALSE\n");
466 HeapFree(GetProcessHeap(), 0, mem);
470 typedef struct SHELL_USER_SID {
471 SID_IDENTIFIER_AUTHORITY sidAuthority;
472 DWORD dwUserGroupID;
473 DWORD dwUserID;
474 } SHELL_USER_SID, *PSHELL_USER_SID;
475 typedef struct SHELL_USER_PERMISSION {
476 SHELL_USER_SID susID;
477 DWORD dwAccessType;
478 BOOL fInherit;
479 DWORD dwAccessMask;
480 DWORD dwInheritMask;
481 DWORD dwInheritAccessMask;
482 } SHELL_USER_PERMISSION, *PSHELL_USER_PERMISSION;
483 static void test_GetShellSecurityDescriptor(void)
485 SHELL_USER_PERMISSION supCurrentUserFull = {
486 { {SECURITY_NULL_SID_AUTHORITY}, 0, 0 },
487 ACCESS_ALLOWED_ACE_TYPE, FALSE,
488 GENERIC_ALL, 0, 0 };
489 #define MY_INHERITANCE 0xBE /* invalid value to proof behavior */
490 SHELL_USER_PERMISSION supEveryoneDenied = {
491 { {SECURITY_WORLD_SID_AUTHORITY}, SECURITY_WORLD_RID, 0 },
492 ACCESS_DENIED_ACE_TYPE, TRUE,
493 GENERIC_WRITE, MY_INHERITANCE | 0xDEADBA00, GENERIC_READ };
494 PSHELL_USER_PERMISSION rgsup[2] = {
495 &supCurrentUserFull, &supEveryoneDenied,
497 SECURITY_DESCRIPTOR* psd;
498 SECURITY_DESCRIPTOR* (WINAPI*pGetShellSecurityDescriptor)(PSHELL_USER_PERMISSION*,int);
500 pGetShellSecurityDescriptor=(void*)GetProcAddress(hShlwapi,(char*)475);
502 if(!pGetShellSecurityDescriptor)
504 win_skip("GetShellSecurityDescriptor not available\n");
505 return;
508 psd = pGetShellSecurityDescriptor(NULL, 2);
509 ok(psd==NULL ||
510 broken(psd==INVALID_HANDLE_VALUE), /* IE5 */
511 "GetShellSecurityDescriptor should fail\n");
512 psd = pGetShellSecurityDescriptor(rgsup, 0);
513 ok(psd==NULL, "GetShellSecurityDescriptor should fail\n");
515 SetLastError(0xdeadbeef);
516 psd = pGetShellSecurityDescriptor(rgsup, 2);
517 if (psd == NULL && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
519 /* The previous calls to GetShellSecurityDescriptor don't set the last error */
520 win_skip("GetShellSecurityDescriptor is not implemented\n");
521 return;
523 if (psd==INVALID_HANDLE_VALUE)
525 win_skip("GetShellSecurityDescriptor is broken on IE5\n");
526 return;
528 ok(psd!=NULL, "GetShellSecurityDescriptor failed\n");
529 if (psd!=NULL)
531 BOOL bHasDacl = FALSE, bDefaulted;
532 PACL pAcl;
533 DWORD dwRev;
534 SECURITY_DESCRIPTOR_CONTROL control;
536 ok(IsValidSecurityDescriptor(psd), "returned value is not valid SD\n");
538 ok(GetSecurityDescriptorControl(psd, &control, &dwRev),
539 "GetSecurityDescriptorControl failed with error %u\n", GetLastError());
540 ok(0 == (control & SE_SELF_RELATIVE), "SD should be absolute\n");
542 ok(GetSecurityDescriptorDacl(psd, &bHasDacl, &pAcl, &bDefaulted),
543 "GetSecurityDescriptorDacl failed with error %u\n", GetLastError());
545 ok(bHasDacl, "SD has no DACL\n");
546 if (bHasDacl)
548 ok(!bDefaulted, "DACL should not be defaulted\n");
550 ok(pAcl != NULL, "NULL DACL!\n");
551 if (pAcl != NULL)
553 ACL_SIZE_INFORMATION asiSize;
555 ok(IsValidAcl(pAcl), "DACL is not valid\n");
557 ok(GetAclInformation(pAcl, &asiSize, sizeof(asiSize), AclSizeInformation),
558 "GetAclInformation failed with error %u\n", GetLastError());
560 ok(asiSize.AceCount == 3, "Incorrect number of ACEs: %d entries\n", asiSize.AceCount);
561 if (asiSize.AceCount == 3)
563 ACCESS_ALLOWED_ACE *paaa; /* will use for DENIED too */
565 ok(GetAce(pAcl, 0, (LPVOID*)&paaa), "GetAce failed with error %u\n", GetLastError());
566 ok(paaa->Header.AceType == ACCESS_ALLOWED_ACE_TYPE,
567 "Invalid ACE type %d\n", paaa->Header.AceType);
568 ok(paaa->Header.AceFlags == 0, "Invalid ACE flags %x\n", paaa->Header.AceFlags);
569 ok(paaa->Mask == GENERIC_ALL, "Invalid ACE mask %x\n", paaa->Mask);
571 ok(GetAce(pAcl, 1, (LPVOID*)&paaa), "GetAce failed with error %u\n", GetLastError());
572 ok(paaa->Header.AceType == ACCESS_DENIED_ACE_TYPE,
573 "Invalid ACE type %d\n", paaa->Header.AceType);
574 /* first one of two ACEs generated from inheritable entry - without inheritance */
575 ok(paaa->Header.AceFlags == 0, "Invalid ACE flags %x\n", paaa->Header.AceFlags);
576 ok(paaa->Mask == GENERIC_WRITE, "Invalid ACE mask %x\n", paaa->Mask);
578 ok(GetAce(pAcl, 2, (LPVOID*)&paaa), "GetAce failed with error %u\n", GetLastError());
579 ok(paaa->Header.AceType == ACCESS_DENIED_ACE_TYPE,
580 "Invalid ACE type %d\n", paaa->Header.AceType);
581 /* second ACE - with inheritance */
582 ok(paaa->Header.AceFlags == MY_INHERITANCE,
583 "Invalid ACE flags %x\n", paaa->Header.AceFlags);
584 ok(paaa->Mask == GENERIC_READ, "Invalid ACE mask %x\n", paaa->Mask);
589 LocalFree(psd);
593 static void test_SHPackDispParams(void)
595 DISPPARAMS params;
596 VARIANT vars[10];
597 HRESULT hres;
599 if(!pSHPackDispParams)
600 win_skip("SHPackSidpParams not available\n");
602 memset(&params, 0xc0, sizeof(params));
603 memset(vars, 0xc0, sizeof(vars));
604 hres = pSHPackDispParams(&params, vars, 1, VT_I4, 0xdeadbeef);
605 ok(hres == S_OK, "SHPackDispParams failed: %08x\n", hres);
606 ok(params.cArgs == 1, "params.cArgs = %d\n", params.cArgs);
607 ok(params.cNamedArgs == 0, "params.cNamedArgs = %d\n", params.cArgs);
608 ok(params.rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", params.rgdispidNamedArgs);
609 ok(params.rgvarg == vars, "params.rgvarg = %p\n", params.rgvarg);
610 ok(V_VT(vars) == VT_I4, "V_VT(var) = %d\n", V_VT(vars));
611 ok(V_I4(vars) == 0xdeadbeef, "failed %x\n", V_I4(vars));
613 memset(&params, 0xc0, sizeof(params));
614 hres = pSHPackDispParams(&params, NULL, 0, 0);
615 ok(hres == S_OK, "SHPackDispParams failed: %08x\n", hres);
616 ok(params.cArgs == 0, "params.cArgs = %d\n", params.cArgs);
617 ok(params.cNamedArgs == 0, "params.cNamedArgs = %d\n", params.cArgs);
618 ok(params.rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", params.rgdispidNamedArgs);
619 ok(params.rgvarg == NULL, "params.rgvarg = %p\n", params.rgvarg);
621 memset(vars, 0xc0, sizeof(vars));
622 memset(&params, 0xc0, sizeof(params));
623 hres = pSHPackDispParams(&params, vars, 4, VT_BSTR, (void*)0xdeadbeef, VT_EMPTY, 10,
624 VT_I4, 100, VT_DISPATCH, (void*)0xdeadbeef);
625 ok(hres == S_OK, "SHPackDispParams failed: %08x\n", hres);
626 ok(params.cArgs == 4, "params.cArgs = %d\n", params.cArgs);
627 ok(params.cNamedArgs == 0, "params.cNamedArgs = %d\n", params.cArgs);
628 ok(params.rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", params.rgdispidNamedArgs);
629 ok(params.rgvarg == vars, "params.rgvarg = %p\n", params.rgvarg);
630 ok(V_VT(vars) == VT_DISPATCH, "V_VT(vars[0]) = %x\n", V_VT(vars));
631 ok(V_I4(vars) == 0xdeadbeef, "V_I4(vars[0]) = %x\n", V_I4(vars));
632 ok(V_VT(vars+1) == VT_I4, "V_VT(vars[1]) = %d\n", V_VT(vars+1));
633 ok(V_I4(vars+1) == 100, "V_I4(vars[1]) = %x\n", V_I4(vars+1));
634 ok(V_VT(vars+2) == VT_I4, "V_VT(vars[2]) = %d\n", V_VT(vars+2));
635 ok(V_I4(vars+2) == 10, "V_I4(vars[2]) = %x\n", V_I4(vars+2));
636 ok(V_VT(vars+3) == VT_BSTR, "V_VT(vars[3]) = %d\n", V_VT(vars+3));
637 ok(V_BSTR(vars+3) == (void*)0xdeadbeef, "V_BSTR(vars[3]) = %p\n", V_BSTR(vars+3));
640 typedef struct _disp
642 const IDispatchVtbl *vtbl;
643 LONG refCount;
644 } Disp;
646 typedef struct _contain
648 const IConnectionPointContainerVtbl *vtbl;
649 LONG refCount;
651 UINT ptCount;
652 IConnectionPoint **pt;
653 } Contain;
655 typedef struct _cntptn
657 const IConnectionPointVtbl *vtbl;
658 LONG refCount;
660 Contain *container;
661 GUID id;
662 UINT sinkCount;
663 IUnknown **sink;
664 } ConPt;
666 typedef struct _enum
668 const IEnumConnectionsVtbl *vtbl;
669 LONG refCount;
671 UINT idx;
672 ConPt *pt;
673 } EnumCon;
675 typedef struct _enumpt
677 const IEnumConnectionPointsVtbl *vtbl;
678 LONG refCount;
680 int idx;
681 Contain *container;
682 } EnumPt;
685 static HRESULT WINAPI Disp_QueryInterface(
686 IDispatch* This,
687 REFIID riid,
688 void **ppvObject)
690 *ppvObject = NULL;
692 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch))
694 *ppvObject = This;
697 if (*ppvObject)
699 IUnknown_AddRef(This);
700 return S_OK;
703 trace("no interface\n");
704 return E_NOINTERFACE;
707 static ULONG WINAPI Disp_AddRef(IDispatch* This)
709 Disp *iface = (Disp*)This;
710 return InterlockedIncrement(&iface->refCount);
713 static ULONG WINAPI Disp_Release(IDispatch* This)
715 Disp *iface = (Disp*)This;
716 ULONG ret;
718 ret = InterlockedDecrement(&iface->refCount);
719 if (ret == 0)
720 HeapFree(GetProcessHeap(),0,This);
721 return ret;
724 static HRESULT WINAPI Disp_GetTypeInfoCount(
725 IDispatch* This,
726 UINT *pctinfo)
728 return ERROR_SUCCESS;
731 static HRESULT WINAPI Disp_GetTypeInfo(
732 IDispatch* This,
733 UINT iTInfo,
734 LCID lcid,
735 ITypeInfo **ppTInfo)
737 return ERROR_SUCCESS;
740 static HRESULT WINAPI Disp_GetIDsOfNames(
741 IDispatch* This,
742 REFIID riid,
743 LPOLESTR *rgszNames,
744 UINT cNames,
745 LCID lcid,
746 DISPID *rgDispId)
748 return ERROR_SUCCESS;
751 static HRESULT WINAPI Disp_Invoke(
752 IDispatch* This,
753 DISPID dispIdMember,
754 REFIID riid,
755 LCID lcid,
756 WORD wFlags,
757 DISPPARAMS *pDispParams,
758 VARIANT *pVarResult,
759 EXCEPINFO *pExcepInfo,
760 UINT *puArgErr)
762 trace("%p %x %p %x %x %p %p %p %p\n",This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr);
764 ok(dispIdMember == 0xa0 || dispIdMember == 0xa1, "Unknown dispIdMember\n");
765 ok(pDispParams != NULL, "Invoked with NULL pDispParams\n");
766 ok(wFlags == DISPATCH_METHOD, "Wrong flags %x\n",wFlags);
767 ok(lcid == 0,"Wrong lcid %x\n",lcid);
768 if (dispIdMember == 0xa0)
770 ok(pDispParams->cArgs == 0, "params.cArgs = %d\n", pDispParams->cArgs);
771 ok(pDispParams->cNamedArgs == 0, "params.cNamedArgs = %d\n", pDispParams->cArgs);
772 ok(pDispParams->rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", pDispParams->rgdispidNamedArgs);
773 ok(pDispParams->rgvarg == NULL, "params.rgvarg = %p\n", pDispParams->rgvarg);
775 else if (dispIdMember == 0xa1)
777 ok(pDispParams->cArgs == 2, "params.cArgs = %d\n", pDispParams->cArgs);
778 ok(pDispParams->cNamedArgs == 0, "params.cNamedArgs = %d\n", pDispParams->cArgs);
779 ok(pDispParams->rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", pDispParams->rgdispidNamedArgs);
780 ok(V_VT(pDispParams->rgvarg) == VT_BSTR, "V_VT(var) = %d\n", V_VT(pDispParams->rgvarg));
781 ok(V_I4(pDispParams->rgvarg) == 0xdeadcafe , "failed %p\n", V_BSTR(pDispParams->rgvarg));
782 ok(V_VT(pDispParams->rgvarg+1) == VT_I4, "V_VT(var) = %d\n", V_VT(pDispParams->rgvarg+1));
783 ok(V_I4(pDispParams->rgvarg+1) == 0xdeadbeef, "failed %x\n", V_I4(pDispParams->rgvarg+1));
786 return ERROR_SUCCESS;
789 static const IDispatchVtbl disp_vtbl = {
790 Disp_QueryInterface,
791 Disp_AddRef,
792 Disp_Release,
794 Disp_GetTypeInfoCount,
795 Disp_GetTypeInfo,
796 Disp_GetIDsOfNames,
797 Disp_Invoke
800 static HRESULT WINAPI Enum_QueryInterface(
801 IEnumConnections* This,
802 REFIID riid,
803 void **ppvObject)
805 *ppvObject = NULL;
807 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IEnumConnections))
809 *ppvObject = This;
812 if (*ppvObject)
814 IUnknown_AddRef(This);
815 return S_OK;
818 trace("no interface\n");
819 return E_NOINTERFACE;
822 static ULONG WINAPI Enum_AddRef(IEnumConnections* This)
824 EnumCon *iface = (EnumCon*)This;
825 return InterlockedIncrement(&iface->refCount);
828 static ULONG WINAPI Enum_Release(IEnumConnections* This)
830 EnumCon *iface = (EnumCon*)This;
831 ULONG ret;
833 ret = InterlockedDecrement(&iface->refCount);
834 if (ret == 0)
835 HeapFree(GetProcessHeap(),0,This);
836 return ret;
839 static HRESULT WINAPI Enum_Next(
840 IEnumConnections* This,
841 ULONG cConnections,
842 LPCONNECTDATA rgcd,
843 ULONG *pcFetched)
845 EnumCon *iface = (EnumCon*)This;
847 if (cConnections > 0 && iface->idx < iface->pt->sinkCount)
849 rgcd->pUnk = iface->pt->sink[iface->idx];
850 IUnknown_AddRef(iface->pt->sink[iface->idx]);
851 rgcd->dwCookie=0xff;
852 if (pcFetched)
853 *pcFetched = 1;
854 iface->idx++;
855 return S_OK;
858 return E_FAIL;
861 static HRESULT WINAPI Enum_Skip(
862 IEnumConnections* This,
863 ULONG cConnections)
865 return E_FAIL;
868 static HRESULT WINAPI Enum_Reset(
869 IEnumConnections* This)
871 return E_FAIL;
874 static HRESULT WINAPI Enum_Clone(
875 IEnumConnections* This,
876 IEnumConnections **ppEnum)
878 return E_FAIL;
881 static const IEnumConnectionsVtbl enum_vtbl = {
883 Enum_QueryInterface,
884 Enum_AddRef,
885 Enum_Release,
886 Enum_Next,
887 Enum_Skip,
888 Enum_Reset,
889 Enum_Clone
892 static HRESULT WINAPI ConPt_QueryInterface(
893 IConnectionPoint* This,
894 REFIID riid,
895 void **ppvObject)
897 *ppvObject = NULL;
899 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IConnectionPoint))
901 *ppvObject = This;
904 if (*ppvObject)
906 IUnknown_AddRef(This);
907 return S_OK;
910 trace("no interface\n");
911 return E_NOINTERFACE;
914 static ULONG WINAPI ConPt_AddRef(
915 IConnectionPoint* This)
917 ConPt *iface = (ConPt*)This;
918 return InterlockedIncrement(&iface->refCount);
921 static ULONG WINAPI ConPt_Release(
922 IConnectionPoint* This)
924 ConPt *iface = (ConPt*)This;
925 ULONG ret;
927 ret = InterlockedDecrement(&iface->refCount);
928 if (ret == 0)
930 if (iface->sinkCount > 0)
932 int i;
933 for (i = 0; i < iface->sinkCount; i++)
935 if (iface->sink[i])
936 IUnknown_Release(iface->sink[i]);
938 HeapFree(GetProcessHeap(),0,iface->sink);
940 HeapFree(GetProcessHeap(),0,This);
942 return ret;
945 static HRESULT WINAPI ConPt_GetConnectionInterface(
946 IConnectionPoint* This,
947 IID *pIID)
949 static int i = 0;
950 ConPt *iface = (ConPt*)This;
951 if (i==0)
953 i++;
954 return E_FAIL;
956 else
957 memcpy(pIID,&iface->id,sizeof(GUID));
958 return S_OK;
961 static HRESULT WINAPI ConPt_GetConnectionPointContainer(
962 IConnectionPoint* This,
963 IConnectionPointContainer **ppCPC)
965 ConPt *iface = (ConPt*)This;
967 *ppCPC = (IConnectionPointContainer*)iface->container;
968 return S_OK;
971 static HRESULT WINAPI ConPt_Advise(
972 IConnectionPoint* This,
973 IUnknown *pUnkSink,
974 DWORD *pdwCookie)
976 ConPt *iface = (ConPt*)This;
978 if (iface->sinkCount == 0)
979 iface->sink = HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown*));
980 else
981 iface->sink = HeapReAlloc(GetProcessHeap(),0,iface->sink,sizeof(IUnknown*)*(iface->sinkCount+1));
982 iface->sink[iface->sinkCount] = pUnkSink;
983 IUnknown_AddRef(pUnkSink);
984 iface->sinkCount++;
985 *pdwCookie = iface->sinkCount;
986 return S_OK;
989 static HRESULT WINAPI ConPt_Unadvise(
990 IConnectionPoint* This,
991 DWORD dwCookie)
993 ConPt *iface = (ConPt*)This;
995 if (dwCookie > iface->sinkCount)
996 return E_FAIL;
997 else
999 IUnknown_Release(iface->sink[dwCookie-1]);
1000 iface->sink[dwCookie-1] = NULL;
1002 return S_OK;
1005 static HRESULT WINAPI ConPt_EnumConnections(
1006 IConnectionPoint* This,
1007 IEnumConnections **ppEnum)
1009 EnumCon *ec;
1011 ec = HeapAlloc(GetProcessHeap(),0,sizeof(EnumCon));
1012 ec->vtbl = &enum_vtbl;
1013 ec->refCount = 1;
1014 ec->pt = (ConPt*)This;
1015 ec->idx = 0;
1016 *ppEnum = (IEnumConnections*)ec;
1018 return S_OK;
1021 static const IConnectionPointVtbl point_vtbl = {
1022 ConPt_QueryInterface,
1023 ConPt_AddRef,
1024 ConPt_Release,
1026 ConPt_GetConnectionInterface,
1027 ConPt_GetConnectionPointContainer,
1028 ConPt_Advise,
1029 ConPt_Unadvise,
1030 ConPt_EnumConnections
1033 static HRESULT WINAPI EnumPt_QueryInterface(
1034 IEnumConnectionPoints* This,
1035 REFIID riid,
1036 void **ppvObject)
1038 *ppvObject = NULL;
1040 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IEnumConnectionPoints))
1042 *ppvObject = This;
1045 if (*ppvObject)
1047 IUnknown_AddRef(This);
1048 return S_OK;
1051 trace("no interface\n");
1052 return E_NOINTERFACE;
1055 static ULONG WINAPI EnumPt_AddRef(IEnumConnectionPoints* This)
1057 EnumPt *iface = (EnumPt*)This;
1058 return InterlockedIncrement(&iface->refCount);
1061 static ULONG WINAPI EnumPt_Release(IEnumConnectionPoints* This)
1063 EnumPt *iface = (EnumPt*)This;
1064 ULONG ret;
1066 ret = InterlockedDecrement(&iface->refCount);
1067 if (ret == 0)
1068 HeapFree(GetProcessHeap(),0,This);
1069 return ret;
1072 static HRESULT WINAPI EnumPt_Next(
1073 IEnumConnectionPoints* This,
1074 ULONG cConnections,
1075 IConnectionPoint **rgcd,
1076 ULONG *pcFetched)
1078 EnumPt *iface = (EnumPt*)This;
1080 if (cConnections > 0 && iface->idx < iface->container->ptCount)
1082 *rgcd = iface->container->pt[iface->idx];
1083 IUnknown_AddRef(iface->container->pt[iface->idx]);
1084 if (pcFetched)
1085 *pcFetched = 1;
1086 iface->idx++;
1087 return S_OK;
1090 return E_FAIL;
1093 static HRESULT WINAPI EnumPt_Skip(
1094 IEnumConnectionPoints* This,
1095 ULONG cConnections)
1097 return E_FAIL;
1100 static HRESULT WINAPI EnumPt_Reset(
1101 IEnumConnectionPoints* This)
1103 return E_FAIL;
1106 static HRESULT WINAPI EnumPt_Clone(
1107 IEnumConnectionPoints* This,
1108 IEnumConnectionPoints **ppEnumPt)
1110 return E_FAIL;
1113 static const IEnumConnectionPointsVtbl enumpt_vtbl = {
1115 EnumPt_QueryInterface,
1116 EnumPt_AddRef,
1117 EnumPt_Release,
1118 EnumPt_Next,
1119 EnumPt_Skip,
1120 EnumPt_Reset,
1121 EnumPt_Clone
1124 static HRESULT WINAPI Contain_QueryInterface(
1125 IConnectionPointContainer* This,
1126 REFIID riid,
1127 void **ppvObject)
1129 *ppvObject = NULL;
1131 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IConnectionPointContainer))
1133 *ppvObject = This;
1136 if (*ppvObject)
1138 IUnknown_AddRef(This);
1139 return S_OK;
1142 trace("no interface\n");
1143 return E_NOINTERFACE;
1146 static ULONG WINAPI Contain_AddRef(
1147 IConnectionPointContainer* This)
1149 Contain *iface = (Contain*)This;
1150 return InterlockedIncrement(&iface->refCount);
1153 static ULONG WINAPI Contain_Release(
1154 IConnectionPointContainer* This)
1156 Contain *iface = (Contain*)This;
1157 ULONG ret;
1159 ret = InterlockedDecrement(&iface->refCount);
1160 if (ret == 0)
1162 if (iface->ptCount > 0)
1164 int i;
1165 for (i = 0; i < iface->ptCount; i++)
1166 IUnknown_Release(iface->pt[i]);
1167 HeapFree(GetProcessHeap(),0,iface->pt);
1169 HeapFree(GetProcessHeap(),0,This);
1171 return ret;
1174 static HRESULT WINAPI Contain_EnumConnectionPoints(
1175 IConnectionPointContainer* This,
1176 IEnumConnectionPoints **ppEnum)
1178 EnumPt *ec;
1180 ec = HeapAlloc(GetProcessHeap(),0,sizeof(EnumPt));
1181 ec->vtbl = &enumpt_vtbl;
1182 ec->refCount = 1;
1183 ec->idx= 0;
1184 ec->container = (Contain*)This;
1185 *ppEnum = (IEnumConnectionPoints*)ec;
1187 return S_OK;
1190 static HRESULT WINAPI Contain_FindConnectionPoint(
1191 IConnectionPointContainer* This,
1192 REFIID riid,
1193 IConnectionPoint **ppCP)
1195 Contain *iface = (Contain*)This;
1196 ConPt *pt;
1198 if (!IsEqualIID(riid, &IID_NULL) || iface->ptCount ==0)
1200 pt = HeapAlloc(GetProcessHeap(),0,sizeof(ConPt));
1201 pt->vtbl = &point_vtbl;
1202 pt->refCount = 1;
1203 pt->sinkCount = 0;
1204 pt->sink = NULL;
1205 pt->container = iface;
1206 pt->id = IID_IDispatch;
1208 if (iface->ptCount == 0)
1209 iface->pt =HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown*));
1210 else
1211 iface->pt = HeapReAlloc(GetProcessHeap(),0,iface->pt,sizeof(IUnknown*)*(iface->ptCount+1));
1212 iface->pt[iface->ptCount] = (IConnectionPoint*)pt;
1213 iface->ptCount++;
1215 *ppCP = (IConnectionPoint*)pt;
1217 else
1219 *ppCP = iface->pt[0];
1220 IUnknown_AddRef((IUnknown*)*ppCP);
1223 return S_OK;
1226 static const IConnectionPointContainerVtbl contain_vtbl = {
1227 Contain_QueryInterface,
1228 Contain_AddRef,
1229 Contain_Release,
1231 Contain_EnumConnectionPoints,
1232 Contain_FindConnectionPoint
1235 static void test_IConnectionPoint(void)
1237 HRESULT rc;
1238 ULONG ref;
1239 IConnectionPoint *point;
1240 Contain *container;
1241 Disp *dispatch;
1242 DWORD cookie = 0xffffffff;
1243 DISPPARAMS params;
1244 VARIANT vars[10];
1246 if (!pIConnectionPoint_SimpleInvoke || !pConnectToConnectionPoint)
1248 win_skip("IConnectionPoint Apis not present\n");
1249 return;
1252 container = HeapAlloc(GetProcessHeap(),0,sizeof(Contain));
1253 container->vtbl = &contain_vtbl;
1254 container->refCount = 1;
1255 container->ptCount = 0;
1256 container->pt = NULL;
1258 dispatch = HeapAlloc(GetProcessHeap(),0,sizeof(Disp));
1259 dispatch->vtbl = &disp_vtbl;
1260 dispatch->refCount = 1;
1262 rc = pConnectToConnectionPoint((IUnknown*)dispatch, &IID_NULL, TRUE, (IUnknown*)container, &cookie, &point);
1263 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
1264 ok(point != NULL, "returned ConnectionPoint is NULL\n");
1265 ok(cookie != 0xffffffff, "invalid cookie returned\n");
1267 rc = pIConnectionPoint_SimpleInvoke(point,0xa0,NULL);
1268 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
1270 if (pSHPackDispParams)
1272 memset(&params, 0xc0, sizeof(params));
1273 memset(vars, 0xc0, sizeof(vars));
1274 rc = pSHPackDispParams(&params, vars, 2, VT_I4, 0xdeadbeef, VT_BSTR, 0xdeadcafe);
1275 ok(rc == S_OK, "SHPackDispParams failed: %08x\n", rc);
1277 rc = pIConnectionPoint_SimpleInvoke(point,0xa1,&params);
1278 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
1280 else
1281 win_skip("pSHPackDispParams not present\n");
1283 rc = pConnectToConnectionPoint(NULL, &IID_NULL, FALSE, (IUnknown*)container, &cookie, NULL);
1284 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
1286 /* MSDN says this should be required but it crashs on XP
1287 IUnknown_Release(point);
1289 ref = IUnknown_Release((IUnknown*)container);
1290 ok(ref == 0, "leftover IConnectionPointContainer reference %i\n",ref);
1291 ref = IUnknown_Release((IUnknown*)dispatch);
1292 ok(ref == 0, "leftover IDispatch reference %i\n",ref);
1295 typedef struct _propbag
1297 const IPropertyBagVtbl *vtbl;
1298 LONG refCount;
1300 } PropBag;
1303 static HRESULT WINAPI Prop_QueryInterface(
1304 IPropertyBag* This,
1305 REFIID riid,
1306 void **ppvObject)
1308 *ppvObject = NULL;
1310 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IPropertyBag))
1312 *ppvObject = This;
1315 if (*ppvObject)
1317 IUnknown_AddRef(This);
1318 return S_OK;
1321 trace("no interface\n");
1322 return E_NOINTERFACE;
1325 static ULONG WINAPI Prop_AddRef(
1326 IPropertyBag* This)
1328 PropBag *iface = (PropBag*)This;
1329 return InterlockedIncrement(&iface->refCount);
1332 static ULONG WINAPI Prop_Release(
1333 IPropertyBag* This)
1335 PropBag *iface = (PropBag*)This;
1336 ULONG ret;
1338 ret = InterlockedDecrement(&iface->refCount);
1339 if (ret == 0)
1340 HeapFree(GetProcessHeap(),0,This);
1341 return ret;
1344 static HRESULT WINAPI Prop_Read(
1345 IPropertyBag* This,
1346 LPCOLESTR pszPropName,
1347 VARIANT *pVar,
1348 IErrorLog *pErrorLog)
1350 V_VT(pVar) = VT_BLOB|VT_BYREF;
1351 V_BYREF(pVar) = (LPVOID)0xdeadcafe;
1352 return S_OK;
1355 static HRESULT WINAPI Prop_Write(
1356 IPropertyBag* This,
1357 LPCOLESTR pszPropName,
1358 VARIANT *pVar)
1360 return S_OK;
1364 static const IPropertyBagVtbl prop_vtbl = {
1365 Prop_QueryInterface,
1366 Prop_AddRef,
1367 Prop_Release,
1369 Prop_Read,
1370 Prop_Write
1373 static void test_SHPropertyBag_ReadLONG(void)
1375 PropBag *pb;
1376 HRESULT rc;
1377 LONG out;
1378 static const WCHAR szName1[] = {'n','a','m','e','1',0};
1380 if (!pSHPropertyBag_ReadLONG)
1382 win_skip("SHPropertyBag_ReadLONG not present\n");
1383 return;
1386 pb = HeapAlloc(GetProcessHeap(),0,sizeof(PropBag));
1387 pb->refCount = 1;
1388 pb->vtbl = &prop_vtbl;
1390 out = 0xfeedface;
1391 rc = pSHPropertyBag_ReadLONG(NULL, szName1, &out);
1392 ok(rc == E_INVALIDARG || broken(rc == 0), "incorrect return %x\n",rc);
1393 ok(out == 0xfeedface, "value should not have changed\n");
1394 rc = pSHPropertyBag_ReadLONG((IPropertyBag*)pb, NULL, &out);
1395 ok(rc == E_INVALIDARG || broken(rc == 0) || broken(rc == 1), "incorrect return %x\n",rc);
1396 ok(out == 0xfeedface, "value should not have changed\n");
1397 rc = pSHPropertyBag_ReadLONG((IPropertyBag*)pb, szName1, NULL);
1398 ok(rc == E_INVALIDARG || broken(rc == 0) || broken(rc == 1), "incorrect return %x\n",rc);
1399 ok(out == 0xfeedface, "value should not have changed\n");
1400 rc = pSHPropertyBag_ReadLONG((IPropertyBag*)pb, szName1, &out);
1401 ok(rc == DISP_E_BADVARTYPE || broken(rc == 0) || broken(rc == 1), "incorrect return %x\n",rc);
1402 ok(out == 0xfeedface || broken(out == 0xfeedfa00), "value should not have changed %x\n",out);
1403 IUnknown_Release((IUnknown*)pb);
1408 static void test_SHSetWindowBits(void)
1410 HWND hwnd;
1411 DWORD style, styleold;
1412 WNDCLASSA clsA;
1414 if(!pSHSetWindowBits)
1416 win_skip("SHSetWindowBits is not available\n");
1417 return;
1420 clsA.style = 0;
1421 clsA.lpfnWndProc = DefWindowProcA;
1422 clsA.cbClsExtra = 0;
1423 clsA.cbWndExtra = 0;
1424 clsA.hInstance = GetModuleHandleA(NULL);
1425 clsA.hIcon = 0;
1426 clsA.hCursor = LoadCursorA(0, IDC_ARROW);
1427 clsA.hbrBackground = NULL;
1428 clsA.lpszMenuName = NULL;
1429 clsA.lpszClassName = "Shlwapi test class";
1430 RegisterClassA(&clsA);
1432 hwnd = CreateWindowA("Shlwapi test class", "Test", WS_VISIBLE, 0, 0, 100, 100,
1433 NULL, NULL, GetModuleHandle(NULL), 0);
1434 ok(IsWindow(hwnd), "failed to create window\n");
1436 /* null window */
1437 SetLastError(0xdeadbeef);
1438 style = pSHSetWindowBits(NULL, GWL_STYLE, 0, 0);
1439 ok(style == 0, "expected 0 retval, got %d\n", style);
1440 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE ||
1441 broken(GetLastError() == 0xdeadbeef), /* Win9x/WinMe */
1442 "expected ERROR_INVALID_WINDOW_HANDLE, got %d\n", GetLastError());
1444 /* zero mask, zero flags */
1445 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1446 style = pSHSetWindowBits(hwnd, GWL_STYLE, 0, 0);
1447 ok(styleold == style, "expected old style\n");
1448 ok(styleold == GetWindowLongA(hwnd, GWL_STYLE), "expected to keep old style\n");
1450 /* test mask */
1451 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1452 ok(styleold & WS_VISIBLE, "expected WS_VISIBLE\n");
1453 style = pSHSetWindowBits(hwnd, GWL_STYLE, WS_VISIBLE, 0);
1455 ok(style == styleold, "expected previous style, got %x\n", style);
1456 ok((GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE) == 0, "expected updated style\n");
1458 /* test mask, unset style bit used */
1459 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1460 style = pSHSetWindowBits(hwnd, GWL_STYLE, WS_VISIBLE, 0);
1461 ok(style == styleold, "expected previous style, got %x\n", style);
1462 ok(styleold == GetWindowLongA(hwnd, GWL_STYLE), "expected to keep old style\n");
1464 /* set back with flags */
1465 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1466 style = pSHSetWindowBits(hwnd, GWL_STYLE, WS_VISIBLE, WS_VISIBLE);
1467 ok(style == styleold, "expected previous style, got %x\n", style);
1468 ok(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE, "expected updated style\n");
1470 /* reset and try to set without a mask */
1471 pSHSetWindowBits(hwnd, GWL_STYLE, WS_VISIBLE, 0);
1472 ok((GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE) == 0, "expected updated style\n");
1473 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1474 style = pSHSetWindowBits(hwnd, GWL_STYLE, 0, WS_VISIBLE);
1475 ok(style == styleold, "expected previous style, got %x\n", style);
1476 ok((GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE) == 0, "expected updated style\n");
1478 DestroyWindow(hwnd);
1480 UnregisterClassA("Shlwapi test class", GetModuleHandleA(NULL));
1483 static void test_SHFormatDateTimeA(void)
1485 FILETIME UNALIGNED filetime;
1486 CHAR buff[100], buff2[100], buff3[100];
1487 SYSTEMTIME st;
1488 DWORD flags;
1489 INT ret;
1491 if(!pSHFormatDateTimeA)
1493 win_skip("pSHFormatDateTimeA isn't available\n");
1494 return;
1497 if (0)
1499 /* crashes on native */
1500 ret = pSHFormatDateTimeA(NULL, NULL, NULL, 0);
1503 GetLocalTime(&st);
1504 SystemTimeToFileTime(&st, &filetime);
1505 /* SHFormatDateTime expects input as utc */
1506 LocalFileTimeToFileTime(&filetime, &filetime);
1508 /* no way to get required buffer length here */
1509 SetLastError(0xdeadbeef);
1510 ret = pSHFormatDateTimeA(&filetime, NULL, NULL, 0);
1511 ok(ret == 0, "got %d\n", ret);
1512 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1514 SetLastError(0xdeadbeef);
1515 buff[0] = 'a'; buff[1] = 0;
1516 ret = pSHFormatDateTimeA(&filetime, NULL, buff, 0);
1517 ok(ret == 0, "got %d\n", ret);
1518 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1519 ok(buff[0] == 'a', "expected same string, got %s\n", buff);
1521 /* all combinations documented as invalid succeeded */
1522 flags = FDTF_SHORTTIME | FDTF_LONGTIME;
1523 SetLastError(0xdeadbeef);
1524 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1525 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1526 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1528 flags = FDTF_SHORTDATE | FDTF_LONGDATE;
1529 SetLastError(0xdeadbeef);
1530 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1531 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1532 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1534 flags = FDTF_SHORTDATE | FDTF_LTRDATE | FDTF_RTLDATE;
1535 SetLastError(0xdeadbeef);
1536 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1537 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1538 ok(GetLastError() == 0xdeadbeef ||
1539 broken(GetLastError() == ERROR_INVALID_FLAGS), /* Win9x/WinMe */
1540 "expected 0xdeadbeef, got %d\n", GetLastError());
1542 /* now check returned strings */
1543 flags = FDTF_SHORTTIME;
1544 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1545 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1546 ret = GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff2, sizeof(buff2));
1547 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1548 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1550 flags = FDTF_LONGTIME;
1551 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1552 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1553 ret = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2));
1554 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1555 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1557 /* both time flags */
1558 flags = FDTF_LONGTIME | FDTF_SHORTTIME;
1559 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1560 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1561 ret = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2));
1562 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1563 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1565 flags = FDTF_SHORTDATE;
1566 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1567 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1568 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2));
1569 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1570 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1572 flags = FDTF_LONGDATE;
1573 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1574 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1575 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
1576 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1577 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1579 /* both date flags */
1580 flags = FDTF_LONGDATE | FDTF_SHORTDATE;
1581 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1582 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1583 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
1584 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1585 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1587 /* various combinations of date/time flags */
1588 flags = FDTF_LONGDATE | FDTF_SHORTTIME;
1589 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1590 ok(ret == lstrlenA(buff)+1, "got %d, length %d\n", ret, lstrlenA(buff)+1);
1591 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
1592 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1593 strcat(buff2, ", ");
1594 ret = GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3));
1595 ok(ret == lstrlenA(buff3)+1, "got %d\n", ret);
1596 strcat(buff2, buff3);
1597 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1599 flags = FDTF_LONGDATE | FDTF_LONGTIME;
1600 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1601 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1602 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
1603 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1604 strcat(buff2, ", ");
1605 ret = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3));
1606 ok(ret == lstrlenA(buff3)+1, "got %d\n", ret);
1607 strcat(buff2, buff3);
1608 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1610 flags = FDTF_SHORTDATE | FDTF_SHORTTIME;
1611 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1612 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1613 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2));
1614 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1615 strcat(buff2, " ");
1616 ret = GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3));
1617 ok(ret == lstrlenA(buff3)+1, "got %d\n", ret);
1618 strcat(buff2, buff3);
1619 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1621 flags = FDTF_SHORTDATE | FDTF_LONGTIME;
1622 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1623 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1624 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2));
1625 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1626 strcat(buff2, " ");
1627 ret = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3));
1628 ok(ret == lstrlenA(buff3)+1, "got %d\n", ret);
1629 strcat(buff2, buff3);
1630 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1633 static void test_SHFormatDateTimeW(void)
1635 FILETIME UNALIGNED filetime;
1636 WCHAR buff[100], buff2[100], buff3[100];
1637 SYSTEMTIME st;
1638 DWORD flags;
1639 INT ret;
1640 static const WCHAR spaceW[] = {' ',0};
1641 static const WCHAR commaW[] = {',',' ',0};
1643 if(!pSHFormatDateTimeW)
1645 win_skip("pSHFormatDateTimeW isn't available\n");
1646 return;
1649 if (0)
1651 /* crashes on native */
1652 ret = pSHFormatDateTimeW(NULL, NULL, NULL, 0);
1655 GetLocalTime(&st);
1656 SystemTimeToFileTime(&st, &filetime);
1657 /* SHFormatDateTime expects input as utc */
1658 LocalFileTimeToFileTime(&filetime, &filetime);
1660 /* no way to get required buffer length here */
1661 SetLastError(0xdeadbeef);
1662 ret = pSHFormatDateTimeW(&filetime, NULL, NULL, 0);
1663 ok(ret == 0, "got %d\n", ret);
1664 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1666 SetLastError(0xdeadbeef);
1667 buff[0] = 'a'; buff[1] = 0;
1668 ret = pSHFormatDateTimeW(&filetime, NULL, buff, 0);
1669 ok(ret == 0, "got %d\n", ret);
1670 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1671 ok(buff[0] == 'a', "expected same string\n");
1673 /* all combinations documented as invalid succeeded */
1674 flags = FDTF_SHORTTIME | FDTF_LONGTIME;
1675 SetLastError(0xdeadbeef);
1676 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1677 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1678 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1680 flags = FDTF_SHORTDATE | FDTF_LONGDATE;
1681 SetLastError(0xdeadbeef);
1682 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1683 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1684 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1686 flags = FDTF_SHORTDATE | FDTF_LTRDATE | FDTF_RTLDATE;
1687 SetLastError(0xdeadbeef);
1688 buff[0] = 0; /* NT4 doesn't clear the buffer on failure */
1689 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1690 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1691 ok(GetLastError() == 0xdeadbeef ||
1692 broken(GetLastError() == ERROR_INVALID_FLAGS), /* Win9x/WinMe/NT4 */
1693 "expected 0xdeadbeef, got %d\n", GetLastError());
1695 /* now check returned strings */
1696 flags = FDTF_SHORTTIME;
1697 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1698 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1699 SetLastError(0xdeadbeef);
1700 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1701 if (ret == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1703 win_skip("Needed W-functions are not implemented\n");
1704 return;
1706 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1707 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1709 flags = FDTF_LONGTIME;
1710 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1711 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1712 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1713 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1714 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1716 /* both time flags */
1717 flags = FDTF_LONGTIME | FDTF_SHORTTIME;
1718 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1719 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1720 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1721 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1722 ok(lstrcmpW(buff, buff2) == 0, "expected equal string\n");
1724 flags = FDTF_SHORTDATE;
1725 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1726 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1727 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1728 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1729 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1731 flags = FDTF_LONGDATE;
1732 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1733 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1734 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1735 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1736 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1738 /* both date flags */
1739 flags = FDTF_LONGDATE | FDTF_SHORTDATE;
1740 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1741 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1742 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1743 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1744 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1746 /* various combinations of date/time flags */
1747 flags = FDTF_LONGDATE | FDTF_SHORTTIME;
1748 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1749 ok(ret == lstrlenW(buff)+1, "got %d, length %d\n", ret, lstrlenW(buff)+1);
1750 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1751 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1752 lstrcatW(buff2, commaW);
1753 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
1754 ok(ret == lstrlenW(buff3)+1, "got %d\n", ret);
1755 lstrcatW(buff2, buff3);
1756 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1758 flags = FDTF_LONGDATE | FDTF_LONGTIME;
1759 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1760 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1761 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1762 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1763 lstrcatW(buff2, commaW);
1764 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
1765 ok(ret == lstrlenW(buff3)+1, "got %d\n", ret);
1766 lstrcatW(buff2, buff3);
1767 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1769 flags = FDTF_SHORTDATE | FDTF_SHORTTIME;
1770 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1771 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1772 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1773 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1774 lstrcatW(buff2, spaceW);
1775 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
1776 ok(ret == lstrlenW(buff3)+1, "got %d\n", ret);
1777 lstrcatW(buff2, buff3);
1778 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1780 flags = FDTF_SHORTDATE | FDTF_LONGTIME;
1781 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1782 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1783 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1784 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1785 lstrcatW(buff2, spaceW);
1786 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
1787 ok(ret == lstrlenW(buff3)+1, "got %d\n", ret);
1788 lstrcatW(buff2, buff3);
1789 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1792 static void test_SHGetObjectCompatFlags(void)
1794 struct compat_value {
1795 CHAR nameA[30];
1796 DWORD value;
1799 struct compat_value values[] = {
1800 { "OTNEEDSSFCACHE", 0x1 },
1801 { "NO_WEBVIEW", 0x2 },
1802 { "UNBINDABLE", 0x4 },
1803 { "PINDLL", 0x8 },
1804 { "NEEDSFILESYSANCESTOR", 0x10 },
1805 { "NOTAFILESYSTEM", 0x20 },
1806 { "CTXMENU_NOVERBS", 0x40 },
1807 { "CTXMENU_LIMITEDQI", 0x80 },
1808 { "COCREATESHELLFOLDERONLY", 0x100 },
1809 { "NEEDSSTORAGEANCESTOR", 0x200 },
1810 { "NOLEGACYWEBVIEW", 0x400 },
1811 { "CTXMENU_XPQCMFLAGS", 0x1000 },
1812 { "NOIPROPERTYSTORE", 0x2000 }
1815 static const char compat_path[] = "Software\\Microsoft\\Windows\\CurrentVersion\\ShellCompatibility\\Objects";
1816 CHAR keyA[39]; /* {CLSID} */
1817 HKEY root;
1818 DWORD ret;
1819 int i;
1821 if (!pSHGetObjectCompatFlags)
1823 win_skip("SHGetObjectCompatFlags isn't available\n");
1824 return;
1827 /* null args */
1828 ret = pSHGetObjectCompatFlags(NULL, NULL);
1829 ok(ret == 0, "got %d\n", ret);
1831 ret = RegOpenKeyA(HKEY_LOCAL_MACHINE, compat_path, &root);
1832 if (ret != ERROR_SUCCESS)
1834 skip("No compatibility class data found\n");
1835 return;
1838 for (i = 0; RegEnumKeyA(root, i, keyA, sizeof(keyA)) == ERROR_SUCCESS; i++)
1840 HKEY clsid_key;
1842 if (RegOpenKeyA(root, keyA, &clsid_key) == ERROR_SUCCESS)
1844 CHAR valueA[30];
1845 DWORD expected = 0, got, length = sizeof(valueA);
1846 CLSID clsid;
1847 int v;
1849 for (v = 0; RegEnumValueA(clsid_key, v, valueA, &length, NULL, NULL, NULL, NULL) == ERROR_SUCCESS; v++)
1851 int j;
1853 for (j = 0; j < sizeof(values)/sizeof(struct compat_value); j++)
1854 if (lstrcmpA(values[j].nameA, valueA) == 0)
1856 expected |= values[j].value;
1857 break;
1860 length = sizeof(valueA);
1863 pGUIDFromStringA(keyA, &clsid);
1864 got = pSHGetObjectCompatFlags(NULL, &clsid);
1865 ok(got == expected, "got 0x%08x, expected 0x%08x. Key %s\n", got, expected, keyA);
1867 RegCloseKey(clsid_key);
1871 RegCloseKey(root);
1874 static void init_pointers(void)
1876 #define MAKEFUNC(f, ord) (p##f = (void*)GetProcAddress(hShlwapi, (LPSTR)(ord)))
1877 MAKEFUNC(SHAllocShared, 7);
1878 MAKEFUNC(SHLockShared, 8);
1879 MAKEFUNC(SHUnlockShared, 9);
1880 MAKEFUNC(SHFreeShared, 10);
1881 MAKEFUNC(GetAcceptLanguagesA, 14);
1882 MAKEFUNC(SHSetWindowBits, 165);
1883 MAKEFUNC(ConnectToConnectionPoint, 168);
1884 MAKEFUNC(SHSearchMapInt, 198);
1885 MAKEFUNC(GUIDFromStringA, 269);
1886 MAKEFUNC(SHPackDispParams, 282);
1887 MAKEFUNC(IConnectionPoint_InvokeWithCancel, 283);
1888 MAKEFUNC(IConnectionPoint_SimpleInvoke, 284);
1889 MAKEFUNC(SHFormatDateTimeA, 353);
1890 MAKEFUNC(SHFormatDateTimeW, 354);
1891 MAKEFUNC(SHGetObjectCompatFlags, 476);
1892 MAKEFUNC(SHPropertyBag_ReadLONG, 496);
1893 #undef MAKEFUNC
1896 START_TEST(ordinal)
1898 hShlwapi = GetModuleHandleA("shlwapi.dll");
1900 init_pointers();
1902 hmlang = LoadLibraryA("mlang.dll");
1903 pLcidToRfc1766A = (void *)GetProcAddress(hmlang, "LcidToRfc1766A");
1905 test_GetAcceptLanguagesA();
1906 test_SHSearchMapInt();
1907 test_alloc_shared();
1908 test_fdsa();
1909 test_GetShellSecurityDescriptor();
1910 test_SHPackDispParams();
1911 test_IConnectionPoint();
1912 test_SHPropertyBag_ReadLONG();
1913 test_SHSetWindowBits();
1914 test_SHFormatDateTimeA();
1915 test_SHFormatDateTimeW();
1916 test_SHGetObjectCompatFlags();