[SHLWAPI_WINETEST]
[reactos.git] / rostests / winetests / shlwapi / ordinal.c
1 /* Unit test suite for SHLWAPI ordinal functions
2 *
3 * Copyright 2004 Jon Griffiths
4 *
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.
9 *
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.
14 *
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
18 */
19
20 #include <stdio.h>
21
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
32 /* Function ptrs for ordinal calls */
33 static HMODULE hShlwapi;
34 static int (WINAPI *pSHSearchMapInt)(const int*,const int*,int,int);
35 static HRESULT (WINAPI *pGetAcceptLanguagesA)(LPSTR,LPDWORD);
36
37 static HANDLE (WINAPI *pSHAllocShared)(LPCVOID,DWORD,DWORD);
38 static LPVOID (WINAPI *pSHLockShared)(HANDLE,DWORD);
39 static BOOL (WINAPI *pSHUnlockShared)(LPVOID);
40 static BOOL (WINAPI *pSHFreeShared)(HANDLE,DWORD);
41 static HRESULT(WINAPIV *pSHPackDispParams)(DISPPARAMS*,VARIANTARG*,UINT,...);
42 static HRESULT(WINAPI *pIConnectionPoint_SimpleInvoke)(IConnectionPoint*,DISPID,DISPPARAMS*);
43 static HRESULT(WINAPI *pIConnectionPoint_InvokeWithCancel)(IConnectionPoint*,DISPID,DISPPARAMS*,DWORD,DWORD);
44 static HRESULT(WINAPI *pConnectToConnectionPoint)(IUnknown*,REFIID,BOOL,IUnknown*, LPDWORD,IConnectionPoint **);
45 static HRESULT(WINAPI *pSHPropertyBag_ReadLONG)(IPropertyBag *,LPCWSTR,LPLONG);
46
47 static HMODULE hmlang;
48 static HRESULT (WINAPI *pLcidToRfc1766A)(LCID, LPSTR, INT);
49
50 static const CHAR ie_international[] = {
51 'S','o','f','t','w','a','r','e','\\',
52 'M','i','c','r','o','s','o','f','t','\\',
53 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
54 'I','n','t','e','r','n','a','t','i','o','n','a','l',0};
55 static const CHAR acceptlanguage[] = {
56 'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0};
57
58
59 static void test_GetAcceptLanguagesA(void)
60 {
61 static LPCSTR table[] = {"de,en-gb;q=0.7,en;q=0.3",
62 "de,en;q=0.3,en-gb;q=0.7", /* sorting is ignored */
63 "winetest", /* content is ignored */
64 "de-de,de;q=0.5",
65 "de",
66 NULL};
67
68 DWORD exactsize;
69 char original[512];
70 char language[32];
71 char buffer[64];
72 HKEY hroot = NULL;
73 LONG res_query = ERROR_SUCCESS;
74 LONG lres;
75 HRESULT hr;
76 DWORD maxlen = sizeof(buffer) - 2;
77 DWORD len;
78 LCID lcid;
79 LPCSTR entry;
80 INT i = 0;
81
82 if (!pGetAcceptLanguagesA) {
83 win_skip("GetAcceptLanguagesA is not available\n");
84 return;
85 }
86
87 lcid = GetUserDefaultLCID();
88
89 /* Get the original Value */
90 lres = RegOpenKeyA(HKEY_CURRENT_USER, ie_international, &hroot);
91 if (lres) {
92 skip("RegOpenKey(%s) failed: %d\n", ie_international, lres);
93 return;
94 }
95 len = sizeof(original);
96 original[0] = 0;
97 res_query = RegQueryValueExA(hroot, acceptlanguage, 0, NULL, (PBYTE)original, &len);
98
99 RegDeleteValue(hroot, acceptlanguage);
100
101 /* Some windows versions use "lang-COUNTRY" as default */
102 memset(language, 0, sizeof(language));
103 len = GetLocaleInfoA(lcid, LOCALE_SISO639LANGNAME, language, sizeof(language));
104
105 if (len) {
106 lstrcat(language, "-");
107 memset(buffer, 0, sizeof(buffer));
108 len = GetLocaleInfoA(lcid, LOCALE_SISO3166CTRYNAME, buffer, sizeof(buffer) - len - 1);
109 lstrcat(language, buffer);
110 }
111 else
112 {
113 /* LOCALE_SNAME has additional parts in some languages. Try only as last chance */
114 memset(language, 0, sizeof(language));
115 len = GetLocaleInfoA(lcid, LOCALE_SNAME, language, sizeof(language));
116 }
117
118 /* get the default value */
119 len = maxlen;
120 memset(buffer, '#', maxlen);
121 buffer[maxlen] = 0;
122 hr = pGetAcceptLanguagesA( buffer, &len);
123
124 if (hr != S_OK) {
125 win_skip("GetAcceptLanguagesA failed with 0x%x\n", hr);
126 goto restore_original;
127 }
128
129 if (lstrcmpA(buffer, language)) {
130 /* some windows versions use "lang" or "lang-country" as default */
131 language[0] = 0;
132 if (pLcidToRfc1766A) {
133 hr = pLcidToRfc1766A(lcid, language, sizeof(language));
134 ok(hr == S_OK, "LcidToRfc1766A returned 0x%x and %s\n", hr, language);
135 }
136 }
137
138 ok(!lstrcmpA(buffer, language),
139 "have '%s' (searching for '%s')\n", language, buffer);
140
141 if (lstrcmpA(buffer, language)) {
142 win_skip("no more ideas, how to build the default language '%s'\n", buffer);
143 goto restore_original;
144 }
145
146 trace("detected default: %s\n", language);
147 while ((entry = table[i])) {
148
149 exactsize = lstrlenA(entry);
150
151 lres = RegSetValueExA(hroot, acceptlanguage, 0, REG_SZ, (const BYTE *) entry, exactsize + 1);
152 ok(!lres, "got %d for RegSetValueExA: %s\n", lres, entry);
153
154 /* len includes space for the terminating 0 before vista/w2k8 */
155 len = exactsize + 2;
156 memset(buffer, '#', maxlen);
157 buffer[maxlen] = 0;
158 hr = pGetAcceptLanguagesA( buffer, &len);
159 ok(((hr == E_INVALIDARG) && (len == 0)) ||
160 (SUCCEEDED(hr) &&
161 ((len == exactsize) || (len == exactsize+1)) &&
162 !lstrcmpA(buffer, entry)),
163 "+2_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
164
165 len = exactsize + 1;
166 memset(buffer, '#', maxlen);
167 buffer[maxlen] = 0;
168 hr = pGetAcceptLanguagesA( buffer, &len);
169 ok(((hr == E_INVALIDARG) && (len == 0)) ||
170 (SUCCEEDED(hr) &&
171 ((len == exactsize) || (len == exactsize+1)) &&
172 !lstrcmpA(buffer, entry)),
173 "+1_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
174
175 len = exactsize;
176 memset(buffer, '#', maxlen);
177 buffer[maxlen] = 0;
178 hr = pGetAcceptLanguagesA( buffer, &len);
179
180 /* There is no space for the string in the registry.
181 When the buffer is large enough, the default language is returned
182
183 When the buffer is to small for that fallback, win7_32 and w2k8_64
184 and above fail with HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), but
185 recent os succeed and return a partial result while
186 older os succeed and overflow the buffer */
187
188 ok(((hr == E_INVALIDARG) && (len == 0)) ||
189 (((hr == S_OK) && !lstrcmpA(buffer, language) && (len == lstrlenA(language))) ||
190 ((hr == S_OK) && !memcmp(buffer, language, len)) ||
191 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len)),
192 "==_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
193
194 if (exactsize > 1) {
195 len = exactsize - 1;
196 memset(buffer, '#', maxlen);
197 buffer[maxlen] = 0;
198 hr = pGetAcceptLanguagesA( buffer, &len);
199 ok(((hr == E_INVALIDARG) && (len == 0)) ||
200 (((hr == S_OK) && !lstrcmpA(buffer, language) && (len == lstrlenA(language))) ||
201 ((hr == S_OK) && !memcmp(buffer, language, len)) ||
202 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len)),
203 "-1_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
204 }
205
206 len = 1;
207 memset(buffer, '#', maxlen);
208 buffer[maxlen] = 0;
209 hr = pGetAcceptLanguagesA( buffer, &len);
210 ok(((hr == E_INVALIDARG) && (len == 0)) ||
211 (((hr == S_OK) && !lstrcmpA(buffer, language) && (len == lstrlenA(language))) ||
212 ((hr == S_OK) && !memcmp(buffer, language, len)) ||
213 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len)),
214 "=1_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
215
216 len = maxlen;
217 hr = pGetAcceptLanguagesA( NULL, &len);
218
219 /* w2k3 and below: E_FAIL and untouched len,
220 since w2k8: S_OK and needed size (excluding 0) */
221 ok( ((hr == S_OK) && (len == exactsize)) ||
222 ((hr == E_FAIL) && (len == maxlen)),
223 "NULL,max #%d: got 0x%x with %d and %s\n", i, hr, len, buffer);
224
225 i++;
226 }
227
228 /* without a value in the registry, a default language is returned */
229 RegDeleteValue(hroot, acceptlanguage);
230
231 len = maxlen;
232 memset(buffer, '#', maxlen);
233 buffer[maxlen] = 0;
234 hr = pGetAcceptLanguagesA( buffer, &len);
235 ok( ((hr == S_OK) && (len == lstrlenA(language))),
236 "max: got 0x%x with %d and %s (expected S_OK with %d and '%s'\n",
237 hr, len, buffer, lstrlenA(language), language);
238
239 len = 2;
240 memset(buffer, '#', maxlen);
241 buffer[maxlen] = 0;
242 hr = pGetAcceptLanguagesA( buffer, &len);
243 ok( (((hr == S_OK) || (hr == E_INVALIDARG)) && !memcmp(buffer, language, len)) ||
244 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len),
245 "=2: got 0x%x with %d and %s\n", hr, len, buffer);
246
247 len = 1;
248 memset(buffer, '#', maxlen);
249 buffer[maxlen] = 0;
250 hr = pGetAcceptLanguagesA( buffer, &len);
251 /* When the buffer is to small, win7_32 and w2k8_64 and above fail with
252 HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), other versions suceed
253 and return a partial 0 terminated result while other versions
254 fail with E_INVALIDARG and return a partial unterminated result */
255 ok( (((hr == S_OK) || (hr == E_INVALIDARG)) && !memcmp(buffer, language, len)) ||
256 ((hr == __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) && !len),
257 "=1: got 0x%x with %d and %s\n", hr, len, buffer);
258
259 len = 0;
260 memset(buffer, '#', maxlen);
261 buffer[maxlen] = 0;
262 hr = pGetAcceptLanguagesA( buffer, &len);
263 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
264 ok((hr == E_FAIL) || (hr == E_INVALIDARG),
265 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr);
266
267 memset(buffer, '#', maxlen);
268 buffer[maxlen] = 0;
269 hr = pGetAcceptLanguagesA( buffer, NULL);
270 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
271 ok((hr == E_FAIL) || (hr == E_INVALIDARG),
272 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr);
273
274
275 hr = pGetAcceptLanguagesA( NULL, NULL);
276 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */
277 ok((hr == E_FAIL) || (hr == E_INVALIDARG),
278 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr);
279
280 restore_original:
281 if (!res_query) {
282 len = lstrlenA(original);
283 lres = RegSetValueExA(hroot, acceptlanguage, 0, REG_SZ, (const BYTE *) original, len ? len + 1: 0);
284 ok(!lres, "RegSetValueEx(%s) failed: %d\n", original, lres);
285 }
286 else
287 {
288 RegDeleteValue(hroot, acceptlanguage);
289 }
290 RegCloseKey(hroot);
291 }
292
293 static void test_SHSearchMapInt(void)
294 {
295 int keys[8], values[8];
296 int i = 0;
297
298 if (!pSHSearchMapInt)
299 return;
300
301 memset(keys, 0, sizeof(keys));
302 memset(values, 0, sizeof(values));
303 keys[0] = 99; values[0] = 101;
304
305 /* NULL key/value lists crash native, so skip testing them */
306
307 /* 1 element */
308 i = pSHSearchMapInt(keys, values, 1, keys[0]);
309 ok(i == values[0], "Len 1, expected %d, got %d\n", values[0], i);
310
311 /* Key doesn't exist */
312 i = pSHSearchMapInt(keys, values, 1, 100);
313 ok(i == -1, "Len 1 - bad key, expected -1, got %d\n", i);
314
315 /* Len = 0 => not found */
316 i = pSHSearchMapInt(keys, values, 0, keys[0]);
317 ok(i == -1, "Len 1 - passed len 0, expected -1, got %d\n", i);
318
319 /* 2 elements, len = 1 */
320 keys[1] = 98; values[1] = 102;
321 i = pSHSearchMapInt(keys, values, 1, keys[1]);
322 ok(i == -1, "Len 1 - array len 2, expected -1, got %d\n", i);
323
324 /* 2 elements, len = 2 */
325 i = pSHSearchMapInt(keys, values, 2, keys[1]);
326 ok(i == values[1], "Len 2, expected %d, got %d\n", values[1], i);
327
328 /* Searches forward */
329 keys[2] = 99; values[2] = 103;
330 i = pSHSearchMapInt(keys, values, 3, keys[0]);
331 ok(i == values[0], "Len 3, expected %d, got %d\n", values[0], i);
332 }
333
334 static void test_alloc_shared(void)
335 {
336 DWORD procid;
337 HANDLE hmem;
338 int val;
339 int* p;
340 BOOL ret;
341
342 procid=GetCurrentProcessId();
343 hmem=pSHAllocShared(NULL,10,procid);
344 ok(hmem!=NULL,"SHAllocShared(NULL...) failed: %u\n", GetLastError());
345 ret = pSHFreeShared(hmem, procid);
346 ok( ret, "SHFreeShared failed: %u\n", GetLastError());
347
348 val=0x12345678;
349 hmem=pSHAllocShared(&val,4,procid);
350 ok(hmem!=NULL,"SHAllocShared(NULL...) failed: %u\n", GetLastError());
351
352 p=pSHLockShared(hmem,procid);
353 ok(p!=NULL,"SHLockShared failed: %u\n", GetLastError());
354 if (p!=NULL)
355 ok(*p==val,"Wrong value in shared memory: %d instead of %d\n",*p,val);
356 ret = pSHUnlockShared(p);
357 ok( ret, "SHUnlockShared failed: %u\n", GetLastError());
358
359 ret = pSHFreeShared(hmem, procid);
360 ok( ret, "SHFreeShared failed: %u\n", GetLastError());
361 }
362
363 static void test_fdsa(void)
364 {
365 typedef struct
366 {
367 DWORD num_items; /* Number of elements inserted */
368 void *mem; /* Ptr to array */
369 DWORD blocks_alloced; /* Number of elements allocated */
370 BYTE inc; /* Number of elements to grow by when we need to expand */
371 BYTE block_size; /* Size in bytes of an element */
372 BYTE flags; /* Flags */
373 } FDSA_info;
374
375 BOOL (WINAPI *pFDSA_Initialize)(DWORD block_size, DWORD inc, FDSA_info *info, void *mem,
376 DWORD init_blocks);
377 BOOL (WINAPI *pFDSA_Destroy)(FDSA_info *info);
378 DWORD (WINAPI *pFDSA_InsertItem)(FDSA_info *info, DWORD where, const void *block);
379 BOOL (WINAPI *pFDSA_DeleteItem)(FDSA_info *info, DWORD where);
380
381 FDSA_info info;
382 int block_size = 10, init_blocks = 4, inc = 2;
383 DWORD ret;
384 char *mem;
385
386 pFDSA_Initialize = (void *)GetProcAddress(hShlwapi, (LPSTR)208);
387 pFDSA_Destroy = (void *)GetProcAddress(hShlwapi, (LPSTR)209);
388 pFDSA_InsertItem = (void *)GetProcAddress(hShlwapi, (LPSTR)210);
389 pFDSA_DeleteItem = (void *)GetProcAddress(hShlwapi, (LPSTR)211);
390
391 mem = HeapAlloc(GetProcessHeap(), 0, block_size * init_blocks);
392 memset(&info, 0, sizeof(info));
393
394 ok(pFDSA_Initialize(block_size, inc, &info, mem, init_blocks), "FDSA_Initialize rets FALSE\n");
395 ok(info.num_items == 0, "num_items = %d\n", info.num_items);
396 ok(info.mem == mem, "mem = %p\n", info.mem);
397 ok(info.blocks_alloced == init_blocks, "blocks_alloced = %d\n", info.blocks_alloced);
398 ok(info.inc == inc, "inc = %d\n", info.inc);
399 ok(info.block_size == block_size, "block_size = %d\n", info.block_size);
400 ok(info.flags == 0, "flags = %d\n", info.flags);
401
402 ret = pFDSA_InsertItem(&info, 1234, "1234567890");
403 ok(ret == 0, "ret = %d\n", ret);
404 ok(info.num_items == 1, "num_items = %d\n", info.num_items);
405 ok(info.mem == mem, "mem = %p\n", info.mem);
406 ok(info.blocks_alloced == init_blocks, "blocks_alloced = %d\n", info.blocks_alloced);
407 ok(info.inc == inc, "inc = %d\n", info.inc);
408 ok(info.block_size == block_size, "block_size = %d\n", info.block_size);
409 ok(info.flags == 0, "flags = %d\n", info.flags);
410
411 ret = pFDSA_InsertItem(&info, 1234, "abcdefghij");
412 ok(ret == 1, "ret = %d\n", ret);
413
414 ret = pFDSA_InsertItem(&info, 1, "klmnopqrst");
415 ok(ret == 1, "ret = %d\n", ret);
416
417 ret = pFDSA_InsertItem(&info, 0, "uvwxyzABCD");
418 ok(ret == 0, "ret = %d\n", ret);
419 ok(info.mem == mem, "mem = %p\n", info.mem);
420 ok(info.flags == 0, "flags = %d\n", info.flags);
421
422 /* This next InsertItem will cause shlwapi to allocate its own mem buffer */
423 ret = pFDSA_InsertItem(&info, 0, "EFGHIJKLMN");
424 ok(ret == 0, "ret = %d\n", ret);
425 ok(info.mem != mem, "mem = %p\n", info.mem);
426 ok(info.blocks_alloced == init_blocks + inc, "blocks_alloced = %d\n", info.blocks_alloced);
427 ok(info.flags == 0x1, "flags = %d\n", info.flags);
428
429 ok(!memcmp(info.mem, "EFGHIJKLMNuvwxyzABCD1234567890klmnopqrstabcdefghij", 50), "mem %s\n", (char*)info.mem);
430
431 ok(pFDSA_DeleteItem(&info, 2), "rets FALSE\n");
432 ok(info.mem != mem, "mem = %p\n", info.mem);
433 ok(info.blocks_alloced == init_blocks + inc, "blocks_alloced = %d\n", info.blocks_alloced);
434 ok(info.flags == 0x1, "flags = %d\n", info.flags);
435
436 ok(!memcmp(info.mem, "EFGHIJKLMNuvwxyzABCDklmnopqrstabcdefghij", 40), "mem %s\n", (char*)info.mem);
437
438 ok(pFDSA_DeleteItem(&info, 3), "rets FALSE\n");
439 ok(info.mem != mem, "mem = %p\n", info.mem);
440 ok(info.blocks_alloced == init_blocks + inc, "blocks_alloced = %d\n", info.blocks_alloced);
441 ok(info.flags == 0x1, "flags = %d\n", info.flags);
442
443 ok(!memcmp(info.mem, "EFGHIJKLMNuvwxyzABCDklmnopqrst", 30), "mem %s\n", (char*)info.mem);
444
445 ok(!pFDSA_DeleteItem(&info, 4), "does not ret FALSE\n");
446
447 /* As shlwapi has allocated memory internally, Destroy will ret FALSE */
448 ok(!pFDSA_Destroy(&info), "FDSA_Destroy does not ret FALSE\n");
449
450
451 /* When Initialize is called with inc = 0, set it to 1 */
452 ok(pFDSA_Initialize(block_size, 0, &info, mem, init_blocks), "FDSA_Initialize rets FALSE\n");
453 ok(info.inc == 1, "inc = %d\n", info.inc);
454
455 /* This time, because shlwapi hasn't had to allocate memory
456 internally, Destroy rets non-zero */
457 ok(pFDSA_Destroy(&info), "FDSA_Destroy rets FALSE\n");
458
459
460 HeapFree(GetProcessHeap(), 0, mem);
461 }
462
463
464 typedef struct SHELL_USER_SID {
465 SID_IDENTIFIER_AUTHORITY sidAuthority;
466 DWORD dwUserGroupID;
467 DWORD dwUserID;
468 } SHELL_USER_SID, *PSHELL_USER_SID;
469 typedef struct SHELL_USER_PERMISSION {
470 SHELL_USER_SID susID;
471 DWORD dwAccessType;
472 BOOL fInherit;
473 DWORD dwAccessMask;
474 DWORD dwInheritMask;
475 DWORD dwInheritAccessMask;
476 } SHELL_USER_PERMISSION, *PSHELL_USER_PERMISSION;
477 static void test_GetShellSecurityDescriptor(void)
478 {
479 SHELL_USER_PERMISSION supCurrentUserFull = {
480 { {SECURITY_NULL_SID_AUTHORITY}, 0, 0 },
481 ACCESS_ALLOWED_ACE_TYPE, FALSE,
482 GENERIC_ALL, 0, 0 };
483 #define MY_INHERITANCE 0xBE /* invalid value to proof behavior */
484 SHELL_USER_PERMISSION supEveryoneDenied = {
485 { {SECURITY_WORLD_SID_AUTHORITY}, SECURITY_WORLD_RID, 0 },
486 ACCESS_DENIED_ACE_TYPE, TRUE,
487 GENERIC_WRITE, MY_INHERITANCE | 0xDEADBA00, GENERIC_READ };
488 PSHELL_USER_PERMISSION rgsup[2] = {
489 &supCurrentUserFull, &supEveryoneDenied,
490 };
491 SECURITY_DESCRIPTOR* psd;
492 SECURITY_DESCRIPTOR* (WINAPI*pGetShellSecurityDescriptor)(PSHELL_USER_PERMISSION*,int);
493
494 pGetShellSecurityDescriptor=(void*)GetProcAddress(hShlwapi,(char*)475);
495
496 if(!pGetShellSecurityDescriptor)
497 {
498 win_skip("GetShellSecurityDescriptor not available\n");
499 return;
500 }
501
502 psd = pGetShellSecurityDescriptor(NULL, 2);
503 ok(psd==NULL ||
504 broken(psd==INVALID_HANDLE_VALUE), /* IE5 */
505 "GetShellSecurityDescriptor should fail\n");
506 psd = pGetShellSecurityDescriptor(rgsup, 0);
507 ok(psd==NULL, "GetShellSecurityDescriptor should fail\n");
508
509 SetLastError(0xdeadbeef);
510 psd = pGetShellSecurityDescriptor(rgsup, 2);
511 if (psd == NULL && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
512 {
513 /* The previous calls to GetShellSecurityDescriptor don't set the last error */
514 win_skip("GetShellSecurityDescriptor is not implemented\n");
515 return;
516 }
517 if (psd==INVALID_HANDLE_VALUE)
518 {
519 win_skip("GetShellSecurityDescriptor is broken on IE5\n");
520 return;
521 }
522 ok(psd!=NULL, "GetShellSecurityDescriptor failed\n");
523 if (psd!=NULL)
524 {
525 BOOL bHasDacl = FALSE, bDefaulted;
526 PACL pAcl;
527 DWORD dwRev;
528 SECURITY_DESCRIPTOR_CONTROL control;
529
530 ok(IsValidSecurityDescriptor(psd), "returned value is not valid SD\n");
531
532 ok(GetSecurityDescriptorControl(psd, &control, &dwRev),
533 "GetSecurityDescriptorControl failed with error %u\n", GetLastError());
534 ok(0 == (control & SE_SELF_RELATIVE), "SD should be absolute\n");
535
536 ok(GetSecurityDescriptorDacl(psd, &bHasDacl, &pAcl, &bDefaulted),
537 "GetSecurityDescriptorDacl failed with error %u\n", GetLastError());
538
539 ok(bHasDacl, "SD has no DACL\n");
540 if (bHasDacl)
541 {
542 ok(!bDefaulted, "DACL should not be defaulted\n");
543
544 ok(pAcl != NULL, "NULL DACL!\n");
545 if (pAcl != NULL)
546 {
547 ACL_SIZE_INFORMATION asiSize;
548
549 ok(IsValidAcl(pAcl), "DACL is not valid\n");
550
551 ok(GetAclInformation(pAcl, &asiSize, sizeof(asiSize), AclSizeInformation),
552 "GetAclInformation failed with error %u\n", GetLastError());
553
554 ok(asiSize.AceCount == 3, "Incorrect number of ACEs: %d entries\n", asiSize.AceCount);
555 if (asiSize.AceCount == 3)
556 {
557 ACCESS_ALLOWED_ACE *paaa; /* will use for DENIED too */
558
559 ok(GetAce(pAcl, 0, (LPVOID*)&paaa), "GetAce failed with error %u\n", GetLastError());
560 ok(paaa->Header.AceType == ACCESS_ALLOWED_ACE_TYPE,
561 "Invalid ACE type %d\n", paaa->Header.AceType);
562 ok(paaa->Header.AceFlags == 0, "Invalid ACE flags %x\n", paaa->Header.AceFlags);
563 ok(paaa->Mask == GENERIC_ALL, "Invalid ACE mask %x\n", paaa->Mask);
564
565 ok(GetAce(pAcl, 1, (LPVOID*)&paaa), "GetAce failed with error %u\n", GetLastError());
566 ok(paaa->Header.AceType == ACCESS_DENIED_ACE_TYPE,
567 "Invalid ACE type %d\n", paaa->Header.AceType);
568 /* first one of two ACEs generated from inheritable entry - without inheritance */
569 ok(paaa->Header.AceFlags == 0, "Invalid ACE flags %x\n", paaa->Header.AceFlags);
570 ok(paaa->Mask == GENERIC_WRITE, "Invalid ACE mask %x\n", paaa->Mask);
571
572 ok(GetAce(pAcl, 2, (LPVOID*)&paaa), "GetAce failed with error %u\n", GetLastError());
573 ok(paaa->Header.AceType == ACCESS_DENIED_ACE_TYPE,
574 "Invalid ACE type %d\n", paaa->Header.AceType);
575 /* second ACE - with inheritance */
576 ok(paaa->Header.AceFlags == MY_INHERITANCE,
577 "Invalid ACE flags %x\n", paaa->Header.AceFlags);
578 ok(paaa->Mask == GENERIC_READ, "Invalid ACE mask %x\n", paaa->Mask);
579 }
580 }
581 }
582
583 LocalFree(psd);
584 }
585 }
586
587 static void test_SHPackDispParams(void)
588 {
589 DISPPARAMS params;
590 VARIANT vars[10];
591 HRESULT hres;
592
593 if(!pSHPackDispParams)
594 win_skip("SHPackSidpParams not available\n");
595
596 memset(&params, 0xc0, sizeof(params));
597 memset(vars, 0xc0, sizeof(vars));
598 hres = pSHPackDispParams(&params, vars, 1, VT_I4, 0xdeadbeef);
599 ok(hres == S_OK, "SHPackDispParams failed: %08x\n", hres);
600 ok(params.cArgs == 1, "params.cArgs = %d\n", params.cArgs);
601 ok(params.cNamedArgs == 0, "params.cNamedArgs = %d\n", params.cArgs);
602 ok(params.rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", params.rgdispidNamedArgs);
603 ok(params.rgvarg == vars, "params.rgvarg = %p\n", params.rgvarg);
604 ok(V_VT(vars) == VT_I4, "V_VT(var) = %d\n", V_VT(vars));
605 ok(V_I4(vars) == 0xdeadbeef, "failed %x\n", V_I4(vars));
606
607 memset(&params, 0xc0, sizeof(params));
608 hres = pSHPackDispParams(&params, NULL, 0, 0);
609 ok(hres == S_OK, "SHPackDispParams failed: %08x\n", hres);
610 ok(params.cArgs == 0, "params.cArgs = %d\n", params.cArgs);
611 ok(params.cNamedArgs == 0, "params.cNamedArgs = %d\n", params.cArgs);
612 ok(params.rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", params.rgdispidNamedArgs);
613 ok(params.rgvarg == NULL, "params.rgvarg = %p\n", params.rgvarg);
614
615 memset(vars, 0xc0, sizeof(vars));
616 memset(&params, 0xc0, sizeof(params));
617 hres = pSHPackDispParams(&params, vars, 4, VT_BSTR, (void*)0xdeadbeef, VT_EMPTY, 10,
618 VT_I4, 100, VT_DISPATCH, (void*)0xdeadbeef);
619 ok(hres == S_OK, "SHPackDispParams failed: %08x\n", hres);
620 ok(params.cArgs == 4, "params.cArgs = %d\n", params.cArgs);
621 ok(params.cNamedArgs == 0, "params.cNamedArgs = %d\n", params.cArgs);
622 ok(params.rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", params.rgdispidNamedArgs);
623 ok(params.rgvarg == vars, "params.rgvarg = %p\n", params.rgvarg);
624 ok(V_VT(vars) == VT_DISPATCH, "V_VT(vars[0]) = %x\n", V_VT(vars));
625 ok(V_I4(vars) == 0xdeadbeef, "V_I4(vars[0]) = %x\n", V_I4(vars));
626 ok(V_VT(vars+1) == VT_I4, "V_VT(vars[1]) = %d\n", V_VT(vars+1));
627 ok(V_I4(vars+1) == 100, "V_I4(vars[1]) = %x\n", V_I4(vars+1));
628 ok(V_VT(vars+2) == VT_I4, "V_VT(vars[2]) = %d\n", V_VT(vars+2));
629 ok(V_I4(vars+2) == 10, "V_I4(vars[2]) = %x\n", V_I4(vars+2));
630 ok(V_VT(vars+3) == VT_BSTR, "V_VT(vars[3]) = %d\n", V_VT(vars+3));
631 ok(V_BSTR(vars+3) == (void*)0xdeadbeef, "V_BSTR(vars[3]) = %p\n", V_BSTR(vars+3));
632 }
633
634 typedef struct _disp
635 {
636 const IDispatchVtbl *vtbl;
637 LONG refCount;
638 } Disp;
639
640 typedef struct _contain
641 {
642 const IConnectionPointContainerVtbl *vtbl;
643 LONG refCount;
644
645 UINT ptCount;
646 IConnectionPoint **pt;
647 } Contain;
648
649 typedef struct _cntptn
650 {
651 const IConnectionPointVtbl *vtbl;
652 LONG refCount;
653
654 Contain *container;
655 GUID id;
656 UINT sinkCount;
657 IUnknown **sink;
658 } ConPt;
659
660 typedef struct _enum
661 {
662 const IEnumConnectionsVtbl *vtbl;
663 LONG refCount;
664
665 UINT idx;
666 ConPt *pt;
667 } EnumCon;
668
669 typedef struct _enumpt
670 {
671 const IEnumConnectionPointsVtbl *vtbl;
672 LONG refCount;
673
674 int idx;
675 Contain *container;
676 } EnumPt;
677
678
679 static HRESULT WINAPI Disp_QueryInterface(
680 IDispatch* This,
681 REFIID riid,
682 void **ppvObject)
683 {
684 *ppvObject = NULL;
685
686 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch))
687 {
688 *ppvObject = This;
689 }
690
691 if (*ppvObject)
692 {
693 IUnknown_AddRef(This);
694 return S_OK;
695 }
696
697 trace("no interface\n");
698 return E_NOINTERFACE;
699 }
700
701 static ULONG WINAPI Disp_AddRef(IDispatch* This)
702 {
703 Disp *iface = (Disp*)This;
704 return InterlockedIncrement(&iface->refCount);
705 }
706
707 static ULONG WINAPI Disp_Release(IDispatch* This)
708 {
709 Disp *iface = (Disp*)This;
710 ULONG ret;
711
712 ret = InterlockedDecrement(&iface->refCount);
713 if (ret == 0)
714 HeapFree(GetProcessHeap(),0,This);
715 return ret;
716 }
717
718 static HRESULT WINAPI Disp_GetTypeInfoCount(
719 IDispatch* This,
720 UINT *pctinfo)
721 {
722 return ERROR_SUCCESS;
723 }
724
725 static HRESULT WINAPI Disp_GetTypeInfo(
726 IDispatch* This,
727 UINT iTInfo,
728 LCID lcid,
729 ITypeInfo **ppTInfo)
730 {
731 return ERROR_SUCCESS;
732 }
733
734 static HRESULT WINAPI Disp_GetIDsOfNames(
735 IDispatch* This,
736 REFIID riid,
737 LPOLESTR *rgszNames,
738 UINT cNames,
739 LCID lcid,
740 DISPID *rgDispId)
741 {
742 return ERROR_SUCCESS;
743 }
744
745 static HRESULT WINAPI Disp_Invoke(
746 IDispatch* This,
747 DISPID dispIdMember,
748 REFIID riid,
749 LCID lcid,
750 WORD wFlags,
751 DISPPARAMS *pDispParams,
752 VARIANT *pVarResult,
753 EXCEPINFO *pExcepInfo,
754 UINT *puArgErr)
755 {
756 trace("%p %x %p %x %x %p %p %p %p\n",This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr);
757
758 ok(dispIdMember == 0xa0 || dispIdMember == 0xa1, "Unknown dispIdMember\n");
759 ok(pDispParams != NULL, "Invoked with NULL pDispParams\n");
760 ok(wFlags == DISPATCH_METHOD, "Wrong flags %x\n",wFlags);
761 ok(lcid == 0,"Wrong lcid %x\n",lcid);
762 if (dispIdMember == 0xa0)
763 {
764 ok(pDispParams->cArgs == 0, "params.cArgs = %d\n", pDispParams->cArgs);
765 ok(pDispParams->cNamedArgs == 0, "params.cNamedArgs = %d\n", pDispParams->cArgs);
766 ok(pDispParams->rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", pDispParams->rgdispidNamedArgs);
767 ok(pDispParams->rgvarg == NULL, "params.rgvarg = %p\n", pDispParams->rgvarg);
768 }
769 else if (dispIdMember == 0xa1)
770 {
771 ok(pDispParams->cArgs == 2, "params.cArgs = %d\n", pDispParams->cArgs);
772 ok(pDispParams->cNamedArgs == 0, "params.cNamedArgs = %d\n", pDispParams->cArgs);
773 ok(pDispParams->rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", pDispParams->rgdispidNamedArgs);
774 ok(V_VT(pDispParams->rgvarg) == VT_BSTR, "V_VT(var) = %d\n", V_VT(pDispParams->rgvarg));
775 ok(V_I4(pDispParams->rgvarg) == 0xdeadcafe , "failed %p\n", V_BSTR(pDispParams->rgvarg));
776 ok(V_VT(pDispParams->rgvarg+1) == VT_I4, "V_VT(var) = %d\n", V_VT(pDispParams->rgvarg+1));
777 ok(V_I4(pDispParams->rgvarg+1) == 0xdeadbeef, "failed %x\n", V_I4(pDispParams->rgvarg+1));
778 }
779
780 return ERROR_SUCCESS;
781 }
782
783 static const IDispatchVtbl disp_vtbl = {
784 Disp_QueryInterface,
785 Disp_AddRef,
786 Disp_Release,
787
788 Disp_GetTypeInfoCount,
789 Disp_GetTypeInfo,
790 Disp_GetIDsOfNames,
791 Disp_Invoke
792 };
793
794 static HRESULT WINAPI Enum_QueryInterface(
795 IEnumConnections* This,
796 REFIID riid,
797 void **ppvObject)
798 {
799 *ppvObject = NULL;
800
801 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IEnumConnections))
802 {
803 *ppvObject = This;
804 }
805
806 if (*ppvObject)
807 {
808 IUnknown_AddRef(This);
809 return S_OK;
810 }
811
812 trace("no interface\n");
813 return E_NOINTERFACE;
814 }
815
816 static ULONG WINAPI Enum_AddRef(IEnumConnections* This)
817 {
818 EnumCon *iface = (EnumCon*)This;
819 return InterlockedIncrement(&iface->refCount);
820 }
821
822 static ULONG WINAPI Enum_Release(IEnumConnections* This)
823 {
824 EnumCon *iface = (EnumCon*)This;
825 ULONG ret;
826
827 ret = InterlockedDecrement(&iface->refCount);
828 if (ret == 0)
829 HeapFree(GetProcessHeap(),0,This);
830 return ret;
831 }
832
833 static HRESULT WINAPI Enum_Next(
834 IEnumConnections* This,
835 ULONG cConnections,
836 LPCONNECTDATA rgcd,
837 ULONG *pcFetched)
838 {
839 EnumCon *iface = (EnumCon*)This;
840
841 if (cConnections > 0 && iface->idx < iface->pt->sinkCount)
842 {
843 rgcd->pUnk = iface->pt->sink[iface->idx];
844 IUnknown_AddRef(iface->pt->sink[iface->idx]);
845 rgcd->dwCookie=0xff;
846 if (pcFetched)
847 *pcFetched = 1;
848 iface->idx++;
849 return S_OK;
850 }
851
852 return E_FAIL;
853 }
854
855 static HRESULT WINAPI Enum_Skip(
856 IEnumConnections* This,
857 ULONG cConnections)
858 {
859 return E_FAIL;
860 }
861
862 static HRESULT WINAPI Enum_Reset(
863 IEnumConnections* This)
864 {
865 return E_FAIL;
866 }
867
868 static HRESULT WINAPI Enum_Clone(
869 IEnumConnections* This,
870 IEnumConnections **ppEnum)
871 {
872 return E_FAIL;
873 }
874
875 static const IEnumConnectionsVtbl enum_vtbl = {
876
877 Enum_QueryInterface,
878 Enum_AddRef,
879 Enum_Release,
880 Enum_Next,
881 Enum_Skip,
882 Enum_Reset,
883 Enum_Clone
884 };
885
886 static HRESULT WINAPI ConPt_QueryInterface(
887 IConnectionPoint* This,
888 REFIID riid,
889 void **ppvObject)
890 {
891 *ppvObject = NULL;
892
893 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IConnectionPoint))
894 {
895 *ppvObject = This;
896 }
897
898 if (*ppvObject)
899 {
900 IUnknown_AddRef(This);
901 return S_OK;
902 }
903
904 trace("no interface\n");
905 return E_NOINTERFACE;
906 }
907
908 static ULONG WINAPI ConPt_AddRef(
909 IConnectionPoint* This)
910 {
911 ConPt *iface = (ConPt*)This;
912 return InterlockedIncrement(&iface->refCount);
913 }
914
915 static ULONG WINAPI ConPt_Release(
916 IConnectionPoint* This)
917 {
918 ConPt *iface = (ConPt*)This;
919 ULONG ret;
920
921 ret = InterlockedDecrement(&iface->refCount);
922 if (ret == 0)
923 {
924 if (iface->sinkCount > 0)
925 {
926 int i;
927 for (i = 0; i < iface->sinkCount; i++)
928 {
929 if (iface->sink[i])
930 IUnknown_Release(iface->sink[i]);
931 }
932 HeapFree(GetProcessHeap(),0,iface->sink);
933 }
934 HeapFree(GetProcessHeap(),0,This);
935 }
936 return ret;
937 }
938
939 static HRESULT WINAPI ConPt_GetConnectionInterface(
940 IConnectionPoint* This,
941 IID *pIID)
942 {
943 static int i = 0;
944 ConPt *iface = (ConPt*)This;
945 if (i==0)
946 {
947 i++;
948 return E_FAIL;
949 }
950 else
951 memcpy(pIID,&iface->id,sizeof(GUID));
952 return S_OK;
953 }
954
955 static HRESULT WINAPI ConPt_GetConnectionPointContainer(
956 IConnectionPoint* This,
957 IConnectionPointContainer **ppCPC)
958 {
959 ConPt *iface = (ConPt*)This;
960
961 *ppCPC = (IConnectionPointContainer*)iface->container;
962 return S_OK;
963 }
964
965 static HRESULT WINAPI ConPt_Advise(
966 IConnectionPoint* This,
967 IUnknown *pUnkSink,
968 DWORD *pdwCookie)
969 {
970 ConPt *iface = (ConPt*)This;
971
972 if (iface->sinkCount == 0)
973 iface->sink = HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown*));
974 else
975 iface->sink = HeapReAlloc(GetProcessHeap(),0,iface->sink,sizeof(IUnknown*)*(iface->sinkCount+1));
976 iface->sink[iface->sinkCount] = pUnkSink;
977 IUnknown_AddRef(pUnkSink);
978 iface->sinkCount++;
979 *pdwCookie = iface->sinkCount;
980 return S_OK;
981 }
982
983 static HRESULT WINAPI ConPt_Unadvise(
984 IConnectionPoint* This,
985 DWORD dwCookie)
986 {
987 ConPt *iface = (ConPt*)This;
988
989 if (dwCookie > iface->sinkCount)
990 return E_FAIL;
991 else
992 {
993 IUnknown_Release(iface->sink[dwCookie-1]);
994 iface->sink[dwCookie-1] = NULL;
995 }
996 return S_OK;
997 }
998
999 static HRESULT WINAPI ConPt_EnumConnections(
1000 IConnectionPoint* This,
1001 IEnumConnections **ppEnum)
1002 {
1003 EnumCon *ec;
1004
1005 ec = HeapAlloc(GetProcessHeap(),0,sizeof(EnumCon));
1006 ec->vtbl = &enum_vtbl;
1007 ec->refCount = 1;
1008 ec->pt = (ConPt*)This;
1009 ec->idx = 0;
1010 *ppEnum = (IEnumConnections*)ec;
1011
1012 return S_OK;
1013 }
1014
1015 static const IConnectionPointVtbl point_vtbl = {
1016 ConPt_QueryInterface,
1017 ConPt_AddRef,
1018 ConPt_Release,
1019
1020 ConPt_GetConnectionInterface,
1021 ConPt_GetConnectionPointContainer,
1022 ConPt_Advise,
1023 ConPt_Unadvise,
1024 ConPt_EnumConnections
1025 };
1026
1027 static HRESULT WINAPI EnumPt_QueryInterface(
1028 IEnumConnectionPoints* This,
1029 REFIID riid,
1030 void **ppvObject)
1031 {
1032 *ppvObject = NULL;
1033
1034 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IEnumConnectionPoints))
1035 {
1036 *ppvObject = This;
1037 }
1038
1039 if (*ppvObject)
1040 {
1041 IUnknown_AddRef(This);
1042 return S_OK;
1043 }
1044
1045 trace("no interface\n");
1046 return E_NOINTERFACE;
1047 }
1048
1049 static ULONG WINAPI EnumPt_AddRef(IEnumConnectionPoints* This)
1050 {
1051 EnumPt *iface = (EnumPt*)This;
1052 return InterlockedIncrement(&iface->refCount);
1053 }
1054
1055 static ULONG WINAPI EnumPt_Release(IEnumConnectionPoints* This)
1056 {
1057 EnumPt *iface = (EnumPt*)This;
1058 ULONG ret;
1059
1060 ret = InterlockedDecrement(&iface->refCount);
1061 if (ret == 0)
1062 HeapFree(GetProcessHeap(),0,This);
1063 return ret;
1064 }
1065
1066 static HRESULT WINAPI EnumPt_Next(
1067 IEnumConnectionPoints* This,
1068 ULONG cConnections,
1069 IConnectionPoint **rgcd,
1070 ULONG *pcFetched)
1071 {
1072 EnumPt *iface = (EnumPt*)This;
1073
1074 if (cConnections > 0 && iface->idx < iface->container->ptCount)
1075 {
1076 *rgcd = iface->container->pt[iface->idx];
1077 IUnknown_AddRef(iface->container->pt[iface->idx]);
1078 if (pcFetched)
1079 *pcFetched = 1;
1080 iface->idx++;
1081 return S_OK;
1082 }
1083
1084 return E_FAIL;
1085 }
1086
1087 static HRESULT WINAPI EnumPt_Skip(
1088 IEnumConnectionPoints* This,
1089 ULONG cConnections)
1090 {
1091 return E_FAIL;
1092 }
1093
1094 static HRESULT WINAPI EnumPt_Reset(
1095 IEnumConnectionPoints* This)
1096 {
1097 return E_FAIL;
1098 }
1099
1100 static HRESULT WINAPI EnumPt_Clone(
1101 IEnumConnectionPoints* This,
1102 IEnumConnectionPoints **ppEnumPt)
1103 {
1104 return E_FAIL;
1105 }
1106
1107 static const IEnumConnectionPointsVtbl enumpt_vtbl = {
1108
1109 EnumPt_QueryInterface,
1110 EnumPt_AddRef,
1111 EnumPt_Release,
1112 EnumPt_Next,
1113 EnumPt_Skip,
1114 EnumPt_Reset,
1115 EnumPt_Clone
1116 };
1117
1118 static HRESULT WINAPI Contain_QueryInterface(
1119 IConnectionPointContainer* This,
1120 REFIID riid,
1121 void **ppvObject)
1122 {
1123 *ppvObject = NULL;
1124
1125 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IConnectionPointContainer))
1126 {
1127 *ppvObject = This;
1128 }
1129
1130 if (*ppvObject)
1131 {
1132 IUnknown_AddRef(This);
1133 return S_OK;
1134 }
1135
1136 trace("no interface\n");
1137 return E_NOINTERFACE;
1138 }
1139
1140 static ULONG WINAPI Contain_AddRef(
1141 IConnectionPointContainer* This)
1142 {
1143 Contain *iface = (Contain*)This;
1144 return InterlockedIncrement(&iface->refCount);
1145 }
1146
1147 static ULONG WINAPI Contain_Release(
1148 IConnectionPointContainer* This)
1149 {
1150 Contain *iface = (Contain*)This;
1151 ULONG ret;
1152
1153 ret = InterlockedDecrement(&iface->refCount);
1154 if (ret == 0)
1155 {
1156 if (iface->ptCount > 0)
1157 {
1158 int i;
1159 for (i = 0; i < iface->ptCount; i++)
1160 IUnknown_Release(iface->pt[i]);
1161 HeapFree(GetProcessHeap(),0,iface->pt);
1162 }
1163 HeapFree(GetProcessHeap(),0,This);
1164 }
1165 return ret;
1166 }
1167
1168 static HRESULT WINAPI Contain_EnumConnectionPoints(
1169 IConnectionPointContainer* This,
1170 IEnumConnectionPoints **ppEnum)
1171 {
1172 EnumPt *ec;
1173
1174 ec = HeapAlloc(GetProcessHeap(),0,sizeof(EnumPt));
1175 ec->vtbl = &enumpt_vtbl;
1176 ec->refCount = 1;
1177 ec->idx= 0;
1178 ec->container = (Contain*)This;
1179 *ppEnum = (IEnumConnectionPoints*)ec;
1180
1181 return S_OK;
1182 }
1183
1184 static HRESULT WINAPI Contain_FindConnectionPoint(
1185 IConnectionPointContainer* This,
1186 REFIID riid,
1187 IConnectionPoint **ppCP)
1188 {
1189 Contain *iface = (Contain*)This;
1190 ConPt *pt;
1191
1192 if (!IsEqualIID(riid, &IID_NULL) || iface->ptCount ==0)
1193 {
1194 pt = HeapAlloc(GetProcessHeap(),0,sizeof(ConPt));
1195 pt->vtbl = &point_vtbl;
1196 pt->refCount = 1;
1197 pt->sinkCount = 0;
1198 pt->sink = NULL;
1199 pt->container = iface;
1200 pt->id = IID_IDispatch;
1201
1202 if (iface->ptCount == 0)
1203 iface->pt =HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown*));
1204 else
1205 iface->pt = HeapReAlloc(GetProcessHeap(),0,iface->pt,sizeof(IUnknown*)*(iface->ptCount+1));
1206 iface->pt[iface->ptCount] = (IConnectionPoint*)pt;
1207 iface->ptCount++;
1208
1209 *ppCP = (IConnectionPoint*)pt;
1210 }
1211 else
1212 {
1213 *ppCP = iface->pt[0];
1214 IUnknown_AddRef((IUnknown*)*ppCP);
1215 }
1216
1217 return S_OK;
1218 }
1219
1220 static const IConnectionPointContainerVtbl contain_vtbl = {
1221 Contain_QueryInterface,
1222 Contain_AddRef,
1223 Contain_Release,
1224
1225 Contain_EnumConnectionPoints,
1226 Contain_FindConnectionPoint
1227 };
1228
1229 static void test_IConnectionPoint(void)
1230 {
1231 HRESULT rc;
1232 ULONG ref;
1233 IConnectionPoint *point;
1234 Contain *container;
1235 Disp *dispatch;
1236 DWORD cookie = 0xffffffff;
1237 DISPPARAMS params;
1238 VARIANT vars[10];
1239
1240 if (!pIConnectionPoint_SimpleInvoke || !pConnectToConnectionPoint)
1241 {
1242 win_skip("IConnectionPoint Apis not present\n");
1243 return;
1244 }
1245
1246 container = HeapAlloc(GetProcessHeap(),0,sizeof(Contain));
1247 container->vtbl = &contain_vtbl;
1248 container->refCount = 1;
1249 container->ptCount = 0;
1250 container->pt = NULL;
1251
1252 dispatch = HeapAlloc(GetProcessHeap(),0,sizeof(Disp));
1253 dispatch->vtbl = &disp_vtbl;
1254 dispatch->refCount = 1;
1255
1256 rc = pConnectToConnectionPoint((IUnknown*)dispatch, &IID_NULL, TRUE, (IUnknown*)container, &cookie, &point);
1257 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
1258 ok(point != NULL, "returned ConnectionPoint is NULL\n");
1259 ok(cookie != 0xffffffff, "invalid cookie returned\n");
1260
1261 rc = pIConnectionPoint_SimpleInvoke(point,0xa0,NULL);
1262 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
1263
1264 if (pSHPackDispParams)
1265 {
1266 memset(&params, 0xc0, sizeof(params));
1267 memset(vars, 0xc0, sizeof(vars));
1268 rc = pSHPackDispParams(&params, vars, 2, VT_I4, 0xdeadbeef, VT_BSTR, 0xdeadcafe);
1269 ok(rc == S_OK, "SHPackDispParams failed: %08x\n", rc);
1270
1271 rc = pIConnectionPoint_SimpleInvoke(point,0xa1,&params);
1272 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
1273 }
1274 else
1275 win_skip("pSHPackDispParams not present\n");
1276
1277 rc = pConnectToConnectionPoint(NULL, &IID_NULL, FALSE, (IUnknown*)container, &cookie, NULL);
1278 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
1279
1280 /* MSDN says this should be required but it crashs on XP
1281 IUnknown_Release(point);
1282 */
1283 ref = IUnknown_Release((IUnknown*)container);
1284 ok(ref == 0, "leftover IConnectionPointContainer reference %i\n",ref);
1285 ref = IUnknown_Release((IUnknown*)dispatch);
1286 ok(ref == 0, "leftover IDispatch reference %i\n",ref);
1287 }
1288
1289 typedef struct _propbag
1290 {
1291 const IPropertyBagVtbl *vtbl;
1292 LONG refCount;
1293
1294 } PropBag;
1295
1296
1297 static HRESULT WINAPI Prop_QueryInterface(
1298 IPropertyBag* This,
1299 REFIID riid,
1300 void **ppvObject)
1301 {
1302 *ppvObject = NULL;
1303
1304 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IPropertyBag))
1305 {
1306 *ppvObject = This;
1307 }
1308
1309 if (*ppvObject)
1310 {
1311 IUnknown_AddRef(This);
1312 return S_OK;
1313 }
1314
1315 trace("no interface\n");
1316 return E_NOINTERFACE;
1317 }
1318
1319 static ULONG WINAPI Prop_AddRef(
1320 IPropertyBag* This)
1321 {
1322 PropBag *iface = (PropBag*)This;
1323 return InterlockedIncrement(&iface->refCount);
1324 }
1325
1326 static ULONG WINAPI Prop_Release(
1327 IPropertyBag* This)
1328 {
1329 PropBag *iface = (PropBag*)This;
1330 ULONG ret;
1331
1332 ret = InterlockedDecrement(&iface->refCount);
1333 if (ret == 0)
1334 HeapFree(GetProcessHeap(),0,This);
1335 return ret;
1336 }
1337
1338 static HRESULT WINAPI Prop_Read(
1339 IPropertyBag* This,
1340 LPCOLESTR pszPropName,
1341 VARIANT *pVar,
1342 IErrorLog *pErrorLog)
1343 {
1344 V_VT(pVar) = VT_BLOB|VT_BYREF;
1345 V_BYREF(pVar) = (LPVOID)0xdeadcafe;
1346 return S_OK;
1347 }
1348
1349 static HRESULT WINAPI Prop_Write(
1350 IPropertyBag* This,
1351 LPCOLESTR pszPropName,
1352 VARIANT *pVar)
1353 {
1354 return S_OK;
1355 }
1356
1357
1358 static const IPropertyBagVtbl prop_vtbl = {
1359 Prop_QueryInterface,
1360 Prop_AddRef,
1361 Prop_Release,
1362
1363 Prop_Read,
1364 Prop_Write
1365 };
1366
1367 static void test_SHPropertyBag_ReadLONG(void)
1368 {
1369 PropBag *pb;
1370 HRESULT rc;
1371 LONG out;
1372 static const WCHAR szName1[] = {'n','a','m','e','1',0};
1373
1374 if (!pSHPropertyBag_ReadLONG)
1375 {
1376 win_skip("SHPropertyBag_ReadLONG not present\n");
1377 return;
1378 }
1379
1380 pb = HeapAlloc(GetProcessHeap(),0,sizeof(PropBag));
1381 pb->refCount = 1;
1382 pb->vtbl = &prop_vtbl;
1383
1384 out = 0xfeedface;
1385 rc = pSHPropertyBag_ReadLONG(NULL, szName1, &out);
1386 ok(rc == E_INVALIDARG || broken(rc == 0), "incorrect return %x\n",rc);
1387 ok(out == 0xfeedface, "value should not have changed\n");
1388 rc = pSHPropertyBag_ReadLONG((IPropertyBag*)pb, NULL, &out);
1389 ok(rc == E_INVALIDARG || broken(rc == 0) || broken(rc == 1), "incorrect return %x\n",rc);
1390 ok(out == 0xfeedface, "value should not have changed\n");
1391 rc = pSHPropertyBag_ReadLONG((IPropertyBag*)pb, szName1, NULL);
1392 ok(rc == E_INVALIDARG || broken(rc == 0) || broken(rc == 1), "incorrect return %x\n",rc);
1393 ok(out == 0xfeedface, "value should not have changed\n");
1394 rc = pSHPropertyBag_ReadLONG((IPropertyBag*)pb, szName1, &out);
1395 ok(rc == DISP_E_BADVARTYPE || broken(rc == 0) || broken(rc == 1), "incorrect return %x\n",rc);
1396 ok(out == 0xfeedface || broken(out == 0xfeedfa00), "value should not have changed %x\n",out);
1397 IUnknown_Release((IUnknown*)pb);
1398 }
1399
1400 START_TEST(ordinal)
1401 {
1402 hShlwapi = GetModuleHandleA("shlwapi.dll");
1403
1404 pGetAcceptLanguagesA = (void*)GetProcAddress(hShlwapi, (LPSTR)14);
1405 pSHSearchMapInt = (void*)GetProcAddress(hShlwapi, (LPSTR)198);
1406 pSHAllocShared=(void*)GetProcAddress(hShlwapi,(char*)7);
1407 pSHLockShared=(void*)GetProcAddress(hShlwapi,(char*)8);
1408 pSHUnlockShared=(void*)GetProcAddress(hShlwapi,(char*)9);
1409 pSHFreeShared=(void*)GetProcAddress(hShlwapi,(char*)10);
1410 pSHPackDispParams=(void*)GetProcAddress(hShlwapi,(char*)282);
1411 pIConnectionPoint_SimpleInvoke=(void*)GetProcAddress(hShlwapi,(char*)284);
1412 pIConnectionPoint_InvokeWithCancel=(void*)GetProcAddress(hShlwapi,(char*)283);
1413 pConnectToConnectionPoint=(void*)GetProcAddress(hShlwapi,(char*)168);
1414 pSHPropertyBag_ReadLONG=(void*)GetProcAddress(hShlwapi,(char*)496);
1415
1416 hmlang = LoadLibraryA("mlang.dll");
1417 pLcidToRfc1766A = (void *)GetProcAddress(hmlang, "LcidToRfc1766A");
1418
1419 test_GetAcceptLanguagesA();
1420 test_SHSearchMapInt();
1421 test_alloc_shared();
1422 test_fdsa();
1423 test_GetShellSecurityDescriptor();
1424 test_SHPackDispParams();
1425 test_IConnectionPoint();
1426 test_SHPropertyBag_ReadLONG();
1427 }