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.

717 lines
12 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. #ifdef DEBUG
  42. DWORD g_GbCurrActiveAlloc = 0;
  43. DWORD g_GbCurrUsedAlloc = 0;
  44. DWORD g_GbMaxActiveAlloc = 0;
  45. DWORD g_GbMaxUsedAlloc = 0;
  46. #endif
  47. //
  48. // Macro expansion list
  49. //
  50. // None
  51. //
  52. // Private function prototypes
  53. //
  54. // None
  55. //
  56. // Macro expansion definition
  57. //
  58. // None
  59. //
  60. // Code
  61. //
  62. PBYTE
  63. RealGbGrow (
  64. IN OUT PGROWBUFFER GrowBuf,
  65. IN DWORD SpaceNeeded
  66. )
  67. /*++
  68. Routine Description:
  69. GrowBuffer makes sure there is enough bytes in the buffer
  70. to accomodate SpaceNeeded. It allocates an initial buffer
  71. when no buffer is allocated, and it reallocates the buffer
  72. in increments of GrowBuf->Size (or DEFAULT_GROW_SIZE) when
  73. needed.
  74. Arguments:
  75. GrowBuf - A pointer to a GROWBUFFER structure.
  76. Initialize this structure to zero for
  77. the first call to GrowBuffer.
  78. SpaceNeeded - The number of free bytes needed in the buffer
  79. Return Value:
  80. A pointer to the SpaceNeeded bytes, or NULL if a memory allocation
  81. error occurred.
  82. --*/
  83. {
  84. PBYTE NewBuffer;
  85. DWORD TotalSpaceNeeded;
  86. DWORD GrowTo;
  87. MYASSERT(SpaceNeeded);
  88. if (!GrowBuf->Buf) {
  89. GrowBuf->Size = 0;
  90. GrowBuf->End = 0;
  91. #ifdef DEBUG
  92. GrowBuf->StatEnd = 0;
  93. #endif
  94. }
  95. if (!GrowBuf->GrowSize) {
  96. GrowBuf->GrowSize = DEFAULT_GROW_SIZE;
  97. }
  98. #ifdef DEBUG
  99. g_GbCurrActiveAlloc -= GrowBuf->Size;
  100. g_GbCurrUsedAlloc -= GrowBuf->StatEnd;
  101. #endif
  102. TotalSpaceNeeded = GrowBuf->End + SpaceNeeded;
  103. if (TotalSpaceNeeded > GrowBuf->Size) {
  104. GrowTo = (TotalSpaceNeeded + GrowBuf->GrowSize) - (TotalSpaceNeeded % GrowBuf->GrowSize);
  105. } else {
  106. GrowTo = 0;
  107. }
  108. if (!GrowBuf->Buf) {
  109. GrowBuf->Buf = (PBYTE) MemAlloc (g_hHeap, 0, GrowTo);
  110. if (!GrowBuf->Buf) {
  111. DEBUGMSG ((DBG_ERROR, "GbGrow: Initial alloc failed"));
  112. return NULL;
  113. }
  114. GrowBuf->Size = GrowTo;
  115. } else if (GrowTo) {
  116. NewBuffer = MemReAlloc (g_hHeap, 0, GrowBuf->Buf, GrowTo);
  117. if (!NewBuffer) {
  118. DEBUGMSG ((DBG_ERROR, "GbGrow: Realloc failed"));
  119. return NULL;
  120. }
  121. #ifdef DEBUG
  122. if (GrowBuf->Buf != NewBuffer) {
  123. DEBUGMSG ((
  124. DBG_WARNING,
  125. "GbGrow: Realloc caused growbuffer to move %u bytes to new location; "
  126. "any pointers inside old buffer are now invalid",
  127. GrowBuf->Size
  128. ));
  129. if (GrowBuf->Size > 32767) {
  130. TRACKDUMP();
  131. }
  132. }
  133. #endif
  134. GrowBuf->Size = GrowTo;
  135. GrowBuf->Buf = NewBuffer;
  136. }
  137. NewBuffer = GrowBuf->Buf + GrowBuf->End;
  138. GrowBuf->End += SpaceNeeded;
  139. #ifdef DEBUG
  140. GrowBuf->StatEnd = GrowBuf->End;
  141. g_GbCurrActiveAlloc += GrowBuf->Size;
  142. if (g_GbMaxActiveAlloc < g_GbCurrActiveAlloc) {
  143. g_GbMaxActiveAlloc = g_GbCurrActiveAlloc;
  144. }
  145. g_GbCurrUsedAlloc += GrowBuf->StatEnd;
  146. if (g_GbMaxUsedAlloc < g_GbCurrUsedAlloc) {
  147. g_GbMaxUsedAlloc = g_GbCurrUsedAlloc;
  148. }
  149. #endif
  150. return NewBuffer;
  151. }
  152. VOID
  153. GbFree (
  154. IN PGROWBUFFER GrowBuf
  155. )
  156. /*++
  157. Routine Description:
  158. FreeGrowBuffer frees a buffer allocated by GrowBuffer.
  159. Arguments:
  160. GrowBuf - A pointer to the same structure passed to GrowBuffer
  161. Return Value:
  162. none
  163. --*/
  164. {
  165. MYASSERT(GrowBuf);
  166. #ifdef DEBUG
  167. g_GbCurrActiveAlloc -= GrowBuf->Size;
  168. g_GbCurrUsedAlloc -= GrowBuf->StatEnd;
  169. #endif
  170. if (GrowBuf->Buf) {
  171. MemFree (g_hHeap, 0, GrowBuf->Buf);
  172. ZeroMemory (GrowBuf, sizeof (GROWBUFFER));
  173. }
  174. }
  175. /*++
  176. Routine Descriptions:
  177. MultiSzAppend
  178. This function is a general-purpose function to append a string
  179. to a grow buffer.
  180. MultiSzAppendVal
  181. This function adds a key=decimal_val string, where key is a
  182. specified string, and decimal_val is a specified DWORD.
  183. MultiSzAppendString
  184. This function adds key=string to the grow buffer, where key
  185. is a specified string, and string is a specified string value.
  186. Arguments:
  187. GrowBuf - The buffer to append the string or key/value pair
  188. Key - The key part of the key=val pair
  189. Val - The val part of the key=val pair
  190. Return Value:
  191. TRUE if the function succeeded, or FALSE if a memory allocation
  192. failure occurred.
  193. --*/
  194. BOOL
  195. RealGbMultiSzAppendA (
  196. PGROWBUFFER GrowBuf,
  197. PCSTR String
  198. )
  199. {
  200. PSTR p;
  201. p = (PSTR) GbGrow (GrowBuf, SizeOfStringA (String) + sizeof(CHAR));
  202. if (!p) {
  203. return FALSE;
  204. }
  205. StringCopyA (p, String);
  206. GrowBuf->End -= sizeof (CHAR);
  207. GrowBuf->Buf[GrowBuf->End] = 0;
  208. return TRUE;
  209. }
  210. BOOL
  211. RealGbMultiSzAppendValA (
  212. PGROWBUFFER GrowBuf,
  213. PCSTR Key,
  214. DWORD Val
  215. )
  216. {
  217. CHAR KeyValPair[256];
  218. wsprintfA (KeyValPair, "%s=%u", Key, Val);
  219. return GbMultiSzAppendA (GrowBuf, KeyValPair);
  220. }
  221. BOOL
  222. RealGbMultiSzAppendStringA (
  223. PGROWBUFFER GrowBuf,
  224. PCSTR Key,
  225. PCSTR Val
  226. )
  227. {
  228. CHAR KeyValPair[1024];
  229. wsprintfA (KeyValPair, "%s=%s", Key, Val);
  230. return GbMultiSzAppendA (GrowBuf, KeyValPair);
  231. }
  232. BOOL
  233. RealGbMultiSzAppendW (
  234. PGROWBUFFER GrowBuf,
  235. PCWSTR String
  236. )
  237. {
  238. PWSTR p;
  239. p = (PWSTR) GbGrow (GrowBuf, SizeOfStringW (String) + sizeof(WCHAR));
  240. if (!p) {
  241. return FALSE;
  242. }
  243. StringCopyW (p, String);
  244. GrowBuf->End -= sizeof (WCHAR);
  245. *((PWCHAR) (GrowBuf->Buf + GrowBuf->End)) = 0;
  246. return TRUE;
  247. }
  248. BOOL
  249. RealGbMultiSzAppendValW (
  250. PGROWBUFFER GrowBuf,
  251. PCWSTR Key,
  252. DWORD Val
  253. )
  254. {
  255. WCHAR KeyValPair[256];
  256. wsprintfW (KeyValPair, L"%s=%u", Key, Val);
  257. return GbMultiSzAppendW (GrowBuf, KeyValPair);
  258. }
  259. BOOL
  260. RealGbMultiSzAppendStringW (
  261. PGROWBUFFER GrowBuf,
  262. PCWSTR Key,
  263. PCWSTR Val
  264. )
  265. {
  266. WCHAR KeyValPair[1024];
  267. wsprintfW (KeyValPair, L"%s=%s", Key, Val);
  268. return GbMultiSzAppendW (GrowBuf, KeyValPair);
  269. }
  270. BOOL
  271. RealGbAppendDword (
  272. PGROWBUFFER GrowBuf,
  273. DWORD d
  274. )
  275. {
  276. PDWORD p;
  277. p = (PDWORD) GbGrow (GrowBuf, sizeof (DWORD));
  278. if (!p) {
  279. return FALSE;
  280. }
  281. *p = d;
  282. return TRUE;
  283. }
  284. BOOL
  285. RealGbAppendPvoid (
  286. PGROWBUFFER GrowBuf,
  287. PCVOID Ptr
  288. )
  289. {
  290. PCVOID *p;
  291. p = (PVOID *) GbGrow (GrowBuf, sizeof (PVOID));
  292. if (!p) {
  293. return FALSE;
  294. }
  295. *p = Ptr;
  296. return TRUE;
  297. }
  298. /*++
  299. Routine Description:
  300. GrowBufAppendString copies the specified string to the end of the grow
  301. buffer. This is the equivalent of strcat. The grow buffer is
  302. automatically expanded as necessary.
  303. Arguments:
  304. GrowBuf - Specifies the destination grow buffer
  305. String - Specifies the string to append
  306. Return Value:
  307. Always TRUE.
  308. --*/
  309. BOOL
  310. RealGbAppendStringA (
  311. IN OUT PGROWBUFFER GrowBuf,
  312. IN PCSTR String
  313. )
  314. {
  315. UINT OldEnd;
  316. PSTR p;
  317. UINT Bytes;
  318. if (String) {
  319. Bytes = SizeOfStringA (String);
  320. OldEnd = GrowBuf->End;
  321. if (OldEnd) {
  322. p = (PSTR) (GrowBuf->Buf + OldEnd - sizeof (CHAR));
  323. if (*p == 0) {
  324. OldEnd -= sizeof (CHAR);
  325. }
  326. }
  327. RealGbGrow (GrowBuf, Bytes);
  328. p = (PSTR) (GrowBuf->Buf + OldEnd);
  329. StringCopyA (p, String);
  330. GrowBuf->End = OldEnd + Bytes;
  331. }
  332. return TRUE;
  333. }
  334. BOOL
  335. RealGbAppendStringW (
  336. IN OUT PGROWBUFFER GrowBuf,
  337. IN PCWSTR String
  338. )
  339. {
  340. UINT OldEnd;
  341. PWSTR p;
  342. UINT Bytes;
  343. if (String) {
  344. Bytes = SizeOfStringW (String);
  345. OldEnd = GrowBuf->End;
  346. if (OldEnd) {
  347. p = (PWSTR) (GrowBuf->Buf + OldEnd - sizeof (WCHAR));
  348. if (*p == 0) {
  349. OldEnd -= sizeof (WCHAR);
  350. }
  351. }
  352. RealGbGrow (GrowBuf, Bytes);
  353. p = (PWSTR) (GrowBuf->Buf + OldEnd);
  354. StringCopyW (p, String);
  355. GrowBuf->End = OldEnd + Bytes;
  356. }
  357. return TRUE;
  358. }
  359. /*++
  360. Routine Description:
  361. GrowBufAppendStringAB copies the specified string range to the
  362. end of the grow buffer. This concatenates the string to the
  363. existing buffer contents, and keeps the buffer terminated.
  364. Arguments:
  365. GrowBuf - Specifies the destination grow buffer
  366. Start - Specifies the start of string to append
  367. EndPlusOne - Specifies one logical character beyond the end of
  368. the string, and can point to a nul.
  369. Return Value:
  370. Always TRUE.
  371. --*/
  372. BOOL
  373. RealGbAppendStringABA (
  374. IN OUT PGROWBUFFER GrowBuf,
  375. IN PCSTR Start,
  376. IN PCSTR EndPlusOne
  377. )
  378. {
  379. UINT OldEnd;
  380. PSTR p;
  381. UINT Bytes;
  382. if (Start && Start < EndPlusOne) {
  383. Bytes = (UINT)((UBINT) EndPlusOne - (UBINT) Start);
  384. OldEnd = GrowBuf->End;
  385. if (OldEnd) {
  386. p = (PSTR) (GrowBuf->Buf + OldEnd - sizeof (CHAR));
  387. if (*p == 0) {
  388. OldEnd -= sizeof (CHAR);
  389. }
  390. }
  391. RealGbGrow (GrowBuf, Bytes + sizeof (CHAR));
  392. p = (PSTR) (GrowBuf->Buf + OldEnd);
  393. CopyMemory (p, Start, Bytes);
  394. p = (PSTR) ((PBYTE) p + Bytes);
  395. *p = 0;
  396. GrowBuf->End = OldEnd + Bytes + sizeof (CHAR);
  397. }
  398. return TRUE;
  399. }
  400. BOOL
  401. RealGbAppendStringABW (
  402. IN OUT PGROWBUFFER GrowBuf,
  403. IN PCWSTR Start,
  404. IN PCWSTR EndPlusOne
  405. )
  406. {
  407. UINT OldEnd;
  408. PWSTR p;
  409. UINT Bytes;
  410. if (Start && Start < EndPlusOne) {
  411. Bytes = (UINT)((UBINT) EndPlusOne - (UBINT) Start);
  412. OldEnd = GrowBuf->End;
  413. if (OldEnd > sizeof (WCHAR)) {
  414. p = (PWSTR) (GrowBuf->Buf + OldEnd - sizeof (WCHAR));
  415. if (*p == 0) {
  416. OldEnd -= sizeof (WCHAR);
  417. }
  418. }
  419. RealGbGrow (GrowBuf, Bytes + sizeof (WCHAR));
  420. p = (PWSTR) (GrowBuf->Buf + OldEnd);
  421. CopyMemory (p, Start, Bytes);
  422. p = (PWSTR) ((PBYTE) p + Bytes);
  423. *p = 0;
  424. GrowBuf->End = OldEnd + Bytes + sizeof (WCHAR);
  425. }
  426. return TRUE;
  427. }
  428. /*++
  429. Routine Description:
  430. GrowBufCopyString copies the specified string to the end of the grow buffer.
  431. Arguments:
  432. GrowBuf - Specifies the grow buffer to add to, receives the updated buffer
  433. String - Specifies the string to add to GrowBuf
  434. Return Value:
  435. --*/
  436. BOOL
  437. RealGbCopyStringA (
  438. IN OUT PGROWBUFFER GrowBuf,
  439. IN PCSTR String
  440. )
  441. {
  442. PBYTE Buf;
  443. UINT Size;
  444. Size = SizeOfStringA (String);
  445. Buf = RealGbGrow (GrowBuf, Size);
  446. if (!Buf) {
  447. return FALSE;
  448. }
  449. CopyMemory (Buf, String, Size);
  450. return TRUE;
  451. }
  452. BOOL
  453. RealGbCopyStringW (
  454. IN OUT PGROWBUFFER GrowBuf,
  455. IN PCWSTR String
  456. )
  457. {
  458. PBYTE Buf;
  459. UINT Size;
  460. Size = SizeOfStringW (String);
  461. Buf = RealGbGrow (GrowBuf, Size);
  462. if (!Buf) {
  463. return FALSE;
  464. }
  465. CopyMemory (Buf, String, Size);
  466. return TRUE;
  467. }
  468. BOOL
  469. RealGbCopyQuotedStringA (
  470. IN OUT PGROWBUFFER GrowBuf,
  471. IN PCSTR String
  472. )
  473. {
  474. PBYTE Buf;
  475. UINT Size;
  476. Size = SizeOfStringA (String);
  477. Buf = RealGbGrow (GrowBuf, Size + 2 * sizeof (CHAR));
  478. if (!Buf) {
  479. return FALSE;
  480. }
  481. *((CHAR *)(Buf)) = '\"';
  482. CopyMemory (Buf + sizeof (CHAR), String, Size);
  483. *((CHAR *)(Buf + Size)) = '\"';
  484. *((CHAR *)(Buf + Size + sizeof (CHAR))) = 0;
  485. return TRUE;
  486. }
  487. BOOL
  488. RealGbCopyQuotedStringW (
  489. IN OUT PGROWBUFFER GrowBuf,
  490. IN PCWSTR String
  491. )
  492. {
  493. PBYTE Buf;
  494. UINT Size;
  495. Size = SizeOfStringW (String);
  496. Buf = RealGbGrow (GrowBuf, Size + 2 * sizeof (WCHAR));
  497. if (!Buf) {
  498. return FALSE;
  499. }
  500. *((WCHAR *)(Buf)) = L'\"';
  501. CopyMemory (Buf + sizeof (WCHAR), String, Size);
  502. *((WCHAR *)(Buf + Size)) = L'\"';
  503. *((WCHAR *)(Buf + Size + sizeof (WCHAR))) = 0;
  504. return TRUE;
  505. }
  506. #ifdef DEBUG
  507. VOID
  508. GbDumpStatistics (
  509. VOID
  510. )
  511. {
  512. DEBUGMSG ((
  513. DBG_STATS,
  514. "Grow buffers usage:\nPeak : Usable:%-8d Used:%-8d\nCurrent: Usable:%-8d Leak:%-8d",
  515. g_GbMaxActiveAlloc,
  516. g_GbMaxUsedAlloc,
  517. g_GbCurrActiveAlloc,
  518. g_GbCurrUsedAlloc
  519. ));
  520. }
  521. #endif