Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygendpa.c
Go to the documentation of this file.
00001 /* 00002 * Dynamic pointer array (DPA) implementation 00003 * 00004 * Copyright 1998 Eric Kohl 00005 * 1998 Juergen Schmied <j.schmied@metronet.de> 00006 * 2000 Eric Kohl for CodeWeavers 00007 * 00008 * This library is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU Lesser General Public 00010 * License as published by the Free Software Foundation; either 00011 * version 2.1 of the License, or (at your option) any later version. 00012 * 00013 * This library is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License along with this library; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00021 * 00022 * NOTES 00023 * These functions were involuntarily documented by Microsoft in 2002 as 00024 * the outcome of an anti-trust suit brought by various U.S. governments. 00025 * As a result the specifications on MSDN are inaccurate, incomplete 00026 * and misleading. A much more complete (unofficial) documentation is 00027 * available at: 00028 * 00029 * http://members.ozemail.com.au/~geoffch/samples/win32/shell/comctl32 00030 */ 00031 00032 #define COBJMACROS 00033 00034 #include <stdarg.h> 00035 #include <limits.h> 00036 00037 #include "windef.h" 00038 #include "winbase.h" 00039 #include "winuser.h" 00040 #include "commctrl.h" 00041 #include "objbase.h" 00042 00043 #include "comctl32.h" 00044 #include "wine/debug.h" 00045 00046 WINE_DEFAULT_DEBUG_CHANNEL(dpa); 00047 00048 typedef struct _DPA 00049 { 00050 INT nItemCount; 00051 LPVOID *ptrs; 00052 HANDLE hHeap; 00053 INT nGrow; 00054 INT nMaxCount; 00055 } DPA; 00056 00057 typedef struct _STREAMDATA 00058 { 00059 DWORD dwSize; 00060 DWORD dwData2; 00061 DWORD dwItems; 00062 } STREAMDATA, *PSTREAMDATA; 00063 00064 /************************************************************************** 00065 * DPA_LoadStream [COMCTL32.9] 00066 * 00067 * Loads a dynamic pointer array from a stream 00068 * 00069 * PARAMS 00070 * phDpa [O] pointer to a handle to a dynamic pointer array 00071 * loadProc [I] pointer to a callback function 00072 * pStream [I] pointer to a stream 00073 * pData [I] pointer to callback data 00074 * 00075 * RETURNS 00076 * Success: S_OK, S_FALSE - partial success 00077 * Failure: HRESULT error code 00078 * 00079 * NOTES 00080 * No more information available yet! 00081 */ 00082 HRESULT WINAPI DPA_LoadStream (HDPA *phDpa, PFNDPASTREAM loadProc, 00083 IStream *pStream, LPVOID pData) 00084 { 00085 HRESULT errCode; 00086 LARGE_INTEGER position; 00087 ULARGE_INTEGER initial_pos; 00088 STREAMDATA streamData; 00089 DPASTREAMINFO streamInfo; 00090 ULONG ulRead; 00091 HDPA hDpa; 00092 PVOID *ptr; 00093 00094 TRACE ("phDpa=%p loadProc=%p pStream=%p pData=%p\n", 00095 phDpa, loadProc, pStream, pData); 00096 00097 if (!phDpa || !loadProc || !pStream) 00098 return E_INVALIDARG; 00099 00100 *phDpa = NULL; 00101 00102 position.QuadPart = 0; 00103 00104 errCode = IStream_Seek (pStream, position, STREAM_SEEK_CUR, &initial_pos); 00105 if (errCode != S_OK) 00106 return errCode; 00107 00108 memset(&streamData, 0, sizeof(STREAMDATA)); 00109 errCode = IStream_Read (pStream, &streamData, sizeof(STREAMDATA), &ulRead); 00110 if (errCode != S_OK) 00111 return errCode; 00112 00113 TRACE ("dwSize=%u dwData2=%u dwItems=%u\n", 00114 streamData.dwSize, streamData.dwData2, streamData.dwItems); 00115 00116 if (ulRead < sizeof(STREAMDATA) || 00117 streamData.dwSize < sizeof(STREAMDATA) || streamData.dwData2 != 1) { 00118 /* back to initial position */ 00119 position.QuadPart = initial_pos.QuadPart; 00120 IStream_Seek (pStream, position, STREAM_SEEK_SET, NULL); 00121 return E_FAIL; 00122 } 00123 00124 if (streamData.dwItems > (UINT_MAX / 2 / sizeof(VOID*))) /* 536870911 */ 00125 return E_OUTOFMEMORY; 00126 00127 /* create the dpa */ 00128 hDpa = DPA_Create (streamData.dwItems); 00129 if (!hDpa) 00130 return E_OUTOFMEMORY; 00131 00132 if (!DPA_Grow (hDpa, streamData.dwItems)) 00133 return E_OUTOFMEMORY; 00134 00135 /* load data from the stream into the dpa */ 00136 ptr = hDpa->ptrs; 00137 for (streamInfo.iPos = 0; streamInfo.iPos < streamData.dwItems; streamInfo.iPos++) { 00138 errCode = (loadProc)(&streamInfo, pStream, pData); 00139 if (errCode != S_OK) { 00140 errCode = S_FALSE; 00141 break; 00142 } 00143 00144 *ptr = streamInfo.pvItem; 00145 ptr++; 00146 } 00147 00148 /* set the number of items */ 00149 hDpa->nItemCount = streamInfo.iPos; 00150 00151 /* store the handle to the dpa */ 00152 *phDpa = hDpa; 00153 TRACE ("new hDpa=%p, errorcode=%x\n", hDpa, errCode); 00154 00155 return errCode; 00156 } 00157 00158 00159 /************************************************************************** 00160 * DPA_SaveStream [COMCTL32.10] 00161 * 00162 * Saves a dynamic pointer array to a stream 00163 * 00164 * PARAMS 00165 * hDpa [I] handle to a dynamic pointer array 00166 * saveProc [I] pointer to a callback function 00167 * pStream [I] pointer to a stream 00168 * pData [I] pointer to callback data 00169 * 00170 * RETURNS 00171 * Success: S_OK, S_FALSE - partial success 00172 * Failure: HRESULT error code 00173 * 00174 * NOTES 00175 * No more information available yet! 00176 */ 00177 HRESULT WINAPI DPA_SaveStream (const HDPA hDpa, PFNDPASTREAM saveProc, 00178 IStream *pStream, LPVOID pData) 00179 { 00180 LARGE_INTEGER position; 00181 ULARGE_INTEGER initial_pos, curr_pos; 00182 STREAMDATA streamData; 00183 DPASTREAMINFO streamInfo; 00184 HRESULT hr; 00185 PVOID *ptr; 00186 00187 TRACE ("hDpa=%p saveProc=%p pStream=%p pData=%p\n", 00188 hDpa, saveProc, pStream, pData); 00189 00190 if (!hDpa || !saveProc || !pStream) return E_INVALIDARG; 00191 00192 /* save initial position to write header after completion */ 00193 position.QuadPart = 0; 00194 hr = IStream_Seek (pStream, position, STREAM_SEEK_CUR, &initial_pos); 00195 if (hr != S_OK) 00196 return hr; 00197 00198 /* write empty header */ 00199 streamData.dwSize = sizeof(streamData); 00200 streamData.dwData2 = 1; 00201 streamData.dwItems = 0; 00202 00203 hr = IStream_Write (pStream, &streamData, sizeof(streamData), NULL); 00204 if (hr != S_OK) { 00205 position.QuadPart = initial_pos.QuadPart; 00206 IStream_Seek (pStream, position, STREAM_SEEK_SET, NULL); 00207 return hr; 00208 } 00209 00210 /* no items - we're done */ 00211 if (hDpa->nItemCount == 0) return S_OK; 00212 00213 ptr = hDpa->ptrs; 00214 for (streamInfo.iPos = 0; streamInfo.iPos < hDpa->nItemCount; streamInfo.iPos++) { 00215 streamInfo.pvItem = *ptr; 00216 hr = (saveProc)(&streamInfo, pStream, pData); 00217 if (hr != S_OK) { 00218 hr = S_FALSE; 00219 break; 00220 } 00221 ptr++; 00222 } 00223 00224 /* write updated header */ 00225 position.QuadPart = 0; 00226 IStream_Seek (pStream, position, STREAM_SEEK_CUR, &curr_pos); 00227 00228 streamData.dwSize = curr_pos.QuadPart - initial_pos.QuadPart; 00229 streamData.dwData2 = 1; 00230 streamData.dwItems = streamInfo.iPos; 00231 00232 position.QuadPart = initial_pos.QuadPart; 00233 IStream_Seek (pStream, position, STREAM_SEEK_SET, NULL); 00234 IStream_Write (pStream, &streamData, sizeof(streamData), NULL); 00235 00236 position.QuadPart = curr_pos.QuadPart; 00237 IStream_Seek (pStream, position, STREAM_SEEK_SET, NULL); 00238 00239 return hr; 00240 } 00241 00242 00243 /************************************************************************** 00244 * DPA_Merge [COMCTL32.11] 00245 * 00246 * Merge two dynamic pointers arrays. 00247 * 00248 * PARAMS 00249 * hdpa1 [I] handle to a dynamic pointer array 00250 * hdpa2 [I] handle to a dynamic pointer array 00251 * dwFlags [I] flags 00252 * pfnCompare [I] pointer to sort function 00253 * pfnMerge [I] pointer to merge function 00254 * lParam [I] application specific value 00255 * 00256 * RETURNS 00257 * Success: TRUE 00258 * Failure: FALSE 00259 * 00260 * NOTES 00261 * No more information available yet! 00262 */ 00263 BOOL WINAPI DPA_Merge (HDPA hdpa1, HDPA hdpa2, DWORD dwFlags, 00264 PFNDPACOMPARE pfnCompare, PFNDPAMERGE pfnMerge, 00265 LPARAM lParam) 00266 { 00267 INT nCount; 00268 LPVOID *pWork1, *pWork2; 00269 INT nResult, i; 00270 INT nIndex; 00271 00272 TRACE("%p %p %08x %p %p %08lx)\n", 00273 hdpa1, hdpa2, dwFlags, pfnCompare, pfnMerge, lParam); 00274 00275 if (IsBadWritePtr (hdpa1, sizeof(*hdpa1))) 00276 return FALSE; 00277 00278 if (IsBadWritePtr (hdpa2, sizeof(*hdpa2))) 00279 return FALSE; 00280 00281 if (IsBadCodePtr ((FARPROC)pfnCompare)) 00282 return FALSE; 00283 00284 if (IsBadCodePtr ((FARPROC)pfnMerge)) 00285 return FALSE; 00286 00287 if (!(dwFlags & DPAM_SORTED)) { 00288 TRACE("sorting dpa's!\n"); 00289 if (hdpa1->nItemCount > 0) 00290 DPA_Sort (hdpa1, pfnCompare, lParam); 00291 TRACE ("dpa 1 sorted!\n"); 00292 if (hdpa2->nItemCount > 0) 00293 DPA_Sort (hdpa2, pfnCompare, lParam); 00294 TRACE ("dpa 2 sorted!\n"); 00295 } 00296 00297 if (hdpa2->nItemCount < 1) 00298 return TRUE; 00299 00300 TRACE("hdpa1->nItemCount=%d hdpa2->nItemCount=%d\n", 00301 hdpa1->nItemCount, hdpa2->nItemCount); 00302 00303 00304 /* working but untrusted implementation */ 00305 00306 pWork1 = &(hdpa1->ptrs[hdpa1->nItemCount - 1]); 00307 pWork2 = &(hdpa2->ptrs[hdpa2->nItemCount - 1]); 00308 00309 nIndex = hdpa1->nItemCount - 1; 00310 nCount = hdpa2->nItemCount - 1; 00311 00312 do 00313 { 00314 if (nIndex < 0) { 00315 if ((nCount >= 0) && (dwFlags & DPAM_UNION)) { 00316 /* Now insert the remaining new items into DPA 1 */ 00317 TRACE("%d items to be inserted at start of DPA 1\n", 00318 nCount+1); 00319 for (i=nCount; i>=0; i--) { 00320 PVOID ptr; 00321 00322 ptr = (pfnMerge)(DPAMM_INSERT, *pWork2, NULL, lParam); 00323 if (!ptr) 00324 return FALSE; 00325 DPA_InsertPtr (hdpa1, 0, ptr); 00326 pWork2--; 00327 } 00328 } 00329 break; 00330 } 00331 nResult = (pfnCompare)(*pWork1, *pWork2, lParam); 00332 TRACE("compare result=%d, dpa1.cnt=%d, dpa2.cnt=%d\n", 00333 nResult, nIndex, nCount); 00334 00335 if (nResult == 0) 00336 { 00337 PVOID ptr; 00338 00339 ptr = (pfnMerge)(DPAMM_MERGE, *pWork1, *pWork2, lParam); 00340 if (!ptr) 00341 return FALSE; 00342 00343 nCount--; 00344 pWork2--; 00345 *pWork1 = ptr; 00346 nIndex--; 00347 pWork1--; 00348 } 00349 else if (nResult > 0) 00350 { 00351 /* item in DPA 1 missing from DPA 2 */ 00352 if (dwFlags & DPAM_INTERSECT) 00353 { 00354 /* Now delete the extra item in DPA1 */ 00355 PVOID ptr; 00356 00357 ptr = DPA_DeletePtr (hdpa1, nIndex); 00358 00359 (pfnMerge)(DPAMM_DELETE, ptr, NULL, lParam); 00360 } 00361 nIndex--; 00362 pWork1--; 00363 } 00364 else 00365 { 00366 /* new item in DPA 2 */ 00367 if (dwFlags & DPAM_UNION) 00368 { 00369 /* Now insert the new item in DPA 1 */ 00370 PVOID ptr; 00371 00372 ptr = (pfnMerge)(DPAMM_INSERT, *pWork2, NULL, lParam); 00373 if (!ptr) 00374 return FALSE; 00375 DPA_InsertPtr (hdpa1, nIndex+1, ptr); 00376 } 00377 nCount--; 00378 pWork2--; 00379 } 00380 00381 } 00382 while (nCount >= 0); 00383 00384 return TRUE; 00385 } 00386 00387 00388 /************************************************************************** 00389 * DPA_Destroy [COMCTL32.329] 00390 * 00391 * Destroys a dynamic pointer array 00392 * 00393 * PARAMS 00394 * hdpa [I] handle (pointer) to the pointer array 00395 * 00396 * RETURNS 00397 * Success: TRUE 00398 * Failure: FALSE 00399 */ 00400 BOOL WINAPI DPA_Destroy (const HDPA hdpa) 00401 { 00402 TRACE("(%p)\n", hdpa); 00403 00404 if (!hdpa) 00405 return FALSE; 00406 00407 if (hdpa->ptrs && (!HeapFree (hdpa->hHeap, 0, hdpa->ptrs))) 00408 return FALSE; 00409 00410 return HeapFree (hdpa->hHeap, 0, hdpa); 00411 } 00412 00413 00414 /************************************************************************** 00415 * DPA_Grow [COMCTL32.330] 00416 * 00417 * Sets the growth amount. 00418 * 00419 * PARAMS 00420 * hdpa [I] handle (pointer) to the existing (source) pointer array 00421 * nGrow [I] number of items by which the array grows when it's too small 00422 * 00423 * RETURNS 00424 * Success: TRUE 00425 * Failure: FALSE 00426 */ 00427 BOOL WINAPI DPA_Grow (HDPA hdpa, INT nGrow) 00428 { 00429 INT items; 00430 TRACE("(%p %d)\n", hdpa, nGrow); 00431 00432 if (!hdpa) 00433 return FALSE; 00434 00435 nGrow = max( 8, nGrow ); 00436 items = nGrow * (((hdpa->nMaxCount - 1) / nGrow) + 1); 00437 if (items > hdpa->nMaxCount) 00438 { 00439 void *ptr; 00440 00441 if (hdpa->ptrs) 00442 ptr = HeapReAlloc( hdpa->hHeap, HEAP_ZERO_MEMORY, hdpa->ptrs, items * sizeof(LPVOID) ); 00443 else 00444 ptr = HeapAlloc( hdpa->hHeap, HEAP_ZERO_MEMORY, items * sizeof(LPVOID) ); 00445 if (!ptr) return FALSE; 00446 hdpa->nMaxCount = items; 00447 hdpa->ptrs = ptr; 00448 } 00449 hdpa->nGrow = nGrow; 00450 00451 return TRUE; 00452 } 00453 00454 00455 /************************************************************************** 00456 * DPA_Clone [COMCTL32.331] 00457 * 00458 * Copies a pointer array to an other one or creates a copy 00459 * 00460 * PARAMS 00461 * hdpa [I] handle (pointer) to the existing (source) pointer array 00462 * hdpaNew [O] handle (pointer) to the destination pointer array 00463 * 00464 * RETURNS 00465 * Success: pointer to the destination pointer array. 00466 * Failure: NULL 00467 * 00468 * NOTES 00469 * - If the 'hdpaNew' is a NULL-Pointer, a copy of the source pointer 00470 * array will be created and it's handle (pointer) is returned. 00471 * - If 'hdpa' is a NULL-Pointer, the original implementation crashes, 00472 * this implementation just returns NULL. 00473 */ 00474 HDPA WINAPI DPA_Clone (const HDPA hdpa, const HDPA hdpaNew) 00475 { 00476 INT nNewItems, nSize; 00477 HDPA hdpaTemp; 00478 00479 if (!hdpa) 00480 return NULL; 00481 00482 TRACE("(%p %p)\n", hdpa, hdpaNew); 00483 00484 if (!hdpaNew) { 00485 /* create a new DPA */ 00486 hdpaTemp = HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY, 00487 sizeof(*hdpaTemp)); 00488 hdpaTemp->hHeap = hdpa->hHeap; 00489 hdpaTemp->nGrow = hdpa->nGrow; 00490 } 00491 else 00492 hdpaTemp = hdpaNew; 00493 00494 if (hdpaTemp->ptrs) { 00495 /* remove old pointer array */ 00496 HeapFree (hdpaTemp->hHeap, 0, hdpaTemp->ptrs); 00497 hdpaTemp->ptrs = NULL; 00498 hdpaTemp->nItemCount = 0; 00499 hdpaTemp->nMaxCount = 0; 00500 } 00501 00502 /* create a new pointer array */ 00503 nNewItems = hdpaTemp->nGrow * 00504 (((hdpa->nItemCount - 1) / hdpaTemp->nGrow) + 1); 00505 nSize = nNewItems * sizeof(LPVOID); 00506 hdpaTemp->ptrs = HeapAlloc (hdpaTemp->hHeap, HEAP_ZERO_MEMORY, nSize); 00507 hdpaTemp->nMaxCount = nNewItems; 00508 00509 /* clone the pointer array */ 00510 hdpaTemp->nItemCount = hdpa->nItemCount; 00511 memmove (hdpaTemp->ptrs, hdpa->ptrs, 00512 hdpaTemp->nItemCount * sizeof(LPVOID)); 00513 00514 return hdpaTemp; 00515 } 00516 00517 00518 /************************************************************************** 00519 * DPA_GetPtr [COMCTL32.332] 00520 * 00521 * Retrieves a pointer from a dynamic pointer array 00522 * 00523 * PARAMS 00524 * hdpa [I] handle (pointer) to the pointer array 00525 * nIndex [I] array index of the desired pointer 00526 * 00527 * RETURNS 00528 * Success: pointer 00529 * Failure: NULL 00530 */ 00531 LPVOID WINAPI DPA_GetPtr (const HDPA hdpa, INT nIndex) 00532 { 00533 TRACE("(%p %d)\n", hdpa, nIndex); 00534 00535 if (!hdpa) 00536 return NULL; 00537 if (!hdpa->ptrs) { 00538 WARN("no pointer array.\n"); 00539 return NULL; 00540 } 00541 if ((nIndex < 0) || (nIndex >= hdpa->nItemCount)) { 00542 WARN("not enough pointers in array (%d vs %d).\n",nIndex,hdpa->nItemCount); 00543 return NULL; 00544 } 00545 00546 TRACE("-- %p\n", hdpa->ptrs[nIndex]); 00547 00548 return hdpa->ptrs[nIndex]; 00549 } 00550 00551 00552 /************************************************************************** 00553 * DPA_GetPtrIndex [COMCTL32.333] 00554 * 00555 * Retrieves the index of the specified pointer 00556 * 00557 * PARAMS 00558 * hdpa [I] handle (pointer) to the pointer array 00559 * p [I] pointer 00560 * 00561 * RETURNS 00562 * Success: index of the specified pointer 00563 * Failure: -1 00564 */ 00565 INT WINAPI DPA_GetPtrIndex (HDPA hdpa, LPCVOID p) 00566 { 00567 INT i; 00568 00569 if (!hdpa || !hdpa->ptrs) 00570 return -1; 00571 00572 for (i = 0; i < hdpa->nItemCount; i++) { 00573 if (hdpa->ptrs[i] == p) 00574 return i; 00575 } 00576 00577 return -1; 00578 } 00579 00580 00581 /************************************************************************** 00582 * DPA_InsertPtr [COMCTL32.334] 00583 * 00584 * Inserts a pointer into a dynamic pointer array 00585 * 00586 * PARAMS 00587 * hdpa [I] handle (pointer) to the array 00588 * i [I] array index 00589 * p [I] pointer to insert 00590 * 00591 * RETURNS 00592 * Success: index of the inserted pointer 00593 * Failure: -1 00594 */ 00595 INT WINAPI DPA_InsertPtr (const HDPA hdpa, INT i, LPVOID p) 00596 { 00597 TRACE("(%p %d %p)\n", hdpa, i, p); 00598 00599 if (!hdpa || i < 0) return -1; 00600 00601 /* append item if index is out of bounds */ 00602 i = min(hdpa->nItemCount, i); 00603 00604 /* create empty spot at the end */ 00605 if (!DPA_SetPtr(hdpa, hdpa->nItemCount, 0)) return -1; 00606 00607 if (i != hdpa->nItemCount - 1) 00608 memmove (hdpa->ptrs + i + 1, hdpa->ptrs + i, 00609 (hdpa->nItemCount - i - 1) * sizeof(LPVOID)); 00610 00611 hdpa->ptrs[i] = p; 00612 return i; 00613 } 00614 00615 00616 /************************************************************************** 00617 * DPA_SetPtr [COMCTL32.335] 00618 * 00619 * Sets a pointer in the pointer array 00620 * 00621 * PARAMS 00622 * hdpa [I] handle (pointer) to the pointer array 00623 * i [I] index of the pointer that will be set 00624 * p [I] pointer to be set 00625 * 00626 * RETURNS 00627 * Success: TRUE 00628 * Failure: FALSE 00629 */ 00630 BOOL WINAPI DPA_SetPtr (const HDPA hdpa, INT i, LPVOID p) 00631 { 00632 LPVOID *lpTemp; 00633 00634 TRACE("(%p %d %p)\n", hdpa, i, p); 00635 00636 if (!hdpa || i < 0) 00637 return FALSE; 00638 00639 if (hdpa->nItemCount <= i) { 00640 /* within the old array */ 00641 if (hdpa->nMaxCount <= i) { 00642 /* resize the block of memory */ 00643 INT nNewItems = 00644 hdpa->nGrow * ((((i+1) - 1) / hdpa->nGrow) + 1); 00645 INT nSize = nNewItems * sizeof(LPVOID); 00646 00647 if (hdpa->ptrs) 00648 lpTemp = HeapReAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY, hdpa->ptrs, nSize); 00649 else 00650 lpTemp = HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY, nSize); 00651 00652 if (!lpTemp) 00653 return FALSE; 00654 00655 hdpa->nMaxCount = nNewItems; 00656 hdpa->ptrs = lpTemp; 00657 } 00658 hdpa->nItemCount = i+1; 00659 } 00660 00661 /* put the new entry in */ 00662 hdpa->ptrs[i] = p; 00663 00664 return TRUE; 00665 } 00666 00667 00668 /************************************************************************** 00669 * DPA_DeletePtr [COMCTL32.336] 00670 * 00671 * Removes a pointer from the pointer array. 00672 * 00673 * PARAMS 00674 * hdpa [I] handle (pointer) to the pointer array 00675 * i [I] index of the pointer that will be deleted 00676 * 00677 * RETURNS 00678 * Success: deleted pointer 00679 * Failure: NULL 00680 */ 00681 LPVOID WINAPI DPA_DeletePtr (const HDPA hdpa, INT i) 00682 { 00683 LPVOID *lpDest, *lpSrc, lpTemp = NULL; 00684 INT nSize; 00685 00686 TRACE("(%p %d)\n", hdpa, i); 00687 00688 if ((!hdpa) || i < 0 || i >= hdpa->nItemCount) 00689 return NULL; 00690 00691 lpTemp = hdpa->ptrs[i]; 00692 00693 /* do we need to move ?*/ 00694 if (i < hdpa->nItemCount - 1) { 00695 lpDest = hdpa->ptrs + i; 00696 lpSrc = lpDest + 1; 00697 nSize = (hdpa->nItemCount - i - 1) * sizeof(LPVOID); 00698 TRACE("-- move dest=%p src=%p size=%x\n", 00699 lpDest, lpSrc, nSize); 00700 memmove (lpDest, lpSrc, nSize); 00701 } 00702 00703 hdpa->nItemCount --; 00704 00705 /* free memory ?*/ 00706 if ((hdpa->nMaxCount - hdpa->nItemCount) >= hdpa->nGrow) { 00707 INT nNewItems = max(hdpa->nGrow * 2, hdpa->nItemCount); 00708 nSize = nNewItems * sizeof(LPVOID); 00709 lpDest = HeapReAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY, 00710 hdpa->ptrs, nSize); 00711 if (!lpDest) 00712 return NULL; 00713 00714 hdpa->nMaxCount = nNewItems; 00715 hdpa->ptrs = lpDest; 00716 } 00717 00718 return lpTemp; 00719 } 00720 00721 00722 /************************************************************************** 00723 * DPA_DeleteAllPtrs [COMCTL32.337] 00724 * 00725 * Removes all pointers and reinitializes the array. 00726 * 00727 * PARAMS 00728 * hdpa [I] handle (pointer) to the pointer array 00729 * 00730 * RETURNS 00731 * Success: TRUE 00732 * Failure: FALSE 00733 */ 00734 BOOL WINAPI DPA_DeleteAllPtrs (const HDPA hdpa) 00735 { 00736 TRACE("(%p)\n", hdpa); 00737 00738 if (!hdpa) 00739 return FALSE; 00740 00741 if (hdpa->ptrs && (!HeapFree (hdpa->hHeap, 0, hdpa->ptrs))) 00742 return FALSE; 00743 00744 hdpa->nItemCount = 0; 00745 hdpa->nMaxCount = hdpa->nGrow * 2; 00746 hdpa->ptrs = HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY, 00747 hdpa->nMaxCount * sizeof(LPVOID)); 00748 00749 return TRUE; 00750 } 00751 00752 00753 /************************************************************************** 00754 * DPA_QuickSort [Internal] 00755 * 00756 * Ordinary quicksort (used by DPA_Sort). 00757 * 00758 * PARAMS 00759 * lpPtrs [I] pointer to the pointer array 00760 * l [I] index of the "left border" of the partition 00761 * r [I] index of the "right border" of the partition 00762 * pfnCompare [I] pointer to the compare function 00763 * lParam [I] user defined value (3rd parameter in compare function) 00764 * 00765 * RETURNS 00766 * NONE 00767 */ 00768 static VOID DPA_QuickSort (LPVOID *lpPtrs, INT l, INT r, 00769 PFNDPACOMPARE pfnCompare, LPARAM lParam) 00770 { 00771 INT m; 00772 LPVOID t; 00773 00774 TRACE("l=%i r=%i\n", l, r); 00775 00776 if (l==r) /* one element is always sorted */ 00777 return; 00778 if (r<l) /* oops, got it in the wrong order */ 00779 { 00780 DPA_QuickSort(lpPtrs, r, l, pfnCompare, lParam); 00781 return; 00782 } 00783 m = (l+r)/2; /* divide by two */ 00784 DPA_QuickSort(lpPtrs, l, m, pfnCompare, lParam); 00785 DPA_QuickSort(lpPtrs, m+1, r, pfnCompare, lParam); 00786 00787 /* join the two sides */ 00788 while( (l<=m) && (m<r) ) 00789 { 00790 if(pfnCompare(lpPtrs[l],lpPtrs[m+1],lParam)>0) 00791 { 00792 t = lpPtrs[m+1]; 00793 memmove(&lpPtrs[l+1],&lpPtrs[l],(m-l+1)*sizeof(lpPtrs[l])); 00794 lpPtrs[l] = t; 00795 00796 m++; 00797 } 00798 l++; 00799 } 00800 } 00801 00802 00803 /************************************************************************** 00804 * DPA_Sort [COMCTL32.338] 00805 * 00806 * Sorts a pointer array using a user defined compare function 00807 * 00808 * PARAMS 00809 * hdpa [I] handle (pointer) to the pointer array 00810 * pfnCompare [I] pointer to the compare function 00811 * lParam [I] user defined value (3rd parameter of compare function) 00812 * 00813 * RETURNS 00814 * Success: TRUE 00815 * Failure: FALSE 00816 */ 00817 BOOL WINAPI DPA_Sort (const HDPA hdpa, PFNDPACOMPARE pfnCompare, LPARAM lParam) 00818 { 00819 if (!hdpa || !pfnCompare) 00820 return FALSE; 00821 00822 TRACE("(%p %p 0x%lx)\n", hdpa, pfnCompare, lParam); 00823 00824 if ((hdpa->nItemCount > 1) && (hdpa->ptrs)) 00825 DPA_QuickSort (hdpa->ptrs, 0, hdpa->nItemCount - 1, 00826 pfnCompare, lParam); 00827 00828 return TRUE; 00829 } 00830 00831 00832 /************************************************************************** 00833 * DPA_Search [COMCTL32.339] 00834 * 00835 * Searches a pointer array for a specified pointer 00836 * 00837 * PARAMS 00838 * hdpa [I] handle (pointer) to the pointer array 00839 * pFind [I] pointer to search for 00840 * nStart [I] start index 00841 * pfnCompare [I] pointer to the compare function 00842 * lParam [I] user defined value (3rd parameter of compare function) 00843 * uOptions [I] search options 00844 * 00845 * RETURNS 00846 * Success: index of the pointer in the array. 00847 * Failure: -1 00848 */ 00849 INT WINAPI DPA_Search (const HDPA hdpa, LPVOID pFind, INT nStart, 00850 PFNDPACOMPARE pfnCompare, LPARAM lParam, UINT uOptions) 00851 { 00852 if (!hdpa || !pfnCompare || !pFind) 00853 return -1; 00854 00855 TRACE("(%p %p %d %p 0x%08lx 0x%08x)\n", 00856 hdpa, pFind, nStart, pfnCompare, lParam, uOptions); 00857 00858 if (uOptions & DPAS_SORTED) { 00859 /* array is sorted --> use binary search */ 00860 INT l, r, x, n; 00861 LPVOID *lpPtr; 00862 00863 /* for binary search ignore start index */ 00864 l = 0; 00865 r = hdpa->nItemCount - 1; 00866 lpPtr = hdpa->ptrs; 00867 while (r >= l) { 00868 x = (l + r) / 2; 00869 n = (pfnCompare)(pFind, lpPtr[x], lParam); 00870 if (n == 0) 00871 return x; 00872 else if (n < 0) 00873 r = x - 1; 00874 else /* (n > 0) */ 00875 l = x + 1; 00876 } 00877 if (uOptions & (DPAS_INSERTBEFORE|DPAS_INSERTAFTER)) return l; 00878 } 00879 else { 00880 /* array is not sorted --> use linear search */ 00881 LPVOID *lpPtr; 00882 INT nIndex; 00883 00884 nIndex = (nStart == -1)? 0 : nStart; 00885 lpPtr = hdpa->ptrs; 00886 for (; nIndex < hdpa->nItemCount; nIndex++) { 00887 if ((pfnCompare)(pFind, lpPtr[nIndex], lParam) == 0) 00888 return nIndex; 00889 } 00890 } 00891 00892 return -1; 00893 } 00894 00895 00896 /************************************************************************** 00897 * DPA_CreateEx [COMCTL32.340] 00898 * 00899 * Creates a dynamic pointer array using the specified size and heap. 00900 * 00901 * PARAMS 00902 * nGrow [I] number of items by which the array grows when it is filled 00903 * hHeap [I] handle to the heap where the array is stored 00904 * 00905 * RETURNS 00906 * Success: handle (pointer) to the pointer array. 00907 * Failure: NULL 00908 * 00909 * NOTES 00910 * The DPA_ functions can be used to create and manipulate arrays of 00911 * pointers. 00912 */ 00913 HDPA WINAPI DPA_CreateEx (INT nGrow, HANDLE hHeap) 00914 { 00915 HDPA hdpa; 00916 00917 TRACE("(%d %p)\n", nGrow, hHeap); 00918 00919 if (hHeap) 00920 hdpa = HeapAlloc (hHeap, HEAP_ZERO_MEMORY, sizeof(*hdpa)); 00921 else 00922 hdpa = Alloc (sizeof(*hdpa)); 00923 00924 if (hdpa) { 00925 hdpa->nGrow = max(8, nGrow); 00926 hdpa->hHeap = hHeap ? hHeap : GetProcessHeap(); 00927 hdpa->nMaxCount = hdpa->nGrow * 2; 00928 hdpa->ptrs = HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY, 00929 hdpa->nMaxCount * sizeof(LPVOID)); 00930 } 00931 00932 TRACE("-- %p\n", hdpa); 00933 00934 return hdpa; 00935 } 00936 00937 00938 /************************************************************************** 00939 * DPA_Create [COMCTL32.328] 00940 * 00941 * Creates a dynamic pointer array. 00942 * 00943 * PARAMS 00944 * nGrow [I] number of items by which the array grows when it is filled 00945 * 00946 * RETURNS 00947 * Success: handle (pointer) to the pointer array. 00948 * Failure: NULL 00949 * 00950 * NOTES 00951 * The DPA_ functions can be used to create and manipulate arrays of 00952 * pointers. 00953 */ 00954 HDPA WINAPI DPA_Create (INT nGrow) 00955 { 00956 return DPA_CreateEx( nGrow, 0 ); 00957 } 00958 00959 00960 /************************************************************************** 00961 * DPA_EnumCallback [COMCTL32.385] 00962 * 00963 * Enumerates all items in a dynamic pointer array. 00964 * 00965 * PARAMS 00966 * hdpa [I] handle to the dynamic pointer array 00967 * enumProc [I] 00968 * lParam [I] 00969 * 00970 * RETURNS 00971 * none 00972 */ 00973 VOID WINAPI DPA_EnumCallback (HDPA hdpa, PFNDPAENUMCALLBACK enumProc, 00974 LPVOID lParam) 00975 { 00976 INT i; 00977 00978 TRACE("(%p %p %p)\n", hdpa, enumProc, lParam); 00979 00980 if (!hdpa) 00981 return; 00982 if (hdpa->nItemCount <= 0) 00983 return; 00984 00985 for (i = 0; i < hdpa->nItemCount; i++) { 00986 if ((enumProc)(hdpa->ptrs[i], lParam) == 0) 00987 return; 00988 } 00989 00990 return; 00991 } 00992 00993 00994 /************************************************************************** 00995 * DPA_DestroyCallback [COMCTL32.386] 00996 * 00997 * Enumerates all items in a dynamic pointer array and destroys it. 00998 * 00999 * PARAMS 01000 * hdpa [I] handle to the dynamic pointer array 01001 * enumProc [I] 01002 * lParam [I] 01003 * 01004 * RETURNS 01005 * none 01006 */ 01007 void WINAPI DPA_DestroyCallback (HDPA hdpa, PFNDPAENUMCALLBACK enumProc, 01008 LPVOID lParam) 01009 { 01010 TRACE("(%p %p %p)\n", hdpa, enumProc, lParam); 01011 01012 DPA_EnumCallback (hdpa, enumProc, lParam); 01013 DPA_Destroy (hdpa); 01014 } 01015 01016 /************************************************************************** 01017 * DPA_GetSize [COMCTL32.@] 01018 * 01019 * Returns all array allocated memory size 01020 * 01021 * PARAMS 01022 * hdpa [I] handle to the dynamic pointer array 01023 * 01024 * RETURNS 01025 * Size in bytes 01026 */ 01027 ULONGLONG WINAPI DPA_GetSize(HDPA hdpa) 01028 { 01029 TRACE("(%p)\n", hdpa); 01030 01031 if (!hdpa) return 0; 01032 01033 return sizeof(DPA) + hdpa->nMaxCount*sizeof(PVOID); 01034 } Generated on Sat May 26 2012 04:21:32 for ReactOS by
1.7.6.1
|