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.

384 lines
11 KiB

  1. //------------------------------------------------------------*
  2. // File name: DEBUG.C
  3. //
  4. // Description: Debug helper code for System control panel
  5. // applet
  6. //
  7. //
  8. // Microsoft Confidential
  9. // Copyright (c) Microsoft Corporation 1992-1996
  10. // All rights reserved
  11. //
  12. // History
  13. // 10-Nov-1996 JonPa Created it.
  14. //
  15. //------------------------------------------------------------*
  16. #include <windows.h>
  17. #include "debug.h"
  18. ///////////////////////////////////////////////////////////////
  19. // Constants
  20. ///////////////////////////////////////////////////////////////
  21. #ifdef DBG_CODE
  22. #define CCH_LABEL (sizeof(DWORD) * 2) // 64 BITS == 8 ANSI chars
  23. #define CB_TAG sizeof(DWORD)
  24. #define DW_TAG ((DWORD)(0x434C4143)) // 'CALC'
  25. #define DW_TAG2 ((DWORD)(0x444F4F47)) // 'GOOD'
  26. #define CH_FILL '*'
  27. ///////////////////////////////////////////////////////////////
  28. // Structures and Types
  29. ///////////////////////////////////////////////////////////////
  30. //
  31. // NOTE!!!!
  32. //
  33. // The HOBJHDR structure MUST be a multiple of 8 bytes (64bits) in len!
  34. // otherwise this code will *FAULT* on ALPHA machines!
  35. //
  36. typedef struct HHO *PHHO;
  37. struct HHO {
  38. PHHO phhoNext;
  39. PHHO phhoPrev;
  40. CHAR szFile[CCH_LABEL];
  41. DWORD iLine;
  42. DWORD cBytesData;
  43. DWORD dwTmp;
  44. DWORD dwTag2;
  45. };
  46. typedef struct HHO HOBJHDR;
  47. typedef struct {
  48. LPVOID pvPtr;
  49. CHAR szFile[CCH_LABEL];
  50. DWORD iLine;
  51. CHAR szFreedBy[CCH_LABEL];
  52. DWORD iLineFreed;
  53. } FREELOGREC, *PFREELOGREC;
  54. ///////////////////////////////////////////////////////////////
  55. // Global variables
  56. ///////////////////////////////////////////////////////////////
  57. //
  58. // Root of memory chain
  59. HOBJHDR ghhoRoot = { &ghhoRoot, &ghhoRoot, { 'R', 'O', 'O', 'T' }, 0, sizeof(ghhoRoot) };
  60. //
  61. // Buffer used for OutputDebugString formatting (See DbgPrintf and DbgStopX)
  62. TCHAR szDbgOutBuffer[1024];
  63. //
  64. // Buffer used for logging
  65. #define CFLR_MAX 1024
  66. FREELOGREC aflrFreeLog[CFLR_MAX];
  67. PFREELOGREC g_pflrUnused = NULL;
  68. #define NextFreeLogRec( pflr ) ((pflr >= &aflrFreeLog[CFLR_MAX-1]) ? aflrFreeLog : pflr+1)
  69. #define PrevFreeLogRec( pflr ) ((pflr <= aflrFreeLog) ? &aflrFreeLog[CFLR_MAX-1] : pflr-1)
  70. //---------------------------------------------------------------
  71. //
  72. // void DbgPrintf( LPTSTR szFmt, ... )
  73. //
  74. // Formatted version of OutputDebugString
  75. //
  76. // Parameters: Same as printf()
  77. //
  78. // History:
  79. // 18-Jan-1996 JonPa Wrote it
  80. //---------------------------------------------------------------
  81. void DbgPrintf( LPTSTR szFmt, ... ) {
  82. va_list marker;
  83. va_start( marker, szFmt );
  84. wvsprintf( szDbgOutBuffer, szFmt, marker );
  85. OutputDebugString( szDbgOutBuffer );
  86. va_end( marker );
  87. }
  88. //---------------------------------------------------------------
  89. //
  90. // void DbgStopX(LPSTR mszFile, int iLine, LPTSTR szText )
  91. //
  92. // Print a string (with location id) and then break
  93. //
  94. // Parameters:
  95. // mszFile ANSI filename (__FILE__)
  96. // iLine line number (__LINE__)
  97. // szText Text string to send to debug port
  98. //
  99. // History:
  100. // 18-Jan-1996 JonPa Wrote it
  101. //---------------------------------------------------------------
  102. void DbgStopX(LPSTR mszFile, int iLine, LPTSTR szText ) {
  103. int cch;
  104. wsprintf( szDbgOutBuffer, TEXT("RATPAK (%hs %d) : %s\n"), mszFile, iLine, szText );
  105. OutputDebugString(szDbgOutBuffer);
  106. DebugBreak();
  107. }
  108. //---------------------------------------------------------------
  109. //
  110. // void MemAllocWorker(LPSTR szFile, int iLine, UINT uFlags, UINT cBytes)
  111. //
  112. // Debug replacement for LocalAlloc
  113. //
  114. // Parameters:
  115. // mszFile ANSI filename (__FILE__)
  116. // iLine line number (__LINE__)
  117. // uFlags same as LocalAlloc
  118. // cBytes same as LocalAlloc
  119. //
  120. // History:
  121. // 18-Jan-1996 JonPa Wrote it
  122. //---------------------------------------------------------------
  123. HLOCAL MemAllocWorker(LPSTR szFile, int iLine, UINT uFlags, UINT cBytes) {
  124. PHHO phhoNew;
  125. HLOCAL hMem;
  126. LPSTR psz;
  127. UINT i, cBytesAlloc;
  128. cBytesAlloc = cBytes;
  129. //
  130. // If fixed alloc...
  131. //
  132. if ((uFlags & (LMEM_MOVEABLE | LMEM_DISCARDABLE)) != 0) {
  133. DBGSTOPX( szFile, iLine, "Attempting to allocate movable memory... Returning NULL");
  134. return NULL;
  135. }
  136. cBytesAlloc = cBytes + sizeof(HOBJHDR);
  137. // DWORD align Tag
  138. cBytesAlloc = ((cBytesAlloc + 3) & ~3);
  139. cBytesAlloc += CB_TAG;
  140. hMem = LocalAlloc( uFlags, cBytesAlloc );
  141. //
  142. // If a valid pointer, and it is a fixed pointer...
  143. //
  144. phhoNew = (PHHO)hMem;
  145. if (hMem != NULL) {
  146. phhoNew->phhoNext = ghhoRoot.phhoNext;
  147. ghhoRoot.phhoNext = phhoNew;
  148. phhoNew->phhoNext->phhoPrev = phhoNew;
  149. phhoNew->phhoPrev = &ghhoRoot;
  150. phhoNew->dwTag2 = DW_TAG2;
  151. for( psz = szFile; *psz != '\0'; psz++ );
  152. for( ; psz != szFile && *psz != ':' && *psz != '/' && *psz != '\\'; psz--);
  153. if (*psz == ':' || *psz == '/' || *psz == '\\')
  154. psz++;
  155. for( i = 0; i < CCH_LABEL; i++ ) {
  156. phhoNew->szFile[i] = *psz;
  157. if (*psz) {
  158. psz++;
  159. }
  160. }
  161. phhoNew->iLine = iLine;
  162. phhoNew->cBytesData = cBytes;
  163. phhoNew += 1; // point phhoNew to 1st byte after structure
  164. // round up to nearest DWORD
  165. { LPBYTE pb = (LPBYTE)phhoNew + cBytes;
  166. cBytesAlloc -= CB_TAG;
  167. cBytes += sizeof(HOBJHDR);
  168. while( cBytes < cBytesAlloc ) {
  169. *pb++ = CH_FILL;
  170. cBytes++;
  171. }
  172. *((LPDWORD)pb) = DW_TAG;
  173. }
  174. }
  175. return (HLOCAL)phhoNew;
  176. }
  177. //---------------------------------------------------------------
  178. //
  179. // void MemFreeWorker( LPSTR szFile, int iLine, HLOCAL hMem )
  180. //
  181. // Debug replacement for LocalFree
  182. //
  183. // Parameters:
  184. // mszFile ANSI filename (__FILE__)
  185. // iLine line number (__LINE__)
  186. // hMem same as LocalAlloc
  187. //
  188. // History:
  189. // 18-Jan-1996 JonPa Wrote it
  190. //---------------------------------------------------------------
  191. HLOCAL MemFreeWorker( LPSTR szFile, int iLine, HLOCAL hMem ) {
  192. PHHO phhoMem;
  193. UINT uFlags;
  194. UINT cBytes, cBytesAlloc;
  195. LPSTR psz;
  196. INT i;
  197. if (g_pflrUnused == NULL) {
  198. ZeroMemory( aflrFreeLog, sizeof(aflrFreeLog) );
  199. g_pflrUnused = aflrFreeLog;
  200. }
  201. if (hMem == NULL) {
  202. DBGSTOPX( szFile, iLine, "Freeing NULL handle!");
  203. return LocalFree(hMem);
  204. }
  205. phhoMem = (PHHO)hMem - 1;
  206. if (phhoMem->dwTag2 != DW_TAG2) {
  207. PFREELOGREC pflr;
  208. //
  209. // Our tag has been stompped on, see if we have already freed this object
  210. //
  211. for( pflr = PrevFreeLogRec(g_pflrUnused); pflr != g_pflrUnused; pflr = PrevFreeLogRec(pflr) ) {
  212. if (pflr->pvPtr == phhoMem) {
  213. DBGPRINTF((TEXT("RATPAK: Object may have already been freed by %.8hs line %d\n(that obj was allocated by %.8hs line %d)\n"),
  214. pflr->szFreedBy, pflr->iLineFreed, pflr->szFile, pflr->iLine));
  215. break;
  216. }
  217. }
  218. DBGPRINTF((TEXT("RATPAK: Trashed memory object (0x%X%08X) was allocated in %.8hs line %d (%d bytes)\n"), (DWORD)(((DWORDLONG)hMem) >> 32), PtrToUlong(hMem), phhoMem->szFile, phhoMem->iLine, phhoMem->cBytesData));
  219. DBGSTOPX( szFile, iLine, "Either heap object trashed or not allocated object");
  220. }
  221. cBytes = phhoMem->cBytesData;
  222. #if 0
  223. if (cBytes < 0) {
  224. // Not our object?
  225. DBGSTOPX( szFile, iLine, "Either heap object trashed or not allocated object");
  226. return LocalFree(hMem);
  227. }
  228. #endif
  229. cBytes += sizeof(HOBJHDR);
  230. // DWORD align
  231. cBytesAlloc = (cBytes + 3) & ~3;
  232. { LPBYTE pb = (LPBYTE)(phhoMem);
  233. pb += cBytes;
  234. while( cBytes < cBytesAlloc ) {
  235. if (*pb++ != CH_FILL) {
  236. DBGPRINTF((TEXT("RATPAK: Trashed memory object (0x%08X) was allocated in %.8hs line %d (%d bytes)\n"),
  237. hMem, phhoMem->szFile, phhoMem->iLine, phhoMem->cBytesData));
  238. DBGSTOPX( szFile, iLine, "End of structure overwritten");
  239. }
  240. cBytes++;
  241. }
  242. if (*((LPDWORD)pb) != DW_TAG) {
  243. DBGPRINTF((TEXT("RATPAK: Memory object (0x%08X) was not allocated!\n"), hMem));
  244. DBGSTOPX( szFile, iLine, "Freeing structure that was not allocated!");
  245. // Not our structure
  246. return LocalFree(hMem);
  247. }
  248. }
  249. // Our structure, check header
  250. if (phhoMem->phhoNext->phhoPrev != phhoMem || phhoMem->phhoPrev->phhoNext != phhoMem ) {
  251. DBGPRINTF((TEXT("RATPAK: Orphaned memory object (0x%08X) was allocated in %.8hs line %d (%d bytes)\n"),
  252. hMem, phhoMem->szFile, phhoMem->iLine, phhoMem->cBytesData));
  253. DBGSTOPX( szFile, iLine, "Attempting to free orphaned memory object");
  254. }
  255. phhoMem->phhoPrev->phhoNext = phhoMem->phhoNext;
  256. phhoMem->phhoNext->phhoPrev = phhoMem->phhoPrev;
  257. //
  258. // Log this free, incase we try and free it twice
  259. //
  260. // Mark as freed
  261. phhoMem->dwTag2 = 0;
  262. // Remember who alloc'ed obj
  263. g_pflrUnused->pvPtr = phhoMem;
  264. CopyMemory( g_pflrUnused->szFile, phhoMem->szFile, sizeof(g_pflrUnused->szFile) );
  265. g_pflrUnused->iLine = phhoMem->iLine;
  266. // Remember who freed the obj
  267. for( psz = szFile; *psz != '\0'; psz++ );
  268. for( ; psz != szFile && *psz != ':' && *psz != '/' && *psz != '\\'; psz--);
  269. if (*psz == ':' || *psz == '/' || *psz == '\\')
  270. psz++;
  271. for( i = 0; i < CCH_LABEL; i++ ) {
  272. g_pflrUnused->szFreedBy[i] = *psz;
  273. if (*psz) {
  274. psz++;
  275. }
  276. }
  277. g_pflrUnused->iLineFreed = iLine;
  278. // Point roaming ptr to next record and mark as unused
  279. g_pflrUnused = NextFreeLogRec(g_pflrUnused);
  280. ZeroMemory( g_pflrUnused, sizeof(*g_pflrUnused) );
  281. return LocalFree(phhoMem);
  282. }
  283. //---------------------------------------------------------------
  284. //
  285. // void MemExitCheckWorker() {
  286. //
  287. // Debug replacement for LocalFree
  288. //
  289. // Parameters:
  290. // mszFile ANSI filename (__FILE__)
  291. // iLine line number (__LINE__)
  292. // hMem same as LocalAlloc
  293. //
  294. // History:
  295. // 18-Jan-1996 JonPa Wrote it
  296. //---------------------------------------------------------------
  297. void MemExitCheckWorker( void ) {
  298. PHHO phho;
  299. for( phho = ghhoRoot.phhoNext; phho != &ghhoRoot; phho = phho->phhoNext ) {
  300. DBGPRINTF((TEXT("RATPAK: Exiting with out freeing object (Header=0x%08X) allocated in %.8hs line %d (%d bytes)\n"),
  301. phho, phho->szFile, phho->iLine, phho->cBytesData));
  302. }
  303. }
  304. #endif // DBG_CODE