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.

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