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.

4302 lines
102 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // IDebugSystemObjects implementations.
  4. //
  5. // Copyright (C) Microsoft Corporation, 1999-2002.
  6. //
  7. //----------------------------------------------------------------------------
  8. #include "ntsdp.hpp"
  9. //----------------------------------------------------------------------------
  10. //
  11. // Utility functions.
  12. //
  13. //----------------------------------------------------------------------------
  14. void
  15. X86DescriptorToDescriptor64(PX86_LDT_ENTRY X86Desc,
  16. PDESCRIPTOR64 Desc64)
  17. {
  18. Desc64->Base = EXTEND64((ULONG)X86Desc->BaseLow +
  19. ((ULONG)X86Desc->HighWord.Bits.BaseMid << 16) +
  20. ((ULONG)X86Desc->HighWord.Bytes.BaseHi << 24));
  21. Desc64->Limit = (ULONG)X86Desc->LimitLow +
  22. ((ULONG)X86Desc->HighWord.Bits.LimitHi << 16);
  23. if (X86Desc->HighWord.Bits.Granularity)
  24. {
  25. Desc64->Limit = (Desc64->Limit << X86_PAGE_SHIFT) +
  26. ((1 << X86_PAGE_SHIFT) - 1);
  27. }
  28. Desc64->Flags = (ULONG)X86Desc->HighWord.Bytes.Flags1 +
  29. (((ULONG)X86Desc->HighWord.Bytes.Flags2 >> 4) << 8);
  30. }
  31. HRESULT
  32. ReadX86Descriptor(TargetInfo* Target, ProcessInfo* Process,
  33. ULONG Selector, ULONG64 Base, ULONG Limit,
  34. PDESCRIPTOR64 Desc)
  35. {
  36. ULONG Index;
  37. // Mask off irrelevant bits
  38. Index = Selector & ~0x7;
  39. // Check to make sure that the selector is within the table bounds
  40. if (Index > Limit)
  41. {
  42. return E_INVALIDARG;
  43. }
  44. HRESULT Status;
  45. X86_LDT_ENTRY X86Desc;
  46. Status = Target->
  47. ReadAllVirtual(Process, Base + Index, &X86Desc, sizeof(X86Desc));
  48. if (Status != S_OK)
  49. {
  50. return Status;
  51. }
  52. X86DescriptorToDescriptor64(&X86Desc, Desc);
  53. return S_OK;
  54. }
  55. //----------------------------------------------------------------------------
  56. //
  57. // TargetInfo system object methods.
  58. //
  59. //----------------------------------------------------------------------------
  60. HRESULT
  61. TargetInfo::GetProcessorSystemDataOffset(
  62. IN ULONG Processor,
  63. IN ULONG Index,
  64. OUT PULONG64 Offset
  65. )
  66. {
  67. ThreadInfo* Thread;
  68. if (!IS_KERNEL_TARGET(this))
  69. {
  70. return E_UNEXPECTED;
  71. }
  72. // XXX drewb - Temporary until different OS support is
  73. // sorted out.
  74. if (m_ActualSystemVersion < NT_SVER_START ||
  75. m_ActualSystemVersion > NT_SVER_END)
  76. {
  77. return E_UNEXPECTED;
  78. }
  79. Thread = m_ProcessHead->
  80. FindThreadByHandle(VIRTUAL_THREAD_HANDLE(Processor));
  81. if (!Thread)
  82. {
  83. return E_UNEXPECTED;
  84. }
  85. HRESULT Status;
  86. ULONG Read;
  87. if (m_MachineType == IMAGE_FILE_MACHINE_I386)
  88. {
  89. DESCRIPTOR64 Entry;
  90. //
  91. // We always need the PCR address so go ahead and get it.
  92. //
  93. if (!IS_CONTEXT_POSSIBLE(this))
  94. {
  95. X86_DESCRIPTOR GdtDesc;
  96. // We can't go through the normal context segreg mapping
  97. // but all we really need is an entry from the
  98. // kernel GDT that should always be present and
  99. // constant while the system is initialized. We
  100. // can get the GDT information from the x86 control
  101. // space so do that.
  102. if ((Status = ReadControl
  103. (Processor,
  104. m_TypeInfo.OffsetSpecialRegisters +
  105. FIELD_OFFSET(X86_KSPECIAL_REGISTERS, Gdtr),
  106. &GdtDesc, sizeof(GdtDesc), &Read)) != S_OK ||
  107. Read != sizeof(GdtDesc) ||
  108. (Status = ReadX86Descriptor(this, m_ProcessHead,
  109. m_KdDebuggerData.GdtR0Pcr,
  110. EXTEND64(GdtDesc.Base),
  111. GdtDesc.Limit, &Entry)) != S_OK)
  112. {
  113. ErrOut("Unable to read selector for PCR for processor %u\n",
  114. Processor);
  115. return Status != S_OK ?
  116. Status : HRESULT_FROM_WIN32(ERROR_READ_FAULT);
  117. }
  118. }
  119. else
  120. {
  121. if ((Status = GetSelDescriptor(Thread, m_Machine,
  122. m_KdDebuggerData.GdtR0Pcr,
  123. &Entry)) != S_OK)
  124. {
  125. ErrOut("Unable to read selector for PCR for processor %u\n",
  126. Processor);
  127. return Status;
  128. }
  129. }
  130. switch(Index)
  131. {
  132. case DEBUG_DATA_KPCR_OFFSET:
  133. Status = ReadPointer(m_ProcessHead, m_Machine,
  134. Entry.Base +
  135. m_KdDebuggerData.OffsetPcrSelfPcr,
  136. Offset);
  137. if ((Status != S_OK) || Entry.Base != *Offset)
  138. {
  139. ErrOut("KPCR is corrupted !");
  140. }
  141. *Offset = Entry.Base;
  142. break;
  143. case DEBUG_DATA_KPRCB_OFFSET:
  144. case DEBUG_DATA_KTHREAD_OFFSET:
  145. Status = ReadPointer(m_ProcessHead, m_Machine,
  146. Entry.Base +
  147. m_KdDebuggerData.OffsetPcrCurrentPrcb,
  148. Offset);
  149. if (Status != S_OK)
  150. {
  151. return Status;
  152. }
  153. if (Index == DEBUG_DATA_KPRCB_OFFSET)
  154. {
  155. break;
  156. }
  157. Status = ReadPointer(m_ProcessHead, m_Machine,
  158. *Offset +
  159. m_KdDebuggerData.OffsetPrcbCurrentThread,
  160. Offset);
  161. if (Status != S_OK)
  162. {
  163. return Status;
  164. }
  165. break;
  166. }
  167. }
  168. else
  169. {
  170. ULONG ReadSize = m_Machine->m_Ptr64 ?
  171. sizeof(ULONG64) : sizeof(ULONG);
  172. ULONG64 Address;
  173. switch(m_MachineType)
  174. {
  175. case IMAGE_FILE_MACHINE_IA64:
  176. switch(Index)
  177. {
  178. case DEBUG_DATA_KPCR_OFFSET:
  179. Index = IA64_DEBUG_CONTROL_SPACE_PCR;
  180. break;
  181. case DEBUG_DATA_KPRCB_OFFSET:
  182. Index = IA64_DEBUG_CONTROL_SPACE_PRCB;
  183. break;
  184. case DEBUG_DATA_KTHREAD_OFFSET:
  185. Index = IA64_DEBUG_CONTROL_SPACE_THREAD;
  186. break;
  187. }
  188. break;
  189. case IMAGE_FILE_MACHINE_AMD64:
  190. switch(Index)
  191. {
  192. case DEBUG_DATA_KPCR_OFFSET:
  193. Index = AMD64_DEBUG_CONTROL_SPACE_PCR;
  194. break;
  195. case DEBUG_DATA_KPRCB_OFFSET:
  196. Index = AMD64_DEBUG_CONTROL_SPACE_PRCB;
  197. break;
  198. case DEBUG_DATA_KTHREAD_OFFSET:
  199. Index = AMD64_DEBUG_CONTROL_SPACE_THREAD;
  200. break;
  201. }
  202. break;
  203. }
  204. Status = ReadControl(Processor, Index, &Address, ReadSize, &Read);
  205. if (Status != S_OK)
  206. {
  207. return Status;
  208. }
  209. else if (Read != ReadSize)
  210. {
  211. return HRESULT_FROM_WIN32(ERROR_READ_FAULT);
  212. }
  213. if (!m_Machine->m_Ptr64)
  214. {
  215. Address = EXTEND64(Address);
  216. }
  217. *Offset = Address;
  218. }
  219. return S_OK;
  220. }
  221. HRESULT
  222. TargetInfo::GetTargetSegRegDescriptors(ULONG64 Thread,
  223. ULONG Start, ULONG Count,
  224. PDESCRIPTOR64 Descs)
  225. {
  226. while (Count-- > 0)
  227. {
  228. Descs->Flags = SEGDESC_INVALID;
  229. Descs++;
  230. }
  231. return S_OK;
  232. }
  233. HRESULT
  234. TargetInfo::GetTargetSpecialRegisters
  235. (ULONG64 Thread, PCROSS_PLATFORM_KSPECIAL_REGISTERS Special)
  236. {
  237. HRESULT Status;
  238. ULONG Done;
  239. Status = ReadControl(VIRTUAL_THREAD_INDEX(Thread),
  240. m_TypeInfo.OffsetSpecialRegisters,
  241. Special,
  242. m_TypeInfo.SizeKspecialRegisters,
  243. &Done);
  244. if (Status != S_OK)
  245. {
  246. return Status;
  247. }
  248. return Done == m_TypeInfo.SizeKspecialRegisters ?
  249. S_OK : E_FAIL;
  250. }
  251. HRESULT
  252. TargetInfo::SetTargetSpecialRegisters
  253. (ULONG64 Thread, PCROSS_PLATFORM_KSPECIAL_REGISTERS Special)
  254. {
  255. HRESULT Status;
  256. ULONG Done;
  257. Status = WriteControl(VIRTUAL_THREAD_INDEX(Thread),
  258. m_TypeInfo.OffsetSpecialRegisters,
  259. Special,
  260. m_TypeInfo.SizeKspecialRegisters,
  261. &Done);
  262. if (Status != S_OK)
  263. {
  264. return Status;
  265. }
  266. return Done == m_TypeInfo.SizeKspecialRegisters ?
  267. S_OK : E_FAIL;
  268. }
  269. void
  270. TargetInfo::InvalidateTargetContext(void)
  271. {
  272. // Nothing to do.
  273. }
  274. HRESULT
  275. TargetInfo::GetThreadStartOffset(ThreadInfo* Thread,
  276. PULONG64 StartOffset)
  277. {
  278. // Base implementation to indicate no information available.
  279. return E_NOINTERFACE;
  280. }
  281. void
  282. TargetInfo::SuspendThreads(void)
  283. {
  284. // Base implementation for targets that can't suspend threads.
  285. }
  286. BOOL
  287. TargetInfo::ResumeThreads(void)
  288. {
  289. ThreadInfo* Thread;
  290. // Base implementation for targets that can't suspend threads.
  291. //
  292. // Wipe out all cached thread data offsets in
  293. // case operations after the resumption invalidates
  294. // the cached values.
  295. for (Thread = m_ProcessHead ? m_ProcessHead->m_ThreadHead : NULL;
  296. Thread != NULL;
  297. Thread = Thread->m_Next)
  298. {
  299. Thread->m_DataOffset = 0;
  300. }
  301. return TRUE;
  302. }
  303. HRESULT
  304. TargetInfo::GetContext(
  305. ULONG64 Thread,
  306. PCROSS_PLATFORM_CONTEXT Context
  307. )
  308. {
  309. if (m_Machine == NULL)
  310. {
  311. return E_UNEXPECTED;
  312. }
  313. HRESULT Status;
  314. CROSS_PLATFORM_CONTEXT TargetContextBuffer;
  315. PCROSS_PLATFORM_CONTEXT TargetContext;
  316. if (m_Machine->m_SverCanonicalContext <=
  317. m_SystemVersion)
  318. {
  319. TargetContext = Context;
  320. }
  321. else
  322. {
  323. TargetContext = &TargetContextBuffer;
  324. m_Machine->
  325. InitializeContextFlags(TargetContext,
  326. m_SystemVersion);
  327. }
  328. Status = GetTargetContext(Thread, TargetContext);
  329. if (Status == S_OK && TargetContext == &TargetContextBuffer)
  330. {
  331. Status = m_Machine->
  332. ConvertContextFrom(Context, m_SystemVersion,
  333. m_TypeInfo.SizeTargetContext,
  334. TargetContext);
  335. // Conversion should always succeed since the size is
  336. // known to be valid.
  337. DBG_ASSERT(Status == S_OK);
  338. }
  339. return Status;
  340. }
  341. HRESULT
  342. TargetInfo::SetContext(
  343. ULONG64 Thread,
  344. PCROSS_PLATFORM_CONTEXT Context
  345. )
  346. {
  347. if (m_Machine == NULL)
  348. {
  349. return E_UNEXPECTED;
  350. }
  351. CROSS_PLATFORM_CONTEXT TargetContextBuffer;
  352. PCROSS_PLATFORM_CONTEXT TargetContext;
  353. if (m_Machine->m_SverCanonicalContext <=
  354. m_SystemVersion)
  355. {
  356. TargetContext = Context;
  357. }
  358. else
  359. {
  360. TargetContext = &TargetContextBuffer;
  361. HRESULT Status = m_Machine->
  362. ConvertContextTo(Context, m_SystemVersion,
  363. m_TypeInfo.SizeTargetContext,
  364. TargetContext);
  365. // Conversion should always succeed since the size is
  366. // known to be valid.
  367. DBG_ASSERT(Status == S_OK);
  368. }
  369. return SetTargetContext(Thread, TargetContext);
  370. }
  371. HRESULT
  372. TargetInfo::GetContextFromThreadStack(ULONG64 ThreadBase,
  373. PCROSS_PLATFORM_CONTEXT Context,
  374. BOOL Verbose)
  375. {
  376. DBG_ASSERT(ThreadBase && Context != NULL);
  377. if (!IS_KERNEL_TARGET(this))
  378. {
  379. return E_UNEXPECTED;
  380. }
  381. HRESULT Status;
  382. UCHAR Type;
  383. ULONG Proc = 0;
  384. UCHAR State;
  385. ULONG64 Stack;
  386. Status = ReadAllVirtual(m_ProcessHead, ThreadBase, &Type, sizeof(Type));
  387. if (Status != S_OK)
  388. {
  389. ErrOut("Cannot read thread type from thread %s, %s\n",
  390. FormatMachineAddr64(m_Machine, ThreadBase),
  391. FormatStatusCode(Status));
  392. return Status;
  393. }
  394. if (Type != 6)
  395. {
  396. ErrOut("Invalid thread @ %s type - context unchanged.\n",
  397. FormatMachineAddr64(m_Machine, ThreadBase));
  398. return E_INVALIDARG;
  399. }
  400. //
  401. // Check to see if the thread is currently running.
  402. //
  403. Status = ReadAllVirtual(m_ProcessHead,
  404. ThreadBase + m_KdDebuggerData.OffsetKThreadState,
  405. &State, sizeof(State));
  406. if (Status != S_OK)
  407. {
  408. ErrOut("Cannot read thread stack from thread %s, %s\n",
  409. FormatMachineAddr64(m_Machine, ThreadBase),
  410. FormatStatusCode(Status));
  411. return Status;
  412. }
  413. if (State != 2)
  414. {
  415. // thread is not running.
  416. Status = ReadPointer(m_ProcessHead, m_Machine,
  417. ThreadBase +
  418. m_KdDebuggerData.OffsetKThreadKernelStack,
  419. &Stack);
  420. if (Status != S_OK)
  421. {
  422. ErrOut("Cannot read thread stack from thread %s, %s\n",
  423. FormatMachineAddr64(m_Machine, ThreadBase),
  424. FormatStatusCode(Status));
  425. return Status;
  426. }
  427. Status = m_Machine->GetContextFromThreadStack
  428. (ThreadBase, Context, Stack);
  429. }
  430. else
  431. {
  432. if ((Status =
  433. ReadAllVirtual(m_ProcessHead,
  434. ThreadBase +
  435. m_KdDebuggerData.OffsetKThreadNextProcessor,
  436. &Proc, 1)) != S_OK)
  437. {
  438. ErrOut("Cannot read processor number from thread %s, %s\n",
  439. FormatMachineAddr64(m_Machine, ThreadBase),
  440. FormatStatusCode(Status));
  441. return Status;
  442. }
  443. // Get the processor context if it's a valid processor.
  444. if (Proc < m_NumProcessors)
  445. {
  446. // This get may be getting the context of the thread
  447. // currently cached by the register code. Make sure
  448. // the cache is flushed.
  449. FlushRegContext();
  450. m_Machine->
  451. InitializeContextFlags(Context, m_SystemVersion);
  452. if ((Status = GetContext(VIRTUAL_THREAD_HANDLE(Proc),
  453. Context)) != S_OK)
  454. {
  455. ErrOut("Unable to get context for thread "
  456. "running on processor %d, %s\n",
  457. Proc, FormatStatusCode(Status));
  458. return Status;
  459. }
  460. }
  461. else
  462. {
  463. if (Verbose)
  464. {
  465. ErrOut("Thread running on invalid processor %d\n", Proc);
  466. }
  467. return E_INVALIDARG;
  468. }
  469. }
  470. if (Status != S_OK)
  471. {
  472. if (Verbose)
  473. {
  474. ErrOut("Can't retrieve thread context, %s\n",
  475. FormatStatusCode(Status));
  476. }
  477. }
  478. return Status;
  479. }
  480. HRESULT
  481. TargetInfo::StartAttachProcess(ULONG ProcessId,
  482. ULONG AttachFlags,
  483. PPENDING_PROCESS* Pending)
  484. {
  485. return HRESULT_FROM_WIN32(ERROR_CALL_NOT_IMPLEMENTED);
  486. }
  487. HRESULT
  488. TargetInfo::StartCreateProcess(PWSTR CommandLine,
  489. ULONG CreateFlags,
  490. PBOOL InheritHandles,
  491. PWSTR CurrentDir,
  492. PPENDING_PROCESS* Pending)
  493. {
  494. return HRESULT_FROM_WIN32(ERROR_CALL_NOT_IMPLEMENTED);
  495. }
  496. HRESULT
  497. TargetInfo::TerminateProcesses(void)
  498. {
  499. return HRESULT_FROM_WIN32(ERROR_CALL_NOT_IMPLEMENTED);
  500. }
  501. HRESULT
  502. TargetInfo::DetachProcesses(void)
  503. {
  504. return HRESULT_FROM_WIN32(ERROR_CALL_NOT_IMPLEMENTED);
  505. }
  506. HRESULT
  507. TargetInfo::EmulateNtX86SelDescriptor(ThreadInfo* Thread,
  508. MachineInfo* Machine,
  509. ULONG Selector,
  510. PDESCRIPTOR64 Desc)
  511. {
  512. // Only emulate on platforms that support segments.
  513. if (Machine->m_ExecTypes[0] != IMAGE_FILE_MACHINE_I386 &&
  514. Machine->m_ExecTypes[0] != IMAGE_FILE_MACHINE_AMD64)
  515. {
  516. return E_UNEXPECTED;
  517. }
  518. ULONG Type, Gran;
  519. //
  520. // For user mode and triage dumps, we can hardcode the selector
  521. // since we do not have it anywhere.
  522. // XXX drewb - How many should we fake? There are quite
  523. // a few KGDT entries. Which ones are valid in user mode and
  524. // which are valid for a triage dump?
  525. //
  526. if (Selector == m_KdDebuggerData.GdtR3Teb)
  527. {
  528. HRESULT Status;
  529. // In user mode fs points to the TEB so fake up
  530. // a selector for it.
  531. if ((Status = Thread->m_Process->
  532. GetImplicitThreadDataTeb(Thread, &Desc->Base)) != S_OK)
  533. {
  534. return Status;
  535. }
  536. if (Machine != m_Machine)
  537. {
  538. ULONG Read;
  539. // We're asking for an emulated machine's TEB.
  540. // The only case we currently handle is x86-on-IA64
  541. // for Wow64, where the 32-bit TEB pointer is
  542. // stored in NT_TIB.ExceptionList.
  543. // Conveniently, this is the very first entry.
  544. if ((Status = ReadVirtual(Thread->m_Process,
  545. Desc->Base, &Desc->Base,
  546. sizeof(ULONG), &Read)) != S_OK)
  547. {
  548. return Status;
  549. }
  550. if (Read != sizeof(ULONG))
  551. {
  552. return HRESULT_FROM_WIN32(ERROR_READ_FAULT);
  553. }
  554. Desc->Base = EXTEND64(Desc->Base);
  555. }
  556. Desc->Limit = Machine->m_PageSize - 1;
  557. Type = 0x13;
  558. Gran = 0;
  559. }
  560. else if (Selector == m_KdDebuggerData.GdtR3Data)
  561. {
  562. Desc->Base = 0;
  563. Desc->Limit = Machine->m_Ptr64 ? 0xffffffffffffffffI64 : 0xffffffff;
  564. Type = 0x13;
  565. Gran = X86_DESC_GRANULARITY;
  566. }
  567. else
  568. {
  569. // Assume it's a code segment.
  570. Desc->Base = 0;
  571. Desc->Limit = Machine->m_Ptr64 ? 0xffffffffffffffffI64 : 0xffffffff;
  572. Type = 0x1b;
  573. Gran = X86_DESC_GRANULARITY |
  574. (Machine->m_ExecTypes[0] == IMAGE_FILE_MACHINE_AMD64 ?
  575. X86_DESC_LONG_MODE : 0);
  576. }
  577. Desc->Flags = Gran | X86_DESC_DEFAULT_BIG | X86_DESC_PRESENT | Type |
  578. (IS_USER_TARGET(this) ?
  579. (3 << X86_DESC_PRIVILEGE_SHIFT) : (Selector & 3));
  580. return S_OK;
  581. }
  582. HRESULT
  583. TargetInfo::EmulateNtAmd64SelDescriptor(ThreadInfo* Thread,
  584. MachineInfo* Machine,
  585. ULONG Selector,
  586. PDESCRIPTOR64 Desc)
  587. {
  588. if (Machine->m_ExecTypes[0] != IMAGE_FILE_MACHINE_AMD64)
  589. {
  590. return E_UNEXPECTED;
  591. }
  592. ULONG Type, Gran;
  593. //
  594. // XXX drewb - How many should we fake? There are quite
  595. // a few KGDT64 entries. Which ones are valid in user mode and
  596. // which are valid for a triage dump?
  597. //
  598. if (Selector == m_KdDebuggerData.Gdt64R3CmTeb)
  599. {
  600. HRESULT Status;
  601. // In user mode fs points to the TEB so fake up
  602. // a selector for it.
  603. if ((Status = Thread->m_Process->
  604. GetImplicitThreadDataTeb(Thread, &Desc->Base)) != S_OK)
  605. {
  606. return Status;
  607. }
  608. if (Machine != m_Machine)
  609. {
  610. ULONG Read;
  611. // We're asking for an emulated machine's TEB.
  612. // The only case we currently handle is x86-on-IA64
  613. // for Wow64, where the 32-bit TEB pointer is
  614. // stored in NT_TIB.ExceptionList.
  615. // Conveniently, this is the very first entry.
  616. if ((Status = ReadVirtual(Thread->m_Process,
  617. Desc->Base, &Desc->Base,
  618. sizeof(ULONG), &Read)) != S_OK)
  619. {
  620. return Status;
  621. }
  622. if (Read != sizeof(ULONG))
  623. {
  624. return HRESULT_FROM_WIN32(ERROR_READ_FAULT);
  625. }
  626. Desc->Base = EXTEND64(Desc->Base);
  627. }
  628. Desc->Limit = Machine->m_PageSize - 1;
  629. Type = 0x13;
  630. Gran = 0;
  631. }
  632. else if (Selector == m_KdDebuggerData.GdtR3Data)
  633. {
  634. Desc->Base = 0;
  635. Desc->Limit = Machine->m_Ptr64 ? 0xffffffffffffffffI64 : 0xffffffff;
  636. Type = 0x13;
  637. Gran = X86_DESC_GRANULARITY;
  638. }
  639. else if (Selector == m_KdDebuggerData.Gdt64R3CmCode)
  640. {
  641. Desc->Base = 0;
  642. Desc->Limit = 0xffffffff;
  643. Type = 0x1b;
  644. Gran = X86_DESC_GRANULARITY;
  645. }
  646. else
  647. {
  648. // Assume it's a code segment.
  649. Desc->Base = 0;
  650. Desc->Limit = Machine->m_Ptr64 ? 0xffffffffffffffffI64 : 0xffffffff;
  651. Type = 0x1b;
  652. Gran = X86_DESC_GRANULARITY |
  653. (Machine->m_ExecTypes[0] == IMAGE_FILE_MACHINE_AMD64 ?
  654. X86_DESC_LONG_MODE : 0);
  655. }
  656. Desc->Flags = Gran | X86_DESC_DEFAULT_BIG | X86_DESC_PRESENT | Type |
  657. (IS_USER_TARGET(this) ?
  658. (3 << X86_DESC_PRIVILEGE_SHIFT) : (Selector & 3));
  659. return S_OK;
  660. }
  661. HRESULT
  662. TargetInfo::EmulateNtSelDescriptor(ThreadInfo* Thread,
  663. MachineInfo* Machine,
  664. ULONG Selector,
  665. PDESCRIPTOR64 Desc)
  666. {
  667. switch(Machine->m_ExecTypes[0])
  668. {
  669. case IMAGE_FILE_MACHINE_I386:
  670. return EmulateNtX86SelDescriptor(Thread, Machine, Selector, Desc);
  671. case IMAGE_FILE_MACHINE_AMD64:
  672. return EmulateNtAmd64SelDescriptor(Thread, Machine, Selector, Desc);
  673. default:
  674. return E_UNEXPECTED;
  675. }
  676. }
  677. HRESULT
  678. TargetInfo::GetImplicitProcessData(ThreadInfo* Thread, PULONG64 Offset)
  679. {
  680. HRESULT Status;
  681. if (m_ImplicitProcessData == 0 ||
  682. (m_ImplicitProcessDataIsDefault &&
  683. Thread != m_ImplicitProcessDataThread))
  684. {
  685. Status = SetImplicitProcessData(Thread, 0, FALSE);
  686. }
  687. else
  688. {
  689. Status = S_OK;
  690. }
  691. *Offset = m_ImplicitProcessData;
  692. return Status;
  693. }
  694. HRESULT
  695. TargetInfo::GetImplicitProcessDataPeb(ThreadInfo* Thread, PULONG64 Peb)
  696. {
  697. if (IS_USER_TARGET(this))
  698. {
  699. // In user mode the process data is the PEB.
  700. return GetImplicitProcessData(Thread, Peb);
  701. }
  702. else if (IS_KERNEL_TARGET(this))
  703. {
  704. return ReadImplicitProcessInfoPointer
  705. (Thread, m_KdDebuggerData.OffsetEprocessPeb, Peb);
  706. }
  707. else
  708. {
  709. return E_UNEXPECTED;
  710. }
  711. }
  712. HRESULT
  713. TargetInfo::GetImplicitProcessDataParentCID(ThreadInfo* Thread, PULONG64 Pcid)
  714. {
  715. if (!IS_KERNEL_TARGET(this))
  716. {
  717. // In user mode we don't need the parent process ...
  718. return E_NOTIMPL;
  719. }
  720. else
  721. {
  722. return ReadImplicitProcessInfoPointer
  723. (Thread, m_KdDebuggerData.OffsetEprocessParentCID, Pcid);
  724. }
  725. }
  726. HRESULT
  727. TargetInfo::SetImplicitProcessData(ThreadInfo* Thread,
  728. ULONG64 Offset, BOOL Verbose)
  729. {
  730. HRESULT Status;
  731. BOOL Default = FALSE;
  732. if (Offset == 0)
  733. {
  734. if (!Thread || Thread->m_Process->m_Target != this)
  735. {
  736. if (Verbose)
  737. {
  738. ErrOut("Unable to get the current thread data\n");
  739. }
  740. return E_UNEXPECTED;
  741. }
  742. if ((Status = GetProcessInfoDataOffset(Thread, 0, 0, &Offset)) != S_OK)
  743. {
  744. if (Verbose)
  745. {
  746. ErrOut("Unable to get the current process data\n");
  747. }
  748. return Status;
  749. }
  750. if (Offset == 0)
  751. {
  752. if (Verbose)
  753. {
  754. ErrOut("Current process data is NULL\n");
  755. }
  756. return E_FAIL;
  757. }
  758. Default = TRUE;
  759. }
  760. ULONG64 Old = m_ImplicitProcessData;
  761. BOOL OldDefault = m_ImplicitProcessDataIsDefault;
  762. ThreadInfo* OldThread = m_ImplicitProcessDataThread;
  763. m_ImplicitProcessData = Offset;
  764. m_ImplicitProcessDataIsDefault = Default;
  765. m_ImplicitProcessDataThread = Thread;
  766. if (IS_KERNEL_TARGET(this) &&
  767. !IS_KERNEL_TRIAGE_DUMP(this) &&
  768. (Status = m_Machine->
  769. SetDefaultPageDirectories(Thread, PAGE_DIR_ALL)) != S_OK)
  770. {
  771. m_ImplicitProcessData = Old;
  772. m_ImplicitProcessDataIsDefault = OldDefault;
  773. m_ImplicitProcessDataThread = OldThread;
  774. if (Verbose)
  775. {
  776. ErrOut("Process %s has invalid page directories\n",
  777. FormatMachineAddr64(m_Machine, Offset));
  778. }
  779. return Status;
  780. }
  781. return S_OK;
  782. }
  783. HRESULT
  784. TargetInfo::ReadImplicitProcessInfoPointer(ThreadInfo* Thread,
  785. ULONG Offset, PULONG64 Ptr)
  786. {
  787. HRESULT Status;
  788. ULONG64 CurProc;
  789. // Retrieve the current EPROCESS.
  790. if ((Status = GetImplicitProcessData(Thread, &CurProc)) != S_OK)
  791. {
  792. return Status;
  793. }
  794. return ReadPointer(Thread->m_Process, m_Machine, CurProc + Offset, Ptr);
  795. }
  796. HRESULT
  797. TargetInfo::KdGetThreadInfoDataOffset(ThreadInfo* Thread,
  798. ULONG64 ThreadHandle,
  799. PULONG64 Offset)
  800. {
  801. if (Thread != NULL && Thread->m_DataOffset != 0)
  802. {
  803. *Offset = Thread->m_DataOffset;
  804. return S_OK;
  805. }
  806. ULONG Processor;
  807. if (Thread != NULL)
  808. {
  809. ThreadHandle = Thread->m_Handle;
  810. }
  811. Processor = VIRTUAL_THREAD_INDEX(ThreadHandle);
  812. HRESULT Status;
  813. Status = GetProcessorSystemDataOffset(Processor,
  814. DEBUG_DATA_KTHREAD_OFFSET,
  815. Offset);
  816. if (Status == S_OK && Thread != NULL)
  817. {
  818. Thread->m_DataOffset = *Offset;
  819. }
  820. return Status;
  821. }
  822. HRESULT
  823. TargetInfo::KdGetProcessInfoDataOffset(ThreadInfo* Thread,
  824. ULONG Processor,
  825. ULONG64 ThreadData,
  826. PULONG64 Offset)
  827. {
  828. // Process data offsets are not cached for kernel mode
  829. // since the only ProcessInfo is for kernel space.
  830. ULONG64 ProcessAddr;
  831. HRESULT Status;
  832. if (ThreadData == 0)
  833. {
  834. Status = GetThreadInfoDataOffset(Thread,
  835. VIRTUAL_THREAD_HANDLE(Processor),
  836. &ThreadData);
  837. if (Status != S_OK)
  838. {
  839. return Status;
  840. }
  841. }
  842. ThreadData += m_KdDebuggerData.OffsetKThreadApcProcess;
  843. Status = ReadPointer(m_ProcessHead,
  844. m_Machine, ThreadData, &ProcessAddr);
  845. if (Status != S_OK)
  846. {
  847. ErrOut("Unable to read KTHREAD address %p\n", ThreadData);
  848. }
  849. else
  850. {
  851. *Offset = ProcessAddr;
  852. }
  853. return Status;
  854. }
  855. HRESULT
  856. TargetInfo::KdGetThreadInfoTeb(ThreadInfo* Thread,
  857. ULONG ThreadIndex,
  858. ULONG64 ThreadData,
  859. PULONG64 Offset)
  860. {
  861. ULONG64 TebAddr;
  862. HRESULT Status;
  863. if (ThreadData == 0)
  864. {
  865. Status = GetThreadInfoDataOffset(Thread,
  866. VIRTUAL_THREAD_HANDLE(ThreadIndex),
  867. &ThreadData);
  868. if (Status != S_OK)
  869. {
  870. return Status;
  871. }
  872. }
  873. ThreadData += m_KdDebuggerData.OffsetKThreadTeb;
  874. Status = ReadPointer(m_ProcessHead,
  875. m_Machine, ThreadData, &TebAddr);
  876. if (Status != S_OK)
  877. {
  878. ErrOut("Could not read KTHREAD address %p\n", ThreadData);
  879. }
  880. else
  881. {
  882. *Offset = TebAddr;
  883. }
  884. return Status;
  885. }
  886. HRESULT
  887. TargetInfo::KdGetProcessInfoPeb(ThreadInfo* Thread,
  888. ULONG Processor,
  889. ULONG64 ThreadData,
  890. PULONG64 Offset)
  891. {
  892. HRESULT Status;
  893. ULONG64 Process, PebAddr;
  894. Status = GetProcessInfoDataOffset(Thread, Processor,
  895. ThreadData, &Process);
  896. if (Status != S_OK)
  897. {
  898. return Status;
  899. }
  900. Process += m_KdDebuggerData.OffsetEprocessPeb;
  901. Status = ReadPointer(m_ProcessHead,
  902. m_Machine, Process, &PebAddr);
  903. if (Status != S_OK)
  904. {
  905. ErrOut("Could not read KPROCESS address %p\n", Process);
  906. }
  907. else
  908. {
  909. *Offset = PebAddr;
  910. }
  911. return Status;
  912. }
  913. void
  914. TargetInfo::FlushSelectorCache(void)
  915. {
  916. for (ULONG i = 0; i < SELECTOR_CACHE_LENGTH; i++)
  917. {
  918. m_SelectorCache[i].Younger = &m_SelectorCache[i + 1];
  919. m_SelectorCache[i].Older = &m_SelectorCache[i - 1];
  920. m_SelectorCache[i].Processor = (ULONG)-1;
  921. m_SelectorCache[i].Selector = 0;
  922. }
  923. m_SelectorCache[--i].Younger = NULL;
  924. m_SelectorCache[0].Older = NULL;
  925. m_YoungestSel = &m_SelectorCache[i];
  926. m_OldestSel = &m_SelectorCache[0];
  927. }
  928. BOOL
  929. TargetInfo::FindSelector(ULONG Processor, ULONG Selector,
  930. PDESCRIPTOR64 Desc)
  931. {
  932. int i;
  933. for (i = 0; i < SELECTOR_CACHE_LENGTH; i++)
  934. {
  935. if (m_SelectorCache[i].Selector == Selector &&
  936. m_SelectorCache[i].Processor == Processor)
  937. {
  938. *Desc = m_SelectorCache[i].Desc;
  939. return TRUE;
  940. }
  941. }
  942. return FALSE;
  943. }
  944. void
  945. TargetInfo::PutSelector(ULONG Processor, ULONG Selector,
  946. PDESCRIPTOR64 Desc)
  947. {
  948. m_OldestSel->Processor = Processor;
  949. m_OldestSel->Selector = Selector;
  950. m_OldestSel->Desc = *Desc;
  951. (m_OldestSel->Younger)->Older = NULL;
  952. m_OldestSel->Older = m_YoungestSel;
  953. m_YoungestSel->Younger = m_OldestSel;
  954. m_YoungestSel = m_OldestSel;
  955. m_OldestSel = m_OldestSel->Younger;
  956. }
  957. HRESULT
  958. TargetInfo::KdGetSelDescriptor(ThreadInfo* Thread,
  959. MachineInfo* Machine,
  960. ULONG Selector,
  961. PDESCRIPTOR64 Desc)
  962. {
  963. if (!Thread || !Machine)
  964. {
  965. return E_INVALIDARG;
  966. }
  967. ULONG Processor = VIRTUAL_THREAD_INDEX(Thread->m_Handle);
  968. if (FindSelector(Processor, Selector, Desc))
  969. {
  970. return S_OK;
  971. }
  972. ThreadInfo* CtxThread;
  973. CtxThread = m_RegContextThread;
  974. ChangeRegContext(Thread);
  975. ULONG TableReg;
  976. DESCRIPTOR64 Table;
  977. HRESULT Status;
  978. // Find out whether this is a GDT or LDT selector
  979. if (Selector & 0x4)
  980. {
  981. TableReg = SEGREG_LDT;
  982. }
  983. else
  984. {
  985. TableReg = SEGREG_GDT;
  986. }
  987. //
  988. // Fetch the address and limit of the appropriate descriptor table,
  989. // then look up the selector entry.
  990. //
  991. if ((Status = Machine->GetSegRegDescriptor(TableReg, &Table)) != S_OK)
  992. {
  993. goto Exit;
  994. }
  995. Status = ReadX86Descriptor(this, Thread->m_Process,
  996. Selector, Table.Base, (ULONG)Table.Limit, Desc);
  997. if (Status == S_OK)
  998. {
  999. PutSelector(Processor, Selector, Desc);
  1000. }
  1001. Exit:
  1002. ChangeRegContext(CtxThread);
  1003. return Status;
  1004. }
  1005. //----------------------------------------------------------------------------
  1006. //
  1007. // LiveKernelTargetInfo system object methods.
  1008. //
  1009. //----------------------------------------------------------------------------
  1010. HRESULT
  1011. LiveKernelTargetInfo::GetThreadIdByProcessor(
  1012. IN ULONG Processor,
  1013. OUT PULONG Id
  1014. )
  1015. {
  1016. *Id = VIRTUAL_THREAD_ID(Processor);
  1017. return S_OK;
  1018. }
  1019. HRESULT
  1020. LiveKernelTargetInfo::GetThreadInfoDataOffset(ThreadInfo* Thread,
  1021. ULONG64 ThreadHandle,
  1022. PULONG64 Offset)
  1023. {
  1024. return KdGetThreadInfoDataOffset(Thread, ThreadHandle, Offset);
  1025. }
  1026. HRESULT
  1027. LiveKernelTargetInfo::GetProcessInfoDataOffset(ThreadInfo* Thread,
  1028. ULONG Processor,
  1029. ULONG64 ThreadData,
  1030. PULONG64 Offset)
  1031. {
  1032. return KdGetProcessInfoDataOffset(Thread, Processor, ThreadData, Offset);
  1033. }
  1034. HRESULT
  1035. LiveKernelTargetInfo::GetThreadInfoTeb(ThreadInfo* Thread,
  1036. ULONG ThreadIndex,
  1037. ULONG64 ThreadData,
  1038. PULONG64 Offset)
  1039. {
  1040. return KdGetThreadInfoTeb(Thread, ThreadIndex, ThreadData, Offset);
  1041. }
  1042. HRESULT
  1043. LiveKernelTargetInfo::GetProcessInfoPeb(ThreadInfo* Thread,
  1044. ULONG Processor,
  1045. ULONG64 ThreadData,
  1046. PULONG64 Offset)
  1047. {
  1048. return KdGetProcessInfoPeb(Thread, Processor, ThreadData, Offset);
  1049. }
  1050. HRESULT
  1051. LiveKernelTargetInfo::GetSelDescriptor(ThreadInfo* Thread,
  1052. MachineInfo* Machine,
  1053. ULONG Selector,
  1054. PDESCRIPTOR64 Desc)
  1055. {
  1056. return KdGetSelDescriptor(Thread, Machine, Selector, Desc);
  1057. }
  1058. //----------------------------------------------------------------------------
  1059. //
  1060. // ConnLiveKernelTargetInfo system object methods.
  1061. //
  1062. //----------------------------------------------------------------------------
  1063. HRESULT
  1064. ConnLiveKernelTargetInfo::GetTargetContext(
  1065. ULONG64 Thread,
  1066. PVOID Context
  1067. )
  1068. {
  1069. DBGKD_MANIPULATE_STATE64 m;
  1070. PDBGKD_MANIPULATE_STATE64 Reply;
  1071. PDBGKD_GET_CONTEXT a = &m.u.GetContext;
  1072. NTSTATUS st;
  1073. ULONG rc;
  1074. if (m_Machine == NULL)
  1075. {
  1076. return E_UNEXPECTED;
  1077. }
  1078. //
  1079. // Format state manipulate message
  1080. //
  1081. m.ApiNumber = DbgKdGetContextApi;
  1082. m.ReturnStatus = STATUS_PENDING;
  1083. m.Processor = (USHORT)VIRTUAL_THREAD_INDEX(Thread);
  1084. //
  1085. // Send the message and then wait for reply
  1086. //
  1087. do
  1088. {
  1089. m_Transport->WritePacket(&m, sizeof(m),
  1090. PACKET_TYPE_KD_STATE_MANIPULATE,
  1091. NULL, 0);
  1092. rc = m_Transport->
  1093. WaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
  1094. } while (rc != DBGKD_WAIT_PACKET ||
  1095. Reply->ApiNumber != DbgKdGetContextApi);
  1096. st = Reply->ReturnStatus;
  1097. //
  1098. // Since get context response data follows message, Reply+1 should point
  1099. // at the data
  1100. //
  1101. memcpy(Context, Reply + 1, m_TypeInfo.SizeTargetContext);
  1102. KdOut("DbgKdGetContext returns %08lx\n", st);
  1103. return CONV_NT_STATUS(st);
  1104. }
  1105. HRESULT
  1106. ConnLiveKernelTargetInfo::SetTargetContext(
  1107. ULONG64 Thread,
  1108. PVOID Context
  1109. )
  1110. {
  1111. DBGKD_MANIPULATE_STATE64 m;
  1112. PDBGKD_MANIPULATE_STATE64 Reply;
  1113. PDBGKD_SET_CONTEXT a = &m.u.SetContext;
  1114. NTSTATUS st;
  1115. ULONG rc;
  1116. if (m_Machine == NULL)
  1117. {
  1118. return E_UNEXPECTED;
  1119. }
  1120. //
  1121. // Format state manipulate message
  1122. //
  1123. m.ApiNumber = DbgKdSetContextApi;
  1124. m.ReturnStatus = STATUS_PENDING;
  1125. m.Processor = (USHORT)VIRTUAL_THREAD_INDEX(Thread);
  1126. //
  1127. // Send the message and context and then wait for reply
  1128. //
  1129. do
  1130. {
  1131. m_Transport->WritePacket(&m, sizeof(m),
  1132. PACKET_TYPE_KD_STATE_MANIPULATE,
  1133. Context,
  1134. (USHORT)
  1135. m_TypeInfo.SizeTargetContext);
  1136. rc = m_Transport->
  1137. WaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
  1138. } while (rc != DBGKD_WAIT_PACKET ||
  1139. Reply->ApiNumber != DbgKdSetContextApi);
  1140. st = Reply->ReturnStatus;
  1141. KdOut("DbgKdSetContext returns %08lx\n", st);
  1142. return CONV_NT_STATUS(st);
  1143. }
  1144. //----------------------------------------------------------------------------
  1145. //
  1146. // LocalLiveKernelTargetInfo system object methods.
  1147. //
  1148. //----------------------------------------------------------------------------
  1149. HRESULT
  1150. LocalLiveKernelTargetInfo::GetTargetContext(
  1151. ULONG64 Thread,
  1152. PVOID Context
  1153. )
  1154. {
  1155. // There really isn't any way to make
  1156. // this work in a meaningful way unless the system
  1157. // is paused.
  1158. return E_NOTIMPL;
  1159. }
  1160. HRESULT
  1161. LocalLiveKernelTargetInfo::SetTargetContext(
  1162. ULONG64 Thread,
  1163. PVOID Context
  1164. )
  1165. {
  1166. // There really isn't any way to make
  1167. // this work in a meaningful way unless the system
  1168. // is paused.
  1169. return E_NOTIMPL;
  1170. }
  1171. //----------------------------------------------------------------------------
  1172. //
  1173. // ExdiLiveKernelTargetInfo system object methods.
  1174. //
  1175. //----------------------------------------------------------------------------
  1176. HRESULT
  1177. ExdiLiveKernelTargetInfo::GetProcessorSystemDataOffset(
  1178. IN ULONG Processor,
  1179. IN ULONG Index,
  1180. OUT PULONG64 Offset
  1181. )
  1182. {
  1183. if (m_KdSupport != EXDI_KD_GS_PCR ||
  1184. m_MachineType != IMAGE_FILE_MACHINE_AMD64)
  1185. {
  1186. return LiveKernelTargetInfo::
  1187. GetProcessorSystemDataOffset(Processor, Index, Offset);
  1188. }
  1189. HRESULT Status;
  1190. DESCRIPTOR64 GsDesc;
  1191. if ((Status =
  1192. GetTargetSegRegDescriptors(0, SEGREG_GS, 1, &GsDesc)) != S_OK)
  1193. {
  1194. return Status;
  1195. }
  1196. switch(Index)
  1197. {
  1198. case DEBUG_DATA_KPCR_OFFSET:
  1199. *Offset = GsDesc.Base;
  1200. break;
  1201. case DEBUG_DATA_KPRCB_OFFSET:
  1202. case DEBUG_DATA_KTHREAD_OFFSET:
  1203. Status = ReadPointer(m_ProcessHead,
  1204. m_Machine,
  1205. GsDesc.Base +
  1206. m_KdDebuggerData.OffsetPcrCurrentPrcb,
  1207. Offset);
  1208. if (Status != S_OK)
  1209. {
  1210. return Status;
  1211. }
  1212. if (Index == DEBUG_DATA_KPRCB_OFFSET)
  1213. {
  1214. break;
  1215. }
  1216. Status = ReadPointer(m_ProcessHead,
  1217. m_Machine,
  1218. *Offset +
  1219. m_KdDebuggerData.OffsetPrcbCurrentThread,
  1220. Offset);
  1221. if (Status != S_OK)
  1222. {
  1223. return Status;
  1224. }
  1225. break;
  1226. }
  1227. return S_OK;
  1228. }
  1229. HRESULT
  1230. ExdiLiveKernelTargetInfo::GetTargetContext(
  1231. ULONG64 Thread,
  1232. PVOID Context
  1233. )
  1234. {
  1235. if (!m_ContextValid)
  1236. {
  1237. HRESULT Status;
  1238. if ((Status = m_Machine->
  1239. GetExdiContext(m_Context, &m_ContextData, m_ContextType)) != S_OK)
  1240. {
  1241. return Status;
  1242. }
  1243. m_ContextValid = NULL;
  1244. }
  1245. m_Machine->ConvertExdiContextToContext
  1246. (&m_ContextData, m_ContextType, (PCROSS_PLATFORM_CONTEXT)Context);
  1247. return S_OK;
  1248. }
  1249. HRESULT
  1250. ExdiLiveKernelTargetInfo::SetTargetContext(
  1251. ULONG64 Thread,
  1252. PVOID Context
  1253. )
  1254. {
  1255. if (!m_ContextValid)
  1256. {
  1257. HRESULT Status;
  1258. if ((Status = m_Machine->
  1259. GetExdiContext(m_Context, &m_ContextData, m_ContextType)) != S_OK)
  1260. {
  1261. return Status;
  1262. }
  1263. m_ContextValid = TRUE;
  1264. }
  1265. m_Machine->ConvertExdiContextFromContext
  1266. ((PCROSS_PLATFORM_CONTEXT)Context, &m_ContextData, m_ContextType);
  1267. return m_Machine->SetExdiContext(m_Context, &m_ContextData,
  1268. m_ContextType);
  1269. }
  1270. HRESULT
  1271. ExdiLiveKernelTargetInfo::GetTargetSegRegDescriptors(ULONG64 Thread,
  1272. ULONG Start, ULONG Count,
  1273. PDESCRIPTOR64 Descs)
  1274. {
  1275. if (!m_ContextValid)
  1276. {
  1277. HRESULT Status;
  1278. if ((Status = m_Machine->
  1279. GetExdiContext(m_Context, &m_ContextData, m_ContextType)) != S_OK)
  1280. {
  1281. return Status;
  1282. }
  1283. m_ContextValid = TRUE;
  1284. }
  1285. m_Machine->
  1286. ConvertExdiContextToSegDescs(&m_ContextData, m_ContextType,
  1287. Start, Count, Descs);
  1288. return S_OK;
  1289. }
  1290. void
  1291. ExdiLiveKernelTargetInfo::InvalidateTargetContext(void)
  1292. {
  1293. m_ContextValid = FALSE;
  1294. }
  1295. HRESULT
  1296. ExdiLiveKernelTargetInfo::GetTargetSpecialRegisters
  1297. (ULONG64 Thread, PCROSS_PLATFORM_KSPECIAL_REGISTERS Special)
  1298. {
  1299. if (!m_ContextValid)
  1300. {
  1301. HRESULT Status;
  1302. if ((Status = m_Machine->
  1303. GetExdiContext(m_Context, &m_ContextData, m_ContextType)) != S_OK)
  1304. {
  1305. return Status;
  1306. }
  1307. m_ContextValid = TRUE;
  1308. }
  1309. m_Machine->
  1310. ConvertExdiContextToSpecial(&m_ContextData, m_ContextType, Special);
  1311. return S_OK;
  1312. }
  1313. HRESULT
  1314. ExdiLiveKernelTargetInfo::SetTargetSpecialRegisters
  1315. (ULONG64 Thread, PCROSS_PLATFORM_KSPECIAL_REGISTERS Special)
  1316. {
  1317. if (!m_ContextValid)
  1318. {
  1319. HRESULT Status;
  1320. if ((Status = m_Machine->
  1321. GetExdiContext(m_Context, &m_ContextData, m_ContextType)) != S_OK)
  1322. {
  1323. return Status;
  1324. }
  1325. m_ContextValid = TRUE;
  1326. }
  1327. m_Machine->
  1328. ConvertExdiContextFromSpecial(Special, &m_ContextData, m_ContextType);
  1329. return m_Machine->SetExdiContext(m_Context, &m_ContextData,
  1330. m_ContextType);
  1331. }
  1332. //----------------------------------------------------------------------------
  1333. //
  1334. // LiveUserTargetInfo system object methods.
  1335. //
  1336. //----------------------------------------------------------------------------
  1337. HRESULT
  1338. LiveUserTargetInfo::GetTargetContext(
  1339. ULONG64 Thread,
  1340. PVOID Context
  1341. )
  1342. {
  1343. return m_Services->
  1344. GetContext(Thread,
  1345. *(PULONG)((PUCHAR)Context +
  1346. m_TypeInfo.
  1347. OffsetTargetContextFlags),
  1348. m_TypeInfo.OffsetTargetContextFlags,
  1349. Context,
  1350. m_TypeInfo.SizeTargetContext, NULL);
  1351. }
  1352. HRESULT
  1353. LiveUserTargetInfo::SetTargetContext(
  1354. ULONG64 Thread,
  1355. PVOID Context
  1356. )
  1357. {
  1358. return m_Services->
  1359. SetContext(Thread, Context,
  1360. m_TypeInfo.SizeTargetContext,
  1361. NULL);
  1362. }
  1363. HRESULT
  1364. LiveUserTargetInfo::GetThreadStartOffset(ThreadInfo* Thread,
  1365. PULONG64 StartOffset)
  1366. {
  1367. return m_Services->
  1368. GetThreadStartAddress(Thread->m_Handle, StartOffset);
  1369. }
  1370. #define BUFFER_THREADS 64
  1371. void
  1372. LiveUserTargetInfo::SuspendThreads(void)
  1373. {
  1374. HRESULT Status;
  1375. ProcessInfo* Process;
  1376. ThreadInfo* Thread;
  1377. ULONG64 Threads[BUFFER_THREADS];
  1378. ULONG Counts[BUFFER_THREADS];
  1379. PULONG StoreCounts[BUFFER_THREADS];
  1380. ULONG Buffered;
  1381. ULONG i;
  1382. Buffered = 0;
  1383. Process = m_ProcessHead;
  1384. while (Process != NULL)
  1385. {
  1386. Thread = (Process->m_Flags & ENG_PROC_NO_SUSPEND_RESUME) ?
  1387. NULL : Process->m_ThreadHead;
  1388. while (Thread != NULL)
  1389. {
  1390. if (!Process->m_Exited &&
  1391. !Thread->m_Exited &&
  1392. Thread->m_Handle != 0)
  1393. {
  1394. #ifdef DBG_SUSPEND
  1395. dprintf("** suspending thread id: %x handle: %I64x\n",
  1396. Thread->m_SystemId, Thread->m_Handle);
  1397. #endif
  1398. if (Thread->m_InternalFreezeCount > 0)
  1399. {
  1400. Thread->m_InternalFreezeCount--;
  1401. }
  1402. else if (Thread->m_FreezeCount > 0)
  1403. {
  1404. dprintf("thread %d can execute\n", Thread->m_UserId);
  1405. Thread->m_FreezeCount--;
  1406. }
  1407. else
  1408. {
  1409. if (Buffered == BUFFER_THREADS)
  1410. {
  1411. if ((Status = m_Services->
  1412. SuspendThreads(Buffered, Threads,
  1413. Counts)) != S_OK)
  1414. {
  1415. WarnOut("SuspendThread failed, %s\n",
  1416. FormatStatusCode(Status));
  1417. }
  1418. for (i = 0; i < Buffered; i++)
  1419. {
  1420. *StoreCounts[i] = Counts[i];
  1421. }
  1422. Buffered = 0;
  1423. }
  1424. Threads[Buffered] = Thread->m_Handle;
  1425. StoreCounts[Buffered] = &Thread->m_SuspendCount;
  1426. Buffered++;
  1427. }
  1428. }
  1429. Thread = Thread->m_Next;
  1430. }
  1431. Process = Process->m_Next;
  1432. }
  1433. if (Buffered > 0)
  1434. {
  1435. if ((Status = m_Services->
  1436. SuspendThreads(Buffered, Threads, Counts)) != S_OK)
  1437. {
  1438. WarnOut("SuspendThread failed, %s\n",
  1439. FormatStatusCode(Status));
  1440. }
  1441. for (i = 0; i < Buffered; i++)
  1442. {
  1443. *StoreCounts[i] = Counts[i];
  1444. }
  1445. }
  1446. }
  1447. BOOL
  1448. LiveUserTargetInfo::ResumeThreads(void)
  1449. {
  1450. ProcessInfo* Process;
  1451. ThreadInfo* Thread;
  1452. HRESULT Status;
  1453. BOOL EventActive = FALSE;
  1454. BOOL EventAlive = FALSE;
  1455. ULONG64 Threads[BUFFER_THREADS];
  1456. ULONG Counts[BUFFER_THREADS];
  1457. PULONG StoreCounts[BUFFER_THREADS];
  1458. ULONG Buffered;
  1459. ULONG i;
  1460. Buffered = 0;
  1461. Process = m_ProcessHead;
  1462. while (Process != NULL)
  1463. {
  1464. if (Process->m_Flags & ENG_PROC_NO_SUSPEND_RESUME)
  1465. {
  1466. Thread = NULL;
  1467. // Suppress any possible warning message under
  1468. // the assumption that sessions where the caller
  1469. // is managing suspension do not need warnings.
  1470. EventActive = TRUE;
  1471. }
  1472. else
  1473. {
  1474. Thread = Process->m_ThreadHead;
  1475. }
  1476. while (Thread != NULL)
  1477. {
  1478. if (!Process->m_Exited &&
  1479. !Thread->m_Exited &&
  1480. Thread->m_Handle != 0)
  1481. {
  1482. if (Process == g_EventProcess)
  1483. {
  1484. EventAlive = TRUE;
  1485. }
  1486. #ifdef DBG_SUSPEND
  1487. dprintf("** resuming thread id: %x handle: %I64x\n",
  1488. Thread->m_SystemId, Thread->m_Handle);
  1489. #endif
  1490. if ((g_EngStatus & ENG_STATUS_STOP_SESSION) == 0 &&
  1491. !ThreadWillResume(Thread))
  1492. {
  1493. if (!IsSelectedExecutionThread(Thread,
  1494. SELTHREAD_INTERNAL_THREAD))
  1495. {
  1496. dprintf("thread %d not executing\n", Thread->m_UserId);
  1497. Thread->m_FreezeCount++;
  1498. }
  1499. else
  1500. {
  1501. Thread->m_InternalFreezeCount++;
  1502. }
  1503. }
  1504. else
  1505. {
  1506. if (Process == g_EventProcess)
  1507. {
  1508. EventActive = TRUE;
  1509. }
  1510. if (Buffered == BUFFER_THREADS)
  1511. {
  1512. if ((Status = m_Services->
  1513. ResumeThreads(Buffered, Threads,
  1514. Counts)) != S_OK)
  1515. {
  1516. WarnOut("ResumeThread failed, %s\n",
  1517. FormatStatusCode(Status));
  1518. }
  1519. for (i = 0; i < Buffered; i++)
  1520. {
  1521. *StoreCounts[i] = Counts[i];
  1522. }
  1523. Buffered = 0;
  1524. }
  1525. Threads[Buffered] = Thread->m_Handle;
  1526. StoreCounts[Buffered] = &Thread->m_SuspendCount;
  1527. Buffered++;
  1528. }
  1529. }
  1530. Thread = Thread->m_Next;
  1531. }
  1532. Process = Process->m_Next;
  1533. }
  1534. if (Buffered > 0)
  1535. {
  1536. if ((Status = m_Services->
  1537. ResumeThreads(Buffered, Threads, Counts)) != S_OK)
  1538. {
  1539. WarnOut("ResumeThread failed, %s\n",
  1540. FormatStatusCode(Status));
  1541. }
  1542. for (i = 0; i < Buffered; i++)
  1543. {
  1544. *StoreCounts[i] = Counts[i];
  1545. }
  1546. }
  1547. if (EventAlive && !EventActive)
  1548. {
  1549. return FALSE;
  1550. }
  1551. return TRUE;
  1552. }
  1553. HRESULT
  1554. LiveUserTargetInfo::GetThreadInfoDataOffset(ThreadInfo* Thread,
  1555. ULONG64 ThreadHandle,
  1556. PULONG64 Offset)
  1557. {
  1558. if (Thread && Thread->m_DataOffset)
  1559. {
  1560. *Offset = Thread->m_DataOffset;
  1561. return S_OK;
  1562. }
  1563. if (Thread)
  1564. {
  1565. ThreadHandle = Thread->m_Handle;
  1566. }
  1567. else if (!ThreadHandle)
  1568. {
  1569. return E_UNEXPECTED;
  1570. }
  1571. HRESULT Status = m_Services->
  1572. GetThreadDataOffset(ThreadHandle, Offset);
  1573. if (Status == S_OK)
  1574. {
  1575. if (Thread)
  1576. {
  1577. Thread->m_DataOffset = *Offset;
  1578. }
  1579. }
  1580. return Status;
  1581. }
  1582. HRESULT
  1583. LiveUserTargetInfo::GetProcessInfoDataOffset(ThreadInfo* Thread,
  1584. ULONG Processor,
  1585. ULONG64 ThreadData,
  1586. PULONG64 Offset)
  1587. {
  1588. HRESULT Status;
  1589. // Even if an arbitrary thread data pointer is given
  1590. // we still require a thread in order to know what
  1591. // process to read from.
  1592. // Processor isn't any use so fail if no thread is given.
  1593. if (!Thread)
  1594. {
  1595. return E_UNEXPECTED;
  1596. }
  1597. if (ThreadData != 0)
  1598. {
  1599. if (g_DebuggerPlatformId == VER_PLATFORM_WIN32_NT)
  1600. {
  1601. ThreadData += m_Machine->m_Ptr64 ?
  1602. PEB_FROM_TEB64 : PEB_FROM_TEB32;
  1603. Status = ReadPointer(Thread->m_Process, m_Machine,
  1604. ThreadData, Offset);
  1605. }
  1606. else
  1607. {
  1608. Status = E_NOTIMPL;
  1609. }
  1610. }
  1611. else
  1612. {
  1613. ProcessInfo* Process = Thread->m_Process;
  1614. if (Process->m_DataOffset != 0)
  1615. {
  1616. *Offset = Process->m_DataOffset;
  1617. Status = S_OK;
  1618. }
  1619. else
  1620. {
  1621. Status = m_Services->
  1622. GetProcessDataOffset(Process->m_SysHandle, Offset);
  1623. }
  1624. }
  1625. if (Status == S_OK)
  1626. {
  1627. if (!ThreadData)
  1628. {
  1629. Thread->m_Process->m_DataOffset = *Offset;
  1630. }
  1631. }
  1632. return Status;
  1633. }
  1634. HRESULT
  1635. LiveUserTargetInfo::GetThreadInfoTeb(ThreadInfo* Thread,
  1636. ULONG Processor,
  1637. ULONG64 ThreadData,
  1638. PULONG64 Offset)
  1639. {
  1640. return GetThreadInfoDataOffset(Thread, ThreadData, Offset);
  1641. }
  1642. HRESULT
  1643. LiveUserTargetInfo::GetProcessInfoPeb(ThreadInfo* Thread,
  1644. ULONG Processor,
  1645. ULONG64 ThreadData,
  1646. PULONG64 Offset)
  1647. {
  1648. // Thread data is not useful.
  1649. return GetProcessInfoDataOffset(Thread, 0, 0, Offset);
  1650. }
  1651. HRESULT
  1652. LiveUserTargetInfo::GetSelDescriptor(ThreadInfo* Thread,
  1653. MachineInfo* Machine,
  1654. ULONG Selector,
  1655. PDESCRIPTOR64 Desc)
  1656. {
  1657. HRESULT Status;
  1658. ULONG Used;
  1659. X86_LDT_ENTRY X86Desc;
  1660. if ((Status = m_Services->
  1661. DescribeSelector(Thread->m_Handle, Selector,
  1662. &X86Desc, sizeof(X86Desc),
  1663. &Used)) != S_OK)
  1664. {
  1665. return Status;
  1666. }
  1667. if (Used != sizeof(X86Desc))
  1668. {
  1669. return E_FAIL;
  1670. }
  1671. X86DescriptorToDescriptor64(&X86Desc, Desc);
  1672. return S_OK;
  1673. }
  1674. HRESULT
  1675. LiveUserTargetInfo::StartAttachProcess(ULONG ProcessId,
  1676. ULONG AttachFlags,
  1677. PPENDING_PROCESS* Pending)
  1678. {
  1679. HRESULT Status;
  1680. PPENDING_PROCESS Pend;
  1681. if (g_SymOptions & SYMOPT_SECURE)
  1682. {
  1683. ErrOut("SECURE: Process attach disallowed\n");
  1684. return HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
  1685. }
  1686. if (m_Local &&
  1687. ProcessId == GetCurrentProcessId() &&
  1688. !(AttachFlags & DEBUG_ATTACH_NONINVASIVE_NO_SUSPEND))
  1689. {
  1690. ErrOut("Can't debug the current process\n");
  1691. return E_INVALIDARG;
  1692. }
  1693. Pend = new PENDING_PROCESS;
  1694. if (Pend == NULL)
  1695. {
  1696. ErrOut("Unable to allocate memory\n");
  1697. return E_OUTOFMEMORY;
  1698. }
  1699. if ((AttachFlags & DEBUG_ATTACH_NONINVASIVE) == 0)
  1700. {
  1701. if ((Status = m_Services->
  1702. AttachProcess(ProcessId, AttachFlags,
  1703. &Pend->Handle, &Pend->Options)) != S_OK)
  1704. {
  1705. ErrOut("Cannot debug pid %ld, %s\n \"%s\"\n",
  1706. ProcessId, FormatStatusCode(Status), FormatStatus(Status));
  1707. delete Pend;
  1708. return Status;
  1709. }
  1710. Pend->Flags = ENG_PROC_ATTACHED;
  1711. if (AttachFlags & DEBUG_ATTACH_EXISTING)
  1712. {
  1713. Pend->Flags |= ENG_PROC_ATTACH_EXISTING;
  1714. }
  1715. if (AttachFlags & DEBUG_ATTACH_INVASIVE_NO_INITIAL_BREAK)
  1716. {
  1717. Pend->Flags |= ENG_PROC_NO_INITIAL_BREAK;
  1718. }
  1719. if (AttachFlags & DEBUG_ATTACH_INVASIVE_RESUME_PROCESS)
  1720. {
  1721. Pend->Flags |= ENG_PROC_RESUME_AT_ATTACH;
  1722. }
  1723. if (ProcessId == CSRSS_PROCESS_ID)
  1724. {
  1725. if (m_Local)
  1726. {
  1727. g_EngOptions |= DEBUG_ENGOPT_DISALLOW_NETWORK_PATHS |
  1728. DEBUG_ENGOPT_IGNORE_DBGHELP_VERSION;
  1729. g_EngOptions &= ~DEBUG_ENGOPT_ALLOW_NETWORK_PATHS;
  1730. }
  1731. Pend->Flags |= ENG_PROC_SYSTEM;
  1732. }
  1733. }
  1734. else
  1735. {
  1736. Pend->Handle = 0;
  1737. Pend->Flags = ENG_PROC_EXAMINED;
  1738. if (AttachFlags & DEBUG_ATTACH_NONINVASIVE_NO_SUSPEND)
  1739. {
  1740. Pend->Flags |= ENG_PROC_NO_SUSPEND_RESUME;
  1741. }
  1742. Pend->Options = DEBUG_PROCESS_ONLY_THIS_PROCESS;
  1743. }
  1744. Pend->Id = ProcessId;
  1745. Pend->InitialThreadId = 0;
  1746. Pend->InitialThreadHandle = 0;
  1747. AddPendingProcess(Pend);
  1748. *Pending = Pend;
  1749. return S_OK;
  1750. }
  1751. HRESULT
  1752. LiveUserTargetInfo::StartCreateProcess(PWSTR CommandLine,
  1753. ULONG CreateFlags,
  1754. PBOOL InheritHandles,
  1755. PWSTR CurrentDir,
  1756. PPENDING_PROCESS* Pending)
  1757. {
  1758. HRESULT Status;
  1759. PPENDING_PROCESS Pend;
  1760. if ((CreateFlags & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS)) == 0)
  1761. {
  1762. return E_INVALIDARG;
  1763. }
  1764. if (g_SymOptions & SYMOPT_SECURE)
  1765. {
  1766. ErrOut("SECURE: Process creation disallowed\n");
  1767. return HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
  1768. }
  1769. Pend = new PENDING_PROCESS;
  1770. if (Pend == NULL)
  1771. {
  1772. ErrOut("Unable to allocate memory\n");
  1773. return E_OUTOFMEMORY;
  1774. }
  1775. dprintf("CommandLine: %ws\n", CommandLine);
  1776. //
  1777. // Pick up incoming inherit and curdir settings
  1778. // and apply defaults if necessary.
  1779. //
  1780. BOOL FinalInheritHandles;
  1781. if (InheritHandles)
  1782. {
  1783. FinalInheritHandles = *InheritHandles;
  1784. }
  1785. else
  1786. {
  1787. FinalInheritHandles = TRUE;
  1788. }
  1789. if (!CurrentDir)
  1790. {
  1791. CurrentDir = g_StartProcessDir;
  1792. }
  1793. if (CurrentDir)
  1794. {
  1795. dprintf("Starting directory: %ws\n", CurrentDir);
  1796. }
  1797. //
  1798. // Create the process.
  1799. //
  1800. if ((Status = m_Services->
  1801. CreateProcessW(CommandLine, CreateFlags,
  1802. FinalInheritHandles, CurrentDir,
  1803. &Pend->Id, &Pend->InitialThreadId,
  1804. &Pend->Handle, &Pend->InitialThreadHandle)) != S_OK)
  1805. {
  1806. ErrOut("Cannot execute '%ws', %s\n \"%s\"\n",
  1807. CommandLine, FormatStatusCode(Status),
  1808. FormatStatusArgs(Status, NULL));
  1809. delete Pend;
  1810. }
  1811. else
  1812. {
  1813. Pend->Flags = ENG_PROC_CREATED;
  1814. Pend->Options = (CreateFlags & DEBUG_ONLY_THIS_PROCESS) ?
  1815. DEBUG_PROCESS_ONLY_THIS_PROCESS : 0;
  1816. AddPendingProcess(Pend);
  1817. *Pending = Pend;
  1818. }
  1819. return Status;
  1820. }
  1821. HRESULT
  1822. LiveUserTargetInfo::TerminateProcesses(void)
  1823. {
  1824. HRESULT Status;
  1825. if (g_SymOptions & SYMOPT_SECURE)
  1826. {
  1827. ErrOut("SECURE: Process termination disallowed\n");
  1828. return HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
  1829. }
  1830. ProcessInfo* Process;
  1831. ULONG AllExamined = ENG_PROC_EXAMINED;
  1832. ForTargetProcesses(this)
  1833. {
  1834. // The all-examined flag will get turned off if any
  1835. // process is not examined.
  1836. AllExamined &= Process->m_Flags;
  1837. if ((Status = Process->Terminate()) != S_OK)
  1838. {
  1839. goto Exit;
  1840. }
  1841. }
  1842. if (m_DeferContinueEvent)
  1843. {
  1844. // The event's process may just have been terminated so don't
  1845. // check for failures.
  1846. m_Services->ContinueEvent(DBG_CONTINUE);
  1847. m_DeferContinueEvent = FALSE;
  1848. }
  1849. DEBUG_EVENT64 Event;
  1850. ULONG EventUsed;
  1851. BOOL AnyLeft;
  1852. BOOL AnyExited;
  1853. for (;;)
  1854. {
  1855. while (!AllExamined &&
  1856. m_Services->WaitForEvent(0, &Event, sizeof(Event),
  1857. &EventUsed) == S_OK)
  1858. {
  1859. // Check for process exit events so we can
  1860. // mark the process infos as exited.
  1861. if (EventUsed == sizeof(DEBUG_EVENT32))
  1862. {
  1863. DEBUG_EVENT32 Event32 = *(DEBUG_EVENT32*)&Event;
  1864. DebugEvent32To64(&Event32, &Event);
  1865. }
  1866. else if (EventUsed != sizeof(DEBUG_EVENT64))
  1867. {
  1868. ErrOut("Event data corrupt\n");
  1869. Status = E_FAIL;
  1870. goto Exit;
  1871. }
  1872. if (Event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
  1873. {
  1874. Process = FindProcessBySystemId(Event.dwProcessId);
  1875. if (Process != NULL)
  1876. {
  1877. Process->MarkExited();
  1878. }
  1879. }
  1880. m_Services->ContinueEvent(DBG_CONTINUE);
  1881. }
  1882. AnyLeft = FALSE;
  1883. AnyExited = FALSE;
  1884. ForTargetProcesses(this)
  1885. {
  1886. if (!Process->m_Exited)
  1887. {
  1888. ULONG Code;
  1889. if ((Status = m_Services->
  1890. GetProcessExitCode(Process->m_SysHandle, &Code)) == S_OK)
  1891. {
  1892. Process->MarkExited();
  1893. AnyExited = TRUE;
  1894. }
  1895. else if (FAILED(Status))
  1896. {
  1897. ErrOut("Unable to wait for process to terminate, %s\n",
  1898. FormatStatusCode(Status));
  1899. goto Exit;
  1900. }
  1901. else
  1902. {
  1903. AnyLeft = TRUE;
  1904. }
  1905. }
  1906. }
  1907. if (!AnyLeft)
  1908. {
  1909. break;
  1910. }
  1911. if (!AnyExited)
  1912. {
  1913. // Give things time to run and exit.
  1914. Sleep(50);
  1915. }
  1916. }
  1917. // We've terminated everything so it's safe to assume
  1918. // we're no longer debugging any system processes.
  1919. // We do this now rather than wait for DeleteProcess
  1920. // so that shutdown can query the value immediately.
  1921. m_AllProcessFlags &= ~ENG_PROC_SYSTEM;
  1922. //
  1923. // Drain off any remaining events.
  1924. //
  1925. if (!AllExamined)
  1926. {
  1927. while (m_Services->
  1928. WaitForEvent(10, &Event, sizeof(Event), NULL) == S_OK)
  1929. {
  1930. m_Services->ContinueEvent(DBG_CONTINUE);
  1931. }
  1932. }
  1933. Status = S_OK;
  1934. Exit:
  1935. return Status;
  1936. }
  1937. HRESULT
  1938. LiveUserTargetInfo::DetachProcesses(void)
  1939. {
  1940. HRESULT Status;
  1941. if (g_SymOptions & SYMOPT_SECURE)
  1942. {
  1943. ErrOut("SECURE: Process detach disallowed\n");
  1944. return HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
  1945. }
  1946. if (m_DeferContinueEvent)
  1947. {
  1948. if ((Status = m_Services->ContinueEvent(DBG_CONTINUE)) != S_OK)
  1949. {
  1950. ErrOut("Unable to continue terminated process, %s\n",
  1951. FormatStatusCode(Status));
  1952. return Status;
  1953. }
  1954. m_DeferContinueEvent = FALSE;
  1955. }
  1956. ProcessInfo* Process;
  1957. ULONG AllExamined = ENG_PROC_EXAMINED;
  1958. ForTargetProcesses(this)
  1959. {
  1960. // The all-examined flag will get turned off if any
  1961. // process is not examined.
  1962. AllExamined &= Process->m_Flags;
  1963. Process->Detach();
  1964. }
  1965. // We've terminated everything so it's safe to assume
  1966. // we're no longer debugging any system processes.
  1967. // We do this now rather than wait for DeleteProcess
  1968. // so that shutdown can query the value immediately.
  1969. m_AllProcessFlags &= ~ENG_PROC_SYSTEM;
  1970. //
  1971. // Drain off any remaining events.
  1972. //
  1973. if (!AllExamined)
  1974. {
  1975. DEBUG_EVENT64 Event;
  1976. while (m_Services->
  1977. WaitForEvent(10, &Event, sizeof(Event), NULL) == S_OK)
  1978. {
  1979. m_Services->ContinueEvent(DBG_CONTINUE);
  1980. }
  1981. }
  1982. return S_OK;
  1983. }
  1984. void
  1985. LiveUserTargetInfo::AddPendingProcess(PPENDING_PROCESS Pending)
  1986. {
  1987. Pending->Next = m_ProcessPending;
  1988. m_ProcessPending = Pending;
  1989. m_AllPendingFlags |= Pending->Flags;
  1990. }
  1991. void
  1992. LiveUserTargetInfo::RemovePendingProcess(PPENDING_PROCESS Pending)
  1993. {
  1994. PPENDING_PROCESS Prev, Cur;
  1995. ULONG AllFlags = 0;
  1996. Prev = NULL;
  1997. for (Cur = m_ProcessPending; Cur != NULL; Cur = Cur->Next)
  1998. {
  1999. if (Cur == Pending)
  2000. {
  2001. break;
  2002. }
  2003. Prev = Cur;
  2004. AllFlags |= Cur->Flags;
  2005. }
  2006. if (Cur == NULL)
  2007. {
  2008. DBG_ASSERT(Cur != NULL);
  2009. return;
  2010. }
  2011. Cur = Cur->Next;
  2012. if (Prev == NULL)
  2013. {
  2014. m_ProcessPending = Cur;
  2015. }
  2016. else
  2017. {
  2018. Prev->Next = Cur;
  2019. }
  2020. DiscardPendingProcess(Pending);
  2021. while (Cur != NULL)
  2022. {
  2023. AllFlags |= Cur->Flags;
  2024. Cur = Cur->Next;
  2025. }
  2026. m_AllPendingFlags = AllFlags;
  2027. }
  2028. void
  2029. LiveUserTargetInfo::DiscardPendingProcess(PPENDING_PROCESS Pending)
  2030. {
  2031. if (Pending->InitialThreadHandle)
  2032. {
  2033. m_Services->CloseHandle(Pending->InitialThreadHandle);
  2034. }
  2035. if (Pending->Handle)
  2036. {
  2037. m_Services->CloseHandle(Pending->Handle);
  2038. }
  2039. delete Pending;
  2040. }
  2041. void
  2042. LiveUserTargetInfo::DiscardPendingProcesses(void)
  2043. {
  2044. while (m_ProcessPending != NULL)
  2045. {
  2046. PPENDING_PROCESS Next = m_ProcessPending->Next;
  2047. DiscardPendingProcess(m_ProcessPending);
  2048. m_ProcessPending = Next;
  2049. }
  2050. m_AllPendingFlags = 0;
  2051. }
  2052. PPENDING_PROCESS
  2053. LiveUserTargetInfo::FindPendingProcessByFlags(ULONG Flags)
  2054. {
  2055. PPENDING_PROCESS Cur;
  2056. for (Cur = m_ProcessPending; Cur != NULL; Cur = Cur->Next)
  2057. {
  2058. if (Cur->Flags & Flags)
  2059. {
  2060. return Cur;
  2061. }
  2062. }
  2063. return NULL;
  2064. }
  2065. PPENDING_PROCESS
  2066. LiveUserTargetInfo::FindPendingProcessById(ULONG Id)
  2067. {
  2068. PPENDING_PROCESS Cur;
  2069. for (Cur = m_ProcessPending; Cur != NULL; Cur = Cur->Next)
  2070. {
  2071. if (Cur->Id == Id)
  2072. {
  2073. return Cur;
  2074. }
  2075. }
  2076. return NULL;
  2077. }
  2078. void
  2079. LiveUserTargetInfo::VerifyPendingProcesses(void)
  2080. {
  2081. PPENDING_PROCESS Cur;
  2082. Restart:
  2083. for (Cur = m_ProcessPending; Cur != NULL; Cur = Cur->Next)
  2084. {
  2085. ULONG ExitCode;
  2086. if (Cur->Handle &&
  2087. m_Services->GetProcessExitCode(Cur->Handle, &ExitCode) == S_OK)
  2088. {
  2089. ErrOut("Process %d exited before attach completed\n", Cur->Id);
  2090. RemovePendingProcess(Cur);
  2091. goto Restart;
  2092. }
  2093. }
  2094. }
  2095. void
  2096. LiveUserTargetInfo::AddExamineToPendingAttach(void)
  2097. {
  2098. PPENDING_PROCESS Cur;
  2099. for (Cur = m_ProcessPending; Cur != NULL; Cur = Cur->Next)
  2100. {
  2101. if (Cur->Flags & ENG_PROC_ATTACHED)
  2102. {
  2103. Cur->Flags |= ENG_PROC_EXAMINED;
  2104. m_AllPendingFlags |= ENG_PROC_EXAMINED;
  2105. }
  2106. }
  2107. }
  2108. void
  2109. LiveUserTargetInfo::SuspendResumeThreads(ProcessInfo* Process,
  2110. BOOL Susp,
  2111. ThreadInfo* Match)
  2112. {
  2113. ThreadInfo* Thrd;
  2114. for (Thrd = Process->m_ThreadHead; Thrd; Thrd = Thrd->m_Next)
  2115. {
  2116. if (Match != NULL && Match != Thrd)
  2117. {
  2118. continue;
  2119. }
  2120. HRESULT Status;
  2121. ULONG Count;
  2122. if (Susp)
  2123. {
  2124. Status = m_Services->
  2125. SuspendThreads(1, &Thrd->m_Handle, &Count);
  2126. }
  2127. else
  2128. {
  2129. Status = m_Services->
  2130. ResumeThreads(1, &Thrd->m_Handle, &Count);
  2131. }
  2132. if (Status != S_OK)
  2133. {
  2134. ErrOut("Operation failed for thread %d, 0x%X\n",
  2135. Thrd->m_UserId, Status);
  2136. }
  2137. else
  2138. {
  2139. Thrd->m_SuspendCount = Count;
  2140. }
  2141. }
  2142. }
  2143. //----------------------------------------------------------------------------
  2144. //
  2145. // IDebugSystemObjects methods.
  2146. //
  2147. //----------------------------------------------------------------------------
  2148. STDMETHODIMP
  2149. DebugClient::GetEventThread(
  2150. THIS_
  2151. OUT PULONG Id
  2152. )
  2153. {
  2154. ENTER_ENGINE();
  2155. HRESULT Status;
  2156. if (g_EventThread == NULL)
  2157. {
  2158. Status = E_UNEXPECTED;
  2159. }
  2160. else
  2161. {
  2162. *Id = g_EventThread->m_UserId;
  2163. Status = S_OK;
  2164. }
  2165. LEAVE_ENGINE();
  2166. return Status;
  2167. }
  2168. STDMETHODIMP
  2169. DebugClient::GetEventProcess(
  2170. THIS_
  2171. OUT PULONG Id
  2172. )
  2173. {
  2174. ENTER_ENGINE();
  2175. HRESULT Status;
  2176. if (g_EventProcess == NULL)
  2177. {
  2178. Status = E_UNEXPECTED;
  2179. }
  2180. else
  2181. {
  2182. *Id = g_EventProcess->m_UserId;
  2183. Status = S_OK;
  2184. }
  2185. LEAVE_ENGINE();
  2186. return Status;
  2187. }
  2188. STDMETHODIMP
  2189. DebugClient::GetCurrentThreadId(
  2190. THIS_
  2191. OUT PULONG Id
  2192. )
  2193. {
  2194. HRESULT Status;
  2195. ENTER_ENGINE();
  2196. if (g_Thread == NULL)
  2197. {
  2198. Status = E_UNEXPECTED;
  2199. }
  2200. else
  2201. {
  2202. *Id = g_Thread->m_UserId;
  2203. Status = S_OK;
  2204. }
  2205. LEAVE_ENGINE();
  2206. return Status;
  2207. }
  2208. STDMETHODIMP
  2209. DebugClient::SetCurrentThreadId(
  2210. THIS_
  2211. IN ULONG Id
  2212. )
  2213. {
  2214. HRESULT Status;
  2215. ENTER_ENGINE();
  2216. if (IS_RUNNING(g_CmdState))
  2217. {
  2218. Status = E_UNEXPECTED;
  2219. }
  2220. else
  2221. {
  2222. ThreadInfo* Thread = FindAnyThreadByUserId(Id);
  2223. if (Thread != NULL)
  2224. {
  2225. SetCurrentThread(Thread, FALSE);
  2226. ResetCurrentScopeLazy();
  2227. Status = S_OK;
  2228. }
  2229. else
  2230. {
  2231. Status = E_NOINTERFACE;
  2232. }
  2233. }
  2234. LEAVE_ENGINE();
  2235. return Status;
  2236. }
  2237. STDMETHODIMP
  2238. DebugClient::GetCurrentProcessId(
  2239. THIS_
  2240. OUT PULONG Id
  2241. )
  2242. {
  2243. HRESULT Status;
  2244. ENTER_ENGINE();
  2245. if (g_Process == NULL)
  2246. {
  2247. Status = E_UNEXPECTED;
  2248. }
  2249. else
  2250. {
  2251. *Id = g_Process->m_UserId;
  2252. Status = S_OK;
  2253. }
  2254. LEAVE_ENGINE();
  2255. return Status;
  2256. }
  2257. STDMETHODIMP
  2258. DebugClient::SetCurrentProcessId(
  2259. THIS_
  2260. IN ULONG Id
  2261. )
  2262. {
  2263. HRESULT Status;
  2264. ENTER_ENGINE();
  2265. if (IS_RUNNING(g_CmdState))
  2266. {
  2267. Status = E_UNEXPECTED;
  2268. }
  2269. else
  2270. {
  2271. ProcessInfo* Process = FindAnyProcessByUserId(Id);
  2272. if (Process != NULL)
  2273. {
  2274. if (Process->m_CurrentThread == NULL)
  2275. {
  2276. Process->m_CurrentThread = Process->m_ThreadHead;
  2277. }
  2278. if (Process->m_CurrentThread == NULL)
  2279. {
  2280. Status = E_FAIL;
  2281. }
  2282. else
  2283. {
  2284. SetCurrentThread(Process->m_CurrentThread, FALSE);
  2285. ResetCurrentScopeLazy();
  2286. Status = S_OK;
  2287. }
  2288. }
  2289. else
  2290. {
  2291. Status = E_NOINTERFACE;
  2292. }
  2293. }
  2294. LEAVE_ENGINE();
  2295. return Status;
  2296. }
  2297. STDMETHODIMP
  2298. DebugClient::GetNumberThreads(
  2299. THIS_
  2300. OUT PULONG Number
  2301. )
  2302. {
  2303. HRESULT Status;
  2304. ENTER_ENGINE();
  2305. if (g_Process == NULL)
  2306. {
  2307. Status = E_UNEXPECTED;
  2308. }
  2309. else
  2310. {
  2311. *Number = g_Process->m_NumThreads;
  2312. Status = S_OK;
  2313. }
  2314. LEAVE_ENGINE();
  2315. return Status;
  2316. }
  2317. STDMETHODIMP
  2318. DebugClient::GetTotalNumberThreads(
  2319. THIS_
  2320. OUT PULONG Total,
  2321. OUT PULONG LargestProcess
  2322. )
  2323. {
  2324. HRESULT Status;
  2325. ENTER_ENGINE();
  2326. if (!g_Target)
  2327. {
  2328. Status = E_UNEXPECTED;
  2329. }
  2330. else
  2331. {
  2332. *Total = g_Target->m_TotalNumberThreads;
  2333. *LargestProcess = g_Target->m_MaxThreadsInProcess;
  2334. Status = S_OK;
  2335. }
  2336. LEAVE_ENGINE();
  2337. return Status;
  2338. }
  2339. STDMETHODIMP
  2340. DebugClient::GetThreadIdsByIndex(
  2341. THIS_
  2342. IN ULONG Start,
  2343. IN ULONG Count,
  2344. OUT OPTIONAL /* size_is(Count) */ PULONG Ids,
  2345. OUT OPTIONAL /* size_is(Count) */ PULONG SysIds
  2346. )
  2347. {
  2348. HRESULT Status;
  2349. ENTER_ENGINE();
  2350. if (g_Process == NULL)
  2351. {
  2352. Status = E_UNEXPECTED;
  2353. }
  2354. else
  2355. {
  2356. ThreadInfo* Thread;
  2357. ULONG Index;
  2358. if (Start >= g_Process->m_NumThreads ||
  2359. Start + Count > g_Process->m_NumThreads)
  2360. {
  2361. Status = E_INVALIDARG;
  2362. }
  2363. else
  2364. {
  2365. Index = 0;
  2366. for (Thread = g_Process->m_ThreadHead;
  2367. Thread != NULL;
  2368. Thread = Thread->m_Next)
  2369. {
  2370. if (Index >= Start && Index < Start + Count)
  2371. {
  2372. if (Ids != NULL)
  2373. {
  2374. *Ids++ = Thread->m_UserId;
  2375. }
  2376. if (SysIds != NULL)
  2377. {
  2378. *SysIds++ = Thread->m_SystemId;
  2379. }
  2380. }
  2381. Index++;
  2382. }
  2383. Status = S_OK;
  2384. }
  2385. }
  2386. LEAVE_ENGINE();
  2387. return Status;
  2388. }
  2389. STDMETHODIMP
  2390. DebugClient::GetThreadIdByProcessor(
  2391. THIS_
  2392. IN ULONG Processor,
  2393. OUT PULONG Id
  2394. )
  2395. {
  2396. HRESULT Status;
  2397. ENTER_ENGINE();
  2398. if (g_Process == NULL)
  2399. {
  2400. Status = E_UNEXPECTED;
  2401. }
  2402. else
  2403. {
  2404. ULONG SysId;
  2405. Status = g_Target->GetThreadIdByProcessor(Processor, &SysId);
  2406. if (Status == S_OK)
  2407. {
  2408. ThreadInfo* Thread =
  2409. g_Process->FindThreadBySystemId(SysId);
  2410. if (Thread != NULL)
  2411. {
  2412. *Id = Thread->m_UserId;
  2413. }
  2414. else
  2415. {
  2416. Status = E_NOINTERFACE;
  2417. }
  2418. }
  2419. }
  2420. LEAVE_ENGINE();
  2421. return Status;
  2422. }
  2423. STDMETHODIMP
  2424. DebugClient::GetCurrentThreadDataOffset(
  2425. THIS_
  2426. OUT PULONG64 Offset
  2427. )
  2428. {
  2429. HRESULT Status;
  2430. ENTER_ENGINE();
  2431. if (g_Thread == NULL)
  2432. {
  2433. Status = E_UNEXPECTED;
  2434. }
  2435. else
  2436. {
  2437. Status = g_Target->
  2438. GetThreadInfoDataOffset(g_Thread, 0, Offset);
  2439. }
  2440. LEAVE_ENGINE();
  2441. return Status;
  2442. }
  2443. STDMETHODIMP
  2444. DebugClient::GetThreadIdByDataOffset(
  2445. THIS_
  2446. IN ULONG64 Offset,
  2447. OUT PULONG Id
  2448. )
  2449. {
  2450. HRESULT Status;
  2451. ENTER_ENGINE();
  2452. if (g_Process == NULL)
  2453. {
  2454. Status = E_UNEXPECTED;
  2455. }
  2456. else
  2457. {
  2458. ThreadInfo* Thread;
  2459. Status = E_NOINTERFACE;
  2460. for (Thread = g_Process->m_ThreadHead;
  2461. Thread != NULL;
  2462. Thread = Thread->m_Next)
  2463. {
  2464. ULONG64 DataOffset;
  2465. Status = g_Target->GetThreadInfoDataOffset(Thread, 0, &DataOffset);
  2466. if (Status != S_OK)
  2467. {
  2468. break;
  2469. }
  2470. if (DataOffset == Offset)
  2471. {
  2472. *Id = Thread->m_UserId;
  2473. Status = S_OK;
  2474. break;
  2475. }
  2476. }
  2477. }
  2478. LEAVE_ENGINE();
  2479. return Status;
  2480. }
  2481. STDMETHODIMP
  2482. DebugClient::GetCurrentThreadTeb(
  2483. THIS_
  2484. OUT PULONG64 Offset
  2485. )
  2486. {
  2487. HRESULT Status;
  2488. ENTER_ENGINE();
  2489. if (g_Thread == NULL)
  2490. {
  2491. Status = E_UNEXPECTED;
  2492. }
  2493. else
  2494. {
  2495. Status = g_Target->GetThreadInfoTeb(g_Thread, 0, 0, Offset);
  2496. }
  2497. LEAVE_ENGINE();
  2498. return Status;
  2499. }
  2500. STDMETHODIMP
  2501. DebugClient::GetThreadIdByTeb(
  2502. THIS_
  2503. IN ULONG64 Offset,
  2504. OUT PULONG Id
  2505. )
  2506. {
  2507. HRESULT Status;
  2508. ENTER_ENGINE();
  2509. if (g_Process == NULL)
  2510. {
  2511. Status = E_UNEXPECTED;
  2512. }
  2513. else
  2514. {
  2515. ThreadInfo* Thread;
  2516. Status = E_NOINTERFACE;
  2517. for (Thread = g_Process->m_ThreadHead;
  2518. Thread != NULL;
  2519. Thread = Thread->m_Next)
  2520. {
  2521. ULONG64 Teb;
  2522. Status = g_Target->GetThreadInfoTeb(Thread, 0, 0, &Teb);
  2523. if (Status != S_OK)
  2524. {
  2525. break;
  2526. }
  2527. if (Teb == Offset)
  2528. {
  2529. *Id = Thread->m_UserId;
  2530. Status = S_OK;
  2531. break;
  2532. }
  2533. }
  2534. }
  2535. LEAVE_ENGINE();
  2536. return Status;
  2537. }
  2538. STDMETHODIMP
  2539. DebugClient::GetCurrentThreadSystemId(
  2540. THIS_
  2541. OUT PULONG SysId
  2542. )
  2543. {
  2544. HRESULT Status;
  2545. ENTER_ENGINE();
  2546. if (IS_KERNEL_TARGET(g_Target))
  2547. {
  2548. Status = E_NOTIMPL;
  2549. }
  2550. else if (g_Thread == NULL)
  2551. {
  2552. Status = E_UNEXPECTED;
  2553. }
  2554. else
  2555. {
  2556. *SysId = g_Thread->m_SystemId;
  2557. Status = S_OK;
  2558. }
  2559. LEAVE_ENGINE();
  2560. return Status;
  2561. }
  2562. STDMETHODIMP
  2563. DebugClient::GetThreadIdBySystemId(
  2564. THIS_
  2565. IN ULONG SysId,
  2566. OUT PULONG Id
  2567. )
  2568. {
  2569. HRESULT Status;
  2570. ENTER_ENGINE();
  2571. if (IS_KERNEL_TARGET(g_Target))
  2572. {
  2573. Status = E_NOTIMPL;
  2574. }
  2575. else if (g_Process == NULL)
  2576. {
  2577. Status = E_UNEXPECTED;
  2578. }
  2579. else
  2580. {
  2581. ThreadInfo* Thread = g_Process->FindThreadBySystemId(SysId);
  2582. if (Thread != NULL)
  2583. {
  2584. *Id = Thread->m_UserId;
  2585. Status = S_OK;
  2586. }
  2587. else
  2588. {
  2589. Status = E_NOINTERFACE;
  2590. }
  2591. }
  2592. LEAVE_ENGINE();
  2593. return Status;
  2594. }
  2595. STDMETHODIMP
  2596. DebugClient::GetCurrentThreadHandle(
  2597. THIS_
  2598. OUT PULONG64 Handle
  2599. )
  2600. {
  2601. HRESULT Status;
  2602. ENTER_ENGINE();
  2603. if (g_Process == NULL)
  2604. {
  2605. Status = E_UNEXPECTED;
  2606. }
  2607. else
  2608. {
  2609. *Handle = g_Thread->m_Handle;
  2610. Status = S_OK;
  2611. }
  2612. LEAVE_ENGINE();
  2613. return Status;
  2614. }
  2615. STDMETHODIMP
  2616. DebugClient::GetThreadIdByHandle(
  2617. THIS_
  2618. IN ULONG64 Handle,
  2619. OUT PULONG Id
  2620. )
  2621. {
  2622. HRESULT Status;
  2623. ENTER_ENGINE();
  2624. if (g_Process == NULL)
  2625. {
  2626. Status = E_UNEXPECTED;
  2627. }
  2628. else
  2629. {
  2630. ThreadInfo* Thread = g_Process->FindThreadByHandle(Handle);
  2631. if (Thread != NULL)
  2632. {
  2633. *Id = Thread->m_UserId;
  2634. Status = S_OK;
  2635. }
  2636. else
  2637. {
  2638. Status = E_NOINTERFACE;
  2639. }
  2640. }
  2641. LEAVE_ENGINE();
  2642. return Status;
  2643. }
  2644. STDMETHODIMP
  2645. DebugClient::GetNumberProcesses(
  2646. THIS_
  2647. OUT PULONG Number
  2648. )
  2649. {
  2650. HRESULT Status;
  2651. ENTER_ENGINE();
  2652. if (!g_Target)
  2653. {
  2654. Status = E_UNEXPECTED;
  2655. }
  2656. else
  2657. {
  2658. *Number = g_Target->m_NumProcesses;
  2659. Status = S_OK;
  2660. }
  2661. LEAVE_ENGINE();
  2662. return Status;
  2663. }
  2664. STDMETHODIMP
  2665. DebugClient::GetProcessIdsByIndex(
  2666. THIS_
  2667. IN ULONG Start,
  2668. IN ULONG Count,
  2669. OUT OPTIONAL /* size_is(Count) */ PULONG Ids,
  2670. OUT OPTIONAL /* size_is(Count) */ PULONG SysIds
  2671. )
  2672. {
  2673. HRESULT Status;
  2674. ENTER_ENGINE();
  2675. if (!g_Target)
  2676. {
  2677. Status = E_UNEXPECTED;
  2678. goto EH_Exit;
  2679. }
  2680. ProcessInfo* Process;
  2681. ULONG Index;
  2682. if (Start >= g_Target->m_NumProcesses ||
  2683. Start + Count > g_Target->m_NumProcesses)
  2684. {
  2685. Status = E_INVALIDARG;
  2686. goto EH_Exit;
  2687. }
  2688. Index = 0;
  2689. for (Process = g_Target->m_ProcessHead;
  2690. Process != NULL;
  2691. Process = Process->m_Next)
  2692. {
  2693. if (Index >= Start && Index < Start + Count)
  2694. {
  2695. if (Ids != NULL)
  2696. {
  2697. *Ids++ = Process->m_UserId;
  2698. }
  2699. if (SysIds != NULL)
  2700. {
  2701. *SysIds++ = Process->m_SystemId;
  2702. }
  2703. }
  2704. Index++;
  2705. }
  2706. Status = S_OK;
  2707. EH_Exit:
  2708. LEAVE_ENGINE();
  2709. return Status;
  2710. }
  2711. STDMETHODIMP
  2712. DebugClient::GetCurrentProcessDataOffset(
  2713. THIS_
  2714. OUT PULONG64 Offset
  2715. )
  2716. {
  2717. HRESULT Status;
  2718. ENTER_ENGINE();
  2719. if (g_Thread == NULL)
  2720. {
  2721. Status = E_UNEXPECTED;
  2722. }
  2723. else
  2724. {
  2725. Status = g_Target->
  2726. GetProcessInfoDataOffset(g_Thread, 0, 0, Offset);
  2727. }
  2728. LEAVE_ENGINE();
  2729. return Status;
  2730. }
  2731. STDMETHODIMP
  2732. DebugClient::GetProcessIdByDataOffset(
  2733. THIS_
  2734. IN ULONG64 Offset,
  2735. OUT PULONG Id
  2736. )
  2737. {
  2738. HRESULT Status;
  2739. ENTER_ENGINE();
  2740. if (!g_Target)
  2741. {
  2742. Status = E_UNEXPECTED;
  2743. }
  2744. else if (IS_KERNEL_TARGET(g_Target))
  2745. {
  2746. Status = E_NOTIMPL;
  2747. }
  2748. else
  2749. {
  2750. ProcessInfo* Process;
  2751. Status = E_NOINTERFACE;
  2752. for (Process = g_Target->m_ProcessHead;
  2753. Process != NULL;
  2754. Process = Process->m_Next)
  2755. {
  2756. ULONG64 DataOffset;
  2757. Status = g_Target->
  2758. GetProcessInfoDataOffset(Process->m_ThreadHead,
  2759. 0, 0, &DataOffset);
  2760. if (Status != S_OK)
  2761. {
  2762. break;
  2763. }
  2764. if (DataOffset == Offset)
  2765. {
  2766. *Id = Process->m_UserId;
  2767. Status = S_OK;
  2768. break;
  2769. }
  2770. }
  2771. }
  2772. LEAVE_ENGINE();
  2773. return Status;
  2774. }
  2775. STDMETHODIMP
  2776. DebugClient::GetCurrentProcessPeb(
  2777. THIS_
  2778. OUT PULONG64 Offset
  2779. )
  2780. {
  2781. HRESULT Status;
  2782. ENTER_ENGINE();
  2783. if (g_Thread == NULL)
  2784. {
  2785. Status = E_UNEXPECTED;
  2786. }
  2787. else
  2788. {
  2789. Status = g_Target->GetProcessInfoPeb(g_Thread, 0, 0, Offset);
  2790. }
  2791. LEAVE_ENGINE();
  2792. return Status;
  2793. }
  2794. STDMETHODIMP
  2795. DebugClient::GetProcessIdByPeb(
  2796. THIS_
  2797. IN ULONG64 Offset,
  2798. OUT PULONG Id
  2799. )
  2800. {
  2801. HRESULT Status;
  2802. ENTER_ENGINE();
  2803. if (!g_Target)
  2804. {
  2805. Status = E_UNEXPECTED;
  2806. }
  2807. else if (IS_KERNEL_TARGET(g_Target))
  2808. {
  2809. Status = E_NOTIMPL;
  2810. }
  2811. else
  2812. {
  2813. ProcessInfo* Process;
  2814. Status = E_NOINTERFACE;
  2815. for (Process = g_Target->m_ProcessHead;
  2816. Process != NULL;
  2817. Process = Process->m_Next)
  2818. {
  2819. ULONG64 Peb;
  2820. Status = g_Target->GetProcessInfoPeb(Process->m_ThreadHead,
  2821. 0, 0, &Peb);
  2822. if (Status != S_OK)
  2823. {
  2824. break;
  2825. }
  2826. if (Peb == Offset)
  2827. {
  2828. *Id = Process->m_UserId;
  2829. Status = S_OK;
  2830. break;
  2831. }
  2832. }
  2833. }
  2834. LEAVE_ENGINE();
  2835. return Status;
  2836. }
  2837. STDMETHODIMP
  2838. DebugClient::GetCurrentProcessSystemId(
  2839. THIS_
  2840. OUT PULONG SysId
  2841. )
  2842. {
  2843. HRESULT Status;
  2844. ENTER_ENGINE();
  2845. if (IS_KERNEL_TARGET(g_Target))
  2846. {
  2847. Status = E_NOTIMPL;
  2848. }
  2849. else if (g_Process == NULL)
  2850. {
  2851. Status = E_UNEXPECTED;
  2852. }
  2853. else
  2854. {
  2855. *SysId = g_Process->m_SystemId;
  2856. Status = S_OK;
  2857. }
  2858. LEAVE_ENGINE();
  2859. return Status;
  2860. }
  2861. STDMETHODIMP
  2862. DebugClient::GetProcessIdBySystemId(
  2863. THIS_
  2864. IN ULONG SysId,
  2865. OUT PULONG Id
  2866. )
  2867. {
  2868. HRESULT Status;
  2869. ENTER_ENGINE();
  2870. if (!g_Target)
  2871. {
  2872. Status = E_UNEXPECTED;
  2873. }
  2874. else if (IS_KERNEL_TARGET(g_Target))
  2875. {
  2876. Status = E_NOTIMPL;
  2877. }
  2878. else
  2879. {
  2880. ProcessInfo* Process = g_Target->FindProcessBySystemId(SysId);
  2881. if (Process != NULL)
  2882. {
  2883. *Id = Process->m_UserId;
  2884. Status = S_OK;
  2885. }
  2886. else
  2887. {
  2888. Status = E_NOINTERFACE;
  2889. }
  2890. }
  2891. LEAVE_ENGINE();
  2892. return Status;
  2893. }
  2894. STDMETHODIMP
  2895. DebugClient::GetCurrentProcessHandle(
  2896. THIS_
  2897. OUT PULONG64 Handle
  2898. )
  2899. {
  2900. HRESULT Status;
  2901. ENTER_ENGINE();
  2902. if (g_Process == NULL)
  2903. {
  2904. Status = E_UNEXPECTED;
  2905. }
  2906. else
  2907. {
  2908. *Handle = g_Process->m_SysHandle;
  2909. Status = S_OK;
  2910. }
  2911. LEAVE_ENGINE();
  2912. return Status;
  2913. }
  2914. STDMETHODIMP
  2915. DebugClient::GetProcessIdByHandle(
  2916. THIS_
  2917. IN ULONG64 Handle,
  2918. OUT PULONG Id
  2919. )
  2920. {
  2921. HRESULT Status;
  2922. ENTER_ENGINE();
  2923. if (!g_Target)
  2924. {
  2925. Status = E_UNEXPECTED;
  2926. }
  2927. else
  2928. {
  2929. ProcessInfo* Process = g_Target->FindProcessByHandle(Handle);
  2930. if (Process != NULL)
  2931. {
  2932. *Id = Process->m_UserId;
  2933. Status = S_OK;
  2934. }
  2935. else
  2936. {
  2937. Status = E_NOINTERFACE;
  2938. }
  2939. }
  2940. LEAVE_ENGINE();
  2941. return Status;
  2942. }
  2943. STDMETHODIMP
  2944. DebugClient::GetCurrentProcessExecutableName(
  2945. THIS_
  2946. OUT OPTIONAL PSTR Buffer,
  2947. IN ULONG BufferSize,
  2948. OUT OPTIONAL PULONG ExeSize
  2949. )
  2950. {
  2951. HRESULT Status;
  2952. ENTER_ENGINE();
  2953. if (g_Process == NULL)
  2954. {
  2955. Status = E_UNEXPECTED;
  2956. }
  2957. else
  2958. {
  2959. Status = FillStringBuffer(g_Process->GetExecutableImageName(), 0,
  2960. Buffer, BufferSize, ExeSize);
  2961. }
  2962. LEAVE_ENGINE();
  2963. return Status;
  2964. }
  2965. STDMETHODIMP
  2966. DebugClient::GetCurrentProcessUpTime(
  2967. THIS_
  2968. OUT PULONG UpTime
  2969. )
  2970. {
  2971. HRESULT Status;
  2972. ENTER_ENGINE();
  2973. if (!IS_USER_TARGET(g_Target) || g_Process == NULL)
  2974. {
  2975. Status = E_UNEXPECTED;
  2976. }
  2977. else
  2978. {
  2979. ULONG64 LongUpTime;
  2980. LongUpTime = g_Target->GetProcessUpTimeN(g_Process);
  2981. if (LongUpTime == 0)
  2982. {
  2983. Status = E_NOINTERFACE;
  2984. }
  2985. else
  2986. {
  2987. *UpTime = FileTimeToTime(LongUpTime);
  2988. Status = S_OK;
  2989. }
  2990. }
  2991. LEAVE_ENGINE();
  2992. return Status;
  2993. }
  2994. STDMETHODIMP
  2995. DebugClient::GetImplicitThreadDataOffset(
  2996. THIS_
  2997. OUT PULONG64 Offset
  2998. )
  2999. {
  3000. HRESULT Status;
  3001. ENTER_ENGINE();
  3002. if (!IS_CUR_MACHINE_ACCESSIBLE())
  3003. {
  3004. Status = E_UNEXPECTED;
  3005. }
  3006. else
  3007. {
  3008. Status = g_Process->GetImplicitThreadData(g_Thread, Offset);
  3009. }
  3010. LEAVE_ENGINE();
  3011. return Status;
  3012. }
  3013. STDMETHODIMP
  3014. DebugClient::SetImplicitThreadDataOffset(
  3015. THIS_
  3016. IN ULONG64 Offset
  3017. )
  3018. {
  3019. HRESULT Status;
  3020. ENTER_ENGINE();
  3021. if (!IS_CUR_MACHINE_ACCESSIBLE())
  3022. {
  3023. Status = E_UNEXPECTED;
  3024. }
  3025. else
  3026. {
  3027. Status = g_Process->SetImplicitThreadData(g_Thread, Offset, FALSE);
  3028. }
  3029. LEAVE_ENGINE();
  3030. return Status;
  3031. }
  3032. STDMETHODIMP
  3033. DebugClient::GetImplicitProcessDataOffset(
  3034. THIS_
  3035. OUT PULONG64 Offset
  3036. )
  3037. {
  3038. HRESULT Status;
  3039. ENTER_ENGINE();
  3040. if (!IS_CUR_MACHINE_ACCESSIBLE())
  3041. {
  3042. Status = E_UNEXPECTED;
  3043. }
  3044. else
  3045. {
  3046. Status = g_Target->GetImplicitProcessData(g_Thread, Offset);
  3047. }
  3048. LEAVE_ENGINE();
  3049. return Status;
  3050. }
  3051. STDMETHODIMP
  3052. DebugClient::SetImplicitProcessDataOffset(
  3053. THIS_
  3054. IN ULONG64 Offset
  3055. )
  3056. {
  3057. HRESULT Status;
  3058. ENTER_ENGINE();
  3059. if (!IS_CUR_MACHINE_ACCESSIBLE())
  3060. {
  3061. Status = E_UNEXPECTED;
  3062. }
  3063. else
  3064. {
  3065. Status = g_Target->SetImplicitProcessData(g_Thread, Offset, FALSE);
  3066. }
  3067. LEAVE_ENGINE();
  3068. return Status;
  3069. }
  3070. void
  3071. ResetImplicitData(void)
  3072. {
  3073. if (g_Process)
  3074. {
  3075. g_Process->ResetImplicitData();
  3076. }
  3077. if (g_Target)
  3078. {
  3079. g_Target->ResetImplicitData();
  3080. }
  3081. }
  3082. void
  3083. SetImplicitProcessAndCache(ULONG64 Base, BOOL Ptes, BOOL ReloadUser)
  3084. {
  3085. BOOL OldPtes = g_Process->m_VirtualCache.m_ForceDecodePTEs;
  3086. if (Ptes && !Base)
  3087. {
  3088. // If the user has requested a reset to the default
  3089. // process with no translations we need to turn
  3090. // off translations immediately so that any
  3091. // existing base doesn't interfere with determining
  3092. // the default process.
  3093. g_Process->m_VirtualCache.SetForceDecodePtes(FALSE, g_Target);
  3094. }
  3095. if (g_Target->SetImplicitProcessData(g_Thread, Base, TRUE) == S_OK)
  3096. {
  3097. dprintf("Implicit process is now %s\n",
  3098. FormatAddr64(g_Target->m_ImplicitProcessData));
  3099. if (Ptes)
  3100. {
  3101. if (Base)
  3102. {
  3103. g_Process->m_VirtualCache.SetForceDecodePtes(TRUE, g_Target);
  3104. }
  3105. if (IS_REMOTE_KERNEL_TARGET(g_Target))
  3106. {
  3107. dprintf(".cache %sforcedecodeptes done\n",
  3108. Base != 0 ? "" : "no");
  3109. }
  3110. if (ReloadUser)
  3111. {
  3112. PCSTR ArgsRet;
  3113. g_Target->Reload(g_Thread, "/user", &ArgsRet);
  3114. }
  3115. }
  3116. if (Base && !g_Process->m_VirtualCache.m_ForceDecodePTEs &&
  3117. IS_REMOTE_KERNEL_TARGET(g_Target))
  3118. {
  3119. WarnOut("WARNING: .cache forcedecodeptes is not enabled\n");
  3120. }
  3121. }
  3122. else if (Ptes && !Base && OldPtes)
  3123. {
  3124. // Restore settings to the way they were.
  3125. g_Process->m_VirtualCache.SetForceDecodePtes(TRUE, g_Target);
  3126. }
  3127. }
  3128. HRESULT
  3129. SetScopeContextFromThreadData(ULONG64 ThreadBase, BOOL Verbose)
  3130. {
  3131. if (!ThreadBase)
  3132. {
  3133. if (GetCurrentScopeContext())
  3134. {
  3135. ResetCurrentScope();
  3136. }
  3137. return S_OK;
  3138. }
  3139. HRESULT Status;
  3140. DEBUG_STACK_FRAME StkFrame;
  3141. CROSS_PLATFORM_CONTEXT Context;
  3142. if ((Status = g_Target->
  3143. GetContextFromThreadStack(ThreadBase, &Context, Verbose)) != S_OK)
  3144. {
  3145. return Status;
  3146. }
  3147. g_Machine->GetScopeFrameFromContext(&Context, &StkFrame);
  3148. SetCurrentScope(&StkFrame, &Context, sizeof(Context));
  3149. return S_OK;
  3150. }
  3151. void
  3152. DotThread(PDOT_COMMAND Cmd, DebugClient* Client)
  3153. {
  3154. ULONG64 Base = 0;
  3155. BOOL Ptes = FALSE;
  3156. BOOL ReloadUser = FALSE;
  3157. if (!g_Thread)
  3158. {
  3159. error(BADTHREAD);
  3160. }
  3161. while (PeekChar() == '-' || *g_CurCmd == '/')
  3162. {
  3163. switch(*(++g_CurCmd))
  3164. {
  3165. case 'p':
  3166. Ptes = TRUE;
  3167. break;
  3168. case 'r':
  3169. ReloadUser = TRUE;
  3170. break;
  3171. default:
  3172. dprintf("Unknown option '%c'\n", *g_CurCmd);
  3173. break;
  3174. }
  3175. g_CurCmd++;
  3176. }
  3177. if (PeekChar() && *g_CurCmd != ';')
  3178. {
  3179. Base = GetExpression();
  3180. }
  3181. // Save the current setting in case things fail and
  3182. // it needs to be restored.
  3183. IMPLICIT_THREAD_SAVE Save;
  3184. g_Process->SaveImplicitThread(&Save);
  3185. if (g_Process->SetImplicitThreadData(g_Thread, Base, TRUE) == S_OK &&
  3186. (!IS_KERNEL_TARGET(g_Target) ||
  3187. SetScopeContextFromThreadData(Base, TRUE) == S_OK))
  3188. {
  3189. dprintf("Implicit thread is now %s\n",
  3190. FormatAddr64(g_Process->m_ImplicitThreadData));
  3191. if (IS_KERNEL_TARGET(g_Target) &&
  3192. g_Process->m_ImplicitThreadData &&
  3193. Ptes)
  3194. {
  3195. ULONG64 Process;
  3196. if (!Base || g_Target->
  3197. GetProcessInfoDataOffset(NULL, 0,
  3198. g_Process->m_ImplicitThreadData,
  3199. &Process) == S_OK)
  3200. {
  3201. SetImplicitProcessAndCache(Base ? Process : 0, Ptes,
  3202. ReloadUser);
  3203. }
  3204. else
  3205. {
  3206. ErrOut("Unable to get process of implicit thread\n");
  3207. }
  3208. }
  3209. }
  3210. else
  3211. {
  3212. g_Process->RestoreImplicitThread(&Save);
  3213. }
  3214. }
  3215. HRESULT
  3216. KernelPageIn(ULONG64 Process, ULONG64 Data, BOOL Kill)
  3217. {
  3218. HRESULT Status;
  3219. ULONG Work;
  3220. ULONG64 ExpDebuggerProcessKill = 0;
  3221. ULONG64 ExpDebuggerProcessAttach = 0;
  3222. ULONG64 ExpDebuggerPageIn = 0;
  3223. ULONG64 ExpDebuggerWork = 0;
  3224. if (!IS_LIVE_KERNEL_TARGET(g_Target))
  3225. {
  3226. ErrOut("This operation only works on live kernel debug sessions\n");
  3227. return E_NOTIMPL;
  3228. }
  3229. GetOffsetFromSym(g_Process,
  3230. "nt!ExpDebuggerProcessKill", &ExpDebuggerProcessKill,
  3231. NULL);
  3232. GetOffsetFromSym(g_Process,
  3233. "nt!ExpDebuggerProcessAttach", &ExpDebuggerProcessAttach,
  3234. NULL);
  3235. GetOffsetFromSym(g_Process,
  3236. "nt!ExpDebuggerPageIn", &ExpDebuggerPageIn, NULL);
  3237. GetOffsetFromSym(g_Process,
  3238. "nt!ExpDebuggerWork", &ExpDebuggerWork, NULL);
  3239. if ((Kill && !ExpDebuggerProcessKill) ||
  3240. !ExpDebuggerProcessAttach ||
  3241. !ExpDebuggerPageIn ||
  3242. !ExpDebuggerWork)
  3243. {
  3244. ErrOut("Symbols are wrong or this version of the operating system "
  3245. "does not support this command\n");
  3246. return E_NOTIMPL;
  3247. }
  3248. Status = g_Target->ReadAllVirtual(g_Process,
  3249. ExpDebuggerWork, &Work, sizeof(Work));
  3250. if (Status != S_OK)
  3251. {
  3252. ErrOut("Could not determine status or debugger worker thread\n");
  3253. return HRESULT_FROM_WIN32(ERROR_BUSY);
  3254. }
  3255. else if (Work > 1)
  3256. {
  3257. ErrOut("Debugger worker thread has pending command\n");
  3258. return HRESULT_FROM_WIN32(ERROR_BUSY);
  3259. }
  3260. if (Kill)
  3261. {
  3262. Status = g_Target->WritePointer(g_Process, g_Machine,
  3263. ExpDebuggerProcessKill,
  3264. Process);
  3265. }
  3266. else
  3267. {
  3268. Status = g_Target->WritePointer(g_Process, g_Machine,
  3269. ExpDebuggerProcessAttach,
  3270. Process);
  3271. if (Status == S_OK)
  3272. {
  3273. Status = g_Target->WritePointer(g_Process, g_Machine,
  3274. ExpDebuggerPageIn, Data);
  3275. }
  3276. }
  3277. if (Status == S_OK)
  3278. {
  3279. Work = 1;
  3280. Status = g_Target->
  3281. WriteAllVirtual(g_Process, ExpDebuggerWork, &Work, sizeof(Work));
  3282. }
  3283. if (Status != S_OK)
  3284. {
  3285. ErrOut("Could not queue operation to debugger worker thread\n");
  3286. }
  3287. return Status;
  3288. }
  3289. void
  3290. DotProcess(PDOT_COMMAND Cmd, DebugClient* Client)
  3291. {
  3292. if (!g_Thread)
  3293. {
  3294. error(BADTHREAD);
  3295. }
  3296. ULONG64 Base = 0;
  3297. BOOL Ptes = FALSE;
  3298. BOOL Invasive = FALSE;
  3299. BOOL ReloadUser = FALSE;
  3300. while (PeekChar() == '-' || *g_CurCmd == '/')
  3301. {
  3302. switch(*(++g_CurCmd))
  3303. {
  3304. case 'i':
  3305. Invasive = TRUE;
  3306. break;
  3307. case 'p':
  3308. Ptes = TRUE;
  3309. break;
  3310. case 'r':
  3311. ReloadUser = TRUE;
  3312. break;
  3313. default:
  3314. dprintf("Unknown option '%c'\n", *g_CurCmd);
  3315. break;
  3316. }
  3317. g_CurCmd++;
  3318. }
  3319. if (PeekChar() && *g_CurCmd != ';')
  3320. {
  3321. Base = GetExpression();
  3322. }
  3323. if (Invasive)
  3324. {
  3325. if (S_OK == KernelPageIn(Base, 0, FALSE))
  3326. {
  3327. dprintf("You need to continue execution (press 'g' <enter>) "
  3328. "for the context\nto be switched. When the debugger "
  3329. "breaks in again, you will be in\nthe new process "
  3330. "context.\n");
  3331. }
  3332. return;
  3333. }
  3334. SetImplicitProcessAndCache(Base, Ptes, ReloadUser);
  3335. }
  3336. void
  3337. DotFiber(PDOT_COMMAND Cmd, DebugClient* Client)
  3338. {
  3339. ULONG64 Base = 0;
  3340. if (!g_Process)
  3341. {
  3342. error(BADPROCESS);
  3343. }
  3344. if (PeekChar() && *g_CurCmd != ';')
  3345. {
  3346. Base = GetExpression();
  3347. }
  3348. if (Base)
  3349. {
  3350. HRESULT Status;
  3351. DEBUG_STACK_FRAME Frame;
  3352. CROSS_PLATFORM_CONTEXT Context;
  3353. if ((Status = g_Machine->GetContextFromFiber(g_Process, Base, &Context,
  3354. TRUE)) != S_OK)
  3355. {
  3356. return;
  3357. }
  3358. g_Machine->GetScopeFrameFromContext(&Context, &Frame);
  3359. SetCurrentScope(&Frame, &Context, sizeof(Context));
  3360. if (StackTrace(Client,
  3361. Frame.FrameOffset, Frame.StackOffset,
  3362. Frame.InstructionOffset, STACK_NO_DEFAULT,
  3363. &Frame, 1, 0, 0, FALSE) != 1)
  3364. {
  3365. ErrOut("Unable to walk fiber stack\n");
  3366. ResetCurrentScope();
  3367. }
  3368. }
  3369. else if (GetCurrentScopeContext())
  3370. {
  3371. dprintf("Resetting default context\n");
  3372. ResetCurrentScope();
  3373. }
  3374. }
  3375. void
  3376. DotKernelKill(PDOT_COMMAND Cmd, DebugClient* Client)
  3377. {
  3378. ULONG64 Process = 0;
  3379. if (PeekChar() && *g_CurCmd != ';')
  3380. {
  3381. Process = GetExpression();
  3382. }
  3383. if (Process)
  3384. {
  3385. KernelPageIn(Process, 0, TRUE);
  3386. }
  3387. }
  3388. void
  3389. DotPageIn(PDOT_COMMAND Cmd, DebugClient* Client)
  3390. {
  3391. ULONG64 Process = 0;
  3392. ULONG64 Data = 0;
  3393. while (PeekChar() == '-' || *g_CurCmd == '/')
  3394. {
  3395. switch(*(++g_CurCmd))
  3396. {
  3397. case 'p':
  3398. g_CurCmd++;
  3399. Process = GetExpression();
  3400. break;
  3401. default:
  3402. g_CurCmd++;
  3403. dprintf("Unknown option '%c'\n", *g_CurCmd);
  3404. break;
  3405. }
  3406. }
  3407. if (PeekChar() && *g_CurCmd != ';')
  3408. {
  3409. Data = GetExpression();
  3410. }
  3411. if (!Data)
  3412. {
  3413. ErrOut("Pagein requires an address to be specified\n");
  3414. return;
  3415. }
  3416. if (Data > g_Target->m_SystemRangeStart)
  3417. {
  3418. ErrOut("Pagein operations are only supported for user mode"
  3419. " addresses due to limitations in the memory manager\n");
  3420. return;
  3421. }
  3422. //
  3423. // Modify kernel state to do the pagein
  3424. //
  3425. if (S_OK != KernelPageIn(Process, Data, FALSE))
  3426. {
  3427. ErrOut("PageIn for address %s, process %s failed\n",
  3428. FormatAddr64(Data),
  3429. FormatAddr64(Process));
  3430. }
  3431. else
  3432. {
  3433. dprintf("You need to continue execution (press 'g' <enter>) for "
  3434. "the pagein to be brought in. When the debugger breaks in "
  3435. "again, the page will be present.\n");
  3436. }
  3437. }
  3438. STDMETHODIMP
  3439. DebugClient::GetEventSystem(
  3440. THIS_
  3441. OUT PULONG Id
  3442. )
  3443. {
  3444. ENTER_ENGINE();
  3445. HRESULT Status;
  3446. if (!g_EventTarget)
  3447. {
  3448. Status = E_UNEXPECTED;
  3449. }
  3450. else
  3451. {
  3452. *Id = g_EventTarget->m_UserId;
  3453. Status = S_OK;
  3454. }
  3455. LEAVE_ENGINE();
  3456. return Status;
  3457. }
  3458. STDMETHODIMP
  3459. DebugClient::GetCurrentSystemId(
  3460. THIS_
  3461. OUT PULONG Id
  3462. )
  3463. {
  3464. ENTER_ENGINE();
  3465. HRESULT Status;
  3466. if (!g_Target)
  3467. {
  3468. Status = E_UNEXPECTED;
  3469. }
  3470. else
  3471. {
  3472. *Id = g_Target->m_UserId;
  3473. Status = S_OK;
  3474. }
  3475. LEAVE_ENGINE();
  3476. return Status;
  3477. }
  3478. STDMETHODIMP
  3479. DebugClient::SetCurrentSystemId(
  3480. THIS_
  3481. IN ULONG Id
  3482. )
  3483. {
  3484. HRESULT Status;
  3485. ENTER_ENGINE();
  3486. if (IS_RUNNING(g_CmdState))
  3487. {
  3488. Status = E_UNEXPECTED;
  3489. }
  3490. else
  3491. {
  3492. TargetInfo* Target = FindTargetByUserId(Id);
  3493. if (Target && Target == g_Target)
  3494. {
  3495. // Requested system is already current.
  3496. Status = S_OK;
  3497. }
  3498. else if (Target)
  3499. {
  3500. ThreadInfo* Thread = NULL;
  3501. //
  3502. // Systems can exist without processes and threads
  3503. // so allow such a system to be current even
  3504. // if there is no process or thread.
  3505. //
  3506. if (Target->m_CurrentProcess == NULL)
  3507. {
  3508. Target->m_CurrentProcess = Target->m_ProcessHead;
  3509. }
  3510. if (Target->m_CurrentProcess)
  3511. {
  3512. if (Target->m_CurrentProcess->m_CurrentThread == NULL)
  3513. {
  3514. Target->m_CurrentProcess->m_CurrentThread =
  3515. Target->m_CurrentProcess->m_ThreadHead;
  3516. }
  3517. Thread = Target->m_CurrentProcess->m_CurrentThread;
  3518. }
  3519. if (Thread)
  3520. {
  3521. Status = Target->SwitchToTarget(g_Target);
  3522. if (Status == S_OK)
  3523. {
  3524. SetCurrentThread(Thread, FALSE);
  3525. ResetCurrentScopeLazy();
  3526. }
  3527. else if (Status == S_FALSE)
  3528. {
  3529. // The switch requires a wait.
  3530. Status = RawWaitForEvent(DEBUG_WAIT_DEFAULT, INFINITE);
  3531. }
  3532. }
  3533. else
  3534. {
  3535. SetLayersFromTarget(Target);
  3536. // Notify that there is no current thread.
  3537. NotifyChangeEngineState(DEBUG_CES_CURRENT_THREAD,
  3538. DEBUG_ANY_ID, TRUE);
  3539. Status = S_OK;
  3540. }
  3541. }
  3542. else
  3543. {
  3544. Status = E_NOINTERFACE;
  3545. }
  3546. }
  3547. LEAVE_ENGINE();
  3548. return Status;
  3549. }
  3550. STDMETHODIMP
  3551. DebugClient::GetNumberSystems(
  3552. THIS_
  3553. OUT PULONG Number
  3554. )
  3555. {
  3556. HRESULT Status;
  3557. ENTER_ENGINE();
  3558. *Number = g_NumberTargets;
  3559. Status = S_OK;
  3560. LEAVE_ENGINE();
  3561. return Status;
  3562. }
  3563. STDMETHODIMP
  3564. DebugClient::GetSystemIdsByIndex(
  3565. THIS_
  3566. IN ULONG Start,
  3567. IN ULONG Count,
  3568. OUT /* size_is(Count) */ PULONG Ids
  3569. )
  3570. {
  3571. HRESULT Status;
  3572. ENTER_ENGINE();
  3573. TargetInfo* Target;
  3574. ULONG Index;
  3575. if (Start >= g_NumberTargets ||
  3576. Start + Count > g_NumberTargets)
  3577. {
  3578. Status = E_INVALIDARG;
  3579. goto EH_Exit;
  3580. }
  3581. Index = 0;
  3582. ForAllLayersToTarget()
  3583. {
  3584. if (Index >= Start && Index < Start + Count)
  3585. {
  3586. if (Ids != NULL)
  3587. {
  3588. *Ids++ = Target->m_UserId;
  3589. }
  3590. }
  3591. Index++;
  3592. }
  3593. Status = S_OK;
  3594. EH_Exit:
  3595. LEAVE_ENGINE();
  3596. return Status;
  3597. }
  3598. STDMETHODIMP
  3599. DebugClient::GetTotalNumberThreadsAndProcesses(
  3600. THIS_
  3601. OUT PULONG TotalThreads,
  3602. OUT PULONG TotalProcesses,
  3603. OUT PULONG LargestProcessThreads,
  3604. OUT PULONG LargestSystemThreads,
  3605. OUT PULONG LargestSystemProcesses
  3606. )
  3607. {
  3608. HRESULT Status;
  3609. ENTER_ENGINE();
  3610. ULONG TotThreads = 0;
  3611. ULONG TotProcs = 0;
  3612. ULONG LargePt = 0;
  3613. ULONG LargeSt = 0;
  3614. ULONG LargeSp = 0;
  3615. TargetInfo* Target;
  3616. ForAllLayersToTarget()
  3617. {
  3618. TotThreads += Target->m_TotalNumberThreads;
  3619. TotProcs += Target->m_NumProcesses;
  3620. if (Target->m_MaxThreadsInProcess > LargePt)
  3621. {
  3622. LargePt = Target->m_MaxThreadsInProcess;
  3623. }
  3624. if (Target->m_TotalNumberThreads > LargeSt)
  3625. {
  3626. LargeSt = Target->m_TotalNumberThreads;
  3627. }
  3628. if (Target->m_NumProcesses > LargeSp)
  3629. {
  3630. LargeSp = Target->m_NumProcesses;
  3631. }
  3632. }
  3633. *TotalThreads = TotThreads;
  3634. *TotalProcesses = TotProcs;
  3635. *LargestProcessThreads = LargePt;
  3636. *LargestSystemThreads = LargeSt;
  3637. *LargestSystemProcesses = LargeSp;
  3638. Status = S_OK;
  3639. LEAVE_ENGINE();
  3640. return Status;
  3641. }
  3642. STDMETHODIMP
  3643. DebugClient::GetCurrentSystemServer(
  3644. THIS_
  3645. OUT PULONG64 Server
  3646. )
  3647. {
  3648. HRESULT Status;
  3649. ENTER_ENGINE();
  3650. if (!g_Target)
  3651. {
  3652. Status = E_UNEXPECTED;
  3653. }
  3654. else
  3655. {
  3656. *Server = (!IS_LIVE_USER_TARGET(g_Target) ||
  3657. ((LiveUserTargetInfo*)g_Target)->m_Local) ?
  3658. 0 : (ULONG64)((LiveUserTargetInfo*)g_Target)->m_Services;
  3659. Status = S_OK;
  3660. }
  3661. LEAVE_ENGINE();
  3662. return Status;
  3663. }
  3664. STDMETHODIMP
  3665. DebugClient::GetSystemByServer(
  3666. THIS_
  3667. IN ULONG64 Server,
  3668. OUT PULONG Id
  3669. )
  3670. {
  3671. HRESULT Status;
  3672. ENTER_ENGINE();
  3673. if (!g_Target)
  3674. {
  3675. Status = E_UNEXPECTED;
  3676. }
  3677. else
  3678. {
  3679. TargetInfo* Target = FindTargetByServer(Server);
  3680. if (Target)
  3681. {
  3682. *Id = Target->m_UserId;
  3683. Status = S_OK;
  3684. }
  3685. else
  3686. {
  3687. Status = E_NOINTERFACE;
  3688. }
  3689. }
  3690. LEAVE_ENGINE();
  3691. return Status;
  3692. }
  3693. STDMETHODIMP
  3694. DebugClient::GetCurrentSystemServerName(
  3695. THIS_
  3696. OUT OPTIONAL PSTR Buffer,
  3697. IN ULONG BufferSize,
  3698. OUT OPTIONAL PULONG NameSize
  3699. )
  3700. {
  3701. HRESULT Status;
  3702. ENTER_ENGINE();
  3703. if (!g_Target)
  3704. {
  3705. Status = E_UNEXPECTED;
  3706. }
  3707. else
  3708. {
  3709. Status = g_Target->
  3710. GetDescription(Buffer, BufferSize, NameSize);
  3711. }
  3712. LEAVE_ENGINE();
  3713. return Status;
  3714. }