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.

319 lines
7.3 KiB

  1. //
  2. //
  3. //
  4. // This file cannot be compiled as a C++ file, otherwise the linker
  5. // will bail on unresolved externals (even with extern "C" wrapping
  6. // this).
  7. #include "precomp.h"
  8. // Define some things for debug.h
  9. //
  10. #define SZ_DEBUGINI "ccshell.ini"
  11. #define SZ_DEBUGSECTION "deskcpl"
  12. #define SZ_MODULE "DESKCPL"
  13. #define DECLARE_DEBUG
  14. #include "debug.h"
  15. // Include the standard helper functions to dump common ADTs
  16. //#include "..\lib\dump.c"
  17. #ifdef DEBUG
  18. //
  19. // Typedefs
  20. //
  21. typedef struct _ALLOCHEADER {
  22. LIST_ENTRY ListEntry;
  23. PTCHAR File;
  24. ULONG Line;
  25. LONG AllocNumber;
  26. ULONG Size;
  27. } ALLOCHEADER, *PALLOCHEADER;
  28. //
  29. // Globals
  30. //
  31. LIST_ENTRY AllocListHead =
  32. {
  33. &AllocListHead,
  34. &AllocListHead
  35. };
  36. #undef LocalAlloc
  37. #undef LocalReAlloc
  38. #undef LocalFree
  39. INT g_BreakAtAlloc = -1;
  40. INT g_BreakAtFree = -1;
  41. ULONG g_AllocNumber = 0;
  42. #define TRAP() DbgBreakPoint()
  43. //*****************************************************************************
  44. //
  45. // MyAlloc()
  46. //
  47. //*****************************************************************************
  48. HLOCAL
  49. DeskAllocPrivate (
  50. const TCHAR *File,
  51. ULONG Line,
  52. ULONG Flags,
  53. DWORD dwBytes
  54. )
  55. {
  56. static ULONG allocNumber = 0;
  57. DWORD bytes;
  58. PALLOCHEADER header;
  59. if (dwBytes) {
  60. bytes = dwBytes + sizeof(ALLOCHEADER);
  61. header = (PALLOCHEADER)LocalAlloc(Flags, bytes);
  62. if (header != NULL) {
  63. InsertTailList(&AllocListHead, &header->ListEntry);
  64. header->File = (TCHAR*) File;
  65. header->Line = Line;
  66. header->AllocNumber = ++allocNumber;
  67. header->Size = dwBytes;
  68. if (header->AllocNumber == g_BreakAtAlloc) {
  69. // user set assert
  70. TRAP();
  71. }
  72. return (HLOCAL)(header + 1);
  73. }
  74. }
  75. return NULL;
  76. }
  77. //*****************************************************************************
  78. //
  79. // MyReAlloc()
  80. //
  81. //*****************************************************************************
  82. HLOCAL
  83. DeskReAllocPrivate (
  84. const TCHAR *File,
  85. ULONG Line,
  86. HLOCAL hMem,
  87. DWORD dwBytes,
  88. ULONG Flags
  89. )
  90. {
  91. PALLOCHEADER header;
  92. PALLOCHEADER headerNew;
  93. if (hMem)
  94. {
  95. header = (PALLOCHEADER)hMem;
  96. header--;
  97. // Remove the old address from the allocation list
  98. //
  99. RemoveEntryList(&header->ListEntry);
  100. headerNew = (PALLOCHEADER) LocalReAlloc((HLOCAL)header, dwBytes, Flags);
  101. if (headerNew != NULL)
  102. {
  103. // Add the new address to the allocation list
  104. //
  105. headerNew->File = (TCHAR*) File;
  106. headerNew->Line = Line;
  107. headerNew->AllocNumber = ++g_AllocNumber;
  108. headerNew->Size = dwBytes;
  109. if (headerNew->AllocNumber == g_BreakAtAlloc) {
  110. // user set assert
  111. TRAP();
  112. }
  113. InsertTailList(&AllocListHead, &headerNew->ListEntry);
  114. return (HLOCAL)(headerNew + 1);
  115. }
  116. else
  117. {
  118. // If GlobalReAlloc fails, the original memory is not freed,
  119. // and the original handle and pointer are still valid.
  120. // Add the old address back to the allocation list.
  121. //
  122. InsertTailList(&AllocListHead, &header->ListEntry);
  123. }
  124. }
  125. return NULL;
  126. }
  127. //*****************************************************************************
  128. //
  129. // MyFree()
  130. //
  131. //*****************************************************************************
  132. HLOCAL
  133. DeskFreePrivate (
  134. HLOCAL hMem
  135. )
  136. {
  137. PALLOCHEADER header;
  138. TCHAR buf[128];
  139. if (hMem)
  140. {
  141. header = (PALLOCHEADER)hMem;
  142. header--;
  143. if (header->AllocNumber == g_BreakAtFree) {
  144. TRAP();
  145. }
  146. wsprintf(buf, TEXT("free alloc number %d, size %d\r\n"),
  147. header->AllocNumber, header->Size);
  148. RemoveEntryList(&header->ListEntry);
  149. return LocalFree((HLOCAL)header);
  150. }
  151. return LocalFree(hMem);
  152. }
  153. HLOCAL DeskFreeDirect (HLOCAL hMem)
  154. {
  155. return(LocalFree(hMem));
  156. }
  157. //*****************************************************************************
  158. //
  159. // MyCheckForLeaks()
  160. //
  161. //*****************************************************************************
  162. VOID
  163. DeskCheckForLeaksPrivate (
  164. VOID
  165. )
  166. {
  167. PALLOCHEADER header;
  168. TCHAR buf[1024+40], tmpBuf[512];
  169. unsigned int i, size, size2, ic;
  170. DWORD *pdw;
  171. char *pch, *pch2;
  172. LPVOID mem;
  173. #if UNICODE
  174. #define DeskIsPrintable iswprint
  175. #else
  176. #define DeskIsPrintable isprint
  177. #endif
  178. while (!IsListEmpty(&AllocListHead))
  179. {
  180. header = (PALLOCHEADER)RemoveHeadList(&AllocListHead);
  181. mem = header + 1;
  182. wsprintf(buf, TEXT("Desk.cpl mem leak in File: %s\r\n Line: %d Size: %d Allocation: %d Buffer: 0x%x\r\n"),
  183. header->File, header->Line, header->Size, header->AllocNumber, mem);
  184. OutputDebugString(buf);
  185. //
  186. // easy stuff, print out all the 4 DWORDS we can
  187. //
  188. pdw = (DWORD *) mem;
  189. pch = (char *) mem;
  190. *buf = TEXT('\0');
  191. for (i = 0; i < header->Size/16; i++, pdw += 4) {
  192. wsprintf(tmpBuf, TEXT(" %08x %08x %08x %08x "),
  193. pdw[0], pdw[1], pdw[2], pdw[3]);
  194. lstrcat(buf, tmpBuf);
  195. for (ic = 0; ic < 16; ic++, pch++) {
  196. tmpBuf[ic] = DeskIsPrintable(*pch) ? *pch : TEXT('.');
  197. }
  198. tmpBuf[ic] = TEXT('\0');
  199. lstrcat(buf, tmpBuf);
  200. OutputDebugString(buf);
  201. OutputDebugString(TEXT("\n"));
  202. *buf = TEXT('\0');
  203. }
  204. //
  205. // Is there less than a 16 byte chunk left?
  206. //
  207. size = header->Size % 16;
  208. if (size) {
  209. //
  210. // Print all the DWORDs we can
  211. //
  212. for (i = 0; i < size / 4; i++, pdw++) {
  213. wsprintf(tmpBuf, TEXT(" %08x"), *pdw);
  214. lstrcat(buf, tmpBuf);
  215. }
  216. if (size % 4) {
  217. //
  218. // Print the remaining bytes
  219. //
  220. lstrcat(buf, TEXT(" "));
  221. pch2 = (char*) pdw;
  222. for (i = 0; i < size % 4; i++, pch2++) {
  223. wsprintf(tmpBuf, TEXT("%02x"), (DWORD) *pch2);
  224. lstrcat(buf, tmpBuf);
  225. }
  226. //
  227. // Align with 4 bytes
  228. //
  229. for ( ; i < 4; i++) {
  230. lstrcat(buf, TEXT(" "));
  231. }
  232. }
  233. //
  234. // Print blanks for any remaining DWORDs (ie to match the 4 above)
  235. //
  236. size2 = (16 - (header->Size % 16)) / 4;
  237. for (i = 0; i < size2; i++) {
  238. lstrcat(buf, TEXT(" "));
  239. }
  240. lstrcat(buf, TEXT(" "));
  241. //
  242. // Print the actual remain bytes as chars
  243. //
  244. for (i = 0; i < size; i++, pch++) {
  245. tmpBuf[i] = DeskIsPrintable(*pch) ? *pch : TEXT('.');
  246. }
  247. tmpBuf[i] = TEXT('\0');
  248. lstrcat(buf, tmpBuf);
  249. OutputDebugString(buf);
  250. OutputDebugString(TEXT("\n"));
  251. }
  252. OutputDebugString(TEXT("\n"));
  253. ASSERT(0);
  254. }
  255. }
  256. #endif