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.

1119 lines
32 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Module list abstraction.
  4. //
  5. // Copyright (C) Microsoft Corporation, 2001-2002.
  6. //
  7. //----------------------------------------------------------------------------
  8. #include "ntsdp.hpp"
  9. //
  10. // Note by olegk
  11. // We using KLDR_DATA_TABLE_ENTRY64 in some places like
  12. // GetModNameFromLoaderList) instead of LDR_DATA_TABLE_ENTRY assuming that
  13. // most important fields are the same in these structures.
  14. // So I add some asserts for quick notification if anything will change
  15. // (these are not fullproof checks just a basics)
  16. //
  17. C_ASSERT(&(((PLDR_DATA_TABLE_ENTRY64)0)->InLoadOrderLinks) ==
  18. &(((PKLDR_DATA_TABLE_ENTRY64)0)->InLoadOrderLinks));
  19. C_ASSERT(&(((PLDR_DATA_TABLE_ENTRY64)0)->DllBase) ==
  20. &(((PKLDR_DATA_TABLE_ENTRY64)0)->DllBase));
  21. C_ASSERT(&(((PLDR_DATA_TABLE_ENTRY64)0)->FullDllName) ==
  22. &(((PKLDR_DATA_TABLE_ENTRY64)0)->FullDllName));
  23. //----------------------------------------------------------------------------
  24. //
  25. // Module list abstraction.
  26. //
  27. //----------------------------------------------------------------------------
  28. void
  29. ModuleInfo::ReadImageHeaderInfo(PMODULE_INFO_ENTRY Entry)
  30. {
  31. HRESULT Status;
  32. UCHAR SectorBuffer[ 1024 ];
  33. PIMAGE_NT_HEADERS64 NtHeaders;
  34. ULONG Result;
  35. if (Entry->ImageInfoValid)
  36. {
  37. return;
  38. }
  39. //
  40. // For live debugging of both user mode and kernel mode, we have
  41. // to go load the checksum timestamp directly out of the image header
  42. // because someone decided to overwrite these fields in the OS
  43. // module list - Argh !
  44. //
  45. Entry->CheckSum = UNKNOWN_CHECKSUM;
  46. Entry->TimeDateStamp = UNKNOWN_TIMESTAMP;
  47. Status = m_Target->ReadVirtual(m_Process, Entry->Base, SectorBuffer,
  48. sizeof(SectorBuffer), &Result);
  49. if (Status == S_OK && Result >= sizeof(SectorBuffer))
  50. {
  51. NtHeaders = (PIMAGE_NT_HEADERS64)ImageNtHeader(SectorBuffer);
  52. if (NtHeaders != NULL)
  53. {
  54. switch (NtHeaders->OptionalHeader.Magic)
  55. {
  56. case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
  57. Entry->CheckSum = ((PIMAGE_NT_HEADERS32)NtHeaders)->
  58. OptionalHeader.CheckSum;
  59. Entry->Size = ((PIMAGE_NT_HEADERS32)NtHeaders)->
  60. OptionalHeader.SizeOfImage;
  61. Entry->SizeOfCode = ((PIMAGE_NT_HEADERS32)NtHeaders)->
  62. OptionalHeader.SizeOfCode;
  63. Entry->SizeOfData = ((PIMAGE_NT_HEADERS32)NtHeaders)->
  64. OptionalHeader.SizeOfInitializedData;
  65. Entry->MajorImageVersion = ((PIMAGE_NT_HEADERS32)NtHeaders)->
  66. OptionalHeader.MajorImageVersion;
  67. Entry->MinorImageVersion = ((PIMAGE_NT_HEADERS32)NtHeaders)->
  68. OptionalHeader.MinorImageVersion;
  69. break;
  70. case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
  71. Entry->CheckSum = NtHeaders->OptionalHeader.CheckSum;
  72. Entry->Size = NtHeaders->OptionalHeader.SizeOfImage;
  73. Entry->SizeOfCode = NtHeaders->OptionalHeader.SizeOfCode;
  74. Entry->SizeOfData =
  75. NtHeaders->OptionalHeader.SizeOfInitializedData;
  76. Entry->MajorImageVersion =
  77. NtHeaders->OptionalHeader.MajorImageVersion;
  78. Entry->MinorImageVersion =
  79. NtHeaders->OptionalHeader.MinorImageVersion;
  80. break;
  81. }
  82. Entry->TimeDateStamp = NtHeaders->FileHeader.TimeDateStamp;
  83. Entry->MachineType = NtHeaders->FileHeader.Machine;
  84. Entry->ImageInfoValid = 1;
  85. Entry->ImageVersionValid = 1;
  86. Entry->ImageMachineTypeValid = 1;
  87. }
  88. }
  89. }
  90. void
  91. ModuleInfo::InitSource(ThreadInfo* Thread)
  92. {
  93. m_Thread = Thread;
  94. m_Process = m_Thread->m_Process;
  95. m_Target = m_Process->m_Target;
  96. m_Machine = m_Target->m_Machine;
  97. m_InfoLevel = MODULE_INFO_ALL;
  98. }
  99. HRESULT
  100. NtModuleInfo::GetEntry(PMODULE_INFO_ENTRY Entry)
  101. {
  102. HRESULT Status;
  103. ULONG Result = 0;
  104. ULONG Length;
  105. ULONG64 Buffer;
  106. if (m_Cur == m_Head)
  107. {
  108. return S_FALSE;
  109. }
  110. KLDR_DATA_TABLE_ENTRY64 LdrEntry;
  111. Status = m_Target->
  112. ReadLoaderEntry(m_Process, m_Machine, m_Cur, &LdrEntry);
  113. if (Status != S_OK)
  114. {
  115. ErrOut("Unable to read KLDR_DATA_TABLE_ENTRY at %s - %s\n",
  116. FormatAddr64(m_Cur), FormatStatusCode(Status));
  117. return Status;
  118. }
  119. m_Cur = LdrEntry.InLoadOrderLinks.Flink;
  120. //
  121. // Get the image path if possible, otherwise
  122. // just use the image base name.
  123. //
  124. Entry->NamePtr = NULL;
  125. Entry->NameLength = 0;
  126. if (m_InfoLevel > MODULE_INFO_BASE_SIZE)
  127. {
  128. Length = (ULONG)(ULONG_PTR)LdrEntry.FullDllName.Length;
  129. Buffer = LdrEntry.FullDllName.Buffer;
  130. // In the NT4 dumps that we have the long name may
  131. // point to valid memory but the memory content is
  132. // rarely the correct name, so just don't bother
  133. // trying to read the long name on NT4.
  134. if (m_Target->m_SystemVersion >= NT_SVER_W2K &&
  135. Length != 0 && Buffer != 0 &&
  136. Length < (MAX_IMAGE_PATH * sizeof(WCHAR)))
  137. {
  138. Status = m_Target->ReadVirtual(m_Process, Buffer,
  139. Entry->Buffer,
  140. Length,
  141. &Result);
  142. if (Status != S_OK || (Result < Length))
  143. {
  144. // Make this a verbose message since it's possible the
  145. // name is simply paged out.
  146. VerbOut("Unable to read NT module Full Name "
  147. "string at %s - %s\n",
  148. FormatAddr64(Buffer), FormatStatusCode(Status));
  149. Result = 0;
  150. }
  151. }
  152. if (!Result)
  153. {
  154. Length = (ULONG)(ULONG_PTR)LdrEntry.BaseDllName.Length;
  155. Buffer = LdrEntry.BaseDllName.Buffer;
  156. if (Length != 0 && Buffer != 0 &&
  157. Length < (MAX_IMAGE_PATH * sizeof(WCHAR)))
  158. {
  159. Status = m_Target->ReadVirtual(m_Process, Buffer,
  160. Entry->Buffer,
  161. Length,
  162. &Result);
  163. if (Status != S_OK || (Result < Length))
  164. {
  165. WarnOut("Unable to read NT module Base Name "
  166. "string at %s - %s\n",
  167. FormatAddr64(Buffer), FormatStatusCode(Status));
  168. Result = 0;
  169. }
  170. }
  171. }
  172. if (!Result)
  173. {
  174. // We did not get any name - just return.
  175. return S_OK;
  176. }
  177. *(PWCHAR)(Entry->Buffer + Length) = UNICODE_NULL;
  178. Entry->NamePtr = &(Entry->Buffer[0]);
  179. Entry->UnicodeNamePtr = 1;
  180. Entry->NameLength = Length;
  181. }
  182. Entry->Base = LdrEntry.DllBase;
  183. Entry->Size = LdrEntry.SizeOfImage;
  184. Entry->CheckSum = LdrEntry.CheckSum;
  185. Entry->TimeDateStamp = LdrEntry.TimeDateStamp;
  186. //
  187. // Update the image information, such as timestamp and real image size,
  188. // directly from the image header
  189. //
  190. if (m_InfoLevel > MODULE_INFO_BASE_SIZE)
  191. {
  192. ReadImageHeaderInfo(Entry);
  193. }
  194. //
  195. // For newer NT builds, we also have an alternate entry in the
  196. // LdrDataTable to store image information in case the actual header
  197. // is paged out. We do this for session space images only right now.
  198. //
  199. if (m_InfoLevel > MODULE_INFO_BASE_SIZE &&
  200. (LdrEntry.Flags & LDRP_NON_PAGED_DEBUG_INFO))
  201. {
  202. NON_PAGED_DEBUG_INFO di;
  203. Status = m_Target->ReadVirtual(m_Process,
  204. LdrEntry.NonPagedDebugInfo,
  205. &di,
  206. sizeof(di), // Only read the base struct
  207. &Result);
  208. if (Status != S_OK || (Result < sizeof(di)))
  209. {
  210. WarnOut("Unable to read NonPagedDebugInfo at %s - %s\n",
  211. FormatAddr64(LdrEntry.NonPagedDebugInfo),
  212. FormatStatusCode(Status));
  213. return S_OK;
  214. }
  215. Entry->TimeDateStamp = di.TimeDateStamp;
  216. Entry->CheckSum = di.CheckSum;
  217. Entry->Size = di.SizeOfImage;
  218. Entry->MachineType = di.Machine;
  219. Entry->ImageInfoPartial = 1;
  220. Entry->ImageInfoValid = 1;
  221. Entry->ImageMachineTypeValid = 1;
  222. if (di.Flags == 1)
  223. {
  224. Entry->DebugHeader = malloc(di.Size - sizeof(di));
  225. if (Entry->DebugHeader)
  226. {
  227. Status = m_Target->ReadVirtual(m_Process,
  228. LdrEntry.NonPagedDebugInfo +
  229. sizeof(di),
  230. Entry->DebugHeader,
  231. di.Size - sizeof(di),
  232. &Result);
  233. if (Status != S_OK || (Result < di.Size - sizeof(di)))
  234. {
  235. WarnOut("Unable to read NonPagedDebugInfo data at %s - %s\n",
  236. FormatAddr64(LdrEntry.NonPagedDebugInfo + sizeof(di)),
  237. FormatStatusCode(Status));
  238. return S_OK;
  239. }
  240. Entry->ImageDebugHeader = 1;
  241. Entry->SizeOfDebugHeader = di.Size - sizeof(di);
  242. }
  243. }
  244. }
  245. return S_OK;
  246. }
  247. HRESULT
  248. NtKernelModuleInfo::Initialize(ThreadInfo* Thread)
  249. {
  250. HRESULT Status;
  251. LIST_ENTRY64 List64;
  252. InitSource(Thread);
  253. if ((m_Head = m_Target->m_KdDebuggerData.PsLoadedModuleList) == 0)
  254. {
  255. //
  256. // This field is ALWAYS set in NT 5 targets.
  257. //
  258. // We will only fail here if someone changed the debugger code
  259. // and did not "make up" this structure properly for NT 4 or
  260. // dump targets..
  261. //
  262. ErrOut("Module List address is NULL - "
  263. "debugger not initialized properly.\n");
  264. return E_FAIL;
  265. }
  266. Status = m_Target->ReadListEntry(m_Process, m_Machine, m_Head, &List64);
  267. if (Status != S_OK)
  268. {
  269. // PsLoadedModuleList is a global kernel variable, so if
  270. // it isn't around the kernel must not be mapped and
  271. // we're in a very weird state.
  272. ErrOut("Unable to read PsLoadedModuleList\n");
  273. return S_FALSE;
  274. }
  275. if (!List64.Flink)
  276. {
  277. ULONG64 LoaderBlock;
  278. IMAGE_NT_HEADERS64 ImageHdr;
  279. //
  280. // In live debug sessions, the debugger connects before Mm creates
  281. // the actual module list. If PsLoadedModuleList is
  282. // uninitialized, try to load symbols from the loader
  283. // block module list.
  284. //
  285. // If there is no loader block module list but we know
  286. // the kernel base address and can read the image headers
  287. // we fake a single entry for the kernel so that kernel
  288. // symbols will load even without any module lists.
  289. //
  290. if (m_Target->m_KdDebuggerData.KeLoaderBlock &&
  291. m_Target->ReadPointer(m_Process, m_Machine,
  292. m_Target->m_KdDebuggerData.KeLoaderBlock,
  293. &LoaderBlock) == S_OK &&
  294. LoaderBlock &&
  295. m_Target->ReadListEntry(m_Process, m_Machine, LoaderBlock,
  296. &List64) == S_OK &&
  297. List64.Flink)
  298. {
  299. m_Head = LoaderBlock;
  300. }
  301. else if (m_Target->m_KdDebuggerData.KernBase &&
  302. m_Target->ReadImageNtHeaders(m_Process, m_Target->
  303. m_KdDebuggerData.KernBase,
  304. &ImageHdr) == S_OK)
  305. {
  306. m_Head = m_Target->m_KdDebuggerData.KernBase;
  307. List64.Flink = m_Target->m_KdDebuggerData.KernBase;
  308. }
  309. else
  310. {
  311. dprintf("No module list information. Delay kernel load.\n");
  312. return S_FALSE;
  313. }
  314. }
  315. m_Cur = List64.Flink;
  316. return S_OK;
  317. }
  318. HRESULT
  319. NtKernelModuleInfo::GetEntry(PMODULE_INFO_ENTRY Entry)
  320. {
  321. HRESULT Status;
  322. if (m_Head && m_Head == m_Target->m_KdDebuggerData.KernBase)
  323. {
  324. //
  325. // We weren't able to locate any actual module list
  326. // information but we do have a kernel base and valid
  327. // image at that address. Fake up a kernel module entry.
  328. //
  329. wcscpy((PWSTR)Entry->Buffer, L"kd_ntoskrnl");
  330. Entry->NamePtr = &(Entry->Buffer[0]);
  331. Entry->UnicodeNamePtr = 1;
  332. Entry->NameLength = wcslen((PWSTR)Entry->NamePtr) * sizeof(WCHAR);
  333. Entry->Base = m_Head;
  334. ReadImageHeaderInfo(Entry);
  335. m_Head = 0;
  336. m_Cur = 0;
  337. Status = S_OK;
  338. }
  339. else
  340. {
  341. Status = NtModuleInfo::GetEntry(Entry);
  342. }
  343. // We know that all kernel modules must be
  344. // native modules so force the machine type
  345. // if it isn't already set.
  346. if (Status == S_OK && !Entry->ImageMachineTypeValid)
  347. {
  348. Entry->MachineType = m_Machine->m_ExecTypes[0];
  349. Entry->ImageMachineTypeValid = 1;
  350. }
  351. return Status;
  352. }
  353. NtKernelModuleInfo g_NtKernelModuleIterator;
  354. HRESULT
  355. NtUserModuleInfo::Initialize(ThreadInfo* Thread)
  356. {
  357. if (Thread)
  358. {
  359. InitSource(Thread);
  360. }
  361. return GetUserModuleListAddress(m_Thread, m_Machine, m_Peb, FALSE,
  362. &m_Head, &m_Cur) ? S_OK : S_FALSE;
  363. }
  364. HRESULT
  365. NtUserModuleInfo::GetEntry(PMODULE_INFO_ENTRY Entry)
  366. {
  367. HRESULT Status = NtModuleInfo::GetEntry(Entry);
  368. if (Status == S_OK)
  369. {
  370. Entry->UserMode = TRUE;
  371. }
  372. return Status;
  373. }
  374. HRESULT
  375. NtTargetUserModuleInfo::Initialize(ThreadInfo* Thread)
  376. {
  377. m_Peb = 0;
  378. return NtUserModuleInfo::Initialize(Thread);
  379. }
  380. NtTargetUserModuleInfo g_NtTargetUserModuleIterator;
  381. HRESULT
  382. NtWow64UserModuleInfo::Initialize(ThreadInfo* Thread)
  383. {
  384. HRESULT Status;
  385. InitSource(Thread);
  386. if (m_Target->m_Machine->m_NumExecTypes < 2)
  387. {
  388. return E_UNEXPECTED;
  389. }
  390. m_Machine = MachineTypeInfo(m_Target, m_Target->m_Machine->m_ExecTypes[1]);
  391. if ((Status = GetPeb32(&m_Peb)) != S_OK)
  392. {
  393. return Status;
  394. }
  395. return NtUserModuleInfo::Initialize(NULL);
  396. }
  397. HRESULT
  398. NtWow64UserModuleInfo::GetPeb32(PULONG64 Peb32)
  399. {
  400. ULONG64 Teb;
  401. ULONG64 Teb32;
  402. HRESULT Status;
  403. if ((Status = m_Process->GetImplicitThreadDataTeb(m_Thread, &Teb)) == S_OK)
  404. {
  405. if ((Status = m_Target->
  406. ReadPointer(m_Process, m_Machine, Teb, &Teb32)) == S_OK)
  407. {
  408. if (!Teb32)
  409. {
  410. return E_UNEXPECTED;
  411. }
  412. ULONG RawPeb32;
  413. Status = m_Target->
  414. ReadAllVirtual(m_Process, Teb32 + PEB_FROM_TEB32, &RawPeb32,
  415. sizeof(RawPeb32));
  416. if (Status != S_OK)
  417. {
  418. ErrOut("Cannot read PEB32 from WOW64 TEB32 %s - %s\n",
  419. FormatAddr64(Teb32), FormatStatusCode(Status));
  420. return Status;
  421. }
  422. *Peb32 = EXTEND64(RawPeb32);
  423. }
  424. }
  425. return Status;
  426. }
  427. NtWow64UserModuleInfo g_NtWow64UserModuleIterator;
  428. HRESULT
  429. DebuggerModuleInfo::Initialize(ThreadInfo* Thread)
  430. {
  431. InitSource(Thread);
  432. m_Image = m_Process->m_ImageHead;
  433. return S_OK;
  434. }
  435. HRESULT
  436. DebuggerModuleInfo::GetEntry(PMODULE_INFO_ENTRY Entry)
  437. {
  438. if (m_Image == NULL)
  439. {
  440. return S_FALSE;
  441. }
  442. Entry->NamePtr = m_Image->m_ImagePath;
  443. Entry->UnicodeNamePtr = 0;
  444. Entry->NameLength = strlen(Entry->NamePtr);
  445. Entry->ModuleName = m_Image->m_ModuleName;
  446. Entry->File = m_Image->m_File;
  447. Entry->Base = m_Image->m_BaseOfImage;
  448. Entry->Size = m_Image->m_SizeOfImage;
  449. Entry->CheckSum = m_Image->m_CheckSum;
  450. Entry->TimeDateStamp = m_Image->m_TimeDateStamp;
  451. Entry->MachineType = m_Image->GetMachineType();
  452. Entry->ImageInfoValid = TRUE;
  453. Entry->ImageMachineTypeValid =
  454. Entry->MachineType != IMAGE_FILE_MACHINE_UNKNOWN ? TRUE : FALSE;
  455. Entry->UserMode = m_Image->m_UserMode;
  456. m_Image = m_Image->m_Next;
  457. return S_OK;
  458. }
  459. DebuggerModuleInfo g_DebuggerModuleIterator;
  460. void
  461. UnloadedModuleInfo::InitSource(ThreadInfo* Thread)
  462. {
  463. m_Thread = Thread;
  464. m_Process = m_Thread->m_Process;
  465. m_Target = m_Process->m_Target;
  466. m_Machine = m_Target->m_Machine;
  467. }
  468. HRESULT
  469. NtKernelUnloadedModuleInfo::Initialize(ThreadInfo* Thread)
  470. {
  471. // Make sure that the kernel dump size doesn't exceed
  472. // the generic size limit.
  473. C_ASSERT((MAX_UNLOADED_NAME_LENGTH / sizeof(WCHAR)) + 1 <=
  474. MAX_INFO_UNLOADED_NAME);
  475. InitSource(Thread);
  476. if (m_Target->m_KdDebuggerData.MmUnloadedDrivers == 0 ||
  477. m_Target->m_KdDebuggerData.MmLastUnloadedDriver == 0)
  478. {
  479. return E_FAIL;
  480. }
  481. // If this is the initial module load we need to be
  482. // careful because much of the system isn't initialized
  483. // yet. Some versions of the OS can crash when scanning
  484. // the unloaded module list, plus at this point we can
  485. // safely assume there are no unloaded modules, so just
  486. // don't enumerate anything.
  487. if (g_EngStatus & ENG_STATUS_AT_INITIAL_MODULE_LOAD)
  488. {
  489. return E_FAIL;
  490. }
  491. HRESULT Status;
  492. ULONG Read;
  493. if ((Status = m_Target->ReadPointer(m_Process, m_Machine,
  494. m_Target->
  495. m_KdDebuggerData.MmUnloadedDrivers,
  496. &m_Base)) != S_OK ||
  497. (Status = m_Target->ReadVirtual(m_Process, m_Target->
  498. m_KdDebuggerData.MmLastUnloadedDriver,
  499. &m_Index, sizeof(m_Index),
  500. &Read)) != S_OK)
  501. {
  502. return Status;
  503. }
  504. if (Read != sizeof(m_Index))
  505. {
  506. return HRESULT_FROM_WIN32(ERROR_READ_FAULT);
  507. }
  508. m_Count = 0;
  509. return S_OK;
  510. }
  511. HRESULT
  512. NtKernelUnloadedModuleInfo::GetEntry(PSTR Name,
  513. PDEBUG_MODULE_PARAMETERS Params)
  514. {
  515. if (m_Count == MI_UNLOADED_DRIVERS)
  516. {
  517. return S_FALSE;
  518. }
  519. if (m_Index == 0)
  520. {
  521. m_Index = MI_UNLOADED_DRIVERS - 1;
  522. }
  523. else
  524. {
  525. m_Index--;
  526. }
  527. ULONG64 Offset;
  528. ULONG Read;
  529. HRESULT Status;
  530. ULONG64 WideName;
  531. ULONG NameLen;
  532. ZeroMemory(Params, sizeof(*Params));
  533. Params->Flags |= DEBUG_MODULE_UNLOADED;
  534. if (m_Target->m_Machine->m_Ptr64)
  535. {
  536. UNLOADED_DRIVERS64 Entry;
  537. Offset = m_Base + m_Index * sizeof(Entry);
  538. if ((Status = m_Target->
  539. ReadAllVirtual(m_Process, Offset, &Entry, sizeof(Entry))) != S_OK)
  540. {
  541. return Status;
  542. }
  543. if (Entry.Name.Buffer == 0)
  544. {
  545. m_Count = MI_UNLOADED_DRIVERS;
  546. return S_FALSE;
  547. }
  548. Params->Base = Entry.StartAddress;
  549. Params->Size = (ULONG)(Entry.EndAddress - Entry.StartAddress);
  550. Params->TimeDateStamp =
  551. FileTimeToTimeDateStamp(Entry.CurrentTime.QuadPart);
  552. WideName = Entry.Name.Buffer;
  553. NameLen = Entry.Name.Length;
  554. }
  555. else
  556. {
  557. UNLOADED_DRIVERS32 Entry;
  558. Offset = m_Base + m_Index * sizeof(Entry);
  559. if ((Status = m_Target->
  560. ReadAllVirtual(m_Process, Offset, &Entry, sizeof(Entry))) != S_OK)
  561. {
  562. return Status;
  563. }
  564. if (Entry.Name.Buffer == 0)
  565. {
  566. m_Count = MI_UNLOADED_DRIVERS;
  567. return S_FALSE;
  568. }
  569. Params->Base = EXTEND64(Entry.StartAddress);
  570. Params->Size = Entry.EndAddress - Entry.StartAddress;
  571. Params->TimeDateStamp =
  572. FileTimeToTimeDateStamp(Entry.CurrentTime.QuadPart);
  573. WideName = EXTEND64(Entry.Name.Buffer);
  574. NameLen = Entry.Name.Length;
  575. }
  576. if (Name != NULL)
  577. {
  578. //
  579. // This size restriction is in force for minidumps only.
  580. // For kernel dumps, just truncate the name for now ...
  581. //
  582. if (NameLen > MAX_UNLOADED_NAME_LENGTH)
  583. {
  584. NameLen = MAX_UNLOADED_NAME_LENGTH;
  585. }
  586. WCHAR WideBuf[MAX_UNLOADED_NAME_LENGTH / sizeof(WCHAR) + 1];
  587. if ((Status = m_Target->
  588. ReadVirtual(m_Process, WideName, WideBuf, NameLen,
  589. &Read)) != S_OK)
  590. {
  591. return Status;
  592. }
  593. WideBuf[NameLen / sizeof(WCHAR)] = 0;
  594. if (WideCharToMultiByte(CP_ACP, 0,
  595. WideBuf, NameLen / sizeof(WCHAR) + 1,
  596. Name,
  597. MAX_UNLOADED_NAME_LENGTH / sizeof(WCHAR) + 1,
  598. NULL, NULL) == 0)
  599. {
  600. return WIN32_LAST_STATUS();
  601. }
  602. Name[MAX_UNLOADED_NAME_LENGTH / sizeof(WCHAR)] = 0;
  603. }
  604. m_Count++;
  605. return S_OK;
  606. }
  607. NtKernelUnloadedModuleInfo g_NtKernelUnloadedModuleIterator;
  608. HRESULT
  609. NtUserUnloadedModuleInfo::Initialize(ThreadInfo* Thread)
  610. {
  611. HRESULT Status;
  612. InitSource(Thread);
  613. if ((Status = m_Target->
  614. GetUnloadedModuleListHead(m_Process, &m_Base)) != S_OK)
  615. {
  616. return Status;
  617. }
  618. m_Index = 0;
  619. return S_OK;
  620. }
  621. HRESULT
  622. NtUserUnloadedModuleInfo::GetEntry(PSTR Name,
  623. PDEBUG_MODULE_PARAMETERS Params)
  624. {
  625. if (m_Index >= RTL_UNLOAD_EVENT_TRACE_NUMBER)
  626. {
  627. return S_FALSE;
  628. }
  629. ULONG64 Offset;
  630. HRESULT Status;
  631. PWSTR NameArray;
  632. RTL_UNLOAD_EVENT_TRACE32 Entry32;
  633. RTL_UNLOAD_EVENT_TRACE64 Entry64;
  634. // Make sure that the RTL record size doesn't exceed
  635. // the generic size limit.
  636. C_ASSERT(DIMA(Entry32.ImageName) <= MAX_INFO_UNLOADED_NAME);
  637. ZeroMemory(Params, sizeof(*Params));
  638. Params->Flags |= DEBUG_MODULE_UNLOADED | DEBUG_MODULE_USER_MODE;
  639. if (m_Machine->m_Ptr64)
  640. {
  641. Offset = m_Base + m_Index * sizeof(Entry64);
  642. if ((Status = m_Target->
  643. ReadAllVirtual(m_Process, Offset,
  644. &Entry64, sizeof(Entry64))) != S_OK)
  645. {
  646. return Status;
  647. }
  648. if (Entry64.BaseAddress == 0)
  649. {
  650. m_Index = RTL_UNLOAD_EVENT_TRACE_NUMBER;
  651. return S_FALSE;
  652. }
  653. Params->Base = Entry64.BaseAddress;
  654. Params->Size = (ULONG)Entry64.SizeOfImage;
  655. Params->TimeDateStamp = Entry64.TimeDateStamp;
  656. Params->Checksum = Entry64.CheckSum;
  657. NameArray = Entry64.ImageName;
  658. }
  659. else
  660. {
  661. Offset = m_Base + m_Index * sizeof(Entry32);
  662. if ((Status = m_Target->
  663. ReadAllVirtual(m_Process, Offset,
  664. &Entry32, sizeof(Entry32))) != S_OK)
  665. {
  666. return Status;
  667. }
  668. if (Entry32.BaseAddress == 0)
  669. {
  670. m_Index = RTL_UNLOAD_EVENT_TRACE_NUMBER;
  671. return S_FALSE;
  672. }
  673. Params->Base = EXTEND64(Entry32.BaseAddress);
  674. Params->Size = (ULONG)Entry32.SizeOfImage;
  675. Params->TimeDateStamp = Entry32.TimeDateStamp;
  676. Params->Checksum = Entry32.CheckSum;
  677. NameArray = Entry32.ImageName;
  678. }
  679. if (Name != NULL)
  680. {
  681. NameArray[DIMA(Entry32.ImageName) - 1] = 0;
  682. if (WideCharToMultiByte(CP_ACP, 0,
  683. NameArray, -1,
  684. Name,
  685. MAX_INFO_UNLOADED_NAME,
  686. NULL, NULL) == 0)
  687. {
  688. return WIN32_LAST_STATUS();
  689. }
  690. Name[MAX_INFO_UNLOADED_NAME - 1] = 0;
  691. }
  692. m_Index++;
  693. return S_OK;
  694. }
  695. NtUserUnloadedModuleInfo g_NtUserUnloadedModuleIterator;
  696. HRESULT
  697. ToolHelpModuleInfo::Initialize(ThreadInfo* Thread)
  698. {
  699. InitSource(Thread);
  700. m_Snap = g_Kernel32Calls.
  701. CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,
  702. m_Process->m_SystemId);
  703. if (m_Snap == INVALID_HANDLE_VALUE)
  704. {
  705. m_Snap = NULL;
  706. ErrOut("Can't create snapshot\n");
  707. return WIN32_LAST_STATUS();
  708. }
  709. m_First = TRUE;
  710. m_LastId = 0;
  711. return S_OK;
  712. }
  713. HRESULT
  714. ToolHelpModuleInfo::GetEntry(PMODULE_INFO_ENTRY Entry)
  715. {
  716. if (m_Snap == NULL)
  717. {
  718. return S_FALSE;
  719. }
  720. BOOL Succ;
  721. MODULEENTRY32 Mod;
  722. Mod.dwSize = sizeof(Mod);
  723. if (m_First)
  724. {
  725. Succ = g_Kernel32Calls.Module32First(m_Snap, &Mod);
  726. m_First = FALSE;
  727. }
  728. else
  729. {
  730. // Win9x seems to require that this module ID be saved
  731. // between calls so stick it back in to keep Win9x happy.
  732. Mod.th32ModuleID = m_LastId;
  733. Succ = g_Kernel32Calls.Module32Next(m_Snap, &Mod);
  734. }
  735. if (!Succ)
  736. {
  737. CloseHandle(m_Snap);
  738. m_Snap = NULL;
  739. return S_FALSE;
  740. }
  741. m_LastId = Mod.th32ModuleID;
  742. CopyString(Entry->Buffer, Mod.szModule, DIMA(Entry->Buffer));
  743. Entry->NamePtr = Entry->Buffer;
  744. Entry->UnicodeNamePtr = 0;
  745. Entry->NameLength = strlen(Entry->NamePtr);
  746. Entry->Base = EXTEND64((ULONG_PTR)Mod.modBaseAddr);
  747. Entry->Size = Mod.modBaseSize;
  748. // Toolhelp only enumerates user-mode modules.
  749. Entry->UserMode = TRUE;
  750. //
  751. // Update the image informaion, such as timestamp and real image size,
  752. // Directly from the image header
  753. //
  754. ReadImageHeaderInfo(Entry);
  755. return S_OK;
  756. }
  757. ToolHelpModuleInfo g_ToolHelpModuleIterator;
  758. //----------------------------------------------------------------------------
  759. //
  760. // Functions.
  761. //
  762. //----------------------------------------------------------------------------
  763. BOOL
  764. GetUserModuleListAddress(
  765. ThreadInfo* Thread,
  766. MachineInfo* Machine,
  767. ULONG64 Peb,
  768. BOOL Quiet,
  769. PULONG64 OrderModuleListStart,
  770. PULONG64 FirstEntry
  771. )
  772. {
  773. ULONG64 PebLdrOffset;
  774. ULONG64 ModuleListOffset;
  775. ULONG64 PebLdr = 0;
  776. *OrderModuleListStart = 0;
  777. *FirstEntry = 0;
  778. if (!Thread || !Machine)
  779. {
  780. return FALSE;
  781. }
  782. //
  783. // Triage dumps have no user mode information.
  784. // User-mode minidumps don't have a loader list.
  785. //
  786. if (IS_KERNEL_TRIAGE_DUMP(Machine->m_Target) ||
  787. IS_USER_MINI_DUMP(Machine->m_Target))
  788. {
  789. return FALSE;
  790. }
  791. if (Machine->m_Ptr64)
  792. {
  793. PebLdrOffset = PEBLDR_FROM_PEB64;
  794. ModuleListOffset = MODULE_LIST_FROM_PEBLDR64;
  795. }
  796. else
  797. {
  798. PebLdrOffset = PEBLDR_FROM_PEB32;
  799. ModuleListOffset = MODULE_LIST_FROM_PEBLDR32;
  800. }
  801. if (!Peb)
  802. {
  803. if (Thread->m_Process->m_Target->
  804. GetImplicitProcessDataPeb(Thread, &Peb) != S_OK)
  805. {
  806. if (!Quiet)
  807. {
  808. ErrOut("Unable to get PEB pointer\n");
  809. }
  810. return FALSE;
  811. }
  812. if (!Peb)
  813. {
  814. // This is a common error as the idle and system process has no
  815. // user address space. So only print the error if we really
  816. // expected to find a user mode address space:
  817. // The Idle and system process have a NULL parent client id - all
  818. // other threads have a valid ID.
  819. //
  820. ULONG64 Pcid;
  821. if ((Thread->m_Process->m_Target->
  822. GetImplicitProcessDataParentCID(Thread, &Pcid) != S_OK) ||
  823. Pcid)
  824. {
  825. if (!Quiet)
  826. {
  827. ErrOut("PEB address is NULL !\n");
  828. }
  829. }
  830. return FALSE;
  831. }
  832. }
  833. //
  834. // Read address the PEB Ldr data from the PEB structure
  835. //
  836. Peb += PebLdrOffset;
  837. if ( (Machine->m_Target->
  838. ReadPointer(Thread->m_Process, Machine, Peb, &PebLdr) != S_OK) ||
  839. (PebLdr == 0) )
  840. {
  841. if (!Quiet)
  842. {
  843. ErrOut("PEB is paged out (Peb = %s). "
  844. "Type \".hh dbgerr001\" for details\n",
  845. FormatMachineAddr64(Machine, Peb));
  846. }
  847. return FALSE;
  848. }
  849. //
  850. // Read address of the user mode module list from the PEB Ldr Data.
  851. //
  852. PebLdr += ModuleListOffset;
  853. *OrderModuleListStart = PebLdr;
  854. if ( (Machine->m_Target->
  855. ReadPointer(Thread->m_Process, Machine,
  856. PebLdr, FirstEntry) != S_OK) ||
  857. (*FirstEntry == 0) )
  858. {
  859. if (!Quiet)
  860. {
  861. ErrOut("UserMode Module List Address is NULL (Addr= %s)\n",
  862. FormatMachineAddr64(Machine, PebLdr));
  863. ErrOut("This is usually caused by being in the wrong process\n");
  864. ErrOut("context or by paging\n");
  865. }
  866. return FALSE;
  867. }
  868. return TRUE;
  869. }
  870. BOOL
  871. GetModNameFromLoaderList(
  872. ThreadInfo* Thread,
  873. MachineInfo* Machine,
  874. ULONG64 Peb,
  875. ULONG64 ModuleBase,
  876. PSTR NameBuffer,
  877. ULONG BufferSize,
  878. BOOL FullPath
  879. )
  880. {
  881. ULONG64 ModList;
  882. ULONG64 List;
  883. HRESULT Status;
  884. KLDR_DATA_TABLE_ENTRY64 Entry;
  885. WCHAR UnicodeBuffer[MAX_IMAGE_PATH];
  886. ULONG Read;
  887. if (!GetUserModuleListAddress(Thread, Machine, Peb, TRUE,
  888. &ModList, &List))
  889. {
  890. return FALSE;
  891. }
  892. while (List != ModList)
  893. {
  894. Status = Machine->m_Target->
  895. ReadLoaderEntry(Thread->m_Process, Machine, List, &Entry);
  896. if (Status != S_OK)
  897. {
  898. ErrOut("Unable to read LDR_DATA_TABLE_ENTRY at %s - %s\n",
  899. FormatMachineAddr64(Machine, List),
  900. FormatStatusCode(Status));
  901. return FALSE;
  902. }
  903. List = Entry.InLoadOrderLinks.Flink;
  904. if (Entry.DllBase == ModuleBase)
  905. {
  906. UNICODE_STRING64 Name;
  907. //
  908. // We found a matching entry. Try to get the name.
  909. //
  910. if (FullPath)
  911. {
  912. Name = Entry.FullDllName;
  913. }
  914. else
  915. {
  916. Name = Entry.BaseDllName;
  917. }
  918. if (Name.Length == 0 ||
  919. Name.Buffer == 0 ||
  920. Name.Length >= sizeof(UnicodeBuffer) - sizeof(WCHAR))
  921. {
  922. return FALSE;
  923. }
  924. Status = Machine->m_Target->
  925. ReadVirtual(Thread->m_Process, Name.Buffer, UnicodeBuffer,
  926. Name.Length, &Read);
  927. if (Status != S_OK || Read < Name.Length)
  928. {
  929. ErrOut("Unable to read name string at %s - %s\n",
  930. FormatMachineAddr64(Machine, Name.Buffer),
  931. FormatStatusCode(Status));
  932. return FALSE;
  933. }
  934. UnicodeBuffer[Name.Length / sizeof(WCHAR)] = UNICODE_NULL;
  935. if (!WideCharToMultiByte(CP_ACP, 0, UnicodeBuffer,
  936. Name.Length / sizeof(WCHAR) + 1,
  937. NameBuffer, BufferSize,
  938. NULL, NULL))
  939. {
  940. ErrOut("Unable to convert Unicode string %ls to ANSI\n",
  941. UnicodeBuffer);
  942. return FALSE;
  943. }
  944. return TRUE;
  945. }
  946. }
  947. return FALSE;
  948. }