Keep track of per-column information inside the listview.
[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   char 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 != -1u, "find returned a container");
300
301       /* Check size */
302       if (inserted && inserted->ulSize & 0x3)
303       {
304         /* Contained */
305         ok(inserted[-1].ulId == -1u, "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   ok(hRet == E_INVALIDARG, "allowed bad element size");
368
369   inserted->ulSize = 44;
370   inserted->ulId = -1;
371   hRet = pSHLWAPI_20(&list, inserted);
372   ok(hRet == E_INVALIDARG, "allowed adding a container");
373
374   item = SHLWAPI_CLIST_items;
375
376   /* Look for non-existing item in populated list */
377   inserted = pSHLWAPI_22(list, 99999999);
378   ok(inserted == NULL, "found a non-existing item");
379
380   while (item->ulSize)
381   {
382     /* Delete items */
383     BOOL bRet = pSHLWAPI_21(&list, item->ulId);
384     ok(bRet == TRUE, "couldn't find item to delete");
385     item++;
386   }
387
388   /* Look for non-existing item in empty list */
389   inserted = pSHLWAPI_22(list, 99999999);
390   ok(inserted == NULL, "found an item in empty list");
391
392   /* Create a list by reading in data */
393   InitDummyStream(&streamobj);
394
395   hRet = pSHLWAPI_18(&streamobj, &list);
396   ok(hRet == S_OK, "failed create from Read()");
397   if (hRet == S_OK)
398   {
399     ok(streamobj.readbeyondend == FALSE, "read beyond end");
400     /* 2 calls per item, but only 1 for the terminator */
401     ok(streamobj.readcalls == sizeof(SHLWAPI_CLIST_items)/sizeof(SHLWAPI_CLIST)*2-1,
402        "wrong call count");
403     ok(streamobj.writecalls == 0, "called Write() from create");
404     ok(streamobj.seekcalls == 0,"called Seek() from create");
405
406     item = SHLWAPI_CLIST_items;
407
408     /* Check the items were added correctly */
409     while (item->ulSize)
410     {
411       inserted = pSHLWAPI_22(list, item->ulId);
412       ok(inserted != NULL, "lost after adding");
413
414       ok(!inserted || inserted->ulId != -1, "find returned a container");
415
416       /* Check size */
417       if (inserted && inserted->ulSize & 0x3)
418       {
419         /* Contained */
420         ok(inserted[-1].ulId == -1, "invalid size is not countained");
421         ok(inserted[-1].ulSize > inserted->ulSize+sizeof(SHLWAPI_CLIST),
422            "container too small");
423       }
424       else if (inserted)
425       {
426         ok(inserted->ulSize==item->ulSize+sizeof(SHLWAPI_CLIST),
427            "id %ld size wrong (%ld!=%ld)", inserted->ulId, inserted->ulSize,
428            item->ulSize+sizeof(SHLWAPI_CLIST));
429       }
430       ok(!inserted || inserted->ulId==item->ulId, "find got wrong item");
431       if (inserted)
432       {
433         BOOL bDataOK = TRUE;
434         char *bufftest = (char*)inserted;
435
436         for (i = 0; i < inserted->ulSize - sizeof(SHLWAPI_CLIST); i++)
437           if (bufftest[sizeof(SHLWAPI_CLIST)+i] != i*2)
438             bDataOK = FALSE;
439
440         ok(bDataOK == TRUE, "data corrupted on insert");
441       }
442       item++;
443     }
444   }
445
446   /* Failure cases for reading */
447   InitDummyStream(&streamobj);
448   streamobj.failreadcall = TRUE;
449   hRet = pSHLWAPI_18(&streamobj, &list);
450   ok(hRet == STG_E_ACCESSDENIED, "changed object failure return");
451   ok(streamobj.readbeyondend == FALSE, "read beyond end");
452   ok(streamobj.readcalls == 1, "called object after read failure");
453   ok(streamobj.writecalls == 0,"called Write() after read failure");
454   ok(streamobj.seekcalls == 0,"called Seek() after read failure");
455
456   /* Read returns large object */
457   InitDummyStream(&streamobj);
458   streamobj.readreturnlarge = TRUE;
459   hRet = pSHLWAPI_18(&streamobj, &list);
460   ok(hRet == S_OK, "failed create from Read() with large item");
461   ok(streamobj.readbeyondend == FALSE, "read beyond end");
462   ok(streamobj.readcalls == 1,"wrong call count");
463   ok(streamobj.writecalls == 0,"called Write() after read failure");
464   ok(streamobj.seekcalls == 2,"wrong Seek() call count (%d)", streamobj.seekcalls);
465
466   pSHLWAPI_19(list);
467 }
468
469 static void test_SHLWAPI_166(void)
470 {
471   _IDummyStream streamobj;
472   BOOL bRet;
473
474   if (!pSHLWAPI_166)
475     return;
476
477   InitDummyStream(&streamobj);
478   bRet = pSHLWAPI_166(&streamobj);
479
480   ok(bRet == TRUE, "failed before seek adjusted");
481   ok(streamobj.readcalls == 0, "called Read()");
482   ok(streamobj.writecalls == 0, "called Write()");
483   ok(streamobj.seekcalls == 0, "called Seek()");
484   ok(streamobj.statcalls == 1, "wrong call count");
485
486   streamobj.statcalls = 0;
487   streamobj.pos.QuadPart = 50001;
488
489   bRet = pSHLWAPI_166(&streamobj);
490
491   ok(bRet == FALSE, "failed after seek adjusted");
492   ok(streamobj.readcalls == 0, "called Read()");
493   ok(streamobj.writecalls == 0, "called Write()");
494   ok(streamobj.seekcalls == 0, "called Seek()");
495   ok(streamobj.statcalls == 1, "wrong call count");
496
497   /* Failure cases */
498   InitDummyStream(&streamobj);
499   streamobj.pos.QuadPart = 50001;
500   streamobj.failstatcall = TRUE; /* 1: Stat() Bad, Read() OK */
501   bRet = pSHLWAPI_166(&streamobj);
502   ok(bRet == FALSE, "should be FALSE after read is OK");
503   ok(streamobj.readcalls == 1, "wrong call count");
504   ok(streamobj.writecalls == 0, "called Write()");
505   ok(streamobj.seekcalls == 1, "wrong call count");
506   ok(streamobj.statcalls == 1, "wrong call count");
507   ok(streamobj.pos.QuadPart == 0, "Didn't seek to start");
508
509   InitDummyStream(&streamobj);
510   streamobj.pos.QuadPart = 50001;
511   streamobj.failstatcall = TRUE;
512   streamobj.failreadcall = TRUE; /* 2: Stat() Bad, Read() Bad Also */
513   bRet = pSHLWAPI_166(&streamobj);
514   ok(bRet == TRUE, "Should be true after read fails");
515   ok(streamobj.readcalls == 1, "wrong call count");
516   ok(streamobj.writecalls == 0, "called Write()");
517   ok(streamobj.seekcalls == 0, "Called Seek()");
518   ok(streamobj.statcalls == 1, "wrong call count");
519   ok(streamobj.pos.QuadPart == 50001, "called Seek() after read failed");
520 }
521
522 static void test_SHLWAPI_184(void)
523 {
524   _IDummyStream streamobj;
525   char buff[256];
526   HRESULT hRet;
527
528   if (!pSHLWAPI_184)
529     return;
530
531   InitDummyStream(&streamobj);
532   hRet = pSHLWAPI_184(&streamobj, buff, sizeof(buff));
533
534   ok(hRet == S_OK, "failed Read()");
535   ok(streamobj.readcalls == 1, "wrong call count");
536   ok(streamobj.writecalls == 0, "called Write()");
537   ok(streamobj.seekcalls == 0, "called Seek()");
538 }
539
540 static void test_SHLWAPI_212(void)
541 {
542   _IDummyStream streamobj;
543   char buff[256];
544   HRESULT hRet;
545
546   if (!pSHLWAPI_212)
547     return;
548
549   InitDummyStream(&streamobj);
550   hRet = pSHLWAPI_212(&streamobj, buff, sizeof(buff));
551
552   ok(hRet == S_OK, "failed Write()");
553   ok(streamobj.readcalls == 0, "called Read()");
554   ok(streamobj.writecalls == 1, "wrong call count");
555   ok(streamobj.seekcalls == 0, "called Seek()");
556 }
557
558 static void test_SHLWAPI_213(void)
559 {
560   _IDummyStream streamobj;
561   ULARGE_INTEGER ul;
562   LARGE_INTEGER ll;
563   HRESULT hRet;
564
565   if (!pSHLWAPI_213 || !pSHLWAPI_214)
566     return;
567
568   InitDummyStream(&streamobj);
569   ll.QuadPart = 5000l;
570   Seek(&streamobj, ll, 0, NULL); /* Seek to 5000l */
571
572   streamobj.seekcalls = 0;
573   pSHLWAPI_213(&streamobj); /* Should rewind */
574   ok(streamobj.statcalls == 0, "called Stat()");
575   ok(streamobj.readcalls == 0, "called Read()");
576   ok(streamobj.writecalls == 0, "called Write()");
577   ok(streamobj.seekcalls == 1, "wrong call count");
578
579   ul.QuadPart = 50001;
580   hRet = pSHLWAPI_214(&streamobj, &ul);
581   ok(hRet == S_OK, "failed Stat()");
582   ok(ul.QuadPart == 0, "213 didn't rewind stream");
583 }
584
585 static void test_SHLWAPI_214(void)
586 {
587   _IDummyStream streamobj;
588   ULARGE_INTEGER ul;
589   LARGE_INTEGER ll;
590   HRESULT hRet;
591
592   if (!pSHLWAPI_214)
593     return;
594
595   InitDummyStream(&streamobj);
596   ll.QuadPart = 5000l;
597   Seek(&streamobj, ll, 0, NULL);
598   ul.QuadPart = 0;
599   streamobj.seekcalls = 0;
600   hRet = pSHLWAPI_214(&streamobj, &ul);
601
602   ok(hRet == S_OK, "failed Stat()");
603   ok(streamobj.statcalls == 1, "wrong call count");
604   ok(streamobj.readcalls == 0, "called Read()");
605   ok(streamobj.writecalls == 0, "called Write()");
606   ok(streamobj.seekcalls == 0, "called Seek()");
607   ok(ul.QuadPart == 5000l, "Stat gave wrong size");
608 }
609
610 START_TEST(clist)
611 {
612   InitFunctionPtrs();
613
614   test_CList();
615
616   test_SHLWAPI_166();
617   test_SHLWAPI_184();
618   test_SHLWAPI_212();
619   test_SHLWAPI_213();
620   test_SHLWAPI_214();
621
622   if (SHLWAPI_hshlwapi)
623     FreeLibrary(SHLWAPI_hshlwapi);
624 }