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