| /* Unit test suite for SHLWAPI Compact List and IStream ordinal functions | |
| * | |
| * Copyright 2002 Jon Griffiths | |
| * | |
| * This library is free software; you can redistribute it and/or | |
| * modify it under the terms of the GNU Lesser General Public | |
| * License as published by the Free Software Foundation; either | |
| * version 2.1 of the License, or (at your option) any later version. | |
| * | |
| * This library is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| * Lesser General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU Lesser General Public | |
| * License along with this library; if not, write to the Free Software | |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| */ | |
| #include <stdarg.h> | |
| #include "wine/test.h" | |
| #include "windef.h" | |
| #include "winbase.h" | |
| #include "objbase.h" | |
| typedef struct tagSHLWAPI_CLIST | |
| { | |
| ULONG ulSize; | |
| ULONG ulId; | |
| } SHLWAPI_CLIST, *LPSHLWAPI_CLIST; | |
| typedef const SHLWAPI_CLIST* LPCSHLWAPI_CLIST; | |
| /* Items to add */ | |
| static const SHLWAPI_CLIST SHLWAPI_CLIST_items[] = | |
| { | |
| {4, 1}, | |
| {8, 3}, | |
| {12, 2}, | |
| {16, 8}, | |
| {20, 9}, | |
| {3, 11}, | |
| {9, 82}, | |
| {33, 16}, | |
| {32, 55}, | |
| {24, 100}, | |
| {39, 116}, | |
| { 0, 0} | |
| }; | |
| /* Dummy IStream object for testing calls */ | |
| typedef struct | |
| { | |
| void* lpVtbl; | |
| ULONG ref; | |
| int readcalls; | |
| BOOL failreadcall; | |
| BOOL failreadsize; | |
| BOOL readbeyondend; | |
| BOOL readreturnlarge; | |
| int writecalls; | |
| BOOL failwritecall; | |
| BOOL failwritesize; | |
| int seekcalls; | |
| int statcalls; | |
| BOOL failstatcall; | |
| LPCSHLWAPI_CLIST item; | |
| ULARGE_INTEGER pos; | |
| } _IDummyStream; | |
| static | |
| HRESULT WINAPI QueryInterface(_IDummyStream *This,REFIID riid, LPVOID *ppvObj) | |
| { | |
| return S_OK; | |
| } | |
| static ULONG WINAPI AddRef(_IDummyStream *This) | |
| { | |
| return InterlockedIncrement(&This->ref); | |
| } | |
| static ULONG WINAPI Release(_IDummyStream *This) | |
| { | |
| return InterlockedDecrement(&This->ref); | |
| } | |
| static HRESULT WINAPI Read(_IDummyStream* This, LPVOID lpMem, ULONG ulSize, | |
| PULONG lpRead) | |
| { | |
| HRESULT hRet = S_OK; | |
| ++This->readcalls; | |
| if (This->failreadcall) | |
| { | |
| return STG_E_ACCESSDENIED; | |
| } | |
| else if (This->failreadsize) | |
| { | |
| *lpRead = ulSize + 8; | |
| return S_OK; | |
| } | |
| else if (This->readreturnlarge) | |
| { | |
| *((ULONG*)lpMem) = 0xffff01; | |
| *lpRead = ulSize; | |
| This->readreturnlarge = FALSE; | |
| return S_OK; | |
| } | |
| if (ulSize == sizeof(ULONG)) | |
| { | |
| /* Read size of item */ | |
| *((ULONG*)lpMem) = This->item->ulSize ? This->item->ulSize + sizeof(SHLWAPI_CLIST) : 0; | |
| *lpRead = ulSize; | |
| } | |
| else | |
| { | |
| unsigned int i; | |
| char* buff = (char*)lpMem; | |
| /* Read item data */ | |
| if (!This->item->ulSize) | |
| { | |
| This->readbeyondend = TRUE; | |
| *lpRead = 0; | |
| return E_FAIL; /* Should never happen */ | |
| } | |
| *((ULONG*)lpMem) = This->item->ulId; | |
| *lpRead = ulSize; | |
| for (i = 0; i < This->item->ulSize; i++) | |
| buff[4+i] = i*2; | |
| This->item++; | |
| } | |
| return hRet; | |
| } | |
| static HRESULT WINAPI Write(_IDummyStream* This, LPVOID lpMem, ULONG ulSize, | |
| PULONG lpWritten) | |
| { | |
| HRESULT hRet = S_OK; | |
| ++This->writecalls; | |
| if (This->failwritecall) | |
| { | |
| return STG_E_ACCESSDENIED; | |
| } | |
| else if (This->failwritesize) | |
| { | |
| *lpWritten = 0; | |
| } | |
| else | |
| *lpWritten = ulSize; | |
| return hRet; | |
| } | |
| static HRESULT WINAPI Seek(_IDummyStream* This, LARGE_INTEGER dlibMove, | |
| DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition) | |
| { | |
| ++This->seekcalls; | |
| This->pos.QuadPart = dlibMove.QuadPart; | |
| if (plibNewPosition) | |
| plibNewPosition->QuadPart = dlibMove.QuadPart; | |
| return S_OK; | |
| } | |
| static HRESULT WINAPI Stat(_IDummyStream* This, STATSTG* pstatstg, | |
| DWORD grfStatFlag) | |
| { | |
| ++This->statcalls; | |
| if (This->failstatcall) | |
| return E_FAIL; | |
| if (pstatstg) | |
| pstatstg->cbSize.QuadPart = This->pos.QuadPart; | |
| return S_OK; | |
| } | |
| /* VTable */ | |
| static void* iclvt[] = | |
| { | |
| QueryInterface, | |
| AddRef, | |
| Release, | |
| Read, | |
| Write, | |
| Seek, | |
| NULL, /* SetSize */ | |
| NULL, /* CopyTo */ | |
| NULL, /* Commit */ | |
| NULL, /* Revert */ | |
| NULL, /* LockRegion */ | |
| NULL, /* UnlockRegion */ | |
| Stat, | |
| NULL /* Clone */ | |
| }; | |
| /* Function ptrs for ordinal calls */ | |
| static HMODULE SHLWAPI_hshlwapi = 0; | |
| static VOID (WINAPI *pSHLWAPI_19)(LPSHLWAPI_CLIST); | |
| static HRESULT (WINAPI *pSHLWAPI_20)(LPSHLWAPI_CLIST*,LPCSHLWAPI_CLIST); | |
| static BOOL (WINAPI *pSHLWAPI_21)(LPSHLWAPI_CLIST*,ULONG); | |
| static LPSHLWAPI_CLIST (WINAPI *pSHLWAPI_22)(LPSHLWAPI_CLIST,ULONG); | |
| static HRESULT (WINAPI *pSHLWAPI_17)(_IDummyStream*,LPSHLWAPI_CLIST); | |
| static HRESULT (WINAPI *pSHLWAPI_18)(_IDummyStream*,LPSHLWAPI_CLIST*); | |
| static BOOL (WINAPI *pSHLWAPI_166)(_IDummyStream*); | |
| static HRESULT (WINAPI *pSHLWAPI_184)(_IDummyStream*,LPVOID,ULONG); | |
| static HRESULT (WINAPI *pSHLWAPI_212)(_IDummyStream*,LPCVOID,ULONG); | |
| static HRESULT (WINAPI *pSHLWAPI_213)(_IDummyStream*); | |
| static HRESULT (WINAPI *pSHLWAPI_214)(_IDummyStream*,ULARGE_INTEGER*); | |
| static void InitFunctionPtrs() | |
| { | |
| SHLWAPI_hshlwapi = LoadLibraryA("shlwapi.dll"); | |
| ok(SHLWAPI_hshlwapi != 0, "LoadLibrary failed\n"); | |
| if (SHLWAPI_hshlwapi) | |
| { | |
| pSHLWAPI_17 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)17); | |
| ok(pSHLWAPI_17 != 0, "No Ordinal 17\n"); | |
| pSHLWAPI_18 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)18); | |
| ok(pSHLWAPI_18 != 0, "No Ordinal 18\n"); | |
| pSHLWAPI_19 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)19); | |
| ok(pSHLWAPI_19 != 0, "No Ordinal 19\n"); | |
| pSHLWAPI_20 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)20); | |
| ok(pSHLWAPI_20 != 0, "No Ordinal 20\n"); | |
| pSHLWAPI_21 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)21); | |
| ok(pSHLWAPI_21 != 0, "No Ordinal 21\n"); | |
| pSHLWAPI_22 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)22); | |
| ok(pSHLWAPI_22 != 0, "No Ordinal 22\n"); | |
| pSHLWAPI_166 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)166); | |
| ok(pSHLWAPI_166 != 0, "No Ordinal 166\n"); | |
| pSHLWAPI_184 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)184); | |
| ok(pSHLWAPI_184 != 0, "No Ordinal 184\n"); | |
| pSHLWAPI_212 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)212); | |
| ok(pSHLWAPI_212 != 0, "No Ordinal 212\n"); | |
| pSHLWAPI_213 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)213); | |
| ok(pSHLWAPI_213 != 0, "No Ordinal 213\n"); | |
| pSHLWAPI_214 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)214); | |
| ok(pSHLWAPI_214 != 0, "No Ordinal 214\n"); | |
| } | |
| } | |
| static void InitDummyStream(_IDummyStream* iface) | |
| { | |
| iface->lpVtbl = (void*)iclvt; | |
| iface->ref = 1; | |
| iface->readcalls = 0; | |
| iface->failreadcall = FALSE; | |
| iface->failreadsize = FALSE; | |
| iface->readbeyondend = FALSE; | |
| iface->readreturnlarge = FALSE; | |
| iface->writecalls = 0; | |
| iface->failwritecall = FALSE; | |
| iface->failwritesize = FALSE; | |
| iface->seekcalls = 0; | |
| iface->statcalls = 0; | |
| iface->failstatcall = FALSE; | |
| iface->item = SHLWAPI_CLIST_items; | |
| iface->pos.QuadPart = 0; | |
| } | |
| static void test_CList(void) | |
| { | |
| _IDummyStream streamobj; | |
| LPSHLWAPI_CLIST list = NULL; | |
| LPCSHLWAPI_CLIST item = SHLWAPI_CLIST_items; | |
| HRESULT hRet; | |
| LPSHLWAPI_CLIST inserted; | |
| BYTE buff[64]; | |
| unsigned int i; | |
| if (!pSHLWAPI_17 || !pSHLWAPI_18 || !pSHLWAPI_19 || !pSHLWAPI_20 || | |
| !pSHLWAPI_21 || !pSHLWAPI_22) | |
| return; | |
| /* Populate a list and test the items are added correctly */ | |
| while (item->ulSize) | |
| { | |
| /* Create item and fill with data */ | |
| inserted = (LPSHLWAPI_CLIST)buff; | |
| inserted->ulSize = item->ulSize + sizeof(SHLWAPI_CLIST); | |
| inserted->ulId = item->ulId; | |
| for (i = 0; i < item->ulSize; i++) | |
| buff[sizeof(SHLWAPI_CLIST)+i] = i*2; | |
| /* Add it */ | |
| hRet = pSHLWAPI_20(&list, inserted); | |
| ok(hRet > S_OK, "failed list add\n"); | |
| if (hRet > S_OK) | |
| { | |
| ok(list && list->ulSize, "item not added\n"); | |
| /* Find it */ | |
| inserted = pSHLWAPI_22(list, item->ulId); | |
| ok(inserted != NULL, "lost after adding\n"); | |
| ok(!inserted || inserted->ulId != ~0UL, "find returned a container\n"); | |
| /* Check size */ | |
| if (inserted && inserted->ulSize & 0x3) | |
| { | |
| /* Contained */ | |
| ok(inserted[-1].ulId == ~0UL, "invalid size is not countained\n"); | |
| ok(inserted[-1].ulSize > inserted->ulSize+sizeof(SHLWAPI_CLIST), | |
| "container too small\n"); | |
| } | |
| else if (inserted) | |
| { | |
| ok(inserted->ulSize==item->ulSize+sizeof(SHLWAPI_CLIST), | |
| "id %ld size wrong (%ld!=%ld)\n", inserted->ulId, inserted->ulSize, | |
| item->ulSize+sizeof(SHLWAPI_CLIST)); | |
| } | |
| if (inserted) | |
| { | |
| BOOL bDataOK = TRUE; | |
| LPBYTE bufftest = (LPBYTE)inserted; | |
| for (i = 0; i < inserted->ulSize - sizeof(SHLWAPI_CLIST); i++) | |
| if (bufftest[sizeof(SHLWAPI_CLIST)+i] != i*2) | |
| bDataOK = FALSE; | |
| ok(bDataOK == TRUE, "data corrupted on insert\n"); | |
| } | |
| ok(!inserted || inserted->ulId==item->ulId, "find got wrong item\n"); | |
| } | |
| item++; | |
| } | |
| /* Write the list */ | |
| InitDummyStream(&streamobj); | |
| hRet = pSHLWAPI_17(&streamobj, list); | |
| ok(hRet == S_OK, "write failed\n"); | |
| if (hRet == S_OK) | |
| { | |
| /* 1 call for each element, + 1 for OK (use our null element for this) */ | |
| ok(streamobj.writecalls == sizeof(SHLWAPI_CLIST_items)/sizeof(SHLWAPI_CLIST), | |
| "wrong call count\n"); | |
| ok(streamobj.readcalls == 0,"called Read() in write\n"); | |
| ok(streamobj.seekcalls == 0,"called Seek() in write\n"); | |
| } | |
| /* Failure cases for writing */ | |
| InitDummyStream(&streamobj); | |
| streamobj.failwritecall = TRUE; | |
| hRet = pSHLWAPI_17(&streamobj, list); | |
| ok(hRet == STG_E_ACCESSDENIED, "changed object failure return\n"); | |
| ok(streamobj.writecalls == 1, "called object after failure\n"); | |
| ok(streamobj.readcalls == 0,"called Read() after failure\n"); | |
| ok(streamobj.seekcalls == 0,"called Seek() after failure\n"); | |
| InitDummyStream(&streamobj); | |
| streamobj.failwritesize = TRUE; | |
| hRet = pSHLWAPI_17(&streamobj, list); | |
| ok(hRet == STG_E_MEDIUMFULL, "changed size failure return\n"); | |
| ok(streamobj.writecalls == 1, "called object after size failure\n"); | |
| ok(streamobj.readcalls == 0,"called Read() after failure\n"); | |
| ok(streamobj.seekcalls == 0,"called Seek() after failure\n"); | |
| /* Invalid inputs for adding */ | |
| inserted = (LPSHLWAPI_CLIST)buff; | |
| inserted->ulSize = sizeof(SHLWAPI_CLIST) -1; | |
| inserted->ulId = 33; | |
| hRet = pSHLWAPI_20(&list, inserted); | |
| /* The call succeeds but the item is not inserted, except on some early | |
| * versions which return failure. Wine behaves like later versions. | |
| */ | |
| #if 0 | |
| ok(hRet == S_OK, "failed bad element size\n"); | |
| #endif | |
| inserted = pSHLWAPI_22(list, 33); | |
| ok(inserted == NULL, "inserted bad element size\n"); | |
| inserted = (LPSHLWAPI_CLIST)buff; | |
| inserted->ulSize = 44; | |
| inserted->ulId = ~0UL; | |
| hRet = pSHLWAPI_20(&list, inserted); | |
| /* See comment above, some early versions fail this call */ | |
| #if 0 | |
| ok(hRet == S_OK, "failed adding a container\n"); | |
| #endif | |
| item = SHLWAPI_CLIST_items; | |
| /* Look for nonexistent item in populated list */ | |
| inserted = pSHLWAPI_22(list, 99999999); | |
| ok(inserted == NULL, "found a nonexistent item\n"); | |
| while (item->ulSize) | |
| { | |
| /* Delete items */ | |
| BOOL bRet = pSHLWAPI_21(&list, item->ulId); | |
| ok(bRet == TRUE, "couldn't find item to delete\n"); | |
| item++; | |
| } | |
| /* Look for nonexistent item in empty list */ | |
| inserted = pSHLWAPI_22(list, 99999999); | |
| ok(inserted == NULL, "found an item in empty list\n"); | |
| /* Create a list by reading in data */ | |
| InitDummyStream(&streamobj); | |
| hRet = pSHLWAPI_18(&streamobj, &list); | |
| ok(hRet == S_OK, "failed create from Read()\n"); | |
| if (hRet == S_OK) | |
| { | |
| ok(streamobj.readbeyondend == FALSE, "read beyond end\n"); | |
| /* 2 calls per item, but only 1 for the terminator */ | |
| ok(streamobj.readcalls == sizeof(SHLWAPI_CLIST_items)/sizeof(SHLWAPI_CLIST)*2-1, | |
| "wrong call count\n"); | |
| ok(streamobj.writecalls == 0, "called Write() from create\n"); | |
| ok(streamobj.seekcalls == 0,"called Seek() from create\n"); | |
| item = SHLWAPI_CLIST_items; | |
| /* Check the items were added correctly */ | |
| while (item->ulSize) | |
| { | |
| inserted = pSHLWAPI_22(list, item->ulId); | |
| ok(inserted != NULL, "lost after adding\n"); | |
| ok(!inserted || inserted->ulId != ~0UL, "find returned a container\n"); | |
| /* Check size */ | |
| if (inserted && inserted->ulSize & 0x3) | |
| { | |
| /* Contained */ | |
| ok(inserted[-1].ulId == ~0UL, "invalid size is not countained\n"); | |
| ok(inserted[-1].ulSize > inserted->ulSize+sizeof(SHLWAPI_CLIST), | |
| "container too small\n"); | |
| } | |
| else if (inserted) | |
| { | |
| ok(inserted->ulSize==item->ulSize+sizeof(SHLWAPI_CLIST), | |
| "id %ld size wrong (%ld!=%ld)\n", inserted->ulId, inserted->ulSize, | |
| item->ulSize+sizeof(SHLWAPI_CLIST)); | |
| } | |
| ok(!inserted || inserted->ulId==item->ulId, "find got wrong item\n"); | |
| if (inserted) | |
| { | |
| BOOL bDataOK = TRUE; | |
| LPBYTE bufftest = (LPBYTE)inserted; | |
| for (i = 0; i < inserted->ulSize - sizeof(SHLWAPI_CLIST); i++) | |
| if (bufftest[sizeof(SHLWAPI_CLIST)+i] != i*2) | |
| bDataOK = FALSE; | |
| ok(bDataOK == TRUE, "data corrupted on insert\n"); | |
| } | |
| item++; | |
| } | |
| } | |
| /* Failure cases for reading */ | |
| InitDummyStream(&streamobj); | |
| streamobj.failreadcall = TRUE; | |
| hRet = pSHLWAPI_18(&streamobj, &list); | |
| ok(hRet == STG_E_ACCESSDENIED, "changed object failure return\n"); | |
| ok(streamobj.readbeyondend == FALSE, "read beyond end\n"); | |
| ok(streamobj.readcalls == 1, "called object after read failure\n"); | |
| ok(streamobj.writecalls == 0,"called Write() after read failure\n"); | |
| ok(streamobj.seekcalls == 0,"called Seek() after read failure\n"); | |
| /* Read returns large object */ | |
| InitDummyStream(&streamobj); | |
| streamobj.readreturnlarge = TRUE; | |
| hRet = pSHLWAPI_18(&streamobj, &list); | |
| ok(hRet == S_OK, "failed create from Read() with large item\n"); | |
| ok(streamobj.readbeyondend == FALSE, "read beyond end\n"); | |
| ok(streamobj.readcalls == 1,"wrong call count\n"); | |
| ok(streamobj.writecalls == 0,"called Write() after read failure\n"); | |
| ok(streamobj.seekcalls == 2,"wrong Seek() call count (%d)\n", streamobj.seekcalls); | |
| pSHLWAPI_19(list); | |
| } | |
| static BOOL test_SHLWAPI_166(void) | |
| { | |
| _IDummyStream streamobj; | |
| BOOL bRet; | |
| if (!pSHLWAPI_166) | |
| return FALSE; | |
| InitDummyStream(&streamobj); | |
| bRet = pSHLWAPI_166(&streamobj); | |
| if (bRet != TRUE) | |
| return FALSE; /* This version doesn't support stream ops on clists */ | |
| ok(streamobj.readcalls == 0, "called Read()\n"); | |
| ok(streamobj.writecalls == 0, "called Write()\n"); | |
| ok(streamobj.seekcalls == 0, "called Seek()\n"); | |
| ok(streamobj.statcalls == 1, "wrong call count\n"); | |
| streamobj.statcalls = 0; | |
| streamobj.pos.QuadPart = 50001; | |
| bRet = pSHLWAPI_166(&streamobj); | |
| ok(bRet == FALSE, "failed after seek adjusted\n"); | |
| ok(streamobj.readcalls == 0, "called Read()\n"); | |
| ok(streamobj.writecalls == 0, "called Write()\n"); | |
| ok(streamobj.seekcalls == 0, "called Seek()\n"); | |
| ok(streamobj.statcalls == 1, "wrong call count\n"); | |
| /* Failure cases */ | |
| InitDummyStream(&streamobj); | |
| streamobj.pos.QuadPart = 50001; | |
| streamobj.failstatcall = TRUE; /* 1: Stat() Bad, Read() OK */ | |
| bRet = pSHLWAPI_166(&streamobj); | |
| ok(bRet == FALSE, "should be FALSE after read is OK\n"); | |
| ok(streamobj.readcalls == 1, "wrong call count\n"); | |
| ok(streamobj.writecalls == 0, "called Write()\n"); | |
| ok(streamobj.seekcalls == 1, "wrong call count\n"); | |
| ok(streamobj.statcalls == 1, "wrong call count\n"); | |
| ok(streamobj.pos.QuadPart == 0, "Didn't seek to start\n"); | |
| InitDummyStream(&streamobj); | |
| streamobj.pos.QuadPart = 50001; | |
| streamobj.failstatcall = TRUE; | |
| streamobj.failreadcall = TRUE; /* 2: Stat() Bad, Read() Bad Also */ | |
| bRet = pSHLWAPI_166(&streamobj); | |
| ok(bRet == TRUE, "Should be true after read fails\n"); | |
| ok(streamobj.readcalls == 1, "wrong call count\n"); | |
| ok(streamobj.writecalls == 0, "called Write()\n"); | |
| ok(streamobj.seekcalls == 0, "Called Seek()\n"); | |
| ok(streamobj.statcalls == 1, "wrong call count\n"); | |
| ok(streamobj.pos.QuadPart == 50001, "called Seek() after read failed\n"); | |
| return TRUE; | |
| } | |
| static void test_SHLWAPI_184(void) | |
| { | |
| _IDummyStream streamobj; | |
| char buff[256]; | |
| HRESULT hRet; | |
| if (!pSHLWAPI_184) | |
| return; | |
| InitDummyStream(&streamobj); | |
| hRet = pSHLWAPI_184(&streamobj, buff, sizeof(buff)); | |
| ok(hRet == S_OK, "failed Read()\n"); | |
| ok(streamobj.readcalls == 1, "wrong call count\n"); | |
| ok(streamobj.writecalls == 0, "called Write()\n"); | |
| ok(streamobj.seekcalls == 0, "called Seek()\n"); | |
| } | |
| static void test_SHLWAPI_212(void) | |
| { | |
| _IDummyStream streamobj; | |
| char buff[256]; | |
| HRESULT hRet; | |
| if (!pSHLWAPI_212) | |
| return; | |
| InitDummyStream(&streamobj); | |
| hRet = pSHLWAPI_212(&streamobj, buff, sizeof(buff)); | |
| ok(hRet == S_OK, "failed Write()\n"); | |
| ok(streamobj.readcalls == 0, "called Read()\n"); | |
| ok(streamobj.writecalls == 1, "wrong call count\n"); | |
| ok(streamobj.seekcalls == 0, "called Seek()\n"); | |
| } | |
| static void test_SHLWAPI_213(void) | |
| { | |
| _IDummyStream streamobj; | |
| ULARGE_INTEGER ul; | |
| LARGE_INTEGER ll; | |
| HRESULT hRet; | |
| if (!pSHLWAPI_213 || !pSHLWAPI_214) | |
| return; | |
| InitDummyStream(&streamobj); | |
| ll.QuadPart = 5000l; | |
| Seek(&streamobj, ll, 0, NULL); /* Seek to 5000l */ | |
| streamobj.seekcalls = 0; | |
| pSHLWAPI_213(&streamobj); /* Should rewind */ | |
| ok(streamobj.statcalls == 0, "called Stat()\n"); | |
| ok(streamobj.readcalls == 0, "called Read()\n"); | |
| ok(streamobj.writecalls == 0, "called Write()\n"); | |
| ok(streamobj.seekcalls == 1, "wrong call count\n"); | |
| ul.QuadPart = 50001; | |
| hRet = pSHLWAPI_214(&streamobj, &ul); | |
| ok(hRet == S_OK, "failed Stat()\n"); | |
| ok(ul.QuadPart == 0, "213 didn't rewind stream\n"); | |
| } | |
| static void test_SHLWAPI_214(void) | |
| { | |
| _IDummyStream streamobj; | |
| ULARGE_INTEGER ul; | |
| LARGE_INTEGER ll; | |
| HRESULT hRet; | |
| if (!pSHLWAPI_214) | |
| return; | |
| InitDummyStream(&streamobj); | |
| ll.QuadPart = 5000l; | |
| Seek(&streamobj, ll, 0, NULL); | |
| ul.QuadPart = 0; | |
| streamobj.seekcalls = 0; | |
| hRet = pSHLWAPI_214(&streamobj, &ul); | |
| ok(hRet == S_OK, "failed Stat()\n"); | |
| ok(streamobj.statcalls == 1, "wrong call count\n"); | |
| ok(streamobj.readcalls == 0, "called Read()\n"); | |
| ok(streamobj.writecalls == 0, "called Write()\n"); | |
| ok(streamobj.seekcalls == 0, "called Seek()\n"); | |
| ok(ul.QuadPart == 5000l, "Stat gave wrong size\n"); | |
| } | |
| START_TEST(clist) | |
| { | |
| InitFunctionPtrs(); | |
| test_CList(); | |
| /* Test streaming if this version supports it */ | |
| if (test_SHLWAPI_166()) | |
| { | |
| test_SHLWAPI_184(); | |
| test_SHLWAPI_212(); | |
| test_SHLWAPI_213(); | |
| test_SHLWAPI_214(); | |
| } | |
| if (SHLWAPI_hshlwapi) | |
| FreeLibrary(SHLWAPI_hshlwapi); | |
| } |