shlwapi/tests: Enable compilation with long types.
[wine.git] / dlls / shlwapi / tests / clist.c
blob5f88e92a5a6720e05fcd01eb393fccb9c32c0f02
1 /* Unit test suite for SHLWAPI Compact List and IStream ordinal functions
3 * Copyright 2002 Jon Griffiths
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.
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.
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
20 #define COBJMACROS
21 #include <stdarg.h>
23 #include "wine/test.h"
24 #include "windef.h"
25 #include "winbase.h"
26 #include "objbase.h"
27 #include "shlobj.h"
29 /* Items to add */
30 static const DATABLOCK_HEADER clist_items[] =
32 {4, 1},
33 {8, 3},
34 {12, 2},
35 {16, 8},
36 {20, 9},
37 {3, 11},
38 {9, 82},
39 {33, 16},
40 {32, 55},
41 {24, 100},
42 {39, 116},
43 { 0, 0}
46 /* Dummy IStream object for testing calls */
47 struct dummystream
49 IStream IStream_iface;
50 LONG ref;
51 int readcalls;
52 BOOL failreadcall;
53 BOOL failreadsize;
54 BOOL readbeyondend;
55 BOOL readreturnlarge;
56 int writecalls;
57 BOOL failwritecall;
58 BOOL failwritesize;
59 int seekcalls;
60 int statcalls;
61 BOOL failstatcall;
62 const DATABLOCK_HEADER *item;
63 ULARGE_INTEGER pos;
66 static inline struct dummystream *impl_from_IStream(IStream *iface)
68 return CONTAINING_RECORD(iface, struct dummystream, IStream_iface);
71 static HRESULT WINAPI QueryInterface(IStream *iface, REFIID riid, void **ret_iface)
73 if (IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IStream, riid)) {
74 *ret_iface = iface;
75 IStream_AddRef(iface);
76 return S_OK;
78 trace("Unexpected REFIID %s\n", wine_dbgstr_guid(riid));
79 *ret_iface = NULL;
80 return E_NOINTERFACE;
83 static ULONG WINAPI AddRef(IStream *iface)
85 struct dummystream *This = impl_from_IStream(iface);
87 return InterlockedIncrement(&This->ref);
90 static ULONG WINAPI Release(IStream *iface)
92 struct dummystream *This = impl_from_IStream(iface);
94 return InterlockedDecrement(&This->ref);
97 static HRESULT WINAPI Read(IStream *iface, void *lpMem, ULONG ulSize, ULONG *lpRead)
99 struct dummystream *This = impl_from_IStream(iface);
100 HRESULT hRet = S_OK;
102 ++This->readcalls;
103 if (This->failreadcall)
105 return STG_E_ACCESSDENIED;
107 else if (This->failreadsize)
109 *lpRead = ulSize + 8;
110 return S_OK;
112 else if (This->readreturnlarge)
114 *((ULONG*)lpMem) = 0xffff01;
115 *lpRead = ulSize;
116 This->readreturnlarge = FALSE;
117 return S_OK;
119 if (ulSize == sizeof(ULONG))
121 /* Read size of item */
122 *((ULONG*)lpMem) = This->item->cbSize ? This->item->cbSize + sizeof(DATABLOCK_HEADER) : 0;
123 *lpRead = ulSize;
125 else
127 unsigned int i;
128 char* buff = lpMem;
130 /* Read item data */
131 if (!This->item->cbSize)
133 This->readbeyondend = TRUE;
134 *lpRead = 0;
135 return E_FAIL; /* Should never happen */
137 *((ULONG *)lpMem) = This->item->dwSignature;
138 *lpRead = ulSize;
140 for (i = 0; i < This->item->cbSize; i++)
141 buff[4+i] = i*2;
143 This->item++;
145 return hRet;
148 static HRESULT WINAPI Write(IStream *iface, const void *lpMem, ULONG ulSize, ULONG *lpWritten)
150 struct dummystream *This = impl_from_IStream(iface);
151 HRESULT hRet = S_OK;
153 ++This->writecalls;
154 if (This->failwritecall)
156 return STG_E_ACCESSDENIED;
158 else if (This->failwritesize)
160 *lpWritten = 0;
162 else
163 *lpWritten = ulSize;
164 return hRet;
167 static HRESULT WINAPI Seek(IStream *iface, LARGE_INTEGER dlibMove, DWORD dwOrigin,
168 ULARGE_INTEGER *plibNewPosition)
170 struct dummystream *This = impl_from_IStream(iface);
172 ++This->seekcalls;
173 This->pos.QuadPart = dlibMove.QuadPart;
174 if (plibNewPosition)
175 plibNewPosition->QuadPart = dlibMove.QuadPart;
176 return S_OK;
179 static HRESULT WINAPI Stat(IStream *iface, STATSTG *pstatstg, DWORD grfStatFlag)
181 struct dummystream *This = impl_from_IStream(iface);
183 ++This->statcalls;
184 if (This->failstatcall)
185 return E_FAIL;
186 if (pstatstg)
187 pstatstg->cbSize.QuadPart = This->pos.QuadPart;
188 return S_OK;
191 /* VTable */
192 static IStreamVtbl iclvt =
194 QueryInterface,
195 AddRef,
196 Release,
197 Read,
198 Write,
199 Seek,
200 NULL, /* SetSize */
201 NULL, /* CopyTo */
202 NULL, /* Commit */
203 NULL, /* Revert */
204 NULL, /* LockRegion */
205 NULL, /* UnlockRegion */
206 Stat,
207 NULL /* Clone */
210 /* Function ptrs for ordinal calls */
211 static HMODULE SHLWAPI_hshlwapi = 0;
213 static void (WINAPI *pSHFreeDataBlockList)(DATABLOCK_HEADER *);
214 static HRESULT (WINAPI *pSHAddDataBlock)(DATABLOCK_HEADER **, DATABLOCK_HEADER *);
215 static BOOL (WINAPI *pSHRemoveDataBlock)(DATABLOCK_HEADER **,ULONG);
216 static DATABLOCK_HEADER *(WINAPI *pSHFindDataBlock)(DATABLOCK_HEADER *,ULONG);
217 static HRESULT (WINAPI *pSHWriteDataBlockList)(IStream *, DATABLOCK_HEADER *);
218 static HRESULT (WINAPI *pSHReadDataBlockList)(IStream *, DATABLOCK_HEADER **);
220 static BOOL (WINAPI *pSHIsEmptyStream)(IStream *);
221 static HRESULT (WINAPI *pIStream_Read)(IStream *, void *, ULONG);
222 static HRESULT (WINAPI *pIStream_Write)(IStream *, const void *, ULONG);
223 static HRESULT (WINAPI *pIStream_Reset)(IStream *);
224 static HRESULT (WINAPI *pIStream_Size)(IStream *, ULARGE_INTEGER *);
227 static BOOL InitFunctionPtrs(void)
229 SHLWAPI_hshlwapi = GetModuleHandleA("shlwapi.dll");
231 /* SHCreateStreamOnFileEx was introduced in shlwapi v6.0 */
232 if(!GetProcAddress(SHLWAPI_hshlwapi, "SHCreateStreamOnFileEx")){
233 win_skip("Too old shlwapi version\n");
234 return FALSE;
237 pSHWriteDataBlockList = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)17);
238 ok(pSHWriteDataBlockList != 0, "No Ordinal 17\n");
239 pSHReadDataBlockList = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)18);
240 ok(pSHReadDataBlockList != 0, "No Ordinal 18\n");
241 pSHFreeDataBlockList = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)19);
242 ok(pSHFreeDataBlockList != 0, "No Ordinal 19\n");
243 pSHAddDataBlock = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)20);
244 ok(pSHAddDataBlock != 0, "No Ordinal 20\n");
245 pSHRemoveDataBlock = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)21);
246 ok(pSHRemoveDataBlock != 0, "No Ordinal 21\n");
247 pSHFindDataBlock = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)22);
248 ok(pSHFindDataBlock != 0, "No Ordinal 22\n");
249 pSHIsEmptyStream = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)166);
250 ok(pSHIsEmptyStream != 0, "No Ordinal 166\n");
251 pIStream_Read = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)184);
252 ok(pIStream_Read != 0, "No Ordinal 184\n");
253 pIStream_Write = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)212);
254 ok(pIStream_Write != 0, "No Ordinal 212\n");
255 pIStream_Reset = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)213);
256 ok(pIStream_Reset != 0, "No Ordinal 213\n");
257 pIStream_Size = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)214);
258 ok(pIStream_Size != 0, "No Ordinal 214\n");
260 return TRUE;
263 static void InitDummyStream(struct dummystream *obj)
265 obj->IStream_iface.lpVtbl = &iclvt;
266 obj->ref = 1;
267 obj->readcalls = 0;
268 obj->failreadcall = FALSE;
269 obj->failreadsize = FALSE;
270 obj->readbeyondend = FALSE;
271 obj->readreturnlarge = FALSE;
272 obj->writecalls = 0;
273 obj->failwritecall = FALSE;
274 obj->failwritesize = FALSE;
275 obj->seekcalls = 0;
276 obj->statcalls = 0;
277 obj->failstatcall = FALSE;
278 obj->item = clist_items;
279 obj->pos.QuadPart = 0;
283 static void test_CList(void)
285 struct dummystream streamobj;
286 DATABLOCK_HEADER *list = NULL;
287 const DATABLOCK_HEADER *item = clist_items;
288 HRESULT hRet;
289 DATABLOCK_HEADER *inserted;
290 BYTE buff[64];
291 unsigned int i;
292 BOOL ret;
294 if (!pSHWriteDataBlockList || !pSHReadDataBlockList || !pSHFreeDataBlockList || !pSHAddDataBlock ||
295 !pSHRemoveDataBlock || !pSHFindDataBlock)
296 return;
298 /* Populate a list and test the items are added correctly */
299 while (item->cbSize)
301 /* Create item and fill with data */
302 inserted = (DATABLOCK_HEADER *)buff;
303 inserted->cbSize = item->cbSize + sizeof(DATABLOCK_HEADER);
304 inserted->dwSignature = item->dwSignature;
305 for (i = 0; i < item->cbSize; i++)
306 buff[sizeof(DATABLOCK_HEADER) + i] = i * 2;
308 ret = pSHAddDataBlock(&list, inserted);
309 ok(ret == TRUE, "got %d\n", ret);
311 if (ret == TRUE)
313 ok(list && list->cbSize, "item not added\n");
315 inserted = pSHFindDataBlock(list, item->dwSignature);
316 ok(inserted != NULL, "lost after adding\n");
318 ok(!inserted || inserted->dwSignature != ~0U, "find returned a container\n");
320 /* Check size */
321 if (inserted && (inserted->cbSize & 0x3))
323 /* Contained */
324 ok(inserted[-1].dwSignature == ~0U, "invalid size is not countained\n");
325 ok(inserted[-1].cbSize > inserted->cbSize + sizeof(DATABLOCK_HEADER),
326 "container too small\n");
328 else if (inserted)
330 ok(inserted->cbSize == item->cbSize + sizeof(DATABLOCK_HEADER),
331 "id %ld wrong size %ld\n", inserted->dwSignature, inserted->cbSize);
333 if (inserted)
335 BOOL bDataOK = TRUE;
336 LPBYTE bufftest = (LPBYTE)inserted;
338 for (i = 0; i < inserted->cbSize - sizeof(DATABLOCK_HEADER); i++)
339 if (bufftest[sizeof(DATABLOCK_HEADER) + i] != i * 2)
340 bDataOK = FALSE;
342 ok(bDataOK == TRUE, "data corrupted on insert\n");
344 ok(!inserted || inserted->dwSignature == item->dwSignature, "find got wrong item\n");
346 item++;
349 /* Write the list */
350 InitDummyStream(&streamobj);
352 hRet = pSHWriteDataBlockList(&streamobj.IStream_iface, list);
353 ok(hRet == S_OK, "write failed\n");
354 if (hRet == S_OK)
356 /* 1 call for each element, + 1 for OK (use our null element for this) */
357 ok(streamobj.writecalls == ARRAY_SIZE(clist_items), "wrong call count\n");
358 ok(streamobj.readcalls == 0,"called Read() in write\n");
359 ok(streamobj.seekcalls == 0,"called Seek() in write\n");
362 /* Failure cases for writing */
363 InitDummyStream(&streamobj);
364 streamobj.failwritecall = TRUE;
365 hRet = pSHWriteDataBlockList(&streamobj.IStream_iface, list);
366 ok(hRet == STG_E_ACCESSDENIED, "changed object failure return\n");
367 ok(streamobj.writecalls == 1, "called object after failure\n");
368 ok(streamobj.readcalls == 0,"called Read() after failure\n");
369 ok(streamobj.seekcalls == 0,"called Seek() after failure\n");
371 InitDummyStream(&streamobj);
372 streamobj.failwritesize = TRUE;
373 hRet = pSHWriteDataBlockList(&streamobj.IStream_iface, list);
374 ok(hRet == STG_E_MEDIUMFULL || broken(hRet == E_FAIL) /* Win7 */,
375 "changed size failure return\n");
376 ok(streamobj.writecalls == 1, "called object after size failure\n");
377 ok(streamobj.readcalls == 0,"called Read() after failure\n");
378 ok(streamobj.seekcalls == 0,"called Seek() after failure\n");
380 /* Invalid inputs for adding */
381 inserted = (DATABLOCK_HEADER *)buff;
382 inserted->cbSize = sizeof(DATABLOCK_HEADER) - 1;
383 inserted->dwSignature = 33;
385 ret = pSHAddDataBlock(NULL, inserted);
386 ok(!ret, "got %d\n", ret);
388 ret = pSHAddDataBlock(&list, inserted);
389 ok(!ret, "got %d\n", ret);
391 inserted = pSHFindDataBlock(list, 33);
392 ok(inserted == NULL, "inserted bad element size\n");
394 inserted = (DATABLOCK_HEADER *)buff;
395 inserted->cbSize = 44;
396 inserted->dwSignature = ~0U;
398 ret = pSHAddDataBlock(&list, inserted);
399 ok(!ret, "got %d\n", ret);
401 item = clist_items;
403 /* Look for nonexistent item in populated list */
404 inserted = pSHFindDataBlock(list, 99999999);
405 ok(inserted == NULL, "found a nonexistent item\n");
407 while (item->cbSize)
409 BOOL bRet = pSHRemoveDataBlock(&list, item->dwSignature);
410 ok(bRet == TRUE, "couldn't find item to delete\n");
411 item++;
414 /* Look for nonexistent item in empty list */
415 inserted = pSHFindDataBlock(list, 99999999);
416 ok(inserted == NULL, "found an item in empty list\n");
418 /* Create a list by reading in data */
419 InitDummyStream(&streamobj);
421 hRet = pSHReadDataBlockList(&streamobj.IStream_iface, &list);
422 ok(hRet == S_OK, "failed create from Read()\n");
423 if (hRet == S_OK)
425 ok(streamobj.readbeyondend == FALSE, "read beyond end\n");
426 /* 2 calls per item, but only 1 for the terminator */
427 ok(streamobj.readcalls == ARRAY_SIZE(clist_items) * 2 - 1, "wrong call count\n");
428 ok(streamobj.writecalls == 0, "called Write() from create\n");
429 ok(streamobj.seekcalls == 0,"called Seek() from create\n");
431 item = clist_items;
433 /* Check the items were added correctly */
434 while (item->cbSize)
436 inserted = pSHFindDataBlock(list, item->dwSignature);
437 ok(inserted != NULL, "lost after adding\n");
439 ok(!inserted || inserted->dwSignature != ~0U, "find returned a container\n");
441 /* Check size */
442 if (inserted && inserted->cbSize & 0x3)
444 /* Contained */
445 ok(inserted[-1].dwSignature == ~0U, "invalid size is not countained\n");
446 ok(inserted[-1].cbSize > inserted->cbSize + sizeof(DATABLOCK_HEADER),
447 "container too small\n");
449 else if (inserted)
451 ok(inserted->cbSize == item->cbSize + sizeof(DATABLOCK_HEADER),
452 "id %ld wrong size %ld\n", inserted->dwSignature, inserted->cbSize);
454 ok(!inserted || inserted->dwSignature == item->dwSignature, "find got wrong item\n");
455 if (inserted)
457 BOOL bDataOK = TRUE;
458 LPBYTE bufftest = (LPBYTE)inserted;
460 for (i = 0; i < inserted->cbSize - sizeof(DATABLOCK_HEADER); i++)
461 if (bufftest[sizeof(DATABLOCK_HEADER) + i] != i * 2)
462 bDataOK = FALSE;
464 ok(bDataOK == TRUE, "data corrupted on insert\n");
466 item++;
470 /* Failure cases for reading */
471 InitDummyStream(&streamobj);
472 streamobj.failreadcall = TRUE;
473 hRet = pSHReadDataBlockList(&streamobj.IStream_iface, &list);
474 ok(hRet == STG_E_ACCESSDENIED, "changed object failure return\n");
475 ok(streamobj.readbeyondend == FALSE, "read beyond end\n");
476 ok(streamobj.readcalls == 1, "called object after read failure\n");
477 ok(streamobj.writecalls == 0,"called Write() after read failure\n");
478 ok(streamobj.seekcalls == 0,"called Seek() after read failure\n");
480 /* Read returns large object */
481 InitDummyStream(&streamobj);
482 streamobj.readreturnlarge = TRUE;
483 hRet = pSHReadDataBlockList(&streamobj.IStream_iface, &list);
484 ok(hRet == S_OK, "failed create from Read() with large item\n");
485 ok(streamobj.readbeyondend == FALSE, "read beyond end\n");
486 ok(streamobj.readcalls == 1,"wrong call count\n");
487 ok(streamobj.writecalls == 0,"called Write() after read failure\n");
488 ok(streamobj.seekcalls == 2,"wrong Seek() call count (%d)\n", streamobj.seekcalls);
490 pSHFreeDataBlockList(list);
493 static BOOL test_SHIsEmptyStream(void)
495 struct dummystream streamobj;
496 BOOL bRet;
498 if (!pSHIsEmptyStream)
499 return FALSE;
501 InitDummyStream(&streamobj);
502 bRet = pSHIsEmptyStream(&streamobj.IStream_iface);
504 if (bRet != TRUE)
505 return FALSE; /* This version doesn't support stream ops on clists */
507 ok(streamobj.readcalls == 0, "called Read()\n");
508 ok(streamobj.writecalls == 0, "called Write()\n");
509 ok(streamobj.seekcalls == 0, "called Seek()\n");
510 ok(streamobj.statcalls == 1, "wrong call count\n");
512 streamobj.statcalls = 0;
513 streamobj.pos.QuadPart = 50001;
515 bRet = pSHIsEmptyStream(&streamobj.IStream_iface);
517 ok(bRet == FALSE, "failed after seek adjusted\n");
518 ok(streamobj.readcalls == 0, "called Read()\n");
519 ok(streamobj.writecalls == 0, "called Write()\n");
520 ok(streamobj.seekcalls == 0, "called Seek()\n");
521 ok(streamobj.statcalls == 1, "wrong call count\n");
523 /* Failure cases */
524 InitDummyStream(&streamobj);
525 streamobj.pos.QuadPart = 50001;
526 streamobj.failstatcall = TRUE; /* 1: Stat() Bad, Read() OK */
527 bRet = pSHIsEmptyStream(&streamobj.IStream_iface);
528 ok(bRet == FALSE, "should be FALSE after read is OK\n");
529 ok(streamobj.readcalls == 1, "wrong call count\n");
530 ok(streamobj.writecalls == 0, "called Write()\n");
531 ok(streamobj.seekcalls == 1, "wrong call count\n");
532 ok(streamobj.statcalls == 1, "wrong call count\n");
533 ok(streamobj.pos.QuadPart == 0, "Didn't seek to start\n");
535 InitDummyStream(&streamobj);
536 streamobj.pos.QuadPart = 50001;
537 streamobj.failstatcall = TRUE;
538 streamobj.failreadcall = TRUE; /* 2: Stat() Bad, Read() Bad Also */
539 bRet = pSHIsEmptyStream(&streamobj.IStream_iface);
540 ok(bRet == TRUE, "Should be true after read fails\n");
541 ok(streamobj.readcalls == 1, "wrong call count\n");
542 ok(streamobj.writecalls == 0, "called Write()\n");
543 ok(streamobj.seekcalls == 0, "Called Seek()\n");
544 ok(streamobj.statcalls == 1, "wrong call count\n");
545 ok(streamobj.pos.QuadPart == 50001, "called Seek() after read failed\n");
546 return TRUE;
549 static void test_IStream_Read(void)
551 struct dummystream streamobj;
552 char buff[256];
553 HRESULT hRet;
555 if (!pIStream_Read)
556 return;
558 InitDummyStream(&streamobj);
559 hRet = pIStream_Read(&streamobj.IStream_iface, buff, sizeof(buff));
561 ok(hRet == S_OK, "failed Read()\n");
562 ok(streamobj.readcalls == 1, "wrong call count\n");
563 ok(streamobj.writecalls == 0, "called Write()\n");
564 ok(streamobj.seekcalls == 0, "called Seek()\n");
567 static void test_IStream_Write(void)
569 struct dummystream streamobj;
570 char buff[256];
571 HRESULT hRet;
573 if (!pIStream_Write)
574 return;
576 InitDummyStream(&streamobj);
577 hRet = pIStream_Write(&streamobj.IStream_iface, buff, sizeof(buff));
579 ok(hRet == S_OK, "failed Write()\n");
580 ok(streamobj.readcalls == 0, "called Read()\n");
581 ok(streamobj.writecalls == 1, "wrong call count\n");
582 ok(streamobj.seekcalls == 0, "called Seek()\n");
585 static void test_IStream_Reset(void)
587 struct dummystream streamobj;
588 ULARGE_INTEGER ul;
589 LARGE_INTEGER ll;
590 HRESULT hRet;
592 if (!pIStream_Reset || !pIStream_Size)
593 return;
595 InitDummyStream(&streamobj);
596 ll.QuadPart = 5000l;
597 Seek(&streamobj.IStream_iface, ll, 0, NULL); /* Seek to 5000l */
599 streamobj.seekcalls = 0;
600 pIStream_Reset(&streamobj.IStream_iface);
601 ok(streamobj.statcalls == 0, "called Stat()\n");
602 ok(streamobj.readcalls == 0, "called Read()\n");
603 ok(streamobj.writecalls == 0, "called Write()\n");
604 ok(streamobj.seekcalls == 1, "wrong call count\n");
606 ul.QuadPart = 50001;
607 hRet = pIStream_Size(&streamobj.IStream_iface, &ul);
608 ok(hRet == S_OK, "failed Stat()\n");
609 ok(ul.QuadPart == 0, "213 didn't rewind stream\n");
612 static void test_IStream_Size(void)
614 struct dummystream streamobj;
615 ULARGE_INTEGER ul;
616 LARGE_INTEGER ll;
617 HRESULT hRet;
619 if (!pIStream_Size)
620 return;
622 InitDummyStream(&streamobj);
623 ll.QuadPart = 5000l;
624 Seek(&streamobj.IStream_iface, ll, 0, NULL);
625 ul.QuadPart = 0;
626 streamobj.seekcalls = 0;
627 hRet = pIStream_Size(&streamobj.IStream_iface, &ul);
629 ok(hRet == S_OK, "failed Stat()\n");
630 ok(streamobj.statcalls == 1, "wrong call count\n");
631 ok(streamobj.readcalls == 0, "called Read()\n");
632 ok(streamobj.writecalls == 0, "called Write()\n");
633 ok(streamobj.seekcalls == 0, "called Seek()\n");
634 ok(ul.QuadPart == 5000l, "Stat gave wrong size\n");
637 START_TEST(clist)
639 if(!InitFunctionPtrs())
640 return;
642 test_CList();
644 /* Test streaming if this version supports it */
645 if (test_SHIsEmptyStream())
647 test_IStream_Read();
648 test_IStream_Write();
649 test_IStream_Reset();
650 test_IStream_Size();