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.

3407 lines
75 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Debug client implementation.
  4. //
  5. // Copyright (C) Microsoft Corporation, 1999-2002.
  6. //
  7. //----------------------------------------------------------------------------
  8. #include "ntsdp.hpp"
  9. #include "dbgver.h"
  10. #define VER_STRING(Specific) \
  11. "\n" \
  12. "Microsoft (R) Windows " Specific \
  13. " Version " VER_PRODUCTVERSION_STR \
  14. "\n" VER_LEGALCOPYRIGHT_STR \
  15. "\n" \
  16. "\n"
  17. PCHAR g_WinVersionString = VER_STRING("Debugger");
  18. BOOL g_VersionMessage;
  19. ULONG g_SessionThread;
  20. ULONG g_SystemAllocGranularity;
  21. BOOL g_QuietMode;
  22. ULONG g_OutputWidth = 80;
  23. PCSTR g_OutputLinePrefix;
  24. // The platform ID of the machine running the debugger. Note
  25. // that this may be different from g_TargetPlatformId, which
  26. // is the platform ID of the machine being debugged.
  27. ULONG g_DebuggerPlatformId;
  28. CRITICAL_SECTION g_QuickLock;
  29. CRITICAL_SECTION g_EngineLock;
  30. ULONG g_EngineNesting;
  31. // Events and storage space for returning event callback
  32. // status from an APC.
  33. HANDLE g_EventStatusWaiting;
  34. HANDLE g_EventStatusReady;
  35. ULONG g_EventStatus;
  36. // Named event to sleep on.
  37. HANDLE g_SleepPidEvent;
  38. API_VERSION g_EngApiVersion =
  39. {
  40. BUILD_MAJOR_VERSION, BUILD_MINOR_VERSION, API_VERSION_NUMBER, 0
  41. };
  42. API_VERSION g_DbgHelpVersion;
  43. WCHAR g_LastFailedDumpFileW[MAX_PATH];
  44. //----------------------------------------------------------------------------
  45. //
  46. // DebugClient.
  47. //
  48. //----------------------------------------------------------------------------
  49. // List of all clients.
  50. DebugClient* g_Clients;
  51. char g_InputBuffer[INPUT_BUFFER_SIZE];
  52. ULONG g_InputSequence;
  53. HANDLE g_InputEvent;
  54. ULONG g_InputSizeRequested;
  55. ULONG g_EngOptions;
  56. ULONG g_EngStatus;
  57. ULONG g_EngDefer;
  58. ULONG g_EngErr;
  59. // Some options set through the process options apply to
  60. // all processes and some are per-process. The global
  61. // options are collected here.
  62. ULONG g_GlobalProcOptions;
  63. #if DBG
  64. ULONG g_EnvOutMask;
  65. #endif
  66. DebugClient::DebugClient(void)
  67. {
  68. m_Next = NULL;
  69. m_Prev = NULL;
  70. m_Refs = 1;
  71. m_Flags = 0;
  72. m_ThreadId = ::GetCurrentThreadId();
  73. m_Thread = NULL;
  74. m_EventCb = NULL;
  75. m_EventInterest = 0;
  76. m_DispatchSema = NULL;
  77. m_InputCb = NULL;
  78. m_InputSequence = 0xffffffff;
  79. m_OutputCb = NULL;
  80. #if DBG
  81. m_OutMask = DEFAULT_OUT_MASK | g_EnvOutMask;
  82. #else
  83. m_OutMask = DEFAULT_OUT_MASK;
  84. #endif
  85. m_OutputWidth = 80;
  86. m_OutputLinePrefix = NULL;
  87. }
  88. DebugClient::~DebugClient(void)
  89. {
  90. // Most of the work is done in Destroy.
  91. if (m_Flags & CLIENT_IN_LIST)
  92. {
  93. Unlink();
  94. }
  95. }
  96. void
  97. DebugClient::Destroy(void)
  98. {
  99. // Clients cannot arbitrarily be removed from the client list
  100. // or their memory deleted due to the possibility of a callback
  101. // loop occurring at the same time. Instead clients are left
  102. // in the list and zeroed out to prevent further callbacks
  103. // from occurring.
  104. // XXX drewb - This memory needs to be reclaimed at some
  105. // point, but there's no simple safe time to do so since
  106. // callbacks can occur at any time. Clients are very small
  107. // right now so the leakage is negligible.
  108. m_Flags = (m_Flags & ~(CLIENT_REMOTE | CLIENT_PRIMARY)) |
  109. CLIENT_DESTROYED;
  110. //
  111. // Remove any references from breakpoints this client added.
  112. //
  113. TargetInfo* Target;
  114. ProcessInfo* Process;
  115. Breakpoint* Bp;
  116. ForAllLayersToProcess()
  117. {
  118. for (Bp = Process->m_Breakpoints; Bp != NULL; Bp = Bp->m_Next)
  119. {
  120. if (Bp->m_Adder == this)
  121. {
  122. Bp->m_Adder = NULL;
  123. }
  124. }
  125. }
  126. if (m_Thread != NULL)
  127. {
  128. CloseHandle(m_Thread);
  129. m_Thread = NULL;
  130. }
  131. m_EventInterest = 0;
  132. RELEASE(m_EventCb);
  133. if (m_DispatchSema != NULL)
  134. {
  135. CloseHandle(m_DispatchSema);
  136. m_DispatchSema = NULL;
  137. }
  138. RELEASE(m_InputCb);
  139. m_InputSequence = 0xffffffff;
  140. RELEASE(m_OutputCb);
  141. m_OutMask = 0;
  142. CollectOutMasks();
  143. }
  144. STDMETHODIMP
  145. DebugClient::QueryInterface(
  146. THIS_
  147. IN REFIID InterfaceId,
  148. OUT PVOID* Interface
  149. )
  150. {
  151. HRESULT Status;
  152. *Interface = NULL;
  153. Status = S_OK;
  154. // Interface specific casts are necessary in order to
  155. // get the right vtable pointer in our multiple
  156. // inheritance scheme.
  157. if (DbgIsEqualIID(InterfaceId, IID_IUnknown) ||
  158. DbgIsEqualIID(InterfaceId, IID_IDebugClient) ||
  159. DbgIsEqualIID(InterfaceId, IID_IDebugClient2) ||
  160. DbgIsEqualIID(InterfaceId, IID_IDebugClient3) ||
  161. DbgIsEqualIID(InterfaceId, IID_IDebugClient4))
  162. {
  163. *Interface = (IDebugClientN *)this;
  164. }
  165. else if (DbgIsEqualIID(InterfaceId, IID_IDebugAdvanced))
  166. {
  167. *Interface = (IDebugAdvancedN *)this;
  168. }
  169. else if (DbgIsEqualIID(InterfaceId, IID_IDebugControl) ||
  170. DbgIsEqualIID(InterfaceId, IID_IDebugControl2) ||
  171. DbgIsEqualIID(InterfaceId, IID_IDebugControl3))
  172. {
  173. *Interface = (IDebugControlN *)this;
  174. }
  175. else if (DbgIsEqualIID(InterfaceId, IID_IDebugDataSpaces) ||
  176. DbgIsEqualIID(InterfaceId, IID_IDebugDataSpaces2) ||
  177. DbgIsEqualIID(InterfaceId, IID_IDebugDataSpaces3))
  178. {
  179. *Interface = (IDebugDataSpacesN *)this;
  180. }
  181. else if (DbgIsEqualIID(InterfaceId, IID_IDebugRegisters))
  182. {
  183. *Interface = (IDebugRegistersN *)this;
  184. }
  185. else if (DbgIsEqualIID(InterfaceId, IID_IDebugSymbols) ||
  186. DbgIsEqualIID(InterfaceId, IID_IDebugSymbols2))
  187. {
  188. *Interface = (IDebugSymbolsN *)this;
  189. }
  190. else if (DbgIsEqualIID(InterfaceId, IID_IDebugSystemObjects) ||
  191. DbgIsEqualIID(InterfaceId, IID_IDebugSystemObjects2) ||
  192. DbgIsEqualIID(InterfaceId, IID_IDebugSystemObjects3))
  193. {
  194. *Interface = (IDebugSystemObjectsN *)this;
  195. }
  196. else
  197. {
  198. Status = E_NOINTERFACE;
  199. }
  200. if (Status == S_OK)
  201. {
  202. AddRef();
  203. }
  204. return Status;
  205. }
  206. STDMETHODIMP_(ULONG)
  207. DebugClient::AddRef(
  208. THIS
  209. )
  210. {
  211. return InterlockedIncrement((PLONG)&m_Refs);
  212. }
  213. STDMETHODIMP_(ULONG)
  214. DebugClient::Release(
  215. THIS
  216. )
  217. {
  218. LONG Refs = InterlockedDecrement((PLONG)&m_Refs);
  219. if (Refs == 0)
  220. {
  221. Destroy();
  222. }
  223. return Refs;
  224. }
  225. STDMETHODIMP
  226. DebugClient::AttachKernel(
  227. THIS_
  228. IN ULONG Flags,
  229. IN OPTIONAL PCSTR ConnectOptions
  230. )
  231. {
  232. HRESULT Status;
  233. ULONG Qual;
  234. if (
  235. #if DEBUG_ATTACH_KERNEL_CONNECTION > 0
  236. Flags < DEBUG_ATTACH_KERNEL_CONNECTION ||
  237. #endif
  238. Flags > DEBUG_ATTACH_EXDI_DRIVER)
  239. {
  240. return E_INVALIDARG;
  241. }
  242. if (Flags == DEBUG_ATTACH_LOCAL_KERNEL)
  243. {
  244. if (ConnectOptions != NULL)
  245. {
  246. return E_INVALIDARG;
  247. }
  248. if (g_DebuggerPlatformId != VER_PLATFORM_WIN32_NT)
  249. {
  250. return E_UNEXPECTED;
  251. }
  252. Qual = DEBUG_KERNEL_LOCAL;
  253. }
  254. else if (Flags == DEBUG_ATTACH_EXDI_DRIVER)
  255. {
  256. Qual = DEBUG_KERNEL_EXDI_DRIVER;
  257. }
  258. else
  259. {
  260. Qual = DEBUG_KERNEL_CONNECTION;
  261. }
  262. ENTER_ENGINE();
  263. TargetInfo* Target;
  264. if ((Status = LiveKernelInitialize(this, Qual, ConnectOptions,
  265. &Target)) == S_OK)
  266. {
  267. DBG_ASSERT(!g_SessionThread ||
  268. g_SessionThread == ::GetCurrentThreadId());
  269. g_SessionThread = ::GetCurrentThreadId();
  270. g_Target = Target;
  271. InitializePrimary();
  272. }
  273. LEAVE_ENGINE();
  274. return Status;
  275. }
  276. STDMETHODIMP
  277. DebugClient::GetKernelConnectionOptions(
  278. THIS_
  279. OUT OPTIONAL PSTR Buffer,
  280. IN ULONG BufferSize,
  281. OUT OPTIONAL PULONG OptionsSize
  282. )
  283. {
  284. if (BufferSize == 0)
  285. {
  286. return E_INVALIDARG;
  287. }
  288. HRESULT Status;
  289. ENTER_ENGINE();
  290. ConnLiveKernelTargetInfo* KdTarg = (ConnLiveKernelTargetInfo*)g_Target;
  291. if (!IS_CONN_KERNEL_TARGET(g_Target) ||
  292. KdTarg->m_Transport == NULL)
  293. {
  294. Status = E_UNEXPECTED;
  295. goto Exit;
  296. }
  297. char LocalBuf[4 * (MAX_PARAM_NAME + MAX_PARAM_VALUE + 16)];
  298. KdTarg->m_Transport->GetParameters(LocalBuf, DIMA(LocalBuf));
  299. Status = FillStringBuffer(LocalBuf, 0,
  300. Buffer, BufferSize, OptionsSize);
  301. Exit:
  302. LEAVE_ENGINE();
  303. return Status;
  304. }
  305. STDMETHODIMP
  306. DebugClient::SetKernelConnectionOptions(
  307. THIS_
  308. IN PCSTR Options
  309. )
  310. {
  311. ConnLiveKernelTargetInfo* KdTarg = (ConnLiveKernelTargetInfo*)g_Target;
  312. if (!IS_CONN_KERNEL_TARGET(g_Target) ||
  313. KdTarg->m_Transport == NULL)
  314. {
  315. return E_UNEXPECTED;
  316. }
  317. // This method is reentrant.
  318. if (!_strcmpi(Options, "resync"))
  319. {
  320. KdTarg->m_Transport->m_Resync = TRUE;
  321. }
  322. else if (!_strcmpi(Options, "cycle_speed"))
  323. {
  324. KdTarg->m_Transport->CycleSpeed();
  325. }
  326. else
  327. {
  328. return E_NOINTERFACE;
  329. }
  330. return S_OK;
  331. }
  332. DBGRPC_SIMPLE_FACTORY(LiveUserDebugServices, IID_IUserDebugServices, \
  333. "Remote Process Server", (TRUE))
  334. LiveUserDebugServicesFactory g_LiveUserDebugServicesFactory;
  335. STDMETHODIMP
  336. DebugClient::StartProcessServer(
  337. THIS_
  338. IN ULONG Flags,
  339. IN PCSTR Options,
  340. IN PVOID Reserved
  341. )
  342. {
  343. if (Flags <= DEBUG_CLASS_KERNEL || Flags > DEBUG_CLASS_USER_WINDOWS)
  344. {
  345. return E_INVALIDARG;
  346. }
  347. // XXX drewb - Turn reserved into public IUserDebugServices
  348. // parameter so that a server can be started over arbitrary services.
  349. if (Reserved != NULL)
  350. {
  351. return E_NOTIMPL;
  352. }
  353. HRESULT Status;
  354. ENTER_ENGINE();
  355. if (g_SymOptions & SYMOPT_SECURE)
  356. {
  357. Status = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
  358. }
  359. else
  360. {
  361. DbgRpcClientObjectFactory* Factory;
  362. switch(Flags)
  363. {
  364. case DEBUG_CLASS_USER_WINDOWS:
  365. Factory = &g_LiveUserDebugServicesFactory;
  366. Status = DbgRpcCreateServer(Options, Factory, FALSE);
  367. break;
  368. default:
  369. // Flags has already been validated, but check
  370. // to prevent PREfast warnings.
  371. Status = E_INVALIDARG;
  372. break;
  373. }
  374. }
  375. LEAVE_ENGINE();
  376. return Status;
  377. }
  378. STDMETHODIMP
  379. DebugClient::ConnectProcessServer(
  380. THIS_
  381. IN PCSTR RemoteOptions,
  382. OUT PULONG64 Server
  383. )
  384. {
  385. HRESULT Status;
  386. ENTER_ENGINE();
  387. if (g_SymOptions & SYMOPT_SECURE)
  388. {
  389. Status = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
  390. }
  391. else
  392. {
  393. PUSER_DEBUG_SERVICES Services;
  394. if ((Status = DbgRpcConnectServer(RemoteOptions,
  395. &IID_IUserDebugServices,
  396. (IUnknown**)&Services)) == S_OK)
  397. {
  398. *Server = (ULONG64)(ULONG_PTR)Services;
  399. }
  400. }
  401. LEAVE_ENGINE();
  402. return Status;
  403. }
  404. STDMETHODIMP
  405. DebugClient::DisconnectProcessServer(
  406. THIS_
  407. IN ULONG64 Server
  408. )
  409. {
  410. HRESULT Status;
  411. ENTER_ENGINE();
  412. PVOID Object = (PVOID)(ULONG_PTR)Server;
  413. if (IsBadReadPtr(Object, sizeof(PVOID)) ||
  414. IsBadReadPtr(*(PVOID*)Object, 3 * sizeof(PVOID)) ||
  415. IsBadCodePtr(**(FARPROC**)Object))
  416. {
  417. Status = E_INVALIDARG;
  418. }
  419. else
  420. {
  421. ((PUSER_DEBUG_SERVICES)Server)->Release();
  422. Status = S_OK;
  423. }
  424. LEAVE_ENGINE();
  425. return Status;
  426. }
  427. STDMETHODIMP
  428. DebugClient::GetRunningProcessSystemIds(
  429. THIS_
  430. IN ULONG64 Server,
  431. OUT OPTIONAL /* size_is(Count) */ PULONG Ids,
  432. IN ULONG Count,
  433. OUT OPTIONAL PULONG ActualCount
  434. )
  435. {
  436. HRESULT Status;
  437. ENTER_ENGINE();
  438. if (g_SymOptions & SYMOPT_SECURE)
  439. {
  440. Status = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
  441. }
  442. else
  443. {
  444. Status = SERVER_SERVICES(Server)->
  445. GetProcessIds(Ids, Count, ActualCount);
  446. }
  447. LEAVE_ENGINE();
  448. return Status;
  449. }
  450. STDMETHODIMP
  451. DebugClient::GetRunningProcessSystemIdByExecutableName(
  452. THIS_
  453. IN ULONG64 Server,
  454. IN PCSTR ExeName,
  455. IN ULONG Flags,
  456. OUT PULONG Id
  457. )
  458. {
  459. HRESULT Status;
  460. PWSTR Wide;
  461. if ((Status = AnsiToWide(ExeName, &Wide)) == S_OK)
  462. {
  463. Status = GetRunningProcessSystemIdByExecutableNameWide(Server, Wide,
  464. Flags, Id);
  465. FreeWide(Wide);
  466. }
  467. return Status;
  468. }
  469. STDMETHODIMP
  470. DebugClient::GetRunningProcessSystemIdByExecutableNameWide(
  471. THIS_
  472. IN ULONG64 Server,
  473. IN PCWSTR ExeName,
  474. IN ULONG Flags,
  475. OUT PULONG Id
  476. )
  477. {
  478. if (Flags & ~(DEBUG_GET_PROC_DEFAULT |
  479. DEBUG_GET_PROC_FULL_MATCH |
  480. DEBUG_GET_PROC_ONLY_MATCH))
  481. {
  482. return E_INVALIDARG;
  483. }
  484. HRESULT Status;
  485. ENTER_ENGINE();
  486. if (g_SymOptions & SYMOPT_SECURE)
  487. {
  488. Status = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
  489. }
  490. else
  491. {
  492. Status = SERVER_SERVICES(Server)->
  493. GetProcessIdByExecutableNameW(ExeName, Flags, Id);
  494. }
  495. LEAVE_ENGINE();
  496. return Status;
  497. }
  498. STDMETHODIMP
  499. DebugClient::GetRunningProcessDescription(
  500. THIS_
  501. IN ULONG64 Server,
  502. IN ULONG SystemId,
  503. IN ULONG Flags,
  504. OUT OPTIONAL PSTR ExeName,
  505. IN ULONG ExeNameSize,
  506. OUT OPTIONAL PULONG ActualExeNameSize,
  507. OUT OPTIONAL PSTR Description,
  508. IN ULONG DescriptionSize,
  509. OUT OPTIONAL PULONG ActualDescriptionSize
  510. )
  511. {
  512. HRESULT Status;
  513. PWSTR ExeWide;
  514. PWSTR DescWide;
  515. if (ExeName && ExeNameSize > 0)
  516. {
  517. ExeWide = (PWSTR)malloc(ExeNameSize * sizeof(WCHAR));
  518. if (ExeWide == NULL)
  519. {
  520. return E_OUTOFMEMORY;
  521. }
  522. }
  523. else
  524. {
  525. ExeWide = NULL;
  526. }
  527. if (Description && DescriptionSize > 0)
  528. {
  529. DescWide = (PWSTR)malloc(DescriptionSize * sizeof(WCHAR));
  530. if (DescWide == NULL)
  531. {
  532. free(ExeWide);
  533. return E_OUTOFMEMORY;
  534. }
  535. }
  536. else
  537. {
  538. DescWide = NULL;
  539. }
  540. Status = GetRunningProcessDescriptionWide(Server, SystemId, Flags,
  541. ExeWide,
  542. ExeNameSize * sizeof(WCHAR),
  543. ActualExeNameSize,
  544. DescWide,
  545. DescriptionSize * sizeof(WCHAR),
  546. ActualDescriptionSize);
  547. if (SUCCEEDED(Status))
  548. {
  549. if ((ExeWide &&
  550. !WideCharToMultiByte(CP_ACP, 0, ExeWide, -1,
  551. ExeName, ExeNameSize,
  552. NULL, NULL)) ||
  553. (DescWide &&
  554. !WideCharToMultiByte(CP_ACP, 0, DescWide, -1,
  555. Description, DescriptionSize,
  556. NULL, NULL)))
  557. {
  558. Status = WIN32_LAST_STATUS();
  559. }
  560. }
  561. free(ExeWide);
  562. free(DescWide);
  563. return Status;
  564. }
  565. STDMETHODIMP
  566. DebugClient::GetRunningProcessDescriptionWide(
  567. THIS_
  568. IN ULONG64 Server,
  569. IN ULONG SystemId,
  570. IN ULONG Flags,
  571. OUT OPTIONAL PWSTR ExeName,
  572. IN ULONG ExeNameSize,
  573. OUT OPTIONAL PULONG ActualExeNameSize,
  574. OUT OPTIONAL PWSTR Description,
  575. IN ULONG DescriptionSize,
  576. OUT OPTIONAL PULONG ActualDescriptionSize
  577. )
  578. {
  579. HRESULT Status;
  580. if (Flags & ~(DEBUG_PROC_DESC_DEFAULT |
  581. DEBUG_PROC_DESC_NO_PATHS |
  582. DEBUG_PROC_DESC_NO_SERVICES |
  583. DEBUG_PROC_DESC_NO_MTS_PACKAGES |
  584. DEBUG_PROC_DESC_NO_COMMAND_LINE))
  585. {
  586. return E_INVALIDARG;
  587. }
  588. ENTER_ENGINE();
  589. if (g_SymOptions & SYMOPT_SECURE)
  590. {
  591. Status = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
  592. }
  593. else
  594. {
  595. Status = SERVER_SERVICES(Server)->
  596. GetProcessDescriptionW(SystemId, Flags,
  597. ExeName, ExeNameSize, ActualExeNameSize,
  598. Description, DescriptionSize,
  599. ActualDescriptionSize);
  600. }
  601. LEAVE_ENGINE();
  602. return Status;
  603. }
  604. #define ALL_ATTACH_FLAGS \
  605. (DEBUG_ATTACH_NONINVASIVE | \
  606. DEBUG_ATTACH_EXISTING | \
  607. DEBUG_ATTACH_NONINVASIVE_NO_SUSPEND | \
  608. DEBUG_ATTACH_INVASIVE_NO_INITIAL_BREAK | \
  609. DEBUG_ATTACH_INVASIVE_RESUME_PROCESS)
  610. BOOL
  611. InvalidAttachFlags(ULONG AttachFlags)
  612. {
  613. return
  614. (AttachFlags & ~ALL_ATTACH_FLAGS) ||
  615. (AttachFlags & (DEBUG_ATTACH_NONINVASIVE | DEBUG_ATTACH_EXISTING)) ==
  616. (DEBUG_ATTACH_NONINVASIVE | DEBUG_ATTACH_EXISTING) ||
  617. ((AttachFlags & DEBUG_ATTACH_NONINVASIVE_NO_SUSPEND) &&
  618. !(AttachFlags & DEBUG_ATTACH_NONINVASIVE)) ||
  619. ((AttachFlags & DEBUG_ATTACH_INVASIVE_NO_INITIAL_BREAK) &&
  620. (AttachFlags & (DEBUG_ATTACH_NONINVASIVE | DEBUG_ATTACH_EXISTING))) ||
  621. ((AttachFlags & DEBUG_ATTACH_INVASIVE_RESUME_PROCESS) &&
  622. (AttachFlags & (DEBUG_ATTACH_NONINVASIVE | DEBUG_ATTACH_EXISTING)));
  623. }
  624. STDMETHODIMP
  625. DebugClient::AttachProcess(
  626. THIS_
  627. IN ULONG64 Server,
  628. IN ULONG ProcessId,
  629. IN ULONG AttachFlags
  630. )
  631. {
  632. HRESULT Status;
  633. if (InvalidAttachFlags(AttachFlags))
  634. {
  635. return E_INVALIDARG;
  636. }
  637. ENTER_ENGINE();
  638. PPENDING_PROCESS Pending;
  639. TargetInfo* Target;
  640. BOOL CreatedTarget;
  641. if ((Status = UserInitialize(this, Server,
  642. &Target, &CreatedTarget)) != S_OK)
  643. {
  644. goto Exit;
  645. }
  646. if ((Status = Target->
  647. StartAttachProcess(ProcessId, AttachFlags, &Pending)) != S_OK)
  648. {
  649. if (CreatedTarget)
  650. {
  651. delete Target;
  652. }
  653. goto Exit;
  654. }
  655. DBG_ASSERT(!g_SessionThread ||
  656. g_SessionThread == ::GetCurrentThreadId());
  657. g_SessionThread = ::GetCurrentThreadId();
  658. InitializePrimary();
  659. g_Target = Target;
  660. Exit:
  661. LEAVE_ENGINE();
  662. return Status;
  663. }
  664. STDMETHODIMP
  665. DebugClient::CreateProcess(
  666. THIS_
  667. IN ULONG64 Server,
  668. IN PSTR CommandLine,
  669. IN ULONG CreateFlags
  670. )
  671. {
  672. HRESULT Status;
  673. PWSTR Wide;
  674. if ((Status = AnsiToWide(CommandLine, &Wide)) == S_OK)
  675. {
  676. Status = CreateProcessWide(Server, Wide, CreateFlags);
  677. FreeWide(Wide);
  678. }
  679. return Status;
  680. }
  681. STDMETHODIMP
  682. DebugClient::CreateProcessWide(
  683. THIS_
  684. IN ULONG64 Server,
  685. IN PWSTR CommandLine,
  686. IN ULONG CreateFlags
  687. )
  688. {
  689. HRESULT Status;
  690. ENTER_ENGINE();
  691. if (!(CreateFlags & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS)))
  692. {
  693. IUserDebugServices* Services = SERVER_SERVICES(Server);
  694. ULONG ProcId, ThreadId;
  695. ULONG64 ProcHandle, ThreadHandle;
  696. // The caller is not requesting that the process be
  697. // debugged, so we're just being used as a create process
  698. // wrapper. This is handy for remote process creation.
  699. Status = Services->
  700. CreateProcessW(CommandLine, CreateFlags,
  701. TRUE, g_StartProcessDir,
  702. &ProcId, &ThreadId,
  703. &ProcHandle, &ThreadHandle);
  704. if (Status == S_OK)
  705. {
  706. Services->CloseHandle(ProcHandle);
  707. Services->CloseHandle(ThreadHandle);
  708. }
  709. goto Exit;
  710. }
  711. PPENDING_PROCESS Pending;
  712. TargetInfo* Target;
  713. BOOL CreatedTarget;
  714. if ((Status = UserInitialize(this, Server,
  715. &Target, &CreatedTarget)) != S_OK)
  716. {
  717. goto Exit;
  718. }
  719. if ((Status = Target->
  720. StartCreateProcess(CommandLine, CreateFlags, NULL, NULL,
  721. &Pending)) != S_OK)
  722. {
  723. if (CreatedTarget)
  724. {
  725. delete Target;
  726. }
  727. goto Exit;
  728. }
  729. DBG_ASSERT(!g_SessionThread ||
  730. g_SessionThread == ::GetCurrentThreadId());
  731. g_SessionThread = ::GetCurrentThreadId();
  732. InitializePrimary();
  733. g_Target = Target;
  734. Exit:
  735. LEAVE_ENGINE();
  736. return Status;
  737. }
  738. STDMETHODIMP
  739. DebugClient::CreateProcessAndAttach(
  740. THIS_
  741. IN ULONG64 Server,
  742. IN OPTIONAL PSTR CommandLine,
  743. IN ULONG CreateFlags,
  744. IN ULONG ProcessId,
  745. IN ULONG AttachFlags
  746. )
  747. {
  748. HRESULT Status;
  749. PWSTR Wide;
  750. if (CommandLine)
  751. {
  752. Status = AnsiToWide(CommandLine, &Wide);
  753. }
  754. else
  755. {
  756. Wide = NULL;
  757. Status = S_OK;
  758. }
  759. if (Status == S_OK)
  760. {
  761. Status = CreateProcessAndAttachWide(Server, Wide, CreateFlags,
  762. ProcessId, AttachFlags);
  763. FreeWide(Wide);
  764. }
  765. return Status;
  766. }
  767. STDMETHODIMP
  768. DebugClient::CreateProcessAndAttachWide(
  769. THIS_
  770. IN ULONG64 Server,
  771. IN OPTIONAL PWSTR CommandLine,
  772. IN ULONG CreateFlags,
  773. IN ULONG ProcessId,
  774. IN ULONG AttachFlags
  775. )
  776. {
  777. if ((CommandLine == NULL && ProcessId == 0) ||
  778. InvalidAttachFlags(AttachFlags))
  779. {
  780. return E_INVALIDARG;
  781. }
  782. HRESULT Status;
  783. ENTER_ENGINE();
  784. PPENDING_PROCESS PendCreate, PendAttach;
  785. TargetInfo* Target;
  786. BOOL CreatedTarget;
  787. if ((Status = UserInitialize(this, Server,
  788. &Target, &CreatedTarget)) != S_OK)
  789. {
  790. goto Exit;
  791. }
  792. if (CommandLine != NULL)
  793. {
  794. if (ProcessId != 0)
  795. {
  796. CreateFlags |= CREATE_SUSPENDED;
  797. }
  798. if ((Status = Target->
  799. StartCreateProcess(CommandLine, CreateFlags, NULL, NULL,
  800. &PendCreate)) != S_OK)
  801. {
  802. goto EH_Target;
  803. }
  804. }
  805. if (ProcessId != 0)
  806. {
  807. if ((Status = Target->
  808. StartAttachProcess(ProcessId, AttachFlags,
  809. &PendAttach)) != S_OK)
  810. {
  811. goto EH_Target;
  812. }
  813. // If we previously created a process we need to wake
  814. // it up when we attach since we created it suspended.
  815. if (CommandLine != NULL)
  816. {
  817. g_ThreadToResume = PendCreate->InitialThreadHandle;
  818. g_ThreadToResumeServices =
  819. ((LiveUserTargetInfo*)Target)->m_Services;
  820. }
  821. }
  822. DBG_ASSERT(!g_SessionThread ||
  823. g_SessionThread == ::GetCurrentThreadId());
  824. g_SessionThread = ::GetCurrentThreadId();
  825. InitializePrimary();
  826. g_Target = Target;
  827. Exit:
  828. LEAVE_ENGINE();
  829. return Status;
  830. EH_Target:
  831. if (CreatedTarget)
  832. {
  833. delete Target;
  834. }
  835. LEAVE_ENGINE();
  836. return Status;
  837. }
  838. STDMETHODIMP
  839. DebugClient::GetProcessOptions(
  840. THIS_
  841. OUT PULONG Options
  842. )
  843. {
  844. HRESULT Status;
  845. ENTER_ENGINE();
  846. if (!IS_LIVE_USER_TARGET(g_Target))
  847. {
  848. Status = E_UNEXPECTED;
  849. }
  850. else
  851. {
  852. Status = S_OK;
  853. *Options = g_GlobalProcOptions;
  854. if (g_Process != NULL)
  855. {
  856. *Options |= g_Process->m_Options;
  857. }
  858. }
  859. LEAVE_ENGINE();
  860. return Status;
  861. }
  862. #define PROCESS_ALL \
  863. (DEBUG_PROCESS_DETACH_ON_EXIT | DEBUG_PROCESS_ONLY_THIS_PROCESS)
  864. #define PROCESS_GLOBAL \
  865. (DEBUG_PROCESS_DETACH_ON_EXIT)
  866. HRESULT
  867. ChangeProcessOptions(ULONG Options, ULONG OptFn)
  868. {
  869. if (Options & ~PROCESS_ALL)
  870. {
  871. return E_INVALIDARG;
  872. }
  873. HRESULT Status;
  874. ENTER_ENGINE();
  875. if (!IS_LIVE_USER_TARGET(g_Target))
  876. {
  877. Status = E_UNEXPECTED;
  878. goto Exit;
  879. }
  880. if (g_SymOptions & SYMOPT_SECURE)
  881. {
  882. Status = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
  883. goto Exit;
  884. }
  885. ULONG NewPer, OldPer;
  886. ULONG NewGlobal;
  887. switch(OptFn)
  888. {
  889. case OPTFN_ADD:
  890. if (Options & ~PROCESS_GLOBAL)
  891. {
  892. if (g_Process == NULL)
  893. {
  894. Status = E_UNEXPECTED;
  895. goto Exit;
  896. }
  897. OldPer = g_Process->m_Options;
  898. NewPer = OldPer | (Options & ~PROCESS_GLOBAL);
  899. }
  900. else
  901. {
  902. NewPer = 0;
  903. OldPer = 0;
  904. }
  905. NewGlobal = g_GlobalProcOptions | (Options & PROCESS_GLOBAL);
  906. break;
  907. case OPTFN_REMOVE:
  908. if (Options & ~PROCESS_GLOBAL)
  909. {
  910. if (g_Process == NULL)
  911. {
  912. Status = E_UNEXPECTED;
  913. goto Exit;
  914. }
  915. OldPer = g_Process->m_Options;
  916. NewPer = OldPer & ~(Options & ~PROCESS_GLOBAL);
  917. }
  918. else
  919. {
  920. NewPer = 0;
  921. OldPer = 0;
  922. }
  923. NewGlobal = g_GlobalProcOptions & ~(Options & PROCESS_GLOBAL);
  924. break;
  925. case OPTFN_SET:
  926. // Always require a process in this case as otherwise
  927. // there's no way to know whether a call to SetProcessOptions
  928. // is actually necessary or not.
  929. if (g_Process == NULL)
  930. {
  931. Status = E_UNEXPECTED;
  932. goto Exit;
  933. }
  934. OldPer = g_Process->m_Options;
  935. NewPer = Options & ~PROCESS_GLOBAL;
  936. NewGlobal = Options & PROCESS_GLOBAL;
  937. break;
  938. }
  939. PUSER_DEBUG_SERVICES Services =
  940. ((LiveUserTargetInfo*)g_Target)->m_Services;
  941. BOOL Notify = FALSE;
  942. if (NewGlobal ^ g_GlobalProcOptions)
  943. {
  944. // Global options can only be changed by the session thread.
  945. if (::GetCurrentThreadId() != g_SessionThread)
  946. {
  947. Status = E_UNEXPECTED;
  948. goto Exit;
  949. }
  950. if ((Status = Services->SetDebugObjectOptions(0, NewGlobal)) != S_OK)
  951. {
  952. goto Exit;
  953. }
  954. Notify = TRUE;
  955. g_GlobalProcOptions = NewGlobal;
  956. }
  957. if (NewPer ^ OldPer)
  958. {
  959. if ((Status = Services->
  960. SetProcessOptions(g_Process->m_SysHandle, NewPer)) != S_OK)
  961. {
  962. goto Exit;
  963. }
  964. g_Process->m_Options = NewPer;
  965. Notify = TRUE;
  966. }
  967. if (Notify)
  968. {
  969. NotifyChangeEngineState(DEBUG_CES_PROCESS_OPTIONS,
  970. NewPer | NewGlobal, FALSE);
  971. }
  972. Status = S_OK;
  973. Exit:
  974. LEAVE_ENGINE();
  975. return Status;
  976. }
  977. STDMETHODIMP
  978. DebugClient::AddProcessOptions(
  979. THIS_
  980. IN ULONG Options
  981. )
  982. {
  983. return ChangeProcessOptions(Options, OPTFN_ADD);
  984. }
  985. STDMETHODIMP
  986. DebugClient::RemoveProcessOptions(
  987. THIS_
  988. IN ULONG Options
  989. )
  990. {
  991. return ChangeProcessOptions(Options, OPTFN_REMOVE);
  992. }
  993. STDMETHODIMP
  994. DebugClient::SetProcessOptions(
  995. THIS_
  996. IN ULONG Options
  997. )
  998. {
  999. return ChangeProcessOptions(Options, OPTFN_SET);
  1000. }
  1001. STDMETHODIMP
  1002. DebugClient::OpenDumpFile(
  1003. THIS_
  1004. IN PCSTR DumpFile
  1005. )
  1006. {
  1007. HRESULT Status;
  1008. PWSTR Wide;
  1009. if ((Status = AnsiToWide(DumpFile, &Wide)) == S_OK)
  1010. {
  1011. Status = OpenDumpFileWide(Wide, 0);
  1012. FreeWide(Wide);
  1013. }
  1014. return Status;
  1015. }
  1016. STDMETHODIMP
  1017. DebugClient::OpenDumpFileWide(
  1018. THIS_
  1019. IN OPTIONAL PCWSTR FileName,
  1020. IN ULONG64 FileHandle
  1021. )
  1022. {
  1023. HRESULT Status;
  1024. ENTER_ENGINE();
  1025. //
  1026. // Special feature that works in conjunction with the perl scripts that
  1027. // index customer minidumps to the database.
  1028. // The script checks machine commit when running multithreaded indexing.
  1029. // Reserve 3 Meg of memory so we don't run into commit problems
  1030. // if the scripts start launching large number of debuggers.
  1031. // Free it up as soon as we know the dump file has loaded.
  1032. //
  1033. LPVOID TmpMem = VirtualAlloc(NULL, 0x300000, MEM_RESERVE, PAGE_READWRITE);
  1034. TargetInfo* Target;
  1035. Status = DumpInitialize(this, FileName, FileHandle, &Target);
  1036. if (TmpMem)
  1037. {
  1038. VirtualFree(TmpMem, 0, MEM_RELEASE);
  1039. }
  1040. if (Status == S_OK)
  1041. {
  1042. DBG_ASSERT(!g_SessionThread ||
  1043. g_SessionThread == ::GetCurrentThreadId());
  1044. g_SessionThread = ::GetCurrentThreadId();
  1045. InitializePrimary();
  1046. g_Target = Target;
  1047. }
  1048. LEAVE_ENGINE();
  1049. return Status;
  1050. }
  1051. STDMETHODIMP
  1052. DebugClient::WriteDumpFile(
  1053. THIS_
  1054. IN PCSTR DumpFile,
  1055. IN ULONG Qualifier
  1056. )
  1057. {
  1058. return WriteDumpFile2(DumpFile, Qualifier, DEBUG_FORMAT_DEFAULT, NULL);
  1059. }
  1060. STDMETHODIMP
  1061. DebugClient::WriteDumpFile2(
  1062. THIS_
  1063. IN PCSTR DumpFile,
  1064. IN ULONG Qualifier,
  1065. IN ULONG FormatFlags,
  1066. IN OPTIONAL PCSTR Comment
  1067. )
  1068. {
  1069. HRESULT Status;
  1070. PWSTR WideFile;
  1071. if ((Status = AnsiToWide(DumpFile, &WideFile)) == S_OK)
  1072. {
  1073. Status = WriteDumpFileInternal(WideFile, 0, Qualifier, FormatFlags,
  1074. Comment, NULL);
  1075. FreeWide(WideFile);
  1076. }
  1077. return Status;
  1078. }
  1079. STDMETHODIMP
  1080. DebugClient::WriteDumpFileWide(
  1081. THIS_
  1082. IN OPTIONAL PCWSTR FileName,
  1083. IN ULONG64 FileHandle,
  1084. IN ULONG Qualifier,
  1085. IN ULONG FormatFlags,
  1086. IN OPTIONAL PCWSTR Comment
  1087. )
  1088. {
  1089. return WriteDumpFileInternal(FileName, FileHandle,
  1090. Qualifier, FormatFlags,
  1091. NULL, Comment);
  1092. }
  1093. HRESULT
  1094. DebugClient::WriteDumpFileInternal(
  1095. IN OPTIONAL PCWSTR FileName,
  1096. IN ULONG64 FileHandle,
  1097. IN ULONG Qualifier,
  1098. IN ULONG FormatFlags,
  1099. IN OPTIONAL PCSTR CommentA,
  1100. IN OPTIONAL PCWSTR CommentW
  1101. )
  1102. {
  1103. HRESULT Status;
  1104. ENTER_ENGINE();
  1105. if ((IS_KERNEL_TARGET(g_Target) &&
  1106. (Qualifier < DEBUG_KERNEL_SMALL_DUMP ||
  1107. Qualifier > DEBUG_KERNEL_FULL_DUMP)) ||
  1108. (IS_USER_TARGET(g_Target) &&
  1109. (Qualifier < DEBUG_USER_WINDOWS_SMALL_DUMP ||
  1110. Qualifier > DEBUG_USER_WINDOWS_DUMP)))
  1111. {
  1112. Status = E_INVALIDARG;
  1113. }
  1114. else
  1115. {
  1116. Status = ::WriteDumpFile(FileName, FileHandle,
  1117. Qualifier, FormatFlags,
  1118. CommentA, CommentW);
  1119. }
  1120. LEAVE_ENGINE();
  1121. return Status;
  1122. }
  1123. #define ALL_CONNECT_SESSION_FLAGS \
  1124. (DEBUG_CONNECT_SESSION_NO_VERSION | \
  1125. DEBUG_CONNECT_SESSION_NO_ANNOUNCE)
  1126. STDMETHODIMP
  1127. DebugClient::ConnectSession(
  1128. THIS_
  1129. IN ULONG Flags,
  1130. IN ULONG HistoryLimit
  1131. )
  1132. {
  1133. if (Flags & ~ALL_CONNECT_SESSION_FLAGS)
  1134. {
  1135. return E_INVALIDARG;
  1136. }
  1137. ENTER_ENGINE();
  1138. OutCtlSave OldCtl;
  1139. PushOutCtl(DEBUG_OUTCTL_THIS_CLIENT | DEBUG_OUTCTL_NOT_LOGGED,
  1140. this, &OldCtl);
  1141. if ((Flags & DEBUG_CONNECT_SESSION_NO_VERSION) == 0)
  1142. {
  1143. dprintf("%s", g_WinVersionString);
  1144. }
  1145. SendOutputHistory(this, HistoryLimit);
  1146. // If we're in the middle of an input request and
  1147. // a new client has joined immediately start
  1148. // the input cycle for it.
  1149. ULONG InputRequest = g_InputSizeRequested;
  1150. if (InputRequest > 0)
  1151. {
  1152. m_InputSequence = 1;
  1153. if (m_InputCb != NULL)
  1154. {
  1155. m_InputCb->StartInput(InputRequest);
  1156. }
  1157. }
  1158. PopOutCtl(&OldCtl);
  1159. if ((Flags & DEBUG_CONNECT_SESSION_NO_ANNOUNCE) == 0)
  1160. {
  1161. InitializePrimary();
  1162. dprintf("%s connected at %s", m_Identity, ctime(&m_LastActivity));
  1163. }
  1164. LEAVE_ENGINE();
  1165. return S_OK;
  1166. }
  1167. DBGRPC_SIMPLE_FACTORY(DebugClient, IID_IDebugClient, \
  1168. "Debugger Server", ())
  1169. DebugClientFactory g_DebugClientFactory;
  1170. HRESULT
  1171. ClientStartServer(PCSTR Options, BOOL Wait)
  1172. {
  1173. HRESULT Status;
  1174. if (g_SymOptions & SYMOPT_SECURE)
  1175. {
  1176. Status = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
  1177. }
  1178. else
  1179. {
  1180. Status = DbgRpcCreateServer(Options, &g_DebugClientFactory, Wait);
  1181. if (Status == S_OK)
  1182. {
  1183. // Turn on output history collection.
  1184. g_OutHistoryMask = DEFAULT_OUT_HISTORY_MASK;
  1185. }
  1186. }
  1187. return Status;
  1188. }
  1189. STDMETHODIMP
  1190. DebugClient::StartServer(
  1191. THIS_
  1192. IN PCSTR Options
  1193. )
  1194. {
  1195. HRESULT Status;
  1196. ENTER_ENGINE();
  1197. Status = ClientStartServer(Options, FALSE);
  1198. LEAVE_ENGINE();
  1199. return Status;
  1200. }
  1201. STDMETHODIMP
  1202. DebugClient::OutputServers(
  1203. THIS_
  1204. IN ULONG OutputControl,
  1205. IN PCSTR Machine,
  1206. IN ULONG Flags
  1207. )
  1208. {
  1209. if (Flags & ~DEBUG_SERVERS_ALL)
  1210. {
  1211. return E_INVALIDARG;
  1212. }
  1213. HRESULT Status;
  1214. ENTER_ENGINE();
  1215. OutCtlSave OldCtl;
  1216. if (g_SymOptions & SYMOPT_SECURE)
  1217. {
  1218. Status = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
  1219. }
  1220. else if (!PushOutCtl(OutputControl, this, &OldCtl))
  1221. {
  1222. Status = E_INVALIDARG;
  1223. }
  1224. else
  1225. {
  1226. LONG RegStatus;
  1227. HKEY RegKey;
  1228. HKEY Key;
  1229. Status = S_OK;
  1230. if ((RegStatus = RegConnectRegistry(Machine, HKEY_LOCAL_MACHINE,
  1231. &RegKey)) != ERROR_SUCCESS)
  1232. {
  1233. Status = HRESULT_FROM_WIN32(RegStatus);
  1234. goto Pop;
  1235. }
  1236. if ((RegStatus = RegOpenKeyEx(RegKey, DEBUG_SERVER_KEY,
  1237. 0, KEY_READ,
  1238. &Key)) != ERROR_SUCCESS)
  1239. {
  1240. // Don't report not-found as an error since it just
  1241. // means there's nothing to enumerate.
  1242. if (RegStatus != ERROR_FILE_NOT_FOUND)
  1243. {
  1244. Status = HRESULT_FROM_WIN32(RegStatus);
  1245. }
  1246. goto RegClose;
  1247. }
  1248. ULONG Index;
  1249. char Name[32];
  1250. char Value[2 * MAX_PARAM_VALUE];
  1251. ULONG NameLen, ValueLen;
  1252. ULONG Type;
  1253. Index = 0;
  1254. for (;;)
  1255. {
  1256. NameLen = sizeof(Name);
  1257. ValueLen = sizeof(Value);
  1258. if ((RegStatus = RegEnumValue(Key, Index, Name, &NameLen,
  1259. NULL, &Type, (LPBYTE)Value,
  1260. &ValueLen)) != ERROR_SUCCESS)
  1261. {
  1262. // Done with the enumeration.
  1263. break;
  1264. }
  1265. if (Type != REG_SZ)
  1266. {
  1267. // Only string values should be present.
  1268. Status = E_FAIL;
  1269. break;
  1270. }
  1271. BOOL Output;
  1272. Output = FALSE;
  1273. if (!strncmp(Value, "Debugger Server", 15))
  1274. {
  1275. if (Flags & DEBUG_SERVERS_DEBUGGER)
  1276. {
  1277. Output = TRUE;
  1278. }
  1279. }
  1280. else if (Flags & DEBUG_SERVERS_PROCESS)
  1281. {
  1282. Output = TRUE;
  1283. }
  1284. if (Output)
  1285. {
  1286. dprintf("%s\n", Value);
  1287. }
  1288. Index++;
  1289. }
  1290. RegCloseKey(Key);
  1291. RegClose:
  1292. RegCloseKey(RegKey);
  1293. Pop:
  1294. PopOutCtl(&OldCtl);
  1295. }
  1296. LEAVE_ENGINE();
  1297. return Status;
  1298. }
  1299. STDMETHODIMP
  1300. DebugClient::TerminateProcesses(
  1301. THIS
  1302. )
  1303. {
  1304. HRESULT Status;
  1305. ENTER_ENGINE();
  1306. Status = ::TerminateProcesses();
  1307. LEAVE_ENGINE();
  1308. return Status;
  1309. }
  1310. STDMETHODIMP
  1311. DebugClient::DetachProcesses(
  1312. THIS
  1313. )
  1314. {
  1315. HRESULT Status;
  1316. ENTER_ENGINE();
  1317. Status = ::DetachProcesses();
  1318. LEAVE_ENGINE();
  1319. return Status;
  1320. }
  1321. STDMETHODIMP
  1322. DebugClient::EndSession(
  1323. THIS_
  1324. IN ULONG Flags
  1325. )
  1326. {
  1327. if (
  1328. #if DEBUG_END_PASSIVE > 0
  1329. Flags < DEBUG_END_PASSIVE ||
  1330. #endif
  1331. Flags > DEBUG_END_DISCONNECT)
  1332. {
  1333. return E_INVALIDARG;
  1334. }
  1335. if (Flags == DEBUG_END_REENTRANT)
  1336. {
  1337. // If somebody's doing a reentrant end that means
  1338. // the process is going away so we can clean up
  1339. // any running server registration entries.
  1340. DbgRpcDeregisterServers();
  1341. return S_OK;
  1342. }
  1343. else if (Flags == DEBUG_END_DISCONNECT)
  1344. {
  1345. if (!(m_Flags & CLIENT_REMOTE))
  1346. {
  1347. return E_INVALIDARG;
  1348. }
  1349. Destroy();
  1350. m_LastActivity = time(NULL);
  1351. dprintf("%s disconnected at %s",
  1352. m_Identity, ctime(&m_LastActivity));
  1353. return S_OK;
  1354. }
  1355. HRESULT Status;
  1356. ENTER_ENGINE();
  1357. if (g_SymOptions & SYMOPT_SECURE)
  1358. {
  1359. Status = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
  1360. goto Exit;
  1361. }
  1362. //
  1363. // Clean up any processes sitting around.
  1364. //
  1365. // If this is an active end, terminate or detach.
  1366. if (Flags == DEBUG_END_ACTIVE_TERMINATE)
  1367. {
  1368. Status = ::TerminateProcesses();
  1369. if (FAILED(Status))
  1370. {
  1371. goto Exit;
  1372. }
  1373. }
  1374. else if (Flags == DEBUG_END_ACTIVE_DETACH)
  1375. {
  1376. Status = ::DetachProcesses();
  1377. if (FAILED(Status))
  1378. {
  1379. goto Exit;
  1380. }
  1381. }
  1382. if (AnySystemProcesses(FALSE) &&
  1383. (g_GlobalProcOptions & DEBUG_PROCESS_DETACH_ON_EXIT) == 0)
  1384. {
  1385. //
  1386. // If we try to quit while debugging CSRSS, raise an
  1387. // error.
  1388. //
  1389. ErrOut("(%d): FATAL ERROR: Exiting Debugger while debugging CSR\n",
  1390. ::GetCurrentProcessId());
  1391. g_NtDllCalls.DbgPrint("(%d): FATAL ERROR: "
  1392. "Exiting Debugger while debugging CSR\n",
  1393. ::GetCurrentProcessId());
  1394. if (g_DebuggerPlatformId == VER_PLATFORM_WIN32_NT)
  1395. {
  1396. g_NtDllCalls.NtSystemDebugControl
  1397. (SysDbgBreakPoint, NULL, 0, NULL, 0, 0);
  1398. }
  1399. DebugBreak();
  1400. }
  1401. DiscardSession(Flags == DEBUG_END_ACTIVE_TERMINATE ?
  1402. DEBUG_SESSION_END_SESSION_ACTIVE_TERMINATE :
  1403. (Flags == DEBUG_END_ACTIVE_DETACH ?
  1404. DEBUG_SESSION_END_SESSION_ACTIVE_DETACH :
  1405. DEBUG_SESSION_END_SESSION_PASSIVE));
  1406. Status = S_OK;
  1407. Exit:
  1408. LEAVE_ENGINE();
  1409. return Status;
  1410. }
  1411. STDMETHODIMP
  1412. DebugClient::GetExitCode(
  1413. THIS_
  1414. OUT PULONG Code
  1415. )
  1416. {
  1417. ENTER_ENGINE();
  1418. HRESULT Status;
  1419. if (!IS_LIVE_USER_TARGET(g_Target) ||
  1420. g_Process == NULL)
  1421. {
  1422. Status = E_UNEXPECTED;
  1423. }
  1424. else
  1425. {
  1426. Status = ((LiveUserTargetInfo*)g_Target)->m_Services->
  1427. GetProcessExitCode(g_Process->m_SysHandle, Code);
  1428. }
  1429. LEAVE_ENGINE();
  1430. return Status;
  1431. }
  1432. STDMETHODIMP
  1433. DebugClient::DispatchCallbacks(
  1434. THIS_
  1435. IN ULONG Timeout
  1436. )
  1437. {
  1438. DWORD Wait;
  1439. // If this client was destroyed its resources are gone.
  1440. // There's also a race condition here that's not easy to fix.
  1441. if (!m_DispatchSema)
  1442. {
  1443. return E_UNEXPECTED;
  1444. }
  1445. // This constitutes interesting activity.
  1446. m_LastActivity = time(NULL);
  1447. // Do not hold the engine lock while waiting.
  1448. for (;;)
  1449. {
  1450. Wait = WaitForSingleObjectEx(m_DispatchSema, Timeout, TRUE);
  1451. if (Wait == WAIT_OBJECT_0)
  1452. {
  1453. return S_OK;
  1454. }
  1455. else if (Wait == WAIT_TIMEOUT)
  1456. {
  1457. return S_FALSE;
  1458. }
  1459. else if (Wait != WAIT_IO_COMPLETION)
  1460. {
  1461. return WIN32_LAST_STATUS();
  1462. }
  1463. }
  1464. }
  1465. STDMETHODIMP
  1466. DebugClient::ExitDispatch(
  1467. THIS_
  1468. IN PDEBUG_CLIENT Client
  1469. )
  1470. {
  1471. DebugClient* IntClient = (DebugClient*)(IDebugClientN*)Client;
  1472. // This method is reentrant.
  1473. // If this client was destroyed its resources are gone.
  1474. // There's also a race condition here that's not easy to fix.
  1475. if (!IntClient->m_DispatchSema)
  1476. {
  1477. return E_UNEXPECTED;
  1478. }
  1479. if (!ReleaseSemaphore(IntClient->m_DispatchSema, 1, NULL))
  1480. {
  1481. return WIN32_LAST_STATUS();
  1482. }
  1483. else
  1484. {
  1485. return S_OK;
  1486. }
  1487. }
  1488. STDMETHODIMP
  1489. DebugClient::CreateClient(
  1490. THIS_
  1491. OUT PDEBUG_CLIENT* Client
  1492. )
  1493. {
  1494. HRESULT Status;
  1495. ENTER_ENGINE();
  1496. DebugClient* DbgClient = new DebugClient;
  1497. if (DbgClient == NULL)
  1498. {
  1499. Status = E_OUTOFMEMORY;
  1500. }
  1501. else
  1502. {
  1503. if ((Status = DbgClient->Initialize()) == S_OK)
  1504. {
  1505. DbgClient->Link();
  1506. *Client = (PDEBUG_CLIENT)(IDebugClientN*)DbgClient;
  1507. }
  1508. else
  1509. {
  1510. DbgClient->Release();
  1511. }
  1512. }
  1513. LEAVE_ENGINE();
  1514. return Status;
  1515. }
  1516. STDMETHODIMP
  1517. DebugClient::GetInputCallbacks(
  1518. THIS_
  1519. OUT PDEBUG_INPUT_CALLBACKS* Callbacks
  1520. )
  1521. {
  1522. ENTER_ENGINE();
  1523. *Callbacks = m_InputCb;
  1524. if (m_InputCb)
  1525. {
  1526. m_InputCb->AddRef();
  1527. }
  1528. LEAVE_ENGINE();
  1529. return S_OK;
  1530. }
  1531. STDMETHODIMP
  1532. DebugClient::SetInputCallbacks(
  1533. THIS_
  1534. IN PDEBUG_INPUT_CALLBACKS Callbacks
  1535. )
  1536. {
  1537. ENTER_ENGINE();
  1538. TRANSFER(m_InputCb, Callbacks);
  1539. LEAVE_ENGINE();
  1540. return S_OK;
  1541. }
  1542. STDMETHODIMP
  1543. DebugClient::GetOutputCallbacks(
  1544. THIS_
  1545. OUT PDEBUG_OUTPUT_CALLBACKS* Callbacks
  1546. )
  1547. {
  1548. ENTER_ENGINE();
  1549. *Callbacks = m_OutputCb;
  1550. if (m_OutputCb)
  1551. {
  1552. m_OutputCb->AddRef();
  1553. }
  1554. LEAVE_ENGINE();
  1555. return S_OK;
  1556. }
  1557. STDMETHODIMP
  1558. DebugClient::SetOutputCallbacks(
  1559. THIS_
  1560. IN PDEBUG_OUTPUT_CALLBACKS Callbacks
  1561. )
  1562. {
  1563. ENTER_ENGINE();
  1564. TRANSFER(m_OutputCb, Callbacks);
  1565. CollectOutMasks();
  1566. LEAVE_ENGINE();
  1567. return S_OK;
  1568. }
  1569. STDMETHODIMP
  1570. DebugClient::GetOutputMask(
  1571. THIS_
  1572. OUT PULONG Mask
  1573. )
  1574. {
  1575. // This method is reentrant.
  1576. *Mask = m_OutMask;
  1577. return S_OK;
  1578. }
  1579. STDMETHODIMP
  1580. DebugClient::SetOutputMask(
  1581. THIS_
  1582. IN ULONG Mask
  1583. )
  1584. {
  1585. // This method is reentrant.
  1586. m_OutMask = Mask;
  1587. CollectOutMasks();
  1588. return S_OK;
  1589. }
  1590. STDMETHODIMP
  1591. DebugClient::GetOtherOutputMask(
  1592. THIS_
  1593. IN PDEBUG_CLIENT Client,
  1594. OUT PULONG Mask
  1595. )
  1596. {
  1597. return Client->GetOutputMask(Mask);
  1598. }
  1599. STDMETHODIMP
  1600. DebugClient::SetOtherOutputMask(
  1601. THIS_
  1602. IN PDEBUG_CLIENT Client,
  1603. IN ULONG Mask
  1604. )
  1605. {
  1606. return Client->SetOutputMask(Mask);
  1607. }
  1608. STDMETHODIMP
  1609. DebugClient::GetOutputWidth(
  1610. THIS_
  1611. OUT PULONG Columns
  1612. )
  1613. {
  1614. ENTER_ENGINE();
  1615. *Columns = m_OutputWidth;
  1616. LEAVE_ENGINE();
  1617. return S_OK;
  1618. }
  1619. STDMETHODIMP
  1620. DebugClient::SetOutputWidth(
  1621. THIS_
  1622. IN ULONG Columns
  1623. )
  1624. {
  1625. if (Columns < 1)
  1626. {
  1627. return E_INVALIDARG;
  1628. }
  1629. ENTER_ENGINE();
  1630. m_OutputWidth = Columns;
  1631. LEAVE_ENGINE();
  1632. return S_OK;
  1633. }
  1634. STDMETHODIMP
  1635. DebugClient::GetOutputLinePrefix(
  1636. THIS_
  1637. OUT OPTIONAL PSTR Buffer,
  1638. IN ULONG BufferSize,
  1639. OUT OPTIONAL PULONG PrefixSize
  1640. )
  1641. {
  1642. HRESULT Status;
  1643. ENTER_ENGINE();
  1644. Status = FillStringBuffer(m_OutputLinePrefix, 0,
  1645. Buffer, BufferSize, PrefixSize);
  1646. LEAVE_ENGINE();
  1647. return S_OK;
  1648. }
  1649. STDMETHODIMP
  1650. DebugClient::SetOutputLinePrefix(
  1651. THIS_
  1652. IN OPTIONAL PCSTR Prefix
  1653. )
  1654. {
  1655. HRESULT Status;
  1656. ENTER_ENGINE();
  1657. ULONG Len;
  1658. Status = ChangeString((PSTR*)&m_OutputLinePrefix, &Len, Prefix);
  1659. LEAVE_ENGINE();
  1660. return Status;
  1661. }
  1662. STDMETHODIMP
  1663. DebugClient::GetIdentity(
  1664. THIS_
  1665. OUT OPTIONAL PSTR Buffer,
  1666. IN ULONG BufferSize,
  1667. OUT OPTIONAL PULONG IdentitySize
  1668. )
  1669. {
  1670. return FillStringBuffer(m_Identity, 0,
  1671. Buffer, BufferSize, IdentitySize);
  1672. }
  1673. STDMETHODIMP
  1674. DebugClient::OutputIdentity(
  1675. THIS_
  1676. IN ULONG OutputControl,
  1677. IN ULONG Flags,
  1678. IN PCSTR Format
  1679. )
  1680. {
  1681. HRESULT Status;
  1682. if (Flags != DEBUG_OUTPUT_IDENTITY_DEFAULT)
  1683. {
  1684. return E_INVALIDARG;
  1685. }
  1686. ENTER_ENGINE();
  1687. OutCtlSave OldCtl;
  1688. if (!PushOutCtl(OutputControl, this, &OldCtl))
  1689. {
  1690. Status = E_INVALIDARG;
  1691. }
  1692. else
  1693. {
  1694. dprintf(Format, m_Identity);
  1695. Status = S_OK;
  1696. PopOutCtl(&OldCtl);
  1697. }
  1698. LEAVE_ENGINE();
  1699. return Status;
  1700. }
  1701. STDMETHODIMP
  1702. DebugClient::GetEventCallbacks(
  1703. THIS_
  1704. OUT PDEBUG_EVENT_CALLBACKS* Callbacks
  1705. )
  1706. {
  1707. ENTER_ENGINE();
  1708. *Callbacks = m_EventCb;
  1709. if (m_EventCb)
  1710. {
  1711. m_EventCb->AddRef();
  1712. }
  1713. LEAVE_ENGINE();
  1714. return S_OK;
  1715. }
  1716. STDMETHODIMP
  1717. DebugClient::SetEventCallbacks(
  1718. THIS_
  1719. IN PDEBUG_EVENT_CALLBACKS Callbacks
  1720. )
  1721. {
  1722. ENTER_ENGINE();
  1723. HRESULT Status;
  1724. ULONG Interest;
  1725. if (Callbacks != NULL)
  1726. {
  1727. Status = Callbacks->GetInterestMask(&Interest);
  1728. }
  1729. else
  1730. {
  1731. Status = S_OK;
  1732. Interest = 0;
  1733. }
  1734. if (Status == S_OK)
  1735. {
  1736. TRANSFER(m_EventCb, Callbacks);
  1737. m_EventInterest = Interest;
  1738. }
  1739. LEAVE_ENGINE();
  1740. return Status;
  1741. }
  1742. STDMETHODIMP
  1743. DebugClient::FlushCallbacks(
  1744. THIS
  1745. )
  1746. {
  1747. ::FlushCallbacks();
  1748. return S_OK;
  1749. }
  1750. STDMETHODIMP
  1751. DebugClient::AddDumpInformationFile(
  1752. THIS_
  1753. IN PCSTR InfoFile,
  1754. IN ULONG Type
  1755. )
  1756. {
  1757. HRESULT Status;
  1758. PWSTR WideFile;
  1759. if ((Status = AnsiToWide(InfoFile, &WideFile)) == S_OK)
  1760. {
  1761. Status = AddDumpInformationFileWide(WideFile, 0, Type);
  1762. FreeWide(WideFile);
  1763. }
  1764. return Status;
  1765. }
  1766. STDMETHODIMP
  1767. DebugClient::AddDumpInformationFileWide(
  1768. THIS_
  1769. IN OPTIONAL PCWSTR FileName,
  1770. IN ULONG64 FileHandle,
  1771. IN ULONG Type
  1772. )
  1773. {
  1774. HRESULT Status;
  1775. if (Type != DEBUG_DUMP_FILE_PAGE_FILE_DUMP)
  1776. {
  1777. return E_INVALIDARG;
  1778. }
  1779. ENTER_ENGINE();
  1780. // This method must be called before OpenDumpFile.
  1781. if (!g_Target)
  1782. {
  1783. Status = E_UNEXPECTED;
  1784. }
  1785. else
  1786. {
  1787. Status = AddDumpInfoFile(FileName, FileHandle,
  1788. DUMP_INFO_PAGE_FILE, 64 * 1024);
  1789. }
  1790. LEAVE_ENGINE();
  1791. return Status;
  1792. }
  1793. STDMETHODIMP
  1794. DebugClient::EndProcessServer(
  1795. THIS_
  1796. IN ULONG64 Server
  1797. )
  1798. {
  1799. return ((IUserDebugServices*)Server)->
  1800. Uninitialize(TRUE);
  1801. }
  1802. STDMETHODIMP
  1803. DebugClient::WaitForProcessServerEnd(
  1804. THIS_
  1805. IN ULONG Timeout
  1806. )
  1807. {
  1808. HRESULT Status;
  1809. ENTER_ENGINE();
  1810. if (g_UserServicesUninitialized)
  1811. {
  1812. Status = S_OK;
  1813. }
  1814. else
  1815. {
  1816. //
  1817. // This could be done with an event to get true
  1818. // waiting but precision isn't that important.
  1819. //
  1820. Status = S_FALSE;
  1821. while (Timeout)
  1822. {
  1823. ULONG UseTimeout;
  1824. UseTimeout = min(1000, Timeout);
  1825. Sleep(UseTimeout);
  1826. if (g_UserServicesUninitialized)
  1827. {
  1828. Status = S_OK;
  1829. break;
  1830. }
  1831. if (Timeout != INFINITE)
  1832. {
  1833. Timeout -= UseTimeout;
  1834. }
  1835. }
  1836. }
  1837. LEAVE_ENGINE();
  1838. return Status;
  1839. }
  1840. STDMETHODIMP
  1841. DebugClient::IsKernelDebuggerEnabled(
  1842. THIS
  1843. )
  1844. {
  1845. HRESULT Status;
  1846. ENTER_ENGINE();
  1847. if (g_DebuggerPlatformId != VER_PLATFORM_WIN32_NT)
  1848. {
  1849. Status = E_UNEXPECTED;
  1850. }
  1851. else
  1852. {
  1853. NTSTATUS NtStatus;
  1854. SYSTEM_KERNEL_DEBUGGER_INFORMATION KdInfo;
  1855. NtStatus = g_NtDllCalls.
  1856. NtQuerySystemInformation(SystemKernelDebuggerInformation,
  1857. &KdInfo, sizeof(KdInfo), NULL);
  1858. if (NT_SUCCESS(NtStatus))
  1859. {
  1860. Status = KdInfo.KernelDebuggerEnabled ? S_OK : S_FALSE;
  1861. }
  1862. else
  1863. {
  1864. Status = HRESULT_FROM_NT(NtStatus);
  1865. }
  1866. }
  1867. LEAVE_ENGINE();
  1868. return Status;
  1869. }
  1870. STDMETHODIMP
  1871. DebugClient::TerminateCurrentProcess(
  1872. THIS
  1873. )
  1874. {
  1875. HRESULT Status;
  1876. ENTER_ENGINE();
  1877. if (g_SymOptions & SYMOPT_SECURE)
  1878. {
  1879. Status = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
  1880. }
  1881. else
  1882. {
  1883. Status = SeparateCurrentProcess(SEP_TERMINATE, NULL);
  1884. }
  1885. LEAVE_ENGINE();
  1886. return Status;
  1887. }
  1888. STDMETHODIMP
  1889. DebugClient::DetachCurrentProcess(
  1890. THIS
  1891. )
  1892. {
  1893. HRESULT Status;
  1894. ENTER_ENGINE();
  1895. if (g_SymOptions & SYMOPT_SECURE)
  1896. {
  1897. Status = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
  1898. }
  1899. else
  1900. {
  1901. Status = SeparateCurrentProcess(SEP_DETACH, NULL);
  1902. }
  1903. LEAVE_ENGINE();
  1904. return Status;
  1905. }
  1906. STDMETHODIMP
  1907. DebugClient::AbandonCurrentProcess(
  1908. THIS
  1909. )
  1910. {
  1911. HRESULT Status;
  1912. ENTER_ENGINE();
  1913. if (g_SymOptions & SYMOPT_SECURE)
  1914. {
  1915. Status = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
  1916. }
  1917. else
  1918. {
  1919. Status = SeparateCurrentProcess(SEP_ABANDON, NULL);
  1920. }
  1921. LEAVE_ENGINE();
  1922. return Status;
  1923. }
  1924. STDMETHODIMP
  1925. DebugClient::GetNumberDumpFiles(
  1926. THIS_
  1927. OUT PULONG Number
  1928. )
  1929. {
  1930. HRESULT Status;
  1931. ENTER_ENGINE();
  1932. if (!IS_DUMP_TARGET(g_Target))
  1933. {
  1934. Status = E_UNEXPECTED;
  1935. }
  1936. else
  1937. {
  1938. DumpTargetInfo* DumpTarget = (DumpTargetInfo*)g_Target;
  1939. ULONG i;
  1940. ULONG Count = 0;
  1941. for (i = 0; i < DUMP_INFO_COUNT; i++)
  1942. {
  1943. if (DumpTarget->m_InfoFiles[i].m_File)
  1944. {
  1945. Count++;
  1946. }
  1947. }
  1948. *Number = Count;
  1949. Status = S_OK;
  1950. }
  1951. LEAVE_ENGINE();
  1952. return Status;
  1953. }
  1954. STDMETHODIMP
  1955. DebugClient::GetDumpFile(
  1956. THIS_
  1957. IN ULONG Index,
  1958. OUT OPTIONAL PSTR Buffer,
  1959. IN ULONG BufferSize,
  1960. OUT OPTIONAL PULONG NameSize,
  1961. OUT OPTIONAL PULONG64 Handle,
  1962. OUT PULONG Type
  1963. )
  1964. {
  1965. HRESULT Status;
  1966. PWSTR BufferWide;
  1967. if (Buffer && BufferSize > 0)
  1968. {
  1969. BufferWide = (PWSTR)malloc(BufferSize * sizeof(WCHAR));
  1970. if (!BufferWide)
  1971. {
  1972. return E_OUTOFMEMORY;
  1973. }
  1974. }
  1975. else
  1976. {
  1977. BufferWide = NULL;
  1978. }
  1979. Status = GetDumpFileWide(Index, BufferWide, BufferSize * sizeof(WCHAR),
  1980. NameSize, Handle, Type);
  1981. if (BufferWide)
  1982. {
  1983. if (SUCCEEDED(Status))
  1984. {
  1985. if (!WideCharToMultiByte(CP_ACP, 0, BufferWide, -1,
  1986. Buffer, BufferSize,
  1987. NULL, NULL))
  1988. {
  1989. Status = WIN32_LAST_STATUS();
  1990. }
  1991. }
  1992. free(BufferWide);
  1993. }
  1994. return Status;
  1995. }
  1996. STDMETHODIMP
  1997. DebugClient::GetDumpFileWide(
  1998. THIS_
  1999. IN ULONG Index,
  2000. OUT OPTIONAL PWSTR Buffer,
  2001. IN ULONG BufferSize,
  2002. OUT OPTIONAL PULONG NameSize,
  2003. OUT OPTIONAL PULONG64 Handle,
  2004. OUT PULONG Type
  2005. )
  2006. {
  2007. HRESULT Status;
  2008. ENTER_ENGINE();
  2009. if (Index == DEBUG_DUMP_FILE_LOAD_FAILED_INDEX)
  2010. {
  2011. //
  2012. // Special case to return a failed dump file open
  2013. //
  2014. Status = FillStringBufferW(g_LastFailedDumpFileW, 0,
  2015. Buffer, BufferSize, NameSize);
  2016. }
  2017. else if (!IS_DUMP_TARGET(g_Target))
  2018. {
  2019. Status = E_UNEXPECTED;
  2020. }
  2021. else
  2022. {
  2023. DumpTargetInfo* DumpTarget = (DumpTargetInfo*)g_Target;
  2024. ULONG i;
  2025. ULONG Count = 0;
  2026. Status = E_NOINTERFACE;
  2027. for (i = 0; i < DUMP_INFO_COUNT; i++)
  2028. {
  2029. if (DumpTarget->m_InfoFiles[i].m_File)
  2030. {
  2031. if (Count == Index)
  2032. {
  2033. Status = FillStringBufferW(DumpTarget->
  2034. m_InfoFiles[i].m_FileNameW, 0,
  2035. Buffer, BufferSize, NameSize);
  2036. if (Handle)
  2037. {
  2038. *Handle = (ULONG_PTR)DumpTarget->m_InfoFiles[i].m_File;
  2039. }
  2040. *Type = g_DumpApiTypes[i];
  2041. break;
  2042. }
  2043. Count++;
  2044. }
  2045. }
  2046. }
  2047. LEAVE_ENGINE();
  2048. return Status;
  2049. }
  2050. HRESULT
  2051. DebugClient::Initialize(void)
  2052. {
  2053. m_DispatchSema = CreateSemaphore(NULL, 0, 0x7fffffff, NULL);
  2054. if (m_DispatchSema == NULL)
  2055. {
  2056. return WIN32_LAST_STATUS();
  2057. }
  2058. if (!DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
  2059. GetCurrentProcess(), &m_Thread,
  2060. 0, FALSE, DUPLICATE_SAME_ACCESS))
  2061. {
  2062. return WIN32_LAST_STATUS();
  2063. }
  2064. // If we're requesting input allow this client
  2065. // to return input immediately.
  2066. if (g_InputSizeRequested > 0)
  2067. {
  2068. m_InputSequence = 1;
  2069. }
  2070. return S_OK;
  2071. }
  2072. void
  2073. DebugClient::InitializePrimary(void)
  2074. {
  2075. if (m_Flags & CLIENT_PRIMARY)
  2076. {
  2077. return;
  2078. }
  2079. m_Flags |= CLIENT_PRIMARY;
  2080. if ((m_Flags & CLIENT_REMOTE) == 0)
  2081. {
  2082. // Can't call GetClientIdentity here as it uses
  2083. // many system APIs and therefore can cause trouble
  2084. // when debugging system processes such as LSA.
  2085. strcpy(m_Identity, "HostMachine\\HostUser");
  2086. }
  2087. m_LastActivity = time(NULL);
  2088. }
  2089. void
  2090. DebugClient::Link(void)
  2091. {
  2092. EnterCriticalSection(&g_QuickLock);
  2093. // Keep list grouped by thread ID.
  2094. DebugClient* Cur;
  2095. for (Cur = g_Clients; Cur != NULL; Cur = Cur->m_Next)
  2096. {
  2097. if (Cur->m_ThreadId == m_ThreadId)
  2098. {
  2099. break;
  2100. }
  2101. }
  2102. m_Prev = Cur;
  2103. if (Cur != NULL)
  2104. {
  2105. m_Next = Cur->m_Next;
  2106. Cur->m_Next = this;
  2107. }
  2108. else
  2109. {
  2110. // No ID match so just put it in the front.
  2111. m_Next = g_Clients;
  2112. g_Clients = this;
  2113. }
  2114. if (m_Next != NULL)
  2115. {
  2116. m_Next->m_Prev = this;
  2117. }
  2118. m_Flags |= CLIENT_IN_LIST;
  2119. LeaveCriticalSection(&g_QuickLock);
  2120. }
  2121. void
  2122. DebugClient::Unlink(void)
  2123. {
  2124. EnterCriticalSection(&g_QuickLock);
  2125. m_Flags &= ~CLIENT_IN_LIST;
  2126. if (m_Next != NULL)
  2127. {
  2128. m_Next->m_Prev = m_Prev;
  2129. }
  2130. if (m_Prev != NULL)
  2131. {
  2132. m_Prev->m_Next = m_Next;
  2133. }
  2134. else
  2135. {
  2136. g_Clients = m_Next;
  2137. }
  2138. LeaveCriticalSection(&g_QuickLock);
  2139. }
  2140. //----------------------------------------------------------------------------
  2141. //
  2142. // Initialize/uninitalize functions.
  2143. //
  2144. //----------------------------------------------------------------------------
  2145. DebugClient*
  2146. FindClient(ULONG Tid, ULONG IncFlags, ULONG ExcFlags)
  2147. {
  2148. DebugClient* Client;
  2149. for (Client = g_Clients; Client != NULL; Client = Client->m_Next)
  2150. {
  2151. if ((!Tid || Client->m_ThreadId == Tid) &&
  2152. (Client->m_Flags & IncFlags) &&
  2153. !(Client->m_Flags & ExcFlags))
  2154. {
  2155. return Client;
  2156. }
  2157. }
  2158. return NULL;
  2159. }
  2160. ULONG __cdecl
  2161. Win32DbgPrint(char *Text, ...)
  2162. {
  2163. char Temp[OUT_BUFFER_SIZE - 16];
  2164. va_list Args;
  2165. va_start(Args, Text);
  2166. _vsnprintf(Temp, sizeof(Temp) - 1, Text, Args);
  2167. Temp[sizeof(Temp) - 1] = 0;
  2168. va_end(Args);
  2169. OutputDebugStringA(Temp);
  2170. return 0;
  2171. }
  2172. HRESULT
  2173. OneTimeInitialization(void)
  2174. {
  2175. static BOOL Init = FALSE;
  2176. if (Init)
  2177. {
  2178. return S_OK;
  2179. }
  2180. // This function is called exactly once at the first
  2181. // DebugCreate for a process. It should perform any
  2182. // global one-time initialization necessary.
  2183. // Nothing initialized here will be explicitly cleaned
  2184. // up, instead it should all be the kind of thing
  2185. // that can wait for process cleanup.
  2186. HRESULT Status = S_OK;
  2187. // These sizes are hard-coded into the remoting script
  2188. // so verify them to ensure no mismatch.
  2189. C_ASSERT(sizeof(DEBUG_BREAKPOINT_PARAMETERS) == 56);
  2190. C_ASSERT(sizeof(DEBUG_STACK_FRAME) == 128);
  2191. C_ASSERT(sizeof(DEBUG_VALUE) == 32);
  2192. C_ASSERT(sizeof(DEBUG_REGISTER_DESCRIPTION) == 32);
  2193. C_ASSERT(sizeof(DEBUG_SYMBOL_PARAMETERS) == 32);
  2194. C_ASSERT(sizeof(DEBUG_MODULE_PARAMETERS) == 64);
  2195. C_ASSERT(sizeof(DEBUG_SPECIFIC_FILTER_PARAMETERS) == 20);
  2196. C_ASSERT(sizeof(DEBUG_EXCEPTION_FILTER_PARAMETERS) == 24);
  2197. C_ASSERT(sizeof(EXCEPTION_RECORD64) == 152);
  2198. C_ASSERT(sizeof(MEMORY_BASIC_INFORMATION64) == 48);
  2199. g_Sym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
  2200. g_Sym->MaxNameLength = MAX_SYMBOL_LEN;
  2201. SYSTEM_INFO SystemInfo;
  2202. GetSystemInfo(&SystemInfo);
  2203. g_SystemAllocGranularity = SystemInfo.dwAllocationGranularity;
  2204. // Get the debugger host system's OS type. Note that
  2205. // this may be different from g_TargetPlatformId, which
  2206. // is the OS type of the debug target.
  2207. OSVERSIONINFO OsVersionInfo;
  2208. OsVersionInfo.dwOSVersionInfoSize = sizeof(OsVersionInfo);
  2209. if (!GetVersionEx(&OsVersionInfo))
  2210. {
  2211. Status = WIN32_LAST_STATUS();
  2212. goto EH_Fail;
  2213. }
  2214. g_DebuggerPlatformId = OsVersionInfo.dwPlatformId;
  2215. if (g_DebuggerPlatformId == VER_PLATFORM_WIN32_NT)
  2216. {
  2217. if ((Status = InitDynamicCalls(&g_NtDllCallsDesc)) != S_OK)
  2218. {
  2219. goto EH_Fail;
  2220. }
  2221. }
  2222. else
  2223. {
  2224. g_NtDllCalls.DbgPrint = Win32DbgPrint;
  2225. }
  2226. if ((Status = InitDynamicCalls(&g_Kernel32CallsDesc)) != S_OK)
  2227. {
  2228. goto EH_Fail;
  2229. }
  2230. if ((Status = InitDynamicCalls(&g_Advapi32CallsDesc)) != S_OK)
  2231. {
  2232. goto EH_Fail;
  2233. }
  2234. ULONG SvcFlags;
  2235. if ((Status = g_LiveUserDebugServices.Initialize(&SvcFlags)) != S_OK)
  2236. {
  2237. goto EH_Fail;
  2238. }
  2239. g_InputEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  2240. if (g_InputEvent == NULL)
  2241. {
  2242. Status = WIN32_LAST_STATUS();
  2243. goto EH_Fail;
  2244. }
  2245. g_EventStatusWaiting = CreateEvent(NULL, FALSE, FALSE, NULL);
  2246. if (g_EventStatusWaiting == NULL)
  2247. {
  2248. Status = WIN32_LAST_STATUS();
  2249. goto EH_InputEvent;
  2250. }
  2251. g_EventStatusReady = CreateEvent(NULL, FALSE, FALSE, NULL);
  2252. if (g_EventStatusReady == NULL)
  2253. {
  2254. Status = WIN32_LAST_STATUS();
  2255. goto EH_EventStatusWaiting;
  2256. }
  2257. g_SleepPidEvent = CreatePidEvent(GetCurrentProcessId(), CREATE_NEW);
  2258. if (g_SleepPidEvent == NULL)
  2259. {
  2260. Status = E_FAIL;
  2261. goto EH_EventStatusReady;
  2262. }
  2263. if ((Status = InitializeAllAccessSecObj()) != S_OK)
  2264. {
  2265. goto EH_SleepPidEvent;
  2266. }
  2267. __try
  2268. {
  2269. InitializeCriticalSection(&g_QuickLock);
  2270. }
  2271. __except(EXCEPTION_EXECUTE_HANDLER)
  2272. {
  2273. Status = HRESULT_FROM_NT(GetExceptionCode());
  2274. goto EH_AllAccessObj;
  2275. }
  2276. __try
  2277. {
  2278. InitializeCriticalSection(&g_EngineLock);
  2279. }
  2280. __except(EXCEPTION_EXECUTE_HANDLER)
  2281. {
  2282. Status = HRESULT_FROM_NT(GetExceptionCode());
  2283. goto EH_QuickLock;
  2284. }
  2285. if ((Status = BreakpointInit()) != S_OK)
  2286. {
  2287. goto EH_EngineLock;
  2288. }
  2289. g_SrcPath = getenv("_NT_SOURCE_PATH");
  2290. if (g_SrcPath != NULL)
  2291. {
  2292. // This path must be in allocated space.
  2293. // If this fails it's not catastrophic.
  2294. g_SrcPath = _strdup(g_SrcPath);
  2295. }
  2296. // Set default symbol options.
  2297. SymSetOptions(g_SymOptions);
  2298. if (getenv("KDQUIET"))
  2299. {
  2300. g_QuietMode = TRUE;
  2301. }
  2302. else
  2303. {
  2304. g_QuietMode = FALSE;
  2305. }
  2306. ReadDebugOptions(TRUE, NULL);
  2307. PCSTR Env;
  2308. #if DBG
  2309. // Get default out mask from environment variables.
  2310. Env = getenv("DBGENG_OUT_MASK");
  2311. if (Env != NULL)
  2312. {
  2313. ULONG Mask = strtoul(Env, NULL, 0);
  2314. g_EnvOutMask |= Mask;
  2315. g_LogMask |= Mask;
  2316. }
  2317. #endif
  2318. Env = getenv("_NT_DEBUG_HISTORY_SIZE");
  2319. if (Env != NULL)
  2320. {
  2321. g_OutHistoryRequestedSize = atoi(Env) * 1024;
  2322. }
  2323. Env = getenv("_NT_EXPR_EVAL");
  2324. if (Env)
  2325. {
  2326. SetExprSyntaxByName(Env);
  2327. }
  2328. Init = TRUE;
  2329. return S_OK;
  2330. EH_EngineLock:
  2331. DeleteCriticalSection(&g_EngineLock);
  2332. EH_QuickLock:
  2333. DeleteCriticalSection(&g_QuickLock);
  2334. EH_AllAccessObj:
  2335. DeleteAllAccessSecObj();
  2336. EH_SleepPidEvent:
  2337. CloseHandle(g_SleepPidEvent);
  2338. g_SleepPidEvent = NULL;
  2339. EH_EventStatusReady:
  2340. CloseHandle(g_EventStatusReady);
  2341. g_EventStatusReady = NULL;
  2342. EH_EventStatusWaiting:
  2343. CloseHandle(g_EventStatusWaiting);
  2344. g_EventStatusWaiting = NULL;
  2345. EH_InputEvent:
  2346. CloseHandle(g_InputEvent);
  2347. g_InputEvent = NULL;
  2348. EH_Fail:
  2349. return Status;
  2350. }
  2351. STDAPI
  2352. DebugConnect(
  2353. IN PCSTR RemoteOptions,
  2354. IN REFIID InterfaceId,
  2355. OUT PVOID* Interface
  2356. )
  2357. {
  2358. HRESULT Status;
  2359. if ((Status = OneTimeInitialization()) != S_OK)
  2360. {
  2361. return Status;
  2362. }
  2363. IUnknown* Client;
  2364. if ((Status = DbgRpcConnectServer(RemoteOptions, &IID_IDebugClient,
  2365. &Client)) != S_OK)
  2366. {
  2367. return Status;
  2368. }
  2369. Status = Client->QueryInterface(InterfaceId, Interface);
  2370. Client->Release();
  2371. return Status;
  2372. }
  2373. STDAPI
  2374. DebugCreate(
  2375. IN REFIID InterfaceId,
  2376. OUT PVOID* Interface
  2377. )
  2378. {
  2379. HRESULT Status;
  2380. if ((Status = OneTimeInitialization()) != S_OK)
  2381. {
  2382. return Status;
  2383. }
  2384. DebugClient* Client = new DebugClient;
  2385. if (Client == NULL)
  2386. {
  2387. Status = E_OUTOFMEMORY;
  2388. }
  2389. else
  2390. {
  2391. if ((Status = Client->Initialize()) == S_OK)
  2392. {
  2393. Status = Client->QueryInterface(InterfaceId, Interface);
  2394. if (Status == S_OK)
  2395. {
  2396. Client->Link();
  2397. }
  2398. }
  2399. Client->Release();
  2400. }
  2401. return Status;
  2402. }
  2403. HRESULT
  2404. CheckDbgHelpVersion(DebugClient* Client)
  2405. {
  2406. g_DbgHelpVersion = *ImagehlpApiVersionEx(&g_EngApiVersion);
  2407. if (g_DbgHelpVersion.Revision < g_EngApiVersion.Revision)
  2408. {
  2409. //
  2410. // Version mismatch.
  2411. //
  2412. if ((g_EngOptions & DEBUG_ENGOPT_IGNORE_DBGHELP_VERSION) == 0)
  2413. {
  2414. ErrOut("dbghelp.dll has a version mismatch with the debugger\n\n");
  2415. OutputVersionInformation(Client);
  2416. return E_FAIL;
  2417. }
  2418. else
  2419. {
  2420. WarnOut("dbghelp.dll has a version mismatch "
  2421. "with the debugger\n\n");
  2422. }
  2423. }
  2424. return S_OK;
  2425. }
  2426. // Roughly 1.5 months.
  2427. #define STALE_SECONDS (60 * 60 * 24 * 45)
  2428. void
  2429. CheckForStaleBinary(PCSTR DllName, BOOL Thorough)
  2430. {
  2431. HMODULE Mod;
  2432. PIMAGE_NT_HEADERS NtHdr;
  2433. time_t CurTime;
  2434. if (!IsInternalPackage())
  2435. {
  2436. // Don't give any warnings for external packages.
  2437. return;
  2438. }
  2439. Mod = GetModuleHandle(DllName);
  2440. if (!Mod)
  2441. {
  2442. return;
  2443. }
  2444. NtHdr = ImageNtHeader(Mod);
  2445. if (!NtHdr)
  2446. {
  2447. return;
  2448. }
  2449. CurTime = time(NULL);
  2450. if (NtHdr->FileHeader.TimeDateStamp + STALE_SECONDS < (ULONG)CurTime)
  2451. {
  2452. WarnOut("\n"
  2453. "***** WARNING: Your debugger is probably out-of-date.\n"
  2454. "***** Check http://dbg for updates.\n"
  2455. "\n");
  2456. return;
  2457. }
  2458. //
  2459. // The debugger is reasonably recent. If we're allowed
  2460. // to, check for a new version on \\dbg\privates.
  2461. //
  2462. if (!Thorough ||
  2463. (g_EngOptions & DEBUG_ENGOPT_DISALLOW_NETWORK_PATHS))
  2464. {
  2465. return;
  2466. }
  2467. HANDLE FindHandle;
  2468. WIN32_FIND_DATA FindData;
  2469. BOOL Stale;
  2470. ULARGE_INTEGER WriteTime;
  2471. FindHandle = FindFirstFile("\\\\dbg\\privates\\latest\\dbg_x86.msi",
  2472. &FindData);
  2473. if (FindHandle == INVALID_HANDLE_VALUE)
  2474. {
  2475. return;
  2476. }
  2477. Stale = FALSE;
  2478. WriteTime.LowPart = FindData.ftLastWriteTime.dwLowDateTime;
  2479. WriteTime.HighPart = FindData.ftLastWriteTime.dwHighDateTime;
  2480. // The package is built after the binaries so its time will
  2481. // normally be slightly more recent than the binary headers.
  2482. // Throw in a fudge factor to account for this.
  2483. if (WriteTime.QuadPart >
  2484. TimeDateStampToFileTime(NtHdr->FileHeader.TimeDateStamp) +
  2485. TimeToFileTime(60I64 * 60 * 24))
  2486. {
  2487. Stale = TRUE;
  2488. }
  2489. FindClose(FindHandle);
  2490. if (Stale)
  2491. {
  2492. WarnOut("\n"
  2493. "***** WARNING: A newer debugger is available.\n"
  2494. "***** Check http://dbg for updates.\n"
  2495. "\n");
  2496. }
  2497. }
  2498. HRESULT
  2499. CheckSessionInitialize(DebugClient* Client)
  2500. {
  2501. HRESULT Status;
  2502. // Enforce that all target creations must come
  2503. // from the same thread.
  2504. if (g_SessionThread &&
  2505. (g_SessionThread != ::GetCurrentThreadId()))
  2506. {
  2507. return E_INVALIDARG;
  2508. }
  2509. if ((Status = CheckDbgHelpVersion(Client)) != S_OK)
  2510. {
  2511. return Status;
  2512. }
  2513. // Show a version message once for the very
  2514. // first session start.
  2515. if (!g_VersionMessage)
  2516. {
  2517. dprintf("%s", g_WinVersionString);
  2518. g_VersionMessage = TRUE;
  2519. CheckForStaleBinary(ENGINE_DLL_NAME, FALSE);
  2520. }
  2521. return S_OK;
  2522. }
  2523. HRESULT
  2524. LiveKernelInitialize(DebugClient* Client, ULONG Qual, PCSTR Options,
  2525. TargetInfo** TargetRet)
  2526. {
  2527. HRESULT Status;
  2528. LiveKernelTargetInfo* Target;
  2529. if ((Status = CheckSessionInitialize(Client)) != S_OK)
  2530. {
  2531. return Status;
  2532. }
  2533. if (Qual == DEBUG_KERNEL_CONNECTION)
  2534. {
  2535. Target = new ConnLiveKernelTargetInfo;
  2536. }
  2537. else if (Qual == DEBUG_KERNEL_LOCAL)
  2538. {
  2539. if (g_SymOptions & SYMOPT_SECURE)
  2540. {
  2541. return HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
  2542. }
  2543. //
  2544. // We need to get the debug privilege to enable local kernel debugging
  2545. //
  2546. if ((Status = EnableDebugPrivilege()) != S_OK)
  2547. {
  2548. ErrOut("Unable to enable debug privilege, %s\n \"%s\"\n",
  2549. FormatStatusCode(Status), FormatStatus(Status));
  2550. return Status;
  2551. }
  2552. Target = new LocalLiveKernelTargetInfo;
  2553. }
  2554. else
  2555. {
  2556. if (g_SymOptions & SYMOPT_SECURE)
  2557. {
  2558. return HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
  2559. }
  2560. Target = new ExdiLiveKernelTargetInfo;
  2561. }
  2562. if (!Target)
  2563. {
  2564. return E_OUTOFMEMORY;
  2565. }
  2566. // These options only need to stay valid until Initialize.
  2567. Target->m_ConnectOptions = Options;
  2568. Status = Target->Initialize();
  2569. if (Status != S_OK)
  2570. {
  2571. delete Target;
  2572. return Status;
  2573. }
  2574. Target->Link();
  2575. *TargetRet = Target;
  2576. return S_OK;
  2577. }
  2578. HRESULT
  2579. UserInitialize(DebugClient* Client, ULONG64 Server,
  2580. TargetInfo** TargetRet, PBOOL CreatedTargetRet)
  2581. {
  2582. HRESULT Status;
  2583. LiveUserTargetInfo* Target;
  2584. PUSER_DEBUG_SERVICES Services;
  2585. if (g_SymOptions & SYMOPT_SECURE)
  2586. {
  2587. return HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
  2588. }
  2589. if ((Status = CheckSessionInitialize(Client)) != S_OK)
  2590. {
  2591. return Status;
  2592. }
  2593. //
  2594. // Look for an existed target handled by this server.
  2595. //
  2596. *TargetRet = FindTargetByServer(Server);
  2597. if (*TargetRet)
  2598. {
  2599. *CreatedTargetRet = FALSE;
  2600. return S_OK;
  2601. }
  2602. //
  2603. // No existing target, so create a new target.
  2604. //
  2605. Target = new LiveUserTargetInfo(Server ?
  2606. DEBUG_USER_WINDOWS_PROCESS_SERVER :
  2607. DEBUG_USER_WINDOWS_PROCESS);
  2608. if (!Target)
  2609. {
  2610. return E_OUTOFMEMORY;
  2611. }
  2612. if ((Status = Target->Initialize()) != S_OK)
  2613. {
  2614. delete Target;
  2615. return Status;
  2616. }
  2617. if (Server == 0)
  2618. {
  2619. Services = new LiveUserDebugServices(FALSE);
  2620. if (!Services)
  2621. {
  2622. delete Target;
  2623. return E_OUTOFMEMORY;
  2624. }
  2625. }
  2626. else
  2627. {
  2628. Services = (PUSER_DEBUG_SERVICES)Server;
  2629. Services->AddRef();
  2630. }
  2631. // Set the services right away so they'll get
  2632. // cleaned up by the target destructor.
  2633. Target->m_Services = Services;
  2634. Status = Target->SetServices(Services, Server != 0);
  2635. if (Status != S_OK)
  2636. {
  2637. delete Target;
  2638. return Status;
  2639. }
  2640. Target->Link();
  2641. *TargetRet = Target;
  2642. *CreatedTargetRet = TRUE;
  2643. return S_OK;
  2644. }
  2645. HRESULT
  2646. DumpInitialize(DebugClient* Client,
  2647. PCWSTR FileName, ULONG64 FileHandle,
  2648. TargetInfo** TargetRet)
  2649. {
  2650. HRESULT Status;
  2651. if (g_SymOptions & SYMOPT_SECURE)
  2652. {
  2653. return HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
  2654. }
  2655. if ((Status = CheckSessionInitialize(Client)) != S_OK)
  2656. {
  2657. return Status;
  2658. }
  2659. //
  2660. // Automatically expand CAB files.
  2661. //
  2662. PCWSTR OpenFile = FileName;
  2663. PWSTR CabWide = NULL;
  2664. INT_PTR CabDumpFh = -1;
  2665. PWSTR Ext;
  2666. if (!FileHandle)
  2667. {
  2668. Ext = wcsrchr(FileName, L'.');
  2669. }
  2670. else
  2671. {
  2672. Ext = NULL;
  2673. }
  2674. if (Ext != NULL && _wcsicmp(Ext, L".cab") == 0)
  2675. {
  2676. PSTR AnsiFile;
  2677. char CabDumpFile[2 * MAX_PATH];
  2678. if ((Status = WideToAnsi(FileName, &AnsiFile)) != S_OK)
  2679. {
  2680. return Status;
  2681. }
  2682. // Expand the first .dmp or .mdmp file in the CAB.
  2683. // Mark it as delete-on-close so it always gets
  2684. // cleaned up regardless of how the process exits.
  2685. if ((Status = ExpandDumpCab(AnsiFile,
  2686. _O_CREAT | _O_EXCL | _O_TEMPORARY,
  2687. NULL,
  2688. CabDumpFile, DIMA(CabDumpFile),
  2689. &CabDumpFh)) != S_OK)
  2690. {
  2691. ErrOut("Unable to extract dump file from CAB file\n");
  2692. }
  2693. else
  2694. {
  2695. Status = AnsiToWide(CabDumpFile, &CabWide);
  2696. }
  2697. FreeAnsi(AnsiFile);
  2698. if (Status != S_OK)
  2699. {
  2700. return Status;
  2701. }
  2702. OpenFile = CabWide;
  2703. dprintf("Extracted %s\n", CabDumpFile);
  2704. }
  2705. DumpTargetInfo* Target;
  2706. Status = IdentifyDump(OpenFile, FileHandle, &Target);
  2707. if (CabDumpFh >= 0)
  2708. {
  2709. // We expanded a file from a CAB and can close it
  2710. // now because it was either reopened or we need
  2711. // to get rid of it.
  2712. _close((int)CabDumpFh);
  2713. }
  2714. if (Status != S_OK)
  2715. {
  2716. CopyStringW(g_LastFailedDumpFileW,
  2717. OpenFile,
  2718. sizeof(g_LastFailedDumpFileW)/sizeof(WCHAR));
  2719. FreeWide(CabWide);
  2720. ErrOut("Could not open dump file [%ws], %s\n \"%s\"\n",
  2721. FileName ? FileName : L"<HandleOnly>",
  2722. FormatStatusCode(Status),
  2723. FormatStatusArgs(Status, &FileName));
  2724. return Status;
  2725. }
  2726. FreeWide(CabWide);
  2727. Status = Target->Initialize();
  2728. if (Status != S_OK)
  2729. {
  2730. delete Target;
  2731. }
  2732. else
  2733. {
  2734. Target->Link();
  2735. *TargetRet = Target;
  2736. }
  2737. return Status;
  2738. }
  2739. void
  2740. DiscardSession(ULONG Reason)
  2741. {
  2742. if (g_TargetHead)
  2743. {
  2744. DiscardTargets(Reason);
  2745. }
  2746. g_SessionThread = 0;
  2747. ClearEventLog();
  2748. g_ThreadToResume = 0;
  2749. g_ThreadToResumeServices = NULL;
  2750. ZeroMemory(g_UserIdFragmented, sizeof(g_UserIdFragmented));
  2751. ZeroMemory(g_HighestUserId, sizeof(g_HighestUserId));
  2752. g_OciOutputRegs = FALSE;
  2753. g_LastCommand[0] = 0;
  2754. g_GlobalProcOptions = 0;
  2755. g_EngStatus = 0;
  2756. g_EngDefer = 0;
  2757. g_EngErr = 0;
  2758. g_OutHistRead = NULL;
  2759. g_OutHistWrite = NULL;
  2760. g_OutHistoryMask = 0;
  2761. g_OutHistoryUsed = 0;
  2762. }
  2763. void
  2764. DiscardedTargets(ULONG Reason)
  2765. {
  2766. // Unload all extension DLLs to allow people to
  2767. // update extensions after shutdown/during reboot.
  2768. DeferAllExtensionDlls();
  2769. ::FlushCallbacks();
  2770. // Send final notifications.
  2771. // This must be done after all the work as the lock
  2772. // will be suspended during the callbacks, allowing
  2773. // other threads in, so the state must be consistent.
  2774. ULONG ExecStatus = GetExecutionStatus();
  2775. if (ExecStatus == DEBUG_STATUS_NO_DEBUGGEE)
  2776. {
  2777. NotifyChangeEngineState(DEBUG_CES_EXECUTION_STATUS,
  2778. ExecStatus, TRUE);
  2779. NotifySessionStatus(Reason);
  2780. NotifyExtensions(DEBUG_NOTIFY_SESSION_INACTIVE, 0);
  2781. }
  2782. }
  2783. void
  2784. DiscardTargets(ULONG Reason)
  2785. {
  2786. g_CmdState = 'i';
  2787. g_ExecutionStatusRequest = DEBUG_STATUS_NO_CHANGE;
  2788. TargetInfo* Target;
  2789. ForAllLayersToTarget()
  2790. {
  2791. Target->m_Exited = TRUE;
  2792. }
  2793. // Breakpoint removal must wait until everything is marked as
  2794. // exited to avoid asserts on breakpoints that are inserted.
  2795. RemoveAllBreakpoints(Reason);
  2796. DeleteAllExitedInfos();
  2797. DiscardLastEvent();
  2798. ZeroMemory(&g_LastEventInfo, sizeof(g_LastEventInfo));
  2799. ResetStepTrace();
  2800. g_EngStatus &= ~(ENG_STATUS_SUSPENDED |
  2801. ENG_STATUS_BREAKPOINTS_INSERTED |
  2802. ENG_STATUS_STATE_CHANGED |
  2803. ENG_STATUS_PREPARED_FOR_CALLS |
  2804. ENG_STATUS_NO_AUTO_WAIT |
  2805. ENG_STATUS_PENDING_BREAK_IN |
  2806. ENG_STATUS_AT_INITIAL_BREAK |
  2807. ENG_STATUS_AT_INITIAL_MODULE_LOAD |
  2808. ENG_STATUS_EXIT_CURRENT_WAIT |
  2809. ENG_STATUS_USER_INTERRUPT |
  2810. ENG_STATUS_WAIT_SUCCESSFUL);
  2811. g_EngDefer &= ~(ENG_DEFER_EXCEPTION_HANDLING |
  2812. ENG_DEFER_UPDATE_CONTROL_SET |
  2813. ENG_DEFER_HARDWARE_TRACING |
  2814. ENG_DEFER_OUTPUT_CURRENT_INFO);
  2815. g_EngErr &= ~(ENG_ERR_DEBUGGER_DATA);
  2816. g_LastSelector = -1;
  2817. ClearAddr(&g_EventPc);
  2818. ClearAddr(&g_PrevEventPc);
  2819. ClearAddr(&g_PrevRelatedPc);
  2820. // Delete all remaining generated types.
  2821. g_GenTypes.DeleteByImage(IMAGE_BASE_ALL);
  2822. DiscardedTargets(Reason);
  2823. }
  2824. //----------------------------------------------------------------------------
  2825. //
  2826. // DbgRpcClientObject implementation.
  2827. //
  2828. //----------------------------------------------------------------------------
  2829. HRESULT
  2830. DebugClient::RpcInitialize(PSTR ClientIdentity, PSTR TransIdentity,
  2831. PVOID* Interface)
  2832. {
  2833. HRESULT Status;
  2834. ULONG Len, Used;
  2835. m_Flags |= CLIENT_REMOTE;
  2836. if ((Status = Initialize()) != S_OK)
  2837. {
  2838. return Status;
  2839. }
  2840. Len = strlen(ClientIdentity);
  2841. if (Len > sizeof(m_Identity) - 16)
  2842. {
  2843. Len = sizeof(m_Identity) - 16;
  2844. }
  2845. memcpy(m_Identity, ClientIdentity, Len);
  2846. Used = Len;
  2847. m_Identity[Used++] = ' ';
  2848. m_Identity[Used++] = '(';
  2849. Len = strlen(TransIdentity);
  2850. if (Len > sizeof(m_Identity) - Used - 2)
  2851. {
  2852. Len = sizeof(m_Identity) - Used - 2;
  2853. }
  2854. memcpy(m_Identity + Used, TransIdentity, Len);
  2855. Used += Len;
  2856. m_Identity[Used++] = ')';
  2857. m_Identity[Used] = 0;
  2858. *Interface = (IDebugClientN*)this;
  2859. return S_OK;
  2860. }
  2861. void
  2862. DebugClient::RpcFinalize(void)
  2863. {
  2864. Link();
  2865. // Take a reference on this object for the RPC client
  2866. // thread to hold.
  2867. AddRef();
  2868. }
  2869. void
  2870. DebugClient::RpcUninitialize(void)
  2871. {
  2872. // Directly destroy the client object rather than releasing
  2873. // as the remote client may have exited without politely
  2874. // cleaning up references.
  2875. Destroy();
  2876. }