Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

610 lines
12 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. growlist.c
  5. Abstract:
  6. Simple buffer management functions that maintenence of a list of binary
  7. objects.
  8. Author:
  9. 08-Aug-1997 jimschm Created
  10. Revision History:
  11. marcw 2-Sep-1999 Moved over from Win9xUpg project.
  12. --*/
  13. #include "pch.h"
  14. #define INSERT_LAST 0xffffffff
  15. PBYTE
  16. pGlAdd (
  17. IN OUT PGROWLIST GrowList,
  18. IN UINT InsertBefore,
  19. IN PBYTE DataToAdd, OPTIONAL
  20. IN UINT SizeOfData,
  21. IN UINT NulBytesToAdd
  22. )
  23. /*++
  24. Routine Description:
  25. pGlAdd allocates memory for a binary block by using a pool, and then expands
  26. an array of pointers, maintaining a quick-access list.
  27. Arguments:
  28. GrowList - Specifies the list to add the entry to
  29. InsertBefore - Specifies the index of the array element to insert
  30. before, or INSERT_LIST to append.
  31. DataToAdd - Specifies the binary block of data to add.
  32. SizeOfData - Specifies the size of data.
  33. NulBytesToAdd - Specifies the number of nul bytes to add to the buffer
  34. Return Value:
  35. A pointer to the binary block if data was copied into the list, 1 if a list
  36. item was created but no data was set for the item, or NULL if an error
  37. occurred.
  38. --*/
  39. {
  40. PBYTE *Item;
  41. PBYTE *InsertAt;
  42. PBYTE Data;
  43. UINT OldEnd;
  44. UINT Size;
  45. UINT TotalSize;
  46. TotalSize = SizeOfData + NulBytesToAdd;
  47. MYASSERT (TotalSize || !DataToAdd);
  48. //
  49. // Allocate pool if necessary
  50. //
  51. if (!GrowList->ListData) {
  52. GrowList->ListData = PmCreateNamedPool ("GrowList");
  53. if (!GrowList->ListData) {
  54. DEBUGMSG ((DBG_WARNING, "GrowList: Could not allocate pool"));
  55. return NULL;
  56. }
  57. PmDisableTracking (GrowList->ListData);
  58. }
  59. //
  60. // Expand list array
  61. //
  62. OldEnd = GrowList->ListArray.End;
  63. Item = (PBYTE *) GbGrow (&GrowList->ListArray, sizeof (PBYTE));
  64. if (!Item) {
  65. DEBUGMSG ((DBG_WARNING, "GrowList: Could not allocate array item"));
  66. return NULL;
  67. }
  68. //
  69. // Copy data
  70. //
  71. if (DataToAdd || NulBytesToAdd) {
  72. Data = PmGetAlignedMemory (GrowList->ListData, TotalSize);
  73. if (!Data) {
  74. GrowList->ListArray.End = OldEnd;
  75. DEBUGMSG ((DBG_WARNING, "GrowList: Could not allocate data block"));
  76. return NULL;
  77. }
  78. if (DataToAdd) {
  79. CopyMemory (Data, DataToAdd, SizeOfData);
  80. }
  81. if (NulBytesToAdd) {
  82. ZeroMemory (Data + SizeOfData, NulBytesToAdd);
  83. }
  84. } else {
  85. Data = NULL;
  86. }
  87. //
  88. // Adjust array
  89. //
  90. Size = GlGetSize (GrowList);
  91. if (InsertBefore >= Size) {
  92. //
  93. // Append mode
  94. //
  95. *Item = Data;
  96. } else {
  97. //
  98. // Insert mode
  99. //
  100. InsertAt = (PBYTE *) (GrowList->ListArray.Buf) + InsertBefore;
  101. MoveMemory (&InsertAt[1], InsertAt, (Size - InsertBefore) * sizeof (PBYTE));
  102. *InsertAt = Data;
  103. }
  104. return Data ? Data : (PBYTE) 1;
  105. }
  106. VOID
  107. GlFree (
  108. IN PGROWLIST GrowList
  109. )
  110. /*++
  111. Routine Description:
  112. GlFree frees the resources allocated by a GROWLIST.
  113. Arguments:
  114. GrowList - Specifies the list to clean up
  115. Return Value:
  116. none
  117. --*/
  118. {
  119. GbFree (&GrowList->ListArray);
  120. if (GrowList->ListData) {
  121. PmDestroyPool (GrowList->ListData);
  122. }
  123. ZeroMemory (GrowList, sizeof (GROWLIST));
  124. }
  125. VOID
  126. GlReset (
  127. IN OUT PGROWLIST GrowList
  128. )
  129. /*++
  130. Routine Description:
  131. GlReset empties the grow list but does not destroy the index buffer or pool.
  132. It is used to efficiently reuse a list.
  133. Arguments:
  134. GrowList - Specifies the list to clean up
  135. Return Value:
  136. none
  137. --*/
  138. {
  139. GrowList->ListArray.End = 0;;
  140. if (GrowList->ListData) {
  141. PmEmptyPool (GrowList->ListData);
  142. }
  143. }
  144. PBYTE
  145. GlGetItem (
  146. IN PGROWLIST GrowList,
  147. IN UINT Index
  148. )
  149. /*++
  150. Routine Description:
  151. GlGetItem returns a pointer to the block of data for item specified by
  152. Index.
  153. Arguments:
  154. GrowList - Specifies the list to access
  155. Index - Specifies zero-based index of item in list to access
  156. Return Value:
  157. A pointer to the item's data, or NULL if the Index does not
  158. represent an actual item.
  159. --*/
  160. {
  161. PBYTE *ItemPtr;
  162. UINT Size;
  163. Size = GlGetSize (GrowList);
  164. if (Index >= Size) {
  165. return NULL;
  166. }
  167. ItemPtr = (PBYTE *) (GrowList->ListArray.Buf);
  168. MYASSERT(ItemPtr);
  169. return ItemPtr[Index];
  170. }
  171. UINT
  172. GlGetSize (
  173. IN PGROWLIST GrowList
  174. )
  175. /*++
  176. Routine Description:
  177. GlGetSize calculates the number of items in the list.
  178. Arguments:
  179. GrowList - Specifies the list to calculate the size of
  180. Return Value:
  181. The number of items in the list, or zero if the list is empty.
  182. --*/
  183. {
  184. return GrowList->ListArray.End / sizeof (PBYTE);
  185. }
  186. PBYTE
  187. RealGlAppend (
  188. IN OUT PGROWLIST GrowList,
  189. IN PBYTE DataToAppend, OPTIONAL
  190. IN UINT SizeOfData
  191. )
  192. /*++
  193. Routine Description:
  194. GlAppend appends a black of data as a new list item.
  195. Arguments:
  196. GrowList - Specifies the list to modify
  197. DataToAppend - Specifies a block of data to be copied
  198. SizeOfData - Specifies the number of bytes in DataToAppend
  199. Return Value:
  200. A pointer to the binary block if data was copied into the list, 1 if a list
  201. item was created but no data was set for the item, or NULL if an error
  202. occurred.
  203. --*/
  204. {
  205. return pGlAdd (GrowList, INSERT_LAST, DataToAppend, SizeOfData, 0);
  206. }
  207. PBYTE
  208. RealGlAppendAddNul (
  209. IN OUT PGROWLIST GrowList,
  210. IN PBYTE DataToAppend, OPTIONAL
  211. IN UINT SizeOfData
  212. )
  213. /*++
  214. Routine Description:
  215. GlAppend appends a black of data as a new list item and appends two zero
  216. bytes (used for string termination).
  217. Arguments:
  218. GrowList - Specifies the list to modify
  219. DataToAppend - Specifies a block of data to be copied
  220. SizeOfData - Specifies the number of bytes in DataToAppend
  221. Return Value:
  222. A pointer to the binary block if data was copied into the list, 1 if a list
  223. item was created but no data was set for the item, or NULL if an error
  224. occurred.
  225. --*/
  226. {
  227. return pGlAdd (GrowList, INSERT_LAST, DataToAppend, SizeOfData, 2);
  228. }
  229. PBYTE
  230. RealGlInsert (
  231. IN OUT PGROWLIST GrowList,
  232. IN UINT Index,
  233. IN PBYTE DataToInsert, OPTIONAL
  234. IN UINT SizeOfData
  235. )
  236. /*++
  237. Routine Description:
  238. GlAppend inserts a black of data as a new list item, before the specified
  239. Index.
  240. Arguments:
  241. GrowList - Specifies the list to modify
  242. Index - Specifies the zero-based index of item to insert ahead of.
  243. DataToInsert - Specifies a block of data to be copied
  244. SizeOfData - Specifies the number of bytes in DataToInsert
  245. Return Value:
  246. A pointer to the binary block if data was copied into the list, 1 if a list
  247. item was created but no data was set for the item, or NULL if an error
  248. occurred.
  249. --*/
  250. {
  251. UINT Size;
  252. Size = GlGetSize (GrowList);
  253. if (Index > Size) {
  254. return NULL;
  255. }
  256. return pGlAdd (GrowList, Index, DataToInsert, SizeOfData, 0);
  257. }
  258. PBYTE
  259. RealGlInsertAddNul (
  260. IN OUT PGROWLIST GrowList,
  261. IN UINT Index,
  262. IN PBYTE DataToInsert, OPTIONAL
  263. IN UINT SizeOfData
  264. )
  265. /*++
  266. Routine Description:
  267. GlAppend inserts a block of data as a new list item, before the specified
  268. Index. Two zero bytes are appended to the block of data (used for string
  269. termination).
  270. Arguments:
  271. GrowList - Specifies the list to modify
  272. Index - Specifies the zero-based index of item to insert ahead of.
  273. DataToInsert - Specifies a block of data to be copied
  274. SizeOfData - Specifies the number of bytes in DataToInsert
  275. Return Value:
  276. A pointer to the binary block if data was copied into the list, 1 if a list
  277. item was created but no data was set for the item, or NULL if an error
  278. occurred.
  279. --*/
  280. {
  281. UINT Size;
  282. Size = GlGetSize (GrowList);
  283. if (Index > Size) {
  284. return NULL;
  285. }
  286. return pGlAdd (GrowList, Index, DataToInsert, SizeOfData, 2);
  287. }
  288. BOOL
  289. GlDeleteItem (
  290. IN OUT PGROWLIST GrowList,
  291. IN UINT Index
  292. )
  293. /*++
  294. Routine Description:
  295. GlDeleteItem removes an item from the list.
  296. Arguments:
  297. GrowList - Specifies the list to modify
  298. Index - Specifies the zero-based index of the item to remove.
  299. Return Value:
  300. TRUE if the data block was removed from the list, or FALSE if
  301. Index is invalid.
  302. --*/
  303. {
  304. UINT Size;
  305. PBYTE *DeleteAt;
  306. Size = GlGetSize (GrowList);
  307. if (Size <= Index) {
  308. return FALSE;
  309. }
  310. DeleteAt = (PBYTE *) (GrowList->ListArray.Buf) + Index;
  311. if (*DeleteAt) {
  312. PmReleaseMemory (GrowList->ListData, (PVOID) (*DeleteAt));
  313. }
  314. Size--;
  315. if (Size > Index) {
  316. MoveMemory (DeleteAt, &DeleteAt[1], (Size - Index) * sizeof (PBYTE));
  317. }
  318. GrowList->ListArray.End = Size * sizeof (PBYTE);
  319. return TRUE;
  320. }
  321. BOOL
  322. GlResetItem (
  323. IN OUT PGROWLIST GrowList,
  324. IN UINT Index
  325. )
  326. /*++
  327. Routine Description:
  328. GlResetItem sets the list pointer of the specified item to NULL, freeing the
  329. memory associated with the item's data.
  330. Arguments:
  331. GrowList - Specifies the list to modify
  332. Index - Specifies the zero-based index of the item to reset.
  333. Return Value:
  334. TRUE if the data block was freed and the list element was nulled,
  335. or FALSE if Index is invalid.
  336. --*/
  337. {
  338. UINT Size;
  339. PBYTE *ResetAt;
  340. Size = GlGetSize (GrowList);
  341. if (Size <= Index) {
  342. return FALSE;
  343. }
  344. ResetAt = (PBYTE *) (GrowList->ListArray.Buf) + Index;
  345. if (*ResetAt) {
  346. PmReleaseMemory (GrowList->ListData, (PVOID) (*ResetAt));
  347. }
  348. *ResetAt = NULL;
  349. return TRUE;
  350. }
  351. PBYTE
  352. RealGlSetItem (
  353. IN OUT PGROWLIST GrowList,
  354. IN UINT Index,
  355. IN PCBYTE DataToCopy,
  356. IN UINT DataSize
  357. )
  358. /*++
  359. Routine Description:
  360. GlSetItem replaces the data associated with a list item.
  361. Arguments:
  362. GrowList - Specifies the list to modify
  363. Index - Specifies the zero-based index of the item to remove.
  364. DataToCopy - Specifies data to associate with the list item
  365. DataSize - Specifies the size of Data
  366. Return Value:
  367. A pointer to the binary block if data was copied into the list, 1 if a list
  368. item was created but no data was set for the item, or NULL if an error
  369. occurred.
  370. --*/
  371. {
  372. UINT Size;
  373. PBYTE *ReplaceAt;
  374. PBYTE Data;
  375. MYASSERT (DataSize || !DataToCopy);
  376. Size = GlGetSize (GrowList);
  377. if (Size <= Index) {
  378. return NULL;
  379. }
  380. //
  381. // Copy data
  382. //
  383. if (DataToCopy) {
  384. Data = PmGetAlignedMemory (GrowList->ListData, DataSize);
  385. if (!Data) {
  386. DEBUGMSG ((DBG_WARNING, "GrowList: Could not allocate data block (2)"));
  387. return NULL;
  388. }
  389. CopyMemory (Data, DataToCopy, DataSize);
  390. } else {
  391. Data = NULL;
  392. }
  393. //
  394. // Update list pointer
  395. //
  396. ReplaceAt = (PBYTE *) (GrowList->ListArray.Buf) + Index;
  397. if (*ReplaceAt) {
  398. PmReleaseMemory (GrowList->ListData, (PVOID) (*ReplaceAt));
  399. }
  400. *ReplaceAt = Data;
  401. return Data ? Data : (PBYTE) 1;
  402. }