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.

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