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.

408 lines
6.7 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. memory.c
  5. Abstract:
  6. This module provides all the memory management functions for all spooler
  7. components
  8. Author:
  9. Krishna Ganugapati (KrishnaG) 03-Feb-1994
  10. Revision History:
  11. --*/
  12. #include "dswarn.h"
  13. #include <nt.h>
  14. #include <ntrtl.h>
  15. #include <nturtl.h>
  16. #include <windows.h>
  17. #include <imagehlp.h>
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include "symhelp.h"
  21. #include "oledsdbg.h"
  22. #define WORD_ALIGN_DOWN(addr) ((LPBYTE)((DWORD)addr &= ~1))
  23. #define DWORD_ALIGN_UP(size) ((size+3)&~3)
  24. #if DBG
  25. DWORD dwMemoryLog = 0;
  26. #define MAXDEPTH 10
  27. typedef struct _ADSMEMTAG {
  28. DWORD Tag ;
  29. DWORD Size ;
  30. PVOID pvBackTrace[MAXDEPTH+1];
  31. LPSTR pszSymbol[MAXDEPTH+1];
  32. DWORD uDepth;
  33. LIST_ENTRY List ;
  34. } ADSMEMTAG, *PADSMEMTAG ;
  35. LIST_ENTRY ADsMemList ;
  36. DWORD ADsMemCount ;
  37. CRITICAL_SECTION ADsMemCritSect ;
  38. /*++
  39. Routine Description:
  40. This function initializes the ADs mem tracking code. Must be call
  41. during DLL load an ONLY during DLL load.
  42. Arguments:
  43. None
  44. Return Value:
  45. None.
  46. --*/
  47. VOID InitADsMem(
  48. VOID
  49. )
  50. {
  51. InitializeCriticalSection(&ADsMemCritSect) ;
  52. InitializeListHead(&ADsMemList) ;
  53. ADsMemCount = 0 ;
  54. }
  55. /*++
  56. Routine Description:
  57. This function asserts that the mem list is empty on exit.
  58. Arguments:
  59. None
  60. Return Value:
  61. None.
  62. --*/
  63. VOID AssertADsMemLeaks(
  64. VOID
  65. )
  66. {
  67. ADsAssert(IsListEmpty(&ADsMemList)) ;
  68. }
  69. #endif
  70. LPVOID
  71. AllocADsMem(
  72. DWORD cb
  73. )
  74. /*++
  75. Routine Description:
  76. This function will allocate local memory. It will possibly allocate extra
  77. memory and fill this with debugging information for the debugging version.
  78. Arguments:
  79. cb - The amount of memory to allocate
  80. Return Value:
  81. NON-NULL - A pointer to the allocated memory
  82. FALSE/NULL - The operation failed. Extended error status is available
  83. using GetLastError.
  84. --*/
  85. {
  86. #if DBG
  87. DWORD cbNew ;
  88. PADSMEMTAG pMem ;
  89. ULONG ulHash;
  90. //
  91. // adjust size for our tag and one spare dword at end
  92. // and allocate the memory
  93. //
  94. cb = DWORD_ALIGN_UP(cb);
  95. cbNew = cb + ( sizeof(ADSMEMTAG) + sizeof(DWORD) );
  96. pMem=(PADSMEMTAG)LocalAlloc(LPTR, cbNew);
  97. if (!pMem) {
  98. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  99. return 0;
  100. }
  101. //
  102. // fill in deadbeef at end and tag info.
  103. // and insert it into the ADsMemList
  104. //
  105. *(LPDWORD)((LPBYTE)pMem+cbNew-sizeof(DWORD)) = 0xdeadbeef;
  106. pMem->Tag = 0xB00FB00F ;
  107. pMem->Size = cb ;
  108. //
  109. // Capture a backtrace at this spot for debugging.
  110. //
  111. #if (defined(i386) && !defined(WIN95))
  112. pMem->uDepth = RtlCaptureStackBackTrace(
  113. 0,
  114. MAXDEPTH,
  115. pMem->pvBackTrace,
  116. &ulHash
  117. );
  118. #else
  119. pMem->uDepth = 0;
  120. #endif
  121. EnterCriticalSection(&ADsMemCritSect) ;
  122. InsertHeadList(&ADsMemList, &pMem->List) ;
  123. ADsMemCount++ ;
  124. LeaveCriticalSection(&ADsMemCritSect) ;
  125. //
  126. // skip past the mem tag
  127. //
  128. pMem++ ;
  129. return (LPVOID)(pMem);
  130. #else
  131. return(LocalAlloc(LPTR, cb));
  132. #endif
  133. }
  134. BOOL
  135. FreeADsMem(
  136. LPVOID pMem
  137. )
  138. {
  139. #if DBG
  140. DWORD cb;
  141. DWORD cbNew = 0;
  142. PADSMEMTAG pNewMem ;
  143. LPDWORD pRetAddr;
  144. DWORD i = 0;
  145. //
  146. // This apparently is a C++ requiremen - that you can call
  147. // delete on a null pointer and it should be handled
  148. //
  149. if (pMem == NULL) {
  150. return 0;
  151. }
  152. pNewMem = (PADSMEMTAG)pMem;
  153. pNewMem -- ;
  154. cb = pNewMem->Size;
  155. cbNew = cb + sizeof(DWORD) + sizeof(ADSMEMTAG);
  156. //
  157. // check the trailing deadbeef and remove from list
  158. //
  159. if (*(LPDWORD)(((LPBYTE)pNewMem) + cbNew - sizeof(DWORD)) != 0xdeadbeef) {
  160. ADsAssert(!"Freeing memory not allocated by AllocADsMem") ;
  161. return FALSE;
  162. }
  163. EnterCriticalSection(&ADsMemCritSect) ;
  164. RemoveEntryList(&pNewMem->List) ;
  165. ADsMemCount-- ;
  166. LeaveCriticalSection(&ADsMemCritSect) ;
  167. for (i = 0; i < pNewMem->uDepth; i++) {
  168. if (pNewMem->pszSymbol[i]) {
  169. LocalFree(pNewMem->pszSymbol[i]);
  170. }
  171. }
  172. //
  173. // Whack freed memory with known pattern
  174. //
  175. memset(pMem, 0x65, cb);
  176. return(LocalFree((LPVOID)pNewMem) == NULL);
  177. #else
  178. return(LocalFree(pMem) == NULL);
  179. #endif
  180. }
  181. LPVOID
  182. ReallocADsMem(
  183. LPVOID pOldMem,
  184. DWORD cbOld,
  185. DWORD cbNew
  186. )
  187. {
  188. LPVOID pNewMem;
  189. pNewMem=AllocADsMem(cbNew);
  190. if (pOldMem && pNewMem) {
  191. memcpy(pNewMem, pOldMem, min(cbNew, cbOld));
  192. FreeADsMem(pOldMem);
  193. }
  194. return pNewMem;
  195. }
  196. LPWSTR
  197. AllocADsStr(
  198. LPCWSTR pStr
  199. )
  200. /*++
  201. Routine Description:
  202. This function will allocate enough local memory to store the specified
  203. string, and copy that string to the allocated memory
  204. Arguments:
  205. pStr - Pointer to the string that needs to be allocated and stored
  206. Return Value:
  207. NON-NULL - A pointer to the allocated memory containing the string
  208. FALSE/NULL - The operation failed. Extended error status is available
  209. using GetLastError.
  210. --*/
  211. {
  212. LPWSTR pMem;
  213. if (!pStr)
  214. return 0;
  215. if (pMem = (LPWSTR)AllocADsMem( wcslen(pStr)*sizeof(WCHAR) + sizeof(WCHAR) ))
  216. wcscpy(pMem, pStr);
  217. return pMem;
  218. }
  219. BOOL
  220. FreeADsStr(
  221. LPWSTR pStr
  222. )
  223. {
  224. return pStr ? FreeADsMem(pStr)
  225. : FALSE;
  226. }
  227. BOOL
  228. ReallocADsStr(
  229. LPWSTR *ppStr,
  230. LPWSTR pStr
  231. )
  232. {
  233. FreeADsStr(*ppStr);
  234. *ppStr=AllocADsStr(pStr);
  235. return TRUE;
  236. }
  237. #if DBG
  238. VOID
  239. DumpMemoryTracker(
  240. VOID
  241. )
  242. {
  243. #if !defined(WIN95) && defined(_X86_)
  244. LIST_ENTRY* pEntry;
  245. ADSMEMTAG* pMem;
  246. BYTE* pTemp;
  247. DWORD i = 0;
  248. CHAR szSymbolPath[MAX_PATH+1];
  249. DWORD dwCount = 0;
  250. pEntry = ADsMemList.Flink;
  251. if (!dwMemoryLog) {
  252. return;
  253. }
  254. if ( pEntry == &ADsMemList ) {
  255. OutputDebugStringA( "No Memory leaks found\n" );
  256. }
  257. while( pEntry != &ADsMemList )
  258. {
  259. CHAR szLeak[1024];
  260. pTemp = (BYTE*)pEntry;
  261. pTemp = pTemp - sizeof(DWORD) - sizeof(DWORD)
  262. - sizeof(DWORD) -
  263. (sizeof(CHAR*) + sizeof(LPVOID))*( MAXDEPTH +1);
  264. pMem = (ADSMEMTAG*)pTemp;
  265. sprintf(
  266. szLeak,
  267. "[oleds] Memory leak!!! Addresss = %.8x Size = %ld \n",
  268. pMem + 1,
  269. pMem->Size
  270. );
  271. OutputDebugStringA( szLeak );
  272. for (i = 0; i < pMem->uDepth; i++) {
  273. dwCount = TranslateAddress(
  274. (ULONG)pMem->pvBackTrace[ i ],
  275. szSymbolPath,
  276. MAX_PATH
  277. );
  278. szSymbolPath[dwCount] = '\0';
  279. sprintf(szLeak, "%s\n",szSymbolPath);
  280. OutputDebugStringA( szLeak);
  281. }
  282. pEntry = pEntry->Flink;
  283. }
  284. #endif
  285. }
  286. #endif