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

clist.c
Go to the documentation of this file.
00001 /*
00002  * SHLWAPI DataBlock List functions
00003  *
00004  * Copyright 2002 Jon Griffiths
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00019  */
00020 #include <stdarg.h>
00021 #include <string.h>
00022 
00023 #define COBJMACROS
00024 
00025 #include "windef.h"
00026 #include "winbase.h"
00027 #include "winuser.h"
00028 #include "objbase.h"
00029 #include "shlobj.h"
00030 #include "wine/debug.h"
00031 
00032 WINE_DEFAULT_DEBUG_CHANNEL(shell);
00033 
00034 /* dwSignature for contained DATABLOCK_HEADER items */
00035 #define CLIST_ID_CONTAINER (~0U)
00036 
00037 /*************************************************************************
00038  * NextItem
00039  *
00040  * Internal helper: move a DataBlock pointer to the next item.
00041  */
00042 static inline LPDATABLOCK_HEADER NextItem(LPDBLIST lpList)
00043 {
00044   char* address = (char*)lpList;
00045   address += lpList->cbSize;
00046   return (LPDATABLOCK_HEADER)address;
00047 }
00048 
00049 /*************************************************************************
00050  *      @   [SHLWAPI.20]
00051  *
00052  * Insert a new item into a DataBlock list.
00053  *
00054  * PARAMS
00055  *  lppList   [0] Pointer to the List
00056  *  lpNewItem [I] The new item to add to the list
00057  *
00058  * RETURNS
00059  *  Success: S_OK. The item is added to the list.
00060  *  Failure: An HRESULT error code.
00061  *
00062  * NOTES
00063  *  If the size of the element to be inserted is less than the size of a
00064  *  DATABLOCK_HEADER node, or the Id for the item is CLIST_ID_CONTAINER,
00065  *  the call returns S_OK but does not actually add the element.
00066  *  See SHWriteDataBlockList.
00067  */
00068 HRESULT WINAPI SHAddDataBlock(LPDBLIST* lppList, const DATABLOCK_HEADER *lpNewItem)
00069 {
00070   LPDATABLOCK_HEADER lpInsertAt = NULL;
00071   ULONG ulSize;
00072 
00073   TRACE("(%p,%p)\n", lppList, lpNewItem);
00074 
00075   if(!lppList || !lpNewItem )
00076     return E_INVALIDARG;
00077 
00078   if (lpNewItem->cbSize < sizeof(DATABLOCK_HEADER) ||
00079       lpNewItem->dwSignature == CLIST_ID_CONTAINER)
00080     return S_OK;
00081 
00082   ulSize = lpNewItem->cbSize;
00083 
00084   if(ulSize & 0x3)
00085   {
00086     /* Tune size to a ULONG boundary, add space for container element */
00087     ulSize = ((ulSize + 0x3) & 0xFFFFFFFC) + sizeof(DATABLOCK_HEADER);
00088     TRACE("Creating container item, new size = %d\n", ulSize);
00089   }
00090 
00091   if(!*lppList)
00092   {
00093     /* An empty list. Allocate space for terminal ulSize also */
00094     *lppList = LocalAlloc(LMEM_ZEROINIT, ulSize + sizeof(ULONG));
00095     lpInsertAt = *lppList;
00096   }
00097   else
00098   {
00099     /* Append to the end of the list */
00100     ULONG ulTotalSize = 0;
00101     LPDATABLOCK_HEADER lpIter = *lppList;
00102 
00103     /* Iterate to the end of the list, calculating the total size */
00104     while (lpIter->cbSize)
00105     {
00106       ulTotalSize += lpIter->cbSize;
00107       lpIter = NextItem(lpIter);
00108     }
00109 
00110     /* Increase the size of the list */
00111     lpIter = LocalReAlloc(*lppList, ulTotalSize + ulSize+sizeof(ULONG),
00112                                           LMEM_ZEROINIT | LMEM_MOVEABLE);
00113     if(lpIter)
00114     {
00115       *lppList = lpIter;
00116       lpInsertAt = (LPDATABLOCK_HEADER)((char*)lpIter + ulTotalSize); /* At end */
00117     }
00118   }
00119 
00120   if(lpInsertAt)
00121   {
00122     /* Copy in the new item */
00123     LPDATABLOCK_HEADER lpDest = lpInsertAt;
00124 
00125     if(ulSize != lpNewItem->cbSize)
00126     {
00127       lpInsertAt->cbSize = ulSize;
00128       lpInsertAt->dwSignature = CLIST_ID_CONTAINER;
00129       lpDest++;
00130     }
00131     memcpy(lpDest, lpNewItem, lpNewItem->cbSize);
00132 
00133     /* Terminate the list */
00134     lpInsertAt = NextItem(lpInsertAt);
00135     lpInsertAt->cbSize = 0;
00136 
00137     return lpNewItem->cbSize;
00138   }
00139   return S_OK;
00140 }
00141 
00142 /*************************************************************************
00143  *      @   [SHLWAPI.17]
00144  *
00145  * Write a DataBlock list to an IStream object.
00146  *
00147  * PARAMS
00148  *  lpStream  [I] IStream object to write the list to
00149  *  lpList    [I] List of items to write
00150  *
00151  * RETURNS
00152  *  Success: S_OK. The object is written to the stream.
00153  *  Failure: An HRESULT error code
00154  *
00155  * NOTES
00156  *  Ordinals 17,18,19,20,21 and 22 are related and together provide a compact
00157  *  list structure (a "DataBlock List"), which may be stored and retrieved from
00158  *  an IStream object.
00159  *
00160  *  The exposed API consists of:
00161  *
00162  *  - SHWriteDataBlockList() - Write a DataBlock list to a stream,
00163  *  - SHReadDataBlockList() - Read and create a list from a stream,
00164  *  - SHFreeDataBlockList() - Free a list,
00165  *  - SHAddDataBlock() - Insert a new item into a list,
00166  *  - SHRemoveDataBlock() - Remove an item from a list,
00167  *  - SHFindDataBlock() - Find an item in a list.
00168  *
00169  *  The DataBlock list is stored packed into a memory array. Each element has a
00170  *  size and an associated ID. Elements must be less than 64k if the list is
00171  *  to be subsequently read from a stream.
00172  *
00173  *  Elements are aligned on DWORD boundaries. If an elements data size is not
00174  *  a DWORD size multiple, the element is wrapped by inserting a surrounding
00175  *  element with an Id of 0xFFFFFFFF, and size sufficient to pad to a DWORD boundary.
00176  *
00177  *  These functions are slow for large objects and long lists.
00178  */
00179 HRESULT WINAPI SHWriteDataBlockList(IStream* lpStream, LPDBLIST lpList)
00180 {
00181   ULONG ulSize;
00182   HRESULT hRet = S_OK;
00183 
00184   TRACE("(%p,%p)\n", lpStream, lpList);
00185 
00186   if(lpList)
00187   {
00188     while (lpList->cbSize)
00189     {
00190       LPDATABLOCK_HEADER lpItem = lpList;
00191 
00192       if(lpList->dwSignature == CLIST_ID_CONTAINER)
00193         lpItem++;
00194 
00195       hRet = IStream_Write(lpStream,lpItem,lpItem->cbSize,&ulSize);
00196       if (FAILED(hRet))
00197         return hRet;
00198 
00199       if(lpItem->cbSize != ulSize)
00200         return STG_E_MEDIUMFULL;
00201 
00202       lpList = NextItem(lpList);
00203     }
00204   }
00205 
00206   if(SUCCEEDED(hRet))
00207   {
00208     ULONG ulDummy;
00209     ulSize = 0;
00210 
00211     /* Write a terminating list entry with zero size */
00212     hRet = IStream_Write(lpStream, &ulSize,sizeof(ulSize),&ulDummy);
00213   }
00214 
00215   return hRet;
00216 }
00217 
00218 /*************************************************************************
00219  *      @   [SHLWAPI.18]
00220  *
00221  * Read and create a DataBlock list from an IStream object.
00222  *
00223  * PARAMS
00224  *  lpStream  [I] Stream to read the list from
00225  *  lppList   [0] Pointer to receive the new List
00226  *
00227  * RETURNS
00228  *  Success: S_OK
00229  *  Failure: An HRESULT error code
00230  *
00231  * NOTES
00232  *  When read from a file, list objects are limited in size to 64k.
00233  *  See SHWriteDataBlockList.
00234  */
00235 HRESULT WINAPI SHReadDataBlockList(IStream* lpStream, LPDBLIST* lppList)
00236 {
00237   DATABLOCK_HEADER bBuff[128]; /* Temporary storage for new list item */
00238   ULONG ulBuffSize = sizeof(bBuff);
00239   LPDATABLOCK_HEADER pItem = bBuff;
00240   ULONG ulRead, ulSize;
00241   HRESULT hRet = S_OK;
00242 
00243   TRACE("(%p,%p)\n", lpStream, lppList);
00244 
00245   if(*lppList)
00246   {
00247     /* Free any existing list */
00248     LocalFree(*lppList);
00249     *lppList = NULL;
00250   }
00251 
00252   do
00253   {
00254     /* Read the size of the next item */
00255     hRet = IStream_Read(lpStream, &ulSize,sizeof(ulSize),&ulRead);
00256 
00257     if(FAILED(hRet) || ulRead != sizeof(ulSize) || !ulSize)
00258       break; /* Read failed or read zero size (the end of the list) */
00259 
00260     if(ulSize > 0xFFFF)
00261     {
00262       LARGE_INTEGER liZero;
00263       ULARGE_INTEGER ulPos;
00264 
00265       liZero.QuadPart = 0;
00266 
00267       /* Back the stream up; this object is too big for the list */
00268       if(SUCCEEDED(IStream_Seek(lpStream, liZero, STREAM_SEEK_CUR, &ulPos)))
00269       {
00270         liZero.QuadPart = ulPos.QuadPart - sizeof(ULONG);
00271         IStream_Seek(lpStream, liZero, STREAM_SEEK_SET, NULL);
00272       }
00273       break;
00274     }
00275     else if (ulSize >= sizeof(DATABLOCK_HEADER))
00276     {
00277       /* Add this new item to the list */
00278       if(ulSize > ulBuffSize)
00279       {
00280         /* We need more buffer space, allocate it */
00281         LPDATABLOCK_HEADER lpTemp;
00282 
00283         if (pItem == bBuff)
00284           lpTemp = LocalAlloc(LMEM_ZEROINIT, ulSize);
00285         else
00286           lpTemp = LocalReAlloc(pItem, ulSize, LMEM_ZEROINIT|LMEM_MOVEABLE);
00287 
00288         if(!lpTemp)
00289         {
00290           hRet = E_OUTOFMEMORY;
00291           break;
00292         }
00293         ulBuffSize = ulSize;
00294         pItem = lpTemp;
00295       }
00296 
00297       pItem->cbSize = ulSize;
00298       ulSize -= sizeof(pItem->cbSize); /* already read this member */
00299 
00300       /* Read the item Id and data */
00301       hRet = IStream_Read(lpStream, &pItem->dwSignature, ulSize, &ulRead);
00302 
00303       if(FAILED(hRet) || ulRead != ulSize)
00304         break;
00305 
00306       SHAddDataBlock(lppList, pItem); /* Insert Item */
00307     }
00308   } while(1);
00309 
00310   /* If we allocated space, free it */
00311   if(pItem != bBuff)
00312     LocalFree(pItem);
00313 
00314   return hRet;
00315 }
00316 
00317 /*************************************************************************
00318  *      @   [SHLWAPI.19]
00319  *
00320  * Free a DataBlock list.
00321  *
00322  * PARAMS
00323  *  lpList [I] List to free
00324  *
00325  * RETURNS
00326  *  Nothing.
00327  *
00328  * NOTES
00329  *  See SHWriteDataBlockList.
00330  */
00331 VOID WINAPI SHFreeDataBlockList(LPDBLIST lpList)
00332 {
00333   TRACE("(%p)\n", lpList);
00334 
00335   if (lpList)
00336     LocalFree(lpList);
00337 }
00338 
00339 /*************************************************************************
00340  *      @   [SHLWAPI.21]
00341  *
00342  * Remove an item from a DataBlock list.
00343  *
00344  * PARAMS
00345  *  lppList     [O] List to remove the item from
00346  *  dwSignature [I] Id of item to remove
00347  *
00348  * RETURNS
00349  *  Success: TRUE.
00350  *  Failure: FALSE, If any parameters are invalid, or the item was not found.
00351  *
00352  * NOTES
00353  *  See SHWriteDataBlockList.
00354  */
00355 BOOL WINAPI SHRemoveDataBlock(LPDBLIST* lppList, DWORD dwSignature)
00356 {
00357   LPDATABLOCK_HEADER lpList = 0;
00358   LPDATABLOCK_HEADER lpItem = NULL;
00359   LPDATABLOCK_HEADER lpNext;
00360   ULONG ulNewSize;
00361 
00362   TRACE("(%p,%d)\n", lppList, dwSignature);
00363 
00364   if(lppList && (lpList = *lppList))
00365   {
00366     /* Search for item in list */
00367     while (lpList->cbSize)
00368     {
00369       if(lpList->dwSignature == dwSignature ||
00370         (lpList->dwSignature == CLIST_ID_CONTAINER && lpList[1].dwSignature == dwSignature))
00371       {
00372         lpItem = lpList; /* Found */
00373         break;
00374       }
00375       lpList = NextItem(lpList);
00376     }
00377   }
00378 
00379   if(!lpItem)
00380     return FALSE;
00381 
00382   lpList = lpNext = NextItem(lpItem);
00383 
00384   /* Locate the end of the list */
00385   while (lpList->cbSize)
00386     lpList = NextItem(lpList);
00387 
00388   /* Resize the list */
00389   ulNewSize = LocalSize(*lppList) - lpItem->cbSize;
00390 
00391   /* Copy following elements over lpItem */
00392   memmove(lpItem, lpNext, (char *)lpList - (char *)lpNext + sizeof(ULONG));
00393 
00394   if(ulNewSize <= sizeof(ULONG))
00395   {
00396     LocalFree(*lppList);
00397     *lppList = NULL; /* Removed the last element */
00398   }
00399   else
00400   {
00401     lpList = LocalReAlloc(*lppList, ulNewSize, LMEM_ZEROINIT|LMEM_MOVEABLE);
00402     if(lpList)
00403       *lppList = lpList;
00404   }
00405   return TRUE;
00406 }
00407 
00408 /*************************************************************************
00409  *      @   [SHLWAPI.22]
00410  *
00411  * Find an item in a DataBlock list.
00412  *
00413  * PARAMS
00414  *  lpList      [I] List to search
00415  *  dwSignature [I] Id of item to find
00416  *
00417  * RETURNS
00418  *  Success: A pointer to the list item found
00419  *  Failure: NULL
00420  *
00421  * NOTES
00422  *  See SHWriteDataBlockList.
00423  */
00424 DATABLOCK_HEADER* WINAPI SHFindDataBlock(LPDBLIST lpList, DWORD dwSignature)
00425 {
00426   TRACE("(%p,%d)\n", lpList, dwSignature);
00427 
00428   if(lpList)
00429   {
00430     while(lpList->cbSize)
00431     {
00432       if(lpList->dwSignature == dwSignature)
00433         return lpList; /* Matched */
00434       else if(lpList->dwSignature == CLIST_ID_CONTAINER && lpList[1].dwSignature == dwSignature)
00435         return lpList + 1; /* Contained item matches */
00436 
00437       lpList = NextItem(lpList);
00438     }
00439   }
00440   return NULL;
00441 }

Generated on Sat May 26 2012 04:25:06 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.