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.

546 lines
12 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. imagehlp.c
  5. Abstract:
  6. This function implements a generic simple symbol handler.
  7. Author:
  8. Wesley Witt (wesw) 1-Sep-1994
  9. Environment:
  10. User Mode
  11. --*/
  12. #ifdef __cplusplus
  13. extern "C" {
  14. #endif
  15. #include <nt.h>
  16. #include <ntrtl.h>
  17. #include <nturtl.h>
  18. #ifdef __cplusplus
  19. }
  20. #endif
  21. #include "private.h"
  22. #include <globals.h>
  23. #define HEAP_SIZE 0x100000
  24. __inline BOOL tlsSetup(HMODULE hmod)
  25. {
  26. return TRUE;
  27. }
  28. __inline BOOL tlsAlloc()
  29. {
  30. g.tlsIndex = TlsAlloc();
  31. return (g.tlsIndex == (DWORD)-1) ? FALSE : TRUE;
  32. }
  33. __inline void tlsFree()
  34. {
  35. if (g.tlsIndex != (DWORD)-1)
  36. TlsFree(g.tlsIndex);
  37. }
  38. __inline void tlsMemFree()
  39. {
  40. PVOID ptls;
  41. ptls = TlsGetValue(g.tlsIndex);
  42. MemFree(ptls);
  43. }
  44. DWORD
  45. DllMain(
  46. HINSTANCE hInstance,
  47. DWORD Reason,
  48. LPVOID Context
  49. )
  50. /*++
  51. Routine Description:
  52. DLL initialization function.
  53. Arguments:
  54. hInstance - Instance handle
  55. Reason - Reason for the entrypoint being called
  56. Context - Context record
  57. Return Value:
  58. TRUE - Initialization succeeded
  59. FALSE - Initialization failed
  60. --*/
  61. {
  62. __try {
  63. switch (Reason)
  64. {
  65. case DLL_PROCESS_ATTACH:
  66. g.hinst = hInstance;
  67. g.OSVerInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  68. GetVersionEx(&g.OSVerInfo);
  69. InitializeCriticalSection(&g.threadlock);
  70. tlsSetup(hInstance);
  71. HeapInitList(&g.HeapHeader);
  72. g.hHeap = HeapCreate(0, HEAP_SIZE, 0);
  73. if (tlsAlloc() && g.hHeap)
  74. return TRUE;
  75. DeleteCriticalSection(&g.threadlock);
  76. return FALSE;
  77. case DLL_PROCESS_DETACH:
  78. tlsFree();
  79. HeapDump("DLL_PROCESS_DETACH\n");
  80. // If this is a process shutdown, don't bother to
  81. // kill the heap. The OS will do it for us. This
  82. // allows us to be called from other DLLs' DLLMain
  83. // DLL_PROCESS_DETACH handler.
  84. if ( !Context && g.hHeap )
  85. HeapDestroy( g.hHeap );
  86. DeleteCriticalSection(&g.threadlock);
  87. break;
  88. case DLL_THREAD_DETACH:
  89. tlsMemFree();
  90. break;
  91. }
  92. } __except(EXCEPTION_EXECUTE_HANDLER) {
  93. return FALSE;
  94. }
  95. return TRUE;
  96. }
  97. #ifdef IMAGEHLP_HEAP_DEBUG
  98. BOOL
  99. pCheckHeap(
  100. PVOID MemPtr,
  101. ULONG Line,
  102. LPSTR File
  103. )
  104. {
  105. CHAR buf[256];
  106. CHAR ext[4];
  107. if (!HeapValidate( g.hHeap, 0, MemPtr )) {
  108. PrintString( buf, DIMA(buf), "IMAGEHLP: heap corruption - " );
  109. _splitpath( File, NULL, NULL, &buf[strlen(buf)], ext );
  110. CatStrArray( buf, ext );
  111. PrintString( &buf[strlen(buf)], DIMA(buf) - (&buf[strlen(buf)] - buf), " @ %d\n", Line );
  112. OutputDebugString( buf );
  113. PrintAllocations();
  114. DebugBreak();
  115. return FALSE;
  116. }
  117. return TRUE;
  118. }
  119. BOOL
  120. pHeapDump(
  121. LPSTR sz,
  122. ULONG line,
  123. LPSTR file
  124. )
  125. {
  126. BOOL rc;
  127. if (sz && *sz)
  128. OutputDebugString(sz);
  129. rc = CheckHeap(NULL);
  130. if (rc)
  131. PrintAllocations();
  132. return rc;
  133. }
  134. #endif
  135. PVOID
  136. pMemReAlloc(
  137. PVOID OldAlloc,
  138. ULONG_PTR AllocSize
  139. #ifdef IMAGEHLP_HEAP_DEBUG
  140. , ULONG Line,
  141. LPSTR File
  142. #endif
  143. )
  144. {
  145. #ifdef IMAGEHLP_HEAP_DEBUG
  146. PVOID NewAlloc;
  147. PHEAP_BLOCK hb;
  148. if (!OldAlloc) {
  149. return NULL;
  150. }
  151. hb = (PHEAP_BLOCK) ((PUCHAR)OldAlloc - sizeof(HEAP_BLOCK));
  152. if (hb->Signature != HEAP_SIG) {
  153. OutputDebugString( "IMAGEHLP: Corrupt heap block\n" );
  154. DebugBreak();
  155. }
  156. NewAlloc = pMemAlloc(AllocSize, Line, File);
  157. if (!NewAlloc)
  158. return NULL;
  159. memcpy(NewAlloc, OldAlloc, min(hb->Size, AllocSize));
  160. RemoveEntryList( &hb->ListEntry );
  161. g.TotalMemory -= hb->Size;
  162. g.TotalAllocs -= 1;
  163. HeapFree( g.hHeap, 0, (PVOID) hb );
  164. return NewAlloc;
  165. #else
  166. return(HeapReAlloc(g.hHeap, HEAP_ZERO_MEMORY, OldAlloc, AllocSize));
  167. #endif
  168. }
  169. PVOID
  170. pMemAlloc(
  171. ULONG_PTR AllocSize
  172. #ifdef IMAGEHLP_HEAP_DEBUG
  173. , ULONG Line,
  174. LPSTR File
  175. #endif
  176. )
  177. {
  178. #ifdef IMAGEHLP_HEAP_DEBUG
  179. PHEAP_BLOCK hb;
  180. CHAR ext[4];
  181. hb = (PHEAP_BLOCK) HeapAlloc( g.hHeap, HEAP_ZERO_MEMORY, AllocSize + sizeof(HEAP_BLOCK) );
  182. if (hb) {
  183. g.TotalMemory += AllocSize;
  184. g.TotalAllocs += 1;
  185. InsertTailList( &g.HeapHeader, &hb->ListEntry );
  186. hb->Signature = HEAP_SIG;
  187. hb->Size = AllocSize;
  188. hb->Line = Line;
  189. _splitpath( File, NULL, NULL, hb->File, ext );
  190. CatStrArray( hb->File, ext );
  191. return (PVOID) ((PUCHAR)hb + sizeof(HEAP_BLOCK));
  192. }
  193. return NULL;
  194. #else
  195. return HeapAlloc( g.hHeap, HEAP_ZERO_MEMORY, AllocSize );
  196. #endif
  197. }
  198. VOID
  199. pMemFree(
  200. PVOID MemPtr
  201. #ifdef IMAGEHLP_HEAP_DEBUG
  202. , ULONG Line,
  203. LPSTR File
  204. #endif
  205. )
  206. {
  207. #ifdef IMAGEHLP_HEAP_DEBUG
  208. PHEAP_BLOCK hb;
  209. if (!MemPtr) {
  210. return;
  211. }
  212. pCheckHeap(NULL, Line, File);
  213. hb = (PHEAP_BLOCK) ((PUCHAR)MemPtr - sizeof(HEAP_BLOCK));
  214. if (hb->Signature != HEAP_SIG) {
  215. OutputDebugString( "IMAGEHLP: Corrupt heap block\n" );
  216. DebugBreak();
  217. }
  218. RemoveEntryList( &hb->ListEntry );
  219. g.TotalMemory -= hb->Size;
  220. g.TotalAllocs -= 1;
  221. HeapFree( g.hHeap, 0, (PVOID) hb );
  222. #else
  223. if (!MemPtr) {
  224. return;
  225. }
  226. HeapFree( g.hHeap, 0, MemPtr );
  227. #endif
  228. }
  229. ULONG_PTR
  230. pMemSize(
  231. PVOID MemPtr
  232. )
  233. {
  234. return HeapSize(g.hHeap, 0, MemPtr);
  235. }
  236. #ifdef IMAGEHLP_HEAP_DEBUG
  237. VOID
  238. PrintAllocations(
  239. VOID
  240. )
  241. {
  242. PLIST_ENTRY Next;
  243. PHEAP_BLOCK hb;
  244. CHAR buf[256];
  245. LARGE_INTEGER PerfFreq;
  246. Next = g.HeapHeader.Flink;
  247. if (!Next) {
  248. return;
  249. }
  250. OutputDebugString( "-----------------------------------------------------------------------------\n" );
  251. PrintString( buf, DIMA(buf), "Memory Allocations for Heap 0x%08x, Allocs=%d, TotalMem=%I64d\n", (ULONG_PTR)g.hHeap, g.TotalAllocs, g.TotalMemory );
  252. OutputDebugString( buf );
  253. OutputDebugString( "-----------------------------------------------------------------------------\n" );
  254. OutputDebugString( "*\n" );
  255. while ((ULONG_PTR)Next != (ULONG_PTR)&g.HeapHeader) {
  256. hb = CONTAINING_RECORD( Next, HEAP_BLOCK, ListEntry );
  257. Next = hb->ListEntry.Flink;
  258. PrintString( buf, DIMA(buf), "%8d %16s @ %5d\n", hb->Size, hb->File, hb->Line );
  259. OutputDebugString( buf );
  260. }
  261. OutputDebugString( "*\n" );
  262. return;
  263. }
  264. #endif
  265. DWORD
  266. ImagepSetLastErrorFromStatus(
  267. IN DWORD Status
  268. )
  269. {
  270. DWORD dwErrorCode;
  271. // dwErrorCode = RtlNtStatusToDosError( Status );
  272. dwErrorCode = Status;
  273. SetLastError( dwErrorCode );
  274. return( dwErrorCode );
  275. }
  276. /////////////////////////////////////////////////////////////////////////////
  277. /*
  278. ******************************************************************************
  279. On a Hydra System, we don't want imaghlp.dll to load user32.dll since it
  280. prevents CSRSS from exiting when running a under a debugger.
  281. The following two functions have been copied from user32.dll so that we don't
  282. link to user32.dll.
  283. ******************************************************************************
  284. */
  285. ////////////////////////////////////////////////////////////////////////////
  286. LPSTR CharNext(
  287. LPCSTR lpCurrentChar)
  288. {
  289. if (IsDBCSLeadByte(*lpCurrentChar)) {
  290. lpCurrentChar++;
  291. }
  292. /*
  293. * if we have only DBCS LeadingByte, we will point string-terminaler.
  294. */
  295. if (*lpCurrentChar) {
  296. lpCurrentChar++;
  297. }
  298. return (LPSTR)lpCurrentChar;
  299. }
  300. LPSTR CharPrev(
  301. LPCSTR lpStart,
  302. LPCSTR lpCurrentChar)
  303. {
  304. if (lpCurrentChar > lpStart) {
  305. LPCSTR lpChar;
  306. BOOL bDBC = FALSE;
  307. for (lpChar = --lpCurrentChar - 1 ; lpChar >= lpStart ; lpChar--) {
  308. if (!IsDBCSLeadByte(*lpChar))
  309. break;
  310. bDBC = !bDBC;
  311. }
  312. if (bDBC)
  313. lpCurrentChar--;
  314. }
  315. return (LPSTR)lpCurrentChar;
  316. }
  317. void * __cdecl AllocIt(unsigned int cb)
  318. {
  319. return (MemAlloc(cb));
  320. }
  321. void __cdecl FreeIt(void * p)
  322. {
  323. MemFree(p);
  324. }
  325. DWORD
  326. IMAGEAPI
  327. WINAPI
  328. UnDecorateSymbolName(
  329. LPCSTR name,
  330. LPSTR outputString,
  331. DWORD maxStringLength,
  332. DWORD flags
  333. )
  334. {
  335. static HMODULE hMsvcrt = 0;
  336. static BOOL fLoadMsvcrtDLL = FALSE;
  337. static PUNDNAME pfUnDname = NULL;
  338. DWORD rc;
  339. // this prevents an AV in __unDName
  340. if (!name) {
  341. SetLastError(ERROR_INVALID_PARAMETER);
  342. return 0;
  343. }
  344. //
  345. // can't undecorate into a zero length buffer
  346. //
  347. if (maxStringLength < 2) {
  348. SetLastError(ERROR_INVALID_PARAMETER);
  349. return 0;
  350. }
  351. if (!fLoadMsvcrtDLL) {
  352. // The first time we run, see if we can find the system undname. Use
  353. // GetModuleHandle to avoid any additionally overhead.
  354. hMsvcrt = GetModuleHandle("msvcrt.dll");
  355. if (hMsvcrt) {
  356. pfUnDname = (PUNDNAME) GetProcAddress(hMsvcrt, "__unDName");
  357. }
  358. fLoadMsvcrtDLL = TRUE;
  359. }
  360. rc = 0; // Assume failure
  361. __try {
  362. if (pfUnDname) {
  363. if (flags & UNDNAME_NO_ARGUMENTS) {
  364. flags |= UNDNAME_NAME_ONLY;
  365. flags &= ~UNDNAME_NO_ARGUMENTS;
  366. }
  367. if (flags & UNDNAME_NO_SPECIAL_SYMS) {
  368. flags &= ~UNDNAME_NO_SPECIAL_SYMS;
  369. }
  370. if (pfUnDname(outputString, name, maxStringLength-1, AllocIt, FreeIt, (USHORT)flags)) {
  371. rc = strlen(outputString);
  372. }
  373. } else {
  374. *outputString = 0;
  375. strncpy(outputString, "Unable to load msvcrt!__unDName", maxStringLength); // SECURITY: Don't know size of output buffer.
  376. rc = strlen(outputString);
  377. }
  378. } __except(EXCEPTION_EXECUTE_HANDLER) { }
  379. if (!rc) {
  380. SetLastError(ERROR_INVALID_PARAMETER);
  381. }
  382. return rc;
  383. }
  384. DWORD
  385. IMAGEAPI
  386. GetTimestampForLoadedLibrary(
  387. HMODULE Module
  388. )
  389. {
  390. PIMAGE_DOS_HEADER DosHdr;
  391. DWORD dwTimeStamp;
  392. __try {
  393. DosHdr = (PIMAGE_DOS_HEADER) Module;
  394. if (DosHdr->e_magic == IMAGE_DOS_SIGNATURE) {
  395. dwTimeStamp = ((PIMAGE_NT_HEADERS32) ((LPBYTE)Module + DosHdr->e_lfanew))->FileHeader.TimeDateStamp;
  396. } else if (DosHdr->e_magic == IMAGE_NT_SIGNATURE) {
  397. dwTimeStamp = ((PIMAGE_NT_HEADERS32) DosHdr)->FileHeader.TimeDateStamp;
  398. } else {
  399. dwTimeStamp = 0;
  400. }
  401. } __except (EXCEPTION_EXECUTE_HANDLER) {
  402. dwTimeStamp = 0;
  403. }
  404. return dwTimeStamp;
  405. }
  406. VOID
  407. EnsureTrailingBackslash(
  408. LPSTR sz
  409. )
  410. {
  411. int i;
  412. assert(sz);
  413. i = lstrlen(sz);
  414. if (!i)
  415. return;
  416. if (sz[i - 1] == '\\')
  417. return;
  418. sz[i] = '\\';
  419. sz[i + 1] = '\0';
  420. }
  421. #if DBG
  422. VOID
  423. __cdecl
  424. dbPrint(
  425. LPCSTR fmt,
  426. ...
  427. )
  428. /*++
  429. This function replaces ntdll!DbgPrint(). We need this to keep from linking to
  430. ntdll so that this library will run on Windows.
  431. --*/
  432. {
  433. CHAR text[_MAX_PATH];
  434. va_list vaList;
  435. assert(fmt);
  436. va_start(vaList, fmt);
  437. vsprintf(text, fmt, vaList);
  438. va_end(vaList);
  439. OutputDebugString(text);
  440. }
  441. #endif
  442. #ifdef BUILD_IMAGEHLP
  443. #include <bindi.c>
  444. #endif