blob: aa5c83dc97b625e62cbad9270af0843c3ac91986 [file] [log] [blame]
/*
* Undocumented functions from COMCTL32.DLL
*
* Copyright 1998 Eric Kohl <ekohl@abo.rhein-zeitung.de>
* 1998 Juergen Schmied <j.schmied@metronet.de>
* NOTES
* All of these functions are UNDOCUMENTED!! And I mean UNDOCUMENTED!!!!
* Do NOT rely on names or contents of undocumented structures and types!!!
* These functions are used by EXPLORER.EXE, IEXPLORE.EXE and
* COMCTL32.DLL (internally).
*
* TODO
* - Fix DSA_InsertItem.
* - Fix DSA_GetItem.
* - Write documentation.
*/
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "windows.h"
#include "heap.h"
#include "debug.h"
typedef struct _DPA_DATA
{
DWORD dwEntryCount;
DWORD dwMaxCount;
DWORD dwGrow;
LPDWORD ptrs;
} DPA_DATA, *LPDPA_DATA;
DWORD WINAPI DPA_Create (DWORD);
DWORD WINAPI DPA_GetPtr (DWORD, DWORD);
DWORD WINAPI DPA_InsertPtr (DWORD, DWORD, DWORD);
CRITICAL_SECTION cs_comctl_alloc;
HANDLE32 hComctl32Heap=0;
/**************************************************************************
* Alloc [COMCTL32.71]
*
*/
LPVOID WINAPI COMCTL32_Alloc (DWORD dwParam)
{ LPVOID lpPtr;
TRACE (commctrl, "(0x%08lx)\n", dwParam);
if (hComctl32Heap==0)
{ EnterCriticalSection((void*)&cs_comctl_alloc);
hComctl32Heap=HeapCreate(0,1,0x4000000);
LeaveCriticalSection((void*)&cs_comctl_alloc);
TRACE (commctrl, "Heap created: 0x%08x\n", hComctl32Heap);
if (! hComctl32Heap)
return FALSE;
}
// lpPtr = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, dwParam);
lpPtr = HeapAlloc (hComctl32Heap, HEAP_ZERO_MEMORY, dwParam);
TRACE (commctrl, "-- ret=%p\n", lpPtr);
return lpPtr;
}
/**************************************************************************
* ReAlloc [COMCTL32.72]
*
*/
LPVOID WINAPI
COMCTL32_ReAlloc (LPVOID dwParam1, DWORD dwParam2)
{
LPVOID dwPtr;
TRACE (commctrl, "(0x%08lx 0x%08lx)\n",(DWORD)dwParam1, dwParam2);
if (dwParam1 == 0)
dwPtr = HeapAlloc (hComctl32Heap, HEAP_ZERO_MEMORY,
dwParam2);
else
dwPtr = HeapReAlloc (hComctl32Heap, HEAP_ZERO_MEMORY,
dwParam1, dwParam2);
TRACE (commctrl, "-- ret=0x%08lx\n", (DWORD)dwPtr);
return dwPtr;
}
/**************************************************************************
* Free [COMCTL32.73]
*
*/
DWORD WINAPI
COMCTL32_Free (LPVOID dwParam)
{
TRACE (commctrl, "(0x%08lx)\n", (DWORD)dwParam);
HeapFree (hComctl32Heap, 0, dwParam);
return 0;
}
/**************************************************************************
* GetSize [COMCTL32.74]
*
*/
DWORD WINAPI
COMCTL32_GetSize (LPVOID dwParam)
{
TRACE (commctrl, "(0x%08lx)\n", (DWORD)dwParam);
return (HeapSize (hComctl32Heap, 0, dwParam));
}
/**************************************************************************
* Str_SetPtrA [COMCTL32.234]
*
* PARAMS
* dwParam1 [I]
* dwParam2 [I]
*/
BOOL32 WINAPI
COMCTL32_Str_SetPtrA (LPSTR lpStr, LPVOID *lpPtr)
{
INT32 len;
LPSTR ptr;
FIXME (commctrl, "(0x%08lx 0x%08lx)\n", (DWORD)lpStr, (DWORD)lpPtr);
FIXME (commctrl, "(\"%s\" \"%s\")\n", lpStr, (LPSTR)*lpPtr);
if (lpStr) {
len = lstrlen32A (lpStr);
ptr = COMCTL32_ReAlloc (lpPtr, len + 1);
if (!(ptr))
return FALSE;
lstrcpy32A (ptr, lpStr);
*lpPtr = ptr;
return TRUE;
}
if (*lpPtr) {
COMCTL32_Free (*lpPtr);
return TRUE;
}
return FALSE;
}
/*************************************************************************
* The DSA-API is a set of functions to create and manipulate arrays of
* fix sized memory blocks. This arrays can store any kind of data (strings,
* icons...) so the name "dynamic string array" is a bit misleading.
*
* STATUS
* complete
*/
typedef struct _DSA_DATA
{ DWORD dwEntryCount;
BYTE * pData;
DWORD dwMaxCount;
DWORD dwElementSize;
DWORD dwGrow;
} DSA_DATA, *LPDSA_DATA;
/**************************************************************************
* DSA_Create [COMCTL32.320] Creates a dynamic string array
*
* PARAMS
* dwSize [I] size of the array elements
* dwGrow [I]
* RETURNS
* pointer to a array control structure. use this like a handle.
*/
LPDSA_DATA WINAPI DSA_Create (DWORD dwSize, DWORD dwGrow)
{ LPDSA_DATA dsaPtr;
TRACE (commctrl, "(size=0x%08lx grow=0x%08lx)\n", dwSize, dwGrow);
if ((dsaPtr=(LPDSA_DATA)COMCTL32_Alloc(sizeof(DSA_DATA))));
{ dsaPtr->dwEntryCount=0x00;
dsaPtr->pData=NULL;
dsaPtr->dwMaxCount=0x00;
dsaPtr->dwElementSize=dwSize;
if ( dwGrow == 0 )
dsaPtr->dwGrow=1;
else
dsaPtr->dwGrow=dwGrow;
return dsaPtr;
}
return FALSE;
}
/**************************************************************************
* DSA_Destroy [COMCTL32.321] Destroys a dynamic string array
*
* PARAMS
* dsaPtr [I] pointer to the array control structure
* RETURNS
* TRUE if dsaPtr = NULL or success
* FALSE if failure
*/
BOOL32 WINAPI DSA_Destroy (const LPDSA_DATA dsaPtr )
{ TRACE (commctrl, "(%p)\n", dsaPtr);
if (! dsaPtr)
return FALSE;
if (dsaPtr->pData && (! COMCTL32_Free(dsaPtr->pData)))
{ return FALSE;
}
return COMCTL32_Free (dsaPtr);
}
/**************************************************************************
* DSA_GetItem [COMCTL32.322]
*
* PARAMS
* dsaPtr [I] pointer to the array control structure
* dwItem [I] number of the Item to get
+ * pDest [O] destination buffer. Has to be >= dwElementSize.
*/
BOOL32 WINAPI DSA_GetItem (const LPDSA_DATA dsaPtr, DWORD dwItem, LPBYTE pDest)
{ BYTE * pSrc;
TRACE (commctrl, "(%p 0x%08lx %p)\n", dsaPtr, dwItem, pDest);
if ( (!dsaPtr) || (dwItem < 0) || (dwItem >= dsaPtr->dwEntryCount))
return FALSE;
pSrc = dsaPtr->pData + (dsaPtr->dwElementSize * dwItem);
memmove(pDest,pSrc,dsaPtr->dwElementSize);
return TRUE;
}
/**************************************************************************
* DSA_GetItemPtr [COMCTL32.323]
*
* PARAMS
* dsaPtr [I] pointer to the array control structure
* dwItem [I] number of the Item to get
* RETURNS
* pointer ti a item
*/
LPBYTE WINAPI DSA_GetItemPtr (const LPDSA_DATA dsaPtr, DWORD dwItem)
{ BYTE * pSrc;
TRACE (commctrl, "(%p 0x%08lx)\n", dsaPtr, dwItem);
if ((!dsaPtr) || (dwItem < 0) || (dwItem >= dsaPtr->dwEntryCount))
return FALSE;
pSrc = dsaPtr->pData + (dsaPtr->dwElementSize * dwItem);
TRACE (commctrl, "-- ret=%p\n", pSrc);
return pSrc;
}
/**************************************************************************
* DSA_SetItem [COMCTL32.325]
*
* PARAMS
* dsaPtr [I] pointer to the array control structure
* dwItem [I] index for the new element
* pSrc [I] the element
*/
BOOL32 WINAPI DSA_SetItem (const LPDSA_DATA dsaPtr, DWORD dwItem, LPBYTE pSrc)
{ LPBYTE pDest;
DWORD dwSize, dwNewItems;
LPBYTE lpTemp;
TRACE (commctrl, "(%p 0x%08lx %p)\n", dsaPtr, dwItem, pSrc);
if ((!dsaPtr) || dwItem<0 )
return FALSE;
if (dsaPtr->dwEntryCount <= dwItem) /* within the old array */
{ if ( dsaPtr->dwMaxCount > dwItem)
{ dsaPtr->dwEntryCount = dwItem; /* within the allocated space, set a new boundary */
}
else
{ /* resize the block of memory*/
dwNewItems = dsaPtr->dwGrow * ( (WORD)((dwItem-1)/dsaPtr->dwGrow) +1);
dwSize = dsaPtr->dwElementSize * dwNewItems;
lpTemp = (LPBYTE) COMCTL32_ReAlloc(dsaPtr->pData,dwSize);
if (! lpTemp )
{ return FALSE;
}
dsaPtr->dwMaxCount = dwNewItems;
dsaPtr->pData = lpTemp;
}
}
/* put the new entry in */
pDest = dsaPtr->pData + (dsaPtr->dwElementSize * dwItem);
TRACE (commctrl,"move dest=%p src=%p size=%x",pDest,pSrc,dsaPtr->dwElementSize);
memmove(pDest,pSrc,dsaPtr->dwElementSize);
return TRUE;
}
/**************************************************************************
* DSA_InsertItem [COMCTL32.325]
*
* PARAMS
* dsaPtr [I] pointer to the array control structure
* dwItem [I] index for the new element
* pSrc [I] the element
*
* RETURNS
* the position of the new element
*/
DWORD WINAPI DSA_InsertItem (const LPDSA_DATA dsaPtr, DWORD dwItem, LPBYTE pSrc)
{ DWORD dwNewItems, dwSize,i;
LPBYTE lpTemp, lpDest;
LPDWORD p;
TRACE(commctrl, "(%p 0x%08lx %p)\n", dsaPtr, dwItem, pSrc);
if ( (!dsaPtr) || dwItem<0 )
return -1;
for (i=0; i<dsaPtr->dwElementSize;i+=4)
{ p = *(DWORD**)(pSrc+i);
if ( IsBadStringPtr32A ((char*)p,256))
{ TRACE(commctrl,"-- 0x%04lx=%p\n",i,(DWORD*)p);
}
else
{ TRACE(commctrl,"-- 0x%04lx=%p [%s]\n",i,p,debugstr_a((char*)p));
}
}
if (dwItem > dsaPtr->dwEntryCount) /* when dwItem > dwEntryCount then append*/
dwItem = dsaPtr->dwEntryCount+1;
if (dwItem >= dsaPtr->dwMaxCount) /* do we need to resize ? */
{ dwNewItems = dsaPtr->dwMaxCount + dsaPtr->dwGrow;
dwSize = dsaPtr->dwElementSize * dwNewItems;
lpTemp = (LPBYTE)COMCTL32_ReAlloc(dsaPtr->pData,dwSize);
if (!lpTemp)
{ return -1;
}
dsaPtr->dwMaxCount = dwNewItems;
dsaPtr->pData = lpTemp;
}
if (dwItem < dsaPtr->dwEntryCount) /* do we need to move elements ?*/
{ lpTemp = dsaPtr->pData + (dsaPtr->dwElementSize * dwItem);
lpDest = lpTemp + dsaPtr->dwElementSize;
TRACE (commctrl,"-- move dest=%p src=%p size=%x\n",lpDest,lpTemp,dsaPtr->dwElementSize);
memmove (lpDest,lpTemp,dsaPtr->dwElementSize);
}
/* ok, we can put the new Item in*/
dsaPtr->dwEntryCount++;
lpDest = dsaPtr->pData + (dsaPtr->dwElementSize * dwItem);
TRACE (commctrl,"-- move dest=%p src=%p size=%x\n",lpDest,pSrc,dsaPtr->dwElementSize);
memmove (lpDest,pSrc,dsaPtr->dwElementSize);
return dsaPtr->dwEntryCount;
}
/**************************************************************************
* DSA_DeleteItem [COMCTL32.326]
*
* PARAMS
* dsaPtr [I] pointer to the array control structure
* dwItem [I] index for the element to delete
* RETURNS
* number of the element deleted
*/
DWORD WINAPI DSA_DeleteItem (const LPDSA_DATA dsaPtr, DWORD dwItem)
{ LPBYTE lpDest,lpSrc;
DWORD dwSize;
TRACE (commctrl, "(%p 0x%08lx)\n", dsaPtr, dwItem);
if ( (! dsaPtr) || dwItem<0 || dwItem>=dsaPtr->dwEntryCount)
return FALSE;
if ( dwItem < dsaPtr->dwEntryCount-1 ) /* do we need to move ?*/
{ lpDest = dsaPtr->pData + (dsaPtr->dwElementSize * dwItem);
lpSrc = lpDest + dsaPtr->dwElementSize;
dwSize = dsaPtr->dwElementSize * (dsaPtr->dwEntryCount-dwItem-1);
TRACE (commctrl,"-- move dest=%p src=%p size=%x\n",lpDest,lpSrc,dwSize);
memmove (lpDest,lpSrc,dwSize);
}
dsaPtr->dwEntryCount--;
if ( (dsaPtr->dwMaxCount-dsaPtr->dwEntryCount) >= dsaPtr->dwGrow) /* free memory ?*/
{ dwSize = dsaPtr->dwElementSize * dsaPtr->dwEntryCount;
lpDest = (LPBYTE) COMCTL32_ReAlloc(dsaPtr->pData,dwSize);
if (!lpDest)
{ return FALSE;
}
dsaPtr->dwMaxCount = dsaPtr->dwEntryCount;
dsaPtr->pData = lpDest;
}
return dwItem;
}
/**************************************************************************
* DSA_DeleteAllItems [COMCTL32.326]
* deletes all elements and initializes array
*
* PARAMS
* dsaPtr [I] pointer to the array control structure
*
* RETURNS
* TRUE/FALSE
*/
BOOL32 WINAPI DSA_DeleteAllItems (const LPDSA_DATA dsaPtr)
{ TRACE (commctrl, "(%p)\n", dsaPtr);
if (! dsaPtr)
return FALSE;
if (dsaPtr->pData && (! COMCTL32_Free(dsaPtr->pData)))
{ return FALSE;
}
dsaPtr->dwEntryCount=0x00;
dsaPtr->pData=NULL;
dsaPtr->dwMaxCount=0x00;
return TRUE;
}
/**************************************************************************/
DWORD WINAPI
DPA_Create (DWORD dwParam1)
{
LPDPA_DATA dpaPtr;
TRACE (commctrl, "(0x%08lx)\n", dwParam1);
dpaPtr = (LPDPA_DATA)HeapAlloc (SystemHeap, HEAP_ZERO_MEMORY, sizeof(DPA_DATA));
dpaPtr->dwGrow = dwParam1;
TRACE (commctrl, "ret=0x%08lx\n", (DWORD)dpaPtr);
return (DWORD)dpaPtr;
}
DWORD WINAPI
DPA_GetPtr (DWORD dwParam1, DWORD dwParam2)
{
LPDPA_DATA dpaPtr = (LPDPA_DATA)dwParam1;
TRACE (commctrl, "(0x%08lx 0x%08lx)\n", dwParam1, dwParam2);
if (dpaPtr == NULL)
return 0;
if (dpaPtr->ptrs == NULL)
return 0;
if ((dwParam2 < 0) || (dwParam2 >= dpaPtr->dwEntryCount))
return 0;
TRACE (commctrl, "ret=0x%08lx\n", (DWORD)dpaPtr->ptrs[dwParam2]);
return (DWORD)dpaPtr->ptrs[dwParam2];
}
DWORD WINAPI
DPA_InsertPtr (DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
{
LPDPA_DATA dpaPtr = (LPDPA_DATA)dwParam1;
DWORD dwIndex;
TRACE (commctrl, "(0x%08lx 0x%08lx 0x%lx)\n",
dwParam1, dwParam2, dwParam3);
if (dpaPtr->ptrs == NULL) {
dpaPtr->ptrs = (LPDWORD)HeapAlloc (SystemHeap, HEAP_ZERO_MEMORY,
dpaPtr->dwGrow * sizeof(LPVOID));
dpaPtr->dwMaxCount = dpaPtr->dwGrow;
dwIndex = 0;
dpaPtr->ptrs[dwIndex] = dwParam3;
}
else {
FIXME (commctrl, "adding to existing array! stub!\n");
dwIndex = dwParam2;
}
dpaPtr->dwEntryCount++;
return (dwIndex);
}
/**************************************************************************
* DPA_CreateEx [COMCTL32.340]
*
*/
DWORD WINAPI
DPA_CreateEx (DWORD dwParam1, DWORD dwParam2)
{
FIXME (commctrl, "(0x%08lx 0x%08lx)\n",
dwParam1, dwParam2);
return 0;
}
/**************************************************************************
* SendNotify [COMCTL32.341]
*
*/
DWORD WINAPI
COMCTL32_SendNotify (DWORD dw1, DWORD dw2, DWORD dw3, DWORD dw4)
{
FIXME (commctrl, "(0x%08lx 0x%08lx 0x%08lx 0x%08lx)\n",
dw1, dw2, dw3, dw4);
return 0;
}
/**************************************************************************
* StrChrA [COMCTL32.350]
*
*/
LPSTR WINAPI
COMCTL32_StrChrA (LPCSTR lpString, CHAR cChar)
{
return strchr (lpString, cChar);
}
/**************************************************************************
* StrStrIA [COMCTL32.355]
*/
LPSTR WINAPI
COMCTL32_StrStrIA (LPCSTR lpStr1, LPCSTR lpStr2)
{
INT32 len1, len2, i;
CHAR first;
if (*lpStr2 == 0)
return ((LPSTR)lpStr1);
len1 = 0;
while (lpStr1[len1] != 0) ++len1;
len2 = 0;
while (lpStr2[len2] != 0) ++len2;
if (len2 == 0)
return ((LPSTR)(lpStr1 + len1));
first = tolower (*lpStr2);
while (len1 >= len2) {
if (tolower(*lpStr1) == first) {
for (i = 1; i < len2; ++i)
if (tolower (lpStr1[i]) != tolower(lpStr2[i]))
break;
if (i >= len2)
return ((LPSTR)lpStr1);
}
++lpStr1; --len1;
}
return (NULL);
}
/**************************************************************************
* StrToIntA [COMCTL32.357] Converts a string to a signed integer.
*/
INT32 WINAPI
COMCTL32_StrToIntA (LPSTR lpString)
{
return atoi(lpString);
}