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.

500 lines
11 KiB

  1. //
  2. // Copyright (c) Microsoft Corporation 1993-1995
  3. //
  4. // mem.c
  5. //
  6. // This file contains memory management and dynamic
  7. // array functions.
  8. //
  9. // History:
  10. // 09-27-94 ScottH Taken from commctrl
  11. // 04-29-95 ScottH Taken from briefcase and cleaned up
  12. //
  13. #include "proj.h"
  14. #include <rovcomm.h>
  15. #include <debugmem.h>
  16. #ifndef NOMEM
  17. //////////////////////////////////////////////////////////////////
  18. #ifdef WINNT
  19. /*----------------------------------------------------------
  20. Purpose: Wide-char version of SetStringA
  21. Returns: TRUE on success
  22. Cond: --
  23. */
  24. BOOL PUBLIC SetStringW(
  25. LPWSTR FAR * ppszBuf,
  26. LPCWSTR psz) // NULL to free *ppszBuf
  27. {
  28. BOOL bRet = FALSE;
  29. ASSERT(ppszBuf);
  30. // Free the buffer?
  31. if (!psz)
  32. {
  33. // Yes
  34. if (*ppszBuf)
  35. {
  36. FREE_MEMORY(*ppszBuf);
  37. *ppszBuf = NULL;
  38. }
  39. bRet = TRUE;
  40. }
  41. else
  42. {
  43. // No; (re)allocate and set buffer
  44. UINT cb = CbFromCchW(lstrlenW(psz)+1);
  45. if (*ppszBuf)
  46. {
  47. // Need to reallocate?
  48. if (cb > SIZE_OF_MEMORY(*ppszBuf))
  49. {
  50. // Yes
  51. LPWSTR pszT = (LPWSTR)REALLOCATE_MEMORY(*ppszBuf, cb );
  52. if (pszT)
  53. {
  54. *ppszBuf = pszT;
  55. bRet = TRUE;
  56. }
  57. }
  58. else
  59. {
  60. // No
  61. bRet = TRUE;
  62. }
  63. }
  64. else
  65. {
  66. *ppszBuf = (LPWSTR)ALLOCATE_MEMORY( cb);
  67. if (*ppszBuf)
  68. {
  69. bRet = TRUE;
  70. }
  71. }
  72. if (bRet)
  73. {
  74. ASSERT(*ppszBuf);
  75. lstrcpyW(*ppszBuf, psz);
  76. }
  77. }
  78. return bRet;
  79. }
  80. /*----------------------------------------------------------
  81. Purpose: Wide-char version of CatStringA
  82. Returns: TRUE on success
  83. Cond: --
  84. */
  85. BOOL
  86. PRIVATE
  87. MyCatStringW(
  88. IN OUT LPWSTR FAR * ppszBuf,
  89. IN LPCWSTR psz, OPTIONAL
  90. IN BOOL bMultiString)
  91. {
  92. BOOL bRet = FALSE;
  93. ASSERT(ppszBuf);
  94. // Free the buffer?
  95. if ( !psz )
  96. {
  97. // Yes
  98. if (*ppszBuf)
  99. {
  100. FREE_MEMORY(*ppszBuf);
  101. *ppszBuf = NULL;
  102. }
  103. bRet = TRUE;
  104. }
  105. else
  106. {
  107. // No; (re)allocate and set buffer
  108. LPWSTR pszBuf = *ppszBuf;
  109. UINT cch;
  110. cch = lstrlenW(psz) + 1; // account for null
  111. if (bMultiString)
  112. {
  113. cch++; // account for second null
  114. }
  115. if (pszBuf)
  116. {
  117. UINT cchExisting;
  118. LPWSTR pszT;
  119. // Figure out how much of the buffer has been used
  120. // Is this a multi-string (one with strings with a double-null
  121. // terminator)?
  122. if (bMultiString)
  123. {
  124. // Yes
  125. UINT cchT;
  126. cchExisting = 0;
  127. pszT = (LPWSTR)pszBuf;
  128. while (0 != *pszT)
  129. {
  130. cchT = lstrlenW(pszT) + 1;
  131. cchExisting += cchT;
  132. pszT += cchT;
  133. }
  134. }
  135. else
  136. {
  137. // No; (don't need to count null because it is already
  138. // counted in cch)
  139. cchExisting = lstrlenW(pszBuf);
  140. }
  141. // Need to reallocate?
  142. if (CbFromCchW(cch + cchExisting) > SIZE_OF_MEMORY(pszBuf))
  143. {
  144. // Yes; realloc at least MAX_BUF to cut down on the amount
  145. // of calls in the future
  146. cch = cchExisting + max(cch, MAX_BUF);
  147. pszT = (LPWSTR)REALLOCATE_MEMORY(pszBuf,
  148. CbFromCchW(cch));
  149. if (pszT)
  150. {
  151. pszBuf = pszT;
  152. *ppszBuf = pszBuf;
  153. bRet = TRUE;
  154. }
  155. }
  156. else
  157. {
  158. // No
  159. bRet = TRUE;
  160. }
  161. pszBuf += cchExisting;
  162. }
  163. else
  164. {
  165. cch = max(cch, MAX_BUF);
  166. pszBuf = (LPWSTR)ALLOCATE_MEMORY( CbFromCchW(cch));
  167. if (pszBuf)
  168. {
  169. bRet = TRUE;
  170. }
  171. *ppszBuf = pszBuf;
  172. }
  173. if (bRet)
  174. {
  175. ASSERT(pszBuf);
  176. lstrcpyW(pszBuf, psz);
  177. if (bMultiString)
  178. {
  179. pszBuf[lstrlenW(psz) + 1] = 0; // Add second null terminator
  180. }
  181. }
  182. }
  183. return bRet;
  184. }
  185. /*----------------------------------------------------------
  186. Purpose: Wide-char version of CatStringA
  187. Returns: TRUE on success
  188. Cond: --
  189. */
  190. BOOL
  191. PUBLIC
  192. CatStringW(
  193. IN OUT LPWSTR FAR * ppszBuf,
  194. IN LPCWSTR psz)
  195. {
  196. return MyCatStringW(ppszBuf, psz, FALSE);
  197. }
  198. /*----------------------------------------------------------
  199. Purpose: Wide-char version of CatMultiStringA
  200. Returns: TRUE on success
  201. Cond: --
  202. */
  203. BOOL
  204. PUBLIC
  205. CatMultiStringW(
  206. IN OUT LPWSTR FAR * ppszBuf,
  207. IN LPCWSTR psz)
  208. {
  209. return MyCatStringW(ppszBuf, psz, TRUE);
  210. }
  211. #endif // WINNT
  212. /*----------------------------------------------------------
  213. Purpose: Copies psz into *ppszBuf. Will alloc or realloc *ppszBuf
  214. accordingly.
  215. If psz is NULL, this function frees *ppszBuf. This is
  216. the preferred method of freeing the allocated buffer.
  217. Returns: TRUE on success
  218. Cond: --
  219. */
  220. BOOL PUBLIC SetStringA(
  221. LPSTR FAR * ppszBuf,
  222. LPCSTR psz) // NULL to free *ppszBuf
  223. {
  224. BOOL bRet = FALSE;
  225. ASSERT(ppszBuf);
  226. // Free the buffer?
  227. if (!psz)
  228. {
  229. // Yes
  230. if (ppszBuf)
  231. {
  232. FREE_MEMORY(*ppszBuf);
  233. *ppszBuf = NULL;
  234. }
  235. bRet = TRUE;
  236. }
  237. else
  238. {
  239. // No; (re)allocate and set buffer
  240. UINT cb = CbFromCchA(lstrlenA(psz)+1);
  241. if (*ppszBuf)
  242. {
  243. // Need to reallocate?
  244. if (cb > SIZE_OF_MEMORY(*ppszBuf))
  245. {
  246. // Yes
  247. LPSTR pszT = (LPSTR)REALLOCATE_MEMORY(*ppszBuf, cb);
  248. if (pszT)
  249. {
  250. *ppszBuf = pszT;
  251. bRet = TRUE;
  252. }
  253. }
  254. else
  255. {
  256. // No
  257. bRet = TRUE;
  258. }
  259. }
  260. else
  261. {
  262. *ppszBuf = (LPSTR)ALLOCATE_MEMORY( cb);
  263. if (*ppszBuf)
  264. {
  265. bRet = TRUE;
  266. }
  267. }
  268. if (bRet)
  269. {
  270. ASSERT(*ppszBuf);
  271. lstrcpyA(*ppszBuf, psz);
  272. }
  273. }
  274. return bRet;
  275. }
  276. /*----------------------------------------------------------
  277. Purpose: Concatenates psz onto *ppszBuf. Will alloc or
  278. realloc *ppszBuf accordingly.
  279. If bMultiString is TRUE, psz will be appended with
  280. a null terminator separating the existing string
  281. and new string. A double-null terminator will
  282. be tacked on the end, too.
  283. To free, call MyCatString(ppszBuf, NULL).
  284. Returns: TRUE on success
  285. Cond: --
  286. */
  287. BOOL
  288. PRIVATE
  289. MyCatStringA(
  290. IN OUT LPSTR FAR * ppszBuf,
  291. IN LPCSTR psz, OPTIONAL
  292. IN BOOL bMultiString)
  293. {
  294. BOOL bRet = FALSE;
  295. ASSERT(ppszBuf);
  296. // Free the buffer?
  297. if ( !psz )
  298. {
  299. // Yes
  300. if (*ppszBuf)
  301. {
  302. FREE_MEMORY(*ppszBuf);
  303. *ppszBuf = NULL;
  304. }
  305. bRet = TRUE;
  306. }
  307. else
  308. {
  309. // No; (re)allocate and set buffer
  310. LPSTR pszBuf = *ppszBuf;
  311. UINT cch;
  312. cch = lstrlenA(psz) + 1; // account for null
  313. if (bMultiString)
  314. {
  315. cch++; // account for second null
  316. }
  317. if (pszBuf)
  318. {
  319. UINT cchExisting;
  320. LPSTR pszT;
  321. // Figure out how much of the buffer has been used
  322. // Is this a multi-string (one with strings with a double-null
  323. // terminator)?
  324. if (bMultiString)
  325. {
  326. // Yes
  327. UINT cchT;
  328. cchExisting = 0;
  329. pszT = (LPSTR)pszBuf;
  330. while (0 != *pszT)
  331. {
  332. cchT = lstrlenA(pszT) + 1;
  333. cchExisting += cchT;
  334. pszT += cchT;
  335. }
  336. }
  337. else
  338. {
  339. // No; (don't need to count null because it is already
  340. // counted in cch)
  341. cchExisting = lstrlenA(pszBuf);
  342. }
  343. // Need to reallocate?
  344. if (CbFromCchA(cch + cchExisting) > SIZE_OF_MEMORY(pszBuf))
  345. {
  346. // Yes; realloc at least MAX_BUF to cut down on the amount
  347. // of calls in the future
  348. cch = cchExisting + max(cch, MAX_BUF);
  349. pszT = (LPSTR)REALLOCATE_MEMORY(pszBuf,
  350. CbFromCchA(cch));
  351. if (pszT)
  352. {
  353. pszBuf = pszT;
  354. *ppszBuf = pszBuf;
  355. bRet = TRUE;
  356. }
  357. }
  358. else
  359. {
  360. // No
  361. bRet = TRUE;
  362. }
  363. pszBuf += cchExisting;
  364. }
  365. else
  366. {
  367. cch = max(cch, MAX_BUF);
  368. pszBuf = (LPSTR)ALLOCATE_MEMORY( CbFromCchA(cch));
  369. if (pszBuf)
  370. {
  371. bRet = TRUE;
  372. }
  373. *ppszBuf = pszBuf;
  374. }
  375. if (bRet)
  376. {
  377. ASSERT(pszBuf);
  378. lstrcpyA(pszBuf, psz);
  379. if (bMultiString)
  380. {
  381. pszBuf[lstrlenA(psz) + 1] = 0; // Add second null terminator
  382. }
  383. }
  384. }
  385. return bRet;
  386. }
  387. /*----------------------------------------------------------
  388. Purpose: Concatenates psz onto *ppszBuf. Will alloc or
  389. realloc *ppszBuf accordingly.
  390. To free, call CatString(ppszBuf, NULL).
  391. Returns: TRUE on success
  392. Cond: --
  393. */
  394. BOOL
  395. PUBLIC
  396. CatStringA(
  397. IN OUT LPSTR FAR * ppszBuf,
  398. IN LPCSTR psz) OPTIONAL
  399. {
  400. return MyCatStringA(ppszBuf, psz, FALSE);
  401. }
  402. /*----------------------------------------------------------
  403. Purpose: Concatenates psz onto *ppszBuf. Will alloc or
  404. realloc *ppszBuf accordingly.
  405. psz will be appended with a null terminator separating
  406. the existing string and new string. A double-null
  407. terminator will be tacked on the end, too.
  408. To free, call CatMultiString(ppszBuf, NULL).
  409. Returns: TRUE on success
  410. Cond: --
  411. */
  412. BOOL
  413. PUBLIC
  414. CatMultiStringA(
  415. IN OUT LPSTR FAR * ppszBuf,
  416. IN LPCSTR psz)
  417. {
  418. return MyCatStringA(ppszBuf, psz, TRUE);
  419. }
  420. #endif // NOMEM