Source code of Windows XP (NT5)
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.

611 lines
10 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. growbuf.c
  5. Abstract:
  6. Simple buffer management functions that allow variable blocks to
  7. be added as an array. (Initially used to build a SID array, where
  8. each SID can be a different size.)
  9. Author:
  10. Jim Schmidt (jimschm) 05-Feb-1997
  11. Revision History:
  12. marcw 2-Sep-1999 Moved over from Win9xUpg project.
  13. jimschm 11-Aug-1998 Added GrowBufAppendString
  14. calinn 15-Jan-1998 modified MultiSzAppend
  15. --*/
  16. #include "pch.h"
  17. //
  18. // Includes
  19. //
  20. // None
  21. #define DBG_GROWBUF "GrowBuffer"
  22. //
  23. // Strings
  24. //
  25. // None
  26. //
  27. // Constants
  28. //
  29. #define DEFAULT_GROW_SIZE 8192
  30. //
  31. // Macros
  32. //
  33. // None
  34. //
  35. // Types
  36. //
  37. // None
  38. //
  39. // Globals
  40. //
  41. // None
  42. //
  43. // Macro expansion list
  44. //
  45. // None
  46. //
  47. // Private function prototypes
  48. //
  49. // None
  50. //
  51. // Macro expansion definition
  52. //
  53. // None
  54. //
  55. // Code
  56. //
  57. PBYTE
  58. RealGbGrow (
  59. IN OUT PGROWBUFFER GrowBuf,
  60. IN DWORD SpaceNeeded
  61. )
  62. /*++
  63. Routine Description:
  64. GrowBuffer makes sure there is enough bytes in the buffer
  65. to accomodate SpaceNeeded. It allocates an initial buffer
  66. when no buffer is allocated, and it reallocates the buffer
  67. in increments of GrowBuf->Size (or DEFAULT_GROW_SIZE) when
  68. needed.
  69. Arguments:
  70. GrowBuf - A pointer to a GROWBUFFER structure.
  71. Initialize this structure to zero for
  72. the first call to GrowBuffer.
  73. SpaceNeeded - The number of free bytes needed in the buffer
  74. Return Value:
  75. A pointer to the SpaceNeeded bytes, or NULL if a memory allocation
  76. error occurred.
  77. --*/
  78. {
  79. PBYTE NewBuffer;
  80. DWORD TotalSpaceNeeded;
  81. DWORD GrowTo;
  82. MYASSERT(SpaceNeeded);
  83. if (!GrowBuf->Buf) {
  84. GrowBuf->Size = 0;
  85. GrowBuf->End = 0;
  86. }
  87. if (!GrowBuf->GrowSize) {
  88. GrowBuf->GrowSize = DEFAULT_GROW_SIZE;
  89. }
  90. TotalSpaceNeeded = GrowBuf->End + SpaceNeeded;
  91. if (TotalSpaceNeeded > GrowBuf->Size) {
  92. GrowTo = (TotalSpaceNeeded + GrowBuf->GrowSize) - (TotalSpaceNeeded % GrowBuf->GrowSize);
  93. } else {
  94. GrowTo = 0;
  95. }
  96. if (!GrowBuf->Buf) {
  97. GrowBuf->Buf = (PBYTE) MemAlloc (g_hHeap, 0, GrowTo);
  98. if (!GrowBuf->Buf) {
  99. DEBUGMSG ((DBG_ERROR, "GbGrow: Initial alloc failed"));
  100. return NULL;
  101. }
  102. GrowBuf->Size = GrowTo;
  103. } else if (GrowTo) {
  104. NewBuffer = MemReAlloc (g_hHeap, 0, GrowBuf->Buf, GrowTo);
  105. if (!NewBuffer) {
  106. DEBUGMSG ((DBG_ERROR, "GbGrow: Realloc failed"));
  107. return NULL;
  108. }
  109. DEBUGMSG_IF ((
  110. GrowBuf->Buf != NewBuffer,
  111. DBG_WARNING,
  112. "GbGrow: Realloc caused growbuffer to move location; "
  113. "any pointers inside old buffer are now invalid!"
  114. ));
  115. GrowBuf->Size = GrowTo;
  116. GrowBuf->Buf = NewBuffer;
  117. }
  118. NewBuffer = GrowBuf->Buf + GrowBuf->End;
  119. GrowBuf->End += SpaceNeeded;
  120. return NewBuffer;
  121. }
  122. VOID
  123. GbFree (
  124. IN PGROWBUFFER GrowBuf
  125. )
  126. /*++
  127. Routine Description:
  128. FreeGrowBuffer frees a buffer allocated by GrowBuffer.
  129. Arguments:
  130. GrowBuf - A pointer to the same structure passed to GrowBuffer
  131. Return Value:
  132. none
  133. --*/
  134. {
  135. MYASSERT(GrowBuf);
  136. if (GrowBuf->Buf) {
  137. MemFree (g_hHeap, 0, GrowBuf->Buf);
  138. ZeroMemory (GrowBuf, sizeof (GROWBUFFER));
  139. }
  140. }
  141. /*++
  142. Routine Descriptions:
  143. MultiSzAppend
  144. This function is a general-purpose function to append a string
  145. to a grow buffer.
  146. MultiSzAppendVal
  147. This function adds a key=decimal_val string, where key is a
  148. specified string, and decimal_val is a specified DWORD.
  149. MultiSzAppendString
  150. This function adds key=string to the grow buffer, where key
  151. is a specified string, and string is a specified string value.
  152. Arguments:
  153. GrowBuf - The buffer to append the string or key/value pair
  154. Key - The key part of the key=val pair
  155. Val - The val part of the key=val pair
  156. Return Value:
  157. TRUE if the function succeeded, or FALSE if a memory allocation
  158. failure occurred.
  159. --*/
  160. BOOL
  161. RealGbMultiSzAppendA (
  162. PGROWBUFFER GrowBuf,
  163. PCSTR String
  164. )
  165. {
  166. PSTR p;
  167. p = (PSTR) GbGrow (GrowBuf, SizeOfStringA (String) + sizeof(CHAR));
  168. if (!p) {
  169. return FALSE;
  170. }
  171. StringCopyA (p, String);
  172. GrowBuf->End -= sizeof (CHAR);
  173. GrowBuf->Buf[GrowBuf->End] = 0;
  174. return TRUE;
  175. }
  176. BOOL
  177. RealGbMultiSzAppendValA (
  178. PGROWBUFFER GrowBuf,
  179. PCSTR Key,
  180. DWORD Val
  181. )
  182. {
  183. CHAR KeyValPair[256];
  184. wsprintfA (KeyValPair, "%s=%u", Key, Val);
  185. return GbMultiSzAppendA (GrowBuf, KeyValPair);
  186. }
  187. BOOL
  188. RealGbMultiSzAppendStringA (
  189. PGROWBUFFER GrowBuf,
  190. PCSTR Key,
  191. PCSTR Val
  192. )
  193. {
  194. CHAR KeyValPair[1024];
  195. wsprintfA (KeyValPair, "%s=%s", Key, Val);
  196. return GbMultiSzAppendA (GrowBuf, KeyValPair);
  197. }
  198. BOOL
  199. RealGbMultiSzAppendW (
  200. PGROWBUFFER GrowBuf,
  201. PCWSTR String
  202. )
  203. {
  204. PWSTR p;
  205. p = (PWSTR) GbGrow (GrowBuf, SizeOfStringW (String) + sizeof(WCHAR));
  206. if (!p) {
  207. return FALSE;
  208. }
  209. StringCopyW (p, String);
  210. GrowBuf->End -= sizeof (WCHAR);
  211. *((PWCHAR) (GrowBuf->Buf + GrowBuf->End)) = 0;
  212. return TRUE;
  213. }
  214. BOOL
  215. RealGbMultiSzAppendValW (
  216. PGROWBUFFER GrowBuf,
  217. PCWSTR Key,
  218. DWORD Val
  219. )
  220. {
  221. WCHAR KeyValPair[256];
  222. wsprintfW (KeyValPair, L"%s=%u", Key, Val);
  223. return GbMultiSzAppendW (GrowBuf, KeyValPair);
  224. }
  225. BOOL
  226. RealGbMultiSzAppendStringW (
  227. PGROWBUFFER GrowBuf,
  228. PCWSTR Key,
  229. PCWSTR Val
  230. )
  231. {
  232. WCHAR KeyValPair[1024];
  233. wsprintfW (KeyValPair, L"%s=%s", Key, Val);
  234. return GbMultiSzAppendW (GrowBuf, KeyValPair);
  235. }
  236. BOOL
  237. RealGbAppendDword (
  238. PGROWBUFFER GrowBuf,
  239. DWORD d
  240. )
  241. {
  242. PDWORD p;
  243. p = (PDWORD) GbGrow (GrowBuf, sizeof (DWORD));
  244. if (!p) {
  245. return FALSE;
  246. }
  247. *p = d;
  248. return TRUE;
  249. }
  250. BOOL
  251. RealGbAppendPvoid (
  252. PGROWBUFFER GrowBuf,
  253. PCVOID Ptr
  254. )
  255. {
  256. PCVOID *p;
  257. p = (PVOID *) GbGrow (GrowBuf, sizeof (PVOID));
  258. if (!p) {
  259. return FALSE;
  260. }
  261. *p = Ptr;
  262. return TRUE;
  263. }
  264. /*++
  265. Routine Description:
  266. GrowBufAppendString copies the specified string to the end of the grow
  267. buffer. This is the equivalent of strcat. The grow buffer is
  268. automatically expanded as necessary.
  269. Arguments:
  270. GrowBuf - Specifies the destination grow buffer
  271. String - Specifies the string to append
  272. Return Value:
  273. Always TRUE.
  274. --*/
  275. BOOL
  276. RealGbAppendStringA (
  277. IN OUT PGROWBUFFER GrowBuf,
  278. IN PCSTR String
  279. )
  280. {
  281. UINT OldEnd;
  282. PSTR p;
  283. UINT Bytes;
  284. if (String) {
  285. Bytes = SizeOfStringA (String);
  286. OldEnd = GrowBuf->End;
  287. if (OldEnd) {
  288. p = (PSTR) (GrowBuf->Buf + OldEnd - sizeof (CHAR));
  289. if (*p == 0) {
  290. OldEnd -= sizeof (CHAR);
  291. }
  292. }
  293. RealGbGrow (GrowBuf, Bytes);
  294. p = (PSTR) (GrowBuf->Buf + OldEnd);
  295. StringCopyA (p, String);
  296. GrowBuf->End = OldEnd + Bytes;
  297. }
  298. return TRUE;
  299. }
  300. BOOL
  301. RealGbAppendStringW (
  302. IN OUT PGROWBUFFER GrowBuf,
  303. IN PCWSTR String
  304. )
  305. {
  306. UINT OldEnd;
  307. PWSTR p;
  308. UINT Bytes;
  309. if (String) {
  310. Bytes = SizeOfStringW (String);
  311. OldEnd = GrowBuf->End;
  312. if (OldEnd) {
  313. p = (PWSTR) (GrowBuf->Buf + OldEnd - sizeof (WCHAR));
  314. if (*p == 0) {
  315. OldEnd -= sizeof (WCHAR);
  316. }
  317. }
  318. RealGbGrow (GrowBuf, Bytes);
  319. p = (PWSTR) (GrowBuf->Buf + OldEnd);
  320. StringCopyW (p, String);
  321. GrowBuf->End = OldEnd + Bytes;
  322. }
  323. return TRUE;
  324. }
  325. /*++
  326. Routine Description:
  327. GrowBufAppendStringAB copies the specified string range to the
  328. end of the grow buffer. This concatenates the string to the
  329. existing buffer contents, and keeps the buffer terminated.
  330. Arguments:
  331. GrowBuf - Specifies the destination grow buffer
  332. Start - Specifies the start of string to append
  333. EndPlusOne - Specifies one logical character beyond the end of
  334. the string, and can point to a nul.
  335. Return Value:
  336. Always TRUE.
  337. --*/
  338. BOOL
  339. RealGbAppendStringABA (
  340. IN OUT PGROWBUFFER GrowBuf,
  341. IN PCSTR Start,
  342. IN PCSTR EndPlusOne
  343. )
  344. {
  345. UINT OldEnd;
  346. PSTR p;
  347. UINT Bytes;
  348. if (Start && Start < EndPlusOne) {
  349. Bytes = (UINT)((UBINT) EndPlusOne - (UBINT) Start);
  350. OldEnd = GrowBuf->End;
  351. if (OldEnd) {
  352. p = (PSTR) (GrowBuf->Buf + OldEnd - sizeof (CHAR));
  353. if (*p == 0) {
  354. OldEnd -= sizeof (CHAR);
  355. }
  356. }
  357. RealGbGrow (GrowBuf, Bytes + sizeof (CHAR));
  358. p = (PSTR) (GrowBuf->Buf + OldEnd);
  359. CopyMemory (p, Start, Bytes);
  360. p = (PSTR) ((PBYTE) p + Bytes);
  361. *p = 0;
  362. GrowBuf->End = OldEnd + Bytes + sizeof (CHAR);
  363. }
  364. return TRUE;
  365. }
  366. BOOL
  367. RealGbAppendStringABW (
  368. IN OUT PGROWBUFFER GrowBuf,
  369. IN PCWSTR Start,
  370. IN PCWSTR EndPlusOne
  371. )
  372. {
  373. UINT OldEnd;
  374. PWSTR p;
  375. UINT Bytes;
  376. if (Start && Start < EndPlusOne) {
  377. Bytes = (UINT)((UBINT) EndPlusOne - (UBINT) Start);
  378. OldEnd = GrowBuf->End;
  379. if (OldEnd > sizeof (WCHAR)) {
  380. p = (PWSTR) (GrowBuf->Buf + OldEnd - sizeof (WCHAR));
  381. if (*p == 0) {
  382. OldEnd -= sizeof (WCHAR);
  383. }
  384. }
  385. RealGbGrow (GrowBuf, Bytes + sizeof (WCHAR));
  386. p = (PWSTR) (GrowBuf->Buf + OldEnd);
  387. CopyMemory (p, Start, Bytes);
  388. p = (PWSTR) ((PBYTE) p + Bytes);
  389. *p = 0;
  390. GrowBuf->End = OldEnd + Bytes + sizeof (WCHAR);
  391. }
  392. return TRUE;
  393. }
  394. /*++
  395. Routine Description:
  396. GrowBufCopyString copies the specified string to the end of the grow buffer.
  397. Arguments:
  398. GrowBuf - Specifies the grow buffer to add to, receives the updated buffer
  399. String - Specifies the string to add to GrowBuf
  400. Return Value:
  401. --*/
  402. BOOL
  403. RealGbCopyStringA (
  404. IN OUT PGROWBUFFER GrowBuf,
  405. IN PCSTR String
  406. )
  407. {
  408. PBYTE Buf;
  409. UINT Size;
  410. Size = SizeOfStringA (String);
  411. Buf = RealGbGrow (GrowBuf, Size);
  412. if (!Buf) {
  413. return FALSE;
  414. }
  415. CopyMemory (Buf, String, Size);
  416. return TRUE;
  417. }
  418. BOOL
  419. RealGbCopyStringW (
  420. IN OUT PGROWBUFFER GrowBuf,
  421. IN PCWSTR String
  422. )
  423. {
  424. PBYTE Buf;
  425. UINT Size;
  426. Size = SizeOfStringW (String);
  427. Buf = RealGbGrow (GrowBuf, Size);
  428. if (!Buf) {
  429. return FALSE;
  430. }
  431. CopyMemory (Buf, String, Size);
  432. return TRUE;
  433. }