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.

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