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.

353 lines
8.7 KiB

  1. /*****************************************************************************\
  2. * MODULE: mem.c
  3. *
  4. * Memory management routines. These routines provide head/tail checking
  5. * to verify memory corruption problems.
  6. *
  7. *
  8. * Copyright (C) 1996-1997 Microsoft Corporation
  9. * Copyright (C) 1996-1997 Hewlett Packard
  10. *
  11. * History:
  12. * 07-Oct-1996 HWP-Guys Initiated port from win95 to winNT
  13. *
  14. \*****************************************************************************/
  15. #include "precomp.h"
  16. #include "priv.h"
  17. /*********************************************************** local routine ***\
  18. * mem_HeadPtr
  19. *
  20. * Returns the pointer to the head-block. This needs to decrement enough
  21. * to account for the extra information stored at the head.
  22. *
  23. \*****************************************************************************/
  24. _inline PMEMHEAD mem_HeadPtr(
  25. PVOID pvMem)
  26. {
  27. return (PMEMHEAD)(pvMem ? (((PBYTE)pvMem) - MEM_HEADSIZE) : NULL);
  28. }
  29. /*********************************************************** local routine ***\
  30. * mem_TailPtr
  31. *
  32. * Returns the pointer to the tail-block. This requires the aligned-size
  33. * to retrieve the offset.
  34. *
  35. \*****************************************************************************/
  36. _inline PMEMTAIL mem_TailPtr(
  37. PMEMHEAD pmh,
  38. DWORD cbAlign)
  39. {
  40. return (PMEMTAIL)((PBYTE)pmh + cbAlign - MEM_TAILSIZE);
  41. }
  42. #ifdef DEBUG
  43. PMEMHEAD g_pmHead = NULL;
  44. /*********************************************************** local routine ***\
  45. * mem_InsPtr
  46. *
  47. * Inserts the pointer into our list for tracking allocations.
  48. *
  49. \*****************************************************************************/
  50. _inline VOID mem_InsPtr(
  51. PMEMHEAD pmHead)
  52. {
  53. if (g_pmHead) {
  54. g_pmHead->pmPrev = pmHead;
  55. pmHead->pmNext = g_pmHead;
  56. } else {
  57. pmHead->pmNext = NULL;
  58. }
  59. g_pmHead = pmHead;
  60. }
  61. /*********************************************************** local routine ***\
  62. * mem_DelPtr
  63. *
  64. * Removes the pointer from our list of tracked allocations.
  65. |
  66. \*****************************************************************************/
  67. _inline VOID mem_DelPtr(
  68. PMEMHEAD pmHead)
  69. {
  70. PMEMHEAD pmPtr;
  71. if (pmHead->pmNext) {
  72. pmPtr = pmHead->pmNext;
  73. pmPtr->pmPrev = pmHead->pmPrev;
  74. }
  75. if (pmHead->pmPrev) {
  76. pmPtr = pmHead->pmPrev;
  77. pmPtr->pmNext = pmHead->pmNext;
  78. } else {
  79. g_pmHead = pmHead->pmNext;
  80. }
  81. }
  82. /*****************************************************************************\
  83. * _mem_validate (Local Routine)
  84. *
  85. * Checks memory blocks allocated by memAlloc. These blocks contain
  86. * debugging information that helps to check for pointer overruns and
  87. * underruns.
  88. *
  89. * Returns a pointer to the memory header. Otherwise, we return NULL.
  90. *
  91. \*****************************************************************************/
  92. PVOID _mem_validate(
  93. PVOID pvMem,
  94. UINT cbSize)
  95. {
  96. DWORD cbAlign;
  97. PMEMHEAD pmHead;
  98. PMEMTAIL pmTail;
  99. PMEMHEAD pmRet = NULL;
  100. // Retrieve the head-pointer.
  101. //
  102. if (pmHead = mem_HeadPtr(pvMem)) {
  103. // Calculate the "real" size of our allocated block and round it
  104. // up to an even number of DWORD blocks.
  105. //
  106. cbAlign = memAlignSize(cbSize + MEM_SIZE);
  107. // Get the tail location.
  108. //
  109. pmTail = mem_TailPtr(pmHead, cbAlign);
  110. // Compare the values that memAlloc stored at the beginning
  111. // and end of the block
  112. //
  113. if ((pmHead->cbSize == cbSize) && (pmTail->dwSignature == DEADBEEF))
  114. pmRet = pmHead;
  115. // Assert if errors.
  116. //
  117. DBG_ASSERT((pmHead->cbSize == cbSize), (TEXT("Err : _mem_validate: Bad Size at %08lX"), pvMem));
  118. DBG_ASSERT((pmTail->dwSignature == DEADBEEF), (TEXT("Err : _mem_validate: Block Corruption at %08lX"), pvMem));
  119. } else {
  120. DBG_MSG(DBG_LEV_ERROR, (TEXT("Err : _mem_validate: Bad Pointer")));
  121. }
  122. return pmRet;
  123. }
  124. #else
  125. /*********************************************************** local routine ***\
  126. * Non-Debug Mappings.
  127. *
  128. * On non-debug builds, we will just return the most efficient values.
  129. *
  130. \*****************************************************************************/
  131. #define mem_InsPtr(pmHead) {}
  132. #define mem_DelPtr(pmHead) {}
  133. #define _mem_validate(pvMem, cbSize) mem_HeadPtr(pvMem)
  134. #endif
  135. /*****************************************************************************\
  136. * memAlloc
  137. *
  138. *
  139. \*****************************************************************************/
  140. PVOID memAlloc(
  141. UINT cbSize)
  142. {
  143. PMEMHEAD pmHead;
  144. PMEMTAIL pmTail;
  145. DWORD cbAlign;
  146. // The size of this memory-block will include header-information. So,
  147. // we will add the header-size and align our memory on DWORD boundries.
  148. //
  149. cbAlign = memAlignSize(cbSize + MEM_SIZE);
  150. // Attempt to allocate the memory. Proceed to setup
  151. // the memory block.
  152. //
  153. if (pmHead = (PMEMHEAD)GlobalAlloc(GPTR, cbAlign)) {
  154. pmTail = mem_TailPtr(pmHead, cbAlign);
  155. // Zero the memory-block so that we're dealing with
  156. // a clean contiguous array.
  157. //
  158. ZeroMemory((PVOID)pmHead, cbAlign);
  159. // Set up header/tail-information. This contains the requested
  160. // size of the memory-block. Increment the block so we return
  161. // the next available memory for the caller to use.
  162. //
  163. pmTail->dwSignature = DEADBEEF;
  164. pmHead->dwTag = 0;
  165. pmHead->cbSize = cbSize;
  166. pmHead->pmPrev = NULL;
  167. pmHead->pmNext = NULL;
  168. mem_InsPtr(pmHead);
  169. } else {
  170. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  171. }
  172. return (pmHead ? pmHead->pvMem : NULL);
  173. }
  174. /*****************************************************************************\
  175. * memFree
  176. *
  177. *
  178. \*****************************************************************************/
  179. BOOL memFree(
  180. PVOID pvMem,
  181. UINT cbSize)
  182. {
  183. PMEMHEAD pmHead;
  184. BOOL bRet = FALSE;
  185. // Try to at least make sure it's our memory and that no pointers have
  186. // gone astray in it.
  187. //
  188. if (pmHead = (PMEMHEAD) _mem_validate(pvMem, cbSize)) {
  189. mem_DelPtr(pmHead);
  190. bRet = (GlobalFree((PVOID)pmHead) == NULL);
  191. }
  192. return bRet;
  193. }
  194. /*****************************************************************************\
  195. * memCopy
  196. *
  197. * Copies a block of memory into a Win32 format buffer -- a structure at the
  198. * front of the buffer and strings packed into the end.
  199. *
  200. * On entry, *buf should point to the last available byte in the buffer.
  201. *
  202. \*****************************************************************************/
  203. VOID memCopy(
  204. PSTR *ppDst,
  205. PSTR pSrc,
  206. UINT cbSize,
  207. PSTR *ppBuf)
  208. {
  209. if (pSrc != NULL) {
  210. // Place bytes at end of buffer.
  211. //
  212. (*ppBuf) -= cbSize + 1;
  213. memcpy(*ppBuf, pSrc, cbSize);
  214. // Place buffer address in structure and save pointer to new
  215. // last available byte.
  216. //
  217. *ppDst = *ppBuf;
  218. (*ppBuf)--;
  219. } else {
  220. *ppDst = NULL;
  221. }
  222. }
  223. /*****************************************************************************\
  224. * memGetSize
  225. *
  226. * Returns the size of a block of memory that was allocated with memAlloc().
  227. *
  228. \*****************************************************************************/
  229. UINT memGetSize(
  230. PVOID pvMem)
  231. {
  232. PMEMHEAD pmHead;
  233. return ((pmHead = mem_HeadPtr(pvMem)) ? pmHead->cbSize : 0);
  234. }
  235. /*****************************************************************************\
  236. * memAllocStr
  237. *
  238. * Allocates local memory to store the specified string. This takes in a
  239. * (lpszStr) which is copied to the new memory.
  240. *
  241. \*****************************************************************************/
  242. PTSTR memAllocStr(
  243. LPCTSTR lpszStr)
  244. {
  245. PTSTR pMem = NULL;
  246. size_t uSize = 0;
  247. if (lpszStr == NULL)
  248. {
  249. return NULL;
  250. }
  251. uSize = utlStrSize(lpszStr);
  252. pMem = (PTSTR)memAlloc(uSize);
  253. if (pMem)
  254. {
  255. if (FAILED(StringCbCopy((LPTSTR)pMem, uSize, lpszStr)))
  256. {
  257. memFreeStr (pMem);
  258. pMem = NULL;
  259. }
  260. }
  261. return pMem;
  262. }
  263. /*****************************************************************************\
  264. * memFreeStr
  265. *
  266. * Frees the memory allocated by memAllocStr.
  267. *
  268. \*****************************************************************************/
  269. BOOL memFreeStr(
  270. PTSTR pszStr)
  271. {
  272. return memFree(pszStr, memGetSize(pszStr));
  273. }