/*++ Copyright (c) 1996 Microsoft Corporation Module Name: growlist.c Abstract: Simple buffer management functions that maintenence of a list of binary objects. Author: 08-Aug-1997 jimschm Created Revision History: marcw 2-Sep-1999 Moved over from Win9xUpg project. --*/ #include "pch.h" #include "commonp.h" #define INSERT_LAST 0xffffffff PBYTE pGlAdd ( IN OUT PGROWLIST GrowList, IN UINT InsertBefore, IN PBYTE DataToAdd, OPTIONAL IN UINT SizeOfData, IN UINT NulBytesToAdd ) /*++ Routine Description: pGlAdd allocates memory for a binary block by using a pool, and then expands an array of pointers, maintaining a quick-access list. Arguments: GrowList - Specifies the list to add the entry to InsertBefore - Specifies the index of the array element to insert before, or INSERT_LIST to append. DataToAdd - Specifies the binary block of data to add. SizeOfData - Specifies the size of data. NulBytesToAdd - Specifies the number of nul bytes to add to the buffer Return Value: A pointer to the binary block if data was copied into the list, 1 if a list item was created but no data was set for the item, or NULL if an error occurred. --*/ { PBYTE *Item; PBYTE *InsertAt; PBYTE Data; UINT OldEnd; UINT Size; UINT TotalSize; TotalSize = SizeOfData + NulBytesToAdd; MYASSERT (TotalSize || !DataToAdd); // // Expand list array // OldEnd = GrowList->ListArray.End; Item = (PBYTE *) GbGrow (&GrowList->ListArray, sizeof (PBYTE)); if (!Item) { DEBUGMSG ((DBG_WARNING, "GrowList: Could not allocate array item")); return NULL; } // // Copy data // if (DataToAdd || NulBytesToAdd) { Data = FAST_MALLOC (TotalSize); if (!Data) { GrowList->ListArray.End = OldEnd; DEBUGMSG ((DBG_WARNING, "GrowList: Could not allocate data block")); return NULL; } if (DataToAdd) { CopyMemory (Data, DataToAdd, SizeOfData); } if (NulBytesToAdd) { ZeroMemory (Data + SizeOfData, NulBytesToAdd); } } else { Data = NULL; } // // Adjust array // Size = GlGetSize (GrowList); if (InsertBefore >= Size) { // // Append mode // *Item = Data; } else { // // Insert mode // InsertAt = (PBYTE *) (GrowList->ListArray.Buf) + InsertBefore; MoveMemory (&InsertAt[1], InsertAt, (Size - InsertBefore) * sizeof (PBYTE)); *InsertAt = Data; } return Data ? Data : (PBYTE) 1; } VOID GlFree ( IN PGROWLIST GrowList ) /*++ Routine Description: GlFree frees the resources allocated by a GROWLIST. Arguments: GrowList - Specifies the list to clean up Return Value: none --*/ { if (!GrowList) { return; } GlReset (GrowList); GbFree (&GrowList->ListArray); ZeroMemory (GrowList, sizeof (GROWLIST)); } VOID GlReset ( IN OUT PGROWLIST GrowList ) /*++ Routine Description: GlReset empties the grow list but does not destroy the index buffer or pool. It is used to efficiently reuse a list. Arguments: GrowList - Specifies the list to clean up Return Value: none --*/ { UINT u; UINT count; PBYTE *dataPtr; if (!GrowList) { MYASSERT (FALSE); return; } count = GlGetSize (GrowList); dataPtr = (PBYTE *) (GrowList->ListArray.Buf); for (u = 0 ; u < count ; u++) { FAST_FREE (dataPtr[u]); } GrowList->ListArray.End = 0; } PBYTE GlGetItem ( IN PGROWLIST GrowList, IN UINT Index ) /*++ Routine Description: GlGetItem returns a pointer to the block of data for item specified by Index. Arguments: GrowList - Specifies the list to access Index - Specifies zero-based index of item in list to access Return Value: A pointer to the item's data, or NULL if the Index does not represent an actual item. --*/ { PBYTE *ItemPtr; UINT Size; Size = GlGetSize (GrowList); if (Index >= Size) { return NULL; } ItemPtr = (PBYTE *) (GrowList->ListArray.Buf); MYASSERT(ItemPtr); return ItemPtr[Index]; } UINT GlGetSize ( IN PGROWLIST GrowList ) /*++ Routine Description: GlGetSize calculates the number of items in the list. Arguments: GrowList - Specifies the list to calculate the size of Return Value: The number of items in the list, or zero if the list is empty. --*/ { return GrowList->ListArray.End / sizeof (PBYTE); } PBYTE RealGlAppend ( IN OUT PGROWLIST GrowList, IN PBYTE DataToAppend, OPTIONAL IN UINT SizeOfData ) /*++ Routine Description: GlAppend appends a black of data as a new list item. Arguments: GrowList - Specifies the list to modify DataToAppend - Specifies a block of data to be copied SizeOfData - Specifies the number of bytes in DataToAppend Return Value: A pointer to the binary block if data was copied into the list, 1 if a list item was created but no data was set for the item, or NULL if an error occurred. --*/ { return pGlAdd (GrowList, INSERT_LAST, DataToAppend, SizeOfData, 0); } PBYTE RealGlAppendAddNul ( IN OUT PGROWLIST GrowList, IN PBYTE DataToAppend, OPTIONAL IN UINT SizeOfData ) /*++ Routine Description: GlAppend appends a black of data as a new list item and appends two zero bytes (used for string termination). Arguments: GrowList - Specifies the list to modify DataToAppend - Specifies a block of data to be copied SizeOfData - Specifies the number of bytes in DataToAppend Return Value: A pointer to the binary block if data was copied into the list, 1 if a list item was created but no data was set for the item, or NULL if an error occurred. --*/ { return pGlAdd (GrowList, INSERT_LAST, DataToAppend, SizeOfData, 2); } PBYTE RealGlInsert ( IN OUT PGROWLIST GrowList, IN UINT Index, IN PBYTE DataToInsert, OPTIONAL IN UINT SizeOfData ) /*++ Routine Description: GlAppend inserts a black of data as a new list item, before the specified Index. Arguments: GrowList - Specifies the list to modify Index - Specifies the zero-based index of item to insert ahead of. DataToInsert - Specifies a block of data to be copied SizeOfData - Specifies the number of bytes in DataToInsert Return Value: A pointer to the binary block if data was copied into the list, 1 if a list item was created but no data was set for the item, or NULL if an error occurred. --*/ { UINT Size; Size = GlGetSize (GrowList); if (Index > Size) { return NULL; } return pGlAdd (GrowList, Index, DataToInsert, SizeOfData, 0); } PBYTE RealGlInsertAddNul ( IN OUT PGROWLIST GrowList, IN UINT Index, IN PBYTE DataToInsert, OPTIONAL IN UINT SizeOfData ) /*++ Routine Description: GlAppend inserts a block of data as a new list item, before the specified Index. Two zero bytes are appended to the block of data (used for string termination). Arguments: GrowList - Specifies the list to modify Index - Specifies the zero-based index of item to insert ahead of. DataToInsert - Specifies a block of data to be copied SizeOfData - Specifies the number of bytes in DataToInsert Return Value: A pointer to the binary block if data was copied into the list, 1 if a list item was created but no data was set for the item, or NULL if an error occurred. --*/ { UINT Size; Size = GlGetSize (GrowList); if (Index > Size) { return NULL; } return pGlAdd (GrowList, Index, DataToInsert, SizeOfData, 2); } BOOL GlDeleteItem ( IN OUT PGROWLIST GrowList, IN UINT Index ) /*++ Routine Description: GlDeleteItem removes an item from the list. Arguments: GrowList - Specifies the list to modify Index - Specifies the zero-based index of the item to remove. Return Value: TRUE if the data block was removed from the list, or FALSE if Index is invalid. --*/ { UINT Size; PBYTE *DeleteAt; Size = GlGetSize (GrowList); if (Size <= Index) { return FALSE; } DeleteAt = (PBYTE *) (GrowList->ListArray.Buf) + Index; if (*DeleteAt) { FAST_FREE (*DeleteAt); } Size--; if (Size > Index) { MoveMemory (DeleteAt, &DeleteAt[1], (Size - Index) * sizeof (PBYTE)); } GrowList->ListArray.End = Size * sizeof (PBYTE); return TRUE; } BOOL GlResetItem ( IN OUT PGROWLIST GrowList, IN UINT Index ) /*++ Routine Description: GlResetItem sets the list pointer of the specified item to NULL, freeing the memory associated with the item's data. Arguments: GrowList - Specifies the list to modify Index - Specifies the zero-based index of the item to reset. Return Value: TRUE if the data block was freed and the list element was nulled, or FALSE if Index is invalid. --*/ { UINT Size; PBYTE *ResetAt; Size = GlGetSize (GrowList); if (Size <= Index) { return FALSE; } ResetAt = (PBYTE *) (GrowList->ListArray.Buf) + Index; if (*ResetAt) { FAST_FREE (*ResetAt); } *ResetAt = NULL; return TRUE; } PBYTE RealGlSetItem ( IN OUT PGROWLIST GrowList, IN UINT Index, IN PCBYTE DataToCopy, IN UINT DataSize ) /*++ Routine Description: GlSetItem replaces the data associated with a list item. Arguments: GrowList - Specifies the list to modify Index - Specifies the zero-based index of the item to remove. DataToCopy - Specifies data to associate with the list item DataSize - Specifies the size of Data Return Value: A pointer to the binary block if data was copied into the list, 1 if a list item was created but no data was set for the item, or NULL if an error occurred. --*/ { UINT Size; PBYTE *ReplaceAt; PBYTE Data; MYASSERT (DataSize || !DataToCopy); Size = GlGetSize (GrowList); if (Size <= Index) { return NULL; } // // Copy data // if (DataToCopy) { Data = FAST_MALLOC (DataSize); if (!Data) { DEBUGMSG ((DBG_WARNING, "GrowList: Could not allocate data block (2)")); return NULL; } CopyMemory (Data, DataToCopy, DataSize); } else { Data = NULL; } // // Update list pointer // ReplaceAt = (PBYTE *) (GrowList->ListArray.Buf) + Index; if (*ReplaceAt) { FAST_FREE (*ReplaceAt); } *ReplaceAt = Data; return Data ? Data : (PBYTE) 1; }