shlwapi/tests: Fix some test failures on Win2000.
[wine/hramrach.git] / dlls / shlwapi / tests / ordinal.c
blobc3c59c4e38c16ebda3f617f0038ee1c2772ec45a
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;
40 static int (WINAPI *pSHSearchMapInt)(const int*,const int*,int,int);
41 static HRESULT (WINAPI *pGetAcceptLanguagesA)(LPSTR,LPDWORD);
43 static HANDLE (WINAPI *pSHAllocShared)(LPCVOID,DWORD,DWORD);
44 static LPVOID (WINAPI *pSHLockShared)(HANDLE,DWORD);
45 static BOOL (WINAPI *pSHUnlockShared)(LPVOID);
46 static BOOL (WINAPI *pSHFreeShared)(HANDLE,DWORD);
47 static HRESULT(WINAPIV *pSHPackDispParams)(DISPPARAMS*,VARIANTARG*,UINT,...);
48 static HRESULT(WINAPI *pIConnectionPoint_SimpleInvoke)(IConnectionPoint*,DISPID,DISPPARAMS*);
49 static HRESULT(WINAPI *pIConnectionPoint_InvokeWithCancel)(IConnectionPoint*,DISPID,DISPPARAMS*,DWORD,DWORD);
50 static HRESULT(WINAPI *pConnectToConnectionPoint)(IUnknown*,REFIID,BOOL,IUnknown*, LPDWORD,IConnectionPoint **);
51 static HRESULT(WINAPI *pSHPropertyBag_ReadLONG)(IPropertyBag *,LPCWSTR,LPLONG);
52 static LONG (WINAPI *pSHSetWindowBits)(HWND, INT, UINT, UINT);
53 static INT (WINAPI *pSHFormatDateTimeA)(const FILETIME UNALIGNED*, DWORD*, LPSTR, UINT);
54 static INT (WINAPI *pSHFormatDateTimeW)(const FILETIME UNALIGNED*, DWORD*, LPWSTR, UINT);
55 static DWORD (WINAPI *pSHGetObjectCompatFlags)(IUnknown*, const CLSID*);
56 static BOOL (WINAPI *pGUIDFromStringA)(LPSTR, CLSID *);
57 static HRESULT (WINAPI *pIUnknown_QueryServiceExec)(IUnknown*, REFIID, const GUID*, DWORD, DWORD, VARIANT*, VARIANT*);
58 static HRESULT (WINAPI *pIUnknown_ProfferService)(IUnknown*, REFGUID, IServiceProvider*, DWORD*);
59 static HWND (WINAPI *pSHCreateWorkerWindowA)(LONG, HWND, DWORD, DWORD, HMENU, LONG_PTR);
60 static HRESULT (WINAPI *pSHIShellFolder_EnumObjects)(LPSHELLFOLDER, HWND, SHCONTF, IEnumIDList**);
61 static DWORD (WINAPI *pSHGetIniStringW)(LPCWSTR, LPCWSTR, LPWSTR, DWORD, LPCWSTR);
62 static BOOL (WINAPI *pSHSetIniStringW)(LPCWSTR, LPCWSTR, LPCWSTR, LPCWSTR);
64 static HMODULE hmlang;
65 static HRESULT (WINAPI *pLcidToRfc1766A)(LCID, LPSTR, INT);
67 static HMODULE hshell32;
68 static HRESULT (WINAPI *pSHGetDesktopFolder)(IShellFolder**);
70 static const CHAR ie_international[] = {
71 'S','o','f','t','w','a','r','e','\\',
72 'M','i','c','r','o','s','o','f','t','\\',
73 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
74 'I','n','t','e','r','n','a','t','i','o','n','a','l',0};
75 static const CHAR acceptlanguage[] = {
76 'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0};
78 static int strcmp_wa(LPCWSTR strw, const char *stra)
80 CHAR buf[512];
81 WideCharToMultiByte(CP_ACP, 0, strw, -1, buf, sizeof(buf), NULL, NULL);
82 return lstrcmpA(stra, buf);
85 typedef struct {
86 int id;
87 const void *args[5];
88 } call_entry_t;
90 typedef struct {
91 call_entry_t *calls;
92 int count;
93 int alloc;
94 } call_trace_t;
96 static void init_call_trace(call_trace_t *ctrace)
98 ctrace->alloc = 10;
99 ctrace->count = 0;
100 ctrace->calls = HeapAlloc(GetProcessHeap(), 0, sizeof(call_entry_t) * ctrace->alloc);
103 static void free_call_trace(const call_trace_t *ctrace)
105 HeapFree(GetProcessHeap(), 0, ctrace->calls);
108 static void add_call(call_trace_t *ctrace, int id, const void *arg0,
109 const void *arg1, const void *arg2, const void *arg3, const void *arg4)
111 call_entry_t call;
113 call.id = id;
114 call.args[0] = arg0;
115 call.args[1] = arg1;
116 call.args[2] = arg2;
117 call.args[3] = arg3;
118 call.args[4] = arg4;
120 if (ctrace->count == ctrace->alloc)
122 ctrace->alloc *= 2;
123 ctrace->calls = HeapReAlloc(GetProcessHeap(),0, ctrace->calls, ctrace->alloc*sizeof(call_entry_t));
126 ctrace->calls[ctrace->count++] = call;
129 static void ok_trace_(call_trace_t *texpected, call_trace_t *tgot, int line)
131 if (texpected->count == tgot->count)
133 INT i;
134 /* compare */
135 for (i = 0; i < texpected->count; i++)
137 call_entry_t *expected = &texpected->calls[i];
138 call_entry_t *got = &tgot->calls[i];
139 INT j;
141 ok_(__FILE__, line)(expected->id == got->id, "got different ids %d: %d, %d\n", i+1, expected->id, got->id);
143 for (j = 0; j < 5; j++)
145 ok_(__FILE__, line)(expected->args[j] == got->args[j], "got different args[%d] for %d: %p, %p\n", j, i+1,
146 expected->args[j], got->args[j]);
150 else
151 ok_(__FILE__, line)(0, "traces length mismatch\n");
154 #define ok_trace(a, b) ok_trace_(a, b, __LINE__)
156 /* trace of actually made calls */
157 static call_trace_t trace_got;
159 static void test_GetAcceptLanguagesA(void)
161 static LPCSTR table[] = {"de,en-gb;q=0.7,en;q=0.3",
162 "de,en;q=0.3,en-gb;q=0.7", /* sorting is ignored */
163 "winetest", /* content is ignored */
164 "de-de,de;q=0.5",
165 "de",
166 NULL};
168 DWORD exactsize;
169 char original[512];
170 char language[32];
171 char buffer[64];
172 HKEY hroot = NULL;
173 LONG res_query = ERROR_SUCCESS;
174 LONG lres;
175 HRESULT hr;
176 DWORD maxlen = sizeof(buffer) - 2;
177 DWORD len;
178 LCID lcid;
179 LPCSTR entry;
180 INT i = 0;
182 if (!pGetAcceptLanguagesA) {
183 win_skip("GetAcceptLanguagesA is not available\n");
184 return;
187 lcid = GetUserDefaultLCID();
189 /* Get the original Value */
190 lres = RegOpenKeyA(HKEY_CURRENT_USER, ie_international, &hroot);
191 if (lres) {
192 skip("RegOpenKey(%s) failed: %d\n", ie_international, lres);
193 return;
195 len = sizeof(original);
196 original[0] = 0;
197 res_query = RegQueryValueExA(hroot, acceptlanguage, 0, NULL, (PBYTE)original, &len);
199 RegDeleteValue(hroot, acceptlanguage);
201 /* Some windows versions use "lang-COUNTRY" as default */
202 memset(language, 0, sizeof(language));
203 len = GetLocaleInfoA(lcid, LOCALE_SISO639LANGNAME, language, sizeof(language));
205 if (len) {
206 lstrcat(language, "-");
207 memset(buffer, 0, sizeof(buffer));
208 len = GetLocaleInfoA(lcid, LOCALE_SISO3166CTRYNAME, buffer, sizeof(buffer) - len - 1);
209 lstrcat(language, buffer);
211 else
213 /* LOCALE_SNAME has additional parts in some languages. Try only as last chance */
214 memset(language, 0, sizeof(language));
215 len = GetLocaleInfoA(lcid, LOCALE_SNAME, language, sizeof(language));
218 /* get the default value */
219 len = maxlen;
220 memset(buffer, '#', maxlen);
221 buffer[maxlen] = 0;
222 hr = pGetAcceptLanguagesA( buffer, &len);
224 if (hr != S_OK) {
225 win_skip("GetAcceptLanguagesA failed with 0x%x\n", hr);
226 goto restore_original;
229 if (lstrcmpA(buffer, language)) {
230 /* some windows versions use "lang" or "lang-country" as default */
231 language[0] = 0;
232 if (pLcidToRfc1766A) {
233 hr = pLcidToRfc1766A(lcid, language, sizeof(language));
234 ok(hr == S_OK, "LcidToRfc1766A returned 0x%x and %s\n", hr, language);
238 ok(!lstrcmpA(buffer, language),
239 "have '%s' (searching for '%s')\n", language, buffer);
241 if (lstrcmpA(buffer, language)) {
242 win_skip("no more ideas, how to build the default language '%s'\n", buffer);
243 goto restore_original;
246 trace("detected default: %s\n", language);
247 while ((entry = table[i])) {
249 exactsize = lstrlenA(entry);
251 lres = RegSetValueExA(hroot, acceptlanguage, 0, REG_SZ, (const BYTE *) entry, exactsize + 1);
252 ok(!lres, "got %d for RegSetValueExA: %s\n", lres, entry);
254 /* len includes space for the terminating 0 before vista/w2k8 */
255 len = exactsize + 2;
256 memset(buffer, '#', maxlen);
257 buffer[maxlen] = 0;
258 hr = pGetAcceptLanguagesA( buffer, &len);
259 ok(((hr == E_INVALIDARG) && (len == 0)) ||
260 (SUCCEEDED(hr) &&
261 ((len == exactsize) || (len == exactsize+1)) &&
262 !lstrcmpA(buffer, entry)),
263 "+2_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
265 len = exactsize + 1;
266 memset(buffer, '#', maxlen);
267 buffer[maxlen] = 0;
268 hr = pGetAcceptLanguagesA( buffer, &len);
269 ok(((hr == E_INVALIDARG) && (len == 0)) ||
270 (SUCCEEDED(hr) &&
271 ((len == exactsize) || (len == exactsize+1)) &&
272 !lstrcmpA(buffer, entry)),
273 "+1_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
275 len = exactsize;
276 memset(buffer, '#', maxlen);
277 buffer[maxlen] = 0;
278 hr = pGetAcceptLanguagesA( buffer, &len);
280 /* There is no space for the string in the registry.
281 When the buffer is large enough, the default language is returned
283 When the buffer is too small for that fallback, win7_32 and w2k8_64
284 and above fail with HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), but
285 recent os succeed and return a partial result while
286 older os succeed and overflow the buffer */
288 ok(((hr == E_INVALIDARG) && (len == 0)) ||
289 (((hr == S_OK) && !lstrcmpA(buffer, language) && (len == lstrlenA(language))) ||
290 ((hr == S_OK) && !memcmp(buffer, language, len)) ||
291 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len)),
292 "==_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
294 if (exactsize > 1) {
295 len = exactsize - 1;
296 memset(buffer, '#', maxlen);
297 buffer[maxlen] = 0;
298 hr = pGetAcceptLanguagesA( buffer, &len);
299 ok(((hr == E_INVALIDARG) && (len == 0)) ||
300 (((hr == S_OK) && !lstrcmpA(buffer, language) && (len == lstrlenA(language))) ||
301 ((hr == S_OK) && !memcmp(buffer, language, len)) ||
302 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len)),
303 "-1_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
306 len = 1;
307 memset(buffer, '#', maxlen);
308 buffer[maxlen] = 0;
309 hr = pGetAcceptLanguagesA( buffer, &len);
310 ok(((hr == E_INVALIDARG) && (len == 0)) ||
311 (((hr == S_OK) && !lstrcmpA(buffer, language) && (len == lstrlenA(language))) ||
312 ((hr == S_OK) && !memcmp(buffer, language, len)) ||
313 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len)),
314 "=1_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
316 len = maxlen;
317 hr = pGetAcceptLanguagesA( NULL, &len);
319 /* w2k3 and below: E_FAIL and untouched len,
320 since w2k8: S_OK and needed size (excluding 0) */
321 ok( ((hr == S_OK) && (len == exactsize)) ||
322 ((hr == E_FAIL) && (len == maxlen)),
323 "NULL,max #%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
325 i++;
328 /* without a value in the registry, a default language is returned */
329 RegDeleteValue(hroot, acceptlanguage);
331 len = maxlen;
332 memset(buffer, '#', maxlen);
333 buffer[maxlen] = 0;
334 hr = pGetAcceptLanguagesA( buffer, &len);
335 ok( ((hr == S_OK) && (len == lstrlenA(language))),
336 "max: got 0x%x with %d and %s (expected S_OK with %d and '%s'\n",
337 hr, len, buffer, lstrlenA(language), language);
339 len = 2;
340 memset(buffer, '#', maxlen);
341 buffer[maxlen] = 0;
342 hr = pGetAcceptLanguagesA( buffer, &len);
343 ok( (((hr == S_OK) || (hr == E_INVALIDARG)) && !memcmp(buffer, language, len)) ||
344 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len),
345 "=2: got 0x%x with %d and %s\n", hr, len, buffer);
347 len = 1;
348 memset(buffer, '#', maxlen);
349 buffer[maxlen] = 0;
350 hr = pGetAcceptLanguagesA( buffer, &len);
351 /* When the buffer is too small, win7_32 and w2k8_64 and above fail with
352 HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), other versions suceed
353 and return a partial 0 terminated result while other versions
354 fail with E_INVALIDARG and return a partial unterminated result */
355 ok( (((hr == S_OK) || (hr == E_INVALIDARG)) && !memcmp(buffer, language, len)) ||
356 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len),
357 "=1: got 0x%x with %d and %s\n", hr, len, buffer);
359 len = 0;
360 memset(buffer, '#', maxlen);
361 buffer[maxlen] = 0;
362 hr = pGetAcceptLanguagesA( buffer, &len);
363 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
364 ok((hr == E_FAIL) || (hr == E_INVALIDARG),
365 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr);
367 memset(buffer, '#', maxlen);
368 buffer[maxlen] = 0;
369 hr = pGetAcceptLanguagesA( buffer, NULL);
370 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
371 ok((hr == E_FAIL) || (hr == E_INVALIDARG),
372 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr);
375 hr = pGetAcceptLanguagesA( NULL, NULL);
376 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
377 ok((hr == E_FAIL) || (hr == E_INVALIDARG),
378 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr);
380 restore_original:
381 if (!res_query) {
382 len = lstrlenA(original);
383 lres = RegSetValueExA(hroot, acceptlanguage, 0, REG_SZ, (const BYTE *) original, len ? len + 1: 0);
384 ok(!lres, "RegSetValueEx(%s) failed: %d\n", original, lres);
386 else
388 RegDeleteValue(hroot, acceptlanguage);
390 RegCloseKey(hroot);
393 static void test_SHSearchMapInt(void)
395 int keys[8], values[8];
396 int i = 0;
398 if (!pSHSearchMapInt)
399 return;
401 memset(keys, 0, sizeof(keys));
402 memset(values, 0, sizeof(values));
403 keys[0] = 99; values[0] = 101;
405 /* NULL key/value lists crash native, so skip testing them */
407 /* 1 element */
408 i = pSHSearchMapInt(keys, values, 1, keys[0]);
409 ok(i == values[0], "Len 1, expected %d, got %d\n", values[0], i);
411 /* Key doesn't exist */
412 i = pSHSearchMapInt(keys, values, 1, 100);
413 ok(i == -1, "Len 1 - bad key, expected -1, got %d\n", i);
415 /* Len = 0 => not found */
416 i = pSHSearchMapInt(keys, values, 0, keys[0]);
417 ok(i == -1, "Len 1 - passed len 0, expected -1, got %d\n", i);
419 /* 2 elements, len = 1 */
420 keys[1] = 98; values[1] = 102;
421 i = pSHSearchMapInt(keys, values, 1, keys[1]);
422 ok(i == -1, "Len 1 - array len 2, expected -1, got %d\n", i);
424 /* 2 elements, len = 2 */
425 i = pSHSearchMapInt(keys, values, 2, keys[1]);
426 ok(i == values[1], "Len 2, expected %d, got %d\n", values[1], i);
428 /* Searches forward */
429 keys[2] = 99; values[2] = 103;
430 i = pSHSearchMapInt(keys, values, 3, keys[0]);
431 ok(i == values[0], "Len 3, expected %d, got %d\n", values[0], i);
434 static void test_alloc_shared(void)
436 DWORD procid;
437 HANDLE hmem;
438 int val;
439 int* p;
440 BOOL ret;
442 procid=GetCurrentProcessId();
443 hmem=pSHAllocShared(NULL,10,procid);
444 ok(hmem!=NULL,"SHAllocShared(NULL...) failed: %u\n", GetLastError());
445 ret = pSHFreeShared(hmem, procid);
446 ok( ret, "SHFreeShared failed: %u\n", GetLastError());
448 val=0x12345678;
449 hmem=pSHAllocShared(&val,4,procid);
450 ok(hmem!=NULL,"SHAllocShared(NULL...) failed: %u\n", GetLastError());
452 p=pSHLockShared(hmem,procid);
453 ok(p!=NULL,"SHLockShared failed: %u\n", GetLastError());
454 if (p!=NULL)
455 ok(*p==val,"Wrong value in shared memory: %d instead of %d\n",*p,val);
456 ret = pSHUnlockShared(p);
457 ok( ret, "SHUnlockShared failed: %u\n", GetLastError());
459 ret = pSHFreeShared(hmem, procid);
460 ok( ret, "SHFreeShared failed: %u\n", GetLastError());
463 static void test_fdsa(void)
465 typedef struct
467 DWORD num_items; /* Number of elements inserted */
468 void *mem; /* Ptr to array */
469 DWORD blocks_alloced; /* Number of elements allocated */
470 BYTE inc; /* Number of elements to grow by when we need to expand */
471 BYTE block_size; /* Size in bytes of an element */
472 BYTE flags; /* Flags */
473 } FDSA_info;
475 BOOL (WINAPI *pFDSA_Initialize)(DWORD block_size, DWORD inc, FDSA_info *info, void *mem,
476 DWORD init_blocks);
477 BOOL (WINAPI *pFDSA_Destroy)(FDSA_info *info);
478 DWORD (WINAPI *pFDSA_InsertItem)(FDSA_info *info, DWORD where, const void *block);
479 BOOL (WINAPI *pFDSA_DeleteItem)(FDSA_info *info, DWORD where);
481 FDSA_info info;
482 int block_size = 10, init_blocks = 4, inc = 2;
483 DWORD ret;
484 char *mem;
486 pFDSA_Initialize = (void *)GetProcAddress(hShlwapi, (LPSTR)208);
487 pFDSA_Destroy = (void *)GetProcAddress(hShlwapi, (LPSTR)209);
488 pFDSA_InsertItem = (void *)GetProcAddress(hShlwapi, (LPSTR)210);
489 pFDSA_DeleteItem = (void *)GetProcAddress(hShlwapi, (LPSTR)211);
491 mem = HeapAlloc(GetProcessHeap(), 0, block_size * init_blocks);
492 memset(&info, 0, sizeof(info));
494 ok(pFDSA_Initialize(block_size, inc, &info, mem, init_blocks), "FDSA_Initialize rets FALSE\n");
495 ok(info.num_items == 0, "num_items = %d\n", info.num_items);
496 ok(info.mem == mem, "mem = %p\n", info.mem);
497 ok(info.blocks_alloced == init_blocks, "blocks_alloced = %d\n", info.blocks_alloced);
498 ok(info.inc == inc, "inc = %d\n", info.inc);
499 ok(info.block_size == block_size, "block_size = %d\n", info.block_size);
500 ok(info.flags == 0, "flags = %d\n", info.flags);
502 ret = pFDSA_InsertItem(&info, 1234, "1234567890");
503 ok(ret == 0, "ret = %d\n", ret);
504 ok(info.num_items == 1, "num_items = %d\n", info.num_items);
505 ok(info.mem == mem, "mem = %p\n", info.mem);
506 ok(info.blocks_alloced == init_blocks, "blocks_alloced = %d\n", info.blocks_alloced);
507 ok(info.inc == inc, "inc = %d\n", info.inc);
508 ok(info.block_size == block_size, "block_size = %d\n", info.block_size);
509 ok(info.flags == 0, "flags = %d\n", info.flags);
511 ret = pFDSA_InsertItem(&info, 1234, "abcdefghij");
512 ok(ret == 1, "ret = %d\n", ret);
514 ret = pFDSA_InsertItem(&info, 1, "klmnopqrst");
515 ok(ret == 1, "ret = %d\n", ret);
517 ret = pFDSA_InsertItem(&info, 0, "uvwxyzABCD");
518 ok(ret == 0, "ret = %d\n", ret);
519 ok(info.mem == mem, "mem = %p\n", info.mem);
520 ok(info.flags == 0, "flags = %d\n", info.flags);
522 /* This next InsertItem will cause shlwapi to allocate its own mem buffer */
523 ret = pFDSA_InsertItem(&info, 0, "EFGHIJKLMN");
524 ok(ret == 0, "ret = %d\n", ret);
525 ok(info.mem != mem, "mem = %p\n", info.mem);
526 ok(info.blocks_alloced == init_blocks + inc, "blocks_alloced = %d\n", info.blocks_alloced);
527 ok(info.flags == 0x1, "flags = %d\n", info.flags);
529 ok(!memcmp(info.mem, "EFGHIJKLMNuvwxyzABCD1234567890klmnopqrstabcdefghij", 50), "mem %s\n", (char*)info.mem);
531 ok(pFDSA_DeleteItem(&info, 2), "rets FALSE\n");
532 ok(info.mem != mem, "mem = %p\n", info.mem);
533 ok(info.blocks_alloced == init_blocks + inc, "blocks_alloced = %d\n", info.blocks_alloced);
534 ok(info.flags == 0x1, "flags = %d\n", info.flags);
536 ok(!memcmp(info.mem, "EFGHIJKLMNuvwxyzABCDklmnopqrstabcdefghij", 40), "mem %s\n", (char*)info.mem);
538 ok(pFDSA_DeleteItem(&info, 3), "rets FALSE\n");
539 ok(info.mem != mem, "mem = %p\n", info.mem);
540 ok(info.blocks_alloced == init_blocks + inc, "blocks_alloced = %d\n", info.blocks_alloced);
541 ok(info.flags == 0x1, "flags = %d\n", info.flags);
543 ok(!memcmp(info.mem, "EFGHIJKLMNuvwxyzABCDklmnopqrst", 30), "mem %s\n", (char*)info.mem);
545 ok(!pFDSA_DeleteItem(&info, 4), "does not ret FALSE\n");
547 /* As shlwapi has allocated memory internally, Destroy will ret FALSE */
548 ok(!pFDSA_Destroy(&info), "FDSA_Destroy does not ret FALSE\n");
551 /* When Initialize is called with inc = 0, set it to 1 */
552 ok(pFDSA_Initialize(block_size, 0, &info, mem, init_blocks), "FDSA_Initialize rets FALSE\n");
553 ok(info.inc == 1, "inc = %d\n", info.inc);
555 /* This time, because shlwapi hasn't had to allocate memory
556 internally, Destroy rets non-zero */
557 ok(pFDSA_Destroy(&info), "FDSA_Destroy rets FALSE\n");
560 HeapFree(GetProcessHeap(), 0, mem);
564 typedef struct SHELL_USER_SID {
565 SID_IDENTIFIER_AUTHORITY sidAuthority;
566 DWORD dwUserGroupID;
567 DWORD dwUserID;
568 } SHELL_USER_SID, *PSHELL_USER_SID;
569 typedef struct SHELL_USER_PERMISSION {
570 SHELL_USER_SID susID;
571 DWORD dwAccessType;
572 BOOL fInherit;
573 DWORD dwAccessMask;
574 DWORD dwInheritMask;
575 DWORD dwInheritAccessMask;
576 } SHELL_USER_PERMISSION, *PSHELL_USER_PERMISSION;
577 static void test_GetShellSecurityDescriptor(void)
579 SHELL_USER_PERMISSION supCurrentUserFull = {
580 { {SECURITY_NULL_SID_AUTHORITY}, 0, 0 },
581 ACCESS_ALLOWED_ACE_TYPE, FALSE,
582 GENERIC_ALL, 0, 0 };
583 #define MY_INHERITANCE 0xBE /* invalid value to proof behavior */
584 SHELL_USER_PERMISSION supEveryoneDenied = {
585 { {SECURITY_WORLD_SID_AUTHORITY}, SECURITY_WORLD_RID, 0 },
586 ACCESS_DENIED_ACE_TYPE, TRUE,
587 GENERIC_WRITE, MY_INHERITANCE | 0xDEADBA00, GENERIC_READ };
588 PSHELL_USER_PERMISSION rgsup[2] = {
589 &supCurrentUserFull, &supEveryoneDenied,
591 SECURITY_DESCRIPTOR* psd;
592 SECURITY_DESCRIPTOR* (WINAPI*pGetShellSecurityDescriptor)(PSHELL_USER_PERMISSION*,int);
593 void *pChrCmpIW = GetProcAddress(hShlwapi, "ChrCmpIW");
595 pGetShellSecurityDescriptor=(void*)GetProcAddress(hShlwapi,(char*)475);
597 if(!pGetShellSecurityDescriptor)
599 win_skip("GetShellSecurityDescriptor not available\n");
600 return;
603 if(pChrCmpIW && pChrCmpIW == pGetShellSecurityDescriptor) /* win2k */
605 win_skip("Skipping for GetShellSecurityDescriptor, same ordinal used for ChrCmpIW\n");
606 return;
609 psd = pGetShellSecurityDescriptor(NULL, 2);
610 ok(psd==NULL ||
611 broken(psd==INVALID_HANDLE_VALUE), /* IE5 */
612 "GetShellSecurityDescriptor should fail\n");
613 psd = pGetShellSecurityDescriptor(rgsup, 0);
614 ok(psd==NULL, "GetShellSecurityDescriptor should fail, got %p\n", psd);
616 SetLastError(0xdeadbeef);
617 psd = pGetShellSecurityDescriptor(rgsup, 2);
618 if (psd == NULL && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
620 /* The previous calls to GetShellSecurityDescriptor don't set the last error */
621 win_skip("GetShellSecurityDescriptor is not implemented\n");
622 return;
624 if (psd == INVALID_HANDLE_VALUE)
626 win_skip("GetShellSecurityDescriptor is broken on IE5\n");
627 return;
629 ok(psd!=NULL, "GetShellSecurityDescriptor failed\n");
630 if (psd!=NULL)
632 BOOL bHasDacl = FALSE, bDefaulted;
633 PACL pAcl;
634 DWORD dwRev;
635 SECURITY_DESCRIPTOR_CONTROL control;
637 ok(IsValidSecurityDescriptor(psd), "returned value is not valid SD\n");
639 ok(GetSecurityDescriptorControl(psd, &control, &dwRev),
640 "GetSecurityDescriptorControl failed with error %u\n", GetLastError());
641 ok(0 == (control & SE_SELF_RELATIVE), "SD should be absolute\n");
643 ok(GetSecurityDescriptorDacl(psd, &bHasDacl, &pAcl, &bDefaulted),
644 "GetSecurityDescriptorDacl failed with error %u\n", GetLastError());
646 ok(bHasDacl, "SD has no DACL\n");
647 if (bHasDacl)
649 ok(!bDefaulted, "DACL should not be defaulted\n");
651 ok(pAcl != NULL, "NULL DACL!\n");
652 if (pAcl != NULL)
654 ACL_SIZE_INFORMATION asiSize;
656 ok(IsValidAcl(pAcl), "DACL is not valid\n");
658 ok(GetAclInformation(pAcl, &asiSize, sizeof(asiSize), AclSizeInformation),
659 "GetAclInformation failed with error %u\n", GetLastError());
661 ok(asiSize.AceCount == 3, "Incorrect number of ACEs: %d entries\n", asiSize.AceCount);
662 if (asiSize.AceCount == 3)
664 ACCESS_ALLOWED_ACE *paaa; /* will use for DENIED too */
666 ok(GetAce(pAcl, 0, (LPVOID*)&paaa), "GetAce failed with error %u\n", GetLastError());
667 ok(paaa->Header.AceType == ACCESS_ALLOWED_ACE_TYPE,
668 "Invalid ACE type %d\n", paaa->Header.AceType);
669 ok(paaa->Header.AceFlags == 0, "Invalid ACE flags %x\n", paaa->Header.AceFlags);
670 ok(paaa->Mask == GENERIC_ALL, "Invalid ACE mask %x\n", paaa->Mask);
672 ok(GetAce(pAcl, 1, (LPVOID*)&paaa), "GetAce failed with error %u\n", GetLastError());
673 ok(paaa->Header.AceType == ACCESS_DENIED_ACE_TYPE,
674 "Invalid ACE type %d\n", paaa->Header.AceType);
675 /* first one of two ACEs generated from inheritable entry - without inheritance */
676 ok(paaa->Header.AceFlags == 0, "Invalid ACE flags %x\n", paaa->Header.AceFlags);
677 ok(paaa->Mask == GENERIC_WRITE, "Invalid ACE mask %x\n", paaa->Mask);
679 ok(GetAce(pAcl, 2, (LPVOID*)&paaa), "GetAce failed with error %u\n", GetLastError());
680 ok(paaa->Header.AceType == ACCESS_DENIED_ACE_TYPE,
681 "Invalid ACE type %d\n", paaa->Header.AceType);
682 /* second ACE - with inheritance */
683 ok(paaa->Header.AceFlags == MY_INHERITANCE,
684 "Invalid ACE flags %x\n", paaa->Header.AceFlags);
685 ok(paaa->Mask == GENERIC_READ, "Invalid ACE mask %x\n", paaa->Mask);
690 LocalFree(psd);
694 static void test_SHPackDispParams(void)
696 DISPPARAMS params;
697 VARIANT vars[10];
698 HRESULT hres;
700 if(!pSHPackDispParams)
701 win_skip("SHPackSidpParams not available\n");
703 memset(&params, 0xc0, sizeof(params));
704 memset(vars, 0xc0, sizeof(vars));
705 hres = pSHPackDispParams(&params, vars, 1, VT_I4, 0xdeadbeef);
706 ok(hres == S_OK, "SHPackDispParams failed: %08x\n", hres);
707 ok(params.cArgs == 1, "params.cArgs = %d\n", params.cArgs);
708 ok(params.cNamedArgs == 0, "params.cNamedArgs = %d\n", params.cArgs);
709 ok(params.rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", params.rgdispidNamedArgs);
710 ok(params.rgvarg == vars, "params.rgvarg = %p\n", params.rgvarg);
711 ok(V_VT(vars) == VT_I4, "V_VT(var) = %d\n", V_VT(vars));
712 ok(V_I4(vars) == 0xdeadbeef, "failed %x\n", V_I4(vars));
714 memset(&params, 0xc0, sizeof(params));
715 hres = pSHPackDispParams(&params, NULL, 0, 0);
716 ok(hres == S_OK, "SHPackDispParams failed: %08x\n", hres);
717 ok(params.cArgs == 0, "params.cArgs = %d\n", params.cArgs);
718 ok(params.cNamedArgs == 0, "params.cNamedArgs = %d\n", params.cArgs);
719 ok(params.rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", params.rgdispidNamedArgs);
720 ok(params.rgvarg == NULL, "params.rgvarg = %p\n", params.rgvarg);
722 memset(vars, 0xc0, sizeof(vars));
723 memset(&params, 0xc0, sizeof(params));
724 hres = pSHPackDispParams(&params, vars, 4, VT_BSTR, (void*)0xdeadbeef, VT_EMPTY, 10,
725 VT_I4, 100, VT_DISPATCH, (void*)0xdeadbeef);
726 ok(hres == S_OK, "SHPackDispParams failed: %08x\n", hres);
727 ok(params.cArgs == 4, "params.cArgs = %d\n", params.cArgs);
728 ok(params.cNamedArgs == 0, "params.cNamedArgs = %d\n", params.cArgs);
729 ok(params.rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", params.rgdispidNamedArgs);
730 ok(params.rgvarg == vars, "params.rgvarg = %p\n", params.rgvarg);
731 ok(V_VT(vars) == VT_DISPATCH, "V_VT(vars[0]) = %x\n", V_VT(vars));
732 ok(V_I4(vars) == 0xdeadbeef, "V_I4(vars[0]) = %x\n", V_I4(vars));
733 ok(V_VT(vars+1) == VT_I4, "V_VT(vars[1]) = %d\n", V_VT(vars+1));
734 ok(V_I4(vars+1) == 100, "V_I4(vars[1]) = %x\n", V_I4(vars+1));
735 ok(V_VT(vars+2) == VT_I4, "V_VT(vars[2]) = %d\n", V_VT(vars+2));
736 ok(V_I4(vars+2) == 10, "V_I4(vars[2]) = %x\n", V_I4(vars+2));
737 ok(V_VT(vars+3) == VT_BSTR, "V_VT(vars[3]) = %d\n", V_VT(vars+3));
738 ok(V_BSTR(vars+3) == (void*)0xdeadbeef, "V_BSTR(vars[3]) = %p\n", V_BSTR(vars+3));
741 typedef struct _disp
743 const IDispatchVtbl *vtbl;
744 LONG refCount;
745 } Disp;
747 typedef struct _contain
749 const IConnectionPointContainerVtbl *vtbl;
750 LONG refCount;
752 UINT ptCount;
753 IConnectionPoint **pt;
754 } Contain;
756 typedef struct _cntptn
758 const IConnectionPointVtbl *vtbl;
759 LONG refCount;
761 Contain *container;
762 GUID id;
763 UINT sinkCount;
764 IUnknown **sink;
765 } ConPt;
767 typedef struct _enum
769 const IEnumConnectionsVtbl *vtbl;
770 LONG refCount;
772 UINT idx;
773 ConPt *pt;
774 } EnumCon;
776 typedef struct _enumpt
778 const IEnumConnectionPointsVtbl *vtbl;
779 LONG refCount;
781 int idx;
782 Contain *container;
783 } EnumPt;
786 static HRESULT WINAPI Disp_QueryInterface(
787 IDispatch* This,
788 REFIID riid,
789 void **ppvObject)
791 *ppvObject = NULL;
793 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch))
795 *ppvObject = This;
798 if (*ppvObject)
800 IUnknown_AddRef(This);
801 return S_OK;
804 trace("no interface\n");
805 return E_NOINTERFACE;
808 static ULONG WINAPI Disp_AddRef(IDispatch* This)
810 Disp *iface = (Disp*)This;
811 return InterlockedIncrement(&iface->refCount);
814 static ULONG WINAPI Disp_Release(IDispatch* This)
816 Disp *iface = (Disp*)This;
817 ULONG ret;
819 ret = InterlockedDecrement(&iface->refCount);
820 if (ret == 0)
821 HeapFree(GetProcessHeap(),0,This);
822 return ret;
825 static HRESULT WINAPI Disp_GetTypeInfoCount(
826 IDispatch* This,
827 UINT *pctinfo)
829 return ERROR_SUCCESS;
832 static HRESULT WINAPI Disp_GetTypeInfo(
833 IDispatch* This,
834 UINT iTInfo,
835 LCID lcid,
836 ITypeInfo **ppTInfo)
838 return ERROR_SUCCESS;
841 static HRESULT WINAPI Disp_GetIDsOfNames(
842 IDispatch* This,
843 REFIID riid,
844 LPOLESTR *rgszNames,
845 UINT cNames,
846 LCID lcid,
847 DISPID *rgDispId)
849 return ERROR_SUCCESS;
852 static HRESULT WINAPI Disp_Invoke(
853 IDispatch* This,
854 DISPID dispIdMember,
855 REFIID riid,
856 LCID lcid,
857 WORD wFlags,
858 DISPPARAMS *pDispParams,
859 VARIANT *pVarResult,
860 EXCEPINFO *pExcepInfo,
861 UINT *puArgErr)
863 trace("%p %x %p %x %x %p %p %p %p\n",This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr);
865 ok(dispIdMember == 0xa0 || dispIdMember == 0xa1, "Unknown dispIdMember\n");
866 ok(pDispParams != NULL, "Invoked with NULL pDispParams\n");
867 ok(wFlags == DISPATCH_METHOD, "Wrong flags %x\n",wFlags);
868 ok(lcid == 0,"Wrong lcid %x\n",lcid);
869 if (dispIdMember == 0xa0)
871 ok(pDispParams->cArgs == 0, "params.cArgs = %d\n", pDispParams->cArgs);
872 ok(pDispParams->cNamedArgs == 0, "params.cNamedArgs = %d\n", pDispParams->cArgs);
873 ok(pDispParams->rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", pDispParams->rgdispidNamedArgs);
874 ok(pDispParams->rgvarg == NULL, "params.rgvarg = %p\n", pDispParams->rgvarg);
876 else if (dispIdMember == 0xa1)
878 ok(pDispParams->cArgs == 2, "params.cArgs = %d\n", pDispParams->cArgs);
879 ok(pDispParams->cNamedArgs == 0, "params.cNamedArgs = %d\n", pDispParams->cArgs);
880 ok(pDispParams->rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", pDispParams->rgdispidNamedArgs);
881 ok(V_VT(pDispParams->rgvarg) == VT_BSTR, "V_VT(var) = %d\n", V_VT(pDispParams->rgvarg));
882 ok(V_I4(pDispParams->rgvarg) == 0xdeadcafe , "failed %p\n", V_BSTR(pDispParams->rgvarg));
883 ok(V_VT(pDispParams->rgvarg+1) == VT_I4, "V_VT(var) = %d\n", V_VT(pDispParams->rgvarg+1));
884 ok(V_I4(pDispParams->rgvarg+1) == 0xdeadbeef, "failed %x\n", V_I4(pDispParams->rgvarg+1));
887 return ERROR_SUCCESS;
890 static const IDispatchVtbl disp_vtbl = {
891 Disp_QueryInterface,
892 Disp_AddRef,
893 Disp_Release,
895 Disp_GetTypeInfoCount,
896 Disp_GetTypeInfo,
897 Disp_GetIDsOfNames,
898 Disp_Invoke
901 static HRESULT WINAPI Enum_QueryInterface(
902 IEnumConnections* This,
903 REFIID riid,
904 void **ppvObject)
906 *ppvObject = NULL;
908 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IEnumConnections))
910 *ppvObject = This;
913 if (*ppvObject)
915 IUnknown_AddRef(This);
916 return S_OK;
919 trace("no interface\n");
920 return E_NOINTERFACE;
923 static ULONG WINAPI Enum_AddRef(IEnumConnections* This)
925 EnumCon *iface = (EnumCon*)This;
926 return InterlockedIncrement(&iface->refCount);
929 static ULONG WINAPI Enum_Release(IEnumConnections* This)
931 EnumCon *iface = (EnumCon*)This;
932 ULONG ret;
934 ret = InterlockedDecrement(&iface->refCount);
935 if (ret == 0)
936 HeapFree(GetProcessHeap(),0,This);
937 return ret;
940 static HRESULT WINAPI Enum_Next(
941 IEnumConnections* This,
942 ULONG cConnections,
943 LPCONNECTDATA rgcd,
944 ULONG *pcFetched)
946 EnumCon *iface = (EnumCon*)This;
948 if (cConnections > 0 && iface->idx < iface->pt->sinkCount)
950 rgcd->pUnk = iface->pt->sink[iface->idx];
951 IUnknown_AddRef(iface->pt->sink[iface->idx]);
952 rgcd->dwCookie=0xff;
953 if (pcFetched)
954 *pcFetched = 1;
955 iface->idx++;
956 return S_OK;
959 return E_FAIL;
962 static HRESULT WINAPI Enum_Skip(
963 IEnumConnections* This,
964 ULONG cConnections)
966 return E_FAIL;
969 static HRESULT WINAPI Enum_Reset(
970 IEnumConnections* This)
972 return E_FAIL;
975 static HRESULT WINAPI Enum_Clone(
976 IEnumConnections* This,
977 IEnumConnections **ppEnum)
979 return E_FAIL;
982 static const IEnumConnectionsVtbl enum_vtbl = {
984 Enum_QueryInterface,
985 Enum_AddRef,
986 Enum_Release,
987 Enum_Next,
988 Enum_Skip,
989 Enum_Reset,
990 Enum_Clone
993 static HRESULT WINAPI ConPt_QueryInterface(
994 IConnectionPoint* This,
995 REFIID riid,
996 void **ppvObject)
998 *ppvObject = NULL;
1000 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IConnectionPoint))
1002 *ppvObject = This;
1005 if (*ppvObject)
1007 IUnknown_AddRef(This);
1008 return S_OK;
1011 trace("no interface\n");
1012 return E_NOINTERFACE;
1015 static ULONG WINAPI ConPt_AddRef(
1016 IConnectionPoint* This)
1018 ConPt *iface = (ConPt*)This;
1019 return InterlockedIncrement(&iface->refCount);
1022 static ULONG WINAPI ConPt_Release(
1023 IConnectionPoint* This)
1025 ConPt *iface = (ConPt*)This;
1026 ULONG ret;
1028 ret = InterlockedDecrement(&iface->refCount);
1029 if (ret == 0)
1031 if (iface->sinkCount > 0)
1033 int i;
1034 for (i = 0; i < iface->sinkCount; i++)
1036 if (iface->sink[i])
1037 IUnknown_Release(iface->sink[i]);
1039 HeapFree(GetProcessHeap(),0,iface->sink);
1041 HeapFree(GetProcessHeap(),0,This);
1043 return ret;
1046 static HRESULT WINAPI ConPt_GetConnectionInterface(
1047 IConnectionPoint* This,
1048 IID *pIID)
1050 static int i = 0;
1051 ConPt *iface = (ConPt*)This;
1052 if (i==0)
1054 i++;
1055 return E_FAIL;
1057 else
1058 memcpy(pIID,&iface->id,sizeof(GUID));
1059 return S_OK;
1062 static HRESULT WINAPI ConPt_GetConnectionPointContainer(
1063 IConnectionPoint* This,
1064 IConnectionPointContainer **ppCPC)
1066 ConPt *iface = (ConPt*)This;
1068 *ppCPC = (IConnectionPointContainer*)iface->container;
1069 return S_OK;
1072 static HRESULT WINAPI ConPt_Advise(
1073 IConnectionPoint* This,
1074 IUnknown *pUnkSink,
1075 DWORD *pdwCookie)
1077 ConPt *iface = (ConPt*)This;
1079 if (iface->sinkCount == 0)
1080 iface->sink = HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown*));
1081 else
1082 iface->sink = HeapReAlloc(GetProcessHeap(),0,iface->sink,sizeof(IUnknown*)*(iface->sinkCount+1));
1083 iface->sink[iface->sinkCount] = pUnkSink;
1084 IUnknown_AddRef(pUnkSink);
1085 iface->sinkCount++;
1086 *pdwCookie = iface->sinkCount;
1087 return S_OK;
1090 static HRESULT WINAPI ConPt_Unadvise(
1091 IConnectionPoint* This,
1092 DWORD dwCookie)
1094 ConPt *iface = (ConPt*)This;
1096 if (dwCookie > iface->sinkCount)
1097 return E_FAIL;
1098 else
1100 IUnknown_Release(iface->sink[dwCookie-1]);
1101 iface->sink[dwCookie-1] = NULL;
1103 return S_OK;
1106 static HRESULT WINAPI ConPt_EnumConnections(
1107 IConnectionPoint* This,
1108 IEnumConnections **ppEnum)
1110 EnumCon *ec;
1112 ec = HeapAlloc(GetProcessHeap(),0,sizeof(EnumCon));
1113 ec->vtbl = &enum_vtbl;
1114 ec->refCount = 1;
1115 ec->pt = (ConPt*)This;
1116 ec->idx = 0;
1117 *ppEnum = (IEnumConnections*)ec;
1119 return S_OK;
1122 static const IConnectionPointVtbl point_vtbl = {
1123 ConPt_QueryInterface,
1124 ConPt_AddRef,
1125 ConPt_Release,
1127 ConPt_GetConnectionInterface,
1128 ConPt_GetConnectionPointContainer,
1129 ConPt_Advise,
1130 ConPt_Unadvise,
1131 ConPt_EnumConnections
1134 static HRESULT WINAPI EnumPt_QueryInterface(
1135 IEnumConnectionPoints* This,
1136 REFIID riid,
1137 void **ppvObject)
1139 *ppvObject = NULL;
1141 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IEnumConnectionPoints))
1143 *ppvObject = This;
1146 if (*ppvObject)
1148 IUnknown_AddRef(This);
1149 return S_OK;
1152 trace("no interface\n");
1153 return E_NOINTERFACE;
1156 static ULONG WINAPI EnumPt_AddRef(IEnumConnectionPoints* This)
1158 EnumPt *iface = (EnumPt*)This;
1159 return InterlockedIncrement(&iface->refCount);
1162 static ULONG WINAPI EnumPt_Release(IEnumConnectionPoints* This)
1164 EnumPt *iface = (EnumPt*)This;
1165 ULONG ret;
1167 ret = InterlockedDecrement(&iface->refCount);
1168 if (ret == 0)
1169 HeapFree(GetProcessHeap(),0,This);
1170 return ret;
1173 static HRESULT WINAPI EnumPt_Next(
1174 IEnumConnectionPoints* This,
1175 ULONG cConnections,
1176 IConnectionPoint **rgcd,
1177 ULONG *pcFetched)
1179 EnumPt *iface = (EnumPt*)This;
1181 if (cConnections > 0 && iface->idx < iface->container->ptCount)
1183 *rgcd = iface->container->pt[iface->idx];
1184 IUnknown_AddRef(iface->container->pt[iface->idx]);
1185 if (pcFetched)
1186 *pcFetched = 1;
1187 iface->idx++;
1188 return S_OK;
1191 return E_FAIL;
1194 static HRESULT WINAPI EnumPt_Skip(
1195 IEnumConnectionPoints* This,
1196 ULONG cConnections)
1198 return E_FAIL;
1201 static HRESULT WINAPI EnumPt_Reset(
1202 IEnumConnectionPoints* This)
1204 return E_FAIL;
1207 static HRESULT WINAPI EnumPt_Clone(
1208 IEnumConnectionPoints* This,
1209 IEnumConnectionPoints **ppEnumPt)
1211 return E_FAIL;
1214 static const IEnumConnectionPointsVtbl enumpt_vtbl = {
1216 EnumPt_QueryInterface,
1217 EnumPt_AddRef,
1218 EnumPt_Release,
1219 EnumPt_Next,
1220 EnumPt_Skip,
1221 EnumPt_Reset,
1222 EnumPt_Clone
1225 static HRESULT WINAPI Contain_QueryInterface(
1226 IConnectionPointContainer* This,
1227 REFIID riid,
1228 void **ppvObject)
1230 *ppvObject = NULL;
1232 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IConnectionPointContainer))
1234 *ppvObject = This;
1237 if (*ppvObject)
1239 IUnknown_AddRef(This);
1240 return S_OK;
1243 trace("no interface\n");
1244 return E_NOINTERFACE;
1247 static ULONG WINAPI Contain_AddRef(
1248 IConnectionPointContainer* This)
1250 Contain *iface = (Contain*)This;
1251 return InterlockedIncrement(&iface->refCount);
1254 static ULONG WINAPI Contain_Release(
1255 IConnectionPointContainer* This)
1257 Contain *iface = (Contain*)This;
1258 ULONG ret;
1260 ret = InterlockedDecrement(&iface->refCount);
1261 if (ret == 0)
1263 if (iface->ptCount > 0)
1265 int i;
1266 for (i = 0; i < iface->ptCount; i++)
1267 IUnknown_Release(iface->pt[i]);
1268 HeapFree(GetProcessHeap(),0,iface->pt);
1270 HeapFree(GetProcessHeap(),0,This);
1272 return ret;
1275 static HRESULT WINAPI Contain_EnumConnectionPoints(
1276 IConnectionPointContainer* This,
1277 IEnumConnectionPoints **ppEnum)
1279 EnumPt *ec;
1281 ec = HeapAlloc(GetProcessHeap(),0,sizeof(EnumPt));
1282 ec->vtbl = &enumpt_vtbl;
1283 ec->refCount = 1;
1284 ec->idx= 0;
1285 ec->container = (Contain*)This;
1286 *ppEnum = (IEnumConnectionPoints*)ec;
1288 return S_OK;
1291 static HRESULT WINAPI Contain_FindConnectionPoint(
1292 IConnectionPointContainer* This,
1293 REFIID riid,
1294 IConnectionPoint **ppCP)
1296 Contain *iface = (Contain*)This;
1297 ConPt *pt;
1299 if (!IsEqualIID(riid, &IID_NULL) || iface->ptCount ==0)
1301 pt = HeapAlloc(GetProcessHeap(),0,sizeof(ConPt));
1302 pt->vtbl = &point_vtbl;
1303 pt->refCount = 1;
1304 pt->sinkCount = 0;
1305 pt->sink = NULL;
1306 pt->container = iface;
1307 pt->id = IID_IDispatch;
1309 if (iface->ptCount == 0)
1310 iface->pt =HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown*));
1311 else
1312 iface->pt = HeapReAlloc(GetProcessHeap(),0,iface->pt,sizeof(IUnknown*)*(iface->ptCount+1));
1313 iface->pt[iface->ptCount] = (IConnectionPoint*)pt;
1314 iface->ptCount++;
1316 *ppCP = (IConnectionPoint*)pt;
1318 else
1320 *ppCP = iface->pt[0];
1321 IUnknown_AddRef((IUnknown*)*ppCP);
1324 return S_OK;
1327 static const IConnectionPointContainerVtbl contain_vtbl = {
1328 Contain_QueryInterface,
1329 Contain_AddRef,
1330 Contain_Release,
1332 Contain_EnumConnectionPoints,
1333 Contain_FindConnectionPoint
1336 static void test_IConnectionPoint(void)
1338 HRESULT rc;
1339 ULONG ref;
1340 IConnectionPoint *point;
1341 Contain *container;
1342 Disp *dispatch;
1343 DWORD cookie = 0xffffffff;
1344 DISPPARAMS params;
1345 VARIANT vars[10];
1347 if (!pIConnectionPoint_SimpleInvoke || !pConnectToConnectionPoint)
1349 win_skip("IConnectionPoint Apis not present\n");
1350 return;
1353 container = HeapAlloc(GetProcessHeap(),0,sizeof(Contain));
1354 container->vtbl = &contain_vtbl;
1355 container->refCount = 1;
1356 container->ptCount = 0;
1357 container->pt = NULL;
1359 dispatch = HeapAlloc(GetProcessHeap(),0,sizeof(Disp));
1360 dispatch->vtbl = &disp_vtbl;
1361 dispatch->refCount = 1;
1363 rc = pConnectToConnectionPoint((IUnknown*)dispatch, &IID_NULL, TRUE, (IUnknown*)container, &cookie, &point);
1364 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
1365 ok(point != NULL, "returned ConnectionPoint is NULL\n");
1366 ok(cookie != 0xffffffff, "invalid cookie returned\n");
1368 rc = pIConnectionPoint_SimpleInvoke(point,0xa0,NULL);
1369 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
1371 if (pSHPackDispParams)
1373 memset(&params, 0xc0, sizeof(params));
1374 memset(vars, 0xc0, sizeof(vars));
1375 rc = pSHPackDispParams(&params, vars, 2, VT_I4, 0xdeadbeef, VT_BSTR, 0xdeadcafe);
1376 ok(rc == S_OK, "SHPackDispParams failed: %08x\n", rc);
1378 rc = pIConnectionPoint_SimpleInvoke(point,0xa1,&params);
1379 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
1381 else
1382 win_skip("pSHPackDispParams not present\n");
1384 rc = pConnectToConnectionPoint(NULL, &IID_NULL, FALSE, (IUnknown*)container, &cookie, NULL);
1385 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
1387 /* MSDN says this should be required but it crashs on XP
1388 IUnknown_Release(point);
1390 ref = IUnknown_Release((IUnknown*)container);
1391 ok(ref == 0, "leftover IConnectionPointContainer reference %i\n",ref);
1392 ref = IUnknown_Release((IUnknown*)dispatch);
1393 ok(ref == 0, "leftover IDispatch reference %i\n",ref);
1396 typedef struct _propbag
1398 const IPropertyBagVtbl *vtbl;
1399 LONG refCount;
1401 } PropBag;
1404 static HRESULT WINAPI Prop_QueryInterface(
1405 IPropertyBag* This,
1406 REFIID riid,
1407 void **ppvObject)
1409 *ppvObject = NULL;
1411 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IPropertyBag))
1413 *ppvObject = This;
1416 if (*ppvObject)
1418 IUnknown_AddRef(This);
1419 return S_OK;
1422 trace("no interface\n");
1423 return E_NOINTERFACE;
1426 static ULONG WINAPI Prop_AddRef(
1427 IPropertyBag* This)
1429 PropBag *iface = (PropBag*)This;
1430 return InterlockedIncrement(&iface->refCount);
1433 static ULONG WINAPI Prop_Release(
1434 IPropertyBag* This)
1436 PropBag *iface = (PropBag*)This;
1437 ULONG ret;
1439 ret = InterlockedDecrement(&iface->refCount);
1440 if (ret == 0)
1441 HeapFree(GetProcessHeap(),0,This);
1442 return ret;
1445 static HRESULT WINAPI Prop_Read(
1446 IPropertyBag* This,
1447 LPCOLESTR pszPropName,
1448 VARIANT *pVar,
1449 IErrorLog *pErrorLog)
1451 V_VT(pVar) = VT_BLOB|VT_BYREF;
1452 V_BYREF(pVar) = (LPVOID)0xdeadcafe;
1453 return S_OK;
1456 static HRESULT WINAPI Prop_Write(
1457 IPropertyBag* This,
1458 LPCOLESTR pszPropName,
1459 VARIANT *pVar)
1461 return S_OK;
1465 static const IPropertyBagVtbl prop_vtbl = {
1466 Prop_QueryInterface,
1467 Prop_AddRef,
1468 Prop_Release,
1470 Prop_Read,
1471 Prop_Write
1474 static void test_SHPropertyBag_ReadLONG(void)
1476 PropBag *pb;
1477 HRESULT rc;
1478 LONG out;
1479 static const WCHAR szName1[] = {'n','a','m','e','1',0};
1481 if (!pSHPropertyBag_ReadLONG)
1483 win_skip("SHPropertyBag_ReadLONG not present\n");
1484 return;
1487 pb = HeapAlloc(GetProcessHeap(),0,sizeof(PropBag));
1488 pb->refCount = 1;
1489 pb->vtbl = &prop_vtbl;
1491 out = 0xfeedface;
1492 rc = pSHPropertyBag_ReadLONG(NULL, szName1, &out);
1493 ok(rc == E_INVALIDARG || broken(rc == 0), "incorrect return %x\n",rc);
1494 ok(out == 0xfeedface, "value should not have changed\n");
1495 rc = pSHPropertyBag_ReadLONG((IPropertyBag*)pb, NULL, &out);
1496 ok(rc == E_INVALIDARG || broken(rc == 0) || broken(rc == 1), "incorrect return %x\n",rc);
1497 ok(out == 0xfeedface, "value should not have changed\n");
1498 rc = pSHPropertyBag_ReadLONG((IPropertyBag*)pb, szName1, NULL);
1499 ok(rc == E_INVALIDARG || broken(rc == 0) || broken(rc == 1), "incorrect return %x\n",rc);
1500 ok(out == 0xfeedface, "value should not have changed\n");
1501 rc = pSHPropertyBag_ReadLONG((IPropertyBag*)pb, szName1, &out);
1502 ok(rc == DISP_E_BADVARTYPE || broken(rc == 0) || broken(rc == 1), "incorrect return %x\n",rc);
1503 ok(out == 0xfeedface || broken(out == 0xfeedfa00), "value should not have changed %x\n",out);
1504 IUnknown_Release((IUnknown*)pb);
1509 static void test_SHSetWindowBits(void)
1511 HWND hwnd;
1512 DWORD style, styleold;
1513 WNDCLASSA clsA;
1515 if(!pSHSetWindowBits)
1517 win_skip("SHSetWindowBits is not available\n");
1518 return;
1521 clsA.style = 0;
1522 clsA.lpfnWndProc = DefWindowProcA;
1523 clsA.cbClsExtra = 0;
1524 clsA.cbWndExtra = 0;
1525 clsA.hInstance = GetModuleHandleA(NULL);
1526 clsA.hIcon = 0;
1527 clsA.hCursor = LoadCursorA(0, IDC_ARROW);
1528 clsA.hbrBackground = NULL;
1529 clsA.lpszMenuName = NULL;
1530 clsA.lpszClassName = "Shlwapi test class";
1531 RegisterClassA(&clsA);
1533 hwnd = CreateWindowA("Shlwapi test class", "Test", WS_VISIBLE, 0, 0, 100, 100,
1534 NULL, NULL, GetModuleHandle(NULL), 0);
1535 ok(IsWindow(hwnd), "failed to create window\n");
1537 /* null window */
1538 SetLastError(0xdeadbeef);
1539 style = pSHSetWindowBits(NULL, GWL_STYLE, 0, 0);
1540 ok(style == 0, "expected 0 retval, got %d\n", style);
1541 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE ||
1542 broken(GetLastError() == 0xdeadbeef), /* Win9x/WinMe */
1543 "expected ERROR_INVALID_WINDOW_HANDLE, got %d\n", GetLastError());
1545 /* zero mask, zero flags */
1546 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1547 style = pSHSetWindowBits(hwnd, GWL_STYLE, 0, 0);
1548 ok(styleold == style, "expected old style\n");
1549 ok(styleold == GetWindowLongA(hwnd, GWL_STYLE), "expected to keep old style\n");
1551 /* test mask */
1552 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1553 ok(styleold & WS_VISIBLE, "expected WS_VISIBLE\n");
1554 style = pSHSetWindowBits(hwnd, GWL_STYLE, WS_VISIBLE, 0);
1556 ok(style == styleold, "expected previous style, got %x\n", style);
1557 ok((GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE) == 0, "expected updated style\n");
1559 /* test mask, unset style bit used */
1560 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1561 style = pSHSetWindowBits(hwnd, GWL_STYLE, WS_VISIBLE, 0);
1562 ok(style == styleold, "expected previous style, got %x\n", style);
1563 ok(styleold == GetWindowLongA(hwnd, GWL_STYLE), "expected to keep old style\n");
1565 /* set back with flags */
1566 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1567 style = pSHSetWindowBits(hwnd, GWL_STYLE, WS_VISIBLE, WS_VISIBLE);
1568 ok(style == styleold, "expected previous style, got %x\n", style);
1569 ok(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE, "expected updated style\n");
1571 /* reset and try to set without a mask */
1572 pSHSetWindowBits(hwnd, GWL_STYLE, WS_VISIBLE, 0);
1573 ok((GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE) == 0, "expected updated style\n");
1574 styleold = GetWindowLongA(hwnd, GWL_STYLE);
1575 style = pSHSetWindowBits(hwnd, GWL_STYLE, 0, WS_VISIBLE);
1576 ok(style == styleold, "expected previous style, got %x\n", style);
1577 ok((GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE) == 0, "expected updated style\n");
1579 DestroyWindow(hwnd);
1581 UnregisterClassA("Shlwapi test class", GetModuleHandleA(NULL));
1584 static void test_SHFormatDateTimeA(void)
1586 FILETIME UNALIGNED filetime;
1587 CHAR buff[100], buff2[100], buff3[100];
1588 SYSTEMTIME st;
1589 DWORD flags;
1590 INT ret;
1592 if(!pSHFormatDateTimeA)
1594 win_skip("pSHFormatDateTimeA isn't available\n");
1595 return;
1598 if (0)
1600 /* crashes on native */
1601 ret = pSHFormatDateTimeA(NULL, NULL, NULL, 0);
1604 GetLocalTime(&st);
1605 SystemTimeToFileTime(&st, &filetime);
1606 /* SHFormatDateTime expects input as utc */
1607 LocalFileTimeToFileTime(&filetime, &filetime);
1609 /* no way to get required buffer length here */
1610 SetLastError(0xdeadbeef);
1611 ret = pSHFormatDateTimeA(&filetime, NULL, NULL, 0);
1612 ok(ret == 0, "got %d\n", ret);
1613 ok(GetLastError() == 0xdeadbeef || broken(GetLastError() == ERROR_SUCCESS /* Win7 */),
1614 "expected 0xdeadbeef, got %d\n", GetLastError());
1616 SetLastError(0xdeadbeef);
1617 buff[0] = 'a'; buff[1] = 0;
1618 ret = pSHFormatDateTimeA(&filetime, NULL, buff, 0);
1619 ok(ret == 0, "got %d\n", ret);
1620 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1621 ok(buff[0] == 'a', "expected same string, got %s\n", buff);
1623 /* flags needs to have FDTF_NOAUTOREADINGORDER for these tests to succeed on Vista+ */
1625 /* all combinations documented as invalid succeeded */
1626 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTTIME | FDTF_LONGTIME;
1627 SetLastError(0xdeadbeef);
1628 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1629 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1630 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1632 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTDATE | FDTF_LONGDATE;
1633 SetLastError(0xdeadbeef);
1634 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1635 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1636 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1638 flags = FDTF_SHORTDATE | FDTF_LTRDATE | FDTF_RTLDATE;
1639 SetLastError(0xdeadbeef);
1640 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1641 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1642 ok(GetLastError() == 0xdeadbeef ||
1643 broken(GetLastError() == ERROR_INVALID_FLAGS), /* Win9x/WinMe */
1644 "expected 0xdeadbeef, got %d\n", GetLastError());
1646 /* now check returned strings */
1647 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTTIME;
1648 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1649 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1650 ret = GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff2, sizeof(buff2));
1651 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1652 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1654 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGTIME;
1655 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1656 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1657 ret = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2));
1658 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1659 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1661 /* both time flags */
1662 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGTIME | FDTF_SHORTTIME;
1663 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1664 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1665 ret = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2));
1666 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1667 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1669 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTDATE;
1670 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1671 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1672 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2));
1673 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1674 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1676 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGDATE;
1677 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1678 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1679 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
1680 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1681 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1683 /* both date flags */
1684 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGDATE | FDTF_SHORTDATE;
1685 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1686 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1687 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
1688 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1689 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1691 /* various combinations of date/time flags */
1692 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGDATE | FDTF_SHORTTIME;
1693 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1694 ok(ret == lstrlenA(buff)+1, "got %d, length %d\n", ret, lstrlenA(buff)+1);
1695 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
1696 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1697 strcat(buff2, ", ");
1698 ret = GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3));
1699 ok(ret == lstrlenA(buff3)+1, "got %d\n", ret);
1700 strcat(buff2, buff3);
1701 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1703 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGDATE | FDTF_LONGTIME;
1704 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1705 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1706 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
1707 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1708 strcat(buff2, ", ");
1709 ret = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3));
1710 ok(ret == lstrlenA(buff3)+1, "got %d\n", ret);
1711 strcat(buff2, buff3);
1712 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1714 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTDATE | FDTF_SHORTTIME;
1715 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1716 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1717 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2));
1718 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1719 strcat(buff2, " ");
1720 ret = GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3));
1721 ok(ret == lstrlenA(buff3)+1, "got %d\n", ret);
1722 strcat(buff2, buff3);
1723 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1725 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTDATE | FDTF_LONGTIME;
1726 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
1727 ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
1728 ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2));
1729 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
1730 strcat(buff2, " ");
1731 ret = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3));
1732 ok(ret == lstrlenA(buff3)+1, "got %d\n", ret);
1733 strcat(buff2, buff3);
1734 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
1737 static void test_SHFormatDateTimeW(void)
1739 FILETIME UNALIGNED filetime;
1740 WCHAR buff[100], buff2[100], buff3[100];
1741 SYSTEMTIME st;
1742 DWORD flags;
1743 INT ret;
1744 static const WCHAR spaceW[] = {' ',0};
1745 static const WCHAR commaW[] = {',',' ',0};
1747 if(!pSHFormatDateTimeW)
1749 win_skip("pSHFormatDateTimeW isn't available\n");
1750 return;
1753 if (0)
1755 /* crashes on native */
1756 ret = pSHFormatDateTimeW(NULL, NULL, NULL, 0);
1759 GetLocalTime(&st);
1760 SystemTimeToFileTime(&st, &filetime);
1761 /* SHFormatDateTime expects input as utc */
1762 LocalFileTimeToFileTime(&filetime, &filetime);
1764 /* no way to get required buffer length here */
1765 SetLastError(0xdeadbeef);
1766 ret = pSHFormatDateTimeW(&filetime, NULL, NULL, 0);
1767 ok(ret == 0, "got %d\n", ret);
1768 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1770 SetLastError(0xdeadbeef);
1771 buff[0] = 'a'; buff[1] = 0;
1772 ret = pSHFormatDateTimeW(&filetime, NULL, buff, 0);
1773 ok(ret == 0, "got %d\n", ret);
1774 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1775 ok(buff[0] == 'a', "expected same string\n");
1777 /* all combinations documented as invalid succeeded */
1778 flags = FDTF_SHORTTIME | FDTF_LONGTIME;
1779 SetLastError(0xdeadbeef);
1780 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1781 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1782 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1784 flags = FDTF_SHORTDATE | FDTF_LONGDATE;
1785 SetLastError(0xdeadbeef);
1786 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1787 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1788 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1790 flags = FDTF_SHORTDATE | FDTF_LTRDATE | FDTF_RTLDATE;
1791 SetLastError(0xdeadbeef);
1792 buff[0] = 0; /* NT4 doesn't clear the buffer on failure */
1793 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1794 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1795 ok(GetLastError() == 0xdeadbeef ||
1796 broken(GetLastError() == ERROR_INVALID_FLAGS), /* Win9x/WinMe/NT4 */
1797 "expected 0xdeadbeef, got %d\n", GetLastError());
1799 /* now check returned strings */
1800 flags = FDTF_SHORTTIME;
1801 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1802 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1803 SetLastError(0xdeadbeef);
1804 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1805 if (ret == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1807 win_skip("Needed W-functions are not implemented\n");
1808 return;
1810 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1811 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1813 flags = FDTF_LONGTIME;
1814 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1815 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1816 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1817 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1818 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1820 /* both time flags */
1821 flags = FDTF_LONGTIME | FDTF_SHORTTIME;
1822 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1823 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1824 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1825 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1826 ok(lstrcmpW(buff, buff2) == 0, "expected equal string\n");
1828 flags = FDTF_SHORTDATE;
1829 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1830 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1831 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1832 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1833 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1835 flags = FDTF_LONGDATE;
1836 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1837 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1838 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1839 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1840 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1842 /* both date flags */
1843 flags = FDTF_LONGDATE | FDTF_SHORTDATE;
1844 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1845 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1846 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1847 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1848 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1850 /* various combinations of date/time flags */
1851 flags = FDTF_LONGDATE | FDTF_SHORTTIME;
1852 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1853 ok(ret == lstrlenW(buff)+1, "got %d, length %d\n", ret, lstrlenW(buff)+1);
1854 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1855 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1856 lstrcatW(buff2, commaW);
1857 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
1858 ok(ret == lstrlenW(buff3)+1, "got %d\n", ret);
1859 lstrcatW(buff2, buff3);
1860 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1862 flags = FDTF_LONGDATE | FDTF_LONGTIME;
1863 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1864 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1865 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1866 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1867 lstrcatW(buff2, commaW);
1868 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
1869 ok(ret == lstrlenW(buff3)+1, "got %d\n", ret);
1870 lstrcatW(buff2, buff3);
1871 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1873 flags = FDTF_SHORTDATE | FDTF_SHORTTIME;
1874 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1875 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1876 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1877 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1878 lstrcatW(buff2, spaceW);
1879 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
1880 ok(ret == lstrlenW(buff3)+1, "got %d\n", ret);
1881 lstrcatW(buff2, buff3);
1882 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1884 flags = FDTF_SHORTDATE | FDTF_LONGTIME;
1885 ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
1886 ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
1887 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
1888 ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
1889 lstrcatW(buff2, spaceW);
1890 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
1891 ok(ret == lstrlenW(buff3)+1, "got %d\n", ret);
1892 lstrcatW(buff2, buff3);
1893 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
1896 static void test_SHGetObjectCompatFlags(void)
1898 struct compat_value {
1899 CHAR nameA[30];
1900 DWORD value;
1903 struct compat_value values[] = {
1904 { "OTNEEDSSFCACHE", 0x1 },
1905 { "NO_WEBVIEW", 0x2 },
1906 { "UNBINDABLE", 0x4 },
1907 { "PINDLL", 0x8 },
1908 { "NEEDSFILESYSANCESTOR", 0x10 },
1909 { "NOTAFILESYSTEM", 0x20 },
1910 { "CTXMENU_NOVERBS", 0x40 },
1911 { "CTXMENU_LIMITEDQI", 0x80 },
1912 { "COCREATESHELLFOLDERONLY", 0x100 },
1913 { "NEEDSSTORAGEANCESTOR", 0x200 },
1914 { "NOLEGACYWEBVIEW", 0x400 },
1915 { "CTXMENU_XPQCMFLAGS", 0x1000 },
1916 { "NOIPROPERTYSTORE", 0x2000 }
1919 static const char compat_path[] = "Software\\Microsoft\\Windows\\CurrentVersion\\ShellCompatibility\\Objects";
1920 void *pColorAdjustLuma = GetProcAddress(hShlwapi, "ColorAdjustLuma");
1921 CHAR keyA[39]; /* {CLSID} */
1922 HKEY root;
1923 DWORD ret;
1924 int i;
1926 if (!pSHGetObjectCompatFlags)
1928 win_skip("SHGetObjectCompatFlags isn't available\n");
1929 return;
1932 if (pColorAdjustLuma && pColorAdjustLuma == pSHGetObjectCompatFlags) /* win2k */
1934 win_skip("Skipping SHGetObjectCompatFlags, same ordinal used for ColorAdjustLuma\n");
1935 return;
1938 /* null args */
1939 ret = pSHGetObjectCompatFlags(NULL, NULL);
1940 ok(ret == 0, "got %d\n", ret);
1942 ret = RegOpenKeyA(HKEY_LOCAL_MACHINE, compat_path, &root);
1943 if (ret != ERROR_SUCCESS)
1945 skip("No compatibility class data found\n");
1946 return;
1949 for (i = 0; RegEnumKeyA(root, i, keyA, sizeof(keyA)) == ERROR_SUCCESS; i++)
1951 HKEY clsid_key;
1953 if (RegOpenKeyA(root, keyA, &clsid_key) == ERROR_SUCCESS)
1955 CHAR valueA[30];
1956 DWORD expected = 0, got, length = sizeof(valueA);
1957 CLSID clsid;
1958 int v;
1960 for (v = 0; RegEnumValueA(clsid_key, v, valueA, &length, NULL, NULL, NULL, NULL) == ERROR_SUCCESS; v++)
1962 int j;
1964 for (j = 0; j < sizeof(values)/sizeof(struct compat_value); j++)
1965 if (lstrcmpA(values[j].nameA, valueA) == 0)
1967 expected |= values[j].value;
1968 break;
1971 length = sizeof(valueA);
1974 pGUIDFromStringA(keyA, &clsid);
1975 got = pSHGetObjectCompatFlags(NULL, &clsid);
1976 ok(got == expected, "got 0x%08x, expected 0x%08x. Key %s\n", got, expected, keyA);
1978 RegCloseKey(clsid_key);
1982 RegCloseKey(root);
1985 typedef struct {
1986 const IOleCommandTargetVtbl *lpVtbl;
1987 LONG ref;
1988 } IOleCommandTargetImpl;
1990 static const IOleCommandTargetVtbl IOleCommandTargetImpl_Vtbl;
1992 static IOleCommandTarget* IOleCommandTargetImpl_Construct(void)
1994 IOleCommandTargetImpl *obj;
1996 obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*obj));
1997 obj->lpVtbl = &IOleCommandTargetImpl_Vtbl;
1998 obj->ref = 1;
2000 return (IOleCommandTarget*)obj;
2003 static HRESULT WINAPI IOleCommandTargetImpl_QueryInterface(IOleCommandTarget *iface, REFIID riid, void **ppvObj)
2005 IOleCommandTargetImpl *This = (IOleCommandTargetImpl *)iface;
2007 if (IsEqualIID(riid, &IID_IUnknown) ||
2008 IsEqualIID(riid, &IID_IOleCommandTarget))
2010 *ppvObj = This;
2013 if(*ppvObj)
2015 IUnknown_AddRef(iface);
2016 return S_OK;
2019 return E_NOINTERFACE;
2022 static ULONG WINAPI IOleCommandTargetImpl_AddRef(IOleCommandTarget *iface)
2024 IOleCommandTargetImpl *This = (IOleCommandTargetImpl *)iface;
2025 return InterlockedIncrement(&This->ref);
2028 static ULONG WINAPI IOleCommandTargetImpl_Release(IOleCommandTarget *iface)
2030 IOleCommandTargetImpl *This = (IOleCommandTargetImpl *)iface;
2031 ULONG ref = InterlockedDecrement(&This->ref);
2033 if (!ref)
2035 HeapFree(GetProcessHeap(), 0, This);
2036 return 0;
2038 return ref;
2041 static HRESULT WINAPI IOleCommandTargetImpl_QueryStatus(
2042 IOleCommandTarget *iface, const GUID *group, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText)
2044 return E_NOTIMPL;
2047 static HRESULT WINAPI IOleCommandTargetImpl_Exec(
2048 IOleCommandTarget *iface,
2049 const GUID *CmdGroup,
2050 DWORD nCmdID,
2051 DWORD nCmdexecopt,
2052 VARIANT *pvaIn,
2053 VARIANT *pvaOut)
2055 add_call(&trace_got, 3, CmdGroup, (void*)(DWORD_PTR)nCmdID, (void*)(DWORD_PTR)nCmdexecopt, pvaIn, pvaOut);
2056 return S_OK;
2059 static const IOleCommandTargetVtbl IOleCommandTargetImpl_Vtbl =
2061 IOleCommandTargetImpl_QueryInterface,
2062 IOleCommandTargetImpl_AddRef,
2063 IOleCommandTargetImpl_Release,
2064 IOleCommandTargetImpl_QueryStatus,
2065 IOleCommandTargetImpl_Exec
2068 typedef struct {
2069 const IServiceProviderVtbl *lpVtbl;
2070 LONG ref;
2071 } IServiceProviderImpl;
2073 typedef struct {
2074 const IProfferServiceVtbl *lpVtbl;
2075 LONG ref;
2076 } IProfferServiceImpl;
2079 static const IServiceProviderVtbl IServiceProviderImpl_Vtbl;
2080 static const IProfferServiceVtbl IProfferServiceImpl_Vtbl;
2082 static IServiceProvider* IServiceProviderImpl_Construct(void)
2084 IServiceProviderImpl *obj;
2086 obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*obj));
2087 obj->lpVtbl = &IServiceProviderImpl_Vtbl;
2088 obj->ref = 1;
2090 return (IServiceProvider*)obj;
2093 static IProfferService* IProfferServiceImpl_Construct(void)
2095 IProfferServiceImpl *obj;
2097 obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*obj));
2098 obj->lpVtbl = &IProfferServiceImpl_Vtbl;
2099 obj->ref = 1;
2101 return (IProfferService*)obj;
2104 static HRESULT WINAPI IServiceProviderImpl_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppvObj)
2106 IServiceProviderImpl *This = (IServiceProviderImpl *)iface;
2108 if (IsEqualIID(riid, &IID_IUnknown) ||
2109 IsEqualIID(riid, &IID_IServiceProvider))
2111 *ppvObj = This;
2114 if(*ppvObj)
2116 IUnknown_AddRef(iface);
2117 /* native uses redefined IID_IServiceProvider symbol, so we can't compare pointers */
2118 if (IsEqualIID(riid, &IID_IServiceProvider))
2119 add_call(&trace_got, 1, iface, &IID_IServiceProvider, 0, 0, 0);
2120 return S_OK;
2123 return E_NOINTERFACE;
2126 static ULONG WINAPI IServiceProviderImpl_AddRef(IServiceProvider *iface)
2128 IServiceProviderImpl *This = (IServiceProviderImpl *)iface;
2129 return InterlockedIncrement(&This->ref);
2132 static ULONG WINAPI IServiceProviderImpl_Release(IServiceProvider *iface)
2134 IServiceProviderImpl *This = (IServiceProviderImpl *)iface;
2135 ULONG ref = InterlockedDecrement(&This->ref);
2137 if (!ref)
2139 HeapFree(GetProcessHeap(), 0, This);
2140 return 0;
2142 return ref;
2145 static HRESULT WINAPI IServiceProviderImpl_QueryService(
2146 IServiceProvider *iface, REFGUID service, REFIID riid, void **ppv)
2148 /* native uses redefined pointer for IID_IOleCommandTarget, not one from uuid.lib */
2149 if (IsEqualIID(riid, &IID_IOleCommandTarget))
2151 add_call(&trace_got, 2, iface, service, &IID_IOleCommandTarget, 0, 0);
2152 *ppv = IOleCommandTargetImpl_Construct();
2154 if (IsEqualIID(riid, &IID_IProfferService))
2156 if (IsEqualIID(service, &IID_IProfferService))
2157 add_call(&trace_got, 2, &IID_IProfferService, &IID_IProfferService, 0, 0, 0);
2158 *ppv = IProfferServiceImpl_Construct();
2160 return S_OK;
2163 static const IServiceProviderVtbl IServiceProviderImpl_Vtbl =
2165 IServiceProviderImpl_QueryInterface,
2166 IServiceProviderImpl_AddRef,
2167 IServiceProviderImpl_Release,
2168 IServiceProviderImpl_QueryService
2171 static void test_IUnknown_QueryServiceExec(void)
2173 IServiceProvider *provider = IServiceProviderImpl_Construct();
2174 static const GUID dummy_serviceid = { 0xdeadbeef };
2175 static const GUID dummy_groupid = { 0xbeefbeef };
2176 call_trace_t trace_expected;
2177 HRESULT hr;
2179 /* on <=W2K platforms same ordinal used for another export with different
2180 prototype, so skipping using this indirect condition */
2181 if (is_win2k_and_lower)
2183 win_skip("IUnknown_QueryServiceExec is not available\n");
2184 return;
2187 /* null source pointer */
2188 hr = pIUnknown_QueryServiceExec(NULL, &dummy_serviceid, &dummy_groupid, 0, 0, 0, 0);
2189 ok(hr == E_FAIL, "got 0x%08x\n", hr);
2191 /* expected trace:
2192 IUnknown_QueryServiceExec( ptr1, serviceid, groupid, arg1, arg2, arg3, arg4);
2193 -> IUnknown_QueryInterface( ptr1, &IID_IServiceProvider, &prov );
2194 -> IServiceProvider_QueryService( prov, serviceid, &IID_IOleCommandTarget, &obj );
2195 -> IOleCommandTarget_Exec( obj, groupid, arg1, arg2, arg3, arg4 );
2197 init_call_trace(&trace_expected);
2199 add_call(&trace_expected, 1, provider, &IID_IServiceProvider, 0, 0, 0);
2200 add_call(&trace_expected, 2, provider, &dummy_serviceid, &IID_IOleCommandTarget, 0, 0);
2201 add_call(&trace_expected, 3, &dummy_groupid, (void*)0x1, (void*)0x2, (void*)0x3, (void*)0x4);
2203 init_call_trace(&trace_got);
2204 hr = pIUnknown_QueryServiceExec((IUnknown*)provider, &dummy_serviceid, &dummy_groupid, 0x1, 0x2, (void*)0x3, (void*)0x4);
2205 ok(hr == S_OK, "got 0x%08x\n", hr);
2207 ok_trace(&trace_expected, &trace_got);
2209 free_call_trace(&trace_expected);
2210 free_call_trace(&trace_got);
2212 IServiceProvider_Release(provider);
2216 static HRESULT WINAPI IProfferServiceImpl_QueryInterface(IProfferService *iface, REFIID riid, void **ppvObj)
2218 IProfferServiceImpl *This = (IProfferServiceImpl *)iface;
2220 if (IsEqualIID(riid, &IID_IUnknown) ||
2221 IsEqualIID(riid, &IID_IProfferService))
2223 *ppvObj = This;
2225 else if (IsEqualIID(riid, &IID_IServiceProvider))
2227 *ppvObj = IServiceProviderImpl_Construct();
2228 add_call(&trace_got, 1, iface, &IID_IServiceProvider, 0, 0, 0);
2229 return S_OK;
2232 if(*ppvObj)
2234 IUnknown_AddRef(iface);
2235 return S_OK;
2238 return E_NOINTERFACE;
2241 static ULONG WINAPI IProfferServiceImpl_AddRef(IProfferService *iface)
2243 IProfferServiceImpl *This = (IProfferServiceImpl *)iface;
2244 return InterlockedIncrement(&This->ref);
2247 static ULONG WINAPI IProfferServiceImpl_Release(IProfferService *iface)
2249 IProfferServiceImpl *This = (IProfferServiceImpl *)iface;
2250 ULONG ref = InterlockedDecrement(&This->ref);
2252 if (!ref)
2254 HeapFree(GetProcessHeap(), 0, This);
2255 return 0;
2257 return ref;
2260 static HRESULT WINAPI IProfferServiceImpl_ProfferService(IProfferService *iface,
2261 REFGUID service, IServiceProvider *pService, DWORD *pCookie)
2263 add_call(&trace_got, 3, service, pService, pCookie, 0, 0);
2264 return S_OK;
2267 static HRESULT WINAPI IProfferServiceImpl_RevokeService(IProfferService *iface, DWORD cookie)
2269 add_call(&trace_got, 4, (void*)(DWORD_PTR)cookie, 0, 0, 0, 0);
2270 return S_OK;
2273 static const IProfferServiceVtbl IProfferServiceImpl_Vtbl =
2275 IProfferServiceImpl_QueryInterface,
2276 IProfferServiceImpl_AddRef,
2277 IProfferServiceImpl_Release,
2278 IProfferServiceImpl_ProfferService,
2279 IProfferServiceImpl_RevokeService
2282 static void test_IUnknown_ProfferService(void)
2284 IServiceProvider *provider = IServiceProviderImpl_Construct();
2285 IProfferService *proff = IProfferServiceImpl_Construct();
2286 static const GUID dummy_serviceid = { 0xdeadbeef };
2287 call_trace_t trace_expected;
2288 HRESULT hr;
2289 DWORD cookie;
2291 /* on <=W2K platforms same ordinal used for another export with different
2292 prototype, so skipping using this indirect condition */
2293 if (is_win2k_and_lower)
2295 win_skip("IUnknown_ProfferService is not available\n");
2296 return;
2299 /* null source pointer */
2300 hr = pIUnknown_ProfferService(NULL, &dummy_serviceid, 0, 0);
2301 ok(hr == E_FAIL, "got 0x%08x\n", hr);
2303 /* expected trace:
2304 IUnknown_ProfferService( ptr1, serviceid, arg1, arg2);
2305 -> IUnknown_QueryInterface( ptr1, &IID_IServiceProvider, &provider );
2306 -> IServiceProvider_QueryService( provider, &IID_IProfferService, &IID_IProfferService, &proffer );
2308 if (service pointer not null):
2309 -> IProfferService_ProfferService( proffer, serviceid, arg1, arg2 );
2310 else
2311 -> IProfferService_RevokeService( proffer, *arg2 );
2313 init_call_trace(&trace_expected);
2315 add_call(&trace_expected, 1, proff, &IID_IServiceProvider, 0, 0, 0);
2316 add_call(&trace_expected, 2, &IID_IProfferService, &IID_IProfferService, 0, 0, 0);
2317 add_call(&trace_expected, 3, &dummy_serviceid, provider, &cookie, 0, 0);
2319 init_call_trace(&trace_got);
2320 hr = pIUnknown_ProfferService((IUnknown*)proff, &dummy_serviceid, provider, &cookie);
2321 ok(hr == S_OK, "got 0x%08x\n", hr);
2323 ok_trace(&trace_expected, &trace_got);
2324 free_call_trace(&trace_got);
2325 free_call_trace(&trace_expected);
2327 /* same with ::Revoke path */
2328 init_call_trace(&trace_expected);
2330 add_call(&trace_expected, 1, proff, &IID_IServiceProvider, 0, 0, 0);
2331 add_call(&trace_expected, 2, &IID_IProfferService, &IID_IProfferService, 0, 0, 0);
2332 add_call(&trace_expected, 4, (void*)(DWORD_PTR)cookie, 0, 0, 0, 0);
2334 init_call_trace(&trace_got);
2335 hr = pIUnknown_ProfferService((IUnknown*)proff, &dummy_serviceid, 0, &cookie);
2336 ok(hr == S_OK, "got 0x%08x\n", hr);
2337 ok_trace(&trace_expected, &trace_got);
2338 free_call_trace(&trace_got);
2339 free_call_trace(&trace_expected);
2341 IServiceProvider_Release(provider);
2342 IProfferService_Release(proff);
2345 static void test_SHCreateWorkerWindowA(void)
2347 WNDCLASSA cliA;
2348 char classA[20];
2349 HWND hwnd;
2350 LONG_PTR ret;
2351 BOOL res;
2353 if (is_win2k_and_lower)
2355 win_skip("SHCreateWorkerWindowA not available\n");
2356 return;
2359 hwnd = pSHCreateWorkerWindowA(0, NULL, 0, 0, 0, 0);
2360 ok(hwnd != 0, "expected window\n");
2362 GetClassName(hwnd, classA, 20);
2363 ok(lstrcmpA(classA, "WorkerA") == 0, "expected WorkerA class, got %s\n", classA);
2365 ret = GetWindowLongPtrA(hwnd, 0);
2366 ok(ret == 0, "got %ld\n", ret);
2368 /* class info */
2369 memset(&cliA, 0, sizeof(cliA));
2370 res = GetClassInfoA(GetModuleHandle("shlwapi.dll"), "WorkerA", &cliA);
2371 ok(res, "failed to get class info\n");
2372 ok(cliA.style == 0, "got 0x%08x\n", cliA.style);
2373 ok(cliA.cbClsExtra == 0, "got %d\n", cliA.cbClsExtra);
2374 ok(cliA.cbWndExtra == sizeof(LONG_PTR), "got %d\n", cliA.cbWndExtra);
2375 ok(cliA.lpszMenuName == 0, "got %s\n", cliA.lpszMenuName);
2377 DestroyWindow(hwnd);
2379 /* set extra bytes */
2380 hwnd = pSHCreateWorkerWindowA(0, NULL, 0, 0, 0, 0xdeadbeef);
2381 ok(hwnd != 0, "expected window\n");
2383 GetClassName(hwnd, classA, 20);
2384 ok(lstrcmpA(classA, "WorkerA") == 0, "expected WorkerA class, got %s\n", classA);
2386 ret = GetWindowLongPtrA(hwnd, 0);
2387 ok(ret == 0xdeadbeef, "got %ld\n", ret);
2389 /* test exstyle */
2390 ret = GetWindowLongA(hwnd, GWL_EXSTYLE);
2391 ok(ret == WS_EX_WINDOWEDGE, "0x%08lx\n", ret);
2393 DestroyWindow(hwnd);
2395 hwnd = pSHCreateWorkerWindowA(0, NULL, WS_EX_TOOLWINDOW, 0, 0, 0);
2396 ret = GetWindowLongA(hwnd, GWL_EXSTYLE);
2397 ok(ret == (WS_EX_WINDOWEDGE|WS_EX_TOOLWINDOW), "0x%08lx\n", ret);
2398 DestroyWindow(hwnd);
2401 static HRESULT WINAPI SF_QueryInterface(IShellFolder *iface,
2402 REFIID riid, void **ppv)
2404 /* SHIShellFolder_EnumObjects doesn't QI the object for IShellFolder */
2405 ok(!IsEqualGUID(&IID_IShellFolder, riid),
2406 "Unexpected QI for IShellFolder\n");
2407 return E_NOINTERFACE;
2410 static ULONG WINAPI SF_AddRef(IShellFolder *iface)
2412 return 2;
2415 static ULONG WINAPI SF_Release(IShellFolder *iface)
2417 return 1;
2420 static HRESULT WINAPI SF_ParseDisplayName(IShellFolder *iface,
2421 HWND owner, LPBC reserved, LPOLESTR displayName, ULONG *eaten,
2422 LPITEMIDLIST *idl, ULONG *attr)
2424 ok(0, "Didn't expect ParseDisplayName\n");
2425 return E_NOTIMPL;
2428 static HRESULT WINAPI SF_EnumObjects(IShellFolder *iface,
2429 HWND owner, SHCONTF flags, IEnumIDList **enm)
2431 *enm = (IEnumIDList*)0xcafebabe;
2432 return S_OK;
2435 static HRESULT WINAPI SF_BindToObject(IShellFolder *iface,
2436 LPCITEMIDLIST idl, LPBC reserved, REFIID riid, void **obj)
2438 ok(0, "Didn't expect BindToObject\n");
2439 return E_NOTIMPL;
2442 static HRESULT WINAPI SF_BindToStorage(IShellFolder *iface,
2443 LPCITEMIDLIST idl, LPBC reserved, REFIID riid, void **obj)
2445 ok(0, "Didn't expect BindToStorage\n");
2446 return E_NOTIMPL;
2449 static HRESULT WINAPI SF_CompareIDs(IShellFolder *iface,
2450 LPARAM lparam, LPCITEMIDLIST idl1, LPCITEMIDLIST idl2)
2452 ok(0, "Didn't expect CompareIDs\n");
2453 return E_NOTIMPL;
2456 static HRESULT WINAPI SF_CreateViewObject(IShellFolder *iface,
2457 HWND owner, REFIID riid, void **out)
2459 ok(0, "Didn't expect CreateViewObject\n");
2460 return E_NOTIMPL;
2463 static HRESULT WINAPI SF_GetAttributesOf(IShellFolder *iface,
2464 UINT cidl, LPCITEMIDLIST *idl, SFGAOF *inOut)
2466 ok(0, "Didn't expect GetAttributesOf\n");
2467 return E_NOTIMPL;
2470 static HRESULT WINAPI SF_GetUIObjectOf(IShellFolder *iface,
2471 HWND owner, UINT cidl, LPCITEMIDLIST *idls, REFIID riid, UINT *inOut,
2472 void **out)
2474 ok(0, "Didn't expect GetUIObjectOf\n");
2475 return E_NOTIMPL;
2478 static HRESULT WINAPI SF_GetDisplayNameOf(IShellFolder *iface,
2479 LPCITEMIDLIST idl, SHGDNF flags, STRRET *name)
2481 ok(0, "Didn't expect GetDisplayNameOf\n");
2482 return E_NOTIMPL;
2485 static HRESULT WINAPI SF_SetNameOf(IShellFolder *iface,
2486 HWND hwnd, LPCITEMIDLIST idl, LPCOLESTR name, SHGDNF flags,
2487 LPITEMIDLIST *idlOut)
2489 ok(0, "Didn't expect SetNameOf\n");
2490 return E_NOTIMPL;
2493 static IShellFolderVtbl ShellFolderVtbl = {
2494 SF_QueryInterface,
2495 SF_AddRef,
2496 SF_Release,
2497 SF_ParseDisplayName,
2498 SF_EnumObjects,
2499 SF_BindToObject,
2500 SF_BindToStorage,
2501 SF_CompareIDs,
2502 SF_CreateViewObject,
2503 SF_GetAttributesOf,
2504 SF_GetUIObjectOf,
2505 SF_GetDisplayNameOf,
2506 SF_SetNameOf
2509 static IShellFolder ShellFolder = { &ShellFolderVtbl };
2511 static void test_SHIShellFolder_EnumObjects(void)
2513 IEnumIDList *enm;
2514 HRESULT hres;
2515 IShellFolder *folder;
2517 if(!pSHIShellFolder_EnumObjects || is_win2k_and_lower){
2518 win_skip("SHIShellFolder_EnumObjects not available\n");
2519 return;
2522 if(0){
2523 /* NULL object crashes on Windows */
2524 hres = pSHIShellFolder_EnumObjects(NULL, NULL, 0, NULL);
2527 /* SHIShellFolder_EnumObjects doesn't QI the object for IShellFolder */
2528 enm = (IEnumIDList*)0xdeadbeef;
2529 hres = pSHIShellFolder_EnumObjects(&ShellFolder, NULL, 0, &enm);
2530 ok(hres == S_OK, "SHIShellFolder_EnumObjects failed: 0x%08x\n", hres);
2531 ok(enm == (IEnumIDList*)0xcafebabe, "Didn't get expected enumerator location, instead: %p\n", enm);
2533 /* SHIShellFolder_EnumObjects isn't strict about the IShellFolder object */
2534 hres = pSHGetDesktopFolder(&folder);
2535 ok(hres == S_OK, "SHGetDesktopFolder failed: 0x%08x\n", hres);
2537 enm = NULL;
2538 hres = pSHIShellFolder_EnumObjects(folder, NULL, 0, &enm);
2539 ok(hres == S_OK, "SHIShellFolder_EnumObjects failed: 0x%08x\n", hres);
2540 ok(enm != NULL, "Didn't get an enumerator\n");
2541 if(enm)
2542 IEnumIDList_Release(enm);
2544 IShellFolder_Release(folder);
2547 static void write_inifile(LPCWSTR filename)
2549 DWORD written;
2550 HANDLE file;
2552 static const char data[] =
2553 "[TestApp]\r\n"
2554 "AKey=1\r\n"
2555 "AnotherKey=asdf\r\n";
2557 file = CreateFileW(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
2558 if(file == INVALID_HANDLE_VALUE)
2559 return;
2561 WriteFile(file, data, sizeof(data), &written, NULL);
2563 CloseHandle(file);
2566 #define verify_inifile(f, e) r_verify_inifile(__LINE__, f, e)
2567 static void r_verify_inifile(unsigned l, LPCWSTR filename, LPCSTR exp)
2569 HANDLE file;
2570 CHAR buf[1024];
2571 DWORD read;
2573 file = CreateFileW(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
2574 if(file == INVALID_HANDLE_VALUE)
2575 return;
2577 ReadFile(file, buf, sizeof(buf) * sizeof(CHAR), &read, NULL);
2578 buf[read] = '\0';
2580 CloseHandle(file);
2582 ok_(__FILE__,l)(!strcmp(buf, exp), "Expected:\n%s\nGot:\n%s\n", exp,
2583 buf);
2586 static void test_SHGetIniString(void)
2588 DWORD ret;
2589 WCHAR out[64] = {0};
2591 static const WCHAR TestAppW[] = {'T','e','s','t','A','p','p',0};
2592 static const WCHAR TestIniW[] = {'C',':','\\','t','e','s','t','.','i','n','i',0};
2593 static const WCHAR AKeyW[] = {'A','K','e','y',0};
2594 static const WCHAR AnotherKeyW[] = {'A','n','o','t','h','e','r','K','e','y',0};
2595 static const WCHAR JunkKeyW[] = {'J','u','n','k','K','e','y',0};
2597 if(!pSHGetIniStringW || is_win2k_and_lower){
2598 win_skip("SHGetIniStringW is not available\n");
2599 return;
2602 write_inifile(TestIniW);
2604 if(0){
2605 /* these crash on Windows */
2606 ret = pSHGetIniStringW(NULL, NULL, NULL, 0, NULL);
2607 ret = pSHGetIniStringW(NULL, AKeyW, out, sizeof(out), TestIniW);
2608 ret = pSHGetIniStringW(TestAppW, AKeyW, NULL, sizeof(out), TestIniW);
2611 ret = pSHGetIniStringW(TestAppW, AKeyW, out, 0, TestIniW);
2612 ok(ret == 0, "SHGetIniStringW should have given 0, instead: %d\n", ret);
2614 /* valid arguments */
2615 ret = pSHGetIniStringW(TestAppW, NULL, out, sizeof(out), TestIniW);
2616 ok(broken(ret == 0) || /* win 98 */
2617 ret == 4, "SHGetIniStringW should have given 4, instead: %d\n", ret);
2618 ok(!lstrcmpW(out, AKeyW), "Expected %s, got: %s\n",
2619 wine_dbgstr_w(AKeyW), wine_dbgstr_w(out));
2621 ret = pSHGetIniStringW(TestAppW, AKeyW, out, sizeof(out), TestIniW);
2622 ok(broken(ret == 0) || /* win 98 */
2623 ret == 1, "SHGetIniStringW should have given 1, instead: %d\n", ret);
2624 ok(broken(*out == 0) || /*win 98 */
2625 !strcmp_wa(out, "1"), "Expected L\"1\", got: %s\n", wine_dbgstr_w(out));
2627 ret = pSHGetIniStringW(TestAppW, AnotherKeyW, out, sizeof(out), TestIniW);
2628 ok(broken(ret == 0) || /* win 98 */
2629 ret == 4, "SHGetIniStringW should have given 4, instead: %d\n", ret);
2630 ok(broken(*out == 0) || /* win 98 */
2631 !strcmp_wa(out, "asdf"), "Expected L\"asdf\", got: %s\n", wine_dbgstr_w(out));
2633 ret = pSHGetIniStringW(TestAppW, JunkKeyW, out, sizeof(out), TestIniW);
2634 ok(ret == 0, "SHGetIniStringW should have given 0, instead: %d\n", ret);
2635 ok(*out == 0, "Expected L\"\", got: %s\n", wine_dbgstr_w(out));
2637 DeleteFileW(TestIniW);
2640 static void test_SHSetIniString(void)
2642 BOOL ret;
2644 static const WCHAR TestAppW[] = {'T','e','s','t','A','p','p',0};
2645 static const WCHAR AnotherAppW[] = {'A','n','o','t','h','e','r','A','p','p',0};
2646 static const WCHAR TestIniW[] = {'C',':','\\','t','e','s','t','.','i','n','i',0};
2647 static const WCHAR AKeyW[] = {'A','K','e','y',0};
2648 static const WCHAR NewKeyW[] = {'N','e','w','K','e','y',0};
2649 static const WCHAR AValueW[] = {'A','V','a','l','u','e',0};
2651 if(!pSHSetIniStringW || is_win2k_and_lower){
2652 win_skip("SHSetIniStringW is not available\n");
2653 return;
2656 write_inifile(TestIniW);
2658 ret = pSHSetIniStringW(TestAppW, AKeyW, AValueW, TestIniW);
2659 ok(ret == TRUE, "SHSetIniStringW should not have failed\n");
2660 todo_wine /* wine sticks an extra \r\n at the end of the file */
2661 verify_inifile(TestIniW, "[TestApp]\r\nAKey=AValue\r\nAnotherKey=asdf\r\n");
2663 ret = pSHSetIniStringW(TestAppW, AKeyW, NULL, TestIniW);
2664 ok(ret == TRUE, "SHSetIniStringW should not have failed\n");
2665 verify_inifile(TestIniW, "[TestApp]\r\nAnotherKey=asdf\r\n");
2667 ret = pSHSetIniStringW(AnotherAppW, NewKeyW, AValueW, TestIniW);
2668 ok(ret == TRUE, "SHSetIniStringW should not have failed\n");
2669 verify_inifile(TestIniW, "[TestApp]\r\nAnotherKey=asdf\r\n[AnotherApp]\r\nNewKey=AValue\r\n");
2671 ret = pSHSetIniStringW(TestAppW, NULL, AValueW, TestIniW);
2672 ok(ret == TRUE, "SHSetIniStringW should not have failed\n");
2673 verify_inifile(TestIniW, "[AnotherApp]\r\nNewKey=AValue\r\n");
2675 DeleteFileW(TestIniW);
2678 static void init_pointers(void)
2680 #define MAKEFUNC(f, ord) (p##f = (void*)GetProcAddress(hShlwapi, (LPSTR)(ord)))
2681 MAKEFUNC(SHAllocShared, 7);
2682 MAKEFUNC(SHLockShared, 8);
2683 MAKEFUNC(SHUnlockShared, 9);
2684 MAKEFUNC(SHFreeShared, 10);
2685 MAKEFUNC(GetAcceptLanguagesA, 14);
2686 MAKEFUNC(SHSetWindowBits, 165);
2687 MAKEFUNC(ConnectToConnectionPoint, 168);
2688 MAKEFUNC(SHSearchMapInt, 198);
2689 MAKEFUNC(SHCreateWorkerWindowA, 257);
2690 MAKEFUNC(GUIDFromStringA, 269);
2691 MAKEFUNC(SHPackDispParams, 282);
2692 MAKEFUNC(IConnectionPoint_InvokeWithCancel, 283);
2693 MAKEFUNC(IConnectionPoint_SimpleInvoke, 284);
2694 MAKEFUNC(SHGetIniStringW, 294);
2695 MAKEFUNC(SHSetIniStringW, 295);
2696 MAKEFUNC(SHFormatDateTimeA, 353);
2697 MAKEFUNC(SHFormatDateTimeW, 354);
2698 MAKEFUNC(SHIShellFolder_EnumObjects, 404);
2699 MAKEFUNC(SHGetObjectCompatFlags, 476);
2700 MAKEFUNC(IUnknown_QueryServiceExec, 484);
2701 MAKEFUNC(SHPropertyBag_ReadLONG, 496);
2702 MAKEFUNC(IUnknown_ProfferService, 514);
2703 #undef MAKEFUNC
2706 START_TEST(ordinal)
2708 hShlwapi = GetModuleHandleA("shlwapi.dll");
2709 is_win2k_and_lower = GetProcAddress(hShlwapi, "StrChrNW") == 0;
2711 init_pointers();
2713 hmlang = LoadLibraryA("mlang.dll");
2714 pLcidToRfc1766A = (void *)GetProcAddress(hmlang, "LcidToRfc1766A");
2716 hshell32 = LoadLibraryA("shell32.dll");
2717 pSHGetDesktopFolder = (void *)GetProcAddress(hshell32, "SHGetDesktopFolder");
2719 test_GetAcceptLanguagesA();
2720 test_SHSearchMapInt();
2721 test_alloc_shared();
2722 test_fdsa();
2723 test_GetShellSecurityDescriptor();
2724 test_SHPackDispParams();
2725 test_IConnectionPoint();
2726 test_SHPropertyBag_ReadLONG();
2727 test_SHSetWindowBits();
2728 test_SHFormatDateTimeA();
2729 test_SHFormatDateTimeW();
2730 test_SHGetObjectCompatFlags();
2731 test_IUnknown_QueryServiceExec();
2732 test_IUnknown_ProfferService();
2733 test_SHCreateWorkerWindowA();
2734 test_SHIShellFolder_EnumObjects();
2735 test_SHGetIniString();
2736 test_SHSetIniString();
2738 FreeLibrary(hshell32);
2739 FreeLibrary(hmlang);