ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

dpa.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.