shlwapi/tests: Fix some test failures on RTL enabled boxes.
[wine/wine-gecko.git] / dlls / shlwapi / tests / ordinal.c
blob7b0203194dd48cf97d21293f69b926b6ffabcd2d
1 /* Unit test suite for SHLWAPI ordinal functions
3 * Copyright 2004 Jon Griffiths
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include <stdio.h>
22 #define COBJMACROS
23 #include "wine/test.h"
24 #include "winbase.h"
25 #include "winerror.h"
26 #include "winuser.h"
27 #include "ole2.h"
28 #include "oaidl.h"
29 #include "ocidl.h"
30 #include "mlang.h"
31 #include "shlwapi.h"
32 #include "docobj.h"
33 #include "shobjidl.h"
34 #include "shlobj.h"
36 /* Function ptrs for ordinal calls */
37 static HMODULE hShlwapi;
38 static BOOL is_win2k_and_lower;
39 static BOOL is_win9x;
41 static int (WINAPI *pSHSearchMapInt)(const int*,const int*,int,int);
42 static HRESULT (WINAPI *pGetAcceptLanguagesA)(LPSTR,LPDWORD);
44 static HANDLE (WINAPI *pSHAllocShared)(LPCVOID,DWORD,DWORD);
45 static LPVOID (WINAPI *pSHLockShared)(HANDLE,DWORD);
46 static BOOL (WINAPI *pSHUnlockShared)(LPVOID);
47 static BOOL (WINAPI *pSHFreeShared)(HANDLE,DWORD);
48 static HRESULT(WINAPIV *pSHPackDispParams)(DISPPARAMS*,VARIANTARG*,UINT,...);
49 static HRESULT(WINAPI *pIConnectionPoint_SimpleInvoke)(IConnectionPoint*,DISPID,DISPPARAMS*);
50 static HRESULT(WINAPI *pIConnectionPoint_InvokeWithCancel)(IConnectionPoint*,DISPID,DISPPARAMS*,DWORD,DWORD);
51 static HRESULT(WINAPI *pConnectToConnectionPoint)(IUnknown*,REFIID,BOOL,IUnknown*, LPDWORD,IConnectionPoint **);
52 static HRESULT(WINAPI *pSHPropertyBag_ReadLONG)(IPropertyBag *,LPCWSTR,LPLONG);
53 static LONG (WINAPI *pSHSetWindowBits)(HWND, INT, UINT, UINT);
54 static INT (WINAPI *pSHFormatDateTimeA)(const FILETIME UNALIGNED*, DWORD*, LPSTR, UINT);
55 static INT (WINAPI *pSHFormatDateTimeW)(const FILETIME UNALIGNED*, DWORD*, LPWSTR, UINT);
56 static DWORD (WINAPI *pSHGetObjectCompatFlags)(IUnknown*, const CLSID*);
57 static BOOL (WINAPI *pGUIDFromStringA)(LPSTR, CLSID *);
58 static HRESULT (WINAPI *pIUnknown_QueryServiceExec)(IUnknown*, REFIID, const GUID*, DWORD, DWORD, VARIANT*, VARIANT*);
59 static HRESULT (WINAPI *pIUnknown_ProfferService)(IUnknown*, REFGUID, IServiceProvider*, DWORD*);
60 static HWND (WINAPI *pSHCreateWorkerWindowA)(LONG, HWND, DWORD, DWORD, HMENU, LONG_PTR);
61 static HRESULT (WINAPI *pSHIShellFolder_EnumObjects)(LPSHELLFOLDER, HWND, SHCONTF, IEnumIDList**);
62 static DWORD (WINAPI *pSHGetIniStringW)(LPCWSTR, LPCWSTR, LPWSTR, DWORD, LPCWSTR);
63 static BOOL (WINAPI *pSHSetIniStringW)(LPCWSTR, LPCWSTR, LPCWSTR, LPCWSTR);
64 static HKEY (WINAPI *pSHGetShellKey)(DWORD, LPWSTR, BOOL);
66 static HMODULE hmlang;
67 static HRESULT (WINAPI *pLcidToRfc1766A)(LCID, LPSTR, INT);
69 static HMODULE hshell32;
70 static HRESULT (WINAPI *pSHGetDesktopFolder)(IShellFolder**);
72 static const CHAR ie_international[] = {
73 'S','o','f','t','w','a','r','e','\\',
74 'M','i','c','r','o','s','o','f','t','\\',
75 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
76 'I','n','t','e','r','n','a','t','i','o','n','a','l',0};
77 static const CHAR acceptlanguage[] = {
78 'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0};
80 static int strcmp_wa(LPCWSTR strw, const char *stra)
82 CHAR buf[512];
83 WideCharToMultiByte(CP_ACP, 0, strw, -1, buf, sizeof(buf), NULL, NULL);
84 return lstrcmpA(stra, buf);
87 typedef struct {
88 int id;
89 const void *args[5];
90 } call_entry_t;
92 typedef struct {
93 call_entry_t *calls;
94 int count;
95 int alloc;
96 } call_trace_t;
98 static void init_call_trace(call_trace_t *ctrace)
100 ctrace->alloc = 10;
101 ctrace->count = 0;
102 ctrace->calls = HeapAlloc(GetProcessHeap(), 0, sizeof(call_entry_t) * ctrace->alloc);
105 static void free_call_trace(const call_trace_t *ctrace)
107 HeapFree(GetProcessHeap(), 0, ctrace->calls);
110 static void add_call(call_trace_t *ctrace, int id, const void *arg0,
111 const void *arg1, const void *arg2, const void *arg3, const void *arg4)
113 call_entry_t call;
115 call.id = id;
116 call.args[0] = arg0;
117 call.args[1] = arg1;
118 call.args[2] = arg2;
119 call.args[3] = arg3;
120 call.args[4] = arg4;
122 if (ctrace->count == ctrace->alloc)
124 ctrace->alloc *= 2;
125 ctrace->calls = HeapReAlloc(GetProcessHeap(),0, ctrace->calls, ctrace->alloc*sizeof(call_entry_t));
128 ctrace->calls[ctrace->count++] = call;
131 static void ok_trace_(call_trace_t *texpected, call_trace_t *tgot, int line)
133 if (texpected->count == tgot->count)
135 INT i;
136 /* compare */
137 for (i = 0; i < texpected->count; i++)
139 call_entry_t *expected = &texpected->calls[i];
140 call_entry_t *got = &tgot->calls[i];
141 INT j;
143 ok_(__FILE__, line)(expected->id == got->id, "got different ids %d: %d, %d\n", i+1, expected->id, got->id);
145 for (j = 0; j < 5; j++)
147 ok_(__FILE__, line)(expected->args[j] == got->args[j], "got different args[%d] for %d: %p, %p\n", j, i+1,
148 expected->args[j], got->args[j]);
152 else
153 ok_(__FILE__, line)(0, "traces length mismatch\n");
156 #define ok_trace(a, b) ok_trace_(a, b, __LINE__)
158 /* trace of actually made calls */
159 static call_trace_t trace_got;
161 static void test_GetAcceptLanguagesA(void)
163 static LPCSTR table[] = {"de,en-gb;q=0.7,en;q=0.3",
164 "de,en;q=0.3,en-gb;q=0.7", /* sorting is ignored */
165 "winetest", /* content is ignored */
166 "de-de,de;q=0.5",
167 "de",
168 NULL};
170 DWORD exactsize;
171 char original[512];
172 char language[32];
173 char buffer[64];
174 HKEY hroot = NULL;
175 LONG res_query = ERROR_SUCCESS;
176 LONG lres;
177 HRESULT hr;
178 DWORD maxlen = sizeof(buffer) - 2;
179 DWORD len;
180 LCID lcid;
181 LPCSTR entry;
182 INT i = 0;
184 if (!pGetAcceptLanguagesA) {
185 win_skip("GetAcceptLanguagesA is not available\n");
186 return;
189 lcid = GetUserDefaultLCID();
191 /* Get the original Value */
192 lres = RegOpenKeyA(HKEY_CURRENT_USER, ie_international, &hroot);
193 if (lres) {
194 skip("RegOpenKey(%s) failed: %d\n", ie_international, lres);
195 return;
197 len = sizeof(original);
198 original[0] = 0;
199 res_query = RegQueryValueExA(hroot, acceptlanguage, 0, NULL, (PBYTE)original, &len);
201 RegDeleteValue(hroot, acceptlanguage);
203 /* Some windows versions use "lang-COUNTRY" as default */
204 memset(language, 0, sizeof(language));
205 len = GetLocaleInfoA(lcid, LOCALE_SISO639LANGNAME, language, sizeof(language));
207 if (len) {
208 lstrcat(language, "-");
209 memset(buffer, 0, sizeof(buffer));
210 len = GetLocaleInfoA(lcid, LOCALE_SISO3166CTRYNAME, buffer, sizeof(buffer) - len - 1);
211 lstrcat(language, buffer);
213 else
215 /* LOCALE_SNAME has additional parts in some languages. Try only as last chance */
216 memset(language, 0, sizeof(language));
217 len = GetLocaleInfoA(lcid, LOCALE_SNAME, language, sizeof(language));
220 /* get the default value */
221 len = maxlen;
222 memset(buffer, '#', maxlen);
223 buffer[maxlen] = 0;
224 hr = pGetAcceptLanguagesA( buffer, &len);
226 if (hr != S_OK) {
227 win_skip("GetAcceptLanguagesA failed with 0x%x\n", hr);
228 goto restore_original;
231 if (lstrcmpA(buffer, language)) {
232 /* some windows versions use "lang" or "lang-country" as default */
233 language[0] = 0;
234 if (pLcidToRfc1766A) {
235 hr = pLcidToRfc1766A(lcid, language, sizeof(language));
236 ok(hr == S_OK, "LcidToRfc1766A returned 0x%x and %s\n", hr, language);
240 ok(!lstrcmpA(buffer, language),
241 "have '%s' (searching for '%s')\n", language, buffer);
243 if (lstrcmpA(buffer, language)) {
244 win_skip("no more ideas, how to build the default language '%s'\n", buffer);
245 goto restore_original;
248 trace("detected default: %s\n", language);
249 while ((entry = table[i])) {
251 exactsize = lstrlenA(entry);
253 lres = RegSetValueExA(hroot, acceptlanguage, 0, REG_SZ, (const BYTE *) entry, exactsize + 1);
254 ok(!lres, "got %d for RegSetValueExA: %s\n", lres, entry);
256 /* len includes space for the terminating 0 before vista/w2k8 */
257 len = exactsize + 2;
258 memset(buffer, '#', maxlen);
259 buffer[maxlen] = 0;
260 hr = pGetAcceptLanguagesA( buffer, &len);
261 ok(((hr == E_INVALIDARG) && (len == 0)) ||
262 (SUCCEEDED(hr) &&
263 ((len == exactsize) || (len == exactsize+1)) &&
264 !lstrcmpA(buffer, entry)),
265 "+2_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
267 len = exactsize + 1;
268 memset(buffer, '#', maxlen);
269 buffer[maxlen] = 0;
270 hr = pGetAcceptLanguagesA( buffer, &len);
271 ok(((hr == E_INVALIDARG) && (len == 0)) ||
272 (SUCCEEDED(hr) &&
273 ((len == exactsize) || (len == exactsize+1)) &&
274 !lstrcmpA(buffer, entry)),
275 "+1_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
277 len = exactsize;
278 memset(buffer, '#', maxlen);
279 buffer[maxlen] = 0;
280 hr = pGetAcceptLanguagesA( buffer, &len);
282 /* There is no space for the string in the registry.
283 When the buffer is large enough, the default language is returned
285 When the buffer is too small for that fallback, win7_32 and w2k8_64
286 and above fail with HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), but
287 recent os succeed and return a partial result while
288 older os succeed and overflow the buffer */
290 ok(((hr == E_INVALIDARG) && (len == 0)) ||
291 (((hr == S_OK) && !lstrcmpA(buffer, language) && (len == lstrlenA(language))) ||
292 ((hr == S_OK) && !memcmp(buffer, language, len)) ||
293 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len)),
294 "==_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
296 if (exactsize > 1) {
297 len = exactsize - 1;
298 memset(buffer, '#', maxlen);
299 buffer[maxlen] = 0;
300 hr = pGetAcceptLanguagesA( buffer, &len);
301 ok(((hr == E_INVALIDARG) && (len == 0)) ||
302 (((hr == S_OK) && !lstrcmpA(buffer, language) && (len == lstrlenA(language))) ||
303 ((hr == S_OK) && !memcmp(buffer, language, len)) ||
304 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len)),
305 "-1_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
308 len = 1;
309 memset(buffer, '#', maxlen);
310 buffer[maxlen] = 0;
311 hr = pGetAcceptLanguagesA( buffer, &len);
312 ok(((hr == E_INVALIDARG) && (len == 0)) ||
313 (((hr == S_OK) && !lstrcmpA(buffer, language) && (len == lstrlenA(language))) ||
314 ((hr == S_OK) && !memcmp(buffer, language, len)) ||
315 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len)),
316 "=1_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
318 len = maxlen;
319 hr = pGetAcceptLanguagesA( NULL, &len);
321 /* w2k3 and below: E_FAIL and untouched len,
322 since w2k8: S_OK and needed size (excluding 0) */
323 ok( ((hr == S_OK) && (len == exactsize)) ||
324 ((hr == E_FAIL) && (len == maxlen)),
325 "NULL,max #%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
327 i++;
330 /* without a value in the registry, a default language is returned */
331 RegDeleteValue(hroot, acceptlanguage);
333 len = maxlen;
334 memset(buffer, '#', maxlen);
335 buffer[maxlen] = 0;
336 hr = pGetAcceptLanguagesA( buffer, &len);
337 ok( ((hr == S_OK) && (len == lstrlenA(language))),
338 "max: got 0x%x with %d and %s (expected S_OK with %d and '%s'\n",
339 hr, len, buffer, lstrlenA(language), language);
341 len = 2;
342 memset(buffer, '#', maxlen);
343 buffer[maxlen] = 0;
344 hr = pGetAcceptLanguagesA( buffer, &len);
345 ok( (((hr == S_OK) || (hr == E_INVALIDARG)) && !memcmp(buffer, language, len)) ||
346 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len),
347 "=2: got 0x%x with %d and %s\n", hr, len, buffer);
349 len = 1;
350 memset(buffer, '#', maxlen);
351 buffer[maxlen] = 0;
352 hr = pGetAcceptLanguagesA( buffer, &len);
353 /* When the buffer is too small, win7_32 and w2k8_64 and above fail with
354 HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), other versions suceed
355 and return a partial 0 terminated result while other versions
356 fail with E_INVALIDARG and return a partial unterminated result */
357 ok( (((hr == S_OK) || (hr == E_INVALIDARG)) && !memcmp(buffer, language, len)) ||
358 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len),
359 "=1: got 0x%x with %d and %s\n", hr, len, buffer);
361 len = 0;
362 memset(buffer, '#', maxlen);
363 buffer[maxlen] = 0;
364 hr = pGetAcceptLanguagesA( buffer, &len);
365 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
366 ok((hr == E_FAIL) || (hr == E_INVALIDARG),
367 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr);
369 memset(buffer, '#', maxlen);
370 buffer[maxlen] = 0;
371 hr = pGetAcceptLanguagesA( buffer, NULL);
372 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
373 ok((hr == E_FAIL) || (hr == E_INVALIDARG),
374 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr);
377 hr = pGetAcceptLanguagesA( NULL, NULL);
378 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
379 ok((hr == E_FAIL) || (hr == E_INVALIDARG),
380 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr);
382 restore_original:
383 if (!res_query) {
384 len = lstrlenA(original);
385 lres = RegSetValueExA(hroot, acceptlanguage, 0, REG_SZ, (const BYTE *) original, len ? len + 1: 0);
386 ok(!lres, "RegSetValueEx(%s) failed: %d\n", original, lres);
388 else
390 RegDeleteValue(hroot, acceptlanguage);
392 RegCloseKey(hroot);
395 static void test_SHSearchMapInt(void)
397 int keys[8], values[8];
398 int i = 0;
400 if (!pSHSearchMapInt)
401 return;
403 memset(keys, 0, sizeof(keys));
404 memset(values, 0, sizeof(values));
405 keys[0] = 99; values[0] = 101;
407 /* NULL key/value lists crash native, so skip testing them */
409 /* 1 element */
410 i = pSHSearchMapInt(keys, values, 1, keys[0]);
411 ok(i == values[0], "Len 1, expected %d, got %d\n", values[0], i);
413 /* Key doesn't exist */
414 i = pSHSearchMapInt(keys, values, 1, 100);
415 ok(i == -1, "Len 1 - bad key, expected -1, got %d\n", i);
417 /* Len = 0 => not found */
418 i = pSHSearchMapInt(keys, values, 0, keys[0]);
419 ok(i == -1, "Len 1 - passed len 0, expected -1, got %d\n", i);
421 /* 2 elements, len = 1 */
422 keys[1] = 98; values[1] = 102;
423 i = pSHSearchMapInt(keys, values, 1, keys[1]);
424 ok(i == -1, "Len 1 - array len 2, expected -1, got %d\n", i);
426 /* 2 elements, len = 2 */
427 i = pSHSearchMapInt(keys, values, 2, keys[1]);
428 ok(i == values[1], "Len 2, expected %d, got %d\n", values[1], i);
430 /* Searches forward */
431 keys[2] = 99; values[2] = 103;
432 i = pSHSearchMapInt(keys, values, 3, keys[0]);
433 ok(i == values[0], "Len 3, expected %d, got %d\n", values[0], i);
436 static void test_alloc_shared(void)
438 DWORD procid;
439 HANDLE hmem;
440 int val;
441 int* p;
442 BOOL ret;
444 procid=GetCurrentProcessId();
445 hmem=pSHAllocShared(NULL,10,procid);
446 ok(hmem!=NULL,"SHAllocShared(NULL...) failed: %u\n", GetLastError());
447 ret = pSHFreeShared(hmem, procid);
448 ok( ret, "SHFreeShared failed: %u\n", GetLastError());
450 val=0x12345678;
451 hmem=pSHAllocShared(&val,4,procid);
452 ok(hmem!=NULL,"SHAllocShared(NULL...) failed: %u\n", GetLastError());
454 p=pSHLockShared(hmem,procid);
455 ok(p!=NULL,"SHLockShared failed: %u\n", GetLastError());
456 if (p!=NULL)
457 ok(*p==val,"Wrong value in shared memory: %d instead of %d\n",*p,val);
458 ret = pSHUnlockShared(p);
459 ok( ret, "SHUnlockShared failed: %u\n", GetLastError());
461 ret = pSHFreeShared(hmem, procid);
462 ok( ret, "SHFreeShared failed: %u\n", GetLastError());
465 static void test_fdsa(void)
467 typedef struct
469 DWORD num_items; /* Number of elements inserted */
470 void *mem; /* Ptr to array */
471 DWORD blocks_alloced; /* Number of elements allocated */
472 BYTE inc; /* Number of elements to grow by when we need to expand */
473 BYTE block_size; /* Size in bytes of an element */
474 BYTE flags; /* Flags */
475 } FDSA_info;
477 BOOL (WINAPI *pFDSA_Initialize)(DWORD block_size, DWORD inc, FDSA_info *info, void *mem,
478 DWORD init_blocks);
479 BOOL (WINAPI *pFDSA_Destroy)(FDSA_info *info);
480 DWORD (WINAPI *pFDSA_InsertItem)(FDSA_info *info, DWORD where, const void *block);
481 BOOL (WINAPI *pFDSA_DeleteItem)(FDSA_info *info, DWORD where);
483 FDSA_info info;
484 int block_size = 10, init_blocks = 4, inc = 2;
485 DWORD ret;
486 char *mem;
488 pFDSA_Initialize = (void *)GetProcAddress(hShlwapi, (LPSTR)208);
489 pFDSA_Destroy = (void *)GetProcAddress(hShlwapi, (LPSTR)209);
490 pFDSA_InsertItem = (void *)GetProcAddress(hShlwapi, (LPSTR)210);
491 pFDSA_DeleteItem = (void *)GetProcAddress(hShlwapi, (LPSTR)211);
493 mem = HeapAlloc(GetProcessHeap(), 0, block_size * init_blocks);
494 memset(&info, 0, sizeof(info));
496 ok(pFDSA_Initialize(block_size, inc, &info, mem, init_blocks), "FDSA_Initialize rets FALSE\n");
497 ok(info.num_items == 0, "num_items = %d\n", info.num_items);
498 ok(info.mem == mem, "mem = %p\n", info.mem);
499 ok(info.blocks_alloced == init_blocks, "blocks_alloced = %d\n", info.blocks_alloced);
500 ok(info.inc == inc, "inc = %d\n", info.inc);
501 ok(info.block_size == block_size, "block_size = %d\n", info.block_size);
502 ok(info.flags == 0, "flags = %d\n", info.flags);
504 ret = pFDSA_InsertItem(&info, 1234, "1234567890");
505 ok(ret == 0, "ret = %d\n", ret);
506 ok(info.num_items == 1, "num_items = %d\n", info.num_items);
507 ok(info.mem == mem, "mem = %p\n", info.mem);
508 ok(info.blocks_alloced == init_blocks, "blocks_alloced = %d\n", info.blocks_alloced);
509 ok(info.inc == inc, "inc = %d\n", info.inc);
510 ok(info.block_size == block_size, "block_size = %d\n", info.block_size);
511 ok(info.flags == 0, "flags = %d\n", info.flags);
513 ret = pFDSA_InsertItem(&info, 1234, "abcdefghij");
514 ok(ret == 1, "ret = %d\n", ret);
516 ret = pFDSA_InsertItem(&info, 1, "klmnopqrst");
517 ok(ret == 1, "ret = %d\n", ret);
519 ret = pFDSA_InsertItem(&info, 0, "uvwxyzABCD");
520 ok(ret == 0, "ret = %d\n", ret);
521 ok(info.mem == mem, "mem = %p\n", info.mem);
522 ok(info.flags == 0, "flags = %d\n", info.flags);
524 /* This next InsertItem will cause shlwapi to allocate its own mem buffer */
525 ret = pFDSA_InsertItem(&info, 0, "EFGHIJKLMN");
526 ok(ret == 0, "ret = %d\n", ret);
527 ok(info.mem != mem, "mem = %p\n", info.mem);
528 ok(info.blocks_alloced == init_blocks + inc, "blocks_alloced = %d\n", info.blocks_alloced);
529 ok(info.flags == 0x1, "flags = %d\n", info.flags);
531 ok(!memcmp(info.mem, "EFGHIJKLMNuvwxyzABCD1234567890klmnopqrstabcdefghij", 50), "mem %s\n", (char*)info.mem);
533 ok(pFDSA_DeleteItem(&info, 2), "rets FALSE\n");
534 ok(info.mem != mem, "mem = %p\n", info.mem);
535 ok(info.blocks_alloced == init_blocks + inc, "blocks_alloced = %d\n", info.blocks_alloced);
536 ok(info.flags == 0x1, "flags = %d\n", info.flags);
538 ok(!memcmp(info.mem, "EFGHIJKLMNuvwxyzABCDklmnopqrstabcdefghij", 40), "mem %s\n", (char*)info.mem);
540 ok(pFDSA_DeleteItem(&info, 3), "rets FALSE\n");
541 ok(info.mem != mem, "mem = %p\n", info.mem);
542 ok(info.blocks_alloced == init_blocks + inc, "blocks_alloced = %d\n", info.blocks_alloced);
543 ok(info.flags == 0x1, "flags = %d\n", info.flags);
545 ok(!memcmp(info.mem, "EFGHIJKLMNuvwxyzABCDklmnopqrst", 30), "mem %s\n", (char*)info.mem);
547 ok(!pFDSA_DeleteItem(&info, 4), "does not ret FALSE\n");
549 /* As shlwapi has allocated memory internally, Destroy will ret FALSE */
550 ok(!pFDSA_Destroy(&info), "FDSA_Destroy does not ret FALSE\n");
553 /* When Initialize is called with inc = 0, set it to 1 */
554 ok(pFDSA_Initialize(block_size, 0, &info, mem, init_blocks), "FDSA_Initialize rets FALSE\n");
555 ok(info.inc == 1, "inc = %d\n", info.inc);
557 /* This time, because shlwapi hasn't had to allocate memory
558 internally, Destroy rets non-zero */
559 ok(pFDSA_Destroy(&info), "FDSA_Destroy rets FALSE\n");
562 HeapFree(GetProcessHeap(), 0, mem);
566 typedef struct SHELL_USER_SID {
567 SID_IDENTIFIER_AUTHORITY sidAuthority;
568 DWORD dwUserGroupID;
569 DWORD dwUserID;
570 } SHELL_USER_SID, *PSHELL_USER_SID;
571 typedef struct SHELL_USER_PERMISSION {
572 SHELL_USER_SID susID;
573 DWORD dwAccessType;
574 BOOL fInherit;
575 DWORD dwAccessMask;
576 DWORD dwInheritMask;
577 DWORD dwInheritAccessMask;
578 } SHELL_USER_PERMISSION, *PSHELL_USER_PERMISSION;
579 static void test_GetShellSecurityDescriptor(void)
581 SHELL_USER_PERMISSION supCurrentUserFull = {
582 { {SECURITY_NULL_SID_AUTHORITY}, 0, 0 },
583 ACCESS_ALLOWED_ACE_TYPE, FALSE,
584 GENERIC_ALL, 0, 0 };
585 #define MY_INHERITANCE 0xBE /* invalid value to proof behavior */
586 SHELL_USER_PERMISSION supEveryoneDenied = {
587 { {SECURITY_WORLD_SID_AUTHORITY}, SECURITY_WORLD_RID, 0 },
588 ACCESS_DENIED_ACE_TYPE, TRUE,
589 GENERIC_WRITE, MY_INHERITANCE | 0xDEADBA00, GENERIC_READ };
590 PSHELL_USER_PERMISSION rgsup[2] = {
591 &supCurrentUserFull, &supEveryoneDenied,
593 SECURITY_DESCRIPTOR* psd;
594 SECURITY_DESCRIPTOR* (WINAPI*pGetShellSecurityDescriptor)(PSHELL_USER_PERMISSION*,int);
595 void *pChrCmpIW = GetProcAddress(hShlwapi, "ChrCmpIW");
597 pGetShellSecurityDescriptor=(void*)GetProcAddress(hShlwapi,(char*)475);
599 if(!pGetShellSecurityDescriptor)
601 win_skip("GetShellSecurityDescriptor not available\n");
602 return;
605 if(pChrCmpIW && pChrCmpIW == pGetShellSecurityDescriptor) /* win2k */
607 win_skip("Skipping for GetShellSecurityDescriptor, same ordinal used for ChrCmpIW\n");
608 return;
611 psd = pGetShellSecurityDescriptor(NULL, 2);
612 ok(psd==NULL ||
613 broken(psd==INVALID_HANDLE_VALUE), /* IE5 */
614 "GetShellSecurityDescriptor should fail\n");
615 psd = pGetShellSecurityDescriptor(rgsup, 0);
616 ok(psd==NULL, "GetShellSecurityDescriptor should fail, got %p\n", psd);
618 SetLastError(0xdeadbeef);
619 psd = pGetShellSecurityDescriptor(rgsup, 2);
620 if (psd == NULL && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
622 /* The previous calls to GetShellSecurityDescriptor don't set the last error */
623 win_skip("GetShellSecurityDescriptor is not implemented\n");
624 return;
626 if (psd == INVALID_HANDLE_VALUE)
628 win_skip("GetShellSecurityDescriptor is broken on IE5\n");
629 return;
631 ok(psd!=NULL, "GetShellSecurityDescriptor failed\n");
632 if (psd!=NULL)
634 BOOL bHasDacl = FALSE, bDefaulted;
635 PACL pAcl;
636 DWORD dwRev;
637 SECURITY_DESCRIPTOR_CONTROL control;
639 ok(IsValidSecurityDescriptor(psd), "returned value is not valid SD\n");
641 ok(GetSecurityDescriptorControl(psd, &control, &dwRev),
642 "GetSecurityDescriptorControl failed with error %u\n", GetLastError());
643 ok(0 == (control & SE_SELF_RELATIVE), "SD should be absolute\n");
645 ok(GetSecurityDescriptorDacl(psd, &bHasDacl, &pAcl, &bDefaulted),
646 "GetSecurityDescriptorDacl failed with error %u\n", GetLastError());
648 ok(bHasDacl, "SD has no DACL\n");
649 if (bHasDacl)
651 ok(!bDefaulted, "DACL should not be defaulted\n");
653 ok(pAcl != NULL, "NULL DACL!\n");
654 if (pAcl != NULL)
656 ACL_SIZE_INFORMATION asiSize;
658 ok(IsValidAcl(pAcl), "DACL is not valid\n");
660 ok(GetAclInformation(pAcl, &asiSize, sizeof(asiSize), AclSizeInformation),
661 "GetAclInformation failed with error %u\n", GetLastError());
663 ok(asiSize.AceCount == 3, "Incorrect number of ACEs: %d entries\n", asiSize.AceCount);
664 if (asiSize.AceCount == 3)
666 ACCESS_ALLOWED_ACE *paaa; /* will use for DENIED too */
668 ok(GetAce(pAcl, 0, (LPVOID*)&paaa), "GetAce failed with error %u\n", GetLastError());
669 ok(paaa->Header.AceType == ACCESS_ALLOWED_ACE_TYPE,
670 "Invalid ACE type %d\n", paaa->Header.AceType);
671 ok(paaa->Header.AceFlags == 0, "Invalid ACE flags %x\n", paaa->Header.AceFlags);
672 ok(paaa->Mask == GENERIC_ALL, "Invalid ACE mask %x\n", paaa->Mask);
674 ok(GetAce(pAcl, 1, (LPVOID*)&paaa), "GetAce failed with error %u\n", GetLastError());
675 ok(paaa->Header.AceType == ACCESS_DENIED_ACE_TYPE,
676 "Invalid ACE type %d\n", paaa->Header.AceType);
677 /* first one of two ACEs generated from inheritable entry - without inheritance */
678 ok(paaa->Header.AceFlags == 0, "Invalid ACE flags %x\n", paaa->Header.AceFlags);
679 ok(paaa->Mask == GENERIC_WRITE, "Invalid ACE mask %x\n", paaa->Mask);
681 ok(GetAce(pAcl, 2, (LPVOID*)&paaa), "GetAce failed with error %u\n", GetLastError());
682 ok(paaa->Header.AceType == ACCESS_DENIED_ACE_TYPE,
683 "Invalid ACE type %d\n", paaa->Header.AceType);
684 /* second ACE - with inheritance */
685 ok(paaa->Header.AceFlags == MY_INHERITANCE,
686 "Invalid ACE flags %x\n", paaa->Header.AceFlags);
687 ok(paaa->Mask == GENERIC_READ, "Invalid ACE mask %x\n", paaa->Mask);
692 LocalFree(psd);
696 static void test_SHPackDispParams(void)
698 DISPPARAMS params;
699 VARIANT vars[10];
700 HRESULT hres;
702 if(!pSHPackDispParams)
703 win_skip("SHPackSidpParams not available\n");
705 memset(&params, 0xc0, sizeof(params));
706 memset(vars, 0xc0, sizeof(vars));
707 hres = pSHPackDispParams(&params, vars, 1, VT_I4, 0xdeadbeef);
708 ok(hres == S_OK, "SHPackDispParams failed: %08x\n", hres);
709 ok(params.cArgs == 1, "params.cArgs = %d\n", params.cArgs);
710 ok(params.cNamedArgs == 0, "params.cNamedArgs = %d\n", params.cArgs);
711 ok(params.rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", params.rgdispidNamedArgs);
712 ok(params.rgvarg == vars, "params.rgvarg = %p\n", params.rgvarg);
713 ok(V_VT(vars) == VT_I4, "V_VT(var) = %d\n", V_VT(vars));
714 ok(V_I4(vars) == 0xdeadbeef, "failed %x\n", V_I4(vars));
716 memset(&params, 0xc0, sizeof(params));
717 hres = pSHPackDispParams(&params, NULL, 0, 0);
718 ok(hres == S_OK, "SHPackDispParams failed: %08x\n", hres);
719 ok(params.cArgs == 0, "params.cArgs = %d\n", params.cArgs);
720 ok(params.cNamedArgs == 0, "params.cNamedArgs = %d\n", params.cArgs);
721 ok(params.rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", params.rgdispidNamedArgs);
722 ok(params.rgvarg == NULL, "params.rgvarg = %p\n", params.rgvarg);
724 memset(vars, 0xc0, sizeof(vars));
725 memset(&params, 0xc0, sizeof(params));
726 hres = pSHPackDispParams(&params, vars, 4, VT_BSTR, (void*)0xdeadbeef, VT_EMPTY, 10,
727 VT_I4, 100, VT_DISPATCH, (void*)0xdeadbeef);
728 ok(hres == S_OK, "SHPackDispParams failed: %08x\n", hres);
729 ok(params.cArgs == 4, "params.cArgs = %d\n", params.cArgs);
730 ok(params.cNamedArgs == 0, "params.cNamedArgs = %d\n", params.cArgs);
731 ok(params.rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", params.rgdispidNamedArgs);
732 ok(params.rgvarg == vars, "params.rgvarg = %p\n", params.rgvarg);
733 ok(V_VT(vars) == VT_DISPATCH, "V_VT(vars[0]) = %x\n", V_VT(vars));
734 ok(V_I4(vars) == 0xdeadbeef, "V_I4(vars[0]) = %x\n", V_I4(vars));
735 ok(V_VT(vars+1) == VT_I4, "V_VT(vars[1]) = %d\n", V_VT(vars+1));
736 ok(V_I4(vars+1) == 100, "V_I4(vars[1]) = %x\n", V_I4(vars+1));
737 ok(V_VT(vars+2) == VT_I4, "V_VT(vars[2]) = %d\n", V_VT(vars+2));
738 ok(V_I4(vars+2) == 10, "V_I4(vars[2]) = %x\n", V_I4(vars+2));
739 ok(V_VT(vars+3) == VT_BSTR, "V_VT(vars[3]) = %d\n", V_VT(vars+3));
740 ok(V_BSTR(vars+3) == (void*)0xdeadbeef, "V_BSTR(vars[3]) = %p\n", V_BSTR(vars+3));
743 typedef struct _disp
745 const IDispatchVtbl *vtbl;
746 LONG refCount;
747 } Disp;
749 typedef struct _contain
751 const IConnectionPointContainerVtbl *vtbl;
752 LONG refCount;
754 UINT ptCount;
755 IConnectionPoint **pt;
756 } Contain;
758 typedef struct _cntptn
760 const IConnectionPointVtbl *vtbl;
761 LONG refCount;
763 Contain *container;
764 GUID id;
765 UINT sinkCount;
766 IUnknown **sink;
767 } ConPt;
769 typedef struct _enum
771 const IEnumConnectionsVtbl *vtbl;
772 LONG refCount;
774 UINT idx;
775 ConPt *pt;
776 } EnumCon;
778 typedef struct _enumpt
780 const IEnumConnectionPointsVtbl *vtbl;
781 LONG refCount;
783 int idx;
784 Contain *container;
785 } EnumPt;
788 static HRESULT WINAPI Disp_QueryInterface(
789 IDispatch* This,
790 REFIID riid,
791 void **ppvObject)
793 *ppvObject = NULL;
795 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch))
797 *ppvObject = This;
800 if (*ppvObject)
802 IUnknown_AddRef(This);
803 return S_OK;
806 trace("no interface\n");
807 return E_NOINTERFACE;
810 static ULONG WINAPI Disp_AddRef(IDispatch* This)
812 Disp *iface = (Disp*)This;
813 return InterlockedIncrement(&iface->refCount);
816 static ULONG WINAPI Disp_Release(IDispatch* This)
818 Disp *iface = (Disp*)This;
819 ULONG ret;
821 ret = InterlockedDecrement(&iface->refCount);
822 if (ret == 0)
823 HeapFree(GetProcessHeap(),0,This);
824 return ret;
827 static HRESULT WINAPI Disp_GetTypeInfoCount(
828 IDispatch* This,
829 UINT *pctinfo)
831 return ERROR_SUCCESS;
834 static HRESULT WINAPI Disp_GetTypeInfo(
835 IDispatch* This,
836 UINT iTInfo,
837 LCID lcid,
838 ITypeInfo **ppTInfo)
840 return ERROR_SUCCESS;
843 static HRESULT WINAPI Disp_GetIDsOfNames(
844 IDispatch* This,
845 REFIID riid,
846 LPOLESTR *rgszNames,
847 UINT cNames,
848 LCID lcid,
849 DISPID *rgDispId)
851 return ERROR_SUCCESS;
854 static HRESULT WINAPI Disp_Invoke(
855 IDispatch* This,
856 DISPID dispIdMember,
857 REFIID riid,
858 LCID lcid,
859 WORD wFlags,
860 DISPPARAMS *pDispParams,
861 VARIANT *pVarResult,
862 EXCEPINFO *pExcepInfo,
863 UINT *puArgErr)
865 trace("%p %x %p %x %x %p %p %p %p\n",This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr);
867 ok(dispIdMember == 0xa0 || dispIdMember == 0xa1, "Unknown dispIdMember\n");
868 ok(pDispParams != NULL, "Invoked with NULL pDispParams\n");
869 ok(wFlags == DISPATCH_METHOD, "Wrong flags %x\n",wFlags);
870 ok(lcid == 0,"Wrong lcid %x\n",lcid);
871 if (dispIdMember == 0xa0)
873 ok(pDispParams->cArgs == 0, "params.cArgs = %d\n", pDispParams->cArgs);
874 ok(pDispParams->cNamedArgs == 0, "params.cNamedArgs = %d\n", pDispParams->cArgs);
875 ok(pDispParams->rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", pDispParams->rgdispidNamedArgs);
876 ok(pDispParams->rgvarg == NULL, "params.rgvarg = %p\n", pDispParams->rgvarg);
878 else if (dispIdMember == 0xa1)
880 ok(pDispParams->cArgs == 2, "params.cArgs = %d\n", pDispParams->cArgs);
881 ok(pDispParams->cNamedArgs == 0, "params.cNamedArgs = %d\n", pDispParams->cArgs);
882 ok(pDispParams->rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", pDispParams->rgdispidNamedArgs);
883 ok(V_VT(pDispParams->rgvarg) == VT_BSTR, "V_VT(var) = %d\n", V_VT(pDispParams->rgvarg));
884 ok(V_I4(pDispParams->rgvarg) == 0xdeadcafe , "failed %p\n", V_BSTR(pDispParams->rgvarg));
885 ok(V_VT(pDispParams->rgvarg+1) == VT_I4, "V_VT(var) = %d\n", V_VT(pDispParams->rgvarg+1));
886 ok(V_I4(pDispParams->rgvarg+1) == 0xdeadbeef, "failed %x\n", V_I4(pDispParams->rgvarg+1));
889 return ERROR_SUCCESS;
892 static const IDispatchVtbl disp_vtbl = {
893 Disp_QueryInterface,
894 Disp_AddRef,
895 Disp_Release,
897 Disp_GetTypeInfoCount,
898 Disp_GetTypeInfo,
899 Disp_GetIDsOfNames,
900 Disp_Invoke
903 static HRESULT WINAPI Enum_QueryInterface(
904 IEnumConnections* This,
905 REFIID riid,
906 void **ppvObject)
908 *ppvObject = NULL;
910 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IEnumConnections))
912 *ppvObject = This;
915 if (*ppvObject)
917 IUnknown_AddRef(This);
918 return S_OK;
921 trace("no interface\n");
922 return E_NOINTERFACE;
925 static ULONG WINAPI Enum_AddRef(IEnumConnections* This)
927 EnumCon *iface = (EnumCon*)This;
928 return InterlockedIncrement(&iface->refCount);
931 static ULONG WINAPI Enum_Release(IEnumConnections* This)
933 EnumCon *iface = (EnumCon*)This;
934 ULONG ret;
936 ret = InterlockedDecrement(&iface->refCount);
937 if (ret == 0)
938 HeapFree(GetProcessHeap(),0,This);
939 return ret;
942 static HRESULT WINAPI Enum_Next(
943 IEnumConnections* This,
944 ULONG cConnections,
945 LPCONNECTDATA rgcd,
946 ULONG *pcFetched)
948 EnumCon *iface = (EnumCon*)This;
950 if (cConnections > 0 && iface->idx < iface->pt->sinkCount)
952 rgcd->pUnk = iface->pt->sink[iface->idx];
953 IUnknown_AddRef(iface->pt->sink[iface->idx]);
954 rgcd->dwCookie=0xff;
955 if (pcFetched)
956 *pcFetched = 1;
957 iface->idx++;
958 return S_OK;
961 return E_FAIL;
964 static HRESULT WINAPI Enum_Skip(
965 IEnumConnections* This,
966 ULONG cConnections)
968 return E_FAIL;
971 static HRESULT WINAPI Enum_Reset(
972 IEnumConnections* This)
974 return E_FAIL;
977 static HRESULT WINAPI Enum_Clone(
978 IEnumConnections* This,
979 IEnumConnections **ppEnum)
981 return E_FAIL;
984 static const IEnumConnectionsVtbl enum_vtbl = {
986 Enum_QueryInterface,
987 Enum_AddRef,
988 Enum_Release,
989 Enum_Next,
990 Enum_Skip,
991 Enum_Reset,
992 Enum_Clone
995 static HRESULT WINAPI ConPt_QueryInterface(
996 IConnectionPoint* This,
997 REFIID riid,
998 void **ppvObject)
1000 *ppvObject = NULL;
1002 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IConnectionPoint))
1004 *ppvObject = This;
1007 if (*ppvObject)
1009 IUnknown_AddRef(This);
1010 return S_OK;
1013 trace("no interface\n");
1014 return E_NOINTERFACE;
1017 static ULONG WINAPI ConPt_AddRef(
1018 IConnectionPoint* This)
1020 ConPt *iface = (ConPt*)This;
1021 return InterlockedIncrement(&iface->refCount);
1024 static ULONG WINAPI ConPt_Release(
1025 IConnectionPoint* This)
1027 ConPt *iface = (ConPt*)This;
1028 ULONG ret;
1030 ret = InterlockedDecrement(&iface->refCount);
1031 if (ret == 0)
1033 if (iface->sinkCount > 0)
1035 int i;
1036 for (i = 0; i < iface->sinkCount; i++)
1038 if (iface->sink[i])
1039 IUnknown_Release(iface->sink[i]);
1041 HeapFree(GetProcessHeap(),0,iface->sink);
1043 HeapFree(GetProcessHeap(),0,This);
1045 return ret;
1048 static HRESULT WINAPI ConPt_GetConnectionInterface(
1049 IConnectionPoint* This,
1050 IID *pIID)
1052 static int i = 0;
1053 ConPt *iface = (ConPt*)This;
1054 if (i==0)
1056 i++;
1057 return E_FAIL;
1059 else
1060 memcpy(pIID,&iface->id,sizeof(GUID));
1061 return S_OK;
1064 static HRESULT WINAPI ConPt_GetConnectionPointContainer(
1065 IConnectionPoint* This,
1066 IConnectionPointContainer **ppCPC)
1068 ConPt *iface = (ConPt*)This;
1070 *ppCPC = (IConnectionPointContainer*)iface->container;
1071 return S_OK;
1074 static HRESULT WINAPI ConPt_Advise(
1075 IConnectionPoint* This,
1076 IUnknown *pUnkSink,
1077 DWORD *pdwCookie)
1079 ConPt *iface = (ConPt*)This;
1081 if (iface->sinkCount == 0)
1082 iface->sink = HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown*));
1083 else
1084 iface->sink = HeapReAlloc(GetProcessHeap(),0,iface->sink,sizeof(IUnknown*)*(iface->sinkCount+1));
1085 iface->sink[iface->sinkCount] = pUnkSink;
1086 IUnknown_AddRef(pUnkSink);
1087 iface->sinkCount++;
1088 *pdwCookie = iface->sinkCount;
1089 return S_OK;
1092 static HRESULT WINAPI ConPt_Unadvise(
1093 IConnectionPoint* This,
1094 DWORD dwCookie)
1096 ConPt *iface = (ConPt*)This;
1098 if (dwCookie > iface->sinkCount)
1099 return E_FAIL;
1100 else
1102 IUnknown_Release(iface->sink[dwCookie-1]);
1103 iface->sink[dwCookie-1] = NULL;
1105 return S_OK;
1108 static HRESULT WINAPI ConPt_EnumConnections(
1109 IConnectionPoint* This,
1110 IEnumConnections **ppEnum)
1112 EnumCon *ec;
1114 ec = HeapAlloc(GetProcessHeap(),0,sizeof(EnumCon));
1115 ec->vtbl = &enum_vtbl;
1116 ec->refCount = 1;
1117 ec->pt = (ConPt*)This;
1118 ec->idx = 0;
1119 *ppEnum = (IEnumConnections*)ec;
1121 return S_OK;
1124 static const IConnectionPointVtbl point_vtbl = {
1125 ConPt_QueryInterface,
1126 ConPt_AddRef,
1127 ConPt_Release,
1129 ConPt_GetConnectionInterface,
1130 ConPt_GetConnectionPointContainer,
1131 ConPt_Advise,
1132 ConPt_Unadvise,
1133 ConPt_EnumConnections
1136 static HRESULT WINAPI EnumPt_QueryInterface(
1137 IEnumConnectionPoints* This,
1138 REFIID riid,
1139 void **ppvObject)
1141 *ppvObject = NULL;
1143 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IEnumConnectionPoints))
1145 *ppvObject = This;
1148 if (*ppvObject)
1150 IUnknown_AddRef(This);
1151 return S_OK;
1154 trace("no interface\n");
1155 return E_NOINTERFACE;
1158 static ULONG WINAPI EnumPt_AddRef(IEnumConnectionPoints* This)
1160 EnumPt *iface = (EnumPt*)This;
1161 return InterlockedIncrement(&iface->refCount);
1164 static ULONG WINAPI EnumPt_Release(IEnumConnectionPoints* This)
1166 EnumPt *iface = (EnumPt*)This;
1167 ULONG ret;
1169 ret = InterlockedDecrement(&iface->refCount);
1170 if (ret == 0)
1171 HeapFree(GetProcessHeap(),0,This);
1172 return ret;
1175 static HRESULT WINAPI EnumPt_Next(
1176 IEnumConnectionPoints* This,
1177 ULONG cConnections,
1178 IConnectionPoint **rgcd,
1179 ULONG *pcFetched)
1181 EnumPt *iface = (EnumPt*)This;
1183 if (cConnections > 0 && iface->idx < iface->container->ptCount)
1185 *rgcd = iface->container->pt[iface->idx];
1186 IUnknown_AddRef(iface->container->pt[iface->idx]);
1187 if (pcFetched)
1188 *pcFetched = 1;
1189 iface->idx++;
1190 return S_OK;
1193 return E_FAIL;
1196 static HRESULT WINAPI EnumPt_Skip(
1197 IEnumConnectionPoints* This,
1198 ULONG cConnections)
1200 return E_FAIL;
1203 static HRESULT WINAPI EnumPt_Reset(
1204 IEnumConnectionPoints* This)
1206 return E_FAIL;
1209 static HRESULT WINAPI EnumPt_Clone(
1210 IEnumConnectionPoints* This,
1211 IEnumConnectionPoints **ppEnumPt)
1213 return E_FAIL;
1216 static const IEnumConnectionPointsVtbl enumpt_vtbl = {
1218 EnumPt_QueryInterface,
1219 EnumPt_AddRef,
1220 EnumPt_Release,
1221 EnumPt_Next,
1222 EnumPt_Skip,
1223 EnumPt_Reset,
1224 EnumPt_Clone
1227 static HRESULT WINAPI Contain_QueryInterface(
1228 IConnectionPointContainer* This,
1229 REFIID riid,
1230 void **ppvObject)
1232 *ppvObject = NULL;
1234 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IConnectionPointContainer))
1236 *ppvObject = This;
1239 if (*ppvObject)
1241 IUnknown_AddRef(This);
1242 return S_OK;
1245 trace("no interface\n");
1246 return E_NOINTERFACE;
1249 static ULONG WINAPI Contain_AddRef(
1250 IConnectionPointContainer* This)
1252 Contain *iface = (Contain*)This;
1253 return InterlockedIncrement(&iface->refCount);
1256 static ULONG WINAPI Contain_Release(
1257 IConnectionPointContainer* This)
1259 Contain *iface = (Contain*)This;
1260 ULONG ret;
1262 ret = InterlockedDecrement(&iface->refCount);
1263 if (ret == 0)
1265 if (iface->ptCount > 0)
1267 int i;
1268 for (i = 0; i < iface->ptCount; i++)
1269 IUnknown_Release(iface->pt[i]);
1270 HeapFree(GetProcessHeap(),0,iface->pt);
1272 HeapFree(GetProcessHeap(),0,This);
1274 return ret;
1277 static HRESULT WINAPI Contain_EnumConnectionPoints(
1278 IConnectionPointContainer* This,
1279 IEnumConnectionPoints **ppEnum)
1281 EnumPt *ec;
1283 ec = HeapAlloc(GetProcessHeap(),0,sizeof(EnumPt));
1284 ec->vtbl = &enumpt_vtbl;
1285 ec->refCount = 1;
1286 ec->idx= 0;
1287 ec->container = (Contain*)This;
1288 *ppEnum = (IEnumConnectionPoints*)ec;
1290 return S_OK;
1293 static HRESULT WINAPI Contain_FindConnectionPoint(
1294 IConnectionPointContainer* This,
1295 REFIID riid,
1296 IConnectionPoint **ppCP)
1298 Contain *iface = (Contain*)This;
1299 ConPt *pt;
1301 if (!IsEqualIID(riid, &IID_NULL) || iface->ptCount ==0)
1303 pt = HeapAlloc(GetProcessHeap(),0,sizeof(ConPt));
1304 pt->vtbl = &point_vtbl;
1305 pt->refCount = 1;
1306 pt->sinkCount = 0;
1307 pt->sink = NULL;
1308 pt->container = iface;
1309 pt->id = IID_IDispatch;
1311 if (iface->ptCount == 0)
1312 iface->pt =HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown*));
1313 else
1314 iface->pt = HeapReAlloc(GetProcessHeap(),0,iface->pt,sizeof(IUnknown*)*(iface->ptCount+1));
1315 iface->pt[iface->ptCount] = (IConnectionPoint*)pt;
1316 iface->ptCount++;
1318 *ppCP = (IConnectionPoint*)pt;
1320 else
1322 *ppCP = iface->pt[0];
1323 IUnknown_AddRef((IUnknown*)*ppCP);
1326 return S_OK;
1329 static const IConnectionPointContainerVtbl contain_vtbl = {
1330 Contain_QueryInterface,
1331 Contain_AddRef,
1332 Contain_Release,
1334 Contain_EnumConnectionPoints,
1335 Contain_FindConnectionPoint
1338 static void test_IConnectionPoint(void)
1340 HRESULT rc;
1341 ULONG ref;
1342 IConnectionPoint *point;
1343 Contain *container;
1344 Disp *dispatch;
1345 DWORD cookie = 0xffffffff;
1346 DISPPARAMS params;
1347 VARIANT vars[10];
1349 if (!pIConnectionPoint_SimpleInvoke || !pConnectToConnectionPoint)
1351 win_skip("IConnectionPoint Apis not present\n");
1352 return;
1355 container = HeapAlloc(GetProcessHeap(),0,sizeof(Contain));
1356 container->vtbl = &contain_vtbl;
1357 container->refCount = 1;
1358 container->ptCount = 0;
1359 container->pt = NULL;
1361 dispatch = HeapAlloc(GetProcessHeap(),0,sizeof(Disp));
1362 dispatch->vtbl = &disp_vtbl;
1363 dispatch->refCount = 1;
1365 rc = pConnectToConnectionPoint((IUnknown*)dispatch, &IID_NULL, TRUE, (IUnknown*)container, &cookie, &point);
1366 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
1367 ok(point != NULL, "returned ConnectionPoint is NULL\n");
1368 ok(cookie != 0xffffffff, "invalid cookie returned\n");
1370 rc = pIConnectionPoint_SimpleInvoke(point,0xa0,NULL);
1371 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
1373 if (pSHPackDispParams)
1375 memset(&params, 0xc0, sizeof(params));
1376 memset(vars, 0xc0, sizeof(vars));
1377 rc = pSHPackDispParams(&params, vars, 2, VT_I4, 0xdeadbeef, VT_BSTR, 0xdeadcafe);
1378 ok(rc == S_OK, "SHPackDispParams failed: %08x\n", rc);
1380 rc = pIConnectionPoint_SimpleInvoke(point,0xa1,&params);
1381 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
1383 else
1384 win_skip("pSHPackDispParams not present\n");
1386 rc = pConnectToConnectionPoint(NULL, &IID_NULL, FALSE, (IUnknown*)container, &cookie, NULL);
1387 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
1389 /* MSDN says this should be required but it crashs on XP
1390 IUnknown_Release(point);
1392 ref = IUnknown_Release((IUnknown*)container);
1393 ok(ref == 0, "leftover IConnectionPointContainer reference %i\n",ref);
1394 ref = IUnknown_Release((IUnknown*)dispatch);
1395 ok(ref == 0, "leftover IDispatch reference %i\n",ref);
1398 typedef struct _propbag
1400 const IPropertyBagVtbl *vtbl;
1401 LONG refCount;
1403 } PropBag;
1406 static HRESULT WINAPI Prop_QueryInterface(
1407 IPropertyBag* This,
1408 REFIID riid,
1409 void **ppvObject)
1411 *ppvObject = NULL;
1413 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IPropertyBag))
1415 *ppvObject = This;
1418 if (*ppvObject)
1420 IUnknown_AddRef(This);
1421 return S_OK;
1424 trace("no interface\n");
1425 return E_NOINTERFACE;
1428 static ULONG WINAPI Prop_AddRef(
1429 IPropertyBag* This)
1431 PropBag *iface = (PropBag*)This;
1432 return InterlockedIncrement(&iface->refCount);
1435 static ULONG WINAPI Prop_Release(
1436 IPropertyBag* This)
1438 PropBag *iface = (PropBag*)This;
1439 ULONG ret;
1441 ret = InterlockedDecrement(&iface->refCount);
1442 if (ret == 0)
1443 HeapFree(GetProcessHeap(),0,This);
1444 return ret;
1447 static HRESULT WINAPI Prop_Read(
1448 IPropertyBag* This,
1449 LPCOLESTR pszPropName,
1450 VARIANT *pVar,
1451 IErrorLog *pErrorLog)
1453 V_VT(pVar) = VT_BLOB|VT_BYREF;
1454 V_BYREF(pVar) = (LPVOID)0xdeadcafe;
1455 return S_OK;
1458 static HRESULT WINAPI Prop_Write(
1459 IPropertyBag* This,
1460 LPCOLESTR pszPropName,
1461 VARIANT *pVar)
1463 return S_OK;
1467 static const IPropertyBagVtbl prop_vtbl = {
1468 Prop_QueryInterface,
1469 Prop_AddRef,
1470 Prop_Release,
1472 Prop_Read,
1473 Prop_Write
1476 static void test_SHPropertyBag_ReadLONG(void)
1478 PropBag *pb;
1479 HRESULT rc;
1480 LONG out;
1481 static const WCHAR szName1[] = {'n','a','m','e','1',0};
1483 if (!pSHPropertyBag_ReadLONG)
1485 win_skip("SHPropertyBag_ReadLONG not present\n");
1486 return;
1489 pb = HeapAlloc(GetProcessHeap(),0,sizeof(PropBag));
1490 pb->refCount = 1;
1491 pb->vtbl = &prop_vtbl;
1493 out = 0xfeedface;
1494 rc = pSHPropertyBag_ReadLONG(NULL, szName1, &out);
1495 ok(rc == E_INVALIDARG || broken(rc == 0), "incorrect return %x\n",rc);
1496 ok(out == 0xfeedface, "value should not have changed\n");
1497 rc = pSHPropertyBag_ReadLONG((IPropertyBag*)pb, NULL, &out);
1498 ok(rc == E_INVALIDARG || broken(rc == 0) || broken(rc == 1), "incorrect return %x\n",rc);
1499 ok(out == 0xfeedface, "value should not have changed\n");
1500 rc = pSHPropertyBag_ReadLONG((IPropertyBag*)pb, szName1, NULL);
1501 ok(rc == E_INVALIDARG || broken(rc == 0) || broken(rc == 1), "incorrect return %x\n",rc);
1502 ok(out == 0xfeedface, "value should not have changed\n");
1503 rc = pSHPropertyBag_ReadLONG((IPropertyBag*)pb, szName1, &out);
1504 ok(rc == DISP_E_BADVARTYPE || broken(rc == 0) || broken(rc == 1), "incorrect return %x\n",rc);
1505 ok(out == 0xfeedface || broken(out == 0xfeedfa00), "value should not have changed %x\n",out);
1506 IUnknown_Release((IUnknown*)pb);
1511 static void test_SHSetWindowBits(void)
1513 HWND hwnd;
1514 DWORD style, styleold;
1515 WNDCLASSA clsA;
1517 if(!pSHSetWindowBits)
1519 win_skip("SHSetWindowBits is not available\n");
1520 return;
1523 clsA.style = 0;
1524 clsA.lpfnWndProc = DefWindowProcA;
1525 clsA.cbClsExtra = 0;
1526 clsA.cbWndExtra = 0;
1527 clsA.hInstance = GetModuleHandleA(NULL);
1528 clsA.hIcon = 0;
1529 clsA.hCursor = LoadCursorA(0, IDC_ARROW);
1530 clsA.hbrBackground = NULL;
1531 clsA.lpszMenuName = NULL;
1532 clsA.lpszClassName = "Shlwapi test class";
1533 RegisterClassA(&clsA);
1535 hwnd = CreateWindowA("Shlwapi test class", "Test", WS_VISIBLE, 0, 0, 100, 100,
1536 NULL, NULL, GetModuleHandle(NULL), 0);
1537 ok(IsWindow(hwnd), "failed to create window\n");
1539 /* null window */
1540 SetLastError(0xdeadbeef);
1541 style = pSHSetWindowBits(NULL, GWL_STYLE, 0, 0);
1542 ok(style == 0, "expected 0 retval, got %d\n", style);
1543 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE ||
1544 broken(GetLastError() == 0xdeadbeef), /* Win9x/WinMe */
1545 "expected ERROR_INVALID_WINDOW_HANDLE, got %d\n", GetLastError());
1547 /* zero mask, zero flags */
1548 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1549 style = pSHSetWindowBits(hwnd, GWL_STYLE, 0, 0);
1550 ok(styleold == style, "expected old style\n");
1551 ok(styleold == GetWindowLongA(hwnd, GWL_STYLE), "expected to keep old style\n");
1553 /* test mask */
1554 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1555 ok(styleold & WS_VISIBLE, "expected WS_VISIBLE\n");
1556 style = pSHSetWindowBits(hwnd, GWL_STYLE, WS_VISIBLE, 0);
1558 ok(style == styleold, "expected previous style, got %x\n", style);
1559 ok((GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE) == 0, "expected updated style\n");
1561 /* test mask, unset style bit used */
1562 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1563 style = pSHSetWindowBits(hwnd, GWL_STYLE, WS_VISIBLE, 0);
1564 ok(style == styleold, "expected previous style, got %x\n", style);
1565 ok(styleold == GetWindowLongA(hwnd, GWL_STYLE), "expected to keep old style\n");
1567 /* set back with flags */
1568 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1569 style = pSHSetWindowBits(hwnd, GWL_STYLE, WS_VISIBLE, WS_VISIBLE);
1570 ok(style == styleold, "expected previous style, got %x\n", style);
1571 ok(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE, "expected updated style\n");
1573 /* reset and try to set without a mask */
1574 pSHSetWindowBits(hwnd, GWL_STYLE, WS_VISIBLE, 0);
1575 ok((GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE) == 0, "expected updated style\n");
1576 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1577 style = pSHSetWindowBits(hwnd, GWL_STYLE, 0, WS_VISIBLE);
1578 ok(style == styleold, "expected previous style, got %x\n", style);
1579 ok((GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE) == 0, "expected updated style\n");
1581 DestroyWindow(hwnd);
1583 UnregisterClassA("Shlwapi test class", GetModuleHandleA(NULL));
1586 static void test_SHFormatDateTimeA(void)
1588 FILETIME UNALIGNED filetime;
1589 CHAR buff[100], buff2[100], buff3[100];
1590 SYSTEMTIME st;
1591 DWORD flags;
1592 INT ret;
1594 if(!pSHFormatDateTimeA)
1596 win_skip("pSHFormatDateTimeA isn't available\n");
1597 return;
1600 if (0)
1602 /* crashes on native */
1603 ret = pSHFormatDateTimeA(NULL, NULL, NULL, 0);
1606 GetLocalTime(&st);
1607 SystemTimeToFileTime(&st, &filetime);
1608 /* SHFormatDateTime expects input as utc */
1609 LocalFileTimeToFileTime(&filetime, &filetime);
1611 /* no way to get required buffer length here */
1612 SetLastError(0xdeadbeef);
1613 ret = pSHFormatDateTimeA(&filetime, NULL, NULL, 0);
1614 ok(ret == 0, "got %d\n", ret);
1615 ok(GetLastError() == 0xdeadbeef || broken(GetLastError() == ERROR_SUCCESS /* Win7 */),
1616 "expected 0xdeadbeef, got %d\n", GetLastError());
1618 SetLastError(0xdeadbeef);
1619 buff[0] = 'a'; buff[1] = 0;
1620 ret = pSHFormatDateTimeA(&filetime, NULL, buff, 0);
1621 ok(ret == 0, "got %d\n", ret);
1622 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1623 ok(buff[0] == 'a', "expected same string, got %s\n", buff);
1625 /* flags needs to have FDTF_NOAUTOREADINGORDER for these tests to succeed on Vista+ */
1627 /* all combinations documented as invalid succeeded */
1628 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTTIME | FDTF_LONGTIME;
1629 SetLastError(0xdeadbeef);
1630 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1631 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1632 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1634 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTDATE | FDTF_LONGDATE;
1635 SetLastError(0xdeadbeef);
1636 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1637 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1638 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1640 flags = FDTF_SHORTDATE | FDTF_LTRDATE | FDTF_RTLDATE;
1641 SetLastError(0xdeadbeef);
1642 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1643 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1644 ok(GetLastError() == 0xdeadbeef ||
1645 broken(GetLastError() == ERROR_INVALID_FLAGS), /* Win9x/WinMe */
1646 "expected 0xdeadbeef, got %d\n", GetLastError());
1648 /* now check returned strings */
1649 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTTIME;
1650 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1651 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1652 ret = GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff2, sizeof(buff2));
1653 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1654 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1656 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGTIME;
1657 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1658 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1659 ret = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2));
1660 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1661 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1663 /* both time flags */
1664 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGTIME | FDTF_SHORTTIME;
1665 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1666 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1667 ret = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2));
1668 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1669 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1671 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTDATE;
1672 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1673 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1674 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2));
1675 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1676 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1678 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGDATE;
1679 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1680 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1681 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
1682 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1683 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1685 /* both date flags */
1686 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGDATE | FDTF_SHORTDATE;
1687 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1688 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1689 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
1690 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1691 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1693 /* various combinations of date/time flags */
1694 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGDATE | FDTF_SHORTTIME;
1695 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1696 ok(ret == lstrlenA(buff)+1, "got %d, length %d\n", ret, lstrlenA(buff)+1);
1697 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
1698 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1699 strcat(buff2, ", ");
1700 ret = GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3));
1701 ok(ret == lstrlenA(buff3)+1, "got %d\n", ret);
1702 strcat(buff2, buff3);
1703 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1705 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGDATE | FDTF_LONGTIME;
1706 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1707 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1708 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
1709 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1710 strcat(buff2, ", ");
1711 ret = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3));
1712 ok(ret == lstrlenA(buff3)+1, "got %d\n", ret);
1713 strcat(buff2, buff3);
1714 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1716 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTDATE | FDTF_SHORTTIME;
1717 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1718 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1719 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2));
1720 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1721 strcat(buff2, " ");
1722 ret = GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3));
1723 ok(ret == lstrlenA(buff3)+1, "got %d\n", ret);
1724 strcat(buff2, buff3);
1725 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1727 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTDATE | FDTF_LONGTIME;
1728 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1729 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1730 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2));
1731 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1732 strcat(buff2, " ");
1733 ret = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3));
1734 ok(ret == lstrlenA(buff3)+1, "got %d\n", ret);
1735 strcat(buff2, buff3);
1736 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1739 static void test_SHFormatDateTimeW(void)
1741 FILETIME UNALIGNED filetime;
1742 WCHAR buff[100], buff2[100], buff3[100];
1743 SYSTEMTIME st;
1744 DWORD flags;
1745 INT ret;
1746 static const WCHAR spaceW[] = {' ',0};
1747 static const WCHAR commaW[] = {',',' ',0};
1749 if(!pSHFormatDateTimeW)
1751 win_skip("pSHFormatDateTimeW isn't available\n");
1752 return;
1755 if (0)
1757 /* crashes on native */
1758 ret = pSHFormatDateTimeW(NULL, NULL, NULL, 0);
1761 GetLocalTime(&st);
1762 SystemTimeToFileTime(&st, &filetime);
1763 /* SHFormatDateTime expects input as utc */
1764 LocalFileTimeToFileTime(&filetime, &filetime);
1766 /* no way to get required buffer length here */
1767 SetLastError(0xdeadbeef);
1768 ret = pSHFormatDateTimeW(&filetime, NULL, NULL, 0);
1769 ok(ret == 0, "got %d\n", ret);
1770 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1772 SetLastError(0xdeadbeef);
1773 buff[0] = 'a'; buff[1] = 0;
1774 ret = pSHFormatDateTimeW(&filetime, NULL, buff, 0);
1775 ok(ret == 0, "got %d\n", ret);
1776 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1777 ok(buff[0] == 'a', "expected same string\n");
1779 /* all combinations documented as invalid succeeded */
1780 flags = FDTF_SHORTTIME | FDTF_LONGTIME;
1781 SetLastError(0xdeadbeef);
1782 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1783 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1784 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1786 flags = FDTF_SHORTDATE | FDTF_LONGDATE;
1787 SetLastError(0xdeadbeef);
1788 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1789 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1790 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1792 flags = FDTF_SHORTDATE | FDTF_LTRDATE | FDTF_RTLDATE;
1793 SetLastError(0xdeadbeef);
1794 buff[0] = 0; /* NT4 doesn't clear the buffer on failure */
1795 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1796 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1797 ok(GetLastError() == 0xdeadbeef ||
1798 broken(GetLastError() == ERROR_INVALID_FLAGS), /* Win9x/WinMe/NT4 */
1799 "expected 0xdeadbeef, got %d\n", GetLastError());
1801 /* now check returned strings */
1802 flags = FDTF_SHORTTIME;
1803 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1804 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1805 SetLastError(0xdeadbeef);
1806 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1807 if (ret == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1809 win_skip("Needed W-functions are not implemented\n");
1810 return;
1812 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1813 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1815 flags = FDTF_LONGTIME;
1816 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1817 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1818 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1819 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1820 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1822 /* both time flags */
1823 flags = FDTF_LONGTIME | FDTF_SHORTTIME;
1824 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1825 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1826 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1827 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1828 ok(lstrcmpW(buff, buff2) == 0, "expected equal string\n");
1830 flags = FDTF_SHORTDATE;
1831 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1832 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1833 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1834 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1835 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1837 flags = FDTF_LONGDATE;
1838 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1839 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1840 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1841 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1842 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1844 /* both date flags */
1845 flags = FDTF_LONGDATE | FDTF_SHORTDATE;
1846 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1847 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1848 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1849 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1850 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1852 /* various combinations of date/time flags */
1853 flags = FDTF_LONGDATE | FDTF_SHORTTIME;
1854 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1855 ok(ret == lstrlenW(buff)+1, "got %d, length %d\n", ret, lstrlenW(buff)+1);
1856 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1857 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1858 lstrcatW(buff2, commaW);
1859 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
1860 ok(ret == lstrlenW(buff3)+1, "got %d\n", ret);
1861 lstrcatW(buff2, buff3);
1862 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1864 flags = FDTF_LONGDATE | FDTF_LONGTIME;
1865 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1866 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1867 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1868 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1869 lstrcatW(buff2, commaW);
1870 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
1871 ok(ret == lstrlenW(buff3)+1, "got %d\n", ret);
1872 lstrcatW(buff2, buff3);
1873 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1875 flags = FDTF_SHORTDATE | FDTF_SHORTTIME;
1876 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1877 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1878 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1879 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1880 lstrcatW(buff2, spaceW);
1881 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
1882 ok(ret == lstrlenW(buff3)+1, "got %d\n", ret);
1883 lstrcatW(buff2, buff3);
1884 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1886 flags = FDTF_SHORTDATE | FDTF_LONGTIME;
1887 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1888 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1889 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1890 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1891 lstrcatW(buff2, spaceW);
1892 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
1893 ok(ret == lstrlenW(buff3)+1, "got %d\n", ret);
1894 lstrcatW(buff2, buff3);
1895 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1898 static void test_SHGetObjectCompatFlags(void)
1900 struct compat_value {
1901 CHAR nameA[30];
1902 DWORD value;
1905 struct compat_value values[] = {
1906 { "OTNEEDSSFCACHE", 0x1 },
1907 { "NO_WEBVIEW", 0x2 },
1908 { "UNBINDABLE", 0x4 },
1909 { "PINDLL", 0x8 },
1910 { "NEEDSFILESYSANCESTOR", 0x10 },
1911 { "NOTAFILESYSTEM", 0x20 },
1912 { "CTXMENU_NOVERBS", 0x40 },
1913 { "CTXMENU_LIMITEDQI", 0x80 },
1914 { "COCREATESHELLFOLDERONLY", 0x100 },
1915 { "NEEDSSTORAGEANCESTOR", 0x200 },
1916 { "NOLEGACYWEBVIEW", 0x400 },
1917 { "CTXMENU_XPQCMFLAGS", 0x1000 },
1918 { "NOIPROPERTYSTORE", 0x2000 }
1921 static const char compat_path[] = "Software\\Microsoft\\Windows\\CurrentVersion\\ShellCompatibility\\Objects";
1922 void *pColorAdjustLuma = GetProcAddress(hShlwapi, "ColorAdjustLuma");
1923 CHAR keyA[39]; /* {CLSID} */
1924 HKEY root;
1925 DWORD ret;
1926 int i;
1928 if (!pSHGetObjectCompatFlags)
1930 win_skip("SHGetObjectCompatFlags isn't available\n");
1931 return;
1934 if (pColorAdjustLuma && pColorAdjustLuma == pSHGetObjectCompatFlags) /* win2k */
1936 win_skip("Skipping SHGetObjectCompatFlags, same ordinal used for ColorAdjustLuma\n");
1937 return;
1940 /* null args */
1941 ret = pSHGetObjectCompatFlags(NULL, NULL);
1942 ok(ret == 0, "got %d\n", ret);
1944 ret = RegOpenKeyA(HKEY_LOCAL_MACHINE, compat_path, &root);
1945 if (ret != ERROR_SUCCESS)
1947 skip("No compatibility class data found\n");
1948 return;
1951 for (i = 0; RegEnumKeyA(root, i, keyA, sizeof(keyA)) == ERROR_SUCCESS; i++)
1953 HKEY clsid_key;
1955 if (RegOpenKeyA(root, keyA, &clsid_key) == ERROR_SUCCESS)
1957 CHAR valueA[30];
1958 DWORD expected = 0, got, length = sizeof(valueA);
1959 CLSID clsid;
1960 int v;
1962 for (v = 0; RegEnumValueA(clsid_key, v, valueA, &length, NULL, NULL, NULL, NULL) == ERROR_SUCCESS; v++)
1964 int j;
1966 for (j = 0; j < sizeof(values)/sizeof(struct compat_value); j++)
1967 if (lstrcmpA(values[j].nameA, valueA) == 0)
1969 expected |= values[j].value;
1970 break;
1973 length = sizeof(valueA);
1976 pGUIDFromStringA(keyA, &clsid);
1977 got = pSHGetObjectCompatFlags(NULL, &clsid);
1978 ok(got == expected, "got 0x%08x, expected 0x%08x. Key %s\n", got, expected, keyA);
1980 RegCloseKey(clsid_key);
1984 RegCloseKey(root);
1987 typedef struct {
1988 const IOleCommandTargetVtbl *lpVtbl;
1989 LONG ref;
1990 } IOleCommandTargetImpl;
1992 static const IOleCommandTargetVtbl IOleCommandTargetImpl_Vtbl;
1994 static IOleCommandTarget* IOleCommandTargetImpl_Construct(void)
1996 IOleCommandTargetImpl *obj;
1998 obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*obj));
1999 obj->lpVtbl = &IOleCommandTargetImpl_Vtbl;
2000 obj->ref = 1;
2002 return (IOleCommandTarget*)obj;
2005 static HRESULT WINAPI IOleCommandTargetImpl_QueryInterface(IOleCommandTarget *iface, REFIID riid, void **ppvObj)
2007 IOleCommandTargetImpl *This = (IOleCommandTargetImpl *)iface;
2009 if (IsEqualIID(riid, &IID_IUnknown) ||
2010 IsEqualIID(riid, &IID_IOleCommandTarget))
2012 *ppvObj = This;
2015 if(*ppvObj)
2017 IUnknown_AddRef(iface);
2018 return S_OK;
2021 return E_NOINTERFACE;
2024 static ULONG WINAPI IOleCommandTargetImpl_AddRef(IOleCommandTarget *iface)
2026 IOleCommandTargetImpl *This = (IOleCommandTargetImpl *)iface;
2027 return InterlockedIncrement(&This->ref);
2030 static ULONG WINAPI IOleCommandTargetImpl_Release(IOleCommandTarget *iface)
2032 IOleCommandTargetImpl *This = (IOleCommandTargetImpl *)iface;
2033 ULONG ref = InterlockedDecrement(&This->ref);
2035 if (!ref)
2037 HeapFree(GetProcessHeap(), 0, This);
2038 return 0;
2040 return ref;
2043 static HRESULT WINAPI IOleCommandTargetImpl_QueryStatus(
2044 IOleCommandTarget *iface, const GUID *group, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText)
2046 return E_NOTIMPL;
2049 static HRESULT WINAPI IOleCommandTargetImpl_Exec(
2050 IOleCommandTarget *iface,
2051 const GUID *CmdGroup,
2052 DWORD nCmdID,
2053 DWORD nCmdexecopt,
2054 VARIANT *pvaIn,
2055 VARIANT *pvaOut)
2057 add_call(&trace_got, 3, CmdGroup, (void*)(DWORD_PTR)nCmdID, (void*)(DWORD_PTR)nCmdexecopt, pvaIn, pvaOut);
2058 return S_OK;
2061 static const IOleCommandTargetVtbl IOleCommandTargetImpl_Vtbl =
2063 IOleCommandTargetImpl_QueryInterface,
2064 IOleCommandTargetImpl_AddRef,
2065 IOleCommandTargetImpl_Release,
2066 IOleCommandTargetImpl_QueryStatus,
2067 IOleCommandTargetImpl_Exec
2070 typedef struct {
2071 const IServiceProviderVtbl *lpVtbl;
2072 LONG ref;
2073 } IServiceProviderImpl;
2075 typedef struct {
2076 const IProfferServiceVtbl *lpVtbl;
2077 LONG ref;
2078 } IProfferServiceImpl;
2081 static const IServiceProviderVtbl IServiceProviderImpl_Vtbl;
2082 static const IProfferServiceVtbl IProfferServiceImpl_Vtbl;
2084 static IServiceProvider* IServiceProviderImpl_Construct(void)
2086 IServiceProviderImpl *obj;
2088 obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*obj));
2089 obj->lpVtbl = &IServiceProviderImpl_Vtbl;
2090 obj->ref = 1;
2092 return (IServiceProvider*)obj;
2095 static IProfferService* IProfferServiceImpl_Construct(void)
2097 IProfferServiceImpl *obj;
2099 obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*obj));
2100 obj->lpVtbl = &IProfferServiceImpl_Vtbl;
2101 obj->ref = 1;
2103 return (IProfferService*)obj;
2106 static HRESULT WINAPI IServiceProviderImpl_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppvObj)
2108 IServiceProviderImpl *This = (IServiceProviderImpl *)iface;
2110 if (IsEqualIID(riid, &IID_IUnknown) ||
2111 IsEqualIID(riid, &IID_IServiceProvider))
2113 *ppvObj = This;
2116 if(*ppvObj)
2118 IUnknown_AddRef(iface);
2119 /* native uses redefined IID_IServiceProvider symbol, so we can't compare pointers */
2120 if (IsEqualIID(riid, &IID_IServiceProvider))
2121 add_call(&trace_got, 1, iface, &IID_IServiceProvider, 0, 0, 0);
2122 return S_OK;
2125 return E_NOINTERFACE;
2128 static ULONG WINAPI IServiceProviderImpl_AddRef(IServiceProvider *iface)
2130 IServiceProviderImpl *This = (IServiceProviderImpl *)iface;
2131 return InterlockedIncrement(&This->ref);
2134 static ULONG WINAPI IServiceProviderImpl_Release(IServiceProvider *iface)
2136 IServiceProviderImpl *This = (IServiceProviderImpl *)iface;
2137 ULONG ref = InterlockedDecrement(&This->ref);
2139 if (!ref)
2141 HeapFree(GetProcessHeap(), 0, This);
2142 return 0;
2144 return ref;
2147 static HRESULT WINAPI IServiceProviderImpl_QueryService(
2148 IServiceProvider *iface, REFGUID service, REFIID riid, void **ppv)
2150 /* native uses redefined pointer for IID_IOleCommandTarget, not one from uuid.lib */
2151 if (IsEqualIID(riid, &IID_IOleCommandTarget))
2153 add_call(&trace_got, 2, iface, service, &IID_IOleCommandTarget, 0, 0);
2154 *ppv = IOleCommandTargetImpl_Construct();
2156 if (IsEqualIID(riid, &IID_IProfferService))
2158 if (IsEqualIID(service, &IID_IProfferService))
2159 add_call(&trace_got, 2, &IID_IProfferService, &IID_IProfferService, 0, 0, 0);
2160 *ppv = IProfferServiceImpl_Construct();
2162 return S_OK;
2165 static const IServiceProviderVtbl IServiceProviderImpl_Vtbl =
2167 IServiceProviderImpl_QueryInterface,
2168 IServiceProviderImpl_AddRef,
2169 IServiceProviderImpl_Release,
2170 IServiceProviderImpl_QueryService
2173 static void test_IUnknown_QueryServiceExec(void)
2175 IServiceProvider *provider = IServiceProviderImpl_Construct();
2176 static const GUID dummy_serviceid = { 0xdeadbeef };
2177 static const GUID dummy_groupid = { 0xbeefbeef };
2178 call_trace_t trace_expected;
2179 HRESULT hr;
2181 /* on <=W2K platforms same ordinal used for another export with different
2182 prototype, so skipping using this indirect condition */
2183 if (is_win2k_and_lower)
2185 win_skip("IUnknown_QueryServiceExec is not available\n");
2186 return;
2189 /* null source pointer */
2190 hr = pIUnknown_QueryServiceExec(NULL, &dummy_serviceid, &dummy_groupid, 0, 0, 0, 0);
2191 ok(hr == E_FAIL, "got 0x%08x\n", hr);
2193 /* expected trace:
2194 IUnknown_QueryServiceExec( ptr1, serviceid, groupid, arg1, arg2, arg3, arg4);
2195 -> IUnknown_QueryInterface( ptr1, &IID_IServiceProvider, &prov );
2196 -> IServiceProvider_QueryService( prov, serviceid, &IID_IOleCommandTarget, &obj );
2197 -> IOleCommandTarget_Exec( obj, groupid, arg1, arg2, arg3, arg4 );
2199 init_call_trace(&trace_expected);
2201 add_call(&trace_expected, 1, provider, &IID_IServiceProvider, 0, 0, 0);
2202 add_call(&trace_expected, 2, provider, &dummy_serviceid, &IID_IOleCommandTarget, 0, 0);
2203 add_call(&trace_expected, 3, &dummy_groupid, (void*)0x1, (void*)0x2, (void*)0x3, (void*)0x4);
2205 init_call_trace(&trace_got);
2206 hr = pIUnknown_QueryServiceExec((IUnknown*)provider, &dummy_serviceid, &dummy_groupid, 0x1, 0x2, (void*)0x3, (void*)0x4);
2207 ok(hr == S_OK, "got 0x%08x\n", hr);
2209 ok_trace(&trace_expected, &trace_got);
2211 free_call_trace(&trace_expected);
2212 free_call_trace(&trace_got);
2214 IServiceProvider_Release(provider);
2218 static HRESULT WINAPI IProfferServiceImpl_QueryInterface(IProfferService *iface, REFIID riid, void **ppvObj)
2220 IProfferServiceImpl *This = (IProfferServiceImpl *)iface;
2222 if (IsEqualIID(riid, &IID_IUnknown) ||
2223 IsEqualIID(riid, &IID_IProfferService))
2225 *ppvObj = This;
2227 else if (IsEqualIID(riid, &IID_IServiceProvider))
2229 *ppvObj = IServiceProviderImpl_Construct();
2230 add_call(&trace_got, 1, iface, &IID_IServiceProvider, 0, 0, 0);
2231 return S_OK;
2234 if(*ppvObj)
2236 IUnknown_AddRef(iface);
2237 return S_OK;
2240 return E_NOINTERFACE;
2243 static ULONG WINAPI IProfferServiceImpl_AddRef(IProfferService *iface)
2245 IProfferServiceImpl *This = (IProfferServiceImpl *)iface;
2246 return InterlockedIncrement(&This->ref);
2249 static ULONG WINAPI IProfferServiceImpl_Release(IProfferService *iface)
2251 IProfferServiceImpl *This = (IProfferServiceImpl *)iface;
2252 ULONG ref = InterlockedDecrement(&This->ref);
2254 if (!ref)
2256 HeapFree(GetProcessHeap(), 0, This);
2257 return 0;
2259 return ref;
2262 static HRESULT WINAPI IProfferServiceImpl_ProfferService(IProfferService *iface,
2263 REFGUID service, IServiceProvider *pService, DWORD *pCookie)
2265 add_call(&trace_got, 3, service, pService, pCookie, 0, 0);
2266 return S_OK;
2269 static HRESULT WINAPI IProfferServiceImpl_RevokeService(IProfferService *iface, DWORD cookie)
2271 add_call(&trace_got, 4, (void*)(DWORD_PTR)cookie, 0, 0, 0, 0);
2272 return S_OK;
2275 static const IProfferServiceVtbl IProfferServiceImpl_Vtbl =
2277 IProfferServiceImpl_QueryInterface,
2278 IProfferServiceImpl_AddRef,
2279 IProfferServiceImpl_Release,
2280 IProfferServiceImpl_ProfferService,
2281 IProfferServiceImpl_RevokeService
2284 static void test_IUnknown_ProfferService(void)
2286 IServiceProvider *provider = IServiceProviderImpl_Construct();
2287 IProfferService *proff = IProfferServiceImpl_Construct();
2288 static const GUID dummy_serviceid = { 0xdeadbeef };
2289 call_trace_t trace_expected;
2290 HRESULT hr;
2291 DWORD cookie;
2293 /* on <=W2K platforms same ordinal used for another export with different
2294 prototype, so skipping using this indirect condition */
2295 if (is_win2k_and_lower)
2297 win_skip("IUnknown_ProfferService is not available\n");
2298 return;
2301 /* null source pointer */
2302 hr = pIUnknown_ProfferService(NULL, &dummy_serviceid, 0, 0);
2303 ok(hr == E_FAIL, "got 0x%08x\n", hr);
2305 /* expected trace:
2306 IUnknown_ProfferService( ptr1, serviceid, arg1, arg2);
2307 -> IUnknown_QueryInterface( ptr1, &IID_IServiceProvider, &provider );
2308 -> IServiceProvider_QueryService( provider, &IID_IProfferService, &IID_IProfferService, &proffer );
2310 if (service pointer not null):
2311 -> IProfferService_ProfferService( proffer, serviceid, arg1, arg2 );
2312 else
2313 -> IProfferService_RevokeService( proffer, *arg2 );
2315 init_call_trace(&trace_expected);
2317 add_call(&trace_expected, 1, proff, &IID_IServiceProvider, 0, 0, 0);
2318 add_call(&trace_expected, 2, &IID_IProfferService, &IID_IProfferService, 0, 0, 0);
2319 add_call(&trace_expected, 3, &dummy_serviceid, provider, &cookie, 0, 0);
2321 init_call_trace(&trace_got);
2322 hr = pIUnknown_ProfferService((IUnknown*)proff, &dummy_serviceid, provider, &cookie);
2323 ok(hr == S_OK, "got 0x%08x\n", hr);
2325 ok_trace(&trace_expected, &trace_got);
2326 free_call_trace(&trace_got);
2327 free_call_trace(&trace_expected);
2329 /* same with ::Revoke path */
2330 init_call_trace(&trace_expected);
2332 add_call(&trace_expected, 1, proff, &IID_IServiceProvider, 0, 0, 0);
2333 add_call(&trace_expected, 2, &IID_IProfferService, &IID_IProfferService, 0, 0, 0);
2334 add_call(&trace_expected, 4, (void*)(DWORD_PTR)cookie, 0, 0, 0, 0);
2336 init_call_trace(&trace_got);
2337 hr = pIUnknown_ProfferService((IUnknown*)proff, &dummy_serviceid, 0, &cookie);
2338 ok(hr == S_OK, "got 0x%08x\n", hr);
2339 ok_trace(&trace_expected, &trace_got);
2340 free_call_trace(&trace_got);
2341 free_call_trace(&trace_expected);
2343 IServiceProvider_Release(provider);
2344 IProfferService_Release(proff);
2347 static void test_SHCreateWorkerWindowA(void)
2349 WNDCLASSA cliA;
2350 char classA[20];
2351 HWND hwnd;
2352 LONG_PTR ret;
2353 BOOL res;
2355 if (is_win2k_and_lower)
2357 win_skip("SHCreateWorkerWindowA not available\n");
2358 return;
2361 hwnd = pSHCreateWorkerWindowA(0, NULL, 0, 0, 0, 0);
2362 ok(hwnd != 0, "expected window\n");
2364 GetClassName(hwnd, classA, 20);
2365 ok(lstrcmpA(classA, "WorkerA") == 0, "expected WorkerA class, got %s\n", classA);
2367 ret = GetWindowLongPtrA(hwnd, 0);
2368 ok(ret == 0, "got %ld\n", ret);
2370 /* class info */
2371 memset(&cliA, 0, sizeof(cliA));
2372 res = GetClassInfoA(GetModuleHandle("shlwapi.dll"), "WorkerA", &cliA);
2373 ok(res, "failed to get class info\n");
2374 ok(cliA.style == 0, "got 0x%08x\n", cliA.style);
2375 ok(cliA.cbClsExtra == 0, "got %d\n", cliA.cbClsExtra);
2376 ok(cliA.cbWndExtra == sizeof(LONG_PTR), "got %d\n", cliA.cbWndExtra);
2377 ok(cliA.lpszMenuName == 0, "got %s\n", cliA.lpszMenuName);
2379 DestroyWindow(hwnd);
2381 /* set extra bytes */
2382 hwnd = pSHCreateWorkerWindowA(0, NULL, 0, 0, 0, 0xdeadbeef);
2383 ok(hwnd != 0, "expected window\n");
2385 GetClassName(hwnd, classA, 20);
2386 ok(lstrcmpA(classA, "WorkerA") == 0, "expected WorkerA class, got %s\n", classA);
2388 ret = GetWindowLongPtrA(hwnd, 0);
2389 ok(ret == 0xdeadbeef, "got %ld\n", ret);
2391 /* test exstyle */
2392 ret = GetWindowLongA(hwnd, GWL_EXSTYLE);
2393 ok(ret == WS_EX_WINDOWEDGE ||
2394 ret == (WS_EX_WINDOWEDGE|WS_EX_LAYOUTRTL) /* systems with RTL locale */, "0x%08lx\n", ret);
2396 DestroyWindow(hwnd);
2398 hwnd = pSHCreateWorkerWindowA(0, NULL, WS_EX_TOOLWINDOW, 0, 0, 0);
2399 ret = GetWindowLongA(hwnd, GWL_EXSTYLE);
2400 ok(ret == (WS_EX_WINDOWEDGE|WS_EX_TOOLWINDOW) ||
2401 ret == (WS_EX_WINDOWEDGE|WS_EX_TOOLWINDOW|WS_EX_LAYOUTRTL) /* systems with RTL locale */, "0x%08lx\n", ret);
2402 DestroyWindow(hwnd);
2405 static HRESULT WINAPI SF_QueryInterface(IShellFolder *iface,
2406 REFIID riid, void **ppv)
2408 /* SHIShellFolder_EnumObjects doesn't QI the object for IShellFolder */
2409 ok(!IsEqualGUID(&IID_IShellFolder, riid),
2410 "Unexpected QI for IShellFolder\n");
2411 return E_NOINTERFACE;
2414 static ULONG WINAPI SF_AddRef(IShellFolder *iface)
2416 return 2;
2419 static ULONG WINAPI SF_Release(IShellFolder *iface)
2421 return 1;
2424 static HRESULT WINAPI SF_ParseDisplayName(IShellFolder *iface,
2425 HWND owner, LPBC reserved, LPOLESTR displayName, ULONG *eaten,
2426 LPITEMIDLIST *idl, ULONG *attr)
2428 ok(0, "Didn't expect ParseDisplayName\n");
2429 return E_NOTIMPL;
2432 static HRESULT WINAPI SF_EnumObjects(IShellFolder *iface,
2433 HWND owner, SHCONTF flags, IEnumIDList **enm)
2435 *enm = (IEnumIDList*)0xcafebabe;
2436 return S_OK;
2439 static HRESULT WINAPI SF_BindToObject(IShellFolder *iface,
2440 LPCITEMIDLIST idl, LPBC reserved, REFIID riid, void **obj)
2442 ok(0, "Didn't expect BindToObject\n");
2443 return E_NOTIMPL;
2446 static HRESULT WINAPI SF_BindToStorage(IShellFolder *iface,
2447 LPCITEMIDLIST idl, LPBC reserved, REFIID riid, void **obj)
2449 ok(0, "Didn't expect BindToStorage\n");
2450 return E_NOTIMPL;
2453 static HRESULT WINAPI SF_CompareIDs(IShellFolder *iface,
2454 LPARAM lparam, LPCITEMIDLIST idl1, LPCITEMIDLIST idl2)
2456 ok(0, "Didn't expect CompareIDs\n");
2457 return E_NOTIMPL;
2460 static HRESULT WINAPI SF_CreateViewObject(IShellFolder *iface,
2461 HWND owner, REFIID riid, void **out)
2463 ok(0, "Didn't expect CreateViewObject\n");
2464 return E_NOTIMPL;
2467 static HRESULT WINAPI SF_GetAttributesOf(IShellFolder *iface,
2468 UINT cidl, LPCITEMIDLIST *idl, SFGAOF *inOut)
2470 ok(0, "Didn't expect GetAttributesOf\n");
2471 return E_NOTIMPL;
2474 static HRESULT WINAPI SF_GetUIObjectOf(IShellFolder *iface,
2475 HWND owner, UINT cidl, LPCITEMIDLIST *idls, REFIID riid, UINT *inOut,
2476 void **out)
2478 ok(0, "Didn't expect GetUIObjectOf\n");
2479 return E_NOTIMPL;
2482 static HRESULT WINAPI SF_GetDisplayNameOf(IShellFolder *iface,
2483 LPCITEMIDLIST idl, SHGDNF flags, STRRET *name)
2485 ok(0, "Didn't expect GetDisplayNameOf\n");
2486 return E_NOTIMPL;
2489 static HRESULT WINAPI SF_SetNameOf(IShellFolder *iface,
2490 HWND hwnd, LPCITEMIDLIST idl, LPCOLESTR name, SHGDNF flags,
2491 LPITEMIDLIST *idlOut)
2493 ok(0, "Didn't expect SetNameOf\n");
2494 return E_NOTIMPL;
2497 static IShellFolderVtbl ShellFolderVtbl = {
2498 SF_QueryInterface,
2499 SF_AddRef,
2500 SF_Release,
2501 SF_ParseDisplayName,
2502 SF_EnumObjects,
2503 SF_BindToObject,
2504 SF_BindToStorage,
2505 SF_CompareIDs,
2506 SF_CreateViewObject,
2507 SF_GetAttributesOf,
2508 SF_GetUIObjectOf,
2509 SF_GetDisplayNameOf,
2510 SF_SetNameOf
2513 static IShellFolder ShellFolder = { &ShellFolderVtbl };
2515 static void test_SHIShellFolder_EnumObjects(void)
2517 IEnumIDList *enm;
2518 HRESULT hres;
2519 IShellFolder *folder;
2521 if(!pSHIShellFolder_EnumObjects || is_win2k_and_lower){
2522 win_skip("SHIShellFolder_EnumObjects not available\n");
2523 return;
2526 if(0){
2527 /* NULL object crashes on Windows */
2528 hres = pSHIShellFolder_EnumObjects(NULL, NULL, 0, NULL);
2531 /* SHIShellFolder_EnumObjects doesn't QI the object for IShellFolder */
2532 enm = (IEnumIDList*)0xdeadbeef;
2533 hres = pSHIShellFolder_EnumObjects(&ShellFolder, NULL, 0, &enm);
2534 ok(hres == S_OK, "SHIShellFolder_EnumObjects failed: 0x%08x\n", hres);
2535 ok(enm == (IEnumIDList*)0xcafebabe, "Didn't get expected enumerator location, instead: %p\n", enm);
2537 /* SHIShellFolder_EnumObjects isn't strict about the IShellFolder object */
2538 hres = pSHGetDesktopFolder(&folder);
2539 ok(hres == S_OK, "SHGetDesktopFolder failed: 0x%08x\n", hres);
2541 enm = NULL;
2542 hres = pSHIShellFolder_EnumObjects(folder, NULL, 0, &enm);
2543 ok(hres == S_OK, "SHIShellFolder_EnumObjects failed: 0x%08x\n", hres);
2544 ok(enm != NULL, "Didn't get an enumerator\n");
2545 if(enm)
2546 IEnumIDList_Release(enm);
2548 IShellFolder_Release(folder);
2551 static void write_inifile(LPCWSTR filename)
2553 DWORD written;
2554 HANDLE file;
2556 static const char data[] =
2557 "[TestApp]\r\n"
2558 "AKey=1\r\n"
2559 "AnotherKey=asdf\r\n";
2561 file = CreateFileW(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
2562 if(file == INVALID_HANDLE_VALUE)
2563 return;
2565 WriteFile(file, data, sizeof(data), &written, NULL);
2567 CloseHandle(file);
2570 #define verify_inifile(f, e) r_verify_inifile(__LINE__, f, e)
2571 static void r_verify_inifile(unsigned l, LPCWSTR filename, LPCSTR exp)
2573 HANDLE file;
2574 CHAR buf[1024];
2575 DWORD read;
2577 file = CreateFileW(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
2578 if(file == INVALID_HANDLE_VALUE)
2579 return;
2581 ReadFile(file, buf, sizeof(buf) * sizeof(CHAR), &read, NULL);
2582 buf[read] = '\0';
2584 CloseHandle(file);
2586 ok_(__FILE__,l)(!strcmp(buf, exp), "Expected:\n%s\nGot:\n%s\n", exp,
2587 buf);
2590 static void test_SHGetIniString(void)
2592 DWORD ret;
2593 WCHAR out[64] = {0};
2595 static const WCHAR TestAppW[] = {'T','e','s','t','A','p','p',0};
2596 static const WCHAR TestIniW[] = {'C',':','\\','t','e','s','t','.','i','n','i',0};
2597 static const WCHAR AKeyW[] = {'A','K','e','y',0};
2598 static const WCHAR AnotherKeyW[] = {'A','n','o','t','h','e','r','K','e','y',0};
2599 static const WCHAR JunkKeyW[] = {'J','u','n','k','K','e','y',0};
2601 if(!pSHGetIniStringW || is_win2k_and_lower){
2602 win_skip("SHGetIniStringW is not available\n");
2603 return;
2606 write_inifile(TestIniW);
2608 if(0){
2609 /* these crash on Windows */
2610 ret = pSHGetIniStringW(NULL, NULL, NULL, 0, NULL);
2611 ret = pSHGetIniStringW(NULL, AKeyW, out, sizeof(out), TestIniW);
2612 ret = pSHGetIniStringW(TestAppW, AKeyW, NULL, sizeof(out), TestIniW);
2615 ret = pSHGetIniStringW(TestAppW, AKeyW, out, 0, TestIniW);
2616 ok(ret == 0, "SHGetIniStringW should have given 0, instead: %d\n", ret);
2618 /* valid arguments */
2619 ret = pSHGetIniStringW(TestAppW, NULL, out, sizeof(out), TestIniW);
2620 ok(broken(ret == 0) || /* win 98 */
2621 ret == 4, "SHGetIniStringW should have given 4, instead: %d\n", ret);
2622 ok(!lstrcmpW(out, AKeyW), "Expected %s, got: %s\n",
2623 wine_dbgstr_w(AKeyW), wine_dbgstr_w(out));
2625 ret = pSHGetIniStringW(TestAppW, AKeyW, out, sizeof(out), TestIniW);
2626 ok(broken(ret == 0) || /* win 98 */
2627 ret == 1, "SHGetIniStringW should have given 1, instead: %d\n", ret);
2628 ok(broken(*out == 0) || /*win 98 */
2629 !strcmp_wa(out, "1"), "Expected L\"1\", got: %s\n", wine_dbgstr_w(out));
2631 ret = pSHGetIniStringW(TestAppW, AnotherKeyW, out, sizeof(out), TestIniW);
2632 ok(broken(ret == 0) || /* win 98 */
2633 ret == 4, "SHGetIniStringW should have given 4, instead: %d\n", ret);
2634 ok(broken(*out == 0) || /* win 98 */
2635 !strcmp_wa(out, "asdf"), "Expected L\"asdf\", got: %s\n", wine_dbgstr_w(out));
2637 ret = pSHGetIniStringW(TestAppW, JunkKeyW, out, sizeof(out), TestIniW);
2638 ok(ret == 0, "SHGetIniStringW should have given 0, instead: %d\n", ret);
2639 ok(*out == 0, "Expected L\"\", got: %s\n", wine_dbgstr_w(out));
2641 DeleteFileW(TestIniW);
2644 static void test_SHSetIniString(void)
2646 BOOL ret;
2648 static const WCHAR TestAppW[] = {'T','e','s','t','A','p','p',0};
2649 static const WCHAR AnotherAppW[] = {'A','n','o','t','h','e','r','A','p','p',0};
2650 static const WCHAR TestIniW[] = {'C',':','\\','t','e','s','t','.','i','n','i',0};
2651 static const WCHAR AKeyW[] = {'A','K','e','y',0};
2652 static const WCHAR NewKeyW[] = {'N','e','w','K','e','y',0};
2653 static const WCHAR AValueW[] = {'A','V','a','l','u','e',0};
2655 if(!pSHSetIniStringW || is_win2k_and_lower){
2656 win_skip("SHSetIniStringW is not available\n");
2657 return;
2660 write_inifile(TestIniW);
2662 ret = pSHSetIniStringW(TestAppW, AKeyW, AValueW, TestIniW);
2663 ok(ret == TRUE, "SHSetIniStringW should not have failed\n");
2664 todo_wine /* wine sticks an extra \r\n at the end of the file */
2665 verify_inifile(TestIniW, "[TestApp]\r\nAKey=AValue\r\nAnotherKey=asdf\r\n");
2667 ret = pSHSetIniStringW(TestAppW, AKeyW, NULL, TestIniW);
2668 ok(ret == TRUE, "SHSetIniStringW should not have failed\n");
2669 verify_inifile(TestIniW, "[TestApp]\r\nAnotherKey=asdf\r\n");
2671 ret = pSHSetIniStringW(AnotherAppW, NewKeyW, AValueW, TestIniW);
2672 ok(ret == TRUE, "SHSetIniStringW should not have failed\n");
2673 verify_inifile(TestIniW, "[TestApp]\r\nAnotherKey=asdf\r\n[AnotherApp]\r\nNewKey=AValue\r\n");
2675 ret = pSHSetIniStringW(TestAppW, NULL, AValueW, TestIniW);
2676 ok(ret == TRUE, "SHSetIniStringW should not have failed\n");
2677 verify_inifile(TestIniW, "[AnotherApp]\r\nNewKey=AValue\r\n");
2679 DeleteFileW(TestIniW);
2682 enum _shellkey_flags {
2683 SHKEY_Explorer = 0x00,
2684 SHKEY_Root_HKCU = 0x01
2687 static void test_SHGetShellKey(void)
2689 void *pPathBuildRootW = GetProcAddress(hShlwapi, "PathBuildRootW");
2690 HKEY hkey, hkey2;
2691 DWORD ret;
2693 if (!pSHGetShellKey)
2695 win_skip("SHGetShellKey(ordinal 491) isn't available\n");
2696 return;
2699 /* some win2k */
2700 if (pPathBuildRootW && pPathBuildRootW == pSHGetShellKey)
2702 win_skip("SHGetShellKey(ordinal 491) used for PathBuildRootW\n");
2703 return;
2706 if (is_win9x || is_win2k_and_lower)
2708 win_skip("Ordinal 491 used for another call, skipping SHGetShellKey tests\n");
2709 return;
2712 /* marking broken cause latest Vista+ versions fail here */
2713 SetLastError(0xdeadbeef);
2714 hkey = pSHGetShellKey(SHKEY_Explorer, NULL, FALSE);
2715 ok(hkey == NULL || broken(hkey != NULL), "got %p\n", hkey);
2716 if (hkey)
2718 hkey2 = 0;
2719 ret = RegOpenKeyExA(hkey, "Shell Folders", 0, KEY_READ, &hkey2);
2720 ok(ret == ERROR_SUCCESS, "got %d\n", ret);
2721 ok(hkey2 != NULL, "got %p\n", hkey2);
2722 RegCloseKey( hkey2 );
2723 RegCloseKey( hkey );
2726 hkey = pSHGetShellKey(SHKEY_Explorer | SHKEY_Root_HKCU, NULL, FALSE);
2727 ok(hkey != NULL, "got %p\n", hkey);
2729 hkey2 = 0;
2730 ret = RegOpenKeyExA(hkey, "Shell Folders", 0, KEY_READ, &hkey2);
2731 ok(ret == ERROR_SUCCESS, "got %d\n", ret);
2732 ok(hkey2 != NULL, "got %p\n", hkey2);
2733 RegCloseKey( hkey2 );
2735 RegCloseKey( hkey );
2738 static void init_pointers(void)
2740 #define MAKEFUNC(f, ord) (p##f = (void*)GetProcAddress(hShlwapi, (LPSTR)(ord)))
2741 MAKEFUNC(SHAllocShared, 7);
2742 MAKEFUNC(SHLockShared, 8);
2743 MAKEFUNC(SHUnlockShared, 9);
2744 MAKEFUNC(SHFreeShared, 10);
2745 MAKEFUNC(GetAcceptLanguagesA, 14);
2746 MAKEFUNC(SHSetWindowBits, 165);
2747 MAKEFUNC(ConnectToConnectionPoint, 168);
2748 MAKEFUNC(SHSearchMapInt, 198);
2749 MAKEFUNC(SHCreateWorkerWindowA, 257);
2750 MAKEFUNC(GUIDFromStringA, 269);
2751 MAKEFUNC(SHPackDispParams, 282);
2752 MAKEFUNC(IConnectionPoint_InvokeWithCancel, 283);
2753 MAKEFUNC(IConnectionPoint_SimpleInvoke, 284);
2754 MAKEFUNC(SHGetIniStringW, 294);
2755 MAKEFUNC(SHSetIniStringW, 295);
2756 MAKEFUNC(SHFormatDateTimeA, 353);
2757 MAKEFUNC(SHFormatDateTimeW, 354);
2758 MAKEFUNC(SHIShellFolder_EnumObjects, 404);
2759 MAKEFUNC(SHGetObjectCompatFlags, 476);
2760 MAKEFUNC(IUnknown_QueryServiceExec, 484);
2761 MAKEFUNC(SHGetShellKey, 491);
2762 MAKEFUNC(SHPropertyBag_ReadLONG, 496);
2763 MAKEFUNC(IUnknown_ProfferService, 514);
2764 #undef MAKEFUNC
2767 START_TEST(ordinal)
2769 hShlwapi = GetModuleHandleA("shlwapi.dll");
2770 is_win2k_and_lower = GetProcAddress(hShlwapi, "StrChrNW") == 0;
2771 is_win9x = GetProcAddress(hShlwapi, (LPSTR)99) == 0; /* StrCpyNXA */
2773 init_pointers();
2775 hmlang = LoadLibraryA("mlang.dll");
2776 pLcidToRfc1766A = (void *)GetProcAddress(hmlang, "LcidToRfc1766A");
2778 hshell32 = LoadLibraryA("shell32.dll");
2779 pSHGetDesktopFolder = (void *)GetProcAddress(hshell32, "SHGetDesktopFolder");
2781 test_GetAcceptLanguagesA();
2782 test_SHSearchMapInt();
2783 test_alloc_shared();
2784 test_fdsa();
2785 test_GetShellSecurityDescriptor();
2786 test_SHPackDispParams();
2787 test_IConnectionPoint();
2788 test_SHPropertyBag_ReadLONG();
2789 test_SHSetWindowBits();
2790 test_SHFormatDateTimeA();
2791 test_SHFormatDateTimeW();
2792 test_SHGetObjectCompatFlags();
2793 test_IUnknown_QueryServiceExec();
2794 test_IUnknown_ProfferService();
2795 test_SHCreateWorkerWindowA();
2796 test_SHIShellFolder_EnumObjects();
2797 test_SHGetIniString();
2798 test_SHSetIniString();
2799 test_SHGetShellKey();
2801 FreeLibrary(hshell32);
2802 FreeLibrary(hmlang);