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.

4741 lines
122 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Low-level debugging service interface implementations.
  4. //
  5. // Copyright (C) Microsoft Corporation, 2000-2002.
  6. //
  7. //----------------------------------------------------------------------------
  8. #include "pch.hpp"
  9. #include <time.h>
  10. #ifndef _WIN32_WCE
  11. #include <comsvcs.h>
  12. #else
  13. #include <winver.h>
  14. struct SYSTEM_PROCESS_INFORMATION
  15. {
  16. PVOID Member;
  17. };
  18. typedef SYSTEM_PROCESS_INFORMATION *PSYSTEM_PROCESS_INFORMATION;
  19. typedef struct _DBGUI_WAIT_STATE_CHANGE
  20. {
  21. PVOID Member;
  22. } DBGUI_WAIT_STATE_CHANGE;
  23. #define ProcessDebugFlags 0
  24. #define ProcessDebugObjectHandle 0
  25. #define DebugObjectFlags 0
  26. #define STATUS_INVALID_INFO_CLASS ((NTSTATUS)0xC0000003L)
  27. #define PROCESS_DEBUG_INHERIT 0
  28. #define DEBUG_KILL_ON_CLOSE 0
  29. #endif
  30. #include "dbgsvc.hpp"
  31. #ifndef MONO_DBGSRV
  32. // #include <winbasep.h>
  33. extern "C" {
  34. BOOL
  35. WINAPI
  36. CloseProfileUserMapping(
  37. VOID
  38. );
  39. };
  40. // winbasep.h
  41. #else
  42. #ifdef NT_NATIVE
  43. #include <ntnative.h>
  44. #endif
  45. #define CloseProfileUserMapping()
  46. #endif
  47. // SYSTEM_PROCESS_INFORMATION can change in size, requiring
  48. // different offsets to get to thread information.
  49. #define NT4_SYSTEM_PROCESS_INFORMATION_SIZE 136
  50. #define W2K_SYSTEM_PROCESS_INFORMATION_SIZE 184
  51. #define SYSTEM_PROCESS_NAME "System Process"
  52. #define SYSTEM_PROCESS_NAME_W L"System Process"
  53. #define PEBLESS_PROCESS_NAME "System"
  54. #define PEBLESS_PROCESS_NAME_W L"System"
  55. ULONG g_UserServicesUninitialized;
  56. //----------------------------------------------------------------------------
  57. //
  58. // UserDebugServices.
  59. //
  60. //----------------------------------------------------------------------------
  61. UserDebugServices::UserDebugServices(void)
  62. {
  63. m_Refs = 1;
  64. m_Initialized = FALSE;
  65. m_ClientIdentity[0] = 0;
  66. m_TransIdentity[0] = 0;
  67. }
  68. UserDebugServices::~UserDebugServices(void)
  69. {
  70. }
  71. STDMETHODIMP
  72. UserDebugServices::QueryInterface(
  73. THIS_
  74. IN REFIID InterfaceId,
  75. OUT PVOID* Interface
  76. )
  77. {
  78. HRESULT Status;
  79. *Interface = NULL;
  80. Status = S_OK;
  81. #ifdef _WIN32_WCE
  82. if (DbgIsEqualIID(InterfaceId, IID_IUnknown) ||
  83. DbgIsEqualIID(InterfaceId, __uuidof(IUserDebugServices)))
  84. #else
  85. if (DbgIsEqualIID(InterfaceId, __uuidof(IUnknown)) ||
  86. DbgIsEqualIID(InterfaceId, __uuidof(IUserDebugServices)))
  87. #endif
  88. {
  89. *Interface = (IUserDebugServices *)this;
  90. }
  91. else
  92. {
  93. Status = E_NOINTERFACE;
  94. }
  95. if (Status == S_OK)
  96. {
  97. AddRef();
  98. }
  99. return Status;
  100. }
  101. STDMETHODIMP_(ULONG)
  102. UserDebugServices::AddRef(
  103. THIS
  104. )
  105. {
  106. return InterlockedIncrement((PLONG)&m_Refs);
  107. }
  108. STDMETHODIMP_(ULONG)
  109. UserDebugServices::Release(
  110. THIS
  111. )
  112. {
  113. LONG Refs = InterlockedDecrement((PLONG)&m_Refs);
  114. if (Refs == 0)
  115. {
  116. delete this;
  117. }
  118. return Refs;
  119. }
  120. HRESULT
  121. UserDebugServices::Initialize(
  122. THIS_
  123. OUT PULONG Flags
  124. )
  125. {
  126. m_Initialized = TRUE;
  127. *Flags = 0;
  128. return S_OK;
  129. }
  130. HRESULT
  131. UserDebugServices::Uninitialize(
  132. THIS_
  133. IN BOOL Global
  134. )
  135. {
  136. m_Initialized = FALSE;
  137. if (Global)
  138. {
  139. g_UserServicesUninitialized++;
  140. }
  141. return S_OK;
  142. }
  143. HRESULT
  144. UserDebugServices::RpcInitialize(PSTR ClientIdentity, PSTR TransIdentity,
  145. PVOID* Interface)
  146. {
  147. HRESULT Status;
  148. ULONG Flags;
  149. if ((Status = Initialize(&Flags)) != S_OK)
  150. {
  151. return Status;
  152. }
  153. *Interface = (IUserDebugServices*)this;
  154. CopyString(m_ClientIdentity, ClientIdentity, DIMA(m_ClientIdentity));
  155. CopyString(m_TransIdentity, TransIdentity, DIMA(m_TransIdentity));
  156. return S_OK;
  157. }
  158. void
  159. UserDebugServices::RpcFinalize(void)
  160. {
  161. // Take a reference on this object for the RPC client
  162. // thread to hold.
  163. AddRef();
  164. }
  165. void
  166. UserDebugServices::RpcUninitialize(void)
  167. {
  168. // Directly destroy the client object rather than releasing
  169. // as the remote client may have exited without politely
  170. // cleaning up references.
  171. delete this;
  172. }
  173. //----------------------------------------------------------------------------
  174. //
  175. // LiveUserDebugServices.
  176. //
  177. //----------------------------------------------------------------------------
  178. // This global instance is intended for direct use only
  179. // by routines which need a temporary local service instance.
  180. LiveUserDebugServices g_LiveUserDebugServices(FALSE);
  181. LiveUserDebugServices::LiveUserDebugServices(BOOL Remote)
  182. {
  183. m_Remote = Remote;
  184. m_EventProcessId = 0;
  185. m_ContextSize = 0;
  186. m_SysProcInfoSize = 0;
  187. m_PlatformId = VER_PLATFORM_WIN32s;
  188. m_Win95 = FALSE;
  189. m_DebugObject = NULL;
  190. }
  191. LiveUserDebugServices::~LiveUserDebugServices(void)
  192. {
  193. if (m_DebugObject != NULL)
  194. {
  195. g_NtDllCalls.NtClose(m_DebugObject);
  196. }
  197. }
  198. HRESULT
  199. GetOsVerInfo(LPOSVERSIONINFOEXW OsVersionInfo, PBOOL WideCsd)
  200. {
  201. *WideCsd = TRUE;
  202. ZeroMemory(OsVersionInfo, sizeof(*OsVersionInfo));
  203. OsVersionInfo->dwOSVersionInfoSize = sizeof(*OsVersionInfo);
  204. #ifdef NT_NATIVE
  205. NTSTATUS NtStatus;
  206. if (!NT_SUCCESS(NtStatus = RtlGetVersion((LPOSVERSIONINFOW)OsVersionInfo)))
  207. {
  208. return HRESULT_FROM_NT(NtStatus);
  209. }
  210. #else
  211. if (!GetVersionExW((LPOSVERSIONINFOW)OsVersionInfo))
  212. {
  213. if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
  214. {
  215. OSVERSIONINFOA InfoA;
  216. // Must be Win9x.
  217. ZeroMemory(&InfoA, sizeof(InfoA));
  218. InfoA.dwOSVersionInfoSize = sizeof(InfoA);
  219. if (!::GetVersionExA(&InfoA))
  220. {
  221. return WIN32_LAST_STATUS();
  222. }
  223. OsVersionInfo->dwMajorVersion = InfoA.dwMajorVersion;
  224. OsVersionInfo->dwMinorVersion = InfoA.dwMinorVersion;
  225. OsVersionInfo->dwBuildNumber = InfoA.dwBuildNumber;
  226. OsVersionInfo->dwPlatformId = InfoA.dwPlatformId;
  227. memcpy(OsVersionInfo->szCSDVersion, InfoA.szCSDVersion,
  228. sizeof(InfoA.szCSDVersion));
  229. *WideCsd = FALSE;
  230. }
  231. else
  232. {
  233. // Try the plain info.
  234. OsVersionInfo->dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
  235. if (!GetVersionExW((LPOSVERSIONINFOW)OsVersionInfo))
  236. {
  237. return WIN32_LAST_STATUS();
  238. }
  239. }
  240. }
  241. #endif
  242. return S_OK;
  243. }
  244. HRESULT
  245. LiveUserDebugServices::Initialize(
  246. THIS_
  247. OUT PULONG Flags
  248. )
  249. {
  250. HRESULT Status;
  251. OSVERSIONINFOEXW OsVersionInfo;
  252. BOOL WideCsd;
  253. if ((Status = GetOsVerInfo(&OsVersionInfo, &WideCsd)) != S_OK)
  254. {
  255. return Status;
  256. }
  257. ULONG BaseFlags;
  258. if ((Status = UserDebugServices::Initialize(&BaseFlags)) != S_OK)
  259. {
  260. return Status;
  261. }
  262. m_PlatformId = OsVersionInfo.dwPlatformId;
  263. // System structures may change size depending on the OS
  264. // version. Pick the right size to use later.
  265. if (m_PlatformId == VER_PLATFORM_WIN32_NT)
  266. {
  267. if (OsVersionInfo.dwBuildNumber <= 1381)
  268. {
  269. m_SysProcInfoSize = NT4_SYSTEM_PROCESS_INFORMATION_SIZE;
  270. }
  271. else if (OsVersionInfo.dwBuildNumber <= 2195)
  272. {
  273. m_SysProcInfoSize = W2K_SYSTEM_PROCESS_INFORMATION_SIZE;
  274. }
  275. else
  276. {
  277. m_SysProcInfoSize = sizeof(SYSTEM_PROCESS_INFORMATION);
  278. }
  279. }
  280. else if (m_PlatformId == VER_PLATFORM_WIN32_WINDOWS &&
  281. (OsVersionInfo.dwBuildNumber & 0xffff) < 1998)
  282. {
  283. m_Win95 = TRUE;
  284. }
  285. // If the direct NT debugging APIs are available use them
  286. // as they offer more flexibility.
  287. if (g_NtDllCalls.DbgUiSetThreadDebugObject != NULL)
  288. {
  289. // The NtWait/Continue APIs do not automatically manage
  290. // process and thread handles so the caller must close them.
  291. BaseFlags |= DBGSVC_CLOSE_PROC_THREAD_HANDLES;
  292. m_UseDebugObject = TRUE;
  293. }
  294. else
  295. {
  296. m_UseDebugObject = FALSE;
  297. }
  298. *Flags = BaseFlags | DBGSVC_GENERIC_CODE_BREAKPOINTS |
  299. DBGSVC_GENERIC_DATA_BREAKPOINTS;
  300. return S_OK;
  301. }
  302. HRESULT
  303. LiveUserDebugServices::Uninitialize(
  304. THIS_
  305. IN BOOL Global
  306. )
  307. {
  308. HRESULT Status;
  309. if ((Status = UserDebugServices::Uninitialize(Global)) != S_OK)
  310. {
  311. return Status;
  312. }
  313. m_Remote = FALSE;
  314. m_EventProcessId = 0;
  315. m_ContextSize = 0;
  316. m_PlatformId = VER_PLATFORM_WIN32s;
  317. m_Win95 = FALSE;
  318. if (m_DebugObject != NULL)
  319. {
  320. ::CloseHandle(m_DebugObject);
  321. m_DebugObject = NULL;
  322. }
  323. return S_OK;
  324. }
  325. STDMETHODIMP
  326. LiveUserDebugServices::GetTargetInfo(
  327. THIS_
  328. OUT PULONG MachineType,
  329. OUT PULONG NumberProcessors,
  330. OUT PULONG PlatformId,
  331. OUT PULONG BuildNumber,
  332. OUT PULONG CheckedBuild,
  333. OUT PSTR CsdString,
  334. IN ULONG CsdStringSize,
  335. OUT PSTR BuildString,
  336. IN ULONG BuildStringSize,
  337. OUT PULONG ProductType,
  338. OUT PULONG SuiteMask
  339. )
  340. {
  341. HRESULT Status;
  342. OSVERSIONINFOEXW OsVersionInfo;
  343. BOOL WideCsd;
  344. if ((Status = GetOsVerInfo(&OsVersionInfo, &WideCsd)) != S_OK)
  345. {
  346. return Status;
  347. }
  348. ULONG ProcArch, NumProc;
  349. #ifdef NT_NATIVE
  350. NTSTATUS NtStatus;
  351. SYSTEM_BASIC_INFORMATION BasicInfo;
  352. SYSTEM_PROCESSOR_INFORMATION ProcInfo;
  353. if (!NT_SUCCESS(NtStatus =
  354. NtQuerySystemInformation(SystemBasicInformation,
  355. &BasicInfo, sizeof(BasicInfo),
  356. NULL)) ||
  357. !NT_SUCCESS(NtStatus =
  358. NtQuerySystemInformation(SystemProcessorInformation,
  359. &ProcInfo, sizeof(ProcInfo),
  360. NULL)))
  361. {
  362. return HRESULT_FROM_NT(NtStatus);
  363. }
  364. ProcArch = ProcInfo.ProcessorArchitecture;
  365. NumProc = BasicInfo.NumberOfProcessors;
  366. #else
  367. SYSTEM_INFO SystemInfo;
  368. ::GetSystemInfo(&SystemInfo);
  369. ProcArch = SystemInfo.wProcessorArchitecture;
  370. NumProc = SystemInfo.dwNumberOfProcessors;
  371. #endif
  372. switch(ProcArch)
  373. {
  374. case PROCESSOR_ARCHITECTURE_INTEL:
  375. *MachineType = IMAGE_FILE_MACHINE_I386;
  376. switch(OsVersionInfo.dwPlatformId)
  377. {
  378. #ifndef _WIN32_WCE
  379. case VER_PLATFORM_WIN32_NT:
  380. if (OsVersionInfo.dwBuildNumber <= 1381)
  381. {
  382. m_ContextSize = sizeof(X86_CONTEXT);
  383. }
  384. else
  385. {
  386. m_ContextSize = sizeof(X86_NT5_CONTEXT);
  387. }
  388. break;
  389. case VER_PLATFORM_WIN32_WINDOWS:
  390. // Win9x prior to Win98SE didn't support the extended context.
  391. if ((OsVersionInfo.dwBuildNumber & 0xffff) <= 1998)
  392. {
  393. m_ContextSize = sizeof(X86_CONTEXT);
  394. }
  395. else
  396. {
  397. m_ContextSize = sizeof(X86_NT5_CONTEXT);
  398. }
  399. break;
  400. default:
  401. // Assume all other platforms only support the basic x86 context.
  402. m_ContextSize = sizeof(X86_CONTEXT);
  403. break;
  404. #endif // #ifndef _WIN32_WCE
  405. case VER_PLATFORM_WIN32_CE:
  406. m_ContextSize = sizeof(CONTEXT);
  407. break;
  408. }
  409. break;
  410. #ifndef _WIN32_WCE
  411. case PROCESSOR_ARCHITECTURE_ALPHA:
  412. *MachineType = IMAGE_FILE_MACHINE_ALPHA;
  413. // The "NT5" is a misnomer, this context
  414. // applies to all versions.
  415. m_ContextSize = sizeof(ALPHA_NT5_CONTEXT);
  416. break;
  417. case PROCESSOR_ARCHITECTURE_ALPHA64:
  418. *MachineType = IMAGE_FILE_MACHINE_AXP64;
  419. m_ContextSize = sizeof(ALPHA_NT5_CONTEXT);
  420. break;
  421. case PROCESSOR_ARCHITECTURE_IA64:
  422. *MachineType = IMAGE_FILE_MACHINE_IA64;
  423. m_ContextSize = sizeof(IA64_CONTEXT);
  424. break;
  425. case PROCESSOR_ARCHITECTURE_AMD64:
  426. *MachineType = IMAGE_FILE_MACHINE_AMD64;
  427. m_ContextSize = sizeof(AMD64_CONTEXT);
  428. break;
  429. #endif // #ifndef _WIN32_WCE
  430. case PROCESSOR_ARCHITECTURE_ARM:
  431. *MachineType = IMAGE_FILE_MACHINE_ARM;
  432. #ifndef _WIN32_WCE
  433. m_ContextSize = sizeof(ARM_CONTEXT);
  434. #else
  435. m_ContextSize = sizeof(CONTEXT);
  436. #endif
  437. break;
  438. default:
  439. return E_UNEXPECTED;
  440. }
  441. *NumberProcessors = NumProc;
  442. *PlatformId = OsVersionInfo.dwPlatformId;
  443. *BuildNumber = OsVersionInfo.dwBuildNumber;
  444. *CheckedBuild = 0;
  445. if (WideCsd)
  446. {
  447. if (!WideCharToMultiByte(CP_ACP, 0, OsVersionInfo.szCSDVersion, -1,
  448. CsdString, CsdStringSize, NULL, NULL))
  449. {
  450. CsdString[0] = 0;
  451. }
  452. }
  453. else
  454. {
  455. CopyString(CsdString, (PSTR)OsVersionInfo.szCSDVersion, CsdStringSize);
  456. }
  457. BuildString[0] = 0;
  458. *ProductType = OsVersionInfo.wProductType;
  459. *SuiteMask = OsVersionInfo.wSuiteMask;
  460. #ifndef NT_NATIVE
  461. if (VER_PLATFORM_WIN32_NT == OsVersionInfo.dwPlatformId)
  462. {
  463. HKEY hkey = NULL;
  464. TCHAR sz[40] = {0};
  465. DWORD dwType;
  466. DWORD dwSize = sizeof(sz);
  467. if (ERROR_SUCCESS ==
  468. RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  469. "Software\\Microsoft\\Windows NT\\CurrentVersion",
  470. 0,
  471. KEY_READ,
  472. &hkey))
  473. {
  474. if (ERROR_SUCCESS ==
  475. RegQueryValueEx(hkey,
  476. "CurrentType",
  477. NULL,
  478. &dwType,
  479. (PUCHAR) sz,
  480. &dwSize))
  481. {
  482. if (*sz)
  483. {
  484. _strlwr(sz);
  485. if (strstr(sz, "checked"))
  486. {
  487. *CheckedBuild = 0xC;
  488. }
  489. }
  490. }
  491. RegCloseKey(hkey);
  492. }
  493. if (OsVersionInfo.dwBuildNumber > 2195)
  494. {
  495. char RawString[128];
  496. // Look up the file version string for a system DLL to
  497. // try and get the build lab information.
  498. strcpy(RawString, "kernel32.dll version: ");
  499. GetFileStringFileInfo(L"kernel32.dll", "FileVersion",
  500. RawString + strlen(RawString),
  501. sizeof(RawString) - strlen(RawString));
  502. CopyString(BuildString, RawString, BuildStringSize);
  503. }
  504. }
  505. #endif // #ifndef NT_NATIVE
  506. return S_OK;
  507. }
  508. STDMETHODIMP
  509. LiveUserDebugServices::GetConnectionInfo(
  510. THIS_
  511. OUT OPTIONAL PSTR MachineName,
  512. IN ULONG MachineNameSize,
  513. OUT OPTIONAL PSTR ClientIdentity,
  514. IN ULONG ClientIdentitySize,
  515. OUT OPTIONAL PSTR TransportIdentity,
  516. IN ULONG TransportIdentitySize
  517. )
  518. {
  519. HRESULT Status = S_OK;
  520. if (MachineName)
  521. {
  522. #if defined(NT_NATIVE) || defined(_WIN32_WCE)
  523. if (FillStringBuffer("<ComputerName>", 0,
  524. MachineName, MachineNameSize,
  525. NULL) == S_FALSE)
  526. {
  527. Status = S_FALSE;
  528. }
  529. #else
  530. ULONG CompSize;
  531. CompSize = MachineNameSize;
  532. if (!GetComputerName(MachineName, &CompSize))
  533. {
  534. return WIN32_LAST_STATUS();
  535. }
  536. #endif
  537. }
  538. if (ClientIdentity)
  539. {
  540. if (FillStringBuffer(m_ClientIdentity, 0,
  541. ClientIdentity, ClientIdentitySize,
  542. NULL) == S_FALSE)
  543. {
  544. Status = S_FALSE;
  545. }
  546. }
  547. if (TransportIdentity)
  548. {
  549. if (FillStringBuffer(m_TransIdentity, 0,
  550. TransportIdentity, TransportIdentitySize,
  551. NULL) == S_FALSE)
  552. {
  553. Status = S_FALSE;
  554. }
  555. }
  556. return Status;
  557. }
  558. BOOL
  559. X86CpuId(
  560. IN ULONG SubFunction,
  561. OUT PULONG EaxRegister,
  562. OUT PULONG EbxRegister,
  563. OUT PULONG EcxRegister,
  564. OUT PULONG EdxRegister
  565. )
  566. {
  567. #ifdef _X86_
  568. ULONG _Eax;
  569. ULONG _Ebx;
  570. ULONG _Ecx;
  571. ULONG _Edx;
  572. __asm
  573. {
  574. ; Preserve ebx as its value will be changed by cpuid.
  575. push ebx
  576. mov eax, SubFunction
  577. __emit 0x0F
  578. __emit 0xA2 ;; CPUID
  579. mov _Eax, eax
  580. mov _Ebx, ebx
  581. mov _Ecx, ecx
  582. mov _Edx, edx
  583. pop ebx
  584. }
  585. *EaxRegister = _Eax;
  586. *EbxRegister = _Ebx;
  587. *EcxRegister = _Ecx;
  588. *EdxRegister = _Edx;
  589. return TRUE;
  590. #else
  591. return FALSE;
  592. #endif // #ifdef _X86_
  593. }
  594. BOOL
  595. Ia64CpuId(ULONG Reg, PULONG64 Val)
  596. {
  597. // XXX drewb - How should this be implemented?
  598. #if defined(_IA64_) && defined(IA64_INLINE_ASSEMBLY)
  599. ULONG64 _Val;
  600. __asm mov t0, Reg;
  601. __asm mov _Val, cpuid[t0];
  602. *Val = _Val;
  603. return TRUE;
  604. #else
  605. return FALSE;
  606. #endif
  607. }
  608. STDMETHODIMP
  609. LiveUserDebugServices::GetProcessorId(
  610. THIS_
  611. OUT PVOID Buffer,
  612. IN ULONG BufferSize,
  613. OUT PULONG BufferUsed
  614. )
  615. {
  616. if (BufferSize < sizeof(DEBUG_PROCESSOR_IDENTIFICATION_ALL))
  617. {
  618. return E_INVALIDARG;
  619. }
  620. ZeroMemory(Buffer, sizeof(DEBUG_PROCESSOR_IDENTIFICATION_ALL));
  621. ULONG ProcArch, ProcLevel, ProcRevision;
  622. #ifdef NT_NATIVE
  623. NTSTATUS NtStatus;
  624. SYSTEM_PROCESSOR_INFORMATION ProcInfo;
  625. if (!NT_SUCCESS(NtStatus =
  626. NtQuerySystemInformation(SystemProcessorInformation,
  627. &ProcInfo, sizeof(ProcInfo),
  628. NULL)))
  629. {
  630. return HRESULT_FROM_NT(NtStatus);
  631. }
  632. ProcArch = ProcInfo.ProcessorArchitecture;
  633. ProcLevel = ProcInfo.ProcessorLevel;
  634. ProcRevision = ProcInfo.ProcessorRevision;
  635. #else
  636. SYSTEM_INFO SystemInfo;
  637. ::GetSystemInfo(&SystemInfo);
  638. ProcArch = SystemInfo.wProcessorArchitecture;
  639. ProcLevel = SystemInfo.wProcessorLevel;
  640. ProcRevision = SystemInfo.wProcessorRevision;
  641. #endif
  642. PDEBUG_PROCESSOR_IDENTIFICATION_ALL Id =
  643. (PDEBUG_PROCESSOR_IDENTIFICATION_ALL)Buffer;
  644. switch(ProcArch)
  645. {
  646. case PROCESSOR_ARCHITECTURE_INTEL:
  647. *BufferUsed = sizeof(DEBUG_PROCESSOR_IDENTIFICATION_X86);
  648. Id->X86.Family = ProcLevel;
  649. Id->X86.Model = (ProcRevision >> 8) & 0xf;
  650. Id->X86.Stepping = ProcRevision & 0xf;
  651. if (ProcLevel >= 5)
  652. {
  653. ULONG Eax, Ebx, Ecx, Edx;
  654. if (X86CpuId(0, &Eax, &Ebx, &Ecx, &Edx))
  655. {
  656. *(PULONG)(Id->X86.VendorString + 0 * sizeof(ULONG)) = Ebx;
  657. *(PULONG)(Id->X86.VendorString + 1 * sizeof(ULONG)) = Edx;
  658. *(PULONG)(Id->X86.VendorString + 2 * sizeof(ULONG)) = Ecx;
  659. }
  660. }
  661. break;
  662. #ifndef _WIN32_WCE
  663. case PROCESSOR_ARCHITECTURE_ALPHA:
  664. *BufferUsed = sizeof(DEBUG_PROCESSOR_IDENTIFICATION_ALPHA);
  665. Id->Alpha.Type = ProcLevel;
  666. Id->Alpha.Revision = ProcRevision;
  667. break;
  668. case PROCESSOR_ARCHITECTURE_IA64:
  669. ULONG64 Val;
  670. *BufferUsed = sizeof(DEBUG_PROCESSOR_IDENTIFICATION_IA64);
  671. Id->Ia64.Model = ProcLevel;
  672. Id->Ia64.Revision = ProcRevision;
  673. if (Ia64CpuId(3, &Val))
  674. {
  675. Id->Ia64.ArchRev = (ULONG)((Val >> 32) & 0xff);
  676. Id->Ia64.Family = (ULONG)((Val >> 24) & 0xff);
  677. Ia64CpuId(0, (PULONG64)
  678. (Id->Ia64.VendorString + 0 * sizeof(ULONG64)));
  679. Ia64CpuId(1, (PULONG64)
  680. (Id->Ia64.VendorString + 1 * sizeof(ULONG64)));
  681. }
  682. break;
  683. case PROCESSOR_ARCHITECTURE_AMD64:
  684. *BufferUsed = sizeof(DEBUG_PROCESSOR_IDENTIFICATION_AMD64);
  685. Id->Amd64.Family = ProcLevel;
  686. Id->Amd64.Model = (ProcRevision >> 8) & 0xf;
  687. Id->Amd64.Stepping = ProcRevision & 0xf;
  688. break;
  689. #endif // #ifndef _WIN32_WCE
  690. case PROCESSOR_ARCHITECTURE_ARM:
  691. *BufferUsed = sizeof(DEBUG_PROCESSOR_IDENTIFICATION_ARM);
  692. Id->Arm.Type = ProcLevel;
  693. Id->Arm.Revision = ProcRevision;
  694. break;
  695. }
  696. return S_OK;
  697. }
  698. STDMETHODIMP
  699. LiveUserDebugServices::GetGenericProcessorFeatures(
  700. THIS_
  701. OUT OPTIONAL /* size_is(FeaturesSize) */ PULONG64 Features,
  702. IN ULONG FeaturesSize,
  703. OUT OPTIONAL PULONG Used
  704. )
  705. {
  706. ULONG ChunkIndex, BitIndex;
  707. PULONG64 ChunkBits;
  708. ULONG Max;
  709. //
  710. // IsProcessorFeaturePresent doesn't have a fixed upper
  711. // limit so we can't easily say how many bits are
  712. // needed. Right now there are only 11 feature bits
  713. // defined, though, so guessing 128 should give
  714. // plenty of room for expansion.
  715. //
  716. Max = 128 / sizeof(*Features);
  717. if (Used)
  718. {
  719. *Used = Max;
  720. }
  721. if (Features)
  722. {
  723. //
  724. // Fill in as many bits as were provided, up to the maximum.
  725. //
  726. if (FeaturesSize > Max)
  727. {
  728. FeaturesSize = Max;
  729. }
  730. ChunkBits = Features;
  731. for (ChunkIndex = 0; ChunkIndex < FeaturesSize; ChunkIndex++)
  732. {
  733. *ChunkBits = 0;
  734. for (BitIndex = 0; BitIndex < 8 * sizeof(*Features); BitIndex++)
  735. {
  736. ULONG PfIndex = ChunkIndex * sizeof(*Features) + BitIndex;
  737. #ifdef NT_NATIVE
  738. if (USER_SHARED_DATA->ProcessorFeatures[PfIndex])
  739. #else
  740. if (::IsProcessorFeaturePresent(PfIndex))
  741. #endif
  742. {
  743. *ChunkBits |= 1UI64 << BitIndex;
  744. }
  745. }
  746. ChunkBits++;
  747. }
  748. }
  749. return S_OK;
  750. }
  751. STDMETHODIMP
  752. LiveUserDebugServices::GetSpecificProcessorFeatures(
  753. THIS_
  754. OUT OPTIONAL /* size_is(FeaturesSize) */ PULONG64 Features,
  755. IN ULONG FeaturesSize,
  756. OUT OPTIONAL PULONG Used
  757. )
  758. {
  759. #ifdef _X86_
  760. ULONG Count = 0;
  761. ULONG Eax, Ebx, Ecx, Edx;
  762. BOOL Amd = FALSE;
  763. if (!Features)
  764. {
  765. FeaturesSize = 0;
  766. }
  767. //
  768. // x86 indices are:
  769. // 0 = CPUID version information.
  770. // 1 = CPUID feature information.
  771. // 2 = Extended feature information.
  772. //
  773. if (!X86CpuId(0, &Eax, &Ebx, &Ecx, &Edx))
  774. {
  775. return E_FAIL;
  776. }
  777. if (Ebx == AMD_VENDOR_ID_EBX &&
  778. Edx == AMD_VENDOR_ID_EDX &&
  779. Ecx == AMD_VENDOR_ID_ECX)
  780. {
  781. Amd = TRUE;
  782. }
  783. if (!X86CpuId(1, &Eax, &Ebx, &Ecx, &Edx))
  784. {
  785. return E_FAIL;
  786. }
  787. Count += 2;
  788. if (FeaturesSize > 0)
  789. {
  790. *Features++ = Eax;
  791. FeaturesSize--;
  792. }
  793. if (FeaturesSize > 0)
  794. {
  795. *Features++ = Edx;
  796. FeaturesSize--;
  797. }
  798. if (Amd)
  799. {
  800. if (!X86CpuId(0x80000001, &Eax, &Ebx, &Ecx, &Edx))
  801. {
  802. return E_FAIL;
  803. }
  804. Count++;
  805. if (FeaturesSize > 0)
  806. {
  807. *Features++ = Edx;
  808. FeaturesSize--;
  809. }
  810. }
  811. if (Used)
  812. {
  813. *Used = Count;
  814. }
  815. return S_OK;
  816. #else // #ifdef _X86_
  817. return E_NOINTERFACE;
  818. #endif
  819. }
  820. STDMETHODIMP
  821. LiveUserDebugServices::GetFileVersionInformationA(
  822. THIS_
  823. IN PCWSTR File,
  824. IN PCSTR Item,
  825. OUT OPTIONAL PVOID Buffer,
  826. IN ULONG BufferSize,
  827. OUT OPTIONAL PULONG VerInfoSize
  828. )
  829. {
  830. #ifndef NT_NATIVE
  831. PVOID AllInfo = GetAllFileVersionInfo(File);
  832. if (AllInfo == NULL)
  833. {
  834. return E_OUTOFMEMORY;
  835. }
  836. HRESULT Status;
  837. PVOID Val;
  838. UINT ValSize;
  839. if (VerQueryValue(AllInfo, (PSTR)Item, &Val, &ValSize))
  840. {
  841. Status = FillDataBuffer(Val, ValSize,
  842. Buffer, BufferSize, VerInfoSize);
  843. }
  844. else
  845. {
  846. Status = WIN32_LAST_STATUS();
  847. }
  848. free(AllInfo);
  849. return Status;
  850. #else // #ifndef NT_NATIVE
  851. return E_UNEXPECTED;
  852. #endif // #ifndef NT_NATIVE
  853. }
  854. HRESULT
  855. GetNtSystemProcessInformation(PSYSTEM_PROCESS_INFORMATION* ProcInfo)
  856. {
  857. #ifdef _WIN32_WCE
  858. return E_NOTIMPL;
  859. #else
  860. NTSTATUS NtStatus;
  861. PVOID Buffer;
  862. SIZE_T BufferSize = 8192;
  863. for (;;)
  864. {
  865. Buffer = NULL;
  866. NtStatus = g_NtDllCalls.
  867. NtAllocateVirtualMemory(NtCurrentProcess(),
  868. &Buffer, 0, &BufferSize,
  869. MEM_COMMIT, PAGE_READWRITE);
  870. if (!NT_SUCCESS(NtStatus))
  871. {
  872. return HRESULT_FROM_NT(NtStatus);
  873. }
  874. NtStatus = g_NtDllCalls.
  875. NtQuerySystemInformation(SystemProcessInformation,
  876. Buffer, (ULONG)BufferSize, NULL);
  877. if (NT_SUCCESS(NtStatus))
  878. {
  879. break;
  880. }
  881. g_NtDllCalls.NtFreeVirtualMemory(NtCurrentProcess(),
  882. &Buffer, &BufferSize, MEM_RELEASE);
  883. if (NtStatus == STATUS_INFO_LENGTH_MISMATCH)
  884. {
  885. BufferSize += 8192;
  886. }
  887. else
  888. {
  889. return HRESULT_FROM_NT(NtStatus);
  890. }
  891. }
  892. *ProcInfo = (PSYSTEM_PROCESS_INFORMATION)Buffer;
  893. return S_OK;
  894. #endif // #ifndef _WIN32_WCE
  895. }
  896. HRESULT
  897. NtGetProcessIds(PULONG Ids, ULONG Count, PULONG ActualCount)
  898. {
  899. #ifdef _WIN32_WCE
  900. return E_NOTIMPL;
  901. #else
  902. HRESULT Status;
  903. PSYSTEM_PROCESS_INFORMATION ProcessInfo, ProcInfoBuffer;
  904. if ((Status = GetNtSystemProcessInformation(&ProcInfoBuffer)) != S_OK)
  905. {
  906. return Status;
  907. }
  908. ULONG TotalOffset;
  909. ULONG ProcessCount;
  910. ProcessInfo = ProcInfoBuffer;
  911. TotalOffset = 0;
  912. ProcessCount = 0;
  913. for (;;)
  914. {
  915. if (ProcessCount < Count)
  916. {
  917. Ids[ProcessCount] = (ULONG)(ULONG_PTR)ProcessInfo->UniqueProcessId;
  918. }
  919. ProcessCount++;
  920. if (ProcessInfo->NextEntryOffset == 0)
  921. {
  922. break;
  923. }
  924. TotalOffset += ProcessInfo->NextEntryOffset;
  925. ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)
  926. ((PUCHAR)ProcInfoBuffer + TotalOffset);
  927. }
  928. if (ActualCount != NULL)
  929. {
  930. *ActualCount = ProcessCount;
  931. }
  932. SIZE_T MemSize = 0;
  933. g_NtDllCalls.NtFreeVirtualMemory(NtCurrentProcess(),
  934. (PVOID*)&ProcInfoBuffer, &MemSize,
  935. MEM_RELEASE);
  936. return Status;
  937. #endif // #ifndef _WIN32_WCE
  938. }
  939. HRESULT
  940. ThGetProcessIds(PULONG Ids, ULONG Count, PULONG ActualCount)
  941. {
  942. #ifndef NT_NATIVE
  943. HANDLE Snap;
  944. Snap = g_Kernel32Calls.CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  945. if (Snap == INVALID_HANDLE_VALUE)
  946. {
  947. return WIN32_LAST_STATUS();
  948. }
  949. ULONG ProcessCount = 0;
  950. for (;;)
  951. {
  952. PROCESSENTRY32 Proc;
  953. BOOL Succ;
  954. Proc.dwSize = sizeof(Proc);
  955. if (ProcessCount == 0)
  956. {
  957. Succ = g_Kernel32Calls.Process32First(Snap, &Proc);
  958. }
  959. else
  960. {
  961. Succ = g_Kernel32Calls.Process32Next(Snap, &Proc);
  962. }
  963. if (!Succ)
  964. {
  965. break;
  966. }
  967. if (ProcessCount < Count)
  968. {
  969. Ids[ProcessCount] = Proc.th32ProcessID;
  970. }
  971. ProcessCount++;
  972. }
  973. if (ActualCount != NULL)
  974. {
  975. *ActualCount = ProcessCount;
  976. }
  977. CloseHandle(Snap);
  978. return S_OK;
  979. #else
  980. return E_UNEXPECTED;
  981. #endif
  982. }
  983. STDMETHODIMP
  984. LiveUserDebugServices::GetProcessIds(
  985. THIS_
  986. OUT OPTIONAL /* size_is(Count) */ PULONG Ids,
  987. IN ULONG Count,
  988. OUT OPTIONAL PULONG ActualCount
  989. )
  990. {
  991. HRESULT Status;
  992. // Allow privileged enumeration.
  993. if ((Status = EnableDebugPrivilege()) != S_OK)
  994. {
  995. return Status;
  996. }
  997. switch(m_PlatformId)
  998. {
  999. case VER_PLATFORM_WIN32_NT:
  1000. return NtGetProcessIds(Ids, Count, ActualCount);
  1001. case VER_PLATFORM_WIN32_WINDOWS:
  1002. case VER_PLATFORM_WIN32_CE:
  1003. return ThGetProcessIds(Ids, Count, ActualCount);
  1004. default:
  1005. return E_UNEXPECTED;
  1006. }
  1007. }
  1008. HRESULT
  1009. NtGetPidByExe(PCWSTR ExeName, ULONG Flags, PULONG Id)
  1010. {
  1011. #ifdef _WIN32_WCE
  1012. return E_NOTIMPL;
  1013. #else
  1014. HRESULT Status;
  1015. BOOL HasPath;
  1016. // Check if the given name has path components.
  1017. HasPath =
  1018. wcschr(ExeName, '\\') != NULL ||
  1019. wcschr(ExeName, '/') != NULL ||
  1020. (ExeName[0] && ExeName[1] == ':');
  1021. PSYSTEM_PROCESS_INFORMATION ProcessInfo, ProcInfoBuffer;
  1022. if ((Status = GetNtSystemProcessInformation(&ProcInfoBuffer)) != S_OK)
  1023. {
  1024. return Status;
  1025. }
  1026. ULONG TotalOffset;
  1027. ULONG FoundId;
  1028. ProcessInfo = ProcInfoBuffer;
  1029. TotalOffset = 0;
  1030. FoundId = DEBUG_ANY_ID;
  1031. Status = E_NOINTERFACE;
  1032. for (;;)
  1033. {
  1034. PWSTR ImageName;
  1035. if (ProcessInfo->ImageName.Buffer == NULL)
  1036. {
  1037. ImageName = SYSTEM_PROCESS_NAME_W;
  1038. }
  1039. else
  1040. {
  1041. ImageName = ProcessInfo->ImageName.Buffer;
  1042. }
  1043. if ((Flags & DEBUG_GET_PROC_FULL_MATCH) == 0 &&
  1044. !HasPath)
  1045. {
  1046. PWSTR Slash;
  1047. Slash = wcsrchr(ImageName, '\\');
  1048. if (Slash == NULL)
  1049. {
  1050. Slash = wcsrchr(ImageName, '/');
  1051. }
  1052. if (Slash != NULL)
  1053. {
  1054. ImageName = Slash + 1;
  1055. }
  1056. }
  1057. if (!_wcsicmp(ImageName, ExeName))
  1058. {
  1059. if ((Flags & DEBUG_GET_PROC_ONLY_MATCH) &&
  1060. FoundId != DEBUG_ANY_ID)
  1061. {
  1062. Status = S_FALSE;
  1063. break;
  1064. }
  1065. Status = S_OK;
  1066. FoundId = (ULONG)(ULONG_PTR)ProcessInfo->UniqueProcessId;
  1067. *Id = FoundId;
  1068. if ((Flags & DEBUG_GET_PROC_ONLY_MATCH) == 0)
  1069. {
  1070. break;
  1071. }
  1072. }
  1073. if (ProcessInfo->NextEntryOffset == 0)
  1074. {
  1075. break;
  1076. }
  1077. TotalOffset += ProcessInfo->NextEntryOffset;
  1078. ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)
  1079. ((PUCHAR)ProcInfoBuffer + TotalOffset);
  1080. }
  1081. SIZE_T MemSize = 0;
  1082. g_NtDllCalls.NtFreeVirtualMemory(NtCurrentProcess(),
  1083. (PVOID*)&ProcInfoBuffer, &MemSize,
  1084. MEM_RELEASE);
  1085. return Status;
  1086. #endif // #ifndef _WIN32_WCE
  1087. }
  1088. HRESULT
  1089. ThGetPidByExe(PCWSTR ExeName, ULONG Flags, PULONG Id)
  1090. {
  1091. #ifndef NT_NATIVE
  1092. HRESULT Status;
  1093. HANDLE Snap;
  1094. char ExeNameA[MAX_PATH];
  1095. if (!WideCharToMultiByte(CP_ACP, 0, ExeName, -1,
  1096. ExeNameA, sizeof(ExeNameA),
  1097. NULL, NULL))
  1098. {
  1099. return WIN32_LAST_STATUS();
  1100. }
  1101. Snap = g_Kernel32Calls.CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  1102. if (Snap == INVALID_HANDLE_VALUE)
  1103. {
  1104. return WIN32_LAST_STATUS();
  1105. }
  1106. // Check if the given name has path components.
  1107. BOOL HasPath =
  1108. strchr(ExeNameA, '\\') != NULL ||
  1109. strchr(ExeNameA, '/') != NULL ||
  1110. (ExeNameA[0] && ExeNameA[1] == ':');
  1111. ULONG FoundId = DEBUG_ANY_ID;
  1112. BOOL First = TRUE;
  1113. for (;;)
  1114. {
  1115. PROCESSENTRY32 Proc;
  1116. BOOL Succ;
  1117. Proc.dwSize = sizeof(Proc);
  1118. if (First)
  1119. {
  1120. Succ = g_Kernel32Calls.Process32First(Snap, &Proc);
  1121. First = FALSE;
  1122. }
  1123. else
  1124. {
  1125. Succ = g_Kernel32Calls.Process32Next(Snap, &Proc);
  1126. }
  1127. if (!Succ)
  1128. {
  1129. break;
  1130. }
  1131. PSTR ImageName = Proc.szExeFile;
  1132. if ((Flags & DEBUG_GET_PROC_FULL_MATCH) == 0 &&
  1133. !HasPath)
  1134. {
  1135. PSTR Slash;
  1136. Slash = strrchr(ImageName, '\\');
  1137. if (Slash == NULL)
  1138. {
  1139. Slash = strrchr(ImageName, '/');
  1140. }
  1141. if (Slash != NULL)
  1142. {
  1143. ImageName = Slash + 1;
  1144. }
  1145. }
  1146. if (!_stricmp(ImageName, ExeNameA))
  1147. {
  1148. if ((Flags & DEBUG_GET_PROC_ONLY_MATCH) &&
  1149. FoundId != DEBUG_ANY_ID)
  1150. {
  1151. Status = S_FALSE;
  1152. break;
  1153. }
  1154. Status = S_OK;
  1155. FoundId = Proc.th32ProcessID;
  1156. *Id = FoundId;
  1157. if ((Flags & DEBUG_GET_PROC_ONLY_MATCH) == 0)
  1158. {
  1159. break;
  1160. }
  1161. }
  1162. }
  1163. CloseHandle(Snap);
  1164. return S_OK;
  1165. #else
  1166. return E_UNEXPECTED;
  1167. #endif
  1168. }
  1169. STDMETHODIMP
  1170. LiveUserDebugServices::GetProcessIdByExecutableNameW(
  1171. THIS_
  1172. IN PCWSTR ExeName,
  1173. IN ULONG Flags,
  1174. OUT PULONG Id
  1175. )
  1176. {
  1177. HRESULT Status;
  1178. // Allow privileged enumeration.
  1179. if ((Status = EnableDebugPrivilege()) != S_OK)
  1180. {
  1181. return Status;
  1182. }
  1183. switch(m_PlatformId)
  1184. {
  1185. case VER_PLATFORM_WIN32_NT:
  1186. return NtGetPidByExe(ExeName, Flags, Id);
  1187. case VER_PLATFORM_WIN32_WINDOWS:
  1188. case VER_PLATFORM_WIN32_CE:
  1189. return ThGetPidByExe(ExeName, Flags, Id);
  1190. default:
  1191. return E_UNEXPECTED;
  1192. }
  1193. }
  1194. #if !defined(NT_NATIVE) && !defined(_WIN32_WCE)
  1195. HRESULT
  1196. NtGetServiceStatus(PULONG NumServices,
  1197. LPENUM_SERVICE_STATUS_PROCESSW* ServiceStatus)
  1198. {
  1199. SC_HANDLE Scm;
  1200. Scm = g_Advapi32Calls.OpenSCManagerW(NULL, NULL,
  1201. SC_MANAGER_CONNECT |
  1202. SC_MANAGER_ENUMERATE_SERVICE);
  1203. if (!Scm)
  1204. {
  1205. return WIN32_LAST_STATUS();
  1206. }
  1207. HRESULT Status;
  1208. LPENUM_SERVICE_STATUS_PROCESSW Info;
  1209. ULONG InfoSize = 8 * 1024;
  1210. ULONG ExtraNeeded;
  1211. ULONG Resume;
  1212. ULONG Loop = 0;
  1213. //
  1214. // First pass through the loop allocates from an initial guess.
  1215. // If that isn't sufficient, we make another pass and allocate
  1216. // what is actually needed. Things may have changed due to
  1217. // other machine changes, so loop around a few times before
  1218. // giving up.
  1219. //
  1220. for (;;)
  1221. {
  1222. Info = (LPENUM_SERVICE_STATUS_PROCESSW)malloc(InfoSize);
  1223. if (!Info)
  1224. {
  1225. Status = E_OUTOFMEMORY;
  1226. break;
  1227. }
  1228. Resume = 0;
  1229. if (!g_Advapi32Calls.EnumServicesStatusExW(Scm,
  1230. SC_ENUM_PROCESS_INFO,
  1231. SERVICE_WIN32,
  1232. SERVICE_ACTIVE,
  1233. (LPBYTE)Info,
  1234. InfoSize,
  1235. &ExtraNeeded,
  1236. NumServices,
  1237. &Resume,
  1238. NULL))
  1239. {
  1240. free(Info);
  1241. if (Loop > 2 || GetLastError() != ERROR_MORE_DATA)
  1242. {
  1243. Status = WIN32_LAST_STATUS();
  1244. break;
  1245. }
  1246. }
  1247. else
  1248. {
  1249. *ServiceStatus = Info;
  1250. Status = S_OK;
  1251. break;
  1252. }
  1253. InfoSize += ExtraNeeded;
  1254. Loop++;
  1255. }
  1256. CloseServiceHandle(Scm);
  1257. return Status;
  1258. }
  1259. HRESULT
  1260. NtGetProcessServiceNames(HRESULT RetStatus, ULONG ProcessId,
  1261. PWSTR* Description, ULONG* DescriptionSize,
  1262. PULONG ActualDescriptionSize, PBOOL Any)
  1263. {
  1264. HRESULT Status;
  1265. if (!g_Advapi32Calls.EnumServicesStatusExW ||
  1266. !g_Advapi32Calls.OpenSCManagerW)
  1267. {
  1268. return RetStatus;
  1269. }
  1270. ULONG i, NumServices;
  1271. LPENUM_SERVICE_STATUS_PROCESSW ServiceStatus;
  1272. BOOL AnyServices = FALSE;
  1273. if ((Status = NtGetServiceStatus(&NumServices, &ServiceStatus)) != S_OK)
  1274. {
  1275. // If we can't get the service status just leave the
  1276. // string unchanged and do not consider it a serious error.
  1277. return RetStatus;
  1278. }
  1279. for (i = 0; i < NumServices; i++)
  1280. {
  1281. if (ServiceStatus[i].ServiceStatusProcess.dwProcessId != ProcessId ||
  1282. !ServiceStatus[i].lpServiceName ||
  1283. !ServiceStatus[i].lpServiceName[0])
  1284. {
  1285. continue;
  1286. }
  1287. PWSTR Intro;
  1288. if (AnyServices)
  1289. {
  1290. Intro = L",";
  1291. }
  1292. else if (*Any)
  1293. {
  1294. Intro = L" Services: ";
  1295. }
  1296. else
  1297. {
  1298. Intro = L"Services: ";
  1299. }
  1300. RetStatus = AppendToStringBufferW(RetStatus, Intro, !*Any,
  1301. Description, DescriptionSize,
  1302. ActualDescriptionSize);
  1303. RetStatus = AppendToStringBufferW(RetStatus,
  1304. ServiceStatus[i].lpServiceName,
  1305. FALSE, Description, DescriptionSize,
  1306. ActualDescriptionSize);
  1307. *Any = TRUE;
  1308. AnyServices = TRUE;
  1309. }
  1310. free(ServiceStatus);
  1311. return RetStatus;
  1312. }
  1313. HRESULT
  1314. NtGetProcessMtsPackageNames(HRESULT RetStatus, ULONG ProcessId,
  1315. PWSTR* Description, ULONG* DescriptionSize,
  1316. PULONG ActualDescriptionSize, PBOOL Any)
  1317. {
  1318. HRESULT Status;
  1319. // Load and initialize ole32.dll so we can call CoCreateInstance.
  1320. if ((Status = InitDynamicCalls(&g_Ole32CallsDesc)) != S_OK ||
  1321. (Status = InitDynamicCalls(&g_OleAut32CallsDesc)) != S_OK ||
  1322. FAILED(Status = g_Ole32Calls.CoInitializeEx(NULL, COM_THREAD_MODEL)))
  1323. {
  1324. // Just leave things unchanged on failure.
  1325. return RetStatus;
  1326. }
  1327. IMtsGrp* MtsGrp = NULL;
  1328. long Packages;
  1329. long i;
  1330. BOOL AnyPackages = FALSE;
  1331. if ((Status = g_Ole32Calls.
  1332. CoCreateInstance(CLSID_MtsGrp, NULL, CLSCTX_ALL,
  1333. __uuidof(IMtsGrp), (void **)&MtsGrp)) != S_OK ||
  1334. (Status = MtsGrp->Refresh()) != S_OK ||
  1335. (Status = MtsGrp->get_Count(&Packages)) != S_OK)
  1336. {
  1337. goto Exit;
  1338. }
  1339. for (i = 0; i < Packages; i++)
  1340. {
  1341. IUnknown* Unk;
  1342. IMtsEvents* Events;
  1343. BSTR Name;
  1344. ULONG Pid;
  1345. if ((Status = MtsGrp->Item(i, &Unk)) != S_OK)
  1346. {
  1347. continue;
  1348. }
  1349. Status = Unk->QueryInterface(IID_IMtsEvents, (void **)&Events);
  1350. Unk->Release();
  1351. if (Status != S_OK)
  1352. {
  1353. continue;
  1354. }
  1355. Status = Events->GetProcessID((PLONG)&Pid);
  1356. if (Status == S_OK && Pid == ProcessId)
  1357. {
  1358. Status = Events->get_PackageName(&Name);
  1359. }
  1360. Events->Release();
  1361. if (Status != S_OK || Pid != ProcessId)
  1362. {
  1363. continue;
  1364. }
  1365. PWSTR Intro;
  1366. if (AnyPackages)
  1367. {
  1368. Intro = L",";
  1369. }
  1370. else if (*Any)
  1371. {
  1372. Intro = L" MTS Packages: ";
  1373. }
  1374. else
  1375. {
  1376. Intro = L"MTS Packages: ";
  1377. }
  1378. RetStatus = AppendToStringBufferW(RetStatus, Intro, !*Any,
  1379. Description, DescriptionSize,
  1380. ActualDescriptionSize);
  1381. RetStatus = AppendToStringBufferW(RetStatus, Name, FALSE,
  1382. Description, DescriptionSize,
  1383. ActualDescriptionSize);
  1384. g_OleAut32Calls.SysFreeString(Name);
  1385. *Any = TRUE;
  1386. AnyPackages = TRUE;
  1387. }
  1388. Exit:
  1389. if (MtsGrp)
  1390. {
  1391. MtsGrp->Release();
  1392. }
  1393. g_Ole32Calls.CoUninitialize();
  1394. return RetStatus;
  1395. }
  1396. #endif // if !defined(NT_NATIVE) && !defined(_WIN32_WCE)
  1397. HRESULT
  1398. NtGetProcessCommandLine(HRESULT RetStatus, HANDLE Process,
  1399. PUNICODE_STRING ParamsCmdLine,
  1400. PWSTR* Description, ULONG* DescriptionSize,
  1401. PULONG ActualDescriptionSize, PBOOL Any)
  1402. {
  1403. PWSTR FullStr;
  1404. PWSTR Intro;
  1405. SIZE_T Done;
  1406. if (!ParamsCmdLine->Buffer)
  1407. {
  1408. return RetStatus;
  1409. }
  1410. FullStr = (PWSTR)malloc(ParamsCmdLine->Length + sizeof(*FullStr));
  1411. if (!FullStr)
  1412. {
  1413. return RetStatus;
  1414. }
  1415. if (!::ReadProcessMemory(Process, ParamsCmdLine->Buffer,
  1416. FullStr, ParamsCmdLine->Length, &Done) ||
  1417. Done < sizeof(*FullStr))
  1418. {
  1419. goto EH_FullStr;
  1420. }
  1421. FullStr[Done / sizeof(*FullStr)] = 0;
  1422. if (*Any)
  1423. {
  1424. Intro = L" Command Line: ";
  1425. }
  1426. else
  1427. {
  1428. Intro = L"Command Line: ";
  1429. }
  1430. RetStatus = AppendToStringBufferW(RetStatus, Intro, !*Any,
  1431. Description, DescriptionSize,
  1432. ActualDescriptionSize);
  1433. RetStatus = AppendToStringBufferW(RetStatus, FullStr, FALSE,
  1434. Description, DescriptionSize,
  1435. ActualDescriptionSize);
  1436. *Any = TRUE;
  1437. EH_FullStr:
  1438. free(FullStr);
  1439. return RetStatus;
  1440. }
  1441. HRESULT
  1442. NtGetProcDesc(ULONG ProcessId, ULONG Flags,
  1443. PWSTR ExeName, ULONG ExeNameSize, PULONG ActualExeNameSize,
  1444. PWSTR Description, ULONG DescriptionSize,
  1445. PULONG ActualDescriptionSize)
  1446. {
  1447. #ifdef _WIN32_WCE
  1448. return E_NOTIMPL;
  1449. #else
  1450. HRESULT Status;
  1451. if (ProcessId == 0)
  1452. {
  1453. // This is base system process so fake the description.
  1454. Status = FillStringBufferW(SYSTEM_PROCESS_NAME_W, 0,
  1455. ExeName, ExeNameSize, ActualExeNameSize);
  1456. FillStringBufferW(L"", 0,
  1457. Description, DescriptionSize, ActualDescriptionSize);
  1458. return Status;
  1459. }
  1460. NTSTATUS NtStatus;
  1461. HANDLE Process;
  1462. OBJECT_ATTRIBUTES ObjAttr;
  1463. CLIENT_ID ClientId;
  1464. ClientId.UniqueThread = NULL;
  1465. ClientId.UniqueProcess = (HANDLE)(ULONG_PTR)ProcessId;
  1466. InitializeObjectAttributes(&ObjAttr, NULL, 0, NULL, NULL);
  1467. NtStatus = g_NtDllCalls.NtOpenProcess(&Process, PROCESS_ALL_ACCESS,
  1468. &ObjAttr, &ClientId);
  1469. if (!NT_SUCCESS(NtStatus))
  1470. {
  1471. Status = HRESULT_FROM_NT(NtStatus);
  1472. goto EH_Exit;
  1473. }
  1474. PROCESS_BASIC_INFORMATION ProcBasic;
  1475. ULONG Done;
  1476. NtStatus = g_NtDllCalls.
  1477. NtQueryInformationProcess(Process, ProcessBasicInformation,
  1478. &ProcBasic, sizeof(ProcBasic), &Done);
  1479. if (!NT_SUCCESS(NtStatus))
  1480. {
  1481. Status = HRESULT_FROM_NT(NtStatus);
  1482. goto EH_Process;
  1483. }
  1484. if (Done != sizeof(ProcBasic))
  1485. {
  1486. Status = E_FAIL;
  1487. goto EH_Process;
  1488. }
  1489. if (ProcBasic.PebBaseAddress == 0)
  1490. {
  1491. // This process has no PEB so fake the description.
  1492. Status = FillStringBufferW(PEBLESS_PROCESS_NAME_W, 0,
  1493. ExeName, ExeNameSize, ActualExeNameSize);
  1494. FillStringBufferW(L"", 0,
  1495. Description, DescriptionSize, ActualDescriptionSize);
  1496. goto EH_Process;
  1497. }
  1498. PEB Peb;
  1499. SIZE_T DoneSize;
  1500. if (!::ReadProcessMemory(Process, ProcBasic.PebBaseAddress,
  1501. &Peb, sizeof(Peb), &DoneSize))
  1502. {
  1503. Status = WIN32_LAST_STATUS();
  1504. goto EH_Process;
  1505. }
  1506. if (DoneSize != sizeof(Peb))
  1507. {
  1508. Status = E_FAIL;
  1509. goto EH_Process;
  1510. }
  1511. RTL_USER_PROCESS_PARAMETERS Params;
  1512. if (!::ReadProcessMemory(Process, Peb.ProcessParameters,
  1513. &Params, sizeof(Params), &DoneSize))
  1514. {
  1515. Status = WIN32_LAST_STATUS();
  1516. goto EH_Process;
  1517. }
  1518. if (DoneSize != sizeof(Params))
  1519. {
  1520. Status = E_FAIL;
  1521. goto EH_Process;
  1522. }
  1523. if (Params.ImagePathName.Buffer != NULL)
  1524. {
  1525. ULONG Len;
  1526. PWSTR ImagePath;
  1527. PWSTR ImageName;
  1528. Len = (Params.ImagePathName.Length + 1) * sizeof(WCHAR);
  1529. ImagePath = (PWSTR)malloc(Len);
  1530. if (ImagePath == NULL)
  1531. {
  1532. Status = E_OUTOFMEMORY;
  1533. goto EH_Process;
  1534. }
  1535. if (!::ReadProcessMemory(Process, Params.ImagePathName.Buffer,
  1536. ImagePath, Len, &DoneSize))
  1537. {
  1538. Status = WIN32_LAST_STATUS();
  1539. free(ImagePath);
  1540. goto EH_Process;
  1541. }
  1542. if (DoneSize < Len)
  1543. {
  1544. Status = E_FAIL;
  1545. free(ImagePath);
  1546. goto EH_Process;
  1547. }
  1548. if (Flags & DEBUG_PROC_DESC_NO_PATHS)
  1549. {
  1550. ImageName = wcsrchr(ImagePath, '\\');
  1551. if (ImageName == NULL)
  1552. {
  1553. ImageName = wcsrchr(ImagePath, '/');
  1554. }
  1555. if (ImageName == NULL)
  1556. {
  1557. ImageName = ImagePath;
  1558. }
  1559. else
  1560. {
  1561. ImageName++;
  1562. }
  1563. }
  1564. else
  1565. {
  1566. ImageName = ImagePath;
  1567. }
  1568. Status = FillStringBufferW(ImageName, 0,
  1569. ExeName, ExeNameSize, ActualExeNameSize);
  1570. free(ImagePath);
  1571. }
  1572. else
  1573. {
  1574. Status = FillStringBufferW(SYSTEM_PROCESS_NAME_W, 0,
  1575. ExeName, ExeNameSize, ActualExeNameSize);
  1576. }
  1577. #ifndef NT_NATIVE
  1578. if ((Description && DescriptionSize) || ActualDescriptionSize)
  1579. {
  1580. BOOL Any = FALSE;
  1581. if (!(Flags & DEBUG_PROC_DESC_NO_SERVICES))
  1582. {
  1583. Status = NtGetProcessServiceNames(Status, ProcessId,
  1584. &Description, &DescriptionSize,
  1585. ActualDescriptionSize, &Any);
  1586. }
  1587. if (!(Flags & DEBUG_PROC_DESC_NO_SERVICES))
  1588. {
  1589. Status = NtGetProcessMtsPackageNames(Status, ProcessId,
  1590. &Description,
  1591. &DescriptionSize,
  1592. ActualDescriptionSize, &Any);
  1593. }
  1594. if (!(Flags & DEBUG_PROC_DESC_NO_COMMAND_LINE))
  1595. {
  1596. Status = NtGetProcessCommandLine(Status, Process,
  1597. &Params.CommandLine,
  1598. &Description,
  1599. &DescriptionSize,
  1600. ActualDescriptionSize, &Any);
  1601. }
  1602. if (!Any)
  1603. {
  1604. if (FillStringBufferW(L"", 0,
  1605. Description, DescriptionSize,
  1606. ActualDescriptionSize) == S_FALSE)
  1607. {
  1608. Status = S_FALSE;
  1609. }
  1610. }
  1611. }
  1612. else
  1613. #endif // #ifndef NT_NATIVE
  1614. {
  1615. FillStringBufferW(L"", 0,
  1616. Description, DescriptionSize, ActualDescriptionSize);
  1617. }
  1618. EH_Process:
  1619. g_NtDllCalls.NtClose(Process);
  1620. EH_Exit:
  1621. return Status;
  1622. #endif // #ifdef _WIN32_WCE
  1623. }
  1624. HRESULT
  1625. ThGetProcDesc(ULONG ProcessId, ULONG Flags,
  1626. PWSTR ExeName, ULONG ExeNameSize, PULONG ActualExeNameSize,
  1627. PWSTR Description, ULONG DescriptionSize,
  1628. PULONG ActualDescriptionSize)
  1629. {
  1630. #ifndef NT_NATIVE
  1631. HRESULT Status;
  1632. HANDLE Snap;
  1633. Snap = g_Kernel32Calls.CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  1634. if (Snap == INVALID_HANDLE_VALUE)
  1635. {
  1636. return WIN32_LAST_STATUS();
  1637. }
  1638. BOOL First = TRUE;
  1639. Status = E_NOINTERFACE;
  1640. for (;;)
  1641. {
  1642. PROCESSENTRY32 Proc;
  1643. BOOL Succ;
  1644. Proc.dwSize = sizeof(Proc);
  1645. if (First)
  1646. {
  1647. Succ = g_Kernel32Calls.Process32First(Snap, &Proc);
  1648. First = FALSE;
  1649. }
  1650. else
  1651. {
  1652. Succ = g_Kernel32Calls.Process32Next(Snap, &Proc);
  1653. }
  1654. if (!Succ)
  1655. {
  1656. break;
  1657. }
  1658. if (Proc.th32ProcessID == ProcessId)
  1659. {
  1660. PSTR AnsiImage = Proc.szExeFile;
  1661. PSTR ImageName;
  1662. WCHAR WideImage[MAX_PATH];
  1663. if (Flags & DEBUG_PROC_DESC_NO_PATHS)
  1664. {
  1665. ImageName = strrchr(AnsiImage, '\\');
  1666. if (ImageName == NULL)
  1667. {
  1668. ImageName = strrchr(AnsiImage, '/');
  1669. }
  1670. if (ImageName == NULL)
  1671. {
  1672. ImageName = AnsiImage;
  1673. }
  1674. else
  1675. {
  1676. ImageName++;
  1677. }
  1678. }
  1679. else
  1680. {
  1681. ImageName = AnsiImage;
  1682. }
  1683. if (!MultiByteToWideChar(CP_ACP, 0, ImageName, -1, WideImage,
  1684. sizeof(WideImage) / sizeof(WCHAR)))
  1685. {
  1686. Status = WIN32_LAST_STATUS();
  1687. }
  1688. else
  1689. {
  1690. Status = FillStringBufferW(WideImage, 0,
  1691. ExeName, ExeNameSize,
  1692. ActualExeNameSize);
  1693. }
  1694. break;
  1695. }
  1696. }
  1697. CloseHandle(Snap);
  1698. // Win9x doesn't have services and we don't have to
  1699. // worry about IIS so there's currently nothing we provide
  1700. // as a description.
  1701. FillStringBufferW(L"", 0,
  1702. Description, DescriptionSize, ActualDescriptionSize);
  1703. return Status;
  1704. #else
  1705. return E_UNEXPECTED;
  1706. #endif
  1707. }
  1708. STDMETHODIMP
  1709. LiveUserDebugServices::GetProcessDescriptionW(
  1710. THIS_
  1711. IN ULONG ProcessId,
  1712. IN ULONG Flags,
  1713. OUT OPTIONAL PWSTR ExeName,
  1714. IN ULONG ExeNameSize,
  1715. OUT OPTIONAL PULONG ActualExeNameSize,
  1716. OUT OPTIONAL PWSTR Description,
  1717. IN ULONG DescriptionSize,
  1718. OUT OPTIONAL PULONG ActualDescriptionSize
  1719. )
  1720. {
  1721. HRESULT Status;
  1722. // Allow privileged access.
  1723. if ((Status = EnableDebugPrivilege()) != S_OK)
  1724. {
  1725. return Status;
  1726. }
  1727. switch(m_PlatformId)
  1728. {
  1729. case VER_PLATFORM_WIN32_NT:
  1730. return NtGetProcDesc(ProcessId, Flags, ExeName, ExeNameSize,
  1731. ActualExeNameSize, Description, DescriptionSize,
  1732. ActualDescriptionSize);
  1733. case VER_PLATFORM_WIN32_WINDOWS:
  1734. case VER_PLATFORM_WIN32_CE:
  1735. return ThGetProcDesc(ProcessId, Flags, ExeName, ExeNameSize,
  1736. ActualExeNameSize,
  1737. Description, DescriptionSize,
  1738. ActualDescriptionSize);
  1739. default:
  1740. return E_UNEXPECTED;
  1741. }
  1742. }
  1743. HRESULT
  1744. InsertUserThread(ULONG Flags, PUSER_THREAD_INFO Threads, ULONG Index,
  1745. HRESULT Status, ULONG ThreadId, HANDLE ThreadHandle,
  1746. PUSER_THREAD_INFO PrevThreads, ULONG PrevInfoCount)
  1747. {
  1748. // Suspend the thread immediately to try and keep the
  1749. // process state as static as we can.
  1750. if (Status == S_OK &&
  1751. !(Flags & DBGSVC_PROC_INFO_NO_SUSPEND) &&
  1752. ::SuspendThread(ThreadHandle) == -1)
  1753. {
  1754. Status = WIN32_LAST_STATUS();
  1755. ::CloseHandle(ThreadHandle);
  1756. }
  1757. if (Status != S_OK)
  1758. {
  1759. while (Index-- > 0)
  1760. {
  1761. if (!(Flags & DBGSVC_PROC_INFO_NO_SUSPEND))
  1762. {
  1763. ::ResumeThread(OS_HANDLE(Threads[Index].Handle));
  1764. }
  1765. ::CloseHandle(OS_HANDLE(Threads[Index].Handle));
  1766. }
  1767. return Status;
  1768. }
  1769. Threads[Index].Handle = SERVICE_HANDLE(ThreadHandle);
  1770. Threads[Index].Id = ThreadId;
  1771. Threads[Index].Reserved = 0;
  1772. //
  1773. // Search for this thread in any previous information.
  1774. //
  1775. if (PrevThreads == NULL)
  1776. {
  1777. return S_OK;
  1778. }
  1779. ULONG i;
  1780. Status = S_FALSE;
  1781. for (i = 0; i < PrevInfoCount; i++)
  1782. {
  1783. if (PrevThreads[i].Id == ThreadId)
  1784. {
  1785. // Found a match.
  1786. Status = S_OK;
  1787. break;
  1788. }
  1789. }
  1790. return Status;
  1791. }
  1792. HRESULT
  1793. NtGetProcThreads(ULONG ProcessId, ULONG Flags, PUSER_THREAD_INFO Threads,
  1794. ULONG InfoCount, PULONG ThreadCount,
  1795. ULONG SysProcInfoSize,
  1796. PUSER_THREAD_INFO PrevThreads, ULONG PrevInfoCount)
  1797. {
  1798. #ifdef _WIN32_WCE
  1799. return E_NOTIMPL;
  1800. #else
  1801. HRESULT Status;
  1802. PSYSTEM_PROCESS_INFORMATION ProcessInfo, ProcInfoBuffer;
  1803. if ((Status = GetNtSystemProcessInformation(&ProcInfoBuffer)) != S_OK)
  1804. {
  1805. return Status;
  1806. }
  1807. ULONG TotalOffset;
  1808. ProcessInfo = ProcInfoBuffer;
  1809. TotalOffset = 0;
  1810. for (;;)
  1811. {
  1812. if (ProcessInfo->UniqueProcessId == (HANDLE)(ULONG_PTR)ProcessId ||
  1813. ProcessInfo->NextEntryOffset == 0)
  1814. {
  1815. break;
  1816. }
  1817. TotalOffset += ProcessInfo->NextEntryOffset;
  1818. ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)
  1819. ((PUCHAR)ProcInfoBuffer + TotalOffset);
  1820. }
  1821. if (ProcessInfo->UniqueProcessId == (HANDLE)(ULONG_PTR)ProcessId)
  1822. {
  1823. // We can't just use ProcessInfo->NumberOfThreads as some
  1824. // of the threads may exit before we record them.
  1825. ULONG NumThreads = 0;
  1826. // If the last iteration returned a different number
  1827. // of threads there's a mismatch so we need to return S_FALSE.
  1828. Status = (PrevThreads != NULL &&
  1829. PrevInfoCount != ProcessInfo->NumberOfThreads) ?
  1830. S_FALSE : S_OK;
  1831. PSYSTEM_THREAD_INFORMATION ThreadInfo = (PSYSTEM_THREAD_INFORMATION)
  1832. ((PUCHAR)ProcessInfo + SysProcInfoSize);
  1833. for (ULONG i = 0; i < ProcessInfo->NumberOfThreads; i++, ThreadInfo++)
  1834. {
  1835. if (NumThreads < InfoCount)
  1836. {
  1837. NTSTATUS NtStatus;
  1838. OBJECT_ATTRIBUTES ObjAttr;
  1839. HANDLE Thread;
  1840. HRESULT SingleStatus;
  1841. InitializeObjectAttributes(&ObjAttr, NULL, 0, NULL, NULL);
  1842. NtStatus = g_NtDllCalls.
  1843. NtOpenThread(&Thread, THREAD_ALL_ACCESS, &ObjAttr,
  1844. &ThreadInfo->ClientId);
  1845. // If the thread exited since the system info was
  1846. // gathered we may not be able to open it. Check
  1847. // for the specific error to distinguish it from
  1848. // resource problems, etc.
  1849. if (NtStatus == STATUS_INVALID_CID)
  1850. {
  1851. // We know the system state has changed so
  1852. // force a refresh.
  1853. Status = S_FALSE;
  1854. continue;
  1855. }
  1856. SingleStatus = InsertUserThread
  1857. (Flags, Threads, NumThreads, CONV_NT_STATUS(NtStatus),
  1858. (ULONG)(ULONG_PTR)ThreadInfo->ClientId.UniqueThread,
  1859. Thread, PrevThreads, PrevInfoCount);
  1860. if (SingleStatus == S_FALSE)
  1861. {
  1862. // Inserted thread didn't match so return S_FALSE.
  1863. Status = S_FALSE;
  1864. }
  1865. else if (SingleStatus != S_OK)
  1866. {
  1867. Status = SingleStatus;
  1868. break;
  1869. }
  1870. }
  1871. NumThreads++;
  1872. }
  1873. if (ThreadCount != NULL)
  1874. {
  1875. *ThreadCount = NumThreads;
  1876. }
  1877. }
  1878. else
  1879. {
  1880. Status = E_NOINTERFACE;
  1881. }
  1882. SIZE_T MemSize = 0;
  1883. g_NtDllCalls.NtFreeVirtualMemory(NtCurrentProcess(),
  1884. (PVOID*)&ProcInfoBuffer, &MemSize,
  1885. MEM_RELEASE);
  1886. return Status;
  1887. #endif // #ifdef _WIN32_WCE
  1888. }
  1889. // These functions are in the minidump library and are
  1890. // not really public functions, but we need them so
  1891. // just extern them here.
  1892. #if defined(_X86_) && !defined(MONO_DBGSRV)
  1893. BOOL WinInitialize(BOOL Win95);
  1894. HANDLE WINAPI WinOpenThread(BOOL Win95, DWORD dwAccess, BOOL bInheritHandle,
  1895. DWORD ThreadId);
  1896. #else
  1897. #define WinInitialize(Win95) (SetLastError(ERROR_CALL_NOT_IMPLEMENTED), FALSE)
  1898. #define WinOpenThread(Win95, dwAccess, bInheritHandle, ThreadId) NULL
  1899. #endif
  1900. HRESULT
  1901. ThGetProcThreads(BOOL Win9x, BOOL Win95,
  1902. ULONG ProcessId, ULONG Flags, PUSER_THREAD_INFO Threads,
  1903. ULONG InfoCount, PULONG ThreadCount,
  1904. PUSER_THREAD_INFO PrevThreads, ULONG PrevInfoCount)
  1905. {
  1906. #ifndef NT_NATIVE
  1907. HRESULT Status;
  1908. HANDLE Snap;
  1909. #ifdef MONO_DBGSRV
  1910. // The monolithic dbgsrv doesn't have the minidump
  1911. // Win9x hack WinOpenThread.
  1912. Win9x = FALSE;
  1913. #endif
  1914. if (Win9x)
  1915. {
  1916. if (!WinInitialize(Win95))
  1917. {
  1918. return WIN32_LAST_STATUS();
  1919. }
  1920. }
  1921. else if (!g_Kernel32Calls.OpenThread)
  1922. {
  1923. return E_NOTIMPL;
  1924. }
  1925. Snap = g_Kernel32Calls.CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD,
  1926. ProcessId);
  1927. if (Snap == INVALID_HANDLE_VALUE)
  1928. {
  1929. return WIN32_LAST_STATUS();
  1930. }
  1931. BOOL First = TRUE;
  1932. ULONG NumThreads = 0;
  1933. Status = S_OK;
  1934. for (;;)
  1935. {
  1936. THREADENTRY32 Thread;
  1937. BOOL Succ;
  1938. Thread.dwSize = sizeof(Thread);
  1939. if (First)
  1940. {
  1941. Succ = g_Kernel32Calls.Thread32First(Snap, &Thread);
  1942. First = FALSE;
  1943. }
  1944. else
  1945. {
  1946. Succ = g_Kernel32Calls.Thread32Next(Snap, &Thread);
  1947. }
  1948. if (!Succ)
  1949. {
  1950. break;
  1951. }
  1952. if (Thread.th32OwnerProcessID == ProcessId)
  1953. {
  1954. if (NumThreads < InfoCount)
  1955. {
  1956. HRESULT SingleStatus;
  1957. HANDLE Handle;
  1958. if (Win9x)
  1959. {
  1960. Handle = WinOpenThread(Win95, THREAD_ALL_ACCESS, FALSE,
  1961. Thread.th32ThreadID);
  1962. }
  1963. else
  1964. {
  1965. #ifdef _WIN32_WCE
  1966. Handle = (HANDLE)Thread.th32ThreadID;
  1967. #else
  1968. Handle = g_Kernel32Calls.OpenThread(THREAD_ALL_ACCESS,
  1969. FALSE,
  1970. Thread.th32ThreadID);
  1971. #endif
  1972. }
  1973. // If the thread exited since the system info was
  1974. // gathered we may not be able to open it. Check
  1975. // for the specific error to distinguish it from
  1976. // resource problems, etc.
  1977. if (!Handle && GetLastError() == ERROR_INVALID_PARAMETER)
  1978. {
  1979. // We know the system state has changed so
  1980. // force a refresh.
  1981. Status = S_FALSE;
  1982. continue;
  1983. }
  1984. SingleStatus = InsertUserThread
  1985. (Flags, Threads, NumThreads,
  1986. CONV_W32_STATUS(Handle != NULL),
  1987. Thread.th32ThreadID, Handle,
  1988. PrevThreads, PrevInfoCount);
  1989. if (SingleStatus == S_FALSE)
  1990. {
  1991. // Inserted thread didn't match so return S_FALSE.
  1992. Status = S_FALSE;
  1993. }
  1994. else if (SingleStatus != S_OK)
  1995. {
  1996. Status = SingleStatus;
  1997. break;
  1998. }
  1999. }
  2000. NumThreads++;
  2001. }
  2002. }
  2003. if (ThreadCount != NULL)
  2004. {
  2005. *ThreadCount = NumThreads;
  2006. }
  2007. if (Status == S_OK)
  2008. {
  2009. // If no threads were found the process must be invalid.
  2010. if (NumThreads == 0)
  2011. {
  2012. Status = E_NOINTERFACE;
  2013. }
  2014. else if (PrevThreads != NULL && NumThreads != PrevInfoCount)
  2015. {
  2016. // Thread count didn't match so return S_FALSE.
  2017. Status = S_FALSE;
  2018. }
  2019. }
  2020. CloseHandle(Snap);
  2021. return Status;
  2022. #else
  2023. return E_UNEXPECTED;
  2024. #endif
  2025. }
  2026. STDMETHODIMP
  2027. LiveUserDebugServices::GetProcessInfo(
  2028. THIS_
  2029. IN ULONG ProcessId,
  2030. IN ULONG Flags,
  2031. OUT OPTIONAL PULONG64 Handle,
  2032. OUT OPTIONAL /* size_is(InfoCount) */ PUSER_THREAD_INFO Threads,
  2033. IN ULONG InfoCount,
  2034. OUT OPTIONAL PULONG ThreadCount
  2035. )
  2036. {
  2037. HANDLE Process;
  2038. HRESULT Status;
  2039. #if DBG_GET_PROC_INFO
  2040. g_NtDllCalls.DbgPrint("GetProcessInfo(%X, %X, %X)\n",
  2041. ProcessId, Flags, InfoCount);
  2042. #endif
  2043. // Enable the privilege that allows the user to debug
  2044. // another process.
  2045. if ((Status = EnableDebugPrivilege()) != S_OK)
  2046. {
  2047. #if DBG_GET_PROC_INFO
  2048. g_NtDllCalls.DbgPrint(" EDP %X\n", Status);
  2049. #endif
  2050. return Status;
  2051. }
  2052. if (Handle != NULL)
  2053. {
  2054. // This should always be a real process ID so there's
  2055. // no need to look for the special CSR value.
  2056. Process = ::OpenProcess(PROCESS_ALL_ACCESS, 0, ProcessId);
  2057. if (Process == NULL)
  2058. {
  2059. #if DBG_GET_PROC_INFO
  2060. g_NtDllCalls.DbgPrint(" OP %X\n", WIN32_LAST_STATUS());
  2061. #endif
  2062. return WIN32_LAST_STATUS();
  2063. }
  2064. *Handle = SERVICE_HANDLE(Process);
  2065. }
  2066. else
  2067. {
  2068. Process = NULL;
  2069. }
  2070. if (Threads != NULL || ThreadCount != NULL)
  2071. {
  2072. PUSER_THREAD_INFO PrevThreads;
  2073. ULONG PrevInfoCount;
  2074. ULONG _ThreadCount;
  2075. //
  2076. // We need to enumerate the threads in the process.
  2077. // This is a difficult thing to get right as
  2078. // the thread state for the process can continuously
  2079. // change. In order to try and get a clean snapshot
  2080. // of the thread state we iteratively enumerate until
  2081. // we get two consecutive snapshots that match.
  2082. //
  2083. // We suspend enumerated threads immediately to
  2084. // reduce churn from inside the process itself.
  2085. // We can't do anything about external processes so
  2086. // the enumeration could still get stale right after
  2087. // we return but by stopping everything in the process
  2088. // itself we do what we can.
  2089. //
  2090. // If the caller is just getting the count and
  2091. // not the actual thread information we don't bother
  2092. // iterating as there's no expectation that the
  2093. // thread state will be the same from one call to
  2094. // the next so there's no need to do the extra work.
  2095. //
  2096. if (Threads != NULL)
  2097. {
  2098. // Allocate an array to hold previous results. This
  2099. // can always be the same size as the return array
  2100. // because if there are more threads than can fit in
  2101. // the return array the snapshot will be wrong anyway
  2102. // so we just return without doing comparisons.
  2103. PrevThreads = new USER_THREAD_INFO[InfoCount];
  2104. if (PrevThreads == NULL)
  2105. {
  2106. Status = E_OUTOFMEMORY;
  2107. goto EH_CloseProc;
  2108. }
  2109. }
  2110. else
  2111. {
  2112. PrevThreads = NULL;
  2113. }
  2114. PrevInfoCount = 0;
  2115. for (;;)
  2116. {
  2117. switch(m_PlatformId)
  2118. {
  2119. case VER_PLATFORM_WIN32_NT:
  2120. Status = NtGetProcThreads(ProcessId, Flags, Threads, InfoCount,
  2121. &_ThreadCount, m_SysProcInfoSize,
  2122. PrevThreads, PrevInfoCount);
  2123. break;
  2124. case VER_PLATFORM_WIN32_WINDOWS:
  2125. case VER_PLATFORM_WIN32_CE:
  2126. Status = ThGetProcThreads
  2127. (m_PlatformId == VER_PLATFORM_WIN32_WINDOWS, m_Win95,
  2128. ProcessId, Flags, Threads,
  2129. InfoCount, &_ThreadCount,
  2130. PrevThreads, PrevInfoCount);
  2131. break;
  2132. default:
  2133. Status = E_UNEXPECTED;
  2134. break;
  2135. }
  2136. #if DBG_GET_PROC_INFO
  2137. g_NtDllCalls.DbgPrint(" loop prev %X, new %X, status %X\n",
  2138. PrevInfoCount, _ThreadCount, Status);
  2139. #endif
  2140. //
  2141. // We can clean up any previous information now.
  2142. //
  2143. ULONG i;
  2144. for (i = 0; i < PrevInfoCount; i++)
  2145. {
  2146. if (!(Flags & DBGSVC_PROC_INFO_NO_SUSPEND))
  2147. {
  2148. ::ResumeThread(OS_HANDLE(PrevThreads[i].Handle));
  2149. }
  2150. ::CloseHandle(OS_HANDLE(PrevThreads[i].Handle));
  2151. }
  2152. if (Status != S_FALSE ||
  2153. _ThreadCount > InfoCount ||
  2154. (Flags & DBGSVC_PROC_INFO_NO_SUSPEND))
  2155. {
  2156. // The snapshot either matched the previous
  2157. // snapshot or there was an error. Also,
  2158. // if the snapshot overflowed the return array
  2159. // quit and give the caller the option of
  2160. // calling again when they notice they didn't
  2161. // get a complete snapshot.
  2162. // We also don't loop if threads aren't being
  2163. // suspended as there's no guarantee the
  2164. // state will remain stable.
  2165. break;
  2166. }
  2167. // There was a snapshot mismatch so loop again
  2168. // with this snapshot as the previous data.
  2169. PrevInfoCount = _ThreadCount;
  2170. if (PrevInfoCount > InfoCount)
  2171. {
  2172. PrevInfoCount = InfoCount;
  2173. }
  2174. RtlCopyMemory(PrevThreads, Threads,
  2175. PrevInfoCount * sizeof(*PrevThreads));
  2176. }
  2177. if (ThreadCount != NULL)
  2178. {
  2179. *ThreadCount = _ThreadCount;
  2180. }
  2181. delete [] PrevThreads;
  2182. EH_CloseProc:
  2183. if (FAILED(Status) && Process != NULL)
  2184. {
  2185. ::CloseHandle(Process);
  2186. }
  2187. }
  2188. else
  2189. {
  2190. Status = S_OK;
  2191. }
  2192. #if DBG_GET_PROC_INFO
  2193. g_NtDllCalls.DbgPrint(" out %X\n", Status);
  2194. #endif
  2195. return Status;
  2196. }
  2197. HRESULT
  2198. ProcessIdToHandle(ULONG ProcessId, PHANDLE Process)
  2199. {
  2200. if (ProcessId == CSRSS_PROCESS_ID)
  2201. {
  2202. if (g_NtDllCalls.CsrGetProcessId != NULL)
  2203. {
  2204. ProcessId = (ULONG)(ULONG_PTR)g_NtDllCalls.CsrGetProcessId();
  2205. }
  2206. else
  2207. {
  2208. *Process = NULL;
  2209. return S_OK;
  2210. }
  2211. }
  2212. *Process = ::OpenProcess(PROCESS_ALL_ACCESS, 0, ProcessId);
  2213. if (*Process == NULL)
  2214. {
  2215. return WIN32_LAST_STATUS();
  2216. }
  2217. return S_OK;
  2218. }
  2219. NTSTATUS
  2220. CreateDebugObject(PHANDLE Object)
  2221. {
  2222. #ifdef _WIN32_WCE
  2223. return E_NOTIMPL;
  2224. #else
  2225. if (*Object != NULL)
  2226. {
  2227. return STATUS_SUCCESS;
  2228. }
  2229. OBJECT_ATTRIBUTES Attr;
  2230. InitializeObjectAttributes(&Attr, NULL, 0, NULL, g_AllAccessSecDesc);
  2231. return g_NtDllCalls.NtCreateDebugObject(Object, DEBUG_ALL_ACCESS,
  2232. &Attr, DEBUG_KILL_ON_CLOSE);
  2233. #endif
  2234. }
  2235. HRESULT
  2236. LiveUserDebugServices::SysGetProcessOptions(HANDLE Process, PULONG Options)
  2237. {
  2238. NTSTATUS NtStatus;
  2239. ULONG Flags;
  2240. if (m_PlatformId == VER_PLATFORM_WIN32_NT)
  2241. {
  2242. NtStatus = g_NtDllCalls.
  2243. NtQueryInformationProcess(Process, ProcessDebugFlags,
  2244. &Flags, sizeof(Flags), NULL);
  2245. }
  2246. else
  2247. {
  2248. NtStatus = STATUS_INVALID_INFO_CLASS;
  2249. }
  2250. if (NtStatus == STATUS_INVALID_INFO_CLASS)
  2251. {
  2252. // The system doesn't support control over the
  2253. // debug flags. In the attach case this means
  2254. // the flags will be DEBUG_ONLY_THIS_PROCESS.
  2255. *Options = DEBUG_PROCESS_ONLY_THIS_PROCESS;
  2256. NtStatus = STATUS_SUCCESS;
  2257. }
  2258. else if (NT_SUCCESS(NtStatus))
  2259. {
  2260. *Options = 0;
  2261. if ((Flags & PROCESS_DEBUG_INHERIT) == 0)
  2262. {
  2263. *Options = DEBUG_PROCESS_ONLY_THIS_PROCESS;
  2264. }
  2265. }
  2266. return CONV_NT_STATUS(NtStatus);
  2267. }
  2268. HRESULT
  2269. LiveUserDebugServices::OpenDebugActiveProcess(ULONG ProcessId,
  2270. HANDLE Process)
  2271. {
  2272. if (m_PlatformId != VER_PLATFORM_WIN32_NT ||
  2273. !m_UseDebugObject)
  2274. {
  2275. return E_NOTIMPL;
  2276. }
  2277. // We're going to open the process's existing debug
  2278. // object and use it so we can't already have a debug object.
  2279. if (Process == NULL || m_DebugObject != NULL)
  2280. {
  2281. return E_UNEXPECTED;
  2282. }
  2283. NTSTATUS NtStatus;
  2284. NtStatus = g_NtDllCalls.
  2285. NtQueryInformationProcess(Process, ProcessDebugObjectHandle,
  2286. &m_DebugObject, sizeof(m_DebugObject), NULL);
  2287. if (!NT_SUCCESS(NtStatus))
  2288. {
  2289. return HRESULT_FROM_NT(NtStatus);
  2290. }
  2291. return S_OK;
  2292. }
  2293. HRESULT
  2294. LiveUserDebugServices::CreateDebugActiveProcess(ULONG ProcessId,
  2295. HANDLE Process,
  2296. ULONG AttachFlags)
  2297. {
  2298. if (m_UseDebugObject)
  2299. {
  2300. if (Process == NULL)
  2301. {
  2302. return E_FAIL;
  2303. }
  2304. if (g_NtDllCalls.NtDebugActiveProcess == NULL)
  2305. {
  2306. return E_NOTIMPL;
  2307. }
  2308. NTSTATUS NtStatus;
  2309. NtStatus = CreateDebugObject(&m_DebugObject);
  2310. if (NT_SUCCESS(NtStatus))
  2311. {
  2312. NtStatus = g_NtDllCalls.NtDebugActiveProcess(Process,
  2313. m_DebugObject);
  2314. if (NT_SUCCESS(NtStatus) &&
  2315. !(AttachFlags & DEBUG_ATTACH_INVASIVE_NO_INITIAL_BREAK))
  2316. {
  2317. g_NtDllCalls.DbgUiIssueRemoteBreakin(Process);
  2318. }
  2319. }
  2320. if (!NT_SUCCESS(NtStatus))
  2321. {
  2322. return HRESULT_FROM_NT(NtStatus);
  2323. }
  2324. }
  2325. #ifndef NT_NATIVE
  2326. else
  2327. {
  2328. if (AttachFlags & DEBUG_ATTACH_INVASIVE_NO_INITIAL_BREAK)
  2329. {
  2330. return E_NOTIMPL;
  2331. }
  2332. if (!::DebugActiveProcess(ProcessId))
  2333. {
  2334. return WIN32_LAST_STATUS();
  2335. }
  2336. }
  2337. #else
  2338. else
  2339. {
  2340. return E_UNEXPECTED;
  2341. }
  2342. #endif
  2343. return S_OK;
  2344. }
  2345. STDMETHODIMP
  2346. LiveUserDebugServices::AttachProcess(
  2347. THIS_
  2348. IN ULONG ProcessId,
  2349. IN ULONG AttachFlags,
  2350. OUT PULONG64 ProcessHandle,
  2351. OUT PULONG ProcessOptions
  2352. )
  2353. {
  2354. HRESULT Status;
  2355. // Enable the privilege that allows the user to debug
  2356. // another process.
  2357. if ((Status = EnableDebugPrivilege()) != S_OK)
  2358. {
  2359. return Status;
  2360. }
  2361. HANDLE Process;
  2362. if (ProcessId == CSRSS_PROCESS_ID)
  2363. {
  2364. CloseProfileUserMapping();
  2365. }
  2366. if ((Status = ProcessIdToHandle(ProcessId, &Process)) != S_OK)
  2367. {
  2368. return Status;
  2369. }
  2370. if ((Status = SysGetProcessOptions(Process, ProcessOptions)) != S_OK)
  2371. {
  2372. if (Process != NULL)
  2373. {
  2374. ::CloseHandle(Process);
  2375. }
  2376. return Status;
  2377. }
  2378. if (AttachFlags & DEBUG_ATTACH_EXISTING)
  2379. {
  2380. Status = OpenDebugActiveProcess(ProcessId, Process);
  2381. }
  2382. else
  2383. {
  2384. Status = CreateDebugActiveProcess(ProcessId, Process, AttachFlags);
  2385. // Attaching always sets the inherit flag to not-inherit
  2386. // as by default an attached process does not debug
  2387. // children.
  2388. *ProcessOptions |= DEBUG_PROCESS_ONLY_THIS_PROCESS;
  2389. }
  2390. if (Status != S_OK)
  2391. {
  2392. if (Process != NULL)
  2393. {
  2394. ::CloseHandle(Process);
  2395. }
  2396. return Status;
  2397. }
  2398. *ProcessHandle = SERVICE_HANDLE(Process);
  2399. return S_OK;
  2400. }
  2401. STDMETHODIMP
  2402. LiveUserDebugServices::DetachProcess(
  2403. THIS_
  2404. IN ULONG ProcessId
  2405. )
  2406. {
  2407. HRESULT Status;
  2408. //
  2409. // A ProcessId of zero means that the caller is just
  2410. // checking for detach support and no actual detach
  2411. // should occur.
  2412. //
  2413. if (m_UseDebugObject)
  2414. {
  2415. if (g_NtDllCalls.NtRemoveProcessDebug == NULL)
  2416. {
  2417. return E_NOTIMPL;
  2418. }
  2419. // Check for the query before checking the debug
  2420. // object as the query may come in early.
  2421. if (ProcessId == 0)
  2422. {
  2423. return S_OK;
  2424. }
  2425. if (m_DebugObject == NULL)
  2426. {
  2427. return E_UNEXPECTED;
  2428. }
  2429. HANDLE Process;
  2430. if ((Status = ProcessIdToHandle(ProcessId, &Process)) != S_OK)
  2431. {
  2432. return Status;
  2433. }
  2434. if (Process == NULL)
  2435. {
  2436. return E_FAIL;
  2437. }
  2438. NTSTATUS NtStatus;
  2439. NtStatus = g_NtDllCalls.
  2440. NtRemoveProcessDebug(Process, m_DebugObject);
  2441. Status = CONV_NT_STATUS(NtStatus);
  2442. ::CloseHandle(Process);
  2443. }
  2444. else
  2445. {
  2446. if (g_Kernel32Calls.DebugActiveProcessStop == NULL)
  2447. {
  2448. return E_NOTIMPL;
  2449. }
  2450. if (ProcessId == 0)
  2451. {
  2452. return S_OK;
  2453. }
  2454. if (!g_Kernel32Calls.DebugActiveProcessStop(ProcessId))
  2455. {
  2456. return WIN32_LAST_STATUS();
  2457. }
  2458. }
  2459. return S_OK;
  2460. }
  2461. NTSTATUS
  2462. NtSimpleCreateProcess(PCWSTR CommandLine,
  2463. ULONG CreateFlags,
  2464. BOOL InheritHandles,
  2465. PCWSTR CurrentDir,
  2466. HANDLE DebugObject,
  2467. LPPROCESS_INFORMATION RetInfo)
  2468. {
  2469. #ifdef _WIN32_WCE
  2470. return E_NOTIMPL;
  2471. #else
  2472. NTSTATUS Status;
  2473. PWSTR RawAppName;
  2474. ULONG AppLen;
  2475. UNICODE_STRING AppName;
  2476. UNICODE_STRING CurDirStr;
  2477. PUNICODE_STRING CurDir;
  2478. UNICODE_STRING CmdLineStr;
  2479. PRTL_USER_PROCESS_PARAMETERS Params;
  2480. RTL_USER_PROCESS_INFORMATION Info;
  2481. if (!g_NtDllCalls.RtlCreateUserProcess)
  2482. {
  2483. return STATUS_NOT_IMPLEMENTED;
  2484. }
  2485. if (!(CreateFlags & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS)))
  2486. {
  2487. DebugObject = NULL;
  2488. }
  2489. else if (CreateFlags & DEBUG_ONLY_THIS_PROCESS)
  2490. {
  2491. // The hacked way of controlling debug inheritance
  2492. // is via the low bit of the debug object handle.
  2493. // If the bit is set it means do not inherit.
  2494. DebugObject = (HANDLE)((ULONG_PTR)DebugObject | 1);
  2495. }
  2496. //
  2497. // This is a simple interface, so assume the first
  2498. // space-delimited token is the executable to run.
  2499. //
  2500. PCWSTR ExeStart, ExeEnd;
  2501. ExeStart = CommandLine;
  2502. while (*ExeStart == L' ' || *ExeStart == L'\t')
  2503. {
  2504. ExeStart++;
  2505. }
  2506. if (*ExeStart == 0)
  2507. {
  2508. return STATUS_INVALID_PARAMETER;
  2509. }
  2510. ExeEnd = ExeStart;
  2511. while (*ExeEnd && !(*ExeEnd == L' ' || *ExeEnd == L'\t'))
  2512. {
  2513. ExeEnd++;
  2514. }
  2515. AppLen = (ULONG)(ExeEnd - ExeStart);
  2516. RawAppName = new WCHAR[AppLen + 1];
  2517. if (!RawAppName)
  2518. {
  2519. return STATUS_NO_MEMORY;
  2520. }
  2521. memcpy(RawAppName, ExeStart, AppLen * sizeof(WCHAR));
  2522. RawAppName[AppLen] = 0;
  2523. Status = g_NtDllCalls.
  2524. RtlDosPathNameToNtPathName_U(RawAppName, &AppName, NULL, NULL);
  2525. delete [] RawAppName;
  2526. if (!NT_SUCCESS(Status))
  2527. {
  2528. return Status;
  2529. }
  2530. if (CurrentDir)
  2531. {
  2532. Status = g_NtDllCalls.
  2533. RtlDosPathNameToNtPathName_U(CurrentDir, &CurDirStr, NULL, NULL);
  2534. if (!NT_SUCCESS(Status))
  2535. {
  2536. goto EH_AppName;
  2537. }
  2538. CurDir = &CurDirStr;
  2539. }
  2540. else
  2541. {
  2542. CurDir = NULL;
  2543. }
  2544. g_NtDllCalls.RtlInitUnicodeString(&CmdLineStr, CommandLine);
  2545. Status = g_NtDllCalls.
  2546. RtlCreateProcessParameters(&Params, &AppName, NULL, CurDir,
  2547. &CmdLineStr, NULL, NULL, NULL,
  2548. NULL, NULL);
  2549. if (!NT_SUCCESS(Status))
  2550. {
  2551. goto EH_CurDir;
  2552. }
  2553. Info.Length = sizeof(Info);
  2554. Status = g_NtDllCalls.
  2555. RtlCreateUserProcess(&AppName, OBJ_CASE_INSENSITIVE,
  2556. Params, NULL, NULL, NULL,
  2557. InheritHandles ? TRUE : FALSE,
  2558. DebugObject, NULL, &Info);
  2559. g_NtDllCalls.RtlDestroyProcessParameters(Params);
  2560. if (NT_SUCCESS(Status))
  2561. {
  2562. RetInfo->dwProcessId = HandleToUlong(Info.ClientId.UniqueProcess);
  2563. RetInfo->dwThreadId = HandleToUlong(Info.ClientId.UniqueThread);
  2564. RetInfo->hProcess = Info.Process;
  2565. RetInfo->hThread = Info.Thread;
  2566. if ((CreateFlags & CREATE_SUSPENDED) == 0)
  2567. {
  2568. g_NtDllCalls.NtResumeThread(Info.Thread, NULL);
  2569. }
  2570. }
  2571. EH_CurDir:
  2572. if (CurDir)
  2573. {
  2574. g_NtDllCalls.RtlFreeUnicodeString(CurDir);
  2575. }
  2576. EH_AppName:
  2577. g_NtDllCalls.RtlFreeUnicodeString(&AppName);
  2578. return Status;
  2579. #endif // #ifdef _WIN32_WCE
  2580. }
  2581. #define DHEAP_ENV "_NO_DEBUG_HEAP"
  2582. STDMETHODIMP
  2583. LiveUserDebugServices::CreateProcessW(
  2584. THIS_
  2585. IN PWSTR CommandLine,
  2586. IN ULONG CreateFlags,
  2587. IN BOOL InheritHandles,
  2588. IN OPTIONAL PWSTR CurrentDir,
  2589. OUT PULONG ProcessId,
  2590. OUT PULONG ThreadId,
  2591. OUT PULONG64 ProcessHandle,
  2592. OUT PULONG64 ThreadHandle
  2593. )
  2594. {
  2595. HRESULT Status;
  2596. // Enable the privilege that allows the user to debug
  2597. // another process.
  2598. if ((Status = EnableDebugPrivilege()) != S_OK)
  2599. {
  2600. return Status;
  2601. }
  2602. // The system looks at the environment variable
  2603. // _NO_DEBUG_HEAP to determine whether the new
  2604. // process should use the debug heap or not. If
  2605. // the caller has requested the normal heap
  2606. // set this environment variable so that it's
  2607. // inherited.
  2608. if (CreateFlags & DEBUG_CREATE_PROCESS_NO_DEBUG_HEAP)
  2609. {
  2610. #ifndef _WIN32_WCE
  2611. ::SetEnvironmentVariable(DHEAP_ENV, "1");
  2612. #endif
  2613. // Turn off this flag since it's not meaningful
  2614. // to CreateProcess itself.
  2615. CreateFlags &= ~DEBUG_CREATE_PROCESS_NO_DEBUG_HEAP;
  2616. }
  2617. PROCESS_INFORMATION ProcInfo;
  2618. #ifndef NT_NATIVE
  2619. HANDLE OldDebugObject;
  2620. BOOL SetOldDebugObject = FALSE;
  2621. Status = S_OK;
  2622. if ((CreateFlags & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS)) &&
  2623. m_UseDebugObject)
  2624. {
  2625. //
  2626. // Set up this thread's debug object to the one that
  2627. // we're using so that our debug object is used when
  2628. // debugging the new process. This lets us continue
  2629. // to use the normal Win32 CreateProcess call rather
  2630. // than trying to go through NtCreateProcessEx and
  2631. // guarantees we get all the Win32 process creation logic.
  2632. //
  2633. if (g_NtDllCalls.DbgUiSetThreadDebugObject == NULL)
  2634. {
  2635. Status = E_NOTIMPL;
  2636. }
  2637. else
  2638. {
  2639. NTSTATUS NtStatus;
  2640. OldDebugObject = g_NtDllCalls.DbgUiGetThreadDebugObject();
  2641. NtStatus = CreateDebugObject(&m_DebugObject);
  2642. if (NT_SUCCESS(NtStatus))
  2643. {
  2644. g_NtDllCalls.DbgUiSetThreadDebugObject(m_DebugObject);
  2645. SetOldDebugObject = TRUE;
  2646. }
  2647. else
  2648. {
  2649. Status = HRESULT_FROM_NT(NtStatus);
  2650. }
  2651. }
  2652. }
  2653. if (Status == S_OK)
  2654. {
  2655. if (CreateFlags & DEBUG_CREATE_PROCESS_THROUGH_RTL)
  2656. {
  2657. if (!m_UseDebugObject)
  2658. {
  2659. Status = E_UNEXPECTED;
  2660. }
  2661. else
  2662. {
  2663. NTSTATUS NtStatus;
  2664. // The RTL create flag is an overloading of an existing
  2665. // flag, so clear it before the actual create to
  2666. // avoid unwanted behavior.
  2667. CreateFlags &= ~DEBUG_CREATE_PROCESS_THROUGH_RTL;
  2668. NtStatus = NtSimpleCreateProcess(CommandLine,
  2669. CreateFlags,
  2670. InheritHandles,
  2671. CurrentDir,
  2672. m_DebugObject,
  2673. &ProcInfo);
  2674. Status = CONV_NT_STATUS(NtStatus);
  2675. }
  2676. }
  2677. else
  2678. {
  2679. Status = S_OK;
  2680. switch(m_PlatformId)
  2681. {
  2682. case VER_PLATFORM_WIN32_NT:
  2683. #ifdef _WIN32_WCE
  2684. Status = E_NOTIMPL;
  2685. #else
  2686. {
  2687. STARTUPINFOW StartupInfoW;
  2688. ZeroMemory(&StartupInfoW, sizeof(StartupInfoW));
  2689. StartupInfoW.cb = sizeof(StartupInfoW);
  2690. if (!::CreateProcessW(NULL, CommandLine, NULL, NULL,
  2691. InheritHandles, CreateFlags,
  2692. NULL, CurrentDir,
  2693. &StartupInfoW, &ProcInfo))
  2694. {
  2695. Status = WIN32_LAST_STATUS();
  2696. }
  2697. }
  2698. #endif
  2699. break;
  2700. case VER_PLATFORM_WIN32_WINDOWS:
  2701. case VER_PLATFORM_WIN32_CE:
  2702. {
  2703. STARTUPINFOA StartupInfoA;
  2704. PSTR CmdLineA, CurDirA;
  2705. ZeroMemory(&StartupInfoA, sizeof(StartupInfoA));
  2706. StartupInfoA.cb = sizeof(StartupInfoA);
  2707. if ((Status = WideToAnsi(CommandLine, &CmdLineA)) != S_OK)
  2708. {
  2709. break;
  2710. }
  2711. if (CurrentDir)
  2712. {
  2713. if ((Status = WideToAnsi(CurrentDir,
  2714. &CurDirA)) != S_OK)
  2715. {
  2716. FreeAnsi(CmdLineA);
  2717. break;
  2718. }
  2719. }
  2720. else
  2721. {
  2722. CurDirA = NULL;
  2723. }
  2724. if (!::CreateProcessA(NULL, CmdLineA, NULL, NULL,
  2725. InheritHandles, CreateFlags,
  2726. NULL, CurDirA,
  2727. &StartupInfoA, &ProcInfo))
  2728. {
  2729. Status = WIN32_LAST_STATUS();
  2730. }
  2731. FreeAnsi(CmdLineA);
  2732. if (CurDirA)
  2733. {
  2734. FreeAnsi(CurDirA);
  2735. }
  2736. }
  2737. break;
  2738. default:
  2739. Status = E_NOTIMPL;
  2740. break;
  2741. }
  2742. }
  2743. }
  2744. if (SetOldDebugObject)
  2745. {
  2746. g_NtDllCalls.DbgUiSetThreadDebugObject(OldDebugObject);
  2747. }
  2748. #else // #ifndef NT_NATIVE
  2749. if (!m_UseDebugObject)
  2750. {
  2751. Status = E_UNEXPECTED;
  2752. }
  2753. else
  2754. {
  2755. NTSTATUS NtStatus;
  2756. if (CreateFlags & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS))
  2757. {
  2758. NtStatus = CreateDebugObject(&m_DebugObject);
  2759. }
  2760. else
  2761. {
  2762. NtStatus = STATUS_SUCCESS;
  2763. }
  2764. if (NT_SUCCESS(NtStatus))
  2765. {
  2766. NtStatus = NtSimpleCreateProcess(CommandLine,
  2767. CreateFlags,
  2768. InheritHandles,
  2769. CurrentDir,
  2770. m_DebugObject,
  2771. &ProcInfo);
  2772. }
  2773. Status = CONV_NT_STATUS(NtStatus);
  2774. }
  2775. #endif // #ifndef NT_NATIVE
  2776. // Clear the special debug heap variable so it
  2777. // isn't inadvertently used somewhere else.
  2778. #ifndef _WIN32_WCE
  2779. ::SetEnvironmentVariable(DHEAP_ENV, NULL);
  2780. #endif
  2781. if (Status == S_OK)
  2782. {
  2783. *ProcessId = ProcInfo.dwProcessId;
  2784. *ThreadId = ProcInfo.dwThreadId;
  2785. *ProcessHandle = SERVICE_HANDLE(ProcInfo.hProcess);
  2786. *ThreadHandle = SERVICE_HANDLE(ProcInfo.hThread);
  2787. }
  2788. return Status;
  2789. }
  2790. STDMETHODIMP
  2791. LiveUserDebugServices::TerminateProcess(
  2792. THIS_
  2793. IN ULONG64 Process,
  2794. IN ULONG ExitCode
  2795. )
  2796. {
  2797. if (!::TerminateProcess(OS_HANDLE(Process), ExitCode))
  2798. {
  2799. return WIN32_LAST_STATUS();
  2800. }
  2801. return S_OK;
  2802. }
  2803. STDMETHODIMP
  2804. LiveUserDebugServices::AbandonProcess(
  2805. THIS_
  2806. IN ULONG64 Process
  2807. )
  2808. {
  2809. //
  2810. // In order to abandon a process but still leave it
  2811. // as being debugged we need to get the process's
  2812. // debug object and duplicate it into the debuggee
  2813. // process. This gives the debuggee process itself
  2814. // a reference to its debug object, creating a circle
  2815. // that will keep the process alive and in the debugged
  2816. // state.
  2817. //
  2818. // This circular reference will also mean that the
  2819. // process must be manually killed. This may be
  2820. // something interesting to address at some point.
  2821. //
  2822. if (m_DebugObject == NULL)
  2823. {
  2824. return E_NOTIMPL;
  2825. }
  2826. #ifdef _WIN32_WCE
  2827. return E_NOTIMPL;
  2828. #else
  2829. HRESULT Status;
  2830. HANDLE Dup;
  2831. if (!::DuplicateHandle(GetCurrentProcess(), m_DebugObject,
  2832. OS_HANDLE(Process), &Dup, 0, FALSE,
  2833. DUPLICATE_SAME_ACCESS))
  2834. {
  2835. return WIN32_LAST_STATUS();
  2836. }
  2837. #endif
  2838. return S_OK;
  2839. }
  2840. STDMETHODIMP
  2841. LiveUserDebugServices::GetProcessExitCode(
  2842. THIS_
  2843. IN ULONG64 Process,
  2844. OUT PULONG ExitCode
  2845. )
  2846. {
  2847. if (!::GetExitCodeProcess(OS_HANDLE(Process), ExitCode))
  2848. {
  2849. return WIN32_LAST_STATUS();
  2850. }
  2851. return *ExitCode == STILL_ACTIVE ? S_FALSE : S_OK;
  2852. }
  2853. STDMETHODIMP
  2854. LiveUserDebugServices::CloseHandle(
  2855. THIS_
  2856. IN ULONG64 Handle
  2857. )
  2858. {
  2859. if (Handle == 0)
  2860. {
  2861. return S_FALSE;
  2862. }
  2863. if (!::CloseHandle(OS_HANDLE(Handle)))
  2864. {
  2865. return WIN32_LAST_STATUS();
  2866. }
  2867. return S_OK;
  2868. }
  2869. STDMETHODIMP
  2870. LiveUserDebugServices::SetProcessOptions(
  2871. THIS_
  2872. IN ULONG64 Process,
  2873. IN ULONG Options
  2874. )
  2875. {
  2876. if (m_PlatformId != VER_PLATFORM_WIN32_NT)
  2877. {
  2878. return E_NOTIMPL;
  2879. }
  2880. NTSTATUS NtStatus;
  2881. ULONG NtFlags = 0;
  2882. if ((Options & DEBUG_PROCESS_ONLY_THIS_PROCESS) == 0)
  2883. {
  2884. NtFlags |= PROCESS_DEBUG_INHERIT;
  2885. }
  2886. NtStatus = g_NtDllCalls.
  2887. NtSetInformationProcess(OS_HANDLE(Process), ProcessDebugFlags,
  2888. &NtFlags, sizeof(NtFlags));
  2889. if (NtStatus == STATUS_INVALID_INFO_CLASS)
  2890. {
  2891. return E_NOTIMPL;
  2892. }
  2893. else
  2894. {
  2895. return CONV_NT_STATUS(NtStatus);
  2896. }
  2897. }
  2898. STDMETHODIMP
  2899. LiveUserDebugServices::SetDebugObjectOptions(
  2900. THIS_
  2901. IN ULONG64 DebugObject,
  2902. IN ULONG Options
  2903. )
  2904. {
  2905. if (DebugObject == 0)
  2906. {
  2907. if (m_DebugObject == NULL)
  2908. {
  2909. if (g_Kernel32Calls.DebugSetProcessKillOnExit == NULL)
  2910. {
  2911. return E_NOTIMPL;
  2912. }
  2913. if (!g_Kernel32Calls.
  2914. DebugSetProcessKillOnExit((Options &
  2915. DEBUG_PROCESS_DETACH_ON_EXIT) == 0))
  2916. {
  2917. return WIN32_LAST_STATUS();
  2918. }
  2919. return S_OK;
  2920. }
  2921. DebugObject = SERVICE_HANDLE(m_DebugObject);
  2922. }
  2923. if (g_NtDllCalls.NtSetInformationDebugObject == NULL)
  2924. {
  2925. return E_NOTIMPL;
  2926. }
  2927. NTSTATUS NtStatus;
  2928. ULONG NtFlags = 0;
  2929. if ((Options & DEBUG_PROCESS_DETACH_ON_EXIT) == 0)
  2930. {
  2931. NtFlags |= DEBUG_KILL_ON_CLOSE;
  2932. }
  2933. NtStatus = g_NtDllCalls.
  2934. NtSetInformationDebugObject(OS_HANDLE(DebugObject), DebugObjectFlags,
  2935. &NtFlags, sizeof(NtFlags), NULL);
  2936. return CONV_NT_STATUS(NtStatus);
  2937. }
  2938. STDMETHODIMP
  2939. LiveUserDebugServices::GetProcessDebugObject(
  2940. THIS_
  2941. IN ULONG64 Process,
  2942. OUT PULONG64 DebugObject
  2943. )
  2944. {
  2945. if (m_PlatformId != VER_PLATFORM_WIN32_NT)
  2946. {
  2947. return E_NOTIMPL;
  2948. }
  2949. NTSTATUS NtStatus;
  2950. HANDLE ObjHandle;
  2951. NtStatus = g_NtDllCalls.
  2952. NtQueryInformationProcess(OS_HANDLE(Process), ProcessDebugObjectHandle,
  2953. &ObjHandle, sizeof(ObjHandle), NULL);
  2954. if (!NT_SUCCESS(NtStatus))
  2955. {
  2956. return HRESULT_FROM_NT(NtStatus);
  2957. }
  2958. *DebugObject = SERVICE_HANDLE(ObjHandle);
  2959. return S_OK;
  2960. }
  2961. STDMETHODIMP
  2962. LiveUserDebugServices::DuplicateHandle(
  2963. THIS_
  2964. IN ULONG64 InProcess,
  2965. IN ULONG64 InHandle,
  2966. IN ULONG64 OutProcess,
  2967. IN ULONG DesiredAccess,
  2968. IN ULONG Inherit,
  2969. IN ULONG Options,
  2970. OUT PULONG64 OutHandle
  2971. )
  2972. {
  2973. #ifdef _WIN32_WCE
  2974. return E_NOTIMPL;
  2975. #else
  2976. HANDLE Dup;
  2977. if (!::DuplicateHandle(OS_HANDLE(InProcess), OS_HANDLE(InHandle),
  2978. OS_HANDLE(OutProcess), &Dup,
  2979. DesiredAccess, Inherit, Options))
  2980. {
  2981. return WIN32_LAST_STATUS();
  2982. }
  2983. *OutHandle = SERVICE_HANDLE(Dup);
  2984. return S_OK;
  2985. #endif
  2986. }
  2987. STDMETHODIMP
  2988. LiveUserDebugServices::ReadVirtual(
  2989. THIS_
  2990. IN ULONG64 Process,
  2991. IN ULONG64 Offset,
  2992. OUT PVOID Buffer,
  2993. IN ULONG BufferSize,
  2994. OUT OPTIONAL PULONG BytesRead
  2995. )
  2996. {
  2997. SIZE_T SizeRead;
  2998. if (!::ReadProcessMemory(OS_HANDLE(Process),
  2999. (LPCVOID)(ULONG_PTR)Offset,
  3000. Buffer, BufferSize, &SizeRead))
  3001. {
  3002. return WIN32_LAST_STATUS();
  3003. }
  3004. if (BytesRead != NULL)
  3005. {
  3006. *BytesRead = (ULONG)SizeRead;
  3007. }
  3008. return S_OK;
  3009. }
  3010. STDMETHODIMP
  3011. LiveUserDebugServices::WriteVirtual(
  3012. THIS_
  3013. IN ULONG64 Process,
  3014. IN ULONG64 Offset,
  3015. IN PVOID Buffer,
  3016. IN ULONG BufferSize,
  3017. OUT OPTIONAL PULONG BytesWritten
  3018. )
  3019. {
  3020. SIZE_T SizeWritten;
  3021. if (!::WriteProcessMemory(OS_HANDLE(Process),
  3022. (LPVOID)(ULONG_PTR)Offset,
  3023. Buffer, BufferSize, &SizeWritten))
  3024. {
  3025. return WIN32_LAST_STATUS();
  3026. }
  3027. if (BytesWritten != NULL)
  3028. {
  3029. *BytesWritten = (ULONG)SizeWritten;
  3030. }
  3031. return S_OK;
  3032. }
  3033. STDMETHODIMP
  3034. LiveUserDebugServices::QueryVirtual(
  3035. THIS_
  3036. IN ULONG64 Process,
  3037. IN ULONG64 Offset,
  3038. OUT PVOID Buffer,
  3039. IN ULONG BufferSize,
  3040. OUT OPTIONAL PULONG BufferUsed
  3041. )
  3042. {
  3043. #ifdef _WIN32_WCE
  3044. return E_NOTIMPL;
  3045. #else
  3046. if (BufferSize < sizeof(MEMORY_BASIC_INFORMATION))
  3047. {
  3048. return E_INVALIDARG;
  3049. }
  3050. if (BufferUsed != NULL)
  3051. {
  3052. *BufferUsed = sizeof(MEMORY_BASIC_INFORMATION);
  3053. }
  3054. if (!::VirtualQueryEx(OS_HANDLE(Process),
  3055. (LPCVOID)(ULONG_PTR)Offset,
  3056. (PMEMORY_BASIC_INFORMATION)Buffer,
  3057. sizeof(MEMORY_BASIC_INFORMATION)))
  3058. {
  3059. return WIN32_LAST_STATUS();
  3060. }
  3061. return S_OK;
  3062. #endif // #ifdef _WIN32_WCE
  3063. }
  3064. STDMETHODIMP
  3065. LiveUserDebugServices::ProtectVirtual(
  3066. THIS_
  3067. IN ULONG64 Process,
  3068. IN ULONG64 Offset,
  3069. IN ULONG64 Size,
  3070. IN ULONG NewProtect,
  3071. OUT PULONG OldProtect
  3072. )
  3073. {
  3074. #ifdef _WIN32_WCE
  3075. return E_NOTIMPL;
  3076. #else
  3077. BOOL Status = ::VirtualProtectEx(OS_HANDLE(Process),
  3078. (PVOID)(ULONG_PTR)Offset, (SIZE_T)Size,
  3079. NewProtect, OldProtect);
  3080. return CONV_W32_STATUS(Status);
  3081. #endif // #ifdef _WIN32_WCE
  3082. }
  3083. STDMETHODIMP
  3084. LiveUserDebugServices::AllocVirtual(
  3085. THIS_
  3086. IN ULONG64 Process,
  3087. IN ULONG64 Offset,
  3088. IN ULONG64 Size,
  3089. IN ULONG Type,
  3090. IN ULONG Protect,
  3091. OUT PULONG64 AllocOffset
  3092. )
  3093. {
  3094. #ifdef _WIN32_WCE
  3095. return E_NOTIMPL;
  3096. #else
  3097. PVOID Addr = ::VirtualAllocEx(OS_HANDLE(Process), (PVOID)(ULONG_PTR)Offset,
  3098. (SIZE_T)Size, Type, Protect);
  3099. if (Addr == NULL)
  3100. {
  3101. return WIN32_LAST_STATUS();
  3102. }
  3103. *AllocOffset = (ULONG64)(LONG64)(LONG_PTR)Addr;
  3104. return S_OK;
  3105. #endif // #ifdef _WIN32_WCE
  3106. }
  3107. STDMETHODIMP
  3108. LiveUserDebugServices::FreeVirtual(
  3109. THIS_
  3110. IN ULONG64 Process,
  3111. IN ULONG64 Offset,
  3112. IN ULONG64 Size,
  3113. IN ULONG Type
  3114. )
  3115. {
  3116. #ifdef _WIN32_WCE
  3117. return E_NOTIMPL;
  3118. #else
  3119. BOOL Status = ::VirtualFreeEx(OS_HANDLE(Process), (PVOID)(ULONG_PTR)Offset,
  3120. (SIZE_T)Size, Type);
  3121. return CONV_W32_STATUS(Status);
  3122. #endif // #ifdef _WIN32_WCE
  3123. }
  3124. STDMETHODIMP
  3125. LiveUserDebugServices::ReadHandleData(
  3126. THIS_
  3127. IN ULONG64 Process,
  3128. IN ULONG64 Handle,
  3129. IN ULONG DataType,
  3130. OUT OPTIONAL PVOID Buffer,
  3131. IN ULONG BufferSize,
  3132. OUT OPTIONAL PULONG DataSize
  3133. )
  3134. {
  3135. if (m_PlatformId != VER_PLATFORM_WIN32_NT)
  3136. {
  3137. return E_NOTIMPL;
  3138. }
  3139. #ifdef _WIN32_WCE
  3140. return E_NOTIMPL;
  3141. #else
  3142. HANDLE Dup = NULL;
  3143. if (DataType != DEBUG_HANDLE_DATA_TYPE_HANDLE_COUNT &&
  3144. !::DuplicateHandle(OS_HANDLE(Process), OS_HANDLE(Handle),
  3145. GetCurrentProcess(), &Dup, 0, FALSE,
  3146. DUPLICATE_SAME_ACCESS))
  3147. {
  3148. return WIN32_LAST_STATUS();
  3149. }
  3150. ULONG64 NtBuffer[1024 / sizeof(ULONG64)];
  3151. ULONG Used = 0;
  3152. NTSTATUS NtStatus;
  3153. HRESULT Status = S_OK;
  3154. PUNICODE_STRING RetStr = NULL;
  3155. BOOL WideStr = FALSE;
  3156. switch(DataType)
  3157. {
  3158. case DEBUG_HANDLE_DATA_TYPE_BASIC:
  3159. Used = sizeof(DEBUG_HANDLE_DATA_BASIC);
  3160. if (Buffer == NULL)
  3161. {
  3162. break;
  3163. }
  3164. if (BufferSize < Used)
  3165. {
  3166. Status = E_INVALIDARG;
  3167. break;
  3168. }
  3169. POBJECT_BASIC_INFORMATION NtBasic;
  3170. NtBasic = (POBJECT_BASIC_INFORMATION)NtBuffer;
  3171. NtStatus = g_NtDllCalls.NtQueryObject(Dup, ObjectBasicInformation,
  3172. NtBasic, sizeof(*NtBasic), NULL);
  3173. if (!NT_SUCCESS(NtStatus))
  3174. {
  3175. Status = HRESULT_FROM_NT(NtStatus);
  3176. break;
  3177. }
  3178. PDEBUG_HANDLE_DATA_BASIC Basic;
  3179. Basic = (PDEBUG_HANDLE_DATA_BASIC)Buffer;
  3180. Basic->TypeNameSize = NtBasic->TypeInfoSize / sizeof(WCHAR);
  3181. Basic->ObjectNameSize = NtBasic->NameInfoSize / sizeof(WCHAR);
  3182. Basic->Attributes = NtBasic->Attributes;
  3183. Basic->GrantedAccess = NtBasic->GrantedAccess;
  3184. Basic->HandleCount = NtBasic->HandleCount;
  3185. Basic->PointerCount = NtBasic->PointerCount;
  3186. break;
  3187. case DEBUG_HANDLE_DATA_TYPE_TYPE_NAME_WIDE:
  3188. WideStr = TRUE;
  3189. case DEBUG_HANDLE_DATA_TYPE_TYPE_NAME:
  3190. POBJECT_TYPE_INFORMATION NtType;
  3191. NtType = (POBJECT_TYPE_INFORMATION)NtBuffer;
  3192. NtStatus = g_NtDllCalls.NtQueryObject(Dup, ObjectTypeInformation,
  3193. NtType, sizeof(NtBuffer), NULL);
  3194. if (!NT_SUCCESS(NtStatus))
  3195. {
  3196. Status = HRESULT_FROM_NT(NtStatus);
  3197. break;
  3198. }
  3199. RetStr = &NtType->TypeName;
  3200. break;
  3201. case DEBUG_HANDLE_DATA_TYPE_OBJECT_NAME_WIDE:
  3202. WideStr = TRUE;
  3203. case DEBUG_HANDLE_DATA_TYPE_OBJECT_NAME:
  3204. POBJECT_NAME_INFORMATION NtName;
  3205. NtName = (POBJECT_NAME_INFORMATION)NtBuffer;
  3206. NtStatus = g_NtDllCalls.NtQueryObject(Dup, ObjectNameInformation,
  3207. NtName, sizeof(NtBuffer), NULL);
  3208. if (!NT_SUCCESS(NtStatus))
  3209. {
  3210. Status = HRESULT_FROM_NT(NtStatus);
  3211. break;
  3212. }
  3213. RetStr = &NtName->Name;
  3214. break;
  3215. case DEBUG_HANDLE_DATA_TYPE_HANDLE_COUNT:
  3216. NtStatus = g_NtDllCalls.
  3217. NtQueryInformationProcess(OS_HANDLE(Process), ProcessHandleCount,
  3218. Buffer, BufferSize, &Used);
  3219. if (!NT_SUCCESS(NtStatus))
  3220. {
  3221. Status = HRESULT_FROM_NT(NtStatus);
  3222. }
  3223. break;
  3224. }
  3225. if (RetStr)
  3226. {
  3227. if (!RetStr->Buffer)
  3228. {
  3229. Used = WideStr ? sizeof(WCHAR) : sizeof(CHAR);
  3230. if (Buffer)
  3231. {
  3232. if (BufferSize < Used)
  3233. {
  3234. Status = E_INVALIDARG;
  3235. }
  3236. else if (WideStr)
  3237. {
  3238. *(PWCHAR)Buffer = 0;
  3239. }
  3240. else
  3241. {
  3242. *(PCHAR)Buffer = 0;
  3243. }
  3244. }
  3245. }
  3246. else
  3247. {
  3248. if (WideStr)
  3249. {
  3250. Used = RetStr->Length + sizeof(WCHAR);
  3251. if (Buffer)
  3252. {
  3253. BufferSize &= ~(sizeof(WCHAR) - 1);
  3254. if (BufferSize < sizeof(WCHAR))
  3255. {
  3256. Status = E_INVALIDARG;
  3257. }
  3258. else
  3259. {
  3260. ULONG CopySize = Used - sizeof(WCHAR);
  3261. if (BufferSize < CopySize)
  3262. {
  3263. CopySize = BufferSize;
  3264. }
  3265. memcpy(Buffer, RetStr->Buffer, CopySize);
  3266. // Force termination.
  3267. if (BufferSize < Used)
  3268. {
  3269. *(PWCHAR)((PUCHAR)Buffer +
  3270. (BufferSize - sizeof(WCHAR))) = 0;
  3271. Status = S_FALSE;
  3272. }
  3273. else
  3274. {
  3275. *(PWCHAR)((PUCHAR)Buffer +
  3276. (Used - sizeof(WCHAR))) = 0;
  3277. }
  3278. }
  3279. }
  3280. }
  3281. else
  3282. {
  3283. Used = RetStr->Length / sizeof(WCHAR) + 1;
  3284. if (Buffer)
  3285. {
  3286. if (BufferSize < sizeof(CHAR))
  3287. {
  3288. Status = E_INVALIDARG;
  3289. }
  3290. else
  3291. {
  3292. if (!WideCharToMultiByte(CP_ACP, 0,
  3293. RetStr->Buffer, Used - 1,
  3294. (LPSTR)Buffer, BufferSize,
  3295. NULL, NULL))
  3296. {
  3297. Status = WIN32_LAST_STATUS();
  3298. }
  3299. else
  3300. {
  3301. // Force termination.
  3302. if (BufferSize < Used)
  3303. {
  3304. *((PCHAR)Buffer +
  3305. (BufferSize - sizeof(CHAR))) = 0;
  3306. Status = S_FALSE;
  3307. }
  3308. else
  3309. {
  3310. *((PCHAR)Buffer +
  3311. (Used - sizeof(CHAR))) = 0;
  3312. }
  3313. }
  3314. }
  3315. }
  3316. }
  3317. }
  3318. }
  3319. if (DataSize != NULL)
  3320. {
  3321. *DataSize = Used;
  3322. }
  3323. if (Dup != NULL)
  3324. {
  3325. ::CloseHandle(Dup);
  3326. }
  3327. return Status;
  3328. #endif // #ifdef _WIN32_WCE
  3329. }
  3330. STDMETHODIMP
  3331. LiveUserDebugServices::SuspendThreads(
  3332. THIS_
  3333. IN ULONG Count,
  3334. IN /* size_is(Count) */ PULONG64 Threads,
  3335. OUT OPTIONAL /* size_is(Count) */ PULONG SuspendCounts
  3336. )
  3337. {
  3338. ULONG i;
  3339. HRESULT Status;
  3340. Status = S_OK;
  3341. for (i = 0; i < Count; i++)
  3342. {
  3343. ULONG OldCount = ::SuspendThread(OS_HANDLE(Threads[i]));
  3344. if (OldCount == -1)
  3345. {
  3346. Status = WIN32_LAST_STATUS();
  3347. }
  3348. if (SuspendCounts != NULL)
  3349. {
  3350. SuspendCounts[i] = OldCount + 1;
  3351. }
  3352. }
  3353. return Status;
  3354. }
  3355. STDMETHODIMP
  3356. LiveUserDebugServices::ResumeThreads(
  3357. THIS_
  3358. IN ULONG Count,
  3359. IN /* size_is(Count) */ PULONG64 Threads,
  3360. OUT OPTIONAL /* size_is(Count) */ PULONG SuspendCounts
  3361. )
  3362. {
  3363. ULONG i;
  3364. HRESULT Status;
  3365. Status = S_OK;
  3366. for (i = 0; i < Count; i++)
  3367. {
  3368. ULONG OldCount = ::ResumeThread(OS_HANDLE(Threads[i]));
  3369. if (OldCount == -1)
  3370. {
  3371. Status = WIN32_LAST_STATUS();
  3372. }
  3373. if (SuspendCounts != NULL)
  3374. {
  3375. SuspendCounts[i] = OldCount - 1;
  3376. }
  3377. }
  3378. return Status;
  3379. }
  3380. STDMETHODIMP
  3381. LiveUserDebugServices::GetThreadStartAddress(
  3382. THIS_
  3383. IN ULONG64 Thread,
  3384. OUT PULONG64 Offset
  3385. )
  3386. {
  3387. if (m_PlatformId != VER_PLATFORM_WIN32_NT)
  3388. {
  3389. // XXX drewb - Equivalent?
  3390. return E_NOTIMPL;
  3391. }
  3392. #ifdef _WIN32_WCE
  3393. return E_NOTIMPL;
  3394. #else
  3395. NTSTATUS NtStatus;
  3396. LONG_PTR StartAddr;
  3397. NtStatus = g_NtDllCalls.
  3398. NtQueryInformationThread(OS_HANDLE(Thread),
  3399. ThreadQuerySetWin32StartAddress,
  3400. &StartAddr,
  3401. sizeof(StartAddr),
  3402. NULL);
  3403. *Offset = (ULONG64)(LONG64)StartAddr;
  3404. return CONV_NT_STATUS(NtStatus);
  3405. #endif // #ifdef _WIN32_WCE
  3406. }
  3407. STDMETHODIMP
  3408. LiveUserDebugServices::GetContext(
  3409. THIS_
  3410. IN ULONG64 Thread,
  3411. IN ULONG Flags,
  3412. IN ULONG FlagsOffset,
  3413. OUT PVOID Context,
  3414. IN ULONG ContextSize,
  3415. OUT OPTIONAL PULONG ContextUsed
  3416. )
  3417. {
  3418. if (ContextSize < m_ContextSize)
  3419. {
  3420. return E_INVALIDARG;
  3421. }
  3422. if (ContextUsed != NULL)
  3423. {
  3424. *ContextUsed = m_ContextSize;
  3425. }
  3426. // Some platforms have alignment requirements for
  3427. // context information, so just get data into a
  3428. // local context structure, which presumably the
  3429. // compiler will properly align, and then copy
  3430. // it into the output buffer.
  3431. #ifndef _X86_
  3432. CONTEXT _LocalContext;
  3433. PCONTEXT LocalContext = &_LocalContext;
  3434. #else
  3435. PCONTEXT LocalContext = (PCONTEXT)Context;
  3436. #endif
  3437. // Initialize context flags here rather than making Context
  3438. // IN OUT to avoid sending a full CONTEXT just for a
  3439. // ULONG's worth of flags.
  3440. *(PULONG)((PUCHAR)LocalContext + FlagsOffset) = Flags;
  3441. if (!::GetThreadContext(OS_HANDLE(Thread), LocalContext))
  3442. {
  3443. return WIN32_LAST_STATUS();
  3444. }
  3445. #ifndef _X86_
  3446. memcpy(Context, LocalContext, m_ContextSize);
  3447. #endif
  3448. return S_OK;
  3449. }
  3450. STDMETHODIMP
  3451. LiveUserDebugServices::SetContext(
  3452. THIS_
  3453. IN ULONG64 Thread,
  3454. IN PVOID Context,
  3455. IN ULONG ContextSize,
  3456. OUT OPTIONAL PULONG ContextUsed
  3457. )
  3458. {
  3459. if (ContextSize < m_ContextSize)
  3460. {
  3461. return E_INVALIDARG;
  3462. }
  3463. if (ContextUsed != NULL)
  3464. {
  3465. *ContextUsed = m_ContextSize;
  3466. }
  3467. // Some platforms have alignment requirements for
  3468. // context information, so just get data into a
  3469. // local context structure, which presumably the
  3470. // compiler will properly align.
  3471. #ifndef _X86_
  3472. CONTEXT _LocalContext;
  3473. PCONTEXT LocalContext = &_LocalContext;
  3474. memcpy(LocalContext, Context, m_ContextSize);
  3475. #else
  3476. PCONTEXT LocalContext = (PCONTEXT)Context;
  3477. #endif
  3478. if (!::SetThreadContext(OS_HANDLE(Thread), LocalContext))
  3479. {
  3480. return WIN32_LAST_STATUS();
  3481. }
  3482. return S_OK;
  3483. }
  3484. STDMETHODIMP
  3485. LiveUserDebugServices::GetProcessDataOffset(
  3486. THIS_
  3487. IN ULONG64 Process,
  3488. OUT PULONG64 Offset
  3489. )
  3490. {
  3491. if (m_PlatformId != VER_PLATFORM_WIN32_NT)
  3492. {
  3493. // XXX drewb - Equivalent?
  3494. return E_NOTIMPL;
  3495. }
  3496. #ifdef _WIN32_WCE
  3497. return E_NOTIMPL;
  3498. #else
  3499. NTSTATUS NtStatus;
  3500. PROCESS_BASIC_INFORMATION ProcessInformation;
  3501. NtStatus = g_NtDllCalls.
  3502. NtQueryInformationProcess(OS_HANDLE(Process),
  3503. ProcessBasicInformation,
  3504. &ProcessInformation,
  3505. sizeof(ProcessInformation),
  3506. NULL);
  3507. *Offset = (ULONG64)(LONG64)(LONG_PTR)ProcessInformation.PebBaseAddress;
  3508. return CONV_NT_STATUS(NtStatus);
  3509. #endif // #ifdef _WIN32_WCE
  3510. }
  3511. HRESULT
  3512. NtGetThreadTeb(HANDLE Thread,
  3513. PULONG64 Offset)
  3514. {
  3515. #ifdef _WIN32_WCE
  3516. return E_NOTIMPL;
  3517. #else
  3518. NTSTATUS NtStatus;
  3519. THREAD_BASIC_INFORMATION ThreadInformation;
  3520. NtStatus = g_NtDllCalls.
  3521. NtQueryInformationThread(Thread,
  3522. ThreadBasicInformation,
  3523. &ThreadInformation,
  3524. sizeof(ThreadInformation),
  3525. NULL);
  3526. *Offset = (ULONG64)(LONG64)(LONG_PTR)ThreadInformation.TebBaseAddress;
  3527. return CONV_NT_STATUS(NtStatus);
  3528. #endif // #ifdef _WIN32_WCE
  3529. }
  3530. HRESULT
  3531. W9xGetThreadTib(HANDLE Thread,
  3532. PULONG64 Offset)
  3533. {
  3534. #if defined(_WIN32_WCE) || !defined(_X86_)
  3535. return E_NOTIMPL;
  3536. #else
  3537. ULONG Addr;
  3538. LDT_ENTRY Ldt;
  3539. CONTEXT Context;
  3540. Context.ContextFlags = CONTEXT_SEGMENTS;
  3541. if (!::GetThreadContext(Thread, &Context) ||
  3542. !::GetThreadSelectorEntry(Thread,
  3543. Context.SegFs,
  3544. &Ldt))
  3545. {
  3546. return WIN32_LAST_STATUS();
  3547. }
  3548. Addr = (Ldt.HighWord.Bytes.BaseHi << 24) |
  3549. (Ldt.HighWord.Bytes.BaseMid << 16) |
  3550. (Ldt.BaseLow);
  3551. *Offset = (ULONG64)(LONG64)(LONG_PTR)Addr;
  3552. return S_OK;
  3553. #endif // #if defined(_WIN32_WCE) || !defined(_X86_)
  3554. }
  3555. STDMETHODIMP
  3556. LiveUserDebugServices::GetThreadDataOffset(
  3557. THIS_
  3558. IN ULONG64 Thread,
  3559. OUT PULONG64 Offset
  3560. )
  3561. {
  3562. switch(m_PlatformId)
  3563. {
  3564. case VER_PLATFORM_WIN32_NT:
  3565. return NtGetThreadTeb(OS_HANDLE(Thread), Offset);
  3566. case VER_PLATFORM_WIN32_WINDOWS:
  3567. return W9xGetThreadTib(OS_HANDLE(Thread), Offset);
  3568. default:
  3569. return E_UNEXPECTED;
  3570. }
  3571. }
  3572. STDMETHODIMP
  3573. LiveUserDebugServices::DescribeSelector(
  3574. THIS_
  3575. IN ULONG64 Thread,
  3576. IN ULONG Selector,
  3577. OUT PVOID Buffer,
  3578. IN ULONG BufferSize,
  3579. OUT OPTIONAL PULONG BufferUsed
  3580. )
  3581. {
  3582. #ifdef _WIN32_WCE
  3583. return E_NOTIMPL;
  3584. #else
  3585. #ifdef _X86_
  3586. if (BufferSize < sizeof(LDT_ENTRY))
  3587. {
  3588. return E_INVALIDARG;
  3589. }
  3590. if (BufferUsed != NULL)
  3591. {
  3592. *BufferUsed = sizeof(LDT_ENTRY);
  3593. }
  3594. #endif
  3595. if (!::GetThreadSelectorEntry(OS_HANDLE(Thread), Selector,
  3596. (LPLDT_ENTRY)Buffer))
  3597. {
  3598. return WIN32_LAST_STATUS();
  3599. }
  3600. return S_OK;
  3601. #endif // #ifdef _WIN32_WCE
  3602. }
  3603. STDMETHODIMP
  3604. LiveUserDebugServices::GetCurrentTimeDateN(
  3605. THIS_
  3606. OUT PULONG64 TimeDate
  3607. )
  3608. {
  3609. if (m_PlatformId == VER_PLATFORM_WIN32_NT)
  3610. {
  3611. LARGE_INTEGER Large;
  3612. Large.LowPart = USER_SHARED_DATA->SystemTime.LowTime;
  3613. Large.HighPart = USER_SHARED_DATA->SystemTime.High1Time;
  3614. *TimeDate = Large.QuadPart;
  3615. }
  3616. else
  3617. {
  3618. *TimeDate = TimeDateStampToFileTime((ULONG)time(NULL));
  3619. }
  3620. return S_OK;
  3621. }
  3622. STDMETHODIMP
  3623. LiveUserDebugServices::GetCurrentSystemUpTimeN(
  3624. THIS_
  3625. OUT PULONG64 UpTime
  3626. )
  3627. {
  3628. if (m_PlatformId == VER_PLATFORM_WIN32_NT)
  3629. {
  3630. LARGE_INTEGER Large;
  3631. Large.LowPart = USER_SHARED_DATA->InterruptTime.LowTime;
  3632. Large.HighPart = USER_SHARED_DATA->InterruptTime.High1Time;
  3633. *UpTime = Large.QuadPart;
  3634. }
  3635. else
  3636. {
  3637. *UpTime = (ULONG64)GetTickCount() * 10000;
  3638. }
  3639. return S_OK;
  3640. }
  3641. STDMETHODIMP
  3642. LiveUserDebugServices::GetProcessUpTimeN(
  3643. THIS_
  3644. IN ULONG64 Process,
  3645. OUT PULONG64 UpTime
  3646. )
  3647. {
  3648. #ifdef _WIN32_WCE
  3649. return E_NOTIMPL;
  3650. #else
  3651. if (m_PlatformId == VER_PLATFORM_WIN32_NT)
  3652. {
  3653. NTSTATUS NtStatus;
  3654. KERNEL_USER_TIMES KernelUserTimes;
  3655. NtStatus = g_NtDllCalls.
  3656. NtQueryInformationProcess(OS_HANDLE(Process),
  3657. ProcessTimes,
  3658. &KernelUserTimes,
  3659. sizeof(KernelUserTimes),
  3660. NULL);
  3661. if (NT_SUCCESS(NtStatus))
  3662. {
  3663. LARGE_INTEGER Large;
  3664. Large.LowPart = USER_SHARED_DATA->SystemTime.LowTime;
  3665. Large.HighPart = USER_SHARED_DATA->SystemTime.High1Time;
  3666. *UpTime = Large.QuadPart - KernelUserTimes.CreateTime.QuadPart;
  3667. }
  3668. return CONV_NT_STATUS(NtStatus);
  3669. }
  3670. else
  3671. {
  3672. return E_NOTIMPL;
  3673. }
  3674. #endif // #ifdef _WIN32_WCE
  3675. }
  3676. STDMETHODIMP
  3677. LiveUserDebugServices::GetProcessTimes(
  3678. THIS_
  3679. IN ULONG64 Process,
  3680. OUT PULONG64 Create,
  3681. OUT PULONG64 Exit,
  3682. OUT PULONG64 Kernel,
  3683. OUT PULONG64 User
  3684. )
  3685. {
  3686. #ifdef _WIN32_WCE
  3687. return E_NOTIMPL;
  3688. #else
  3689. if (m_PlatformId == VER_PLATFORM_WIN32_NT)
  3690. {
  3691. NTSTATUS NtStatus;
  3692. KERNEL_USER_TIMES KernelUserTimes;
  3693. NtStatus = g_NtDllCalls.
  3694. NtQueryInformationProcess(OS_HANDLE(Process),
  3695. ProcessTimes,
  3696. &KernelUserTimes,
  3697. sizeof(KernelUserTimes),
  3698. NULL);
  3699. if (NT_SUCCESS(NtStatus))
  3700. {
  3701. *Create = KernelUserTimes.CreateTime.QuadPart;
  3702. *Exit = KernelUserTimes.ExitTime.QuadPart;
  3703. *Kernel = KernelUserTimes.KernelTime.QuadPart;
  3704. *User = KernelUserTimes.UserTime.QuadPart;
  3705. }
  3706. return CONV_NT_STATUS(NtStatus);
  3707. }
  3708. #ifndef NT_NATIVE
  3709. else
  3710. {
  3711. FILETIME FtCreate, FtExit, FtKernel, FtUser;
  3712. if (!::GetProcessTimes(OS_HANDLE(Process), &FtCreate, &FtExit,
  3713. &FtKernel, &FtUser))
  3714. {
  3715. return WIN32_LAST_STATUS();
  3716. }
  3717. *Create = ((ULONG64)FtCreate.dwHighDateTime << 32) |
  3718. FtCreate.dwLowDateTime;
  3719. *Exit = ((ULONG64)FtExit.dwHighDateTime << 32) |
  3720. FtExit.dwLowDateTime;
  3721. *Kernel = ((ULONG64)FtKernel.dwHighDateTime << 32) |
  3722. FtKernel.dwLowDateTime;
  3723. *User = ((ULONG64)FtUser.dwHighDateTime << 32) |
  3724. FtUser.dwLowDateTime;
  3725. return S_OK;
  3726. }
  3727. #else
  3728. else
  3729. {
  3730. return E_NOTIMPL;
  3731. }
  3732. #endif // #ifndef NT_NATIVE
  3733. #endif // #ifdef _WIN32_WCE
  3734. }
  3735. STDMETHODIMP
  3736. LiveUserDebugServices::GetThreadTimes(
  3737. THIS_
  3738. IN ULONG64 Thread,
  3739. OUT PULONG64 Create,
  3740. OUT PULONG64 Exit,
  3741. OUT PULONG64 Kernel,
  3742. OUT PULONG64 User
  3743. )
  3744. {
  3745. #ifdef NT_NATIVE
  3746. return E_NOTIMPL;
  3747. #else
  3748. FILETIME FtCreate, FtExit, FtKernel, FtUser;
  3749. if (!::GetThreadTimes(OS_HANDLE(Thread),
  3750. &FtCreate, &FtExit, &FtKernel, &FtUser))
  3751. {
  3752. return WIN32_LAST_STATUS();
  3753. }
  3754. *Create =
  3755. ((ULONG64)FtCreate.dwHighDateTime << 32) | FtCreate.dwLowDateTime;
  3756. *Exit =
  3757. ((ULONG64)FtExit.dwHighDateTime << 32) | FtExit.dwLowDateTime;
  3758. *Kernel =
  3759. ((ULONG64)FtKernel.dwHighDateTime << 32) | FtKernel.dwLowDateTime;
  3760. *User =
  3761. ((ULONG64)FtUser.dwHighDateTime << 32) | FtUser.dwLowDateTime;
  3762. return S_OK;
  3763. #endif
  3764. }
  3765. STDMETHODIMP
  3766. LiveUserDebugServices::RequestBreakIn(
  3767. THIS_
  3768. IN ULONG64 Process
  3769. )
  3770. {
  3771. #ifdef _WIN32_WCE
  3772. return E_NOTIMPL;
  3773. #else
  3774. if (g_Kernel32Calls.DebugBreakProcess != NULL)
  3775. {
  3776. if (!g_Kernel32Calls.DebugBreakProcess(OS_HANDLE(Process)))
  3777. {
  3778. return WIN32_LAST_STATUS();
  3779. }
  3780. }
  3781. else if (g_NtDllCalls.DbgUiIssueRemoteBreakin != NULL)
  3782. {
  3783. NTSTATUS Status;
  3784. Status = g_NtDllCalls.DbgUiIssueRemoteBreakin(OS_HANDLE(Process));
  3785. return CONV_NT_STATUS(Status);
  3786. }
  3787. else
  3788. {
  3789. HANDLE Thread;
  3790. DWORD ThreadId;
  3791. LPTHREAD_START_ROUTINE BreakFn;
  3792. #if defined(_WIN64)
  3793. BreakFn = (LPTHREAD_START_ROUTINE)g_NtDllCalls.DbgBreakPoint;
  3794. #else
  3795. BreakFn = (LPTHREAD_START_ROUTINE)g_Kernel32Calls.DebugBreak;
  3796. #endif
  3797. Thread =
  3798. ::CreateRemoteThread(OS_HANDLE(Process), NULL, 0, BreakFn,
  3799. NULL, 0, &ThreadId);
  3800. if (Thread != NULL)
  3801. {
  3802. ::CloseHandle(Thread);
  3803. }
  3804. else
  3805. {
  3806. return WIN32_LAST_STATUS();
  3807. }
  3808. }
  3809. return S_OK;
  3810. #endif // #ifdef _WIN32_WCE
  3811. }
  3812. STDMETHODIMP
  3813. LiveUserDebugServices::WaitForEvent(
  3814. THIS_
  3815. IN ULONG Timeout,
  3816. OUT PVOID Buffer,
  3817. IN ULONG BufferSize,
  3818. OUT OPTIONAL PULONG BufferUsed
  3819. )
  3820. {
  3821. if (BufferSize < sizeof(DEBUG_EVENT))
  3822. {
  3823. return E_INVALIDARG;
  3824. }
  3825. if (BufferUsed != NULL)
  3826. {
  3827. *BufferUsed = sizeof(DEBUG_EVENT);
  3828. }
  3829. LPDEBUG_EVENT Event = (LPDEBUG_EVENT)Buffer;
  3830. HRESULT Status = E_NOTIMPL;
  3831. if (m_DebugObject == NULL)
  3832. {
  3833. #ifndef NT_NATIVE
  3834. if (!::WaitForDebugEvent(Event, Timeout))
  3835. {
  3836. if (GetLastError() == ERROR_SEM_TIMEOUT)
  3837. {
  3838. Status = S_FALSE;
  3839. }
  3840. else
  3841. {
  3842. Status = WIN32_LAST_STATUS();
  3843. }
  3844. }
  3845. else
  3846. {
  3847. Status = S_OK;
  3848. }
  3849. #endif
  3850. }
  3851. else if (g_NtDllCalls.NtWaitForDebugEvent != NULL &&
  3852. g_NtDllCalls.DbgUiConvertStateChangeStructure != NULL)
  3853. {
  3854. NTSTATUS NtStatus;
  3855. LARGE_INTEGER NtTimeout;
  3856. DBGUI_WAIT_STATE_CHANGE StateChange;
  3857. Win32ToNtTimeout(Timeout, &NtTimeout);
  3858. NtStatus = g_NtDllCalls.NtWaitForDebugEvent(m_DebugObject, FALSE,
  3859. &NtTimeout, &StateChange);
  3860. if (NtStatus == STATUS_TIMEOUT)
  3861. {
  3862. Status = S_FALSE;
  3863. }
  3864. else if (!NT_SUCCESS(NtStatus))
  3865. {
  3866. Status = HRESULT_FROM_NT(NtStatus);
  3867. }
  3868. else
  3869. {
  3870. NtStatus = g_NtDllCalls.
  3871. DbgUiConvertStateChangeStructure(&StateChange, Event);
  3872. // If the conversion fails we'll lose an event, but
  3873. // there's nothing else that can be done. Conversion
  3874. // failures will only occur in out-of-resource situations
  3875. // so normal debugging will not be affected.
  3876. Status = CONV_NT_STATUS(NtStatus);
  3877. }
  3878. }
  3879. if (Status != S_OK)
  3880. {
  3881. return Status;
  3882. }
  3883. m_EventProcessId = Event->dwProcessId;
  3884. m_EventThreadId = Event->dwThreadId;
  3885. #ifdef DBG_WAITFOREVENT
  3886. g_NtDllCalls.DbgPrint("Event %d for %X.%X\n",
  3887. Event->dwDebugEventCode, Event->dwProcessId,
  3888. Event->dwThreadId);
  3889. #endif
  3890. // If this is responding to a remote request then
  3891. // we can't return file handles.
  3892. if (m_Remote)
  3893. {
  3894. switch(Event->dwDebugEventCode)
  3895. {
  3896. case CREATE_PROCESS_DEBUG_EVENT:
  3897. ::CloseHandle(Event->u.CreateProcessInfo.hFile);
  3898. Event->u.CreateProcessInfo.hFile = NULL;
  3899. break;
  3900. case LOAD_DLL_DEBUG_EVENT:
  3901. ::CloseHandle(Event->u.LoadDll.hFile);
  3902. Event->u.LoadDll.hFile = NULL;
  3903. break;
  3904. }
  3905. }
  3906. return S_OK;
  3907. }
  3908. STDMETHODIMP
  3909. LiveUserDebugServices::ContinueEvent(
  3910. THIS_
  3911. IN ULONG ContinueStatus
  3912. )
  3913. {
  3914. #ifdef DBG_WAITFOREVENT
  3915. g_NtDllCalls.DbgPrint("Continue event for %X.%X\n",
  3916. m_EventProcessId, m_EventThreadId);
  3917. #endif
  3918. if (m_EventProcessId == 0)
  3919. {
  3920. return E_UNEXPECTED;
  3921. }
  3922. if (m_DebugObject != NULL && g_NtDllCalls.NtDebugContinue != NULL)
  3923. {
  3924. NTSTATUS NtStatus;
  3925. CLIENT_ID ClientId;
  3926. ClientId.UniqueProcess = UlongToHandle(m_EventProcessId);
  3927. ClientId.UniqueThread = UlongToHandle(m_EventThreadId);
  3928. NtStatus = g_NtDllCalls.NtDebugContinue(m_DebugObject, &ClientId,
  3929. ContinueStatus);
  3930. if (!NT_SUCCESS(NtStatus))
  3931. {
  3932. return HRESULT_FROM_NT(NtStatus);
  3933. }
  3934. }
  3935. #ifndef NT_NATIVE
  3936. else if (!::ContinueDebugEvent(m_EventProcessId, m_EventThreadId,
  3937. ContinueStatus))
  3938. {
  3939. return WIN32_LAST_STATUS();
  3940. }
  3941. #else
  3942. else
  3943. {
  3944. return E_UNEXPECTED;
  3945. }
  3946. #endif
  3947. m_EventProcessId = 0;
  3948. return S_OK;
  3949. }
  3950. STDMETHODIMP
  3951. LiveUserDebugServices::InsertCodeBreakpoint(
  3952. THIS_
  3953. IN ULONG64 Process,
  3954. IN ULONG64 Offset,
  3955. IN ULONG MachineType,
  3956. OUT PVOID Storage,
  3957. IN ULONG StorageSize
  3958. )
  3959. {
  3960. // Generic breakpoint support is used so this method
  3961. // does not do anything.
  3962. return E_UNEXPECTED;
  3963. }
  3964. STDMETHODIMP
  3965. LiveUserDebugServices::RemoveCodeBreakpoint(
  3966. THIS_
  3967. IN ULONG64 Process,
  3968. IN ULONG64 Offset,
  3969. IN ULONG MachineType,
  3970. IN PVOID Storage,
  3971. IN ULONG StorageSize
  3972. )
  3973. {
  3974. // Generic breakpoint support is used so this method
  3975. // does not do anything.
  3976. return E_UNEXPECTED;
  3977. }
  3978. STDMETHODIMP
  3979. LiveUserDebugServices::InsertDataBreakpoint(
  3980. THIS_
  3981. IN ULONG64 Process,
  3982. IN ULONG64 Thread,
  3983. IN ULONG64 Offset,
  3984. IN ULONG AccessLength,
  3985. IN ULONG AccessType,
  3986. IN ULONG MachineType
  3987. )
  3988. {
  3989. // Generic breakpoint support is used so this method
  3990. // does not do anything.
  3991. return E_UNEXPECTED;
  3992. }
  3993. STDMETHODIMP
  3994. LiveUserDebugServices::RemoveDataBreakpoint(
  3995. THIS_
  3996. IN ULONG64 Process,
  3997. IN ULONG64 Thread,
  3998. IN ULONG64 Offset,
  3999. IN ULONG AccessLength,
  4000. IN ULONG AccessType,
  4001. IN ULONG MachineType
  4002. )
  4003. {
  4004. // Generic breakpoint support is used so this method
  4005. // does not do anything.
  4006. return E_UNEXPECTED;
  4007. }
  4008. STDMETHODIMP
  4009. LiveUserDebugServices::GetLastDataBreakpointHit(
  4010. THIS_
  4011. IN ULONG64 Process,
  4012. IN ULONG64 Thread,
  4013. OUT PULONG64 Address,
  4014. OUT PULONG AccessType
  4015. )
  4016. {
  4017. // Generic breakpoint support is used so this method
  4018. // does not do anything.
  4019. return E_UNEXPECTED;
  4020. }
  4021. STDMETHODIMP
  4022. LiveUserDebugServices::GetFunctionTableListHead(
  4023. THIS_
  4024. IN ULONG64 Process,
  4025. OUT PULONG64 Offset
  4026. )
  4027. {
  4028. if (!g_NtDllCalls.RtlGetFunctionTableListHead)
  4029. {
  4030. *Offset = 0;
  4031. return E_NOINTERFACE;
  4032. }
  4033. else
  4034. {
  4035. *Offset = (ULONG64)(LONG64)(LONG_PTR)
  4036. g_NtDllCalls.RtlGetFunctionTableListHead();
  4037. return S_OK;
  4038. }
  4039. }
  4040. STDMETHODIMP
  4041. LiveUserDebugServices::GetOutOfProcessFunctionTableW(
  4042. THIS_
  4043. IN ULONG64 Process,
  4044. IN PWSTR Dll,
  4045. IN ULONG64 LoadedDllHandle,
  4046. IN ULONG64 Table,
  4047. IN OPTIONAL PVOID Buffer,
  4048. IN ULONG BufferSize,
  4049. OUT OPTIONAL PULONG TableSize,
  4050. OUT OPTIONAL PULONG64 UsedDllHandle
  4051. )
  4052. {
  4053. #if !defined(NT_NATIVE) && defined(OUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK_EXPORT_NAME)
  4054. HRESULT Status;
  4055. NTSTATUS NtStatus;
  4056. HMODULE DllHandle;
  4057. POUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK Callback;
  4058. ULONG Entries;
  4059. PRUNTIME_FUNCTION Functions;
  4060. if (LoadedDllHandle)
  4061. {
  4062. DllHandle = (HMODULE)(ULONG_PTR)LoadedDllHandle;
  4063. }
  4064. else if ((DllHandle = ::LoadLibraryW(Dll)) == NULL)
  4065. {
  4066. return WIN32_LAST_STATUS();
  4067. }
  4068. Callback = (POUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK)GetProcAddress
  4069. (DllHandle, OUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK_EXPORT_NAME);
  4070. if (!Callback)
  4071. {
  4072. Status = WIN32_LAST_STATUS();
  4073. goto Exit;
  4074. }
  4075. NtStatus = Callback(OS_HANDLE(Process), (PVOID)(ULONG_PTR)Table,
  4076. &Entries, &Functions);
  4077. if (!NT_SUCCESS(NtStatus))
  4078. {
  4079. Status = HRESULT_FROM_NT(NtStatus);
  4080. goto Exit;
  4081. }
  4082. if (Functions == NULL)
  4083. {
  4084. Status = E_NOINTERFACE;
  4085. goto Exit;
  4086. }
  4087. Status = FillDataBuffer(Functions, Entries * sizeof(RUNTIME_FUNCTION),
  4088. Buffer, BufferSize, TableSize);
  4089. // RtlProcessHeap turns into a TEB reference so it doesn't
  4090. // need to (and can't) be a dynamic reference.
  4091. g_NtDllCalls.RtlFreeHeap(RtlProcessHeap(), 0, Functions);
  4092. Exit:
  4093. if (SUCCEEDED(Status) && UsedDllHandle)
  4094. {
  4095. *UsedDllHandle = (LONG_PTR)DllHandle;
  4096. }
  4097. else if (!LoadedDllHandle)
  4098. {
  4099. ::FreeLibrary(DllHandle);
  4100. }
  4101. return Status;
  4102. #else
  4103. return E_UNEXPECTED;
  4104. #endif
  4105. }
  4106. STDMETHODIMP
  4107. LiveUserDebugServices::GetUnloadedModuleListHead(
  4108. THIS_
  4109. IN ULONG64 Process,
  4110. OUT PULONG64 Offset
  4111. )
  4112. {
  4113. if (!g_NtDllCalls.RtlGetUnloadEventTrace)
  4114. {
  4115. *Offset = 0;
  4116. return E_NOINTERFACE;
  4117. }
  4118. else
  4119. {
  4120. *Offset = (ULONG64)(LONG64)(LONG_PTR)
  4121. g_NtDllCalls.RtlGetUnloadEventTrace();
  4122. return S_OK;
  4123. }
  4124. }
  4125. STDMETHODIMP
  4126. LiveUserDebugServices::LoadLibrary(
  4127. THIS_
  4128. IN PWSTR Path,
  4129. OUT PULONG64 Handle
  4130. )
  4131. {
  4132. #ifndef NT_NATIVE
  4133. HMODULE Mod = ::LoadLibraryW(Path);
  4134. if (!Mod)
  4135. {
  4136. return WIN32_LAST_STATUS();
  4137. }
  4138. *Handle = (LONG_PTR)Mod;
  4139. return S_OK;
  4140. #else
  4141. return E_NOTIMPL;
  4142. #endif
  4143. }
  4144. STDMETHODIMP
  4145. LiveUserDebugServices::FreeLibrary(
  4146. THIS_
  4147. IN ULONG64 Handle
  4148. )
  4149. {
  4150. #ifndef NT_NATIVE
  4151. BOOL Succ = ::FreeLibrary((HMODULE)(ULONG_PTR)Handle);
  4152. return CONV_W32_STATUS(Succ);
  4153. #else
  4154. return E_NOTIMPL;
  4155. #endif
  4156. }
  4157. //----------------------------------------------------------------------------
  4158. //
  4159. // Generated RPC proxies and stubs.
  4160. //
  4161. //----------------------------------------------------------------------------
  4162. // Generated headers.
  4163. #include "dbgsvc_p.hpp"
  4164. #include "dbgsvc_s.hpp"
  4165. #include "dbgsvc_p.cpp"
  4166. #include "dbgsvc_s.cpp"