Implement/document @17,18,19,20,21,22 (Compact list API).
This commit is contained in:
parent
5da88a2cb9
commit
2d990806ec
|
@ -12,6 +12,7 @@ LDDLLFLAGS = @LDDLLFLAGS@
|
||||||
SYMBOLFILE = $(MODULE).tmp.o
|
SYMBOLFILE = $(MODULE).tmp.o
|
||||||
|
|
||||||
C_SRCS = \
|
C_SRCS = \
|
||||||
|
clist.c \
|
||||||
ordinal.c \
|
ordinal.c \
|
||||||
path.c \
|
path.c \
|
||||||
reg.c \
|
reg.c \
|
||||||
|
@ -24,6 +25,7 @@ C_SRCS = \
|
||||||
EXTRASUBDIRS = tests
|
EXTRASUBDIRS = tests
|
||||||
|
|
||||||
CTESTS = \
|
CTESTS = \
|
||||||
|
tests/clist.c \
|
||||||
tests/shreg.c
|
tests/shreg.c
|
||||||
|
|
||||||
@MAKE_DLL_RULES@
|
@MAKE_DLL_RULES@
|
||||||
|
|
|
@ -0,0 +1,434 @@
|
||||||
|
/*
|
||||||
|
* SHLWAPI Compact List 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 <string.h>
|
||||||
|
|
||||||
|
#include "windef.h"
|
||||||
|
#include "winbase.h"
|
||||||
|
#include "winuser.h"
|
||||||
|
#include "wine/obj_base.h"
|
||||||
|
#include "wine/obj_storage.h"
|
||||||
|
#include "wine/debug.h"
|
||||||
|
|
||||||
|
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
||||||
|
|
||||||
|
/* Compact list element (ordinals 17-22) */
|
||||||
|
typedef struct tagSHLWAPI_CLIST
|
||||||
|
{
|
||||||
|
ULONG ulSize; /* Size of this list element and its data */
|
||||||
|
ULONG ulId; /* If -1, The real element follows */
|
||||||
|
/* Item data (or a contained SHLWAPI_CLIST) follows... */
|
||||||
|
} SHLWAPI_CLIST, *LPSHLWAPI_CLIST;
|
||||||
|
|
||||||
|
typedef const SHLWAPI_CLIST* LPCSHLWAPI_CLIST;
|
||||||
|
|
||||||
|
/* ulId for contained SHLWAPI_CLIST items */
|
||||||
|
static const ULONG CLIST_ID_CONTAINER = -1u;
|
||||||
|
|
||||||
|
HRESULT WINAPI SHLWAPI_20(LPSHLWAPI_CLIST*,LPCSHLWAPI_CLIST);
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* NextItem
|
||||||
|
*
|
||||||
|
* Internal helper: move a clist pointer to the next item.
|
||||||
|
*/
|
||||||
|
inline static LPSHLWAPI_CLIST NextItem(LPCSHLWAPI_CLIST lpList)
|
||||||
|
{
|
||||||
|
const char* address = (char*)lpList;
|
||||||
|
address += lpList->ulSize;
|
||||||
|
return (LPSHLWAPI_CLIST)address;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* @ [SHLWAPI.17]
|
||||||
|
*
|
||||||
|
* Write a compact list to a stream.
|
||||||
|
*
|
||||||
|
* PARAMS
|
||||||
|
* lpStream [I] Stream to write the list to
|
||||||
|
* lpList [I] List of items to write
|
||||||
|
*
|
||||||
|
* RETURNS
|
||||||
|
* Success: S_OK
|
||||||
|
* Failure: An HRESULT error code
|
||||||
|
*
|
||||||
|
* NOTES
|
||||||
|
* Ordinals 17,18,19,20,21 and 22 are related and together provide a compact
|
||||||
|
* list structure which may be stored and retrieved from a stream.
|
||||||
|
*
|
||||||
|
* The exposed API consists of:
|
||||||
|
* @17 Write a compact list to a stream
|
||||||
|
* @18 Read and create a list from a stream
|
||||||
|
* @19 Free a list
|
||||||
|
* @20 Insert a new item into a list
|
||||||
|
* @21 Remove an item from a list
|
||||||
|
* @22 Find an item in a list
|
||||||
|
*
|
||||||
|
* The compact list is stored packed into a memory array. Each element has a
|
||||||
|
* size and an associated ID. Elements must be less than 64k if the list is
|
||||||
|
* to be subsequently read from a stream.
|
||||||
|
*
|
||||||
|
* Elements are aligned on DWORD boundaries. If an elements data size is not
|
||||||
|
* a DWORD size multiple, the element is wrapped by inserting a surrounding
|
||||||
|
* element with an Id of -1, and size sufficient to pad to a DWORD boundary.
|
||||||
|
*
|
||||||
|
* These functions are slow for large objects and long lists.
|
||||||
|
*/
|
||||||
|
HRESULT WINAPI SHLWAPI_17(IStream* lpStream, LPSHLWAPI_CLIST lpList)
|
||||||
|
{
|
||||||
|
ULONG ulSize;
|
||||||
|
HRESULT hRet = E_FAIL;
|
||||||
|
|
||||||
|
TRACE("(%p,%p)\n", lpStream, lpList);
|
||||||
|
|
||||||
|
if(lpList)
|
||||||
|
{
|
||||||
|
while (lpList->ulSize)
|
||||||
|
{
|
||||||
|
LPSHLWAPI_CLIST lpItem = lpList;
|
||||||
|
|
||||||
|
if(lpList->ulId == CLIST_ID_CONTAINER)
|
||||||
|
lpItem++;
|
||||||
|
|
||||||
|
hRet = IStream_Write(lpStream,lpItem,lpItem->ulSize,&ulSize);
|
||||||
|
if (FAILED(hRet))
|
||||||
|
return hRet;
|
||||||
|
|
||||||
|
if(lpItem->ulSize != ulSize)
|
||||||
|
return STG_E_MEDIUMFULL;
|
||||||
|
|
||||||
|
lpList = NextItem(lpList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(SUCCEEDED(hRet))
|
||||||
|
{
|
||||||
|
ULONG ulDummy;
|
||||||
|
ulSize = 0;
|
||||||
|
|
||||||
|
/* Write a terminating list entry with zero size */
|
||||||
|
hRet = IStream_Write(lpStream, &ulSize,sizeof(ulSize),&ulDummy);
|
||||||
|
}
|
||||||
|
|
||||||
|
return hRet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* @ [SHLWAPI.18]
|
||||||
|
*
|
||||||
|
* Read and create a compact list from a stream
|
||||||
|
*
|
||||||
|
* PARAMS
|
||||||
|
* lpStream [I] Stream to read the list from
|
||||||
|
* lppList [0] Pointer to recieve the new List
|
||||||
|
*
|
||||||
|
* RETURNS
|
||||||
|
* Success: S_OK
|
||||||
|
* Failure: An HRESULT error code
|
||||||
|
*
|
||||||
|
* NOTES
|
||||||
|
* When read from a file, list objects are limited in size to 64k.
|
||||||
|
*/
|
||||||
|
HRESULT WINAPI SHLWAPI_18(IStream* lpStream, LPSHLWAPI_CLIST* lppList)
|
||||||
|
{
|
||||||
|
SHLWAPI_CLIST bBuff[128]; /* Temporary storage for new list item */
|
||||||
|
ULONG ulBuffSize = sizeof(bBuff);
|
||||||
|
LPSHLWAPI_CLIST pItem = bBuff;
|
||||||
|
ULONG ulRead, ulSize;
|
||||||
|
HRESULT hRet = S_OK;
|
||||||
|
|
||||||
|
TRACE("(%p,%p)\n", lpStream, lppList);
|
||||||
|
|
||||||
|
if(*lppList)
|
||||||
|
{
|
||||||
|
/* Free any existing list */
|
||||||
|
LocalFree((HLOCAL)*lppList);
|
||||||
|
*lppList = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
/* Read the size of the next item */
|
||||||
|
hRet = IStream_Read(lpStream, &ulSize,sizeof(ulSize),&ulRead);
|
||||||
|
|
||||||
|
if(FAILED(hRet) || ulRead != sizeof(ulSize) || !ulSize)
|
||||||
|
break; /* Read failed or read zero size (the end of the list) */
|
||||||
|
|
||||||
|
if(ulSize > 0xFFFF)
|
||||||
|
{
|
||||||
|
LARGE_INTEGER liZero;
|
||||||
|
ULARGE_INTEGER ulPos;
|
||||||
|
|
||||||
|
liZero.QuadPart = 0;
|
||||||
|
|
||||||
|
/* Back the stream up; this object is too big for the list */
|
||||||
|
if(SUCCEEDED(IStream_Seek(lpStream, liZero, STREAM_SEEK_CUR, &ulPos)))
|
||||||
|
{
|
||||||
|
liZero.QuadPart = ulPos.QuadPart - sizeof(ULONG);
|
||||||
|
IStream_Seek(lpStream, liZero, STREAM_SEEK_SET, NULL);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (ulSize >= sizeof(SHLWAPI_CLIST))
|
||||||
|
{
|
||||||
|
/* Add this new item to the list */
|
||||||
|
if(ulSize > ulBuffSize)
|
||||||
|
{
|
||||||
|
/* We need more buffer space, allocate it */
|
||||||
|
LPSHLWAPI_CLIST lpTemp;
|
||||||
|
|
||||||
|
if (pItem == bBuff)
|
||||||
|
lpTemp = (LPSHLWAPI_CLIST)LocalAlloc(LMEM_ZEROINIT, ulSize);
|
||||||
|
else
|
||||||
|
lpTemp = (LPSHLWAPI_CLIST)LocalReAlloc((HLOCAL)pItem, ulSize,
|
||||||
|
LMEM_ZEROINIT|LMEM_MOVEABLE);
|
||||||
|
|
||||||
|
if(!lpTemp)
|
||||||
|
{
|
||||||
|
hRet = E_OUTOFMEMORY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ulBuffSize = ulSize;
|
||||||
|
pItem = lpTemp;
|
||||||
|
}
|
||||||
|
|
||||||
|
pItem->ulSize = ulSize;
|
||||||
|
ulSize -= sizeof(pItem->ulSize); /* already read this member */
|
||||||
|
|
||||||
|
/* Read the item Id and data */
|
||||||
|
hRet = IStream_Read(lpStream, &pItem->ulId, ulSize, &ulRead);
|
||||||
|
|
||||||
|
if(FAILED(hRet) || ulRead != ulSize)
|
||||||
|
break;
|
||||||
|
|
||||||
|
SHLWAPI_20(lppList, pItem); /* Insert Item */
|
||||||
|
}
|
||||||
|
} while(1);
|
||||||
|
|
||||||
|
/* If we allocated space, free it */
|
||||||
|
if(pItem != bBuff)
|
||||||
|
LocalFree((HLOCAL)pItem);
|
||||||
|
|
||||||
|
return hRet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* @ [SHLWAPI.19]
|
||||||
|
*
|
||||||
|
* Free a compact list.
|
||||||
|
*
|
||||||
|
* PARAMS
|
||||||
|
* lpList [I] List to free
|
||||||
|
*
|
||||||
|
* RETURNS
|
||||||
|
* Nothing.
|
||||||
|
*/
|
||||||
|
VOID WINAPI SHLWAPI_19(LPSHLWAPI_CLIST lpList)
|
||||||
|
{
|
||||||
|
TRACE("(%p)\n", lpList);
|
||||||
|
|
||||||
|
if (lpList)
|
||||||
|
LocalFree((HLOCAL)lpList);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* @ [SHLWAPI.20]
|
||||||
|
*
|
||||||
|
* Insert a new item into a compact list.
|
||||||
|
*
|
||||||
|
* PARAMS
|
||||||
|
* lppList [0] Pointer to the List
|
||||||
|
* lpNewItem [I] The new item to add to the list
|
||||||
|
*
|
||||||
|
* RETURNS
|
||||||
|
* Success: The size of the inserted item.
|
||||||
|
* Failure: An HRESULT error code.
|
||||||
|
*/
|
||||||
|
HRESULT WINAPI SHLWAPI_20(LPSHLWAPI_CLIST* lppList, LPCSHLWAPI_CLIST lpNewItem)
|
||||||
|
{
|
||||||
|
LPSHLWAPI_CLIST lpInsertAt = NULL;
|
||||||
|
ULONG ulSize;
|
||||||
|
|
||||||
|
TRACE("(%p,%p)\n", lppList, lpNewItem);
|
||||||
|
|
||||||
|
if(!lppList || !lpNewItem ||
|
||||||
|
lpNewItem->ulId == CLIST_ID_CONTAINER ||
|
||||||
|
lpNewItem->ulSize < sizeof(SHLWAPI_CLIST))
|
||||||
|
return E_INVALIDARG;
|
||||||
|
|
||||||
|
ulSize = lpNewItem->ulSize;
|
||||||
|
|
||||||
|
if(ulSize & 0x3)
|
||||||
|
{
|
||||||
|
/* Tune size to a ULONG boundary, add space for container element */
|
||||||
|
ulSize = ((ulSize + 0x3) & 0xFFFFFFFC) + sizeof(SHLWAPI_CLIST);
|
||||||
|
TRACE("Creating container item, new size = %ld\n", ulSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!*lppList)
|
||||||
|
{
|
||||||
|
/* An empty list. Allocate space for terminal ulSize also */
|
||||||
|
*lppList = (LPSHLWAPI_CLIST)LocalAlloc(LMEM_ZEROINIT,
|
||||||
|
ulSize + sizeof(ULONG));
|
||||||
|
lpInsertAt = *lppList;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Append to the end of the list */
|
||||||
|
ULONG ulTotalSize = 0;
|
||||||
|
LPSHLWAPI_CLIST lpIter = *lppList;
|
||||||
|
|
||||||
|
/* Iterate to the end of the list, calculating the total size */
|
||||||
|
while (lpIter->ulSize)
|
||||||
|
{
|
||||||
|
ulTotalSize += lpIter->ulSize;
|
||||||
|
lpIter = NextItem(lpIter);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Increase the size of the list */
|
||||||
|
lpIter = (LPSHLWAPI_CLIST)LocalReAlloc((HLOCAL)*lppList,
|
||||||
|
ulTotalSize + ulSize+sizeof(ULONG),
|
||||||
|
LMEM_ZEROINIT | LMEM_MOVEABLE);
|
||||||
|
if(lpIter)
|
||||||
|
{
|
||||||
|
*lppList = lpIter;
|
||||||
|
lpInsertAt = (LPSHLWAPI_CLIST)((char*)lpIter + ulTotalSize); /* At end */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(lpInsertAt)
|
||||||
|
{
|
||||||
|
/* Copy in the new item */
|
||||||
|
LPSHLWAPI_CLIST lpDest = lpInsertAt;
|
||||||
|
|
||||||
|
if(ulSize != lpNewItem->ulSize)
|
||||||
|
{
|
||||||
|
lpInsertAt->ulSize = ulSize;
|
||||||
|
lpInsertAt->ulId = CLIST_ID_CONTAINER;
|
||||||
|
lpDest++;
|
||||||
|
}
|
||||||
|
memcpy(lpDest, lpNewItem, lpNewItem->ulSize);
|
||||||
|
|
||||||
|
/* Terminate the list */
|
||||||
|
lpInsertAt = NextItem(lpInsertAt);
|
||||||
|
lpInsertAt->ulSize = 0;
|
||||||
|
|
||||||
|
return lpNewItem->ulSize;
|
||||||
|
}
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* @ [SHLWAPI.21]
|
||||||
|
*
|
||||||
|
* Remove an item from a compact list.
|
||||||
|
*
|
||||||
|
* PARAMS
|
||||||
|
* lppList [O] List to remove the item from
|
||||||
|
* ulId [I] Id of item to remove
|
||||||
|
*
|
||||||
|
* RETURNS
|
||||||
|
* Success: TRUE.
|
||||||
|
* Failure: FALSE, If any parameters are invalid, or the item was not found.
|
||||||
|
*/
|
||||||
|
BOOL WINAPI SHLWAPI_21(LPSHLWAPI_CLIST* lppList, ULONG ulId)
|
||||||
|
{
|
||||||
|
LPSHLWAPI_CLIST lpList = 0;
|
||||||
|
LPSHLWAPI_CLIST lpItem = NULL;
|
||||||
|
LPSHLWAPI_CLIST lpNext;
|
||||||
|
ULONG ulNewSize;
|
||||||
|
|
||||||
|
TRACE("(%p,%ld)\n", lppList, ulId);
|
||||||
|
|
||||||
|
if(lppList && (lpList = *lppList))
|
||||||
|
{
|
||||||
|
/* Search for item in list */
|
||||||
|
while (lpList->ulSize)
|
||||||
|
{
|
||||||
|
if(lpList->ulId == ulId ||
|
||||||
|
(lpList->ulId == CLIST_ID_CONTAINER && lpList[1].ulId == ulId))
|
||||||
|
{
|
||||||
|
lpItem = lpList; /* Found */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lpList = NextItem(lpList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!lpItem)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
lpList = lpNext = NextItem(lpItem);
|
||||||
|
|
||||||
|
/* Locate the end of the list */
|
||||||
|
while (lpList->ulSize)
|
||||||
|
lpList = NextItem(lpList);
|
||||||
|
|
||||||
|
/* Resize the list */
|
||||||
|
ulNewSize = LocalSize((HLOCAL)*lppList) - lpItem->ulSize;
|
||||||
|
|
||||||
|
/* Copy following elements over lpItem */
|
||||||
|
memmove(lpItem, lpNext, (char *)lpList - (char *)lpNext + sizeof(ULONG));
|
||||||
|
|
||||||
|
if(ulNewSize <= sizeof(ULONG))
|
||||||
|
{
|
||||||
|
LocalFree((HLOCAL)*lppList);
|
||||||
|
*lppList = NULL; /* Removed the last element */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lpList = (LPSHLWAPI_CLIST)LocalReAlloc((HLOCAL)*lppList, ulNewSize,
|
||||||
|
LMEM_ZEROINIT|LMEM_MOVEABLE);
|
||||||
|
if(lpList)
|
||||||
|
*lppList = lpList;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* @ [SHLWAPI.22]
|
||||||
|
*
|
||||||
|
* Find an item in a compact list.
|
||||||
|
*
|
||||||
|
* PARAMS
|
||||||
|
* lpList [I] List to search
|
||||||
|
* ulId [I] ID of item to find
|
||||||
|
*
|
||||||
|
* RETURNS
|
||||||
|
* Success: A pointer to the list item found
|
||||||
|
* Failure: NULL
|
||||||
|
*/
|
||||||
|
LPSHLWAPI_CLIST WINAPI SHLWAPI_22(LPSHLWAPI_CLIST lpList, ULONG ulId)
|
||||||
|
{
|
||||||
|
TRACE("(%p,%ld)\n", lpList, ulId);
|
||||||
|
|
||||||
|
if(lpList)
|
||||||
|
{
|
||||||
|
while(lpList->ulSize)
|
||||||
|
{
|
||||||
|
if(lpList->ulId == ulId)
|
||||||
|
return lpList; /* Matched */
|
||||||
|
else if(lpList->ulId == CLIST_ID_CONTAINER && lpList[1].ulId == ulId)
|
||||||
|
return lpList + 1; /* Contained item matches */
|
||||||
|
|
||||||
|
lpList = NextItem(lpList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
|
@ -737,78 +737,6 @@ HRESULT WINAPI SHLWAPI_16 (
|
||||||
return 0xabba1252;
|
return 0xabba1252;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* @ [SHLWAPI.18]
|
|
||||||
*
|
|
||||||
* w is pointer to address of callback routine
|
|
||||||
* x is pointer to LPVOID to receive address of locally allocated
|
|
||||||
* space size 0x14
|
|
||||||
* return is 0 (unless out of memory???)
|
|
||||||
*
|
|
||||||
* related to _19, _21 and _22 below
|
|
||||||
* only seen invoked by SHDOCVW
|
|
||||||
*/
|
|
||||||
LONG WINAPI SHLWAPI_18 (
|
|
||||||
LPVOID *w,
|
|
||||||
LPVOID x)
|
|
||||||
{
|
|
||||||
FIXME("(%p %p)stub\n",w,x);
|
|
||||||
*((LPDWORD)x) = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* @ [SHLWAPI.19]
|
|
||||||
*
|
|
||||||
* w is address of allocated memory from _21
|
|
||||||
* return is 0 (unless out of memory???)
|
|
||||||
*
|
|
||||||
* related to _18, _21 and _22 below
|
|
||||||
* only seen invoked by SHDOCVW
|
|
||||||
*/
|
|
||||||
LONG WINAPI SHLWAPI_19 (
|
|
||||||
LPVOID w)
|
|
||||||
{
|
|
||||||
FIXME("(%p) stub\n",w);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* @ [SHLWAPI.21]
|
|
||||||
*
|
|
||||||
* w points to space allocated via .18 above
|
|
||||||
* LocalSize is done on it (retrieves 18)
|
|
||||||
* LocalReAlloc is done on it to size 8 with LMEM_MOVEABLE & LMEM_ZEROINIT
|
|
||||||
* x values seen 0xa0000005
|
|
||||||
* returns 1
|
|
||||||
*
|
|
||||||
* relates to _18, _19 and _22 above and below
|
|
||||||
* only seen invoked by SHDOCVW
|
|
||||||
*/
|
|
||||||
LONG WINAPI SHLWAPI_21 (
|
|
||||||
LPVOID w,
|
|
||||||
DWORD x)
|
|
||||||
{
|
|
||||||
FIXME("(%p %lx)stub\n",w,x);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* @ [SHLWAPI.22]
|
|
||||||
*
|
|
||||||
* return is 'w' value seen in x is 0xa0000005
|
|
||||||
*
|
|
||||||
* relates to _18, _19 and _21 above
|
|
||||||
* only seen invoked by SHDOCVW
|
|
||||||
*/
|
|
||||||
LPVOID WINAPI SHLWAPI_22 (
|
|
||||||
LPVOID w,
|
|
||||||
DWORD x)
|
|
||||||
{
|
|
||||||
FIXME("(%p %lx)stub\n",w,x);
|
|
||||||
return w;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
* @ [SHLWAPI.23]
|
* @ [SHLWAPI.23]
|
||||||
*
|
*
|
||||||
|
|
|
@ -16,12 +16,12 @@ init SHLWAPI_LibMain
|
||||||
14 stdcall @(ptr ptr) SHLWAPI_14
|
14 stdcall @(ptr ptr) SHLWAPI_14
|
||||||
15 stdcall @(ptr ptr) SHLWAPI_15
|
15 stdcall @(ptr ptr) SHLWAPI_15
|
||||||
16 stdcall @(long long long long) SHLWAPI_16
|
16 stdcall @(long long long long) SHLWAPI_16
|
||||||
17 stub @
|
17 stdcall @ (ptr ptr) SHLWAPI_17
|
||||||
18 stdcall @(ptr ptr) SHLWAPI_18
|
18 stdcall @ (ptr ptr) SHLWAPI_18
|
||||||
19 stdcall @(ptr) SHLWAPI_19
|
19 stdcall @ (ptr) SHLWAPI_19
|
||||||
20 stub @
|
20 stdcall @ (ptr ptr) SHLWAPI_20
|
||||||
21 stdcall @(ptr long) SHLWAPI_21
|
21 stdcall @ (ptr long) SHLWAPI_21
|
||||||
22 stdcall @(ptr long) SHLWAPI_22
|
22 stdcall @ (ptr long) SHLWAPI_22
|
||||||
23 stdcall @(ptr ptr long) SHLWAPI_23
|
23 stdcall @(ptr ptr long) SHLWAPI_23
|
||||||
24 stdcall @(ptr ptr long) SHLWAPI_24
|
24 stdcall @(ptr ptr long) SHLWAPI_24
|
||||||
25 stdcall @(long) SHLWAPI_25
|
25 stdcall @(long) SHLWAPI_25
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
clist.ok
|
||||||
shlwapi_test.exe.spec.c
|
shlwapi_test.exe.spec.c
|
||||||
shreg.ok
|
shreg.ok
|
||||||
testlist.c
|
testlist.c
|
||||||
|
|
|
@ -0,0 +1,454 @@
|
||||||
|
/* Unit test suite for SHLWAPI Compact List 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 "wine/test.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;
|
||||||
|
LPCSHLWAPI_CLIST item;
|
||||||
|
} _IDummyStream;
|
||||||
|
|
||||||
|
static
|
||||||
|
HRESULT WINAPI QueryInterface(_IDummyStream *This,REFIID riid, LPVOID *ppvObj)
|
||||||
|
{
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ULONG WINAPI AddRef(_IDummyStream *This)
|
||||||
|
{
|
||||||
|
return ++This->ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ULONG WINAPI Release(_IDummyStream *This)
|
||||||
|
{
|
||||||
|
return --This->ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI Read(_IDummyStream* This, LPVOID lpMem, ULONG ulSize,
|
||||||
|
LPULONG 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,
|
||||||
|
LPULONG 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;
|
||||||
|
if (plibNewPosition)
|
||||||
|
plibNewPosition->QuadPart = sizeof(ULONG);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI Stat(_IDummyStream* This, STATSTG* pstatstg,
|
||||||
|
DWORD grfStatFlag)
|
||||||
|
{
|
||||||
|
++This->statcalls;
|
||||||
|
if (pstatstg)
|
||||||
|
pstatstg->cbSize.QuadPart = 5000l;
|
||||||
|
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 void InitFunctionPtrs()
|
||||||
|
{
|
||||||
|
SHLWAPI_hshlwapi = LoadLibraryA("shlwapi.dll");
|
||||||
|
ok(SHLWAPI_hshlwapi != 0, "LoadLibrary failed");
|
||||||
|
if (SHLWAPI_hshlwapi)
|
||||||
|
{
|
||||||
|
pSHLWAPI_17 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)17);
|
||||||
|
ok(pSHLWAPI_17 != 0, "No Ordinal 17");
|
||||||
|
pSHLWAPI_18 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)18);
|
||||||
|
ok(pSHLWAPI_18 != 0, "No Ordinal 18");
|
||||||
|
pSHLWAPI_19 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)19);
|
||||||
|
ok(pSHLWAPI_19 != 0, "No Ordinal 19");
|
||||||
|
pSHLWAPI_20 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)20);
|
||||||
|
ok(pSHLWAPI_20 != 0, "No Ordinal 20");
|
||||||
|
pSHLWAPI_21 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)21);
|
||||||
|
ok(pSHLWAPI_21 != 0, "No Ordinal 21");
|
||||||
|
pSHLWAPI_22 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)22);
|
||||||
|
ok(pSHLWAPI_22 != 0, "No Ordinal 22");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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->item = SHLWAPI_CLIST_items;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void test_CList(void)
|
||||||
|
{
|
||||||
|
_IDummyStream streamobj;
|
||||||
|
LPSHLWAPI_CLIST list = NULL;
|
||||||
|
LPCSHLWAPI_CLIST item = SHLWAPI_CLIST_items;
|
||||||
|
HRESULT hRet;
|
||||||
|
LPSHLWAPI_CLIST inserted;
|
||||||
|
char 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");
|
||||||
|
|
||||||
|
if (hRet > S_OK)
|
||||||
|
{
|
||||||
|
ok(list && list->ulSize, "item not added");
|
||||||
|
|
||||||
|
/* Find it */
|
||||||
|
inserted = pSHLWAPI_22(list, item->ulId);
|
||||||
|
ok(inserted != NULL, "lost after adding");
|
||||||
|
|
||||||
|
ok(!inserted || inserted->ulId != -1u, "find returned a container");
|
||||||
|
|
||||||
|
/* Check size */
|
||||||
|
if (inserted && inserted->ulSize & 0x3)
|
||||||
|
{
|
||||||
|
/* Contained */
|
||||||
|
ok(inserted[-1].ulId == -1u, "invalid size is not countained");
|
||||||
|
ok(inserted[-1].ulSize > inserted->ulSize+sizeof(SHLWAPI_CLIST),
|
||||||
|
"container too small");
|
||||||
|
}
|
||||||
|
else if (inserted)
|
||||||
|
{
|
||||||
|
ok(inserted->ulSize==item->ulSize+sizeof(SHLWAPI_CLIST),
|
||||||
|
"id %ld size wrong (%ld!=%ld)", 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");
|
||||||
|
}
|
||||||
|
ok(!inserted || inserted->ulId==item->ulId, "find got wrong item");
|
||||||
|
}
|
||||||
|
item++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write the list */
|
||||||
|
InitDummyStream(&streamobj);
|
||||||
|
|
||||||
|
hRet = pSHLWAPI_17(&streamobj, list);
|
||||||
|
ok(hRet == S_OK, "write failed");
|
||||||
|
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");
|
||||||
|
ok(streamobj.readcalls == 0,"called Read() in write");
|
||||||
|
ok(streamobj.seekcalls == 0,"called Seek() in write");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Failure cases for writing */
|
||||||
|
InitDummyStream(&streamobj);
|
||||||
|
streamobj.failwritecall = TRUE;
|
||||||
|
hRet = pSHLWAPI_17(&streamobj, list);
|
||||||
|
ok(hRet == STG_E_ACCESSDENIED, "changed object failure return");
|
||||||
|
ok(streamobj.writecalls == 1, "called object after failure");
|
||||||
|
ok(streamobj.readcalls == 0,"called Read() after failure");
|
||||||
|
ok(streamobj.seekcalls == 0,"called Seek() after failure");
|
||||||
|
|
||||||
|
InitDummyStream(&streamobj);
|
||||||
|
streamobj.failwritesize = TRUE;
|
||||||
|
hRet = pSHLWAPI_17(&streamobj, list);
|
||||||
|
ok(hRet == STG_E_MEDIUMFULL, "changed size failure return");
|
||||||
|
ok(streamobj.writecalls == 1, "called object after size failure");
|
||||||
|
ok(streamobj.readcalls == 0,"called Read() after failure");
|
||||||
|
ok(streamobj.seekcalls == 0,"called Seek() after failure");
|
||||||
|
|
||||||
|
/* Invalid inputs for adding */
|
||||||
|
inserted = (LPSHLWAPI_CLIST)buff;
|
||||||
|
inserted->ulSize = sizeof(SHLWAPI_CLIST) -1;
|
||||||
|
inserted->ulId = 33;
|
||||||
|
hRet = pSHLWAPI_20(&list, inserted);
|
||||||
|
ok(hRet == E_INVALIDARG, "allowed bad element size");
|
||||||
|
|
||||||
|
inserted->ulSize = 44;
|
||||||
|
inserted->ulId = -1;
|
||||||
|
hRet = pSHLWAPI_20(&list, inserted);
|
||||||
|
ok(hRet == E_INVALIDARG, "allowed adding a container");
|
||||||
|
|
||||||
|
item = SHLWAPI_CLIST_items;
|
||||||
|
|
||||||
|
/* Look for non-existing item in populated list */
|
||||||
|
inserted = pSHLWAPI_22(list, 99999999);
|
||||||
|
ok(inserted == NULL, "found a non-existing item");
|
||||||
|
|
||||||
|
while (item->ulSize)
|
||||||
|
{
|
||||||
|
/* Delete items */
|
||||||
|
BOOL bRet = pSHLWAPI_21(&list, item->ulId);
|
||||||
|
ok(bRet == TRUE, "couldn't find item to delete");
|
||||||
|
item++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Look for non-existing item in empty list */
|
||||||
|
inserted = pSHLWAPI_22(list, 99999999);
|
||||||
|
ok(inserted == NULL, "found an item in empty list");
|
||||||
|
|
||||||
|
/* Create a list by reading in data */
|
||||||
|
InitDummyStream(&streamobj);
|
||||||
|
|
||||||
|
hRet = pSHLWAPI_18(&streamobj, &list);
|
||||||
|
ok(hRet == S_OK, "failed create from Read()");
|
||||||
|
if (hRet == S_OK)
|
||||||
|
{
|
||||||
|
ok(streamobj.readbeyondend == FALSE, "read beyond end");
|
||||||
|
/* 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");
|
||||||
|
ok(streamobj.writecalls == 0, "called Write() from create");
|
||||||
|
ok(streamobj.seekcalls == 0,"called Seek() from create");
|
||||||
|
|
||||||
|
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");
|
||||||
|
|
||||||
|
ok(!inserted || inserted->ulId != -1, "find returned a container");
|
||||||
|
|
||||||
|
/* Check size */
|
||||||
|
if (inserted && inserted->ulSize & 0x3)
|
||||||
|
{
|
||||||
|
/* Contained */
|
||||||
|
ok(inserted[-1].ulId == -1, "invalid size is not countained");
|
||||||
|
ok(inserted[-1].ulSize > inserted->ulSize+sizeof(SHLWAPI_CLIST),
|
||||||
|
"container too small");
|
||||||
|
}
|
||||||
|
else if (inserted)
|
||||||
|
{
|
||||||
|
ok(inserted->ulSize==item->ulSize+sizeof(SHLWAPI_CLIST),
|
||||||
|
"id %ld size wrong (%ld!=%ld)", inserted->ulId, inserted->ulSize,
|
||||||
|
item->ulSize+sizeof(SHLWAPI_CLIST));
|
||||||
|
}
|
||||||
|
ok(!inserted || inserted->ulId==item->ulId, "find got wrong item");
|
||||||
|
if (inserted)
|
||||||
|
{
|
||||||
|
BOOL bDataOK = TRUE;
|
||||||
|
char *bufftest = (char*)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");
|
||||||
|
}
|
||||||
|
item++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Failure cases for reading */
|
||||||
|
InitDummyStream(&streamobj);
|
||||||
|
streamobj.failreadcall = TRUE;
|
||||||
|
hRet = pSHLWAPI_18(&streamobj, &list);
|
||||||
|
ok(hRet == STG_E_ACCESSDENIED, "changed object failure return");
|
||||||
|
ok(streamobj.readbeyondend == FALSE, "read beyond end");
|
||||||
|
ok(streamobj.readcalls == 1, "called object after read failure");
|
||||||
|
ok(streamobj.writecalls == 0,"called Write() after read failure");
|
||||||
|
ok(streamobj.seekcalls == 0,"called Seek() after read failure");
|
||||||
|
|
||||||
|
/* 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");
|
||||||
|
ok(streamobj.readbeyondend == FALSE, "read beyond end");
|
||||||
|
ok(streamobj.readcalls == 1,"wrong call count");
|
||||||
|
ok(streamobj.writecalls == 0,"called Write() after read failure");
|
||||||
|
ok(streamobj.seekcalls == 2,"wrong Seek() call count (%d)", streamobj.seekcalls);
|
||||||
|
|
||||||
|
pSHLWAPI_19(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
START_TEST(clist)
|
||||||
|
{
|
||||||
|
InitFunctionPtrs();
|
||||||
|
|
||||||
|
test_CList();
|
||||||
|
|
||||||
|
if (SHLWAPI_hshlwapi)
|
||||||
|
FreeLibrary(SHLWAPI_hshlwapi);
|
||||||
|
}
|
Loading…
Reference in New Issue