Added version information.
[wine] / dlls / shlwapi / tests / clist.c
1 /* Unit test suite for SHLWAPI Compact List and IStream ordinal functions
2  *
3  * Copyright 2002 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19
20 #include "wine/test.h"
21 #include "winbase.h"
22 #include "objbase.h"
23
24 typedef struct tagSHLWAPI_CLIST
25 {
26   ULONG ulSize;
27   ULONG ulId;
28 } SHLWAPI_CLIST, *LPSHLWAPI_CLIST;
29
30 typedef const SHLWAPI_CLIST* LPCSHLWAPI_CLIST;
31
32 /* Items to add */
33 static const SHLWAPI_CLIST SHLWAPI_CLIST_items[] =
34 {
35   {4, 1},
36   {8, 3},
37   {12, 2},
38   {16, 8},
39   {20, 9},
40   {3, 11},
41   {9, 82},
42   {33, 16},
43   {32, 55},
44   {24, 100},
45   {39, 116},
46   { 0, 0}
47 };
48
49 /* Dummy IStream object for testing calls */
50 typedef struct
51 {
52   void* lpVtbl;
53   ULONG ref;
54   int   readcalls;
55   BOOL  failreadcall;
56   BOOL  failreadsize;
57   BOOL  readbeyondend;
58   BOOL  readreturnlarge;
59   int   writecalls;
60   BOOL  failwritecall;
61   BOOL  failwritesize;
62   int   seekcalls;
63   int   statcalls;
64   BOOL  failstatcall;
65   LPCSHLWAPI_CLIST item;
66   ULARGE_INTEGER   pos;
67 } _IDummyStream;
68
69 static
70 HRESULT WINAPI QueryInterface(_IDummyStream *This,REFIID riid, LPVOID *ppvObj)
71 {
72   return S_OK;
73 }
74
75 static ULONG WINAPI AddRef(_IDummyStream *This)
76 {
77   return ++This->ref;
78 }
79
80 static ULONG WINAPI Release(_IDummyStream *This)
81 {
82   return --This->ref;
83 }
84
85 static HRESULT WINAPI Read(_IDummyStream* This, LPVOID lpMem, ULONG ulSize,
86                            PULONG lpRead)
87 {
88   HRESULT hRet = S_OK;
89   ++This->readcalls;
90
91   if (This->failreadcall)
92   {
93     return STG_E_ACCESSDENIED;
94   }
95   else if (This->failreadsize)
96   {
97     *lpRead = ulSize + 8;
98     return S_OK;
99   }
100   else if (This->readreturnlarge)
101   {
102     *((ULONG*)lpMem) = 0xffff01;
103     *lpRead = ulSize;
104     This->readreturnlarge = FALSE;
105     return S_OK;
106   }
107   if (ulSize == sizeof(ULONG))
108   {
109     /* Read size of item */
110     *((ULONG*)lpMem) = This->item->ulSize ? This->item->ulSize + sizeof(SHLWAPI_CLIST) : 0;
111     *lpRead = ulSize;
112   }
113   else
114   {
115     unsigned int i;
116     char* buff = (char*)lpMem;
117
118     /* Read item data */
119     if (!This->item->ulSize)
120     {
121       This->readbeyondend = TRUE;
122       *lpRead = 0;
123       return E_FAIL; /* Should never happen */
124     }
125     *((ULONG*)lpMem) = This->item->ulId;
126     *lpRead = ulSize;
127
128     for (i = 0; i < This->item->ulSize; i++)
129       buff[4+i] = i*2;
130
131     This->item++;
132   }
133   return hRet;
134 }
135
136 static HRESULT WINAPI Write(_IDummyStream* This, LPVOID lpMem, ULONG ulSize,
137                             PULONG lpWritten)
138 {
139   HRESULT hRet = S_OK;
140
141   ++This->writecalls;
142   if (This->failwritecall)
143   {
144     return STG_E_ACCESSDENIED;
145   }
146   else if (This->failwritesize)
147   {
148     *lpWritten = 0;
149   }
150   else
151     *lpWritten = ulSize;
152   return hRet;
153 }
154
155 static HRESULT WINAPI Seek(_IDummyStream* This, LARGE_INTEGER dlibMove,
156                            DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition)
157 {
158   ++This->seekcalls;
159   This->pos.QuadPart = dlibMove.QuadPart;
160   if (plibNewPosition)
161     plibNewPosition->QuadPart = dlibMove.QuadPart;
162   return S_OK;
163 }
164
165 static HRESULT WINAPI Stat(_IDummyStream* This, STATSTG* pstatstg,
166                            DWORD grfStatFlag)
167 {
168   ++This->statcalls;
169   if (This->failstatcall)
170     return E_FAIL;
171   if (pstatstg)
172     pstatstg->cbSize.QuadPart = This->pos.QuadPart;
173   return S_OK;
174 }
175
176 /* VTable */
177 static void* iclvt[] =
178 {
179   QueryInterface,
180   AddRef,
181   Release,
182   Read,
183   Write,
184   Seek,
185   NULL, /* SetSize */
186   NULL, /* CopyTo */
187   NULL, /* Commit */
188   NULL, /* Revert */
189   NULL, /* LockRegion */
190   NULL, /* UnlockRegion */
191   Stat,
192   NULL  /* Clone */
193 };
194
195 /* Function ptrs for ordinal calls */
196 static HMODULE SHLWAPI_hshlwapi = 0;
197
198 static VOID    (WINAPI *pSHLWAPI_19)(LPSHLWAPI_CLIST);
199 static HRESULT (WINAPI *pSHLWAPI_20)(LPSHLWAPI_CLIST*,LPCSHLWAPI_CLIST);
200 static BOOL    (WINAPI *pSHLWAPI_21)(LPSHLWAPI_CLIST*,ULONG);
201 static LPSHLWAPI_CLIST (WINAPI *pSHLWAPI_22)(LPSHLWAPI_CLIST,ULONG);
202 static HRESULT (WINAPI *pSHLWAPI_17)(_IDummyStream*,LPSHLWAPI_CLIST);
203 static HRESULT (WINAPI *pSHLWAPI_18)(_IDummyStream*,LPSHLWAPI_CLIST*);
204
205 static BOOL    (WINAPI *pSHLWAPI_166)(_IDummyStream*);
206 static HRESULT (WINAPI *pSHLWAPI_184)(_IDummyStream*,LPVOID,ULONG);
207 static HRESULT (WINAPI *pSHLWAPI_212)(_IDummyStream*,LPCVOID,ULONG);
208 static HRESULT (WINAPI *pSHLWAPI_213)(_IDummyStream*);
209 static HRESULT (WINAPI *pSHLWAPI_214)(_IDummyStream*,ULARGE_INTEGER*);
210
211
212 static void InitFunctionPtrs()
213 {
214   SHLWAPI_hshlwapi = LoadLibraryA("shlwapi.dll");
215   ok(SHLWAPI_hshlwapi != 0, "LoadLibrary failed");
216   if (SHLWAPI_hshlwapi)
217   {
218     pSHLWAPI_17 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)17);
219     ok(pSHLWAPI_17 != 0, "No Ordinal 17");
220     pSHLWAPI_18 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)18);
221     ok(pSHLWAPI_18 != 0, "No Ordinal 18");
222     pSHLWAPI_19 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)19);
223     ok(pSHLWAPI_19 != 0, "No Ordinal 19");
224     pSHLWAPI_20 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)20);
225     ok(pSHLWAPI_20 != 0, "No Ordinal 20");
226     pSHLWAPI_21 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)21);
227     ok(pSHLWAPI_21 != 0, "No Ordinal 21");
228     pSHLWAPI_22 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)22);
229     ok(pSHLWAPI_22 != 0, "No Ordinal 22");
230     pSHLWAPI_166 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)166);
231     ok(pSHLWAPI_166 != 0, "No Ordinal 166");
232     pSHLWAPI_184 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)184);
233     ok(pSHLWAPI_184 != 0, "No Ordinal 184");
234     pSHLWAPI_212 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)212);
235     ok(pSHLWAPI_212 != 0, "No Ordinal 212");
236     pSHLWAPI_213 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)213);
237     ok(pSHLWAPI_213 != 0, "No Ordinal 213");
238     pSHLWAPI_214 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)214);
239     ok(pSHLWAPI_214 != 0, "No Ordinal 214");
240   }
241 }
242
243 static void InitDummyStream(_IDummyStream* iface)
244 {
245   iface->lpVtbl = (void*)iclvt;
246   iface->ref = 1;
247   iface->readcalls = 0;
248   iface->failreadcall = FALSE;
249   iface->failreadsize = FALSE;
250   iface->readbeyondend = FALSE;
251   iface->readreturnlarge = FALSE;
252   iface->writecalls = 0;
253   iface->failwritecall = FALSE;
254   iface->failwritesize = FALSE;
255   iface->seekcalls = 0;
256   iface->statcalls = 0;
257   iface->failstatcall = FALSE;
258   iface->item = SHLWAPI_CLIST_items;
259   iface->pos.QuadPart = 0;
260 }
261
262
263 static void test_CList(void)
264 {
265   _IDummyStream streamobj;
266   LPSHLWAPI_CLIST list = NULL;
267   LPCSHLWAPI_CLIST item = SHLWAPI_CLIST_items;
268   HRESULT hRet;
269   LPSHLWAPI_CLIST inserted;
270   BYTE buff[64];
271   unsigned int i;
272
273   if (!pSHLWAPI_17 || !pSHLWAPI_18 || !pSHLWAPI_19 || !pSHLWAPI_20 ||
274       !pSHLWAPI_21 || !pSHLWAPI_22)
275     return;
276
277   /* Populate a list and test the items are added correctly */
278   while (item->ulSize)
279   {
280     /* Create item and fill with data */
281     inserted = (LPSHLWAPI_CLIST)buff;
282     inserted->ulSize = item->ulSize + sizeof(SHLWAPI_CLIST);
283     inserted->ulId = item->ulId;
284     for (i = 0; i < item->ulSize; i++)
285       buff[sizeof(SHLWAPI_CLIST)+i] = i*2;
286
287     /* Add it */
288     hRet = pSHLWAPI_20(&list, inserted);
289     ok(hRet > S_OK, "failed list add");
290
291     if (hRet > S_OK)
292     {
293       ok(list && list->ulSize, "item not added");
294
295       /* Find it */
296       inserted = pSHLWAPI_22(list, item->ulId);
297       ok(inserted != NULL, "lost after adding");
298
299       ok(!inserted || inserted->ulId != -1, "find returned a container");
300
301       /* Check size */
302       if (inserted && inserted->ulSize & 0x3)
303       {
304         /* Contained */
305         ok(inserted[-1].ulId == -1, "invalid size is not countained");
306         ok(inserted[-1].ulSize > inserted->ulSize+sizeof(SHLWAPI_CLIST),
307            "container too small");
308       }
309       else if (inserted)
310       {
311         ok(inserted->ulSize==item->ulSize+sizeof(SHLWAPI_CLIST),
312            "id %ld size wrong (%ld!=%ld)", inserted->ulId, inserted->ulSize,
313            item->ulSize+sizeof(SHLWAPI_CLIST));
314       }
315       if (inserted)
316       {
317         BOOL bDataOK = TRUE;
318         LPBYTE bufftest = (LPBYTE)inserted;
319
320         for (i = 0; i < inserted->ulSize - sizeof(SHLWAPI_CLIST); i++)
321           if (bufftest[sizeof(SHLWAPI_CLIST)+i] != i*2)
322             bDataOK = FALSE;
323
324         ok(bDataOK == TRUE, "data corrupted on insert");
325       }
326       ok(!inserted || inserted->ulId==item->ulId, "find got wrong item");
327     }
328     item++;
329   }
330
331   /* Write the list */
332   InitDummyStream(&streamobj);
333
334   hRet = pSHLWAPI_17(&streamobj, list);
335   ok(hRet == S_OK, "write failed");
336   if (hRet == S_OK)
337   {
338     /* 1 call for each element, + 1 for OK (use our null element for this) */
339     ok(streamobj.writecalls == sizeof(SHLWAPI_CLIST_items)/sizeof(SHLWAPI_CLIST),
340        "wrong call count");
341     ok(streamobj.readcalls == 0,"called Read() in write");
342     ok(streamobj.seekcalls == 0,"called Seek() in write");
343   }
344
345   /* Failure cases for writing */
346   InitDummyStream(&streamobj);
347   streamobj.failwritecall = TRUE;
348   hRet = pSHLWAPI_17(&streamobj, list);
349   ok(hRet == STG_E_ACCESSDENIED, "changed object failure return");
350   ok(streamobj.writecalls == 1, "called object after failure");
351   ok(streamobj.readcalls == 0,"called Read() after failure");
352   ok(streamobj.seekcalls == 0,"called Seek() after failure");
353
354   InitDummyStream(&streamobj);
355   streamobj.failwritesize = TRUE;
356   hRet = pSHLWAPI_17(&streamobj, list);
357   ok(hRet == STG_E_MEDIUMFULL, "changed size failure return");
358   ok(streamobj.writecalls == 1, "called object after size failure");
359   ok(streamobj.readcalls == 0,"called Read() after failure");
360   ok(streamobj.seekcalls == 0,"called Seek() after failure");
361
362   /* Invalid inputs for adding */
363   inserted = (LPSHLWAPI_CLIST)buff;
364   inserted->ulSize = sizeof(SHLWAPI_CLIST) -1;
365   inserted->ulId = 33;
366   hRet = pSHLWAPI_20(&list, inserted);
367   /* The call succeeds but the item is not inserted */
368   ok(hRet == S_OK, "failed bad element size");
369   inserted = pSHLWAPI_22(list, 33);
370   ok(inserted == NULL, "inserted bad element size");
371
372   inserted = (LPSHLWAPI_CLIST)buff;
373   inserted->ulSize = 44;
374   inserted->ulId = -1;
375   hRet = pSHLWAPI_20(&list, inserted);
376   /* The call succeeds but the item is not inserted */
377   ok(hRet == S_OK, "failed adding a container");
378
379   item = SHLWAPI_CLIST_items;
380
381   /* Look for non-existing item in populated list */
382   inserted = pSHLWAPI_22(list, 99999999);
383   ok(inserted == NULL, "found a non-existing item");
384
385   while (item->ulSize)
386   {
387     /* Delete items */
388     BOOL bRet = pSHLWAPI_21(&list, item->ulId);
389     ok(bRet == TRUE, "couldn't find item to delete");
390     item++;
391   }
392
393   /* Look for non-existing item in empty list */
394   inserted = pSHLWAPI_22(list, 99999999);
395   ok(inserted == NULL, "found an item in empty list");
396
397   /* Create a list by reading in data */
398   InitDummyStream(&streamobj);
399
400   hRet = pSHLWAPI_18(&streamobj, &list);
401   ok(hRet == S_OK, "failed create from Read()");
402   if (hRet == S_OK)
403   {
404     ok(streamobj.readbeyondend == FALSE, "read beyond end");
405     /* 2 calls per item, but only 1 for the terminator */
406     ok(streamobj.readcalls == sizeof(SHLWAPI_CLIST_items)/sizeof(SHLWAPI_CLIST)*2-1,
407        "wrong call count");
408     ok(streamobj.writecalls == 0, "called Write() from create");
409     ok(streamobj.seekcalls == 0,"called Seek() from create");
410
411     item = SHLWAPI_CLIST_items;
412
413     /* Check the items were added correctly */
414     while (item->ulSize)
415     {
416       inserted = pSHLWAPI_22(list, item->ulId);
417       ok(inserted != NULL, "lost after adding");
418
419       ok(!inserted || inserted->ulId != -1, "find returned a container");
420
421       /* Check size */
422       if (inserted && inserted->ulSize & 0x3)
423       {
424         /* Contained */
425         ok(inserted[-1].ulId == -1, "invalid size is not countained");
426         ok(inserted[-1].ulSize > inserted->ulSize+sizeof(SHLWAPI_CLIST),
427            "container too small");
428       }
429       else if (inserted)
430       {
431         ok(inserted->ulSize==item->ulSize+sizeof(SHLWAPI_CLIST),
432            "id %ld size wrong (%ld!=%ld)", inserted->ulId, inserted->ulSize,
433            item->ulSize+sizeof(SHLWAPI_CLIST));
434       }
435       ok(!inserted || inserted->ulId==item->ulId, "find got wrong item");
436       if (inserted)
437       {
438         BOOL bDataOK = TRUE;
439         LPBYTE bufftest = (LPBYTE)inserted;
440
441         for (i = 0; i < inserted->ulSize - sizeof(SHLWAPI_CLIST); i++)
442           if (bufftest[sizeof(SHLWAPI_CLIST)+i] != i*2)
443             bDataOK = FALSE;
444
445         ok(bDataOK == TRUE, "data corrupted on insert");
446       }
447       item++;
448     }
449   }
450
451   /* Failure cases for reading */
452   InitDummyStream(&streamobj);
453   streamobj.failreadcall = TRUE;
454   hRet = pSHLWAPI_18(&streamobj, &list);
455   ok(hRet == STG_E_ACCESSDENIED, "changed object failure return");
456   ok(streamobj.readbeyondend == FALSE, "read beyond end");
457   ok(streamobj.readcalls == 1, "called object after read failure");
458   ok(streamobj.writecalls == 0,"called Write() after read failure");
459   ok(streamobj.seekcalls == 0,"called Seek() after read failure");
460
461   /* Read returns large object */
462   InitDummyStream(&streamobj);
463   streamobj.readreturnlarge = TRUE;
464   hRet = pSHLWAPI_18(&streamobj, &list);
465   ok(hRet == S_OK, "failed create from Read() with large item");
466   ok(streamobj.readbeyondend == FALSE, "read beyond end");
467   ok(streamobj.readcalls == 1,"wrong call count");
468   ok(streamobj.writecalls == 0,"called Write() after read failure");
469   ok(streamobj.seekcalls == 2,"wrong Seek() call count (%d)", streamobj.seekcalls);
470
471   pSHLWAPI_19(list);
472 }
473
474 static void test_SHLWAPI_166(void)
475 {
476   _IDummyStream streamobj;
477   BOOL bRet;
478
479   if (!pSHLWAPI_166)
480     return;
481
482   InitDummyStream(&streamobj);
483   bRet = pSHLWAPI_166(&streamobj);
484
485   ok(bRet == TRUE, "failed before seek adjusted");
486   ok(streamobj.readcalls == 0, "called Read()");
487   ok(streamobj.writecalls == 0, "called Write()");
488   ok(streamobj.seekcalls == 0, "called Seek()");
489   ok(streamobj.statcalls == 1, "wrong call count");
490
491   streamobj.statcalls = 0;
492   streamobj.pos.QuadPart = 50001;
493
494   bRet = pSHLWAPI_166(&streamobj);
495
496   ok(bRet == FALSE, "failed after seek adjusted");
497   ok(streamobj.readcalls == 0, "called Read()");
498   ok(streamobj.writecalls == 0, "called Write()");
499   ok(streamobj.seekcalls == 0, "called Seek()");
500   ok(streamobj.statcalls == 1, "wrong call count");
501
502   /* Failure cases */
503   InitDummyStream(&streamobj);
504   streamobj.pos.QuadPart = 50001;
505   streamobj.failstatcall = TRUE; /* 1: Stat() Bad, Read() OK */
506   bRet = pSHLWAPI_166(&streamobj);
507   ok(bRet == FALSE, "should be FALSE after read is OK");
508   ok(streamobj.readcalls == 1, "wrong call count");
509   ok(streamobj.writecalls == 0, "called Write()");
510   ok(streamobj.seekcalls == 1, "wrong call count");
511   ok(streamobj.statcalls == 1, "wrong call count");
512   ok(streamobj.pos.QuadPart == 0, "Didn't seek to start");
513
514   InitDummyStream(&streamobj);
515   streamobj.pos.QuadPart = 50001;
516   streamobj.failstatcall = TRUE;
517   streamobj.failreadcall = TRUE; /* 2: Stat() Bad, Read() Bad Also */
518   bRet = pSHLWAPI_166(&streamobj);
519   ok(bRet == TRUE, "Should be true after read fails");
520   ok(streamobj.readcalls == 1, "wrong call count");
521   ok(streamobj.writecalls == 0, "called Write()");
522   ok(streamobj.seekcalls == 0, "Called Seek()");
523   ok(streamobj.statcalls == 1, "wrong call count");
524   ok(streamobj.pos.QuadPart == 50001, "called Seek() after read failed");
525 }
526
527 static void test_SHLWAPI_184(void)
528 {
529   _IDummyStream streamobj;
530   char buff[256];
531   HRESULT hRet;
532
533   if (!pSHLWAPI_184)
534     return;
535
536   InitDummyStream(&streamobj);
537   hRet = pSHLWAPI_184(&streamobj, buff, sizeof(buff));
538
539   ok(hRet == S_OK, "failed Read()");
540   ok(streamobj.readcalls == 1, "wrong call count");
541   ok(streamobj.writecalls == 0, "called Write()");
542   ok(streamobj.seekcalls == 0, "called Seek()");
543 }
544
545 static void test_SHLWAPI_212(void)
546 {
547   _IDummyStream streamobj;
548   char buff[256];
549   HRESULT hRet;
550
551   if (!pSHLWAPI_212)
552     return;
553
554   InitDummyStream(&streamobj);
555   hRet = pSHLWAPI_212(&streamobj, buff, sizeof(buff));
556
557   ok(hRet == S_OK, "failed Write()");
558   ok(streamobj.readcalls == 0, "called Read()");
559   ok(streamobj.writecalls == 1, "wrong call count");
560   ok(streamobj.seekcalls == 0, "called Seek()");
561 }
562
563 static void test_SHLWAPI_213(void)
564 {
565   _IDummyStream streamobj;
566   ULARGE_INTEGER ul;
567   LARGE_INTEGER ll;
568   HRESULT hRet;
569
570   if (!pSHLWAPI_213 || !pSHLWAPI_214)
571     return;
572
573   InitDummyStream(&streamobj);
574   ll.QuadPart = 5000l;
575   Seek(&streamobj, ll, 0, NULL); /* Seek to 5000l */
576
577   streamobj.seekcalls = 0;
578   pSHLWAPI_213(&streamobj); /* Should rewind */
579   ok(streamobj.statcalls == 0, "called Stat()");
580   ok(streamobj.readcalls == 0, "called Read()");
581   ok(streamobj.writecalls == 0, "called Write()");
582   ok(streamobj.seekcalls == 1, "wrong call count");
583
584   ul.QuadPart = 50001;
585   hRet = pSHLWAPI_214(&streamobj, &ul);
586   ok(hRet == S_OK, "failed Stat()");
587   ok(ul.QuadPart == 0, "213 didn't rewind stream");
588 }
589
590 static void test_SHLWAPI_214(void)
591 {
592   _IDummyStream streamobj;
593   ULARGE_INTEGER ul;
594   LARGE_INTEGER ll;
595   HRESULT hRet;
596
597   if (!pSHLWAPI_214)
598     return;
599
600   InitDummyStream(&streamobj);
601   ll.QuadPart = 5000l;
602   Seek(&streamobj, ll, 0, NULL);
603   ul.QuadPart = 0;
604   streamobj.seekcalls = 0;
605   hRet = pSHLWAPI_214(&streamobj, &ul);
606
607   ok(hRet == S_OK, "failed Stat()");
608   ok(streamobj.statcalls == 1, "wrong call count");
609   ok(streamobj.readcalls == 0, "called Read()");
610   ok(streamobj.writecalls == 0, "called Write()");
611   ok(streamobj.seekcalls == 0, "called Seek()");
612   ok(ul.QuadPart == 5000l, "Stat gave wrong size");
613 }
614
615 START_TEST(clist)
616 {
617   InitFunctionPtrs();
618
619   test_CList();
620
621   test_SHLWAPI_166();
622   test_SHLWAPI_184();
623   test_SHLWAPI_212();
624   test_SHLWAPI_213();
625   test_SHLWAPI_214();
626
627   if (SHLWAPI_hshlwapi)
628     FreeLibrary(SHLWAPI_hshlwapi);
629 }