1*c2c66affSColin Finck /* 2*c2c66affSColin Finck * Dynamic pointer array (DPA) implementation 3*c2c66affSColin Finck * 4*c2c66affSColin Finck * Copyright 1998 Eric Kohl 5*c2c66affSColin Finck * 1998 Juergen Schmied <j.schmied@metronet.de> 6*c2c66affSColin Finck * 2000 Eric Kohl for CodeWeavers 7*c2c66affSColin Finck * 8*c2c66affSColin Finck * This library is free software; you can redistribute it and/or 9*c2c66affSColin Finck * modify it under the terms of the GNU Lesser General Public 10*c2c66affSColin Finck * License as published by the Free Software Foundation; either 11*c2c66affSColin Finck * version 2.1 of the License, or (at your option) any later version. 12*c2c66affSColin Finck * 13*c2c66affSColin Finck * This library is distributed in the hope that it will be useful, 14*c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of 15*c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16*c2c66affSColin Finck * Lesser General Public License for more details. 17*c2c66affSColin Finck * 18*c2c66affSColin Finck * You should have received a copy of the GNU Lesser General Public 19*c2c66affSColin Finck * License along with this library; if not, write to the Free Software 20*c2c66affSColin Finck * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 21*c2c66affSColin Finck * 22*c2c66affSColin Finck * NOTES 23*c2c66affSColin Finck * These functions were involuntarily documented by Microsoft in 2002 as 24*c2c66affSColin Finck * the outcome of an anti-trust suit brought by various U.S. governments. 25*c2c66affSColin Finck * As a result the specifications on MSDN are inaccurate, incomplete 26*c2c66affSColin Finck * and misleading. A much more complete (unofficial) documentation is 27*c2c66affSColin Finck * available at: 28*c2c66affSColin Finck * 29*c2c66affSColin Finck * http://members.ozemail.com.au/~geoffch/samples/win32/shell/comctl32 30*c2c66affSColin Finck */ 31*c2c66affSColin Finck 32*c2c66affSColin Finck #include "comctl32.h" 33*c2c66affSColin Finck 34*c2c66affSColin Finck WINE_DEFAULT_DEBUG_CHANNEL(dpa); 35*c2c66affSColin Finck 36*c2c66affSColin Finck typedef struct _DPA 37*c2c66affSColin Finck { 38*c2c66affSColin Finck INT nItemCount; 39*c2c66affSColin Finck LPVOID *ptrs; 40*c2c66affSColin Finck HANDLE hHeap; 41*c2c66affSColin Finck INT nGrow; 42*c2c66affSColin Finck INT nMaxCount; 43*c2c66affSColin Finck } DPA; 44*c2c66affSColin Finck 45*c2c66affSColin Finck typedef struct _STREAMDATA 46*c2c66affSColin Finck { 47*c2c66affSColin Finck DWORD dwSize; 48*c2c66affSColin Finck DWORD dwData2; 49*c2c66affSColin Finck DWORD dwItems; 50*c2c66affSColin Finck } STREAMDATA, *PSTREAMDATA; 51*c2c66affSColin Finck 52*c2c66affSColin Finck /************************************************************************** 53*c2c66affSColin Finck * DPA_LoadStream [COMCTL32.9] 54*c2c66affSColin Finck * 55*c2c66affSColin Finck * Loads a dynamic pointer array from a stream 56*c2c66affSColin Finck * 57*c2c66affSColin Finck * PARAMS 58*c2c66affSColin Finck * phDpa [O] pointer to a handle to a dynamic pointer array 59*c2c66affSColin Finck * loadProc [I] pointer to a callback function 60*c2c66affSColin Finck * pStream [I] pointer to a stream 61*c2c66affSColin Finck * pData [I] pointer to callback data 62*c2c66affSColin Finck * 63*c2c66affSColin Finck * RETURNS 64*c2c66affSColin Finck * Success: S_OK, S_FALSE - partial success 65*c2c66affSColin Finck * Failure: HRESULT error code 66*c2c66affSColin Finck * 67*c2c66affSColin Finck * NOTES 68*c2c66affSColin Finck * No more information available yet! 69*c2c66affSColin Finck */ 70*c2c66affSColin Finck HRESULT WINAPI DPA_LoadStream (HDPA *phDpa, PFNDPASTREAM loadProc, 71*c2c66affSColin Finck IStream *pStream, LPVOID pData) 72*c2c66affSColin Finck { 73*c2c66affSColin Finck HRESULT errCode; 74*c2c66affSColin Finck LARGE_INTEGER position; 75*c2c66affSColin Finck ULARGE_INTEGER initial_pos; 76*c2c66affSColin Finck STREAMDATA streamData; 77*c2c66affSColin Finck DPASTREAMINFO streamInfo; 78*c2c66affSColin Finck ULONG ulRead; 79*c2c66affSColin Finck HDPA hDpa; 80*c2c66affSColin Finck PVOID *ptr; 81*c2c66affSColin Finck 82*c2c66affSColin Finck TRACE ("phDpa=%p loadProc=%p pStream=%p pData=%p\n", 83*c2c66affSColin Finck phDpa, loadProc, pStream, pData); 84*c2c66affSColin Finck 85*c2c66affSColin Finck if (!phDpa || !loadProc || !pStream) 86*c2c66affSColin Finck return E_INVALIDARG; 87*c2c66affSColin Finck 88*c2c66affSColin Finck *phDpa = NULL; 89*c2c66affSColin Finck 90*c2c66affSColin Finck position.QuadPart = 0; 91*c2c66affSColin Finck 92*c2c66affSColin Finck errCode = IStream_Seek (pStream, position, STREAM_SEEK_CUR, &initial_pos); 93*c2c66affSColin Finck if (errCode != S_OK) 94*c2c66affSColin Finck return errCode; 95*c2c66affSColin Finck 96*c2c66affSColin Finck memset(&streamData, 0, sizeof(STREAMDATA)); 97*c2c66affSColin Finck errCode = IStream_Read (pStream, &streamData, sizeof(STREAMDATA), &ulRead); 98*c2c66affSColin Finck if (errCode != S_OK) 99*c2c66affSColin Finck return errCode; 100*c2c66affSColin Finck 101*c2c66affSColin Finck TRACE ("dwSize=%u dwData2=%u dwItems=%u\n", 102*c2c66affSColin Finck streamData.dwSize, streamData.dwData2, streamData.dwItems); 103*c2c66affSColin Finck 104*c2c66affSColin Finck if (ulRead < sizeof(STREAMDATA) || 105*c2c66affSColin Finck streamData.dwSize < sizeof(STREAMDATA) || streamData.dwData2 != 1) { 106*c2c66affSColin Finck /* back to initial position */ 107*c2c66affSColin Finck position.QuadPart = initial_pos.QuadPart; 108*c2c66affSColin Finck IStream_Seek (pStream, position, STREAM_SEEK_SET, NULL); 109*c2c66affSColin Finck return E_FAIL; 110*c2c66affSColin Finck } 111*c2c66affSColin Finck 112*c2c66affSColin Finck if (streamData.dwItems > (UINT_MAX / 2 / sizeof(VOID*))) /* 536870911 */ 113*c2c66affSColin Finck return E_OUTOFMEMORY; 114*c2c66affSColin Finck 115*c2c66affSColin Finck /* create the dpa */ 116*c2c66affSColin Finck hDpa = DPA_Create (streamData.dwItems); 117*c2c66affSColin Finck if (!hDpa) 118*c2c66affSColin Finck return E_OUTOFMEMORY; 119*c2c66affSColin Finck 120*c2c66affSColin Finck if (!DPA_Grow (hDpa, streamData.dwItems)) { 121*c2c66affSColin Finck DPA_Destroy (hDpa); 122*c2c66affSColin Finck return E_OUTOFMEMORY; 123*c2c66affSColin Finck } 124*c2c66affSColin Finck 125*c2c66affSColin Finck /* load data from the stream into the dpa */ 126*c2c66affSColin Finck ptr = hDpa->ptrs; 127*c2c66affSColin Finck for (streamInfo.iPos = 0; streamInfo.iPos < streamData.dwItems; streamInfo.iPos++) { 128*c2c66affSColin Finck errCode = (loadProc)(&streamInfo, pStream, pData); 129*c2c66affSColin Finck if (errCode != S_OK) { 130*c2c66affSColin Finck errCode = S_FALSE; 131*c2c66affSColin Finck break; 132*c2c66affSColin Finck } 133*c2c66affSColin Finck 134*c2c66affSColin Finck *ptr = streamInfo.pvItem; 135*c2c66affSColin Finck ptr++; 136*c2c66affSColin Finck } 137*c2c66affSColin Finck 138*c2c66affSColin Finck /* set the number of items */ 139*c2c66affSColin Finck hDpa->nItemCount = streamInfo.iPos; 140*c2c66affSColin Finck 141*c2c66affSColin Finck /* store the handle to the dpa */ 142*c2c66affSColin Finck *phDpa = hDpa; 143*c2c66affSColin Finck TRACE ("new hDpa=%p, errorcode=%x\n", hDpa, errCode); 144*c2c66affSColin Finck 145*c2c66affSColin Finck return errCode; 146*c2c66affSColin Finck } 147*c2c66affSColin Finck 148*c2c66affSColin Finck 149*c2c66affSColin Finck /************************************************************************** 150*c2c66affSColin Finck * DPA_SaveStream [COMCTL32.10] 151*c2c66affSColin Finck * 152*c2c66affSColin Finck * Saves a dynamic pointer array to a stream 153*c2c66affSColin Finck * 154*c2c66affSColin Finck * PARAMS 155*c2c66affSColin Finck * hDpa [I] handle to a dynamic pointer array 156*c2c66affSColin Finck * saveProc [I] pointer to a callback function 157*c2c66affSColin Finck * pStream [I] pointer to a stream 158*c2c66affSColin Finck * pData [I] pointer to callback data 159*c2c66affSColin Finck * 160*c2c66affSColin Finck * RETURNS 161*c2c66affSColin Finck * Success: S_OK, S_FALSE - partial success 162*c2c66affSColin Finck * Failure: HRESULT error code 163*c2c66affSColin Finck * 164*c2c66affSColin Finck * NOTES 165*c2c66affSColin Finck * No more information available yet! 166*c2c66affSColin Finck */ 167*c2c66affSColin Finck HRESULT WINAPI DPA_SaveStream (HDPA hDpa, PFNDPASTREAM saveProc, 168*c2c66affSColin Finck IStream *pStream, LPVOID pData) 169*c2c66affSColin Finck { 170*c2c66affSColin Finck LARGE_INTEGER position; 171*c2c66affSColin Finck ULARGE_INTEGER initial_pos, curr_pos; 172*c2c66affSColin Finck STREAMDATA streamData; 173*c2c66affSColin Finck DPASTREAMINFO streamInfo; 174*c2c66affSColin Finck HRESULT hr; 175*c2c66affSColin Finck PVOID *ptr; 176*c2c66affSColin Finck 177*c2c66affSColin Finck TRACE ("hDpa=%p saveProc=%p pStream=%p pData=%p\n", 178*c2c66affSColin Finck hDpa, saveProc, pStream, pData); 179*c2c66affSColin Finck 180*c2c66affSColin Finck if (!hDpa || !saveProc || !pStream) return E_INVALIDARG; 181*c2c66affSColin Finck 182*c2c66affSColin Finck /* save initial position to write header after completion */ 183*c2c66affSColin Finck position.QuadPart = 0; 184*c2c66affSColin Finck hr = IStream_Seek (pStream, position, STREAM_SEEK_CUR, &initial_pos); 185*c2c66affSColin Finck if (hr != S_OK) 186*c2c66affSColin Finck return hr; 187*c2c66affSColin Finck 188*c2c66affSColin Finck /* write empty header */ 189*c2c66affSColin Finck streamData.dwSize = sizeof(streamData); 190*c2c66affSColin Finck streamData.dwData2 = 1; 191*c2c66affSColin Finck streamData.dwItems = 0; 192*c2c66affSColin Finck 193*c2c66affSColin Finck hr = IStream_Write (pStream, &streamData, sizeof(streamData), NULL); 194*c2c66affSColin Finck if (hr != S_OK) { 195*c2c66affSColin Finck position.QuadPart = initial_pos.QuadPart; 196*c2c66affSColin Finck IStream_Seek (pStream, position, STREAM_SEEK_SET, NULL); 197*c2c66affSColin Finck return hr; 198*c2c66affSColin Finck } 199*c2c66affSColin Finck 200*c2c66affSColin Finck /* no items - we're done */ 201*c2c66affSColin Finck if (hDpa->nItemCount == 0) return S_OK; 202*c2c66affSColin Finck 203*c2c66affSColin Finck ptr = hDpa->ptrs; 204*c2c66affSColin Finck for (streamInfo.iPos = 0; streamInfo.iPos < hDpa->nItemCount; streamInfo.iPos++) { 205*c2c66affSColin Finck streamInfo.pvItem = *ptr; 206*c2c66affSColin Finck hr = (saveProc)(&streamInfo, pStream, pData); 207*c2c66affSColin Finck if (hr != S_OK) { 208*c2c66affSColin Finck hr = S_FALSE; 209*c2c66affSColin Finck break; 210*c2c66affSColin Finck } 211*c2c66affSColin Finck ptr++; 212*c2c66affSColin Finck } 213*c2c66affSColin Finck 214*c2c66affSColin Finck /* write updated header */ 215*c2c66affSColin Finck position.QuadPart = 0; 216*c2c66affSColin Finck IStream_Seek (pStream, position, STREAM_SEEK_CUR, &curr_pos); 217*c2c66affSColin Finck 218*c2c66affSColin Finck streamData.dwSize = curr_pos.QuadPart - initial_pos.QuadPart; 219*c2c66affSColin Finck streamData.dwData2 = 1; 220*c2c66affSColin Finck streamData.dwItems = streamInfo.iPos; 221*c2c66affSColin Finck 222*c2c66affSColin Finck position.QuadPart = initial_pos.QuadPart; 223*c2c66affSColin Finck IStream_Seek (pStream, position, STREAM_SEEK_SET, NULL); 224*c2c66affSColin Finck IStream_Write (pStream, &streamData, sizeof(streamData), NULL); 225*c2c66affSColin Finck 226*c2c66affSColin Finck position.QuadPart = curr_pos.QuadPart; 227*c2c66affSColin Finck IStream_Seek (pStream, position, STREAM_SEEK_SET, NULL); 228*c2c66affSColin Finck 229*c2c66affSColin Finck return hr; 230*c2c66affSColin Finck } 231*c2c66affSColin Finck 232*c2c66affSColin Finck 233*c2c66affSColin Finck /************************************************************************** 234*c2c66affSColin Finck * DPA_Merge [COMCTL32.11] 235*c2c66affSColin Finck * 236*c2c66affSColin Finck * Merge two dynamic pointers arrays. 237*c2c66affSColin Finck * 238*c2c66affSColin Finck * PARAMS 239*c2c66affSColin Finck * hdpa1 [I] handle to a dynamic pointer array 240*c2c66affSColin Finck * hdpa2 [I] handle to a dynamic pointer array 241*c2c66affSColin Finck * dwFlags [I] flags 242*c2c66affSColin Finck * pfnCompare [I] pointer to sort function 243*c2c66affSColin Finck * pfnMerge [I] pointer to merge function 244*c2c66affSColin Finck * lParam [I] application specific value 245*c2c66affSColin Finck * 246*c2c66affSColin Finck * RETURNS 247*c2c66affSColin Finck * Success: TRUE 248*c2c66affSColin Finck * Failure: FALSE 249*c2c66affSColin Finck * 250*c2c66affSColin Finck * NOTES 251*c2c66affSColin Finck * No more information available yet! 252*c2c66affSColin Finck */ 253*c2c66affSColin Finck BOOL WINAPI DPA_Merge (HDPA hdpa1, HDPA hdpa2, DWORD dwFlags, 254*c2c66affSColin Finck PFNDPACOMPARE pfnCompare, PFNDPAMERGE pfnMerge, 255*c2c66affSColin Finck LPARAM lParam) 256*c2c66affSColin Finck { 257*c2c66affSColin Finck INT nCount; 258*c2c66affSColin Finck LPVOID *pWork1, *pWork2; 259*c2c66affSColin Finck INT nResult, i; 260*c2c66affSColin Finck INT nIndex; 261*c2c66affSColin Finck 262*c2c66affSColin Finck TRACE("(%p %p %08x %p %p %08lx)\n", 263*c2c66affSColin Finck hdpa1, hdpa2, dwFlags, pfnCompare, pfnMerge, lParam); 264*c2c66affSColin Finck 265*c2c66affSColin Finck if (IsBadWritePtr (hdpa1, sizeof(*hdpa1))) 266*c2c66affSColin Finck return FALSE; 267*c2c66affSColin Finck 268*c2c66affSColin Finck if (IsBadWritePtr (hdpa2, sizeof(*hdpa2))) 269*c2c66affSColin Finck return FALSE; 270*c2c66affSColin Finck 271*c2c66affSColin Finck if (IsBadCodePtr ((FARPROC)pfnCompare)) 272*c2c66affSColin Finck return FALSE; 273*c2c66affSColin Finck 274*c2c66affSColin Finck if (IsBadCodePtr ((FARPROC)pfnMerge)) 275*c2c66affSColin Finck return FALSE; 276*c2c66affSColin Finck 277*c2c66affSColin Finck if (!(dwFlags & DPAM_SORTED)) { 278*c2c66affSColin Finck TRACE("sorting dpa's.\n"); 279*c2c66affSColin Finck if (hdpa1->nItemCount > 0) 280*c2c66affSColin Finck DPA_Sort (hdpa1, pfnCompare, lParam); 281*c2c66affSColin Finck TRACE ("dpa 1 sorted.\n"); 282*c2c66affSColin Finck if (hdpa2->nItemCount > 0) 283*c2c66affSColin Finck DPA_Sort (hdpa2, pfnCompare, lParam); 284*c2c66affSColin Finck TRACE ("dpa 2 sorted.\n"); 285*c2c66affSColin Finck } 286*c2c66affSColin Finck 287*c2c66affSColin Finck if (hdpa2->nItemCount < 1) 288*c2c66affSColin Finck return TRUE; 289*c2c66affSColin Finck 290*c2c66affSColin Finck TRACE("hdpa1->nItemCount=%d hdpa2->nItemCount=%d\n", 291*c2c66affSColin Finck hdpa1->nItemCount, hdpa2->nItemCount); 292*c2c66affSColin Finck 293*c2c66affSColin Finck 294*c2c66affSColin Finck nIndex = hdpa1->nItemCount - 1; 295*c2c66affSColin Finck nCount = hdpa2->nItemCount - 1; 296*c2c66affSColin Finck 297*c2c66affSColin Finck do 298*c2c66affSColin Finck { 299*c2c66affSColin Finck pWork1 = &hdpa1->ptrs[nIndex]; 300*c2c66affSColin Finck pWork2 = &hdpa2->ptrs[nCount]; 301*c2c66affSColin Finck 302*c2c66affSColin Finck if (nIndex < 0) { 303*c2c66affSColin Finck if ((nCount >= 0) && (dwFlags & DPAM_UNION)) { 304*c2c66affSColin Finck /* Now insert the remaining new items into DPA 1 */ 305*c2c66affSColin Finck TRACE("%d items to be inserted at start of DPA 1\n", 306*c2c66affSColin Finck nCount+1); 307*c2c66affSColin Finck for (i=nCount; i>=0; i--) { 308*c2c66affSColin Finck PVOID ptr; 309*c2c66affSColin Finck 310*c2c66affSColin Finck ptr = (pfnMerge)(DPAMM_INSERT, *pWork2, NULL, lParam); 311*c2c66affSColin Finck if (!ptr) 312*c2c66affSColin Finck return FALSE; 313*c2c66affSColin Finck DPA_InsertPtr (hdpa1, 0, ptr); 314*c2c66affSColin Finck pWork2--; 315*c2c66affSColin Finck } 316*c2c66affSColin Finck } 317*c2c66affSColin Finck break; 318*c2c66affSColin Finck } 319*c2c66affSColin Finck nResult = (pfnCompare)(*pWork1, *pWork2, lParam); 320*c2c66affSColin Finck TRACE("compare result=%d, dpa1.cnt=%d, dpa2.cnt=%d\n", 321*c2c66affSColin Finck nResult, nIndex, nCount); 322*c2c66affSColin Finck 323*c2c66affSColin Finck if (nResult == 0) 324*c2c66affSColin Finck { 325*c2c66affSColin Finck PVOID ptr; 326*c2c66affSColin Finck 327*c2c66affSColin Finck ptr = (pfnMerge)(DPAMM_MERGE, *pWork1, *pWork2, lParam); 328*c2c66affSColin Finck if (!ptr) 329*c2c66affSColin Finck return FALSE; 330*c2c66affSColin Finck 331*c2c66affSColin Finck nCount--; 332*c2c66affSColin Finck *pWork1 = ptr; 333*c2c66affSColin Finck nIndex--; 334*c2c66affSColin Finck } 335*c2c66affSColin Finck else if (nResult > 0) 336*c2c66affSColin Finck { 337*c2c66affSColin Finck /* item in DPA 1 missing from DPA 2 */ 338*c2c66affSColin Finck if (dwFlags & DPAM_INTERSECT) 339*c2c66affSColin Finck { 340*c2c66affSColin Finck /* Now delete the extra item in DPA1 */ 341*c2c66affSColin Finck PVOID ptr; 342*c2c66affSColin Finck 343*c2c66affSColin Finck ptr = DPA_DeletePtr (hdpa1, nIndex); 344*c2c66affSColin Finck 345*c2c66affSColin Finck (pfnMerge)(DPAMM_DELETE, ptr, NULL, lParam); 346*c2c66affSColin Finck } 347*c2c66affSColin Finck nIndex--; 348*c2c66affSColin Finck } 349*c2c66affSColin Finck else 350*c2c66affSColin Finck { 351*c2c66affSColin Finck /* new item in DPA 2 */ 352*c2c66affSColin Finck if (dwFlags & DPAM_UNION) 353*c2c66affSColin Finck { 354*c2c66affSColin Finck /* Now insert the new item in DPA 1 */ 355*c2c66affSColin Finck PVOID ptr; 356*c2c66affSColin Finck 357*c2c66affSColin Finck ptr = (pfnMerge)(DPAMM_INSERT, *pWork2, NULL, lParam); 358*c2c66affSColin Finck if (!ptr) 359*c2c66affSColin Finck return FALSE; 360*c2c66affSColin Finck DPA_InsertPtr (hdpa1, nIndex+1, ptr); 361*c2c66affSColin Finck } 362*c2c66affSColin Finck nCount--; 363*c2c66affSColin Finck } 364*c2c66affSColin Finck 365*c2c66affSColin Finck } 366*c2c66affSColin Finck while (nCount >= 0); 367*c2c66affSColin Finck 368*c2c66affSColin Finck return TRUE; 369*c2c66affSColin Finck } 370*c2c66affSColin Finck 371*c2c66affSColin Finck 372*c2c66affSColin Finck /************************************************************************** 373*c2c66affSColin Finck * DPA_Destroy [COMCTL32.329] 374*c2c66affSColin Finck * 375*c2c66affSColin Finck * Destroys a dynamic pointer array 376*c2c66affSColin Finck * 377*c2c66affSColin Finck * PARAMS 378*c2c66affSColin Finck * hdpa [I] handle (pointer) to the pointer array 379*c2c66affSColin Finck * 380*c2c66affSColin Finck * RETURNS 381*c2c66affSColin Finck * Success: TRUE 382*c2c66affSColin Finck * Failure: FALSE 383*c2c66affSColin Finck */ 384*c2c66affSColin Finck BOOL WINAPI DPA_Destroy (HDPA hdpa) 385*c2c66affSColin Finck { 386*c2c66affSColin Finck TRACE("(%p)\n", hdpa); 387*c2c66affSColin Finck 388*c2c66affSColin Finck if (!hdpa) 389*c2c66affSColin Finck return FALSE; 390*c2c66affSColin Finck 391*c2c66affSColin Finck if (hdpa->ptrs && (!HeapFree (hdpa->hHeap, 0, hdpa->ptrs))) 392*c2c66affSColin Finck return FALSE; 393*c2c66affSColin Finck 394*c2c66affSColin Finck return HeapFree (hdpa->hHeap, 0, hdpa); 395*c2c66affSColin Finck } 396*c2c66affSColin Finck 397*c2c66affSColin Finck 398*c2c66affSColin Finck /************************************************************************** 399*c2c66affSColin Finck * DPA_Grow [COMCTL32.330] 400*c2c66affSColin Finck * 401*c2c66affSColin Finck * Sets the growth amount. 402*c2c66affSColin Finck * 403*c2c66affSColin Finck * PARAMS 404*c2c66affSColin Finck * hdpa [I] handle (pointer) to the existing (source) pointer array 405*c2c66affSColin Finck * nGrow [I] number of items by which the array grows when it's too small 406*c2c66affSColin Finck * 407*c2c66affSColin Finck * RETURNS 408*c2c66affSColin Finck * Success: TRUE 409*c2c66affSColin Finck * Failure: FALSE 410*c2c66affSColin Finck */ 411*c2c66affSColin Finck BOOL WINAPI DPA_Grow (HDPA hdpa, INT nGrow) 412*c2c66affSColin Finck { 413*c2c66affSColin Finck INT items; 414*c2c66affSColin Finck TRACE("(%p %d)\n", hdpa, nGrow); 415*c2c66affSColin Finck 416*c2c66affSColin Finck if (!hdpa) 417*c2c66affSColin Finck return FALSE; 418*c2c66affSColin Finck 419*c2c66affSColin Finck nGrow = max( 8, nGrow ); 420*c2c66affSColin Finck items = nGrow * (((hdpa->nMaxCount - 1) / nGrow) + 1); 421*c2c66affSColin Finck if (items > hdpa->nMaxCount) 422*c2c66affSColin Finck { 423*c2c66affSColin Finck void *ptr; 424*c2c66affSColin Finck 425*c2c66affSColin Finck if (hdpa->ptrs) 426*c2c66affSColin Finck ptr = HeapReAlloc( hdpa->hHeap, HEAP_ZERO_MEMORY, hdpa->ptrs, items * sizeof(LPVOID) ); 427*c2c66affSColin Finck else 428*c2c66affSColin Finck ptr = HeapAlloc( hdpa->hHeap, HEAP_ZERO_MEMORY, items * sizeof(LPVOID) ); 429*c2c66affSColin Finck if (!ptr) return FALSE; 430*c2c66affSColin Finck hdpa->nMaxCount = items; 431*c2c66affSColin Finck hdpa->ptrs = ptr; 432*c2c66affSColin Finck } 433*c2c66affSColin Finck hdpa->nGrow = nGrow; 434*c2c66affSColin Finck 435*c2c66affSColin Finck return TRUE; 436*c2c66affSColin Finck } 437*c2c66affSColin Finck 438*c2c66affSColin Finck 439*c2c66affSColin Finck /************************************************************************** 440*c2c66affSColin Finck * DPA_Clone [COMCTL32.331] 441*c2c66affSColin Finck * 442*c2c66affSColin Finck * Copies a pointer array to another one or creates a copy 443*c2c66affSColin Finck * 444*c2c66affSColin Finck * PARAMS 445*c2c66affSColin Finck * hdpa [I] handle (pointer) to the existing (source) pointer array 446*c2c66affSColin Finck * hdpaNew [O] handle (pointer) to the destination pointer array 447*c2c66affSColin Finck * 448*c2c66affSColin Finck * RETURNS 449*c2c66affSColin Finck * Success: pointer to the destination pointer array. 450*c2c66affSColin Finck * Failure: NULL 451*c2c66affSColin Finck * 452*c2c66affSColin Finck * NOTES 453*c2c66affSColin Finck * - If the 'hdpaNew' is a NULL-Pointer, a copy of the source pointer 454*c2c66affSColin Finck * array will be created and its handle (pointer) is returned. 455*c2c66affSColin Finck * - If 'hdpa' is a NULL-Pointer, the original implementation crashes, 456*c2c66affSColin Finck * this implementation just returns NULL. 457*c2c66affSColin Finck */ 458*c2c66affSColin Finck HDPA WINAPI DPA_Clone (const HDPA hdpa, HDPA hdpaNew) 459*c2c66affSColin Finck { 460*c2c66affSColin Finck INT nNewItems, nSize; 461*c2c66affSColin Finck HDPA hdpaTemp; 462*c2c66affSColin Finck 463*c2c66affSColin Finck if (!hdpa) 464*c2c66affSColin Finck return NULL; 465*c2c66affSColin Finck 466*c2c66affSColin Finck TRACE("(%p %p)\n", hdpa, hdpaNew); 467*c2c66affSColin Finck 468*c2c66affSColin Finck if (!hdpaNew) { 469*c2c66affSColin Finck /* create a new DPA */ 470*c2c66affSColin Finck hdpaTemp = HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY, 471*c2c66affSColin Finck sizeof(*hdpaTemp)); 472*c2c66affSColin Finck hdpaTemp->hHeap = hdpa->hHeap; 473*c2c66affSColin Finck hdpaTemp->nGrow = hdpa->nGrow; 474*c2c66affSColin Finck } 475*c2c66affSColin Finck else 476*c2c66affSColin Finck hdpaTemp = hdpaNew; 477*c2c66affSColin Finck 478*c2c66affSColin Finck if (hdpaTemp->ptrs) { 479*c2c66affSColin Finck /* remove old pointer array */ 480*c2c66affSColin Finck HeapFree (hdpaTemp->hHeap, 0, hdpaTemp->ptrs); 481*c2c66affSColin Finck hdpaTemp->ptrs = NULL; 482*c2c66affSColin Finck hdpaTemp->nItemCount = 0; 483*c2c66affSColin Finck hdpaTemp->nMaxCount = 0; 484*c2c66affSColin Finck } 485*c2c66affSColin Finck 486*c2c66affSColin Finck /* create a new pointer array */ 487*c2c66affSColin Finck nNewItems = hdpaTemp->nGrow * 488*c2c66affSColin Finck (((hdpa->nItemCount - 1) / hdpaTemp->nGrow) + 1); 489*c2c66affSColin Finck nSize = nNewItems * sizeof(LPVOID); 490*c2c66affSColin Finck hdpaTemp->ptrs = HeapAlloc (hdpaTemp->hHeap, HEAP_ZERO_MEMORY, nSize); 491*c2c66affSColin Finck hdpaTemp->nMaxCount = nNewItems; 492*c2c66affSColin Finck 493*c2c66affSColin Finck /* clone the pointer array */ 494*c2c66affSColin Finck hdpaTemp->nItemCount = hdpa->nItemCount; 495*c2c66affSColin Finck memmove (hdpaTemp->ptrs, hdpa->ptrs, 496*c2c66affSColin Finck hdpaTemp->nItemCount * sizeof(LPVOID)); 497*c2c66affSColin Finck 498*c2c66affSColin Finck return hdpaTemp; 499*c2c66affSColin Finck } 500*c2c66affSColin Finck 501*c2c66affSColin Finck 502*c2c66affSColin Finck /************************************************************************** 503*c2c66affSColin Finck * DPA_GetPtr [COMCTL32.332] 504*c2c66affSColin Finck * 505*c2c66affSColin Finck * Retrieves a pointer from a dynamic pointer array 506*c2c66affSColin Finck * 507*c2c66affSColin Finck * PARAMS 508*c2c66affSColin Finck * hdpa [I] handle (pointer) to the pointer array 509*c2c66affSColin Finck * nIndex [I] array index of the desired pointer 510*c2c66affSColin Finck * 511*c2c66affSColin Finck * RETURNS 512*c2c66affSColin Finck * Success: pointer 513*c2c66affSColin Finck * Failure: NULL 514*c2c66affSColin Finck */ 515*c2c66affSColin Finck LPVOID WINAPI DPA_GetPtr (HDPA hdpa, INT nIndex) 516*c2c66affSColin Finck { 517*c2c66affSColin Finck TRACE("(%p %d)\n", hdpa, nIndex); 518*c2c66affSColin Finck 519*c2c66affSColin Finck if (!hdpa) 520*c2c66affSColin Finck return NULL; 521*c2c66affSColin Finck if (!hdpa->ptrs) { 522*c2c66affSColin Finck WARN("no pointer array.\n"); 523*c2c66affSColin Finck return NULL; 524*c2c66affSColin Finck } 525*c2c66affSColin Finck if ((nIndex < 0) || (nIndex >= hdpa->nItemCount)) { 526*c2c66affSColin Finck WARN("not enough pointers in array (%d vs %d).\n",nIndex,hdpa->nItemCount); 527*c2c66affSColin Finck return NULL; 528*c2c66affSColin Finck } 529*c2c66affSColin Finck 530*c2c66affSColin Finck TRACE("-- %p\n", hdpa->ptrs[nIndex]); 531*c2c66affSColin Finck 532*c2c66affSColin Finck return hdpa->ptrs[nIndex]; 533*c2c66affSColin Finck } 534*c2c66affSColin Finck 535*c2c66affSColin Finck 536*c2c66affSColin Finck /************************************************************************** 537*c2c66affSColin Finck * DPA_GetPtrIndex [COMCTL32.333] 538*c2c66affSColin Finck * 539*c2c66affSColin Finck * Retrieves the index of the specified pointer 540*c2c66affSColin Finck * 541*c2c66affSColin Finck * PARAMS 542*c2c66affSColin Finck * hdpa [I] handle (pointer) to the pointer array 543*c2c66affSColin Finck * p [I] pointer 544*c2c66affSColin Finck * 545*c2c66affSColin Finck * RETURNS 546*c2c66affSColin Finck * Success: index of the specified pointer 547*c2c66affSColin Finck * Failure: -1 548*c2c66affSColin Finck */ 549*c2c66affSColin Finck INT WINAPI DPA_GetPtrIndex (HDPA hdpa, LPCVOID p) 550*c2c66affSColin Finck { 551*c2c66affSColin Finck INT i; 552*c2c66affSColin Finck 553*c2c66affSColin Finck if (!hdpa || !hdpa->ptrs) 554*c2c66affSColin Finck return -1; 555*c2c66affSColin Finck 556*c2c66affSColin Finck for (i = 0; i < hdpa->nItemCount; i++) { 557*c2c66affSColin Finck if (hdpa->ptrs[i] == p) 558*c2c66affSColin Finck return i; 559*c2c66affSColin Finck } 560*c2c66affSColin Finck 561*c2c66affSColin Finck return -1; 562*c2c66affSColin Finck } 563*c2c66affSColin Finck 564*c2c66affSColin Finck 565*c2c66affSColin Finck /************************************************************************** 566*c2c66affSColin Finck * DPA_InsertPtr [COMCTL32.334] 567*c2c66affSColin Finck * 568*c2c66affSColin Finck * Inserts a pointer into a dynamic pointer array 569*c2c66affSColin Finck * 570*c2c66affSColin Finck * PARAMS 571*c2c66affSColin Finck * hdpa [I] handle (pointer) to the array 572*c2c66affSColin Finck * i [I] array index 573*c2c66affSColin Finck * p [I] pointer to insert 574*c2c66affSColin Finck * 575*c2c66affSColin Finck * RETURNS 576*c2c66affSColin Finck * Success: index of the inserted pointer 577*c2c66affSColin Finck * Failure: -1 578*c2c66affSColin Finck */ 579*c2c66affSColin Finck INT WINAPI DPA_InsertPtr (HDPA hdpa, INT i, LPVOID p) 580*c2c66affSColin Finck { 581*c2c66affSColin Finck TRACE("(%p %d %p)\n", hdpa, i, p); 582*c2c66affSColin Finck 583*c2c66affSColin Finck if (!hdpa || i < 0) return -1; 584*c2c66affSColin Finck 585*c2c66affSColin Finck /* append item if index is out of bounds */ 586*c2c66affSColin Finck i = min(hdpa->nItemCount, i); 587*c2c66affSColin Finck 588*c2c66affSColin Finck /* create empty spot at the end */ 589*c2c66affSColin Finck if (!DPA_SetPtr(hdpa, hdpa->nItemCount, 0)) return -1; 590*c2c66affSColin Finck 591*c2c66affSColin Finck if (i != hdpa->nItemCount - 1) 592*c2c66affSColin Finck memmove (hdpa->ptrs + i + 1, hdpa->ptrs + i, 593*c2c66affSColin Finck (hdpa->nItemCount - i - 1) * sizeof(LPVOID)); 594*c2c66affSColin Finck 595*c2c66affSColin Finck hdpa->ptrs[i] = p; 596*c2c66affSColin Finck return i; 597*c2c66affSColin Finck } 598*c2c66affSColin Finck 599*c2c66affSColin Finck 600*c2c66affSColin Finck /************************************************************************** 601*c2c66affSColin Finck * DPA_SetPtr [COMCTL32.335] 602*c2c66affSColin Finck * 603*c2c66affSColin Finck * Sets a pointer in the pointer array 604*c2c66affSColin Finck * 605*c2c66affSColin Finck * PARAMS 606*c2c66affSColin Finck * hdpa [I] handle (pointer) to the pointer array 607*c2c66affSColin Finck * i [I] index of the pointer that will be set 608*c2c66affSColin Finck * p [I] pointer to be set 609*c2c66affSColin Finck * 610*c2c66affSColin Finck * RETURNS 611*c2c66affSColin Finck * Success: TRUE 612*c2c66affSColin Finck * Failure: FALSE 613*c2c66affSColin Finck */ 614*c2c66affSColin Finck BOOL WINAPI DPA_SetPtr (HDPA hdpa, INT i, LPVOID p) 615*c2c66affSColin Finck { 616*c2c66affSColin Finck LPVOID *lpTemp; 617*c2c66affSColin Finck 618*c2c66affSColin Finck TRACE("(%p %d %p)\n", hdpa, i, p); 619*c2c66affSColin Finck 620*c2c66affSColin Finck if (!hdpa || i < 0) 621*c2c66affSColin Finck return FALSE; 622*c2c66affSColin Finck 623*c2c66affSColin Finck if (hdpa->nItemCount <= i) { 624*c2c66affSColin Finck /* within the old array */ 625*c2c66affSColin Finck if (hdpa->nMaxCount <= i) { 626*c2c66affSColin Finck /* resize the block of memory */ 627*c2c66affSColin Finck INT nNewItems = 628*c2c66affSColin Finck hdpa->nGrow * ((((i+1) - 1) / hdpa->nGrow) + 1); 629*c2c66affSColin Finck INT nSize = nNewItems * sizeof(LPVOID); 630*c2c66affSColin Finck 631*c2c66affSColin Finck if (hdpa->ptrs) 632*c2c66affSColin Finck lpTemp = HeapReAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY, hdpa->ptrs, nSize); 633*c2c66affSColin Finck else 634*c2c66affSColin Finck lpTemp = HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY, nSize); 635*c2c66affSColin Finck 636*c2c66affSColin Finck if (!lpTemp) 637*c2c66affSColin Finck return FALSE; 638*c2c66affSColin Finck 639*c2c66affSColin Finck hdpa->nMaxCount = nNewItems; 640*c2c66affSColin Finck hdpa->ptrs = lpTemp; 641*c2c66affSColin Finck } 642*c2c66affSColin Finck hdpa->nItemCount = i+1; 643*c2c66affSColin Finck } 644*c2c66affSColin Finck 645*c2c66affSColin Finck /* put the new entry in */ 646*c2c66affSColin Finck hdpa->ptrs[i] = p; 647*c2c66affSColin Finck 648*c2c66affSColin Finck return TRUE; 649*c2c66affSColin Finck } 650*c2c66affSColin Finck 651*c2c66affSColin Finck 652*c2c66affSColin Finck /************************************************************************** 653*c2c66affSColin Finck * DPA_DeletePtr [COMCTL32.336] 654*c2c66affSColin Finck * 655*c2c66affSColin Finck * Removes a pointer from the pointer array. 656*c2c66affSColin Finck * 657*c2c66affSColin Finck * PARAMS 658*c2c66affSColin Finck * hdpa [I] handle (pointer) to the pointer array 659*c2c66affSColin Finck * i [I] index of the pointer that will be deleted 660*c2c66affSColin Finck * 661*c2c66affSColin Finck * RETURNS 662*c2c66affSColin Finck * Success: deleted pointer 663*c2c66affSColin Finck * Failure: NULL 664*c2c66affSColin Finck */ 665*c2c66affSColin Finck LPVOID WINAPI DPA_DeletePtr (HDPA hdpa, INT i) 666*c2c66affSColin Finck { 667*c2c66affSColin Finck LPVOID *lpDest, *lpSrc, lpTemp = NULL; 668*c2c66affSColin Finck INT nSize; 669*c2c66affSColin Finck 670*c2c66affSColin Finck TRACE("(%p %d)\n", hdpa, i); 671*c2c66affSColin Finck 672*c2c66affSColin Finck if ((!hdpa) || i < 0 || i >= hdpa->nItemCount) 673*c2c66affSColin Finck return NULL; 674*c2c66affSColin Finck 675*c2c66affSColin Finck lpTemp = hdpa->ptrs[i]; 676*c2c66affSColin Finck 677*c2c66affSColin Finck /* do we need to move ?*/ 678*c2c66affSColin Finck if (i < hdpa->nItemCount - 1) { 679*c2c66affSColin Finck lpDest = hdpa->ptrs + i; 680*c2c66affSColin Finck lpSrc = lpDest + 1; 681*c2c66affSColin Finck nSize = (hdpa->nItemCount - i - 1) * sizeof(LPVOID); 682*c2c66affSColin Finck TRACE("-- move dest=%p src=%p size=%x\n", 683*c2c66affSColin Finck lpDest, lpSrc, nSize); 684*c2c66affSColin Finck memmove (lpDest, lpSrc, nSize); 685*c2c66affSColin Finck } 686*c2c66affSColin Finck 687*c2c66affSColin Finck hdpa->nItemCount --; 688*c2c66affSColin Finck 689*c2c66affSColin Finck /* free memory ?*/ 690*c2c66affSColin Finck if ((hdpa->nMaxCount - hdpa->nItemCount) >= hdpa->nGrow) { 691*c2c66affSColin Finck INT nNewItems = max(hdpa->nGrow * 2, hdpa->nItemCount); 692*c2c66affSColin Finck nSize = nNewItems * sizeof(LPVOID); 693*c2c66affSColin Finck lpDest = HeapReAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY, 694*c2c66affSColin Finck hdpa->ptrs, nSize); 695*c2c66affSColin Finck if (!lpDest) 696*c2c66affSColin Finck return NULL; 697*c2c66affSColin Finck 698*c2c66affSColin Finck hdpa->nMaxCount = nNewItems; 699*c2c66affSColin Finck hdpa->ptrs = lpDest; 700*c2c66affSColin Finck } 701*c2c66affSColin Finck 702*c2c66affSColin Finck return lpTemp; 703*c2c66affSColin Finck } 704*c2c66affSColin Finck 705*c2c66affSColin Finck 706*c2c66affSColin Finck /************************************************************************** 707*c2c66affSColin Finck * DPA_DeleteAllPtrs [COMCTL32.337] 708*c2c66affSColin Finck * 709*c2c66affSColin Finck * Removes all pointers and reinitializes the array. 710*c2c66affSColin Finck * 711*c2c66affSColin Finck * PARAMS 712*c2c66affSColin Finck * hdpa [I] handle (pointer) to the pointer array 713*c2c66affSColin Finck * 714*c2c66affSColin Finck * RETURNS 715*c2c66affSColin Finck * Success: TRUE 716*c2c66affSColin Finck * Failure: FALSE 717*c2c66affSColin Finck */ 718*c2c66affSColin Finck BOOL WINAPI DPA_DeleteAllPtrs (HDPA hdpa) 719*c2c66affSColin Finck { 720*c2c66affSColin Finck TRACE("(%p)\n", hdpa); 721*c2c66affSColin Finck 722*c2c66affSColin Finck if (!hdpa) 723*c2c66affSColin Finck return FALSE; 724*c2c66affSColin Finck 725*c2c66affSColin Finck if (hdpa->ptrs && (!HeapFree (hdpa->hHeap, 0, hdpa->ptrs))) 726*c2c66affSColin Finck return FALSE; 727*c2c66affSColin Finck 728*c2c66affSColin Finck hdpa->nItemCount = 0; 729*c2c66affSColin Finck hdpa->nMaxCount = hdpa->nGrow * 2; 730*c2c66affSColin Finck hdpa->ptrs = HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY, 731*c2c66affSColin Finck hdpa->nMaxCount * sizeof(LPVOID)); 732*c2c66affSColin Finck 733*c2c66affSColin Finck return TRUE; 734*c2c66affSColin Finck } 735*c2c66affSColin Finck 736*c2c66affSColin Finck 737*c2c66affSColin Finck /************************************************************************** 738*c2c66affSColin Finck * DPA_QuickSort [Internal] 739*c2c66affSColin Finck * 740*c2c66affSColin Finck * Ordinary quicksort (used by DPA_Sort). 741*c2c66affSColin Finck * 742*c2c66affSColin Finck * PARAMS 743*c2c66affSColin Finck * lpPtrs [I] pointer to the pointer array 744*c2c66affSColin Finck * l [I] index of the "left border" of the partition 745*c2c66affSColin Finck * r [I] index of the "right border" of the partition 746*c2c66affSColin Finck * pfnCompare [I] pointer to the compare function 747*c2c66affSColin Finck * lParam [I] user defined value (3rd parameter in compare function) 748*c2c66affSColin Finck * 749*c2c66affSColin Finck * RETURNS 750*c2c66affSColin Finck * NONE 751*c2c66affSColin Finck */ 752*c2c66affSColin Finck static VOID DPA_QuickSort (LPVOID *lpPtrs, INT l, INT r, 753*c2c66affSColin Finck PFNDPACOMPARE pfnCompare, LPARAM lParam) 754*c2c66affSColin Finck { 755*c2c66affSColin Finck INT m; 756*c2c66affSColin Finck LPVOID t; 757*c2c66affSColin Finck 758*c2c66affSColin Finck TRACE("l=%i r=%i\n", l, r); 759*c2c66affSColin Finck 760*c2c66affSColin Finck if (l==r) /* one element is always sorted */ 761*c2c66affSColin Finck return; 762*c2c66affSColin Finck if (r<l) /* oops, got it in the wrong order */ 763*c2c66affSColin Finck { 764*c2c66affSColin Finck DPA_QuickSort(lpPtrs, r, l, pfnCompare, lParam); 765*c2c66affSColin Finck return; 766*c2c66affSColin Finck } 767*c2c66affSColin Finck m = (l+r)/2; /* divide by two */ 768*c2c66affSColin Finck DPA_QuickSort(lpPtrs, l, m, pfnCompare, lParam); 769*c2c66affSColin Finck DPA_QuickSort(lpPtrs, m+1, r, pfnCompare, lParam); 770*c2c66affSColin Finck 771*c2c66affSColin Finck /* join the two sides */ 772*c2c66affSColin Finck while( (l<=m) && (m<r) ) 773*c2c66affSColin Finck { 774*c2c66affSColin Finck if(pfnCompare(lpPtrs[l],lpPtrs[m+1],lParam)>0) 775*c2c66affSColin Finck { 776*c2c66affSColin Finck t = lpPtrs[m+1]; 777*c2c66affSColin Finck memmove(&lpPtrs[l+1],&lpPtrs[l],(m-l+1)*sizeof(lpPtrs[l])); 778*c2c66affSColin Finck lpPtrs[l] = t; 779*c2c66affSColin Finck 780*c2c66affSColin Finck m++; 781*c2c66affSColin Finck } 782*c2c66affSColin Finck l++; 783*c2c66affSColin Finck } 784*c2c66affSColin Finck } 785*c2c66affSColin Finck 786*c2c66affSColin Finck 787*c2c66affSColin Finck /************************************************************************** 788*c2c66affSColin Finck * DPA_Sort [COMCTL32.338] 789*c2c66affSColin Finck * 790*c2c66affSColin Finck * Sorts a pointer array using a user defined compare function 791*c2c66affSColin Finck * 792*c2c66affSColin Finck * PARAMS 793*c2c66affSColin Finck * hdpa [I] handle (pointer) to the pointer array 794*c2c66affSColin Finck * pfnCompare [I] pointer to the compare function 795*c2c66affSColin Finck * lParam [I] user defined value (3rd parameter of compare function) 796*c2c66affSColin Finck * 797*c2c66affSColin Finck * RETURNS 798*c2c66affSColin Finck * Success: TRUE 799*c2c66affSColin Finck * Failure: FALSE 800*c2c66affSColin Finck */ 801*c2c66affSColin Finck BOOL WINAPI DPA_Sort (HDPA hdpa, PFNDPACOMPARE pfnCompare, LPARAM lParam) 802*c2c66affSColin Finck { 803*c2c66affSColin Finck if (!hdpa || !pfnCompare) 804*c2c66affSColin Finck return FALSE; 805*c2c66affSColin Finck 806*c2c66affSColin Finck TRACE("(%p %p 0x%lx)\n", hdpa, pfnCompare, lParam); 807*c2c66affSColin Finck 808*c2c66affSColin Finck if ((hdpa->nItemCount > 1) && (hdpa->ptrs)) 809*c2c66affSColin Finck DPA_QuickSort (hdpa->ptrs, 0, hdpa->nItemCount - 1, 810*c2c66affSColin Finck pfnCompare, lParam); 811*c2c66affSColin Finck 812*c2c66affSColin Finck return TRUE; 813*c2c66affSColin Finck } 814*c2c66affSColin Finck 815*c2c66affSColin Finck 816*c2c66affSColin Finck /************************************************************************** 817*c2c66affSColin Finck * DPA_Search [COMCTL32.339] 818*c2c66affSColin Finck * 819*c2c66affSColin Finck * Searches a pointer array for a specified pointer 820*c2c66affSColin Finck * 821*c2c66affSColin Finck * PARAMS 822*c2c66affSColin Finck * hdpa [I] handle (pointer) to the pointer array 823*c2c66affSColin Finck * pFind [I] pointer to search for 824*c2c66affSColin Finck * nStart [I] start index 825*c2c66affSColin Finck * pfnCompare [I] pointer to the compare function 826*c2c66affSColin Finck * lParam [I] user defined value (3rd parameter of compare function) 827*c2c66affSColin Finck * uOptions [I] search options 828*c2c66affSColin Finck * 829*c2c66affSColin Finck * RETURNS 830*c2c66affSColin Finck * Success: index of the pointer in the array. 831*c2c66affSColin Finck * Failure: -1 832*c2c66affSColin Finck */ 833*c2c66affSColin Finck INT WINAPI DPA_Search (HDPA hdpa, LPVOID pFind, INT nStart, 834*c2c66affSColin Finck PFNDPACOMPARE pfnCompare, LPARAM lParam, UINT uOptions) 835*c2c66affSColin Finck { 836*c2c66affSColin Finck if (!hdpa || !pfnCompare || !pFind) 837*c2c66affSColin Finck return -1; 838*c2c66affSColin Finck 839*c2c66affSColin Finck TRACE("(%p %p %d %p 0x%08lx 0x%08x)\n", 840*c2c66affSColin Finck hdpa, pFind, nStart, pfnCompare, lParam, uOptions); 841*c2c66affSColin Finck 842*c2c66affSColin Finck if (uOptions & DPAS_SORTED) { 843*c2c66affSColin Finck /* array is sorted --> use binary search */ 844*c2c66affSColin Finck INT l, r, x, n; 845*c2c66affSColin Finck LPVOID *lpPtr; 846*c2c66affSColin Finck 847*c2c66affSColin Finck /* for binary search ignore start index */ 848*c2c66affSColin Finck l = 0; 849*c2c66affSColin Finck r = hdpa->nItemCount - 1; 850*c2c66affSColin Finck lpPtr = hdpa->ptrs; 851*c2c66affSColin Finck while (r >= l) { 852*c2c66affSColin Finck x = (l + r) / 2; 853*c2c66affSColin Finck n = (pfnCompare)(pFind, lpPtr[x], lParam); 854*c2c66affSColin Finck if (n == 0) 855*c2c66affSColin Finck return x; 856*c2c66affSColin Finck else if (n < 0) 857*c2c66affSColin Finck r = x - 1; 858*c2c66affSColin Finck else /* (n > 0) */ 859*c2c66affSColin Finck l = x + 1; 860*c2c66affSColin Finck } 861*c2c66affSColin Finck if (uOptions & (DPAS_INSERTBEFORE|DPAS_INSERTAFTER)) return l; 862*c2c66affSColin Finck } 863*c2c66affSColin Finck else { 864*c2c66affSColin Finck /* array is not sorted --> use linear search */ 865*c2c66affSColin Finck LPVOID *lpPtr; 866*c2c66affSColin Finck INT nIndex; 867*c2c66affSColin Finck 868*c2c66affSColin Finck nIndex = (nStart == -1)? 0 : nStart; 869*c2c66affSColin Finck lpPtr = hdpa->ptrs; 870*c2c66affSColin Finck for (; nIndex < hdpa->nItemCount; nIndex++) { 871*c2c66affSColin Finck if ((pfnCompare)(pFind, lpPtr[nIndex], lParam) == 0) 872*c2c66affSColin Finck return nIndex; 873*c2c66affSColin Finck } 874*c2c66affSColin Finck } 875*c2c66affSColin Finck 876*c2c66affSColin Finck return -1; 877*c2c66affSColin Finck } 878*c2c66affSColin Finck 879*c2c66affSColin Finck 880*c2c66affSColin Finck /************************************************************************** 881*c2c66affSColin Finck * DPA_CreateEx [COMCTL32.340] 882*c2c66affSColin Finck * 883*c2c66affSColin Finck * Creates a dynamic pointer array using the specified size and heap. 884*c2c66affSColin Finck * 885*c2c66affSColin Finck * PARAMS 886*c2c66affSColin Finck * nGrow [I] number of items by which the array grows when it is filled 887*c2c66affSColin Finck * hHeap [I] handle to the heap where the array is stored 888*c2c66affSColin Finck * 889*c2c66affSColin Finck * RETURNS 890*c2c66affSColin Finck * Success: handle (pointer) to the pointer array. 891*c2c66affSColin Finck * Failure: NULL 892*c2c66affSColin Finck * 893*c2c66affSColin Finck * NOTES 894*c2c66affSColin Finck * The DPA_ functions can be used to create and manipulate arrays of 895*c2c66affSColin Finck * pointers. 896*c2c66affSColin Finck */ 897*c2c66affSColin Finck HDPA WINAPI DPA_CreateEx (INT nGrow, HANDLE hHeap) 898*c2c66affSColin Finck { 899*c2c66affSColin Finck HDPA hdpa; 900*c2c66affSColin Finck 901*c2c66affSColin Finck TRACE("(%d %p)\n", nGrow, hHeap); 902*c2c66affSColin Finck 903*c2c66affSColin Finck if (hHeap) 904*c2c66affSColin Finck hdpa = HeapAlloc (hHeap, HEAP_ZERO_MEMORY, sizeof(*hdpa)); 905*c2c66affSColin Finck else 906*c2c66affSColin Finck hdpa = Alloc (sizeof(*hdpa)); 907*c2c66affSColin Finck 908*c2c66affSColin Finck if (hdpa) { 909*c2c66affSColin Finck hdpa->nGrow = max(8, nGrow); 910*c2c66affSColin Finck hdpa->hHeap = hHeap ? hHeap : GetProcessHeap(); 911*c2c66affSColin Finck hdpa->nMaxCount = hdpa->nGrow * 2; 912*c2c66affSColin Finck hdpa->ptrs = HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY, 913*c2c66affSColin Finck hdpa->nMaxCount * sizeof(LPVOID)); 914*c2c66affSColin Finck } 915*c2c66affSColin Finck 916*c2c66affSColin Finck TRACE("-- %p\n", hdpa); 917*c2c66affSColin Finck 918*c2c66affSColin Finck return hdpa; 919*c2c66affSColin Finck } 920*c2c66affSColin Finck 921*c2c66affSColin Finck 922*c2c66affSColin Finck /************************************************************************** 923*c2c66affSColin Finck * DPA_Create [COMCTL32.328] 924*c2c66affSColin Finck * 925*c2c66affSColin Finck * Creates a dynamic pointer array. 926*c2c66affSColin Finck * 927*c2c66affSColin Finck * PARAMS 928*c2c66affSColin Finck * nGrow [I] number of items by which the array grows when it is filled 929*c2c66affSColin Finck * 930*c2c66affSColin Finck * RETURNS 931*c2c66affSColin Finck * Success: handle (pointer) to the pointer array. 932*c2c66affSColin Finck * Failure: NULL 933*c2c66affSColin Finck * 934*c2c66affSColin Finck * NOTES 935*c2c66affSColin Finck * The DPA_ functions can be used to create and manipulate arrays of 936*c2c66affSColin Finck * pointers. 937*c2c66affSColin Finck */ 938*c2c66affSColin Finck HDPA WINAPI DPA_Create (INT nGrow) 939*c2c66affSColin Finck { 940*c2c66affSColin Finck return DPA_CreateEx( nGrow, 0 ); 941*c2c66affSColin Finck } 942*c2c66affSColin Finck 943*c2c66affSColin Finck 944*c2c66affSColin Finck /************************************************************************** 945*c2c66affSColin Finck * DPA_EnumCallback [COMCTL32.385] 946*c2c66affSColin Finck * 947*c2c66affSColin Finck * Enumerates all items in a dynamic pointer array. 948*c2c66affSColin Finck * 949*c2c66affSColin Finck * PARAMS 950*c2c66affSColin Finck * hdpa [I] handle to the dynamic pointer array 951*c2c66affSColin Finck * enumProc [I] 952*c2c66affSColin Finck * lParam [I] 953*c2c66affSColin Finck * 954*c2c66affSColin Finck * RETURNS 955*c2c66affSColin Finck * none 956*c2c66affSColin Finck */ 957*c2c66affSColin Finck VOID WINAPI DPA_EnumCallback (HDPA hdpa, PFNDPAENUMCALLBACK enumProc, 958*c2c66affSColin Finck LPVOID lParam) 959*c2c66affSColin Finck { 960*c2c66affSColin Finck INT i; 961*c2c66affSColin Finck 962*c2c66affSColin Finck TRACE("(%p %p %p)\n", hdpa, enumProc, lParam); 963*c2c66affSColin Finck 964*c2c66affSColin Finck if (!hdpa) 965*c2c66affSColin Finck return; 966*c2c66affSColin Finck if (hdpa->nItemCount <= 0) 967*c2c66affSColin Finck return; 968*c2c66affSColin Finck 969*c2c66affSColin Finck for (i = 0; i < hdpa->nItemCount; i++) { 970*c2c66affSColin Finck if ((enumProc)(hdpa->ptrs[i], lParam) == 0) 971*c2c66affSColin Finck return; 972*c2c66affSColin Finck } 973*c2c66affSColin Finck 974*c2c66affSColin Finck return; 975*c2c66affSColin Finck } 976*c2c66affSColin Finck 977*c2c66affSColin Finck 978*c2c66affSColin Finck /************************************************************************** 979*c2c66affSColin Finck * DPA_DestroyCallback [COMCTL32.386] 980*c2c66affSColin Finck * 981*c2c66affSColin Finck * Enumerates all items in a dynamic pointer array and destroys it. 982*c2c66affSColin Finck * 983*c2c66affSColin Finck * PARAMS 984*c2c66affSColin Finck * hdpa [I] handle to the dynamic pointer array 985*c2c66affSColin Finck * enumProc [I] 986*c2c66affSColin Finck * lParam [I] 987*c2c66affSColin Finck * 988*c2c66affSColin Finck * RETURNS 989*c2c66affSColin Finck * none 990*c2c66affSColin Finck */ 991*c2c66affSColin Finck void WINAPI DPA_DestroyCallback (HDPA hdpa, PFNDPAENUMCALLBACK enumProc, 992*c2c66affSColin Finck LPVOID lParam) 993*c2c66affSColin Finck { 994*c2c66affSColin Finck TRACE("(%p %p %p)\n", hdpa, enumProc, lParam); 995*c2c66affSColin Finck 996*c2c66affSColin Finck DPA_EnumCallback (hdpa, enumProc, lParam); 997*c2c66affSColin Finck DPA_Destroy (hdpa); 998*c2c66affSColin Finck } 999*c2c66affSColin Finck 1000*c2c66affSColin Finck /************************************************************************** 1001*c2c66affSColin Finck * DPA_GetSize [COMCTL32.@] 1002*c2c66affSColin Finck * 1003*c2c66affSColin Finck * Returns all array allocated memory size 1004*c2c66affSColin Finck * 1005*c2c66affSColin Finck * PARAMS 1006*c2c66affSColin Finck * hdpa [I] handle to the dynamic pointer array 1007*c2c66affSColin Finck * 1008*c2c66affSColin Finck * RETURNS 1009*c2c66affSColin Finck * Size in bytes 1010*c2c66affSColin Finck */ 1011*c2c66affSColin Finck ULONGLONG WINAPI DPA_GetSize(HDPA hdpa) 1012*c2c66affSColin Finck { 1013*c2c66affSColin Finck TRACE("(%p)\n", hdpa); 1014*c2c66affSColin Finck 1015*c2c66affSColin Finck if (!hdpa) return 0; 1016*c2c66affSColin Finck 1017*c2c66affSColin Finck return sizeof(DPA) + hdpa->nMaxCount*sizeof(PVOID); 1018*c2c66affSColin Finck } 1019