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.

422 lines
7.2 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. InitializeListHead(&ADsMemList) ;
  52. ADsMemCount = 0 ;
  53. }
  54. /*++
  55. Routine Description:
  56. This function asserts that the mem list is empty on exit.
  57. Arguments:
  58. None
  59. Return Value:
  60. None.
  61. --*/
  62. VOID AssertADsMemLeaks(
  63. VOID
  64. )
  65. {
  66. ADsAssert(IsListEmpty(&ADsMemList)) ;
  67. }
  68. #endif
  69. LPVOID
  70. AllocADsMem(
  71. DWORD cb
  72. )
  73. /*++
  74. Routine Description:
  75. This function will allocate local memory. It will possibly allocate extra
  76. memory and fill this with debugging information for the debugging version.
  77. Arguments:
  78. cb - The amount of memory to allocate
  79. Return Value:
  80. NON-NULL - A pointer to the allocated memory
  81. FALSE/NULL - The operation failed. Extended error status is available
  82. using GetLastError.
  83. --*/
  84. {
  85. #if DBG
  86. DWORD cbNew ;
  87. PADSMEMTAG pMem ;
  88. ULONG ulHash;
  89. //
  90. // adjust size for our tag and one spare dword at end
  91. // and allocate the memory
  92. //
  93. cb = DWORD_ALIGN_UP(cb);
  94. cbNew = cb + ( sizeof(ADSMEMTAG) + sizeof(DWORD) );
  95. pMem=(PADSMEMTAG)LocalAlloc(LPTR, cbNew);
  96. if (!pMem) {
  97. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  98. return 0;
  99. }
  100. //
  101. // fill in deadbeef at end and tag info.
  102. // and insert it into the ADsMemList
  103. //
  104. *(LPDWORD)((LPBYTE)pMem+cbNew-sizeof(DWORD)) = 0xdeadbeef;
  105. pMem->Tag = 0xB00FB00F ;
  106. pMem->Size = cb ;
  107. //
  108. // Capture a backtrace at this spot for debugging.
  109. //
  110. #if (defined(i386) && !defined(WIN95))
  111. pMem->uDepth = RtlCaptureStackBackTrace(
  112. 0,
  113. MAXDEPTH,
  114. pMem->pvBackTrace,
  115. &ulHash
  116. );
  117. #else
  118. pMem->uDepth = 0;
  119. #endif
  120. EnterCriticalSection(&ADsMemCritSect) ;
  121. InsertHeadList(&ADsMemList, &pMem->List) ;
  122. ADsMemCount++ ;
  123. LeaveCriticalSection(&ADsMemCritSect) ;
  124. //
  125. // skip past the mem tag
  126. //
  127. pMem++ ;
  128. return (LPVOID)(pMem);
  129. #else
  130. return(LocalAlloc(LPTR, cb));
  131. #endif
  132. }
  133. BOOL
  134. FreeADsMem(
  135. LPVOID pMem
  136. )
  137. {
  138. #if DBG
  139. DWORD cb;
  140. DWORD cbNew = 0;
  141. PADSMEMTAG pNewMem ;
  142. LPDWORD pRetAddr;
  143. DWORD i = 0;
  144. //
  145. // This apparently is a C++ requiremen - that you can call
  146. // delete on a null pointer and it should be handled
  147. //
  148. if (pMem == NULL) {
  149. return 0;
  150. }
  151. pNewMem = (PADSMEMTAG)pMem;
  152. pNewMem -- ;
  153. cb = pNewMem->Size;
  154. cbNew = cb + sizeof(DWORD) + sizeof(ADSMEMTAG);
  155. //
  156. // check the trailing deadbeef and remove from list
  157. //
  158. if (*(LPDWORD)(((LPBYTE)pNewMem) + cbNew - sizeof(DWORD)) != 0xdeadbeef) {
  159. ADsAssert(!"Freeing memory not allocated by AllocADsMem") ;
  160. return FALSE;
  161. }
  162. EnterCriticalSection(&ADsMemCritSect) ;
  163. RemoveEntryList(&pNewMem->List) ;
  164. ADsMemCount-- ;
  165. LeaveCriticalSection(&ADsMemCritSect) ;
  166. for (i = 0; i < pNewMem->uDepth; i++) {
  167. if (pNewMem->pszSymbol[i]) {
  168. LocalFree(pNewMem->pszSymbol[i]);
  169. }
  170. }
  171. //
  172. // Whack freed memory with known pattern
  173. //
  174. memset(pMem, 0x65, cb);
  175. return(LocalFree((LPVOID)pNewMem) == NULL);
  176. #else
  177. return(LocalFree(pMem) == NULL);
  178. #endif
  179. }
  180. LPVOID
  181. ReallocADsMem(
  182. LPVOID pOldMem,
  183. DWORD cbOld,
  184. DWORD cbNew
  185. )
  186. {
  187. LPVOID pNewMem;
  188. pNewMem=AllocADsMem(cbNew);
  189. if (pOldMem && pNewMem) {
  190. memcpy(pNewMem, pOldMem, min(cbNew, cbOld));
  191. FreeADsMem(pOldMem);
  192. }
  193. return pNewMem;
  194. }
  195. LPWSTR
  196. AllocADsStr(
  197. LPCWSTR pStr
  198. )
  199. /*++
  200. Routine Description:
  201. This function will allocate enough local memory to store the specified
  202. string, and copy that string to the allocated memory
  203. Arguments:
  204. pStr - Pointer to the string that needs to be allocated and stored
  205. Return Value:
  206. NON-NULL - A pointer to the allocated memory containing the string
  207. FALSE/NULL - The operation failed. Extended error status is available
  208. using GetLastError.
  209. --*/
  210. {
  211. LPWSTR pMem;
  212. if (!pStr)
  213. return 0;
  214. if (pMem = (LPWSTR)AllocADsMem( wcslen(pStr)*sizeof(WCHAR) + sizeof(WCHAR) ))
  215. wcscpy(pMem, pStr);
  216. return pMem;
  217. }
  218. BOOL
  219. FreeADsStr(
  220. LPWSTR pStr
  221. )
  222. {
  223. return pStr ? FreeADsMem(pStr)
  224. : FALSE;
  225. }
  226. BOOL
  227. ReallocADsStr(
  228. LPWSTR *ppStr,
  229. LPWSTR pStr
  230. )
  231. {
  232. if(!ppStr)
  233. {
  234. return FALSE;
  235. }
  236. FreeADsStr(*ppStr);
  237. *ppStr = NULL;
  238. *ppStr=AllocADsStr(pStr);
  239. if(!(*ppStr) && pStr)
  240. {
  241. return FALSE;
  242. }
  243. else
  244. {
  245. return TRUE;
  246. }
  247. }
  248. #if DBG
  249. VOID
  250. DumpMemoryTracker(
  251. VOID
  252. )
  253. {
  254. #if !defined(WIN95) && defined(_X86_)
  255. LIST_ENTRY* pEntry;
  256. ADSMEMTAG* pMem;
  257. BYTE* pTemp;
  258. DWORD i = 0;
  259. CHAR szSymbolPath[MAX_PATH+1];
  260. DWORD dwCount = 0;
  261. pEntry = ADsMemList.Flink;
  262. if (!dwMemoryLog) {
  263. return;
  264. }
  265. if ( pEntry == &ADsMemList ) {
  266. OutputDebugStringA( "No Memory leaks found\n" );
  267. }
  268. while( pEntry != &ADsMemList )
  269. {
  270. CHAR szLeak[1024];
  271. pTemp = (BYTE*)pEntry;
  272. pTemp = pTemp - sizeof(DWORD) - sizeof(DWORD)
  273. - sizeof(DWORD) -
  274. (sizeof(CHAR*) + sizeof(LPVOID))*( MAXDEPTH +1);
  275. pMem = (ADSMEMTAG*)pTemp;
  276. sprintf(
  277. szLeak,
  278. "[oleds] Memory leak!!! Addresss = %.8x Size = %ld \n",
  279. pMem + 1,
  280. pMem->Size
  281. );
  282. OutputDebugStringA( szLeak );
  283. for (i = 0; i < pMem->uDepth; i++) {
  284. dwCount = TranslateAddress(
  285. (ULONG)pMem->pvBackTrace[ i ],
  286. szSymbolPath,
  287. MAX_PATH
  288. );
  289. szSymbolPath[dwCount] = '\0';
  290. sprintf(szLeak, "%s\n",szSymbolPath);
  291. OutputDebugStringA( szLeak);
  292. }
  293. pEntry = pEntry->Flink;
  294. }
  295. #endif
  296. }
  297. #endif