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