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.

299 lines
6.9 KiB

  1. /*****************************************************************************\
  2. * MODULE: genmem.c
  3. *
  4. * This module contains memory-management wrapper routines. These provide
  5. * debugging checks if needed.
  6. *
  7. * The blocks allocated with these routines include two DWORD entrys for
  8. * marking the head and tail of the allocation block. This is structured as
  9. * follows:
  10. *
  11. * DWORD cbSize DWORD
  12. * -------------------------------------------------
  13. * | Block Size | ...Alocated Memory... | DEADBEEF |
  14. * -------------------------------------------------
  15. * ^
  16. * |
  17. * Allocations return this pointer.
  18. *
  19. * routines
  20. * --------
  21. * genGAlloc
  22. * genGFree
  23. * genGRealloc
  24. * genGAllocStr
  25. * genGCopy
  26. * genGSize
  27. *
  28. *
  29. *
  30. * Copyright (C) 1996-1997 Microsoft Corporation
  31. * Copyright (C) 1996-1997 Hewlett Packard
  32. *
  33. * history:
  34. * 22-Nov-1996 <chriswil> created.
  35. *
  36. \*****************************************************************************/
  37. #include "pch.h"
  38. #ifdef DEBUG
  39. /*****************************************************************************\
  40. * mem_validate
  41. *
  42. * Checks the block of memory for any overwrites or size mismatches.
  43. *
  44. \*****************************************************************************/
  45. LPVOID gen_validate(
  46. PDWORD_PTR lpMem,
  47. DWORD cbSize)
  48. {
  49. DWORD cbNew;
  50. PDWORD_PTR lpTail;
  51. PDWORD_PTR lpHead;
  52. LPVOID lpRet = NULL;
  53. // Bad thing if a null-pointer is passed in.
  54. //
  55. if (lpMem != NULL) {
  56. // Reset the block to the true position.
  57. //
  58. lpHead = --lpMem;
  59. // Calculate the "real" size of our allocated block and round it
  60. // up to an even number of DWORD_PTR s.
  61. //
  62. cbNew = cbSize + (2 * sizeof(DWORD_PTR));
  63. if (cbNew & 7)
  64. cbNew += sizeof(DWORD_PTR) - (cbNew & 7);
  65. // Get the tail location.
  66. //
  67. lpTail = (DWORD_PTR)((LPBYTE)lpHead + cbNew - sizeof(DWORD_PTR));
  68. // Compare the values that memAlloc stored at the beginning
  69. // and end of the block
  70. //
  71. SPLASSERT(*lpHead == cbSize);
  72. SPLASSERT(*lpTail == DEADBEEF);
  73. lpRet = (LPVOID)lpHead;
  74. } else {
  75. DBGMSG(DBG_ERROR, ("gen_validate: Bad Pointer"));
  76. }
  77. return lpRet;
  78. }
  79. #else
  80. /*****************************************************************************\
  81. * gen_validate (Non-Debug)
  82. *
  83. * On non-debug builds, we will just return the head ptr.
  84. *
  85. \*****************************************************************************/
  86. _inline LPVOID gen_validate(
  87. PDWORD_PTR lpMem,
  88. DWORD cbSize)
  89. {
  90. if (lpMem) {
  91. lpMem--;
  92. return (LPVOID)lpMem;
  93. }
  94. return NULL;
  95. }
  96. #endif
  97. /*****************************************************************************\
  98. * genGAlloc
  99. *
  100. * Allocates a global-memory block. This allocation also includes a header
  101. * block which contains block-information. This allows for the tracking
  102. * of overwrites.
  103. *
  104. \*****************************************************************************/
  105. LPVOID genGAlloc(
  106. DWORD cbSize)
  107. {
  108. PDWORD_PTR lpMem;
  109. DWORD cbNew;
  110. // Give us a little room for debugging info and make sure that our
  111. // size in bytes results in a whole number of DWORDs.
  112. //
  113. cbNew = cbSize + (2 * sizeof(DWORD_PTR));
  114. // DWORD_PTR align the memory so that we can track the correct amount
  115. // of dword-allocations.
  116. //
  117. if (cbNew & 7)
  118. cbNew += sizeof(DWORD_PTR) - (cbNew & 7);
  119. // Attempt to allocate the memory.
  120. //
  121. if ((lpMem = (PDWORD_PTR)GlobalAlloc(GPTR, cbNew)) == NULL) {
  122. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  123. return NULL;
  124. }
  125. // Set up extra tracking information -- region size at the front
  126. // and an easily distinguishable constant at the back to help
  127. // us detect overwrites.
  128. //
  129. *lpMem = cbSize;
  130. *(PDWORD_PTR)((LPBYTE)lpMem + cbNew - sizeof(DWORD_PTR)) = DEADBEEF;
  131. return (LPVOID)(lpMem + 1);
  132. }
  133. /*****************************************************************************\
  134. * genGFree
  135. *
  136. * Free the memory allocated from genGAlloc. Validate the memory to see
  137. * if any bad-overwrites occured.
  138. *
  139. \*****************************************************************************/
  140. BOOL genGFree(
  141. LPVOID lpMem,
  142. DWORD cbSize)
  143. {
  144. LPVOID lpHead;
  145. BOOL bRet = FALSE;
  146. // Try to at least make sure it's our memory and that no pointers have
  147. // gone astray in it.
  148. //
  149. if (lpHead = gen_validate((PDWORD_PTR)lpMem, cbSize))
  150. bRet = (GlobalFree(lpHead) == NULL);
  151. return bRet;
  152. }
  153. /*****************************************************************************\
  154. * genGRealloc
  155. *
  156. * Reallocate the memory block. This allocates a new block, then copies
  157. * the information to the new-memory. The old one is freed.
  158. *
  159. \*****************************************************************************/
  160. PVOID genGRealloc(
  161. LPVOID lpMem,
  162. DWORD cbOldSize,
  163. DWORD cbNewSize)
  164. {
  165. LPVOID lpNew;
  166. if (lpNew = (LPVOID)genGAlloc(cbNewSize)) {
  167. memcpy(lpNew, lpMem, cbOldSize);
  168. genGFree(lpMem, cbOldSize);
  169. }
  170. return lpNew;
  171. }
  172. /*****************************************************************************\
  173. * genGAllocWStr
  174. *
  175. * Allocate and store a UNICODE string.
  176. *
  177. \*****************************************************************************/
  178. LPWSTR genGAllocWStr(
  179. LPCWSTR lpwszStr)
  180. {
  181. LPWSTR lpwszMem;
  182. if (lpwszStr == NULL)
  183. return NULL;
  184. if (lpwszMem = (LPWSTR)genGAlloc((lstrlen(lpwszStr) + 1) * sizeof(WCHAR)))
  185. lstrcpy(lpwszMem, lpwszStr);
  186. return lpwszMem;
  187. }
  188. /*****************************************************************************\
  189. * genGAllocStr
  190. *
  191. * Allocate and store a string.
  192. *
  193. \*****************************************************************************/
  194. LPTSTR genGAllocStr(
  195. LPCTSTR lpszStr)
  196. {
  197. LPTSTR lpszMem;
  198. if (lpszStr == NULL)
  199. return NULL;
  200. if (lpszMem = (LPTSTR)genGAlloc((lstrlen(lpszStr) + 1) * sizeof(TCHAR)))
  201. lstrcpy(lpszMem, lpszStr);
  202. return lpszMem;
  203. }
  204. /*****************************************************************************\
  205. * genGCopy
  206. *
  207. * Makes a copy of the memory pointed to by (lpSrc), and returns a new
  208. * allocated block.
  209. *
  210. \*****************************************************************************/
  211. LPVOID genGCopy(
  212. LPVOID lpSrc)
  213. {
  214. DWORD cbSize;
  215. LPVOID lpCpy = NULL;
  216. if ((lpSrc != NULL) && (cbSize = genGSize(lpSrc))) {
  217. if (lpCpy = genGAlloc(cbSize))
  218. memcpy(lpCpy, lpSrc, cbSize);
  219. }
  220. return lpCpy;
  221. }
  222. /*****************************************************************************\
  223. * genGSize
  224. *
  225. * Returns the size of the block alloced by genGAlloc().
  226. *
  227. \*****************************************************************************/
  228. DWORD genGSize(
  229. LPVOID lpMem)
  230. {
  231. PDWORD_PTR lpHead;
  232. if (lpHead = (PDWORD_PTR)lpMem)
  233. return (DWORD) *(--lpHead);
  234. return 0;
  235. }