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.

1506 lines
42 KiB

  1. /*++
  2. Copyright(c) 1999-2002 Microsoft Corporation
  3. --*/
  4. #include "pch.cpp"
  5. #include "platform.h"
  6. //----------------------------------------------------------------------------
  7. //
  8. // Win32LiveSystemProvider.
  9. //
  10. //----------------------------------------------------------------------------
  11. Win32LiveSystemProvider::Win32LiveSystemProvider(ULONG PlatformId,
  12. ULONG BuildNumber)
  13. {
  14. m_PlatformId = PlatformId;
  15. m_BuildNumber = BuildNumber;
  16. m_PsApi = NULL;
  17. m_EnumProcessModules = NULL;
  18. m_GetModuleFileNameExW = NULL;
  19. m_Kernel32 = NULL;
  20. m_OpenThread = NULL;
  21. m_Thread32First = NULL;
  22. m_Thread32Next = NULL;
  23. m_Module32First = NULL;
  24. m_Module32Next = NULL;
  25. m_Module32FirstW = NULL;
  26. m_Module32NextW = NULL;
  27. m_CreateToolhelp32Snapshot = NULL;
  28. m_GetLongPathNameA = NULL;
  29. m_GetLongPathNameW = NULL;
  30. m_GetProcessTimes = NULL;
  31. }
  32. Win32LiveSystemProvider::~Win32LiveSystemProvider(void)
  33. {
  34. if (m_PsApi) {
  35. FreeLibrary(m_PsApi);
  36. }
  37. if (m_Kernel32) {
  38. FreeLibrary(m_Kernel32);
  39. }
  40. }
  41. HRESULT
  42. Win32LiveSystemProvider::Initialize(void)
  43. {
  44. m_PsApi = LoadLibrary("psapi.dll");
  45. if (m_PsApi) {
  46. m_EnumProcessModules = (ENUM_PROCESS_MODULES)
  47. GetProcAddress(m_PsApi, "EnumProcessModules");
  48. m_GetModuleFileNameExW = (GET_MODULE_FILE_NAME_EX_W)
  49. GetProcAddress(m_PsApi, "GetModuleFileNameExW");
  50. }
  51. m_Kernel32 = LoadLibrary("kernel32.dll");
  52. if (m_Kernel32) {
  53. m_OpenThread = (OPEN_THREAD)
  54. GetProcAddress(m_Kernel32, "OpenThread");
  55. m_Thread32First = (THREAD32_FIRST)
  56. GetProcAddress(m_Kernel32, "Thread32First");
  57. m_Thread32Next = (THREAD32_NEXT)
  58. GetProcAddress(m_Kernel32, "Thread32Next");
  59. m_Module32First = (MODULE32_FIRST)
  60. GetProcAddress(m_Kernel32, "Module32First");
  61. m_Module32Next = (MODULE32_NEXT)
  62. GetProcAddress(m_Kernel32, "Module32Next");
  63. m_Module32FirstW = (MODULE32_FIRST)
  64. GetProcAddress(m_Kernel32, "Module32FirstW");
  65. m_Module32NextW = (MODULE32_NEXT)
  66. GetProcAddress(m_Kernel32, "Module32NextW");
  67. m_CreateToolhelp32Snapshot = (CREATE_TOOLHELP32_SNAPSHOT)
  68. GetProcAddress(m_Kernel32, "CreateToolhelp32Snapshot");
  69. m_GetLongPathNameA = (GET_LONG_PATH_NAME_A)
  70. GetProcAddress(m_Kernel32, "GetLongPathNameA");
  71. m_GetLongPathNameW = (GET_LONG_PATH_NAME_W)
  72. GetProcAddress(m_Kernel32, "GetLongPathNameW");
  73. m_GetProcessTimes = (GET_PROCESS_TIMES)
  74. GetProcAddress(m_Kernel32, "GetProcessTimes");
  75. }
  76. return S_OK;
  77. }
  78. void
  79. Win32LiveSystemProvider::Release(void)
  80. {
  81. delete this;
  82. }
  83. HRESULT
  84. Win32LiveSystemProvider::GetCurrentTimeDate(OUT PULONG TimeDate)
  85. {
  86. FILETIME FileTime;
  87. GetSystemTimeAsFileTime(&FileTime);
  88. *TimeDate = FileTimeToTimeDate(&FileTime);
  89. return S_OK;
  90. }
  91. HRESULT
  92. Win32LiveSystemProvider::GetCpuType(OUT PULONG Type,
  93. OUT PBOOL BackingStore)
  94. {
  95. SYSTEM_INFO SysInfo;
  96. GetSystemInfo(&SysInfo);
  97. *Type = GenProcArchToImageMachine(SysInfo.wProcessorArchitecture);
  98. if (*Type == IMAGE_FILE_MACHINE_UNKNOWN) {
  99. return E_INVALIDARG;
  100. }
  101. #ifdef DUMP_BACKING_STORE
  102. *BackingStore = TRUE;
  103. #else
  104. *BackingStore = FALSE;
  105. #endif
  106. return S_OK;
  107. }
  108. #if defined(i386)
  109. BOOL
  110. X86CpuId(
  111. IN ULONG32 SubFunction,
  112. OUT PULONG32 EaxRegister, OPTIONAL
  113. OUT PULONG32 EbxRegister, OPTIONAL
  114. OUT PULONG32 EcxRegister, OPTIONAL
  115. OUT PULONG32 EdxRegister OPTIONAL
  116. )
  117. {
  118. BOOL Succ;
  119. ULONG32 _Eax;
  120. ULONG32 _Ebx;
  121. ULONG32 _Ecx;
  122. ULONG32 _Edx;
  123. __try {
  124. __asm {
  125. mov eax, SubFunction
  126. __emit 0x0F
  127. __emit 0xA2 ;; CPUID
  128. mov _Eax, eax
  129. mov _Ebx, ebx
  130. mov _Ecx, ecx
  131. mov _Edx, edx
  132. }
  133. if ( EaxRegister ) {
  134. *EaxRegister = _Eax;
  135. }
  136. if ( EbxRegister ) {
  137. *EbxRegister = _Ebx;
  138. }
  139. if ( EcxRegister ) {
  140. *EcxRegister = _Ecx;
  141. }
  142. if ( EdxRegister ) {
  143. *EdxRegister = _Edx;
  144. }
  145. Succ = TRUE;
  146. }
  147. __except ( EXCEPTION_EXECUTE_HANDLER ) {
  148. Succ = FALSE;
  149. }
  150. return Succ;
  151. }
  152. VOID
  153. GetCpuInformation(
  154. PCPU_INFORMATION Cpu
  155. )
  156. {
  157. BOOL Succ;
  158. //
  159. // Get the VendorID
  160. //
  161. Succ = X86CpuId ( CPUID_VENDOR_ID,
  162. NULL,
  163. &Cpu->X86CpuInfo.VendorId [0],
  164. &Cpu->X86CpuInfo.VendorId [2],
  165. &Cpu->X86CpuInfo.VendorId [1]
  166. );
  167. if ( !Succ ) {
  168. //
  169. // CPUID is not supported on this processor.
  170. //
  171. ZeroMemory (&Cpu->X86CpuInfo, sizeof (Cpu->X86CpuInfo));
  172. }
  173. //
  174. // Get the feature information.
  175. //
  176. Succ = X86CpuId ( CPUID_VERSION_FEATURES,
  177. &Cpu->X86CpuInfo.VersionInformation,
  178. NULL,
  179. NULL,
  180. &Cpu->X86CpuInfo.FeatureInformation
  181. );
  182. if ( !Succ ) {
  183. Cpu->X86CpuInfo.VersionInformation = 0;
  184. Cpu->X86CpuInfo.FeatureInformation = 0;
  185. }
  186. //
  187. // Get the AMD specific information if this is an AMD processor.
  188. //
  189. if ( Cpu->X86CpuInfo.VendorId [0] == AMD_VENDOR_ID_0 &&
  190. Cpu->X86CpuInfo.VendorId [1] == AMD_VENDOR_ID_1 &&
  191. Cpu->X86CpuInfo.VendorId [2] == AMD_VENDOR_ID_2 ) {
  192. Succ = X86CpuId ( CPUID_AMD_EXTENDED_FEATURES,
  193. NULL,
  194. NULL,
  195. NULL,
  196. &Cpu->X86CpuInfo.AMDExtendedCpuFeatures
  197. );
  198. if ( !Succ ) {
  199. Cpu->X86CpuInfo.AMDExtendedCpuFeatures = 0;
  200. }
  201. }
  202. }
  203. #else // #if defined(i386)
  204. VOID
  205. GetCpuInformation(
  206. PCPU_INFORMATION Cpu
  207. )
  208. /*++
  209. Routine Description:
  210. Get CPU information for non-X86 platform using the
  211. IsProcessorFeaturePresent() API call.
  212. Arguments:
  213. Cpu - A buffer where the processor feature information will be copied.
  214. Note: we copy the processor features as a set of bits or'd together.
  215. Also, we only allow for the first 128 processor feature flags.
  216. Return Value:
  217. None.
  218. --*/
  219. {
  220. ULONG i;
  221. DWORD j;
  222. for (i = 0; i < ARRAY_COUNT (Cpu->OtherCpuInfo.ProcessorFeatures); i++) {
  223. Cpu->OtherCpuInfo.ProcessorFeatures[i] = 0;
  224. for (j = 0; j < 64; j++) {
  225. if (IsProcessorFeaturePresent ( j + i * 64 )) {
  226. Cpu->OtherCpuInfo.ProcessorFeatures[i] |= 1 << j;
  227. }
  228. }
  229. }
  230. }
  231. #endif // #if defined(i386)
  232. HRESULT
  233. Win32LiveSystemProvider::GetCpuInfo(OUT PUSHORT Architecture,
  234. OUT PUSHORT Level,
  235. OUT PUSHORT Revision,
  236. OUT PUCHAR NumberOfProcessors,
  237. OUT PCPU_INFORMATION Info)
  238. {
  239. SYSTEM_INFO SysInfo;
  240. GetSystemInfo(&SysInfo);
  241. *Architecture = SysInfo.wProcessorArchitecture;
  242. *Level = SysInfo.wProcessorLevel;
  243. *Revision = SysInfo.wProcessorRevision;
  244. *NumberOfProcessors = (UCHAR)SysInfo.dwNumberOfProcessors;
  245. GetCpuInformation(Info);
  246. return S_OK;
  247. }
  248. void
  249. Win32LiveSystemProvider::GetContextSizes(OUT PULONG Size,
  250. OUT PULONG RegScanOffset,
  251. OUT PULONG RegScanCount)
  252. {
  253. *Size = sizeof(CONTEXT);
  254. #ifdef _X86_
  255. // X86 has two sizes of context.
  256. switch(m_PlatformId) {
  257. case VER_PLATFORM_WIN32_NT:
  258. if (m_BuildNumber < NT_BUILD_WIN2K) {
  259. *Size = FIELD_OFFSET(CONTEXT, ExtendedRegisters);
  260. }
  261. break;
  262. case VER_PLATFORM_WIN32_WINDOWS:
  263. if (m_BuildNumber <= 1998) {
  264. *Size = FIELD_OFFSET(CONTEXT, ExtendedRegisters);
  265. }
  266. break;
  267. default:
  268. *Size = FIELD_OFFSET(CONTEXT, ExtendedRegisters);
  269. break;
  270. }
  271. #endif
  272. // Default reg scan.
  273. *RegScanOffset = -1;
  274. *RegScanCount = -1;
  275. }
  276. void
  277. Win32LiveSystemProvider::GetPointerSize(OUT PULONG Size)
  278. {
  279. *Size = sizeof(PVOID);
  280. }
  281. void
  282. Win32LiveSystemProvider::GetPageSize(OUT PULONG Size)
  283. {
  284. *Size = PAGE_SIZE;
  285. }
  286. void
  287. Win32LiveSystemProvider::GetFunctionTableSizes(OUT PULONG TableSize,
  288. OUT PULONG EntrySize)
  289. {
  290. #if defined(_IA64_) || defined(_AMD64_)
  291. *TableSize = sizeof(DYNAMIC_FUNCTION_TABLE);
  292. *EntrySize = sizeof(RUNTIME_FUNCTION);
  293. #else
  294. *TableSize = 0;
  295. *EntrySize = 0;
  296. #endif
  297. }
  298. void
  299. Win32LiveSystemProvider::GetInstructionWindowSize(OUT PULONG Size)
  300. {
  301. // Default window.
  302. *Size = -1;
  303. }
  304. HRESULT
  305. Win32LiveSystemProvider::GetOsInfo(OUT PULONG PlatformId,
  306. OUT PULONG Major,
  307. OUT PULONG Minor,
  308. OUT PULONG BuildNumber,
  309. OUT PUSHORT ProductType,
  310. OUT PUSHORT SuiteMask)
  311. {
  312. OSVERSIONINFOEXA OsInfo;
  313. // Try first with the EX struct.
  314. OsInfo.dwOSVersionInfoSize = sizeof(OsInfo);
  315. if (!GetVersionExA((LPOSVERSIONINFO)&OsInfo)) {
  316. // EX struct didn't work, try with the basic struct.
  317. ZeroMemory(&OsInfo, sizeof(OsInfo));
  318. OsInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
  319. if (!GetVersionExA((LPOSVERSIONINFO)&OsInfo)) {
  320. return WIN32_LAST_STATUS();
  321. }
  322. }
  323. *PlatformId = OsInfo.dwPlatformId;
  324. *Major = OsInfo.dwMajorVersion;
  325. *Minor = OsInfo.dwMinorVersion;
  326. *BuildNumber = OsInfo.dwBuildNumber;
  327. *ProductType = OsInfo.wProductType;
  328. *SuiteMask = OsInfo.wSuiteMask;
  329. return S_OK;
  330. }
  331. HRESULT
  332. Win32LiveSystemProvider::GetOsCsdString(OUT PWSTR Buffer,
  333. IN ULONG BufferChars)
  334. {
  335. OSVERSIONINFOW OsInfoW;
  336. // Try first with the Unicode struct.
  337. OsInfoW.dwOSVersionInfoSize = sizeof(OsInfoW);
  338. if (GetVersionExW(&OsInfoW)) {
  339. // Got it.
  340. GenStrCopyNW(Buffer, OsInfoW.szCSDVersion, BufferChars);
  341. return S_OK;
  342. }
  343. OSVERSIONINFOA OsInfoA;
  344. // Unicode struct didn't work, try with the ANSI struct.
  345. OsInfoA.dwOSVersionInfoSize = sizeof(OsInfoA);
  346. if (!GetVersionExA(&OsInfoA)) {
  347. return WIN32_LAST_STATUS();
  348. }
  349. if (!MultiByteToWideChar(CP_ACP,
  350. 0,
  351. OsInfoA.szCSDVersion,
  352. -1,
  353. Buffer,
  354. BufferChars)) {
  355. return WIN32_LAST_STATUS();
  356. }
  357. return S_OK;
  358. }
  359. HRESULT
  360. Win32LiveSystemProvider::OpenMapping(IN PCWSTR FilePath,
  361. OUT PULONG Size,
  362. OUT PWSTR LongPath,
  363. IN ULONG LongPathChars,
  364. OUT PVOID* ViewRet)
  365. {
  366. HRESULT Status;
  367. HANDLE File;
  368. HANDLE Mapping;
  369. PVOID View;
  370. DWORD Chars;
  371. //
  372. // The module may be loaded with a short name. Open
  373. // the mapping with the name given, but also determine
  374. // the long name if possible. This is done here as
  375. // the ANSI/Unicode issues are already being handled here.
  376. //
  377. File = CreateFileW(FilePath,
  378. GENERIC_READ,
  379. FILE_SHARE_READ | FILE_SHARE_WRITE,
  380. NULL,
  381. OPEN_EXISTING,
  382. 0,
  383. NULL);
  384. if ( File == NULL || File == INVALID_HANDLE_VALUE ) {
  385. if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {
  386. // We're on an OS that doesn't support Unicode
  387. // file operations. Convert to ANSI and see if
  388. // that helps.
  389. CHAR FilePathA [ MAX_PATH + 10 ];
  390. if (WideCharToMultiByte (CP_ACP,
  391. 0,
  392. FilePath,
  393. -1,
  394. FilePathA,
  395. sizeof (FilePathA),
  396. 0,
  397. 0
  398. ) > 0) {
  399. File = CreateFileA(FilePathA,
  400. GENERIC_READ,
  401. FILE_SHARE_READ | FILE_SHARE_WRITE,
  402. NULL,
  403. OPEN_EXISTING,
  404. 0,
  405. NULL);
  406. if (File != INVALID_HANDLE_VALUE) {
  407. if (!m_GetLongPathNameA) {
  408. Chars = 0;
  409. } else {
  410. Chars = m_GetLongPathNameA(FilePathA, FilePathA,
  411. ARRAY_COUNT(FilePathA));
  412. }
  413. if (Chars == 0 || Chars >= ARRAY_COUNT(FilePathA) ||
  414. MultiByteToWideChar(CP_ACP, 0, FilePathA, -1,
  415. LongPath, LongPathChars) == 0) {
  416. // Couldn't get the long path, just use the
  417. // given path.
  418. GenStrCopyNW(LongPath, FilePath, LongPathChars);
  419. }
  420. }
  421. }
  422. }
  423. if ( File == NULL || File == INVALID_HANDLE_VALUE ) {
  424. return WIN32_LAST_STATUS();
  425. }
  426. } else {
  427. if (!m_GetLongPathNameW) {
  428. Chars = 0;
  429. } else {
  430. Chars = m_GetLongPathNameW(FilePath, LongPath, LongPathChars);
  431. }
  432. if (Chars == 0 || Chars >= LongPathChars) {
  433. // Couldn't get the long path, just use the given path.
  434. GenStrCopyNW(LongPath, FilePath, LongPathChars);
  435. }
  436. }
  437. *Size = GetFileSize(File, NULL);
  438. if (*Size == -1) {
  439. ::CloseHandle( File );
  440. return WIN32_LAST_STATUS();
  441. }
  442. Mapping = CreateFileMapping(File,
  443. NULL,
  444. PAGE_READONLY,
  445. 0,
  446. 0,
  447. NULL);
  448. if (!Mapping) {
  449. ::CloseHandle(File);
  450. return WIN32_LAST_STATUS();
  451. }
  452. View = MapViewOfFile(Mapping,
  453. FILE_MAP_READ,
  454. 0,
  455. 0,
  456. 0);
  457. if (!View) {
  458. Status = WIN32_LAST_STATUS();
  459. } else {
  460. Status = S_OK;
  461. }
  462. ::CloseHandle(Mapping);
  463. ::CloseHandle(File);
  464. *ViewRet = View;
  465. return Status;
  466. }
  467. void
  468. Win32LiveSystemProvider::CloseMapping(PVOID Mapping)
  469. {
  470. UnmapViewOfFile(Mapping);
  471. }
  472. HRESULT
  473. Win32LiveSystemProvider::GetImageHeaderInfo(IN HANDLE Process,
  474. IN PCWSTR FilePath,
  475. IN ULONG64 ImageBase,
  476. OUT PULONG Size,
  477. OUT PULONG CheckSum,
  478. OUT PULONG TimeDateStamp)
  479. {
  480. UCHAR HeaderBuffer[512];
  481. PIMAGE_NT_HEADERS NtHeaders;
  482. IMAGE_NT_HEADERS64 Generic;
  483. SIZE_T Done;
  484. if (!ReadProcessMemory(Process, (PVOID)(ULONG_PTR)ImageBase,
  485. HeaderBuffer, sizeof(HeaderBuffer), &Done)) {
  486. return WIN32_LAST_STATUS();
  487. }
  488. if (Done < sizeof(HeaderBuffer)) {
  489. return HRESULT_FROM_WIN32(ERROR_READ_FAULT);
  490. }
  491. NtHeaders = GenImageNtHeader(HeaderBuffer, &Generic);
  492. if (!NtHeaders) {
  493. return HRESULT_FROM_WIN32(ERROR_INVALID_DLL);
  494. }
  495. *Size = Generic.OptionalHeader.SizeOfImage;
  496. *CheckSum = Generic.OptionalHeader.CheckSum;
  497. *TimeDateStamp = Generic.FileHeader.TimeDateStamp;
  498. return S_OK;
  499. }
  500. HRESULT
  501. Win32LiveSystemProvider::GetImageVersionInfo(IN HANDLE Process,
  502. IN PCWSTR FilePath,
  503. IN ULONG64 ImageBase,
  504. OUT VS_FIXEDFILEINFO* Info)
  505. {
  506. HRESULT Status;
  507. BOOL Succ;
  508. ULONG Unused;
  509. ULONG Size;
  510. UINT VerSize;
  511. PVOID VersionBlock;
  512. PVOID VersionData;
  513. CHAR FilePathA [ MAX_PATH + 10 ];
  514. BOOL UseAnsi = FALSE;
  515. //
  516. // Get the version information.
  517. //
  518. Size = GetFileVersionInfoSizeW (FilePath, &Unused);
  519. if (Size == 0 &&
  520. GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {
  521. // We're on an OS that doesn't support Unicode
  522. // file operations. Convert to ANSI and see if
  523. // that helps.
  524. if (!WideCharToMultiByte(CP_ACP,
  525. 0,
  526. FilePath,
  527. -1,
  528. FilePathA,
  529. sizeof (FilePathA),
  530. 0,
  531. 0
  532. )) {
  533. return WIN32_LAST_STATUS();
  534. }
  535. Size = GetFileVersionInfoSizeA(FilePathA, &Unused);
  536. UseAnsi = TRUE;
  537. }
  538. if (!Size) {
  539. return WIN32_LAST_STATUS();
  540. }
  541. VersionBlock = HeapAlloc(GetProcessHeap(), 0, Size);
  542. if (!VersionBlock) {
  543. return E_OUTOFMEMORY;
  544. }
  545. if (UseAnsi) {
  546. Succ = GetFileVersionInfoA(FilePathA,
  547. 0,
  548. Size,
  549. VersionBlock);
  550. } else {
  551. Succ = GetFileVersionInfoW(FilePath,
  552. 0,
  553. Size,
  554. VersionBlock);
  555. }
  556. if (Succ) {
  557. //
  558. // Get the VS_FIXEDFILEINFO from the image.
  559. //
  560. Succ = VerQueryValue(VersionBlock,
  561. "\\",
  562. &VersionData,
  563. &VerSize);
  564. if ( Succ && (VerSize == sizeof (VS_FIXEDFILEINFO)) ) {
  565. CopyMemory(Info, VersionData, sizeof(*Info));
  566. } else {
  567. Succ = FALSE;
  568. }
  569. }
  570. if (Succ) {
  571. Status = S_OK;
  572. } else {
  573. Status = WIN32_LAST_STATUS();
  574. }
  575. HeapFree(GetProcessHeap(), 0, VersionBlock);
  576. return Status;
  577. }
  578. HRESULT
  579. Win32LiveSystemProvider::GetImageDebugRecord(IN HANDLE Process,
  580. IN PCWSTR FilePath,
  581. IN ULONG64 ImageBase,
  582. IN ULONG RecordType,
  583. OUT OPTIONAL PVOID Data,
  584. IN OUT PULONG DataLen)
  585. {
  586. // We can rely on the default processing.
  587. return E_NOINTERFACE;
  588. }
  589. HRESULT
  590. Win32LiveSystemProvider::EnumImageDataSections(IN HANDLE Process,
  591. IN PCWSTR FilePath,
  592. IN ULONG64 ImageBase,
  593. IN MiniDumpProviderCallbacks*
  594. Callback)
  595. {
  596. // We can rely on the default processing.
  597. return E_NOINTERFACE;
  598. }
  599. HRESULT
  600. Win32LiveSystemProvider::OpenThread(IN ULONG DesiredAccess,
  601. IN BOOL InheritHandle,
  602. IN ULONG ThreadId,
  603. OUT PHANDLE Handle)
  604. {
  605. if (!m_OpenThread) {
  606. return E_NOTIMPL;
  607. }
  608. *Handle = m_OpenThread(DesiredAccess, InheritHandle, ThreadId);
  609. return *Handle ? S_OK : WIN32_LAST_STATUS();
  610. }
  611. void
  612. Win32LiveSystemProvider::CloseThread(IN HANDLE Handle)
  613. {
  614. ::CloseHandle(Handle);
  615. }
  616. ULONG
  617. Win32LiveSystemProvider::GetCurrentThreadId(void)
  618. {
  619. return ::GetCurrentThreadId();
  620. }
  621. ULONG
  622. Win32LiveSystemProvider::SuspendThread(IN HANDLE Thread)
  623. {
  624. return ::SuspendThread(Thread);
  625. }
  626. ULONG
  627. Win32LiveSystemProvider::ResumeThread(IN HANDLE Thread)
  628. {
  629. return ::ResumeThread(Thread);
  630. }
  631. HRESULT
  632. Win32LiveSystemProvider::GetThreadContext(IN HANDLE Thread,
  633. OUT PVOID Context,
  634. IN ULONG ContextSize,
  635. OUT PULONG64 CurrentPc,
  636. OUT PULONG64 CurrentStack,
  637. OUT PULONG64 CurrentStore)
  638. {
  639. CONTEXT StackContext;
  640. BOOL Succ;
  641. if (ContextSize > sizeof(StackContext)) {
  642. return E_INVALIDARG;
  643. }
  644. // Always call GetThreadContext on the CONTEXT structure
  645. // on the stack as CONTEXTs have strict alignment requirements
  646. // and the raw buffer coming in may not obey them.
  647. StackContext.ContextFlags = ALL_REGISTERS;
  648. Succ = ::GetThreadContext(Thread, &StackContext);
  649. if (Succ) {
  650. memcpy(Context, &StackContext, ContextSize);
  651. *CurrentPc = PROGRAM_COUNTER(&StackContext);
  652. *CurrentStack = STACK_POINTER(&StackContext);
  653. #ifdef DUMP_BACKING_STORE
  654. *CurrentStore = BSTORE_POINTER(&StackContext);
  655. #endif
  656. return S_OK;
  657. } else {
  658. return WIN32_LAST_STATUS();
  659. }
  660. }
  661. HRESULT
  662. Win32LiveSystemProvider::GetProcessTimes(IN HANDLE Process,
  663. OUT LPFILETIME Create,
  664. OUT LPFILETIME User,
  665. OUT LPFILETIME Kernel)
  666. {
  667. if (!m_GetProcessTimes) {
  668. return E_NOTIMPL;
  669. }
  670. FILETIME Exit;
  671. if (!m_GetProcessTimes(Process, Create, &Exit, User, Kernel)) {
  672. return WIN32_LAST_STATUS();
  673. }
  674. return S_OK;
  675. }
  676. HRESULT
  677. Win32LiveSystemProvider::ReadVirtual(IN HANDLE Process,
  678. IN ULONG64 Offset,
  679. OUT PVOID Buffer,
  680. IN ULONG Request,
  681. OUT PULONG Done)
  682. {
  683. // ReadProcessMemory will fail if any part of the
  684. // region to read does not have read access. This
  685. // routine attempts to read the largest valid prefix
  686. // so it has to break up reads on page boundaries.
  687. HRESULT Status = S_OK;
  688. SIZE_T TotalBytesRead = 0;
  689. SIZE_T Read;
  690. ULONG ReadSize;
  691. while (Request > 0) {
  692. // Calculate bytes to read and don't let read cross
  693. // a page boundary.
  694. ReadSize = PAGE_SIZE - (ULONG)(Offset & (PAGE_SIZE - 1));
  695. ReadSize = min(Request, ReadSize);
  696. if (!ReadProcessMemory(Process, (PVOID)(ULONG_PTR)Offset,
  697. Buffer, ReadSize, &Read)) {
  698. if (TotalBytesRead == 0) {
  699. // If we haven't read anything indicate failure.
  700. Status = WIN32_LAST_STATUS();
  701. }
  702. break;
  703. }
  704. TotalBytesRead += Read;
  705. Offset += Read;
  706. Buffer = (PVOID)((PUCHAR)Buffer + Read);
  707. Request -= (ULONG)Read;
  708. }
  709. *Done = (ULONG)TotalBytesRead;
  710. return Status;
  711. }
  712. HRESULT
  713. Win32LiveSystemProvider::ReadAllVirtual(IN HANDLE Process,
  714. IN ULONG64 Offset,
  715. OUT PVOID Buffer,
  716. IN ULONG Request)
  717. {
  718. HRESULT Status;
  719. ULONG Done;
  720. if ((Status = ReadVirtual(Process, Offset, Buffer, Request,
  721. &Done)) != S_OK)
  722. {
  723. return Status;
  724. }
  725. if (Done != Request)
  726. {
  727. return HRESULT_FROM_WIN32(ERROR_READ_FAULT);
  728. }
  729. return S_OK;
  730. }
  731. HRESULT
  732. Win32LiveSystemProvider::QueryVirtual(IN HANDLE Process,
  733. IN ULONG64 Offset,
  734. OUT PULONG64 Base,
  735. OUT PULONG64 Size,
  736. OUT PULONG Protect,
  737. OUT PULONG State,
  738. OUT PULONG Type)
  739. {
  740. MEMORY_BASIC_INFORMATION Info;
  741. if (!VirtualQueryEx(Process, (PVOID)(ULONG_PTR)Offset,
  742. &Info, sizeof(Info))) {
  743. return WIN32_LAST_STATUS();
  744. }
  745. *Base = (LONG_PTR)Info.BaseAddress;
  746. *Size = Info.RegionSize;
  747. *Protect = Info.Protect;
  748. *State = Info.State;
  749. *Type = Info.Type;
  750. return S_OK;
  751. }
  752. HRESULT
  753. Win32LiveSystemProvider::StartProcessEnum(IN HANDLE Process,
  754. IN ULONG ProcessId)
  755. {
  756. ULONG SnapFlags;
  757. if (!m_CreateToolhelp32Snapshot) {
  758. return E_NOTIMPL;
  759. }
  760. //
  761. // Toolhelp on older NT builds uses an in-process enumeration
  762. // of modules so don't use it to keep everything out of process.
  763. // On other platforms it's the only option.
  764. //
  765. SnapFlags = TH32CS_SNAPTHREAD;
  766. if (m_PlatformId == VER_PLATFORM_WIN32_NT) {
  767. if (m_BuildNumber >= NT_BUILD_TH_MODULES) {
  768. m_AnsiModules = FALSE;
  769. SnapFlags |= TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32;
  770. }
  771. } else {
  772. m_AnsiModules = TRUE;
  773. SnapFlags |= TH32CS_SNAPMODULE;
  774. }
  775. m_ThSnap = m_CreateToolhelp32Snapshot(SnapFlags, ProcessId);
  776. if (m_ThSnap == INVALID_HANDLE_VALUE) {
  777. return WIN32_LAST_STATUS();
  778. }
  779. m_ProcessHandle = Process;
  780. m_ProcessId = ProcessId;
  781. m_ThreadIndex = 0;
  782. m_ModuleIndex = 0;
  783. return S_OK;
  784. }
  785. HRESULT
  786. Win32LiveSystemProvider::EnumThreads(OUT PULONG ThreadId)
  787. {
  788. HRESULT Status;
  789. THREADENTRY32 ThreadInfo;
  790. ThreadInfo.dwSize = sizeof(ThreadInfo);
  791. if (m_ThreadIndex == 0) {
  792. Status = ProcessThread32First(m_ThSnap, m_ProcessId, &ThreadInfo);
  793. } else {
  794. Status = ProcessThread32Next(m_ThSnap, m_ProcessId, &ThreadInfo);
  795. }
  796. if (Status == S_OK) {
  797. *ThreadId = ThreadInfo.th32ThreadID;
  798. m_ThreadIndex++;
  799. return S_OK;
  800. } else {
  801. return S_FALSE;
  802. }
  803. }
  804. HRESULT
  805. Win32LiveSystemProvider::EnumModules(OUT PULONG64 Base,
  806. OUT PWSTR Path,
  807. IN ULONG PathChars)
  808. {
  809. BOOL Succ;
  810. if (m_AnsiModules) {
  811. if (!m_Module32First || !m_Module32Next) {
  812. return E_NOTIMPL;
  813. }
  814. MODULEENTRY32 ModuleInfo;
  815. ModuleInfo.dwSize = sizeof(ModuleInfo);
  816. if (m_ModuleIndex == 0) {
  817. Succ = m_Module32First(m_ThSnap, &ModuleInfo);
  818. } else {
  819. // Win9x seems to require that this module ID be saved
  820. // between calls so stick it back in to keep Win9x happy.
  821. ModuleInfo.th32ModuleID = m_LastModuleId;
  822. Succ = m_Module32Next(m_ThSnap, &ModuleInfo);
  823. }
  824. if (Succ) {
  825. m_ModuleIndex++;
  826. *Base = (LONG_PTR)ModuleInfo.modBaseAddr;
  827. m_LastModuleId = ModuleInfo.th32ModuleID;
  828. if (!MultiByteToWideChar(CP_ACP,
  829. 0,
  830. ModuleInfo.szExePath,
  831. -1,
  832. Path,
  833. PathChars)) {
  834. return WIN32_LAST_STATUS();
  835. }
  836. return S_OK;
  837. } else {
  838. return S_FALSE;
  839. }
  840. } else {
  841. if (!m_Module32FirstW || !m_Module32NextW) {
  842. return E_NOTIMPL;
  843. }
  844. MODULEENTRY32W ModuleInfo;
  845. ModuleInfo.dwSize = sizeof(ModuleInfo);
  846. if (m_ModuleIndex == 0) {
  847. Succ = m_Module32FirstW(m_ThSnap, &ModuleInfo);
  848. } else {
  849. Succ = m_Module32NextW(m_ThSnap, &ModuleInfo);
  850. }
  851. if (Succ) {
  852. m_ModuleIndex++;
  853. *Base = (LONG_PTR)ModuleInfo.modBaseAddr;
  854. //
  855. // The basic LdrQueryProcessModule API that toolhelp uses
  856. // always returns ANSI strings for module paths. This
  857. // means that even if you use the wide toolhelp calls
  858. // you still lose Unicode information because the original
  859. // Unicode path was converted to ANSI and then back to Unicode.
  860. // To avoid this problem, always try and look up the true
  861. // Unicode path first. This doesn't work for 32-bit modules
  862. // in WOW64, though, so if there's a failure just use the
  863. // incoming string.
  864. //
  865. if (!m_GetModuleFileNameExW ||
  866. !m_GetModuleFileNameExW(m_ProcessHandle,
  867. ModuleInfo.hModule,
  868. Path,
  869. PathChars)) {
  870. GenStrCopyNW(Path, ModuleInfo.szExePath, PathChars);
  871. }
  872. return S_OK;
  873. } else {
  874. return S_FALSE;
  875. }
  876. }
  877. }
  878. HRESULT
  879. Win32LiveSystemProvider::EnumFunctionTables(OUT PULONG64 MinAddress,
  880. OUT PULONG64 MaxAddress,
  881. OUT PULONG64 BaseAddress,
  882. OUT PULONG EntryCount,
  883. OUT PVOID RawTable,
  884. IN ULONG RawTableSize,
  885. OUT PVOID* RawEntryHandle)
  886. {
  887. // Basic Win32 doesn't have function tables.
  888. return S_FALSE;
  889. }
  890. HRESULT
  891. Win32LiveSystemProvider::EnumFunctionTableEntries(IN PVOID RawTable,
  892. IN ULONG RawTableSize,
  893. IN PVOID RawEntryHandle,
  894. OUT PVOID RawEntries,
  895. IN ULONG RawEntriesSize)
  896. {
  897. // Basic Win32 doesn't have function tables.
  898. return E_NOTIMPL;
  899. }
  900. HRESULT
  901. Win32LiveSystemProvider::EnumFunctionTableEntryMemory(IN ULONG64 TableBase,
  902. IN PVOID RawEntries,
  903. IN ULONG Index,
  904. OUT PULONG64 Start,
  905. OUT PULONG Size)
  906. {
  907. // Basic Win32 doesn't have function tables.
  908. return E_NOTIMPL;
  909. }
  910. HRESULT
  911. Win32LiveSystemProvider::EnumUnloadedModules(OUT PWSTR Path,
  912. IN ULONG PathChars,
  913. OUT PULONG64 BaseOfModule,
  914. OUT PULONG SizeOfModule,
  915. OUT PULONG CheckSum,
  916. OUT PULONG TimeDateStamp)
  917. {
  918. // Basic Win32 doesn't have unloaded modules.
  919. return S_FALSE;
  920. }
  921. void
  922. Win32LiveSystemProvider::FinishProcessEnum(void)
  923. {
  924. ::CloseHandle(m_ThSnap);
  925. }
  926. HRESULT
  927. Win32LiveSystemProvider::StartHandleEnum(IN HANDLE Process,
  928. IN ULONG ProcessId,
  929. OUT PULONG Count)
  930. {
  931. // Basic Win32 doesn't have handle data queries.
  932. *Count = 0;
  933. return S_OK;
  934. }
  935. HRESULT
  936. Win32LiveSystemProvider::EnumHandles(OUT PULONG64 Handle,
  937. OUT PULONG Attributes,
  938. OUT PULONG GrantedAccess,
  939. OUT PULONG HandleCount,
  940. OUT PULONG PointerCount,
  941. OUT PWSTR TypeName,
  942. IN ULONG TypeNameChars,
  943. OUT PWSTR ObjectName,
  944. IN ULONG ObjectNameChars)
  945. {
  946. // Basic Win32 doesn't have handle data queries.
  947. return S_FALSE;
  948. }
  949. void
  950. Win32LiveSystemProvider::FinishHandleEnum(void)
  951. {
  952. // Basic Win32 doesn't have handle data queries.
  953. }
  954. HRESULT
  955. Win32LiveSystemProvider::EnumPebMemory(IN HANDLE Process,
  956. IN ULONG64 PebOffset,
  957. IN ULONG PebSize,
  958. IN MiniDumpProviderCallbacks* Callback)
  959. {
  960. // Basic Win32 doesn't have a defined PEB.
  961. return S_OK;
  962. }
  963. HRESULT
  964. Win32LiveSystemProvider::EnumTebMemory(IN HANDLE Process,
  965. IN HANDLE Thread,
  966. IN ULONG64 TebOffset,
  967. IN ULONG TebSize,
  968. IN MiniDumpProviderCallbacks* Callback)
  969. {
  970. // Basic Win32 doesn't have a defined TEB beyond
  971. // the TIB. The TIB can reference fiber data but
  972. // that's NT-specific.
  973. return S_OK;
  974. }
  975. HRESULT
  976. Win32LiveSystemProvider::GetCorDataAccess(IN PWSTR AccessDllName,
  977. IN struct ICorDataAccessServices*
  978. Services,
  979. OUT struct ICorDataAccess**
  980. Access)
  981. {
  982. HRESULT Status;
  983. m_CorDll = ::LoadLibraryW(AccessDllName);
  984. if (!m_CorDll) {
  985. char DllPathA[MAX_PATH];
  986. if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED ||
  987. !WideCharToMultiByte(CP_ACP, 0,
  988. AccessDllName, -1,
  989. DllPathA, sizeof(DllPathA),
  990. 0, 0) ||
  991. !(m_CorDll = ::LoadLibraryA(DllPathA))) {
  992. return WIN32_LAST_STATUS();
  993. }
  994. }
  995. PFN_CreateCorDataAccess Entry = (PFN_CreateCorDataAccess)
  996. GetProcAddress(m_CorDll, "CreateCorDataAccess");
  997. if (!Entry)
  998. {
  999. Status = WIN32_LAST_STATUS();
  1000. FreeLibrary(m_CorDll);
  1001. return Status;
  1002. }
  1003. if ((Status = Entry(__uuidof(ICorDataAccess), Services,
  1004. (void**)Access)) != S_OK)
  1005. {
  1006. FreeLibrary(m_CorDll);
  1007. }
  1008. return Status;
  1009. }
  1010. void
  1011. Win32LiveSystemProvider::ReleaseCorDataAccess(IN struct ICorDataAccess*
  1012. Access)
  1013. {
  1014. Access->Release();
  1015. ::FreeLibrary(m_CorDll);
  1016. }
  1017. HRESULT
  1018. Win32LiveSystemProvider::ProcessThread32Next(IN HANDLE Snapshot,
  1019. IN ULONG ProcessId,
  1020. OUT THREADENTRY32* ThreadInfo)
  1021. {
  1022. BOOL Succ;
  1023. if (!m_Thread32Next) {
  1024. return E_NOTIMPL;
  1025. }
  1026. //
  1027. // NB: Toolhelp says nothing about the order of the threads will be
  1028. // returned in (i.e., if they are grouped by process or not). If they
  1029. // are groupled by process -- which they emperically seem to be -- there
  1030. // is a more efficient algorithm than simple brute force.
  1031. //
  1032. do {
  1033. ThreadInfo->dwSize = sizeof (*ThreadInfo);
  1034. Succ = m_Thread32Next(Snapshot, ThreadInfo);
  1035. } while (Succ && ThreadInfo->th32OwnerProcessID != ProcessId);
  1036. return Succ ? S_OK : WIN32_LAST_STATUS();
  1037. }
  1038. HRESULT
  1039. Win32LiveSystemProvider::ProcessThread32First(IN HANDLE Snapshot,
  1040. IN ULONG ProcessId,
  1041. OUT THREADENTRY32* ThreadInfo)
  1042. {
  1043. HRESULT Status;
  1044. BOOL Succ;
  1045. if (!m_Thread32First) {
  1046. return E_NOTIMPL;
  1047. }
  1048. ThreadInfo->dwSize = sizeof (*ThreadInfo);
  1049. Succ = m_Thread32First(Snapshot, ThreadInfo);
  1050. Status = Succ ? S_OK : WIN32_LAST_STATUS();
  1051. if (Succ && ThreadInfo->th32OwnerProcessID != ProcessId) {
  1052. Status = ProcessThread32Next (Snapshot, ProcessId, ThreadInfo);
  1053. }
  1054. return Status;
  1055. }
  1056. HRESULT
  1057. Win32LiveSystemProvider::TibGetThreadInfo(IN HANDLE Process,
  1058. IN ULONG64 TibBase,
  1059. OUT PULONG64 StackBase,
  1060. OUT PULONG64 StackLimit,
  1061. OUT PULONG64 StoreBase,
  1062. OUT PULONG64 StoreLimit)
  1063. {
  1064. #ifdef _WIN32_WCE
  1065. return E_NOTIMPL;
  1066. #else
  1067. TEB Teb;
  1068. HRESULT Status;
  1069. #if defined (DUMP_BACKING_STORE)
  1070. if ((Status = ReadAllVirtual(Process,
  1071. TibBase,
  1072. &Teb,
  1073. sizeof(Teb))) != S_OK) {
  1074. return Status;
  1075. }
  1076. *StoreBase = BSTORE_BASE(&Teb);
  1077. *StoreLimit = BSTORE_LIMIT(&Teb);
  1078. #else
  1079. if ((Status = ReadAllVirtual(Process,
  1080. TibBase,
  1081. &Teb,
  1082. sizeof(Teb.NtTib))) != S_OK) {
  1083. return Status;
  1084. }
  1085. *StoreBase = 0;
  1086. *StoreLimit = 0;
  1087. #endif
  1088. *StackBase = (LONG_PTR)Teb.NtTib.StackBase;
  1089. *StackLimit = (LONG_PTR)Teb.NtTib.StackLimit;
  1090. return S_OK;
  1091. #endif // #ifdef _WIN32_WCE
  1092. }
  1093. HRESULT
  1094. MiniDumpCreateLiveSystemProvider
  1095. (OUT MiniDumpSystemProvider** Prov)
  1096. {
  1097. HRESULT Status;
  1098. OSVERSIONINFO OsInfo;
  1099. Win32LiveSystemProvider* Obj;
  1100. OsInfo.dwOSVersionInfoSize = sizeof(OsInfo);
  1101. if (!GetVersionEx(&OsInfo)) {
  1102. return WIN32_LAST_STATUS();
  1103. }
  1104. switch(OsInfo.dwPlatformId) {
  1105. case VER_PLATFORM_WIN32_NT:
  1106. Obj = NewNtWin32LiveSystemProvider(OsInfo.dwBuildNumber);
  1107. break;
  1108. case VER_PLATFORM_WIN32_WINDOWS:
  1109. Obj = NewWin9xWin32LiveSystemProvider(OsInfo.dwBuildNumber);
  1110. break;
  1111. case VER_PLATFORM_WIN32_CE:
  1112. Obj = NewWinCeWin32LiveSystemProvider(OsInfo.dwBuildNumber);
  1113. break;
  1114. default:
  1115. return E_INVALIDARG;
  1116. }
  1117. if (!Obj) {
  1118. return E_OUTOFMEMORY;
  1119. }
  1120. if ((Status = Obj->Initialize()) != S_OK) {
  1121. Obj->Release();
  1122. return Status;
  1123. }
  1124. *Prov = (MiniDumpSystemProvider*)Obj;
  1125. return S_OK;
  1126. }
  1127. //----------------------------------------------------------------------------
  1128. //
  1129. // Win32FileOutputProvider.
  1130. //
  1131. //----------------------------------------------------------------------------
  1132. class Win32FileOutputProvider
  1133. {
  1134. public:
  1135. Win32FileOutputProvider(HANDLE Handle);
  1136. virtual void Release(void);
  1137. virtual HRESULT SupportsStreaming(void);
  1138. virtual HRESULT Start(IN ULONG64 MaxSize);
  1139. virtual HRESULT Seek(IN ULONG How,
  1140. IN LONG64 Amount,
  1141. OUT OPTIONAL PULONG64 NewOffset);
  1142. virtual HRESULT WriteAll(IN PVOID Buffer,
  1143. IN ULONG Request);
  1144. virtual void Finish(void);
  1145. protected:
  1146. HANDLE m_Handle;
  1147. };
  1148. Win32FileOutputProvider::Win32FileOutputProvider(HANDLE Handle)
  1149. {
  1150. m_Handle = Handle;
  1151. }
  1152. void
  1153. Win32FileOutputProvider::Release(void)
  1154. {
  1155. delete this;
  1156. }
  1157. HRESULT
  1158. Win32FileOutputProvider::SupportsStreaming(void)
  1159. {
  1160. return S_OK;
  1161. }
  1162. HRESULT
  1163. Win32FileOutputProvider::Start(IN ULONG64 MaxSize)
  1164. {
  1165. // Nothing to do.
  1166. return S_OK;
  1167. }
  1168. HRESULT
  1169. Win32FileOutputProvider::Seek(IN ULONG How,
  1170. IN LONG64 Amount,
  1171. OUT OPTIONAL PULONG64 NewOffset)
  1172. {
  1173. ULONG Ret;
  1174. LONG High;
  1175. High = (LONG)(Amount >> 32);
  1176. Ret = SetFilePointer(m_Handle, (LONG)Amount, &High, How);
  1177. if (Ret == INVALID_SET_FILE_POINTER &&
  1178. GetLastError()) {
  1179. return WIN32_LAST_STATUS();
  1180. }
  1181. if (NewOffset) {
  1182. *NewOffset = ((ULONG64)High << 32) | Ret;
  1183. }
  1184. return S_OK;
  1185. }
  1186. HRESULT
  1187. Win32FileOutputProvider::WriteAll(IN PVOID Buffer,
  1188. IN ULONG Request)
  1189. {
  1190. ULONG Done;
  1191. if (!WriteFile(m_Handle, Buffer, Request, &Done, NULL)) {
  1192. return WIN32_LAST_STATUS();
  1193. }
  1194. if (Done != Request) {
  1195. return HRESULT_FROM_WIN32(ERROR_WRITE_FAULT);
  1196. }
  1197. return S_OK;
  1198. }
  1199. void
  1200. Win32FileOutputProvider::Finish(void)
  1201. {
  1202. // Nothing to do.
  1203. }
  1204. HRESULT
  1205. MiniDumpCreateFileOutputProvider
  1206. (IN HANDLE FileHandle,
  1207. OUT MiniDumpOutputProvider** Prov)
  1208. {
  1209. Win32FileOutputProvider* Obj =
  1210. new Win32FileOutputProvider(FileHandle);
  1211. if (!Obj) {
  1212. return E_OUTOFMEMORY;
  1213. }
  1214. *Prov = (MiniDumpOutputProvider*)Obj;
  1215. return S_OK;
  1216. }
  1217. //----------------------------------------------------------------------------
  1218. //
  1219. // Win32LiveAllocationProvider.
  1220. //
  1221. //----------------------------------------------------------------------------
  1222. class Win32LiveAllocationProvider : public MiniDumpAllocationProvider
  1223. {
  1224. public:
  1225. virtual void Release(void);
  1226. virtual PVOID Alloc(ULONG Size);
  1227. virtual PVOID Realloc(PVOID Mem, ULONG NewSize);
  1228. virtual void Free(PVOID Mem);
  1229. };
  1230. void
  1231. Win32LiveAllocationProvider::Release(void)
  1232. {
  1233. delete this;
  1234. }
  1235. PVOID
  1236. Win32LiveAllocationProvider::Alloc(ULONG Size)
  1237. {
  1238. return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Size);
  1239. }
  1240. PVOID
  1241. Win32LiveAllocationProvider::Realloc(PVOID Mem, ULONG NewSize)
  1242. {
  1243. return HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Mem, NewSize);
  1244. }
  1245. void
  1246. Win32LiveAllocationProvider::Free(PVOID Mem)
  1247. {
  1248. if (Mem) {
  1249. HeapFree(GetProcessHeap(), 0, Mem);
  1250. }
  1251. }
  1252. HRESULT
  1253. MiniDumpCreateLiveAllocationProvider
  1254. (OUT MiniDumpAllocationProvider** Prov)
  1255. {
  1256. Win32LiveAllocationProvider* Obj =
  1257. new Win32LiveAllocationProvider;
  1258. if (!Obj) {
  1259. return E_OUTOFMEMORY;
  1260. }
  1261. *Prov = (MiniDumpAllocationProvider*)Obj;
  1262. return S_OK;
  1263. }