Source code of Windows XP (NT5)
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.

2044 lines
57 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. tlhelp32.c
  5. Abstract:
  6. NT implementation of win95 ToolHelp API's
  7. Author:
  8. John Daly
  9. Environment:
  10. NT Only
  11. Notes:
  12. Version 1.0
  13. structure definitions/documentation in tlhelp32.h
  14. Revision History:
  15. John Daly (johndaly) 5-Apr-1996
  16. initial implementation
  17. --*/
  18. #include "basedll.h"
  19. #pragma hdrstop
  20. #include "tlhelp32.h"
  21. #define BUFFER_SIZE 64*1024
  22. #define ARRAYSIZE(x) (sizeof(x) / sizeof(x[0]))
  23. /*
  24. snapshot structure
  25. This is mapped onto the beginning of the memory we use to hold the information.
  26. */
  27. typedef struct tagSNAPSHOTSTATE {
  28. /* item list counts */
  29. ULONG HeapListCount;
  30. ULONG ProcessCount;
  31. ULONG ModuleCount;
  32. ULONG ThreadCount;
  33. /* item list head pointers */
  34. PHEAPLIST32 HeapListHead;
  35. PPROCESSENTRY32W ProcessListHead;
  36. PMODULEENTRY32W ModuleListHead;
  37. PTHREADENTRY32 ThreadListHead;
  38. /* item list current indexes */
  39. ULONG HeapListIndex;
  40. ULONG ProcessListIndex;
  41. ULONG ModuleListIndex;
  42. ULONG ThreadListIndex;
  43. /* data begins here... */
  44. UCHAR DataBegin;
  45. }SNAPSHOTSTATE;
  46. typedef SNAPSHOTSTATE * PSNAPSHOTSTATE;
  47. //
  48. // private functions
  49. //
  50. NTSTATUS
  51. ThpCreateRawSnap(
  52. IN ULONG dwFlags,
  53. IN ULONG th32ProcessID,
  54. PUCHAR *RawProcess,
  55. PRTL_DEBUG_INFORMATION *RawModule,
  56. PRTL_DEBUG_INFORMATION *RawDebugInfo);
  57. NTSTATUS
  58. ThpAllocateSnapshotSection(
  59. OUT PHANDLE SnapSection,
  60. IN DWORD dwFlags,
  61. IN DWORD th32ProcessID,
  62. PUCHAR RawProcess,
  63. PRTL_DEBUG_INFORMATION RawModule,
  64. PRTL_DEBUG_INFORMATION RawDebugInfo);
  65. NTSTATUS
  66. ThpProcessToSnap(
  67. IN DWORD dwFlags,
  68. IN DWORD th32ProcessID,
  69. IN HANDLE SnapSection,
  70. PUCHAR RawProcess,
  71. PRTL_DEBUG_INFORMATION RawModule,
  72. PRTL_DEBUG_INFORMATION RawDebugInfo);
  73. HANDLE
  74. WINAPI
  75. CreateToolhelp32Snapshot(
  76. IN DWORD dwFlags,
  77. IN DWORD th32ProcessID)
  78. /*++
  79. Routine Description:
  80. Takes a snapshot of the Win32 processes, heaps, modules, and threads used
  81. by the Win32 processes. Returns an open handle to the specified snapshot if
  82. successful or -1 otherwise.
  83. NOTE that all of the snapshots are global except for the heap and module
  84. lists which are process specific. To enumerate the heap or module state for
  85. all WIN32 processes call with TH32CS_SNAPALL and the current process. Then
  86. for each process in the TH32CS_SNAPPROCESS list that isn't the current
  87. process, do a call with just TH32CS_SNAPHEAPLIST and/or TH32CS_SNAPMODULE.
  88. Use CloseHandle to destroy the snapshot
  89. This function is not multi-thread safe. All of the other functions are.
  90. Arguments:
  91. dwFlags - Supplies switches to specify action as follows:
  92. TH32CS_INHERIT Indicates that the snapshot handle is to be inheritable.
  93. TH32CS_SNAPALL Equivalent to specifying the TH32CS_SNAPHEAPLIST,
  94. TH32CS_SNAPMODULE, TH32CS_SNAPPROCESS, and
  95. TH32CS_SNAPTHREAD values.
  96. TH32CS_SNAPHEAPLIST Includes the heap list of the specified Win32
  97. process in the snapshot.
  98. TH32CS_SNAPMODULE Includes the module list of the specified Win32
  99. process in the snapshot.
  100. TH32CS_SNAPPROCESS Includes the Win32 process list in the snapshot.
  101. TH32CS_SNAPTHREAD Includes the Win32 thread list in the snapshot.
  102. th32ProcessID - Supplies a Win32 process identifier. This parameter can be
  103. zero to indicate the current process. This parameter is used when the
  104. TH32CS_SNAPHEAPLIST or TH32CS_SNAPMODULE value is specified. Otherwise,
  105. it is ignored. The snapshot taken by this function is examined by the
  106. other tool help functions to provide their results. Access to the
  107. snapshot is read only. The snapshot handle acts like a Win32 object
  108. handle and is subject to the same rules regarding which processes and
  109. threads it is valid in.
  110. Return Value:
  111. Returns an open handle to the specified snapshot if successful or -1 if not.
  112. To retrieve an extended error status code generated by this function, use
  113. the GetLastError function.
  114. To destroy the snapshot, use the CloseHandle function.
  115. --*/
  116. {
  117. HANDLE SnapSection;
  118. PUCHAR RawProcess;
  119. PRTL_DEBUG_INFORMATION RawModule;
  120. PRTL_DEBUG_INFORMATION RawDebugInfo;
  121. NTSTATUS Status = 0;
  122. if (th32ProcessID == 0) {
  123. th32ProcessID = GetCurrentProcessId();
  124. }
  125. //
  126. // process the requested data types
  127. //
  128. Status = ThpCreateRawSnap(dwFlags,
  129. th32ProcessID,
  130. &RawProcess,
  131. &RawModule,
  132. &RawDebugInfo);
  133. if (!NT_SUCCESS(Status)) {
  134. BaseSetLastNTError(Status);
  135. return (HANDLE)-1;
  136. }
  137. Status = ThpAllocateSnapshotSection(&SnapSection,
  138. dwFlags,
  139. th32ProcessID,
  140. RawProcess,
  141. RawModule,
  142. RawDebugInfo);
  143. if (!NT_SUCCESS(Status)) {
  144. BaseSetLastNTError(Status);
  145. return (HANDLE)-1;
  146. }
  147. Status = ThpProcessToSnap(dwFlags,
  148. th32ProcessID,
  149. SnapSection,
  150. RawProcess,
  151. RawModule,
  152. RawDebugInfo);
  153. if (!NT_SUCCESS(Status)) {
  154. CloseHandle(SnapSection);
  155. BaseSetLastNTError(Status);
  156. return (HANDLE)-1;
  157. }
  158. return SnapSection;
  159. }
  160. BOOL
  161. WINAPI
  162. Heap32ListFirst(
  163. IN HANDLE SnapSection,
  164. IN OUT LPHEAPLIST32 lphl)
  165. /*++
  166. Routine Description:
  167. Retrieves information about the first heap that has been allocated by a
  168. specified Win32 process.
  169. Arguments:
  170. SnapSection - Supplies the handle of the snapshot returned from a previous
  171. call to the CreateToolhelp32Snapshot function.
  172. lphl - Returns a HEAPLIST32 structure. The calling application must set
  173. the dwSize member of HEAPLIST32 to the size, in bytes, of the structure.
  174. Return Value:
  175. Returns TRUE if the first entry of the heap list has been copied to the buffer
  176. or FALSE otherwise. The ERROR_NO_MORE_FILES error value is returned by the
  177. GetLastError function when no heap list exists or the snapshot does not contain
  178. heap list information.
  179. --*/
  180. {
  181. PSNAPSHOTSTATE SnapshotBase;
  182. LARGE_INTEGER SectionOffset;
  183. SIZE_T ViewSize;
  184. NTSTATUS Status = 0;
  185. BOOL retv = FALSE;
  186. if (!lphl || lphl->dwSize != sizeof(HEAPLIST32)) {
  187. BaseSetLastNTError(STATUS_INFO_LENGTH_MISMATCH);
  188. return FALSE;
  189. }
  190. SectionOffset.LowPart = 0;
  191. SectionOffset.HighPart = 0;
  192. ViewSize = 0;
  193. SnapshotBase = 0;
  194. Status = NtMapViewOfSection(SnapSection,
  195. NtCurrentProcess(),
  196. &SnapshotBase,
  197. 0L,
  198. 0L,
  199. &SectionOffset,
  200. &ViewSize,
  201. ViewShare,
  202. 0L,
  203. PAGE_READWRITE);
  204. if (!NT_SUCCESS(Status)) {
  205. BaseSetLastNTError(Status);
  206. return FALSE;
  207. }
  208. if (SnapshotBase->HeapListCount == 0) {
  209. RtlZeroMemory((PUCHAR)lphl + sizeof(SIZE_T), (lphl->dwSize - sizeof(SIZE_T)));
  210. SetLastError(ERROR_NO_MORE_FILES);
  211. } else {
  212. memcpy(lphl,
  213. (LPHEAPLIST32)((ULONG_PTR)SnapshotBase + (ULONG_PTR)SnapshotBase->HeapListHead),
  214. sizeof(HEAPLIST32));
  215. retv = TRUE;
  216. SnapshotBase->HeapListIndex = 1;
  217. }
  218. NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)SnapshotBase);
  219. return retv;
  220. }
  221. BOOL
  222. WINAPI
  223. Heap32ListNext(
  224. IN HANDLE SnapSection,
  225. IN OUT LPHEAPLIST32 lphl)
  226. /*++
  227. Routine Description:
  228. Retrieves information about the next heap that has been allocated by a
  229. Win32 process.
  230. Arguments:
  231. SnapSection - Supplies the handle of the snapshot returned from a previous
  232. call to the CreateToolhelp32Snapshot function.
  233. lphl - Returns a HEAPLIST32 structure. The calling application must set the
  234. dwSize member of HEAPLIST32 to the size, in bytes, of the structure.
  235. Return Value:
  236. Returns TRUE if the next entry of the heap list has been copied to the buffer or
  237. FALSE otherwise. The ERROR_NO_MORE_FILES error value is returned by the
  238. GetLastError function when no more entries in the heap list exist.
  239. --*/
  240. {
  241. PSNAPSHOTSTATE SnapshotBase;
  242. BOOL retv = FALSE;
  243. LARGE_INTEGER SectionOffset;
  244. SIZE_T ViewSize;
  245. NTSTATUS Status = 0;
  246. if (!lphl || lphl->dwSize != sizeof(HEAPLIST32)) {
  247. BaseSetLastNTError(STATUS_INFO_LENGTH_MISMATCH);
  248. return FALSE;
  249. }
  250. SectionOffset.LowPart = 0;
  251. SectionOffset.HighPart = 0;
  252. ViewSize = 0;
  253. SnapshotBase = 0;
  254. Status = NtMapViewOfSection(SnapSection,
  255. NtCurrentProcess(),
  256. &SnapshotBase,
  257. 0L,
  258. 0L,
  259. &SectionOffset,
  260. &ViewSize,
  261. ViewShare,
  262. 0L,
  263. PAGE_READWRITE);
  264. if (!NT_SUCCESS(Status)) {
  265. BaseSetLastNTError(Status);
  266. return FALSE;
  267. }
  268. if (SnapshotBase->HeapListIndex < SnapshotBase->HeapListCount) {
  269. memcpy(lphl,
  270. (LPHEAPLIST32)((ULONG_PTR)SnapshotBase + (ULONG_PTR)(&SnapshotBase->HeapListHead[SnapshotBase->HeapListIndex++])),
  271. sizeof(HEAPLIST32));
  272. retv = TRUE;
  273. } else {
  274. SetLastError(ERROR_NO_MORE_FILES);
  275. }
  276. NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)SnapshotBase);
  277. return(retv);
  278. }
  279. BOOL
  280. WINAPI
  281. Heap32First(
  282. IN OUT LPHEAPENTRY32 lphe,
  283. IN DWORD th32ProcessID,
  284. IN ULONG_PTR th32HeapID)
  285. /*++
  286. Routine Description:
  287. Retrieves information about the first block of a heap that has been
  288. allocated by a Win32 process. Also, create a snapshot of that heap so
  289. the Heap32Next functions can walk them.
  290. Arguments:
  291. lphe - Returns a HEAPENTRY32 structure. The calling application must set
  292. the dwSize member to the size, in bytes, of the structure.
  293. th32ProcessID - Supplies the identifier of the Win32 process context that
  294. owns the heap.
  295. th32HeapID - Supplies the identifier of the heap to enumerate.
  296. Return Value:
  297. Returns TRUE if information for the first heap block has been copied to the buffer
  298. or FALSE otherwise. The ERROR_NO_MORE_FILES error value is returned by the
  299. GetLastError function if the heap is invalid or empty.
  300. Notes:
  301. since there is no way to save heap snapshots or delete heap snapshots in any way that
  302. makes sense (because this info is not associated with snapshots etc), the information
  303. needs to be generated completely for each call. This is very expensive, it would be
  304. a good idea to redesign this API...
  305. We could try and cheat by preserving snapshots until they are completyely iterated or
  306. until a new one is taken, etc, but we will just end up with a bunch of memory leaks
  307. --*/
  308. {
  309. PRTL_DEBUG_INFORMATION ThRawHeapDebugInfo;
  310. ULONG HeapListCount;
  311. PRTL_HEAP_ENTRY p;
  312. PRTL_HEAP_INFORMATION HeapInfo;
  313. ULONG HeapEntryAddress;
  314. NTSTATUS Status = 0;
  315. BOOL retv = FALSE;
  316. if (!lphe || lphe->dwSize != sizeof(HEAPENTRY32)) {
  317. BaseSetLastNTError(STATUS_INFO_LENGTH_MISMATCH);
  318. return FALSE;
  319. }
  320. //
  321. // take snapshot
  322. //
  323. ThRawHeapDebugInfo = RtlCreateQueryDebugBuffer(0, FALSE);
  324. if(ThRawHeapDebugInfo == 0)
  325. {
  326. return STATUS_UNSUCCESSFUL;
  327. }
  328. Status = RtlQueryProcessDebugInformation((HANDLE)LongToHandle(th32ProcessID),
  329. RTL_QUERY_PROCESS_HEAP_SUMMARY |
  330. RTL_QUERY_PROCESS_HEAP_ENTRIES,
  331. ThRawHeapDebugInfo);
  332. if (!NT_SUCCESS(Status)) {
  333. RtlDestroyQueryDebugBuffer(ThRawHeapDebugInfo);
  334. BaseSetLastNTError(Status);
  335. return FALSE;
  336. }
  337. //
  338. // query snapshot
  339. //
  340. for (HeapListCount = 0;
  341. HeapListCount < ThRawHeapDebugInfo->Heaps->NumberOfHeaps;
  342. HeapListCount++) {
  343. HeapInfo = &ThRawHeapDebugInfo->Heaps->Heaps[HeapListCount];
  344. if ((ULONG_PTR)HeapInfo->BaseAddress == th32HeapID) {
  345. p = HeapInfo->Entries;
  346. lphe->dwResvd = 0;
  347. lphe->dwLockCount = 0;
  348. lphe->th32HeapID = th32HeapID;
  349. lphe->th32ProcessID = th32ProcessID;
  350. lphe->hHandle = (HANDLE)th32HeapID;// try this way
  351. // walk up to first non-segment block (I am assuming there is always one)
  352. // skip segments - can you have 2 in a row?
  353. // is first block always a segment?
  354. // We translate the heap flags to the most appropriate LF32_xxx values
  355. while(RTL_HEAP_SEGMENT & p->Flags) {
  356. lphe->dwAddress = (ULONG_PTR)p->u.s2.FirstBlock + ThRawHeapDebugInfo->Heaps->Heaps[HeapListCount].EntryOverhead; // reset this
  357. ++lphe->dwResvd;
  358. ++p;
  359. }
  360. //
  361. // munge flags
  362. //
  363. //----------------------------------------------
  364. if ((p->Flags & RTL_HEAP_BUSY) ||
  365. (p->Flags & RTL_HEAP_SETTABLE_VALUE) ||
  366. (p->Flags & RTL_HEAP_SETTABLE_FLAG2) ||
  367. (p->Flags & RTL_HEAP_SETTABLE_FLAG3) ||
  368. (p->Flags & RTL_HEAP_SETTABLE_FLAGS) ||
  369. (p->Flags & RTL_HEAP_PROTECTED_ENTRY)
  370. ) {
  371. lphe->dwFlags = LF32_FIXED;
  372. }
  373. else if ( p->Flags & RTL_HEAP_SETTABLE_FLAG1) {
  374. lphe->dwFlags = LF32_MOVEABLE;
  375. }
  376. else if ( p->Flags & RTL_HEAP_UNCOMMITTED_RANGE) {
  377. lphe->dwFlags = LF32_FREE;
  378. }
  379. //----------------------------------------------
  380. lphe->dwBlockSize = p->Size;
  381. retv = TRUE;
  382. break;
  383. }
  384. }
  385. //
  386. // free snapshot
  387. //
  388. RtlDestroyQueryDebugBuffer(ThRawHeapDebugInfo);
  389. return retv;
  390. }
  391. BOOL
  392. WINAPI
  393. Heap32Next(
  394. IN OUT LPHEAPENTRY32 lphe)
  395. /*++
  396. Routine Description:
  397. Retrieves information about the next block of a heap that has been
  398. allocated by a Win32 process.
  399. Arguments:
  400. lphe - Returns a HEAPENTRY32 structure. The calling application must set
  401. the dwSize member to the size, in bytes, of the structure.
  402. Return Value:
  403. Returns TRUE if information about the next block in the heap has been
  404. copied to the buffer or FALSE otherwise. The ERROR_NO_MORE_FILES error
  405. value is returned by the GetLastError function when no more objects in
  406. the heap exist.
  407. note:
  408. this function can be prone to error since the heap can change between
  409. calls to get heaplists, Heap32First, etc. There is no good way to
  410. manage a snapshot using this model, so we just get to live with it.
  411. --*/
  412. {
  413. PRTL_DEBUG_INFORMATION ThRawHeapDebugInfo;
  414. PRTL_HEAP_ENTRY p;
  415. PRTL_HEAP_INFORMATION HeapInfo;
  416. ULONG HeapListCount;
  417. BOOL retv = FALSE;
  418. BOOL hit_seg = FALSE;
  419. NTSTATUS Status = 0;
  420. if (!lphe || lphe->dwSize != sizeof(HEAPENTRY32)) {
  421. BaseSetLastNTError(STATUS_INFO_LENGTH_MISMATCH);
  422. return FALSE;
  423. }
  424. //
  425. // take snapshot
  426. //
  427. ThRawHeapDebugInfo = RtlCreateQueryDebugBuffer(0, FALSE);
  428. if(ThRawHeapDebugInfo == 0)
  429. {
  430. return STATUS_UNSUCCESSFUL;
  431. }
  432. Status = RtlQueryProcessDebugInformation((HANDLE)LongToHandle(lphe->th32ProcessID),
  433. RTL_QUERY_PROCESS_HEAP_SUMMARY |
  434. RTL_QUERY_PROCESS_HEAP_ENTRIES,
  435. ThRawHeapDebugInfo);
  436. if (!NT_SUCCESS(Status)) {
  437. RtlDestroyQueryDebugBuffer(ThRawHeapDebugInfo);
  438. BaseSetLastNTError(Status);
  439. return FALSE;
  440. }
  441. //
  442. // get index to correct heap list heap list - th32HeapID / baseadress
  443. //
  444. for (HeapListCount = 0; HeapListCount < ThRawHeapDebugInfo->Heaps->NumberOfHeaps; ++HeapListCount)
  445. {
  446. if((ULONG_PTR)ThRawHeapDebugInfo->Heaps->Heaps[HeapListCount].BaseAddress == lphe->th32HeapID)
  447. {
  448. break;
  449. }
  450. }
  451. //
  452. // ran out of heaps
  453. //
  454. if(HeapListCount >= ThRawHeapDebugInfo->Heaps->NumberOfHeaps)
  455. {
  456. RtlDestroyQueryDebugBuffer(ThRawHeapDebugInfo);
  457. SetLastError(ERROR_NO_MORE_FILES);
  458. return FALSE;
  459. }
  460. //
  461. // check for last entry
  462. //
  463. ++lphe->dwResvd; // point to next one
  464. if(lphe->dwResvd >= ThRawHeapDebugInfo->Heaps->Heaps[HeapListCount].NumberOfEntries)
  465. {
  466. RtlDestroyQueryDebugBuffer(ThRawHeapDebugInfo);
  467. SetLastError(ERROR_NO_MORE_FILES);
  468. return FALSE;
  469. }
  470. //
  471. // point to correct heap entry - index of this is kept in lphe->dwResvd
  472. //
  473. p = (PRTL_HEAP_ENTRY)&ThRawHeapDebugInfo->Heaps->Heaps[HeapListCount].Entries[lphe->dwResvd];
  474. // keep segments in lphe->hHandle
  475. while(RTL_HEAP_SEGMENT & p->Flags) {
  476. lphe->dwAddress = (ULONG_PTR)p->u.s2.FirstBlock + ThRawHeapDebugInfo->Heaps->Heaps[HeapListCount].EntryOverhead;// reset this
  477. if(lphe->dwResvd >= ThRawHeapDebugInfo->Heaps->Heaps[HeapListCount].NumberOfEntries)
  478. {
  479. RtlDestroyQueryDebugBuffer(ThRawHeapDebugInfo);
  480. SetLastError(ERROR_NO_MORE_FILES);
  481. return FALSE;
  482. }
  483. ++lphe->dwResvd;
  484. ++p;
  485. hit_seg = TRUE;
  486. }
  487. //
  488. // calculate the address
  489. // normally, we could add the size of the previous block to the existing (last) address
  490. // to get the current address, but this is only for blocks that do not follow a segment
  491. // I am assuming that there will always be a segment first
  492. // current address = last address() + last size
  493. // by the time we reach this point, either we have just exited from scannin a segment, or
  494. // p-> is pointing at a non-segment entry.
  495. //
  496. if(hit_seg == FALSE)
  497. {
  498. lphe->dwAddress += lphe->dwBlockSize;
  499. }
  500. lphe->dwBlockSize = p->Size;
  501. //
  502. // munge flags
  503. //
  504. // We translate the heap flags to the most appropriate LF32_xxx values
  505. //----------------------------------------------
  506. if( (p->Flags & RTL_HEAP_BUSY) ||
  507. (p->Flags & RTL_HEAP_SETTABLE_VALUE) ||
  508. (p->Flags & RTL_HEAP_SETTABLE_FLAG2) ||
  509. (p->Flags & RTL_HEAP_SETTABLE_FLAG3) ||
  510. (p->Flags & RTL_HEAP_SETTABLE_FLAGS) ||
  511. (p->Flags & RTL_HEAP_PROTECTED_ENTRY)
  512. ) {
  513. lphe->dwFlags = LF32_FIXED;
  514. }
  515. else if( p->Flags & RTL_HEAP_SETTABLE_FLAG1) {
  516. lphe->dwFlags = LF32_MOVEABLE;
  517. }
  518. else if( p->Flags & RTL_HEAP_UNCOMMITTED_RANGE) {
  519. lphe->dwFlags = LF32_FREE;
  520. }
  521. //----------------------------------------------
  522. retv = TRUE;
  523. //
  524. // free snapshot
  525. //
  526. RtlDestroyQueryDebugBuffer(ThRawHeapDebugInfo);
  527. return(retv);
  528. }
  529. BOOL
  530. WINAPI
  531. Toolhelp32ReadProcessMemory(
  532. IN DWORD th32ProcessID,
  533. IN LPCVOID lpBaseAddress,
  534. OUT PUCHAR lpBuffer,
  535. IN SIZE_T cbRead,
  536. OUT SIZE_T *lpNumberOfBytesRead)
  537. /*++
  538. Routine Description:
  539. Copies memory allocated to another process into an application-supplied
  540. buffer. This function is for people who are to lazy to open
  541. the process themselves.
  542. Arguments:
  543. th32ProcessID - Supplies the Identifier of the Win32 process whose memory
  544. is being copied. This parameter can be zero to copy the memory of the
  545. current process.
  546. lpBaseAddress - Supplies the base address in the specified process to read.
  547. Before transferring any data, the system verifies that all data in the
  548. base address and memory of the specified size is accessible for read
  549. access. If this is the case, the function proceeds. Otherwise, the
  550. function fails.
  551. lpBuffer - Returns the requested data
  552. cbRead - Supplies the number of bytes to read from the specified process.
  553. lpNumberOfBytesRead - Returns the number of bytes copied to the buffer. If
  554. this parameter is NULL, it is ignored.
  555. Return Value:
  556. Returns TRUE if successful.
  557. --*/
  558. {
  559. HANDLE hProcess;
  560. BOOL RetVal;
  561. hProcess = OpenProcess(PROCESS_VM_READ, FALSE, th32ProcessID);
  562. if (hProcess == NULL) {
  563. return FALSE;
  564. }
  565. RetVal = ReadProcessMemory(hProcess,
  566. lpBaseAddress,
  567. lpBuffer,
  568. cbRead,
  569. lpNumberOfBytesRead);
  570. CloseHandle(hProcess);
  571. return RetVal;
  572. }
  573. BOOL
  574. WINAPI
  575. Process32FirstW(
  576. IN HANDLE SnapSection,
  577. IN OUT LPPROCESSENTRY32W lppe)
  578. /*++
  579. Routine Description:
  580. Retrieves information about the first Win32 process encountered in a system
  581. snapshot.
  582. Arguments:
  583. SnapSection - Supplies the handle of a snapshot returned from a previous call
  584. to the CreateToolhelp32Snapshot function.
  585. lppe - Returns a PROCESSENTRY32W structure. The caller must set the dwSize
  586. member to the size, in bytes, of the structure.
  587. Return Value:
  588. Returns TRUE if the first entry of the process list has been copied to the buffer
  589. or FALSE otherwise. The ERROR_NO_MORE_FILES error value is returned by the
  590. GetLastError function if no processes exist or the snapshot does not contain
  591. process information.
  592. --*/
  593. {
  594. PSNAPSHOTSTATE SnapshotBase;
  595. LARGE_INTEGER SectionOffset;
  596. SIZE_T ViewSize;
  597. NTSTATUS Status = 0;
  598. BOOL retv = FALSE;
  599. if (!lppe || lppe->dwSize != sizeof(PROCESSENTRY32W)) {
  600. BaseSetLastNTError(STATUS_INFO_LENGTH_MISMATCH);
  601. return FALSE;
  602. }
  603. SectionOffset.LowPart = 0;
  604. SectionOffset.HighPart = 0;
  605. ViewSize = 0;
  606. SnapshotBase = 0;
  607. Status = NtMapViewOfSection(SnapSection,
  608. NtCurrentProcess(),
  609. &SnapshotBase,
  610. 0L,
  611. 0L,
  612. &SectionOffset,
  613. &ViewSize,
  614. ViewShare,
  615. 0L,
  616. PAGE_READWRITE);
  617. if (!NT_SUCCESS(Status)) {
  618. BaseSetLastNTError(Status);
  619. return FALSE;
  620. }
  621. if (SnapshotBase->ProcessCount == 0) {
  622. memset((PUCHAR)lppe + 4, 0, lppe->dwSize - 4);
  623. SetLastError(ERROR_NO_MORE_FILES);
  624. } else {
  625. memcpy(lppe,
  626. (LPPROCESSENTRY32W)((ULONG_PTR)SnapshotBase + (ULONG_PTR)SnapshotBase->ProcessListHead),
  627. sizeof(PROCESSENTRY32W));
  628. SnapshotBase->ProcessListIndex = 1;
  629. retv = TRUE;
  630. }
  631. NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)SnapshotBase);
  632. return retv;
  633. }
  634. BOOL
  635. WINAPI
  636. Process32First(
  637. IN HANDLE SnapSection,
  638. IN OUT LPPROCESSENTRY32 lppe)
  639. /*++
  640. Routine Description:
  641. ANSI version of Process32FirstW.
  642. Retrieves information about the first Win32 process encountered in a system
  643. snapshot.
  644. Arguments:
  645. SnapSection - Supplies the handle of a snapshot returned from a previous call
  646. to the CreateToolhelp32Snapshot function.
  647. lppe - Returns a PROCESSENTRY32 structure. The caller must set the dwSize
  648. member to the size, in bytes, of the structure.
  649. Return Value:
  650. Returns TRUE if the first entry of the process list has been copied to the buffer
  651. or FALSE otherwise. The ERROR_NO_MORE_FILES error value is returned by the
  652. GetLastError function if no processes exist or the snapshot does not contain
  653. process information.
  654. --*/
  655. {
  656. PROCESSENTRY32W pe32w;
  657. BOOL b;
  658. if (lppe == NULL || (lppe->dwSize < sizeof(PROCESSENTRY32))) {
  659. BaseSetLastNTError(STATUS_INFO_LENGTH_MISMATCH);
  660. return FALSE;
  661. }
  662. // Thunk to Process32FirstW
  663. pe32w.dwSize = sizeof(pe32w);
  664. b = Process32FirstW(SnapSection,&pe32w);
  665. WideCharToMultiByte(CP_ACP, 0,
  666. pe32w.szExeFile, -1,
  667. lppe->szExeFile, ARRAYSIZE(lppe->szExeFile),
  668. 0, 0);
  669. lppe->cntUsage = pe32w.cntUsage; // meaningless on NT, copy anyway
  670. lppe->th32ProcessID = pe32w.th32ProcessID;
  671. lppe->th32DefaultHeapID = pe32w.th32DefaultHeapID;
  672. lppe->th32ModuleID = pe32w.th32ModuleID;
  673. lppe->cntThreads = pe32w.cntThreads;
  674. lppe->th32ParentProcessID = pe32w.th32ParentProcessID;
  675. lppe->pcPriClassBase = pe32w.pcPriClassBase;
  676. lppe->dwFlags = pe32w.dwFlags;
  677. return b;
  678. }
  679. BOOL
  680. WINAPI
  681. Process32NextW(
  682. IN HANDLE SnapSection,
  683. IN OUT LPPROCESSENTRY32W lppe)
  684. /*++
  685. Routine Description:
  686. Retrieves information about the next Win32 process recorded in a system snapshot.
  687. Arguments:
  688. SnapSection - Supplies the handle of a snapshot returned from a previous call
  689. to the CreateToolhelp32Snapshot function.
  690. lppe - Returns a PROCESSENTRY32W structure. The caller must set the dwSize
  691. member to the size, in bytes, of the structure.
  692. Return Value:
  693. Returns TRUE if the next entry of the process list has been copied to the buffer or
  694. FALSE otherwise. The ERROR_NO_MORE_FILES error value is returned by the GetLastError
  695. function if no processes exist or the snapshot does not contain process information.
  696. --*/
  697. {
  698. PSNAPSHOTSTATE SnapshotBase;
  699. BOOL retv = FALSE;
  700. LARGE_INTEGER SectionOffset;
  701. SIZE_T ViewSize;
  702. NTSTATUS Status = 0;
  703. if (!lppe || lppe->dwSize != sizeof(PROCESSENTRY32W)) {
  704. BaseSetLastNTError(STATUS_INFO_LENGTH_MISMATCH);
  705. return FALSE;
  706. }
  707. SectionOffset.LowPart = 0;
  708. SectionOffset.HighPart = 0;
  709. ViewSize = 0;
  710. SnapshotBase = 0;
  711. Status = NtMapViewOfSection(SnapSection,
  712. NtCurrentProcess(),
  713. &SnapshotBase,
  714. 0L,
  715. 0L,
  716. &SectionOffset,
  717. &ViewSize,
  718. ViewShare,
  719. 0L,
  720. PAGE_READWRITE);
  721. if (!NT_SUCCESS(Status)) {
  722. BaseSetLastNTError(Status);
  723. return FALSE;
  724. }
  725. if (SnapshotBase->ProcessListIndex < SnapshotBase->ProcessCount) {
  726. memcpy(lppe,
  727. (LPPROCESSENTRY32W)((ULONG_PTR)SnapshotBase + (ULONG_PTR)(&SnapshotBase->ProcessListHead[SnapshotBase->ProcessListIndex++])),
  728. sizeof(PROCESSENTRY32W));
  729. retv = TRUE;
  730. } else {
  731. SetLastError(ERROR_NO_MORE_FILES);
  732. }
  733. NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)SnapshotBase);
  734. return retv;
  735. }
  736. BOOL
  737. WINAPI
  738. Process32Next(
  739. IN HANDLE SnapSection,
  740. IN OUT LPPROCESSENTRY32 lppe)
  741. /*++
  742. Routine Description:
  743. ANSI version of Process32NextW
  744. Retrieves information about the next Win32 process recorded in a system snapshot.
  745. Arguments:
  746. SnapSection - Supplies the handle of a snapshot returned from a previous call
  747. to the CreateToolhelp32Snapshot function.
  748. lppe - Returns a PROCESSENTRY32 structure. The caller must set the dwSize
  749. member to the size, in bytes, of the structure.
  750. Return Value:
  751. Returns TRUE if the next entry of the process list has been copied to the buffer or
  752. FALSE otherwise. The ERROR_NO_MORE_FILES error value is returned by the GetLastError
  753. function if no processes exist or the snapshot does not contain process information.
  754. --*/
  755. {
  756. PROCESSENTRY32W pe32w;
  757. BOOL b;
  758. if (lppe == NULL || (lppe->dwSize < sizeof(PROCESSENTRY32))) {
  759. BaseSetLastNTError(STATUS_INFO_LENGTH_MISMATCH);
  760. return FALSE;
  761. }
  762. // Thunk to Process32NextW
  763. pe32w.dwSize = sizeof(pe32w);
  764. b = Process32NextW(SnapSection,&pe32w);
  765. WideCharToMultiByte(CP_ACP, 0,
  766. pe32w.szExeFile, -1,
  767. lppe->szExeFile, ARRAYSIZE(lppe->szExeFile),
  768. 0, 0);
  769. lppe->cntUsage = pe32w.cntUsage; // meaningless on NT, copy anyway
  770. lppe->th32ProcessID = pe32w.th32ProcessID;
  771. lppe->th32DefaultHeapID = pe32w.th32DefaultHeapID;
  772. lppe->th32ModuleID = pe32w.th32ModuleID;
  773. lppe->cntThreads = pe32w.cntThreads;
  774. lppe->th32ParentProcessID = pe32w.th32ParentProcessID;
  775. lppe->pcPriClassBase = pe32w.pcPriClassBase;
  776. lppe->dwFlags = pe32w.dwFlags;
  777. return b;
  778. }
  779. BOOL
  780. WINAPI
  781. Thread32First(
  782. IN HANDLE SnapSection,
  783. IN OUT LPTHREADENTRY32 lpte)
  784. /*++
  785. Routine Description:
  786. Retrieves information about the first thread of any Win32 process
  787. encountered in a system snapshot.
  788. Arguments:
  789. SnapSection - Supplies the handle of a snapshot returned from a previous
  790. call to the CreateToolhelp32Snapshot function.
  791. lpte - Returns a THREADENTRY32 structure. The caller must set the dwSize
  792. member to the size, in bytes, of the structure.
  793. Return Value:
  794. Returns TRUE if the first entry of the thread list has been copied to the buffer or
  795. FALSE otherwise. The ERROR_NO_MORE_FILES error value is returned by the GetLastError
  796. function if no threads exist or the snapshot does not contain thread information.
  797. --*/
  798. {
  799. PSNAPSHOTSTATE SnapshotBase;
  800. LARGE_INTEGER SectionOffset;
  801. SIZE_T ViewSize;
  802. NTSTATUS Status = 0;
  803. BOOL retv = FALSE;
  804. if (!lpte || lpte->dwSize != sizeof(THREADENTRY32)) {
  805. BaseSetLastNTError(STATUS_INFO_LENGTH_MISMATCH);
  806. return FALSE;
  807. }
  808. SectionOffset.LowPart = 0;
  809. SectionOffset.HighPart = 0;
  810. ViewSize = 0;
  811. SnapshotBase = 0;
  812. Status = NtMapViewOfSection(SnapSection,
  813. NtCurrentProcess(),
  814. &SnapshotBase,
  815. 0L,
  816. 0L,
  817. &SectionOffset,
  818. &ViewSize,
  819. ViewShare,
  820. 0L,
  821. PAGE_READWRITE);
  822. if (!NT_SUCCESS(Status)) {
  823. BaseSetLastNTError(Status);
  824. return FALSE;
  825. }
  826. if (SnapshotBase->ThreadCount == 0) {
  827. memset((PUCHAR)lpte + 4, 0, lpte->dwSize - 4);
  828. SetLastError(ERROR_NO_MORE_FILES);
  829. } else {
  830. memcpy(lpte,
  831. (LPTHREADENTRY32)((ULONG_PTR)SnapshotBase + (ULONG_PTR)SnapshotBase->ThreadListHead),
  832. sizeof(THREADENTRY32));
  833. SnapshotBase->ThreadListIndex = 1;
  834. retv = TRUE;
  835. }
  836. NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)SnapshotBase);
  837. return(retv);
  838. }
  839. BOOL
  840. WINAPI
  841. Thread32Next(
  842. IN HANDLE SnapSection,
  843. IN OUT LPTHREADENTRY32 lpte)
  844. /*++
  845. Routine Description:
  846. Retrieves information about the next thread of any Win32 process encountered in the
  847. system memory snapshot.
  848. Arguments:
  849. SnapSection - Supplies the handle of a snapshot returned from a previous call
  850. to the CreateToolhelp32Snapshot function.
  851. lpte - Reeturns a THREADENTRY32 structure. The caller must set the dwSize
  852. member to the size, in bytes, of the structure.
  853. Return Value:
  854. Returns TRUE if the next entry of the thread list has been copied to the buffer or
  855. FALSE otherwise. The ERROR_NO_MORE_FILES error value is returned by the GetLastError
  856. function if no threads exist or the snapshot does not contain thread information.
  857. --*/
  858. {
  859. PSNAPSHOTSTATE SnapshotBase;
  860. BOOL retv = FALSE;
  861. LARGE_INTEGER SectionOffset;
  862. SIZE_T ViewSize;
  863. NTSTATUS Status = 0;
  864. if (!lpte || lpte->dwSize != sizeof(THREADENTRY32)) {
  865. BaseSetLastNTError(STATUS_INFO_LENGTH_MISMATCH);
  866. return FALSE;
  867. }
  868. SectionOffset.LowPart = 0;
  869. SectionOffset.HighPart = 0;
  870. ViewSize = 0;
  871. SnapshotBase = 0;
  872. Status = NtMapViewOfSection(SnapSection,
  873. NtCurrentProcess(),
  874. &SnapshotBase,
  875. 0L,
  876. 0L,
  877. &SectionOffset,
  878. &ViewSize,
  879. ViewShare,
  880. 0L,
  881. PAGE_READWRITE);
  882. if (!NT_SUCCESS(Status)) {
  883. BaseSetLastNTError(Status);
  884. return FALSE;
  885. }
  886. if (SnapshotBase->ThreadListIndex < SnapshotBase->ThreadCount) {
  887. memcpy(lpte,
  888. (PTHREADENTRY32)((ULONG_PTR)SnapshotBase + (ULONG_PTR)(&SnapshotBase->ThreadListHead[SnapshotBase->ThreadListIndex++])),
  889. sizeof(THREADENTRY32));
  890. retv = TRUE;
  891. } else {
  892. SetLastError(ERROR_NO_MORE_FILES);
  893. }
  894. NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)SnapshotBase);
  895. return(retv);
  896. }
  897. BOOL
  898. WINAPI
  899. Module32FirstW(
  900. IN HANDLE SnapSection,
  901. IN OUT LPMODULEENTRY32W lpme)
  902. /*++
  903. Routine Description:
  904. Retrieves information about the first module associated with a Win32 process.
  905. Arguments:
  906. SnapSection - Supplies the handle of a snapshot returned from a previous call
  907. to the CreateToolhelp32Snapshot function.
  908. lpme - Returns a buffer containing a MODULEENTRY32W structure. The caller
  909. must set the dwSize member to the size, in bytes, of the structure.
  910. Return Value:
  911. Returns TRUE if the first entry of the module list has been copied to the buffer or
  912. FALSE otherwise. The ERROR_NO_MORE_FILES error value is returned by the GetLastError
  913. function if no modules exist or the snapshot does not contain module information.
  914. --*/
  915. {
  916. PSNAPSHOTSTATE SnapshotBase;
  917. LARGE_INTEGER SectionOffset;
  918. SIZE_T ViewSize;
  919. NTSTATUS Status = 0;
  920. BOOL retv = FALSE;
  921. if (!lpme || lpme->dwSize != sizeof(MODULEENTRY32W)) {
  922. BaseSetLastNTError(STATUS_INFO_LENGTH_MISMATCH);
  923. return FALSE;
  924. }
  925. SectionOffset.LowPart = 0;
  926. SectionOffset.HighPart = 0;
  927. ViewSize = 0;
  928. SnapshotBase = 0;
  929. Status = NtMapViewOfSection(SnapSection,
  930. NtCurrentProcess(),
  931. &SnapshotBase,
  932. 0L,
  933. 0L,
  934. &SectionOffset,
  935. &ViewSize,
  936. ViewShare,
  937. 0L,
  938. PAGE_READWRITE);
  939. if (!NT_SUCCESS(Status)) {
  940. BaseSetLastNTError(Status);
  941. return FALSE;
  942. }
  943. if (SnapshotBase->ModuleCount == 0) {
  944. memset((PUCHAR)lpme + 4, 0, lpme->dwSize - 4);
  945. SetLastError(ERROR_NO_MORE_FILES);
  946. } else {
  947. memcpy(lpme,
  948. (PMODULEENTRY32W)((ULONG_PTR)SnapshotBase + (ULONG_PTR)SnapshotBase->ModuleListHead),
  949. sizeof(MODULEENTRY32W));
  950. SnapshotBase->ModuleListIndex = 1;
  951. retv = TRUE;
  952. }
  953. NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)SnapshotBase);
  954. return retv;
  955. }
  956. BOOL
  957. WINAPI
  958. Module32First(
  959. IN HANDLE SnapSection,
  960. IN OUT LPMODULEENTRY32 lpme)
  961. /*++
  962. Routine Description:
  963. ANSI version of Module32FirstW.
  964. Retrieves information about the first module associated with a Win32 process.
  965. Arguments:
  966. SnapSection - Supplies the handle of the snapshot returned from a previous call
  967. to the CreateToolhelp32Snapshot function.
  968. lpme - Returns a buffer containing a MODULEENTRY32 structure. The caller
  969. must set the dwSize member to the size, in bytes, of the structure.
  970. Return Value:
  971. Returns TRUE if the first entry of the module list has been copied to the buffer or
  972. FALSE otherwise. The ERROR_NO_MORE_FILES error value is returned by the GetLastError
  973. function if no modules exist or the snapshot does not contain module information.
  974. --*/
  975. {
  976. MODULEENTRY32W me32w;
  977. DWORD dwSizeToCopy;
  978. BOOL b;
  979. if (lpme == NULL || (lpme->dwSize < sizeof(MODULEENTRY32))) {
  980. SetLastError(ERROR_INVALID_PARAMETER);
  981. return FALSE;
  982. }
  983. // Thunk to Module32FirstW
  984. me32w.dwSize = sizeof(me32w);
  985. b = Module32FirstW(SnapSection,&me32w);
  986. WideCharToMultiByte(CP_ACP, 0,
  987. me32w.szExePath, -1,
  988. lpme->szExePath, ARRAYSIZE(lpme->szExePath),
  989. 0, 0);
  990. WideCharToMultiByte(CP_ACP, 0,
  991. me32w.szModule, -1,
  992. lpme->szModule, ARRAYSIZE(lpme->szModule),
  993. 0, 0);
  994. lpme->th32ModuleID = me32w.th32ModuleID;
  995. lpme->th32ProcessID = me32w.th32ProcessID;
  996. lpme->GlblcntUsage = me32w.GlblcntUsage;
  997. lpme->ProccntUsage = me32w.ProccntUsage;
  998. lpme->modBaseAddr = me32w.modBaseAddr;
  999. lpme->modBaseSize = me32w.modBaseSize;
  1000. lpme->hModule = me32w.hModule;
  1001. return b;
  1002. }
  1003. BOOL
  1004. WINAPI
  1005. Module32NextW(
  1006. IN HANDLE SnapSection,
  1007. IN OUT LPMODULEENTRY32W lpme)
  1008. /*++
  1009. Routine Description:
  1010. Retrieves information about the next module associated with a Win32 process or thread.
  1011. Arguments:
  1012. SnapSection - Supplies the handle of a snapshot returned from a previous call
  1013. to CreateToolhelp32Snapshot.
  1014. lpme - Returns a MODULEENTRY32W structure. The calling application must set
  1015. the dwSize member to the size, in bytes, of the structure.
  1016. Return Value:
  1017. Returns TRUE if the next entry of the module list has been copied to the buffer or
  1018. FALSE otherwise. The ERROR_NO_MORE_FILES error value is returned by the GetLastError
  1019. function if no more modules exist.
  1020. --*/
  1021. {
  1022. PSNAPSHOTSTATE SnapshotBase;
  1023. BOOL retv = FALSE;
  1024. LARGE_INTEGER SectionOffset;
  1025. SIZE_T ViewSize;
  1026. NTSTATUS Status = 0;
  1027. if (!lpme || lpme->dwSize != sizeof(MODULEENTRY32W)) {
  1028. BaseSetLastNTError(STATUS_INFO_LENGTH_MISMATCH);
  1029. return FALSE;
  1030. }
  1031. SectionOffset.LowPart = 0;
  1032. SectionOffset.HighPart = 0;
  1033. ViewSize = 0;
  1034. SnapshotBase = 0;
  1035. Status = NtMapViewOfSection(SnapSection,
  1036. NtCurrentProcess(),
  1037. &SnapshotBase,
  1038. 0L,
  1039. 0L,
  1040. &SectionOffset,
  1041. &ViewSize,
  1042. ViewShare,
  1043. 0L,
  1044. PAGE_READWRITE);
  1045. if (!NT_SUCCESS(Status)) {
  1046. BaseSetLastNTError(Status);
  1047. return FALSE;
  1048. }
  1049. if (SnapshotBase->ModuleListIndex < SnapshotBase->ModuleCount) {
  1050. memcpy(lpme,
  1051. (LPMODULEENTRY32W)((ULONG_PTR)SnapshotBase + (ULONG_PTR)(&SnapshotBase->ModuleListHead[SnapshotBase->ModuleListIndex++])),
  1052. sizeof(MODULEENTRY32W));
  1053. retv = TRUE;
  1054. } else {
  1055. SetLastError(ERROR_NO_MORE_FILES);
  1056. }
  1057. NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)SnapshotBase);
  1058. return(retv);
  1059. }
  1060. BOOL
  1061. WINAPI
  1062. Module32Next(
  1063. IN HANDLE SnapSection,
  1064. IN OUT LPMODULEENTRY32 lpme)
  1065. /*++
  1066. Routine Description:
  1067. ANSI version of Module32NextW.
  1068. Retrieves information about the next module associated with a Win32 process or thread.
  1069. Arguments:
  1070. SnapSection - Supplies the handle of a snapshot returned from a previous call
  1071. to CreateToolhelp32Snapshot.
  1072. lpme - Returns a MODULEENTRY32 structure. The calling application must set
  1073. the dwSize member to the size, in bytes, of the structure.
  1074. Return Value:
  1075. Returns TRUE if the next entry of the module list has been copied to the buffer or
  1076. FALSE otherwise. The ERROR_NO_MORE_FILES error value is returned by the GetLastError
  1077. function if no more modules exist.
  1078. --*/
  1079. {
  1080. MODULEENTRY32W me32w;
  1081. BOOL b;
  1082. if (lpme == NULL || (lpme->dwSize < sizeof(MODULEENTRY32))) {
  1083. SetLastError(ERROR_INVALID_DATA);
  1084. return FALSE;
  1085. }
  1086. // Thunk to Module32NextW
  1087. me32w.dwSize = sizeof(me32w);
  1088. b = Module32NextW(SnapSection,&me32w);
  1089. WideCharToMultiByte(CP_ACP, 0,
  1090. me32w.szModule, -1,
  1091. lpme->szModule, ARRAYSIZE(lpme->szModule),
  1092. 0, 0);
  1093. WideCharToMultiByte(CP_ACP, 0,
  1094. me32w.szExePath, -1,
  1095. lpme->szExePath, ARRAYSIZE(lpme->szExePath),
  1096. 0, 0);
  1097. lpme->th32ModuleID = me32w.th32ModuleID;
  1098. lpme->GlblcntUsage = me32w.GlblcntUsage;
  1099. lpme->ProccntUsage = me32w.ProccntUsage;
  1100. lpme->modBaseAddr = me32w.modBaseAddr;
  1101. lpme->modBaseSize = me32w.modBaseSize;
  1102. lpme->hModule = me32w.hModule;
  1103. return b;
  1104. }
  1105. NTSTATUS
  1106. ThpCreateRawSnap(
  1107. IN DWORD dwFlags,
  1108. IN DWORD th32ProcessID,
  1109. PUCHAR *RawProcess,
  1110. PRTL_DEBUG_INFORMATION *RawModule,
  1111. PRTL_DEBUG_INFORMATION *RawDebugInfo)
  1112. /*++
  1113. Routine Description:
  1114. This function gets raw snapshots for the data types specified by dwFlags.
  1115. Arguments:
  1116. th32ProcessID - Supplies a WIN32 process ID. See CreateToolhelp32Snapshot
  1117. for full description.
  1118. dwFlags - Supplies switches requesting various data. See
  1119. CreateToolhelp32Snapshot for full description
  1120. Return Value:
  1121. NTSTATUS as appropriate
  1122. --*/
  1123. {
  1124. NTSTATUS Status = 0;
  1125. ULONG BufferSize = BUFFER_SIZE;
  1126. SIZE_T stBufferSize = BUFFER_SIZE;
  1127. //
  1128. // get process/thread/module/heap info
  1129. //
  1130. *RawProcess = NULL;
  1131. *RawModule = NULL;
  1132. *RawDebugInfo = NULL;
  1133. if((dwFlags & TH32CS_SNAPPROCESS) || (dwFlags & TH32CS_SNAPTHREAD)){
  1134. do {
  1135. try {
  1136. stBufferSize = BufferSize;
  1137. Status = NtAllocateVirtualMemory(NtCurrentProcess(),
  1138. RawProcess,
  1139. 0,
  1140. &stBufferSize,
  1141. MEM_COMMIT,
  1142. PAGE_READWRITE);
  1143. }
  1144. except( EXCEPTION_EXECUTE_HANDLER ) {
  1145. Status = GetExceptionCode();
  1146. }
  1147. if (!NT_SUCCESS(Status)) {
  1148. break;
  1149. }
  1150. BufferSize = (ULONG)stBufferSize;
  1151. //
  1152. // get all of the status information */
  1153. //
  1154. Status = NtQuerySystemInformation(SystemProcessInformation,
  1155. *RawProcess,
  1156. BufferSize,
  1157. NULL);
  1158. if (Status == STATUS_INFO_LENGTH_MISMATCH) {
  1159. NtFreeVirtualMemory(NtCurrentProcess(),
  1160. RawProcess,
  1161. &stBufferSize,
  1162. MEM_RELEASE);
  1163. *RawProcess = NULL;
  1164. BufferSize += 8192;
  1165. }
  1166. } while(Status == STATUS_INFO_LENGTH_MISMATCH);
  1167. }
  1168. //
  1169. // get module information
  1170. //
  1171. if((dwFlags & TH32CS_SNAPMODULE) || (dwFlags & TH32CS_SNAPMODULE32))
  1172. {
  1173. if (NT_SUCCESS(Status)) {
  1174. *RawModule = RtlCreateQueryDebugBuffer(0, FALSE);
  1175. if (!*RawModule) {
  1176. Status = STATUS_UNSUCCESSFUL;
  1177. }
  1178. }
  1179. if (NT_SUCCESS(Status)) {
  1180. Status = RtlQueryProcessDebugInformation((HANDLE)LongToHandle(th32ProcessID),
  1181. RTL_QUERY_PROCESS_NONINVASIVE |
  1182. ((dwFlags & TH32CS_SNAPMODULE) ? RTL_QUERY_PROCESS_MODULES : 0) |
  1183. ((dwFlags & TH32CS_SNAPMODULE32) ? RTL_QUERY_PROCESS_MODULES32 : 0),
  1184. *RawModule);
  1185. }
  1186. }
  1187. //
  1188. // get the heap summary information for the specified process */
  1189. //
  1190. if (dwFlags & TH32CS_SNAPHEAPLIST) {
  1191. if (NT_SUCCESS(Status)) {
  1192. *RawDebugInfo = RtlCreateQueryDebugBuffer(0, FALSE);
  1193. if (!*RawDebugInfo) {
  1194. Status = STATUS_UNSUCCESSFUL;
  1195. }
  1196. }
  1197. if (NT_SUCCESS(Status)) {
  1198. Status = RtlQueryProcessDebugInformation((HANDLE)LongToHandle(th32ProcessID),
  1199. RTL_QUERY_PROCESS_HEAP_SUMMARY,
  1200. *RawDebugInfo);
  1201. }
  1202. }
  1203. if (!NT_SUCCESS(Status)) {
  1204. if (*RawProcess) {
  1205. SIZE_T Size = 0;
  1206. NtFreeVirtualMemory(NtCurrentProcess(),
  1207. RawProcess,
  1208. &Size,
  1209. MEM_RELEASE);
  1210. *RawProcess = NULL;
  1211. }
  1212. if (*RawModule) {
  1213. RtlDestroyQueryDebugBuffer(*RawModule);
  1214. *RawModule = NULL;
  1215. }
  1216. if (*RawDebugInfo) {
  1217. RtlDestroyQueryDebugBuffer(*RawDebugInfo);
  1218. *RawDebugInfo = NULL;
  1219. }
  1220. }
  1221. return Status;
  1222. }
  1223. NTSTATUS
  1224. ThpAllocateSnapshotSection(
  1225. OUT PHANDLE SnapSection,
  1226. IN DWORD dwFlags,
  1227. IN DWORD th32ProcessID,
  1228. PUCHAR RawProcess,
  1229. PRTL_DEBUG_INFORMATION RawModule,
  1230. PRTL_DEBUG_INFORMATION RawDebugInfo)
  1231. /*++
  1232. Routine Description:
  1233. This function calculates the size of the snapshot and allocates a
  1234. file mapping object for it in the pagefile.
  1235. Also, initialize snapshot information in the header
  1236. Arguments:
  1237. th32ProcessID - Supplies a WIN32 process ID. See CreateToolhelp32Snapshot
  1238. for full description.
  1239. dwFlags - Supplies switches describing requested data. See
  1240. CreateToolhelp32Snapshot for full description.
  1241. th32ProcessID -
  1242. RawProcess -
  1243. RawDebugInfo -
  1244. Return Value:
  1245. Handle to to the mapping object if successful, -1 otherwise
  1246. --*/
  1247. {
  1248. NTSTATUS Status = 0;
  1249. PSNAPSHOTSTATE SnapshotBase;
  1250. SECURITY_ATTRIBUTES SecurityAttributes;
  1251. LPSECURITY_ATTRIBUTES lpSecurityAttributes;
  1252. ULONG SnapShotSize;
  1253. ULONG Offset1;
  1254. PSYSTEM_PROCESS_INFORMATION ProcessInfo;
  1255. OBJECT_ATTRIBUTES Obja;
  1256. POBJECT_ATTRIBUTES pObja;
  1257. LARGE_INTEGER SectionOffset;
  1258. LARGE_INTEGER SectionSize;
  1259. SIZE_T ViewSize;
  1260. SIZE_T Size;
  1261. ULONG ProcessCount = 0;
  1262. ULONG HeapListCount = 0;
  1263. ULONG ModuleCount = 0;
  1264. ULONG ThreadCount = 0;
  1265. SnapShotSize = sizeof(SNAPSHOTSTATE);
  1266. Offset1 = 0;
  1267. //
  1268. // calculate the required snapshot size
  1269. //
  1270. if ((dwFlags & TH32CS_SNAPPROCESS) || (dwFlags & TH32CS_SNAPTHREAD)) {
  1271. do {
  1272. ProcessCount++;
  1273. ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)&RawProcess[Offset1];
  1274. Offset1 += ProcessInfo->NextEntryOffset;
  1275. ThreadCount += ProcessInfo->NumberOfThreads;
  1276. } while (ProcessInfo->NextEntryOffset != 0);
  1277. if (dwFlags & TH32CS_SNAPPROCESS) {
  1278. SnapShotSize += ProcessCount * sizeof(PROCESSENTRY32W);
  1279. }
  1280. if (dwFlags & TH32CS_SNAPTHREAD) {
  1281. SnapShotSize += ThreadCount * sizeof(THREADENTRY32);
  1282. }
  1283. }
  1284. if (dwFlags & TH32CS_SNAPMODULE) {
  1285. SnapShotSize += RawModule->Modules->NumberOfModules * sizeof(MODULEENTRY32W);
  1286. ModuleCount = RawModule->Modules->NumberOfModules;
  1287. }
  1288. if (dwFlags & TH32CS_SNAPHEAPLIST) {
  1289. SnapShotSize += RawDebugInfo->Heaps->NumberOfHeaps * sizeof(HEAPLIST32);
  1290. HeapListCount = RawDebugInfo->Heaps->NumberOfHeaps;
  1291. }
  1292. //
  1293. // Create a security object if needed
  1294. //
  1295. if (dwFlags & TH32CS_INHERIT) {
  1296. SecurityAttributes.lpSecurityDescriptor = NULL;
  1297. SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
  1298. SecurityAttributes.bInheritHandle = TRUE;
  1299. lpSecurityAttributes = &SecurityAttributes;
  1300. } else {
  1301. lpSecurityAttributes = NULL;
  1302. }
  1303. //
  1304. // create a pagefile section to contain the snapshot
  1305. //
  1306. pObja = BaseFormatObjectAttributes(&Obja, lpSecurityAttributes, NULL);
  1307. SectionSize.LowPart = SnapShotSize;
  1308. SectionSize.HighPart = 0;
  1309. Status = NtCreateSection(SnapSection,
  1310. STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE,
  1311. pObja,
  1312. &SectionSize,
  1313. PAGE_READWRITE,
  1314. SEC_COMMIT,
  1315. NULL);
  1316. if ( !NT_SUCCESS(Status) ) {
  1317. return Status;
  1318. }
  1319. SectionOffset.LowPart = 0;
  1320. SectionOffset.HighPart = 0;
  1321. ViewSize = 0;
  1322. SnapshotBase = 0;
  1323. Status = NtMapViewOfSection(*SnapSection,
  1324. NtCurrentProcess(),
  1325. &SnapshotBase,
  1326. 0L,
  1327. 0L,
  1328. &SectionOffset,
  1329. &ViewSize,
  1330. ViewShare,
  1331. 0L,
  1332. PAGE_READWRITE);
  1333. //
  1334. // free all memory if failure
  1335. //
  1336. if ( !NT_SUCCESS(Status) ) {
  1337. CloseHandle(*SnapSection);
  1338. if ((dwFlags & TH32CS_SNAPTHREAD) || (dwFlags & TH32CS_SNAPPROCESS)){
  1339. Size = 0;
  1340. NtFreeVirtualMemory(NtCurrentProcess(),
  1341. &RawProcess,
  1342. &Size,
  1343. MEM_RELEASE);
  1344. }
  1345. if (dwFlags & TH32CS_SNAPPROCESS) {
  1346. RtlDestroyQueryDebugBuffer(RawModule);
  1347. }
  1348. if (dwFlags & TH32CS_SNAPHEAPLIST) {
  1349. RtlDestroyQueryDebugBuffer(RawDebugInfo);
  1350. }
  1351. return Status;
  1352. }
  1353. SnapshotBase->ProcessCount = ProcessCount;
  1354. SnapshotBase->HeapListCount = HeapListCount;
  1355. SnapshotBase->ModuleCount = ModuleCount;
  1356. SnapshotBase->ThreadCount = ThreadCount;
  1357. //
  1358. // return resources
  1359. //
  1360. NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)SnapshotBase);
  1361. return STATUS_SUCCESS;
  1362. }
  1363. NTSTATUS
  1364. ThpCopyAnsiToUnicode(
  1365. PWCHAR Dest,
  1366. PUCHAR Src,
  1367. USHORT Max)
  1368. {
  1369. UNICODE_STRING UnicodeString;
  1370. ANSI_STRING AnsiString;
  1371. UnicodeString.Buffer = Dest;
  1372. UnicodeString.MaximumLength = Max;
  1373. RtlInitAnsiString(&AnsiString, Src);
  1374. return RtlAnsiStringToUnicodeString( &UnicodeString, &AnsiString, FALSE );
  1375. }
  1376. NTSTATUS
  1377. ThpProcessToSnap(
  1378. IN DWORD dwFlags,
  1379. IN DWORD th32ProcessID,
  1380. IN HANDLE SnapSection,
  1381. PUCHAR RawProcess,
  1382. PRTL_DEBUG_INFORMATION RawModule,
  1383. PRTL_DEBUG_INFORMATION RawDebugInfo)
  1384. /*++
  1385. Routine Description:
  1386. This function processes the data in the raw dumps specified by dwFlage into
  1387. a mapped file.
  1388. Arguments:
  1389. dwFlags - Supplies switches describing the data requested. See
  1390. CreateToolhelp32Snapshot for full description.
  1391. th32ProcessID - Supplies a WIN32 process ID. See CreateToolhelp32Snapshot
  1392. for full description.
  1393. SnapSection - Supplies handle to section allocated by ThpAllocateSnapshotSection.
  1394. RawProcess -
  1395. RawDebugInfo -
  1396. Return Value:
  1397. TRUE if successful, FALSE if there was a problem encountered
  1398. --*/
  1399. {
  1400. PSNAPSHOTSTATE SnapshotBase;
  1401. PUCHAR BufferWriteAddr; /* working pointer into out process data - usually points at end */
  1402. LARGE_INTEGER SectionOffset;
  1403. SIZE_T ViewSize;
  1404. NTSTATUS Status = 0;
  1405. SIZE_T Size;
  1406. SectionOffset.LowPart = 0;
  1407. SectionOffset.HighPart = 0;
  1408. ViewSize = 0;
  1409. SnapshotBase = 0;
  1410. Status = NtMapViewOfSection(SnapSection,
  1411. NtCurrentProcess(),
  1412. &SnapshotBase,
  1413. 0L,
  1414. 0L,
  1415. &SectionOffset,
  1416. &ViewSize,
  1417. ViewShare,
  1418. 0L,
  1419. PAGE_READWRITE);
  1420. if (!NT_SUCCESS(Status)) {
  1421. return Status;
  1422. }
  1423. BufferWriteAddr = &SnapshotBase->DataBegin;
  1424. //
  1425. // write heap list to snapshot
  1426. // some of this code adapted from dh.c
  1427. //
  1428. if (dwFlags & TH32CS_SNAPHEAPLIST) {
  1429. ULONG HeapListCount = 0;
  1430. ULONG HeapEntryCount = 0;
  1431. LPHEAPLIST32 pHeapList;
  1432. SnapshotBase->HeapListHead = (PHEAPLIST32)(BufferWriteAddr - (PUCHAR)SnapshotBase);
  1433. pHeapList = (LPHEAPLIST32)BufferWriteAddr;
  1434. // heaplist
  1435. for (HeapListCount = 0; HeapListCount < SnapshotBase->HeapListCount; HeapListCount++){
  1436. pHeapList->dwSize = sizeof(HEAPLIST32);
  1437. pHeapList->th32ProcessID = th32ProcessID;
  1438. /* handle = baseaddress = ID we will use internally */
  1439. pHeapList->th32HeapID = (ULONG_PTR)RawDebugInfo->Heaps->Heaps[HeapListCount].BaseAddress;
  1440. pHeapList->dwFlags = RawDebugInfo->Heaps->Heaps[HeapListCount].Flags;
  1441. ++pHeapList;
  1442. }
  1443. // update the pointer to the write area
  1444. BufferWriteAddr = (PCHAR)(BufferWriteAddr + HeapListCount * sizeof(HEAPLIST32));
  1445. RtlDestroyQueryDebugBuffer(RawDebugInfo);
  1446. }
  1447. //
  1448. // write module list to snapshot
  1449. //
  1450. if (dwFlags & TH32CS_SNAPMODULE) {
  1451. LPMODULEENTRY32W pModule;
  1452. ULONG Offset1 = 0;
  1453. ULONG mCount = 0;
  1454. PRTL_PROCESS_MODULE_INFORMATION ModuleInfo;
  1455. SnapshotBase->ModuleListHead = (PMODULEENTRY32W)(BufferWriteAddr - (PUCHAR)SnapshotBase);
  1456. //
  1457. // get module info from buffer
  1458. //
  1459. pModule = (LPMODULEENTRY32W)(BufferWriteAddr);
  1460. ModuleInfo = &RawModule->Modules->Modules[ 0 ];
  1461. for (mCount = 0; mCount < RawModule->Modules->NumberOfModules; mCount++) {
  1462. pModule->dwSize = sizeof(MODULEENTRY32W);
  1463. pModule->th32ProcessID = th32ProcessID;
  1464. //
  1465. // base == handle
  1466. //
  1467. pModule->hModule = ModuleInfo->ImageBase;
  1468. //
  1469. // Base address of module in th32ProcessID's context
  1470. //
  1471. pModule->modBaseAddr = ModuleInfo->ImageBase;
  1472. //
  1473. // Path
  1474. //
  1475. ThpCopyAnsiToUnicode(pModule->szExePath,
  1476. ModuleInfo->FullPathName,
  1477. sizeof(pModule->szExePath));
  1478. //
  1479. // module name
  1480. //
  1481. ThpCopyAnsiToUnicode(pModule->szModule,
  1482. &ModuleInfo->FullPathName[ModuleInfo->OffsetToFileName],
  1483. sizeof(pModule->szModule));
  1484. //
  1485. // Size in bytes of module starting at modBaseAddr
  1486. //
  1487. pModule->modBaseSize = ModuleInfo->ImageSize;
  1488. //
  1489. // these are meaningless on NT
  1490. // but some apps may care... Gruntz (bugid 327009)
  1491. // was failing because th32ModuleID was 0, so
  1492. // now we stick in the address of the Module descriptor
  1493. //
  1494. // However it turns out that a pointer doesn't fit in a DWORD,
  1495. // so we stick in the value 1 instead.
  1496. //
  1497. pModule->th32ModuleID = 1;
  1498. pModule->GlblcntUsage = ModuleInfo->LoadCount; // will be 0xffff
  1499. pModule->ProccntUsage = ModuleInfo->LoadCount; // will be 0xffff
  1500. ++ModuleInfo;
  1501. ++pModule;
  1502. }
  1503. //
  1504. // update the pointer to the write area
  1505. //
  1506. BufferWriteAddr = (PCHAR)(BufferWriteAddr + mCount * sizeof(MODULEENTRY32W));
  1507. RtlDestroyQueryDebugBuffer(RawModule);
  1508. }
  1509. //
  1510. // write process list to snapshot
  1511. //
  1512. if (dwFlags & TH32CS_SNAPPROCESS) {
  1513. PSYSTEM_PROCESS_INFORMATION ProcessInfo;
  1514. LPPROCESSENTRY32W pEntry;
  1515. ULONG cProcess = 0;
  1516. ULONG Offset1 = 0;
  1517. SnapshotBase->ProcessListHead = (PPROCESSENTRY32W)(BufferWriteAddr - (PUCHAR)SnapshotBase);
  1518. pEntry = (LPPROCESSENTRY32W)(BufferWriteAddr + cProcess * sizeof(PROCESSENTRY32W));
  1519. do {
  1520. /* get process info from buffer */
  1521. ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)&RawProcess[Offset1];
  1522. pEntry->dwSize = sizeof(PROCESSENTRY32W);
  1523. pEntry->th32ProcessID = HandleToUlong(ProcessInfo->UniqueProcessId);
  1524. pEntry->pcPriClassBase = ProcessInfo->BasePriority;
  1525. pEntry->cntThreads = ProcessInfo->NumberOfThreads;
  1526. pEntry->th32ParentProcessID = HandleToUlong(ProcessInfo->InheritedFromUniqueProcessId);
  1527. pEntry->cntUsage = 0;
  1528. pEntry->th32DefaultHeapID = 0;
  1529. pEntry->th32ModuleID = 0;
  1530. pEntry->dwFlags = 0;
  1531. // Path
  1532. if (ProcessInfo->ImageName.Buffer == NULL) {
  1533. lstrcpyW(pEntry->szExeFile, L"[System Process]");
  1534. } else {
  1535. if (ProcessInfo->ImageName.Length >= ARRAYSIZE(pEntry->szExeFile)) {
  1536. ProcessInfo->ImageName.Length = ARRAYSIZE(pEntry->szExeFile)-1;
  1537. }
  1538. memcpy(pEntry->szExeFile, ProcessInfo->ImageName.Buffer, ProcessInfo->ImageName.Length);
  1539. pEntry->szExeFile[ProcessInfo->ImageName.Length] = TEXT('\0');
  1540. }
  1541. Offset1 += ProcessInfo->NextEntryOffset;
  1542. ++cProcess;
  1543. ++pEntry;
  1544. } while (ProcessInfo->NextEntryOffset != 0);
  1545. // update the pointer to the write area
  1546. BufferWriteAddr = (PCHAR)(BufferWriteAddr + cProcess * sizeof(PROCESSENTRY32W));
  1547. }
  1548. //
  1549. // write thread list to snapshot
  1550. //
  1551. if (dwFlags & TH32CS_SNAPTHREAD) {
  1552. PSYSTEM_PROCESS_INFORMATION ProcessInfo;
  1553. PSYSTEM_THREAD_INFORMATION ThreadInfo;
  1554. LPTHREADENTRY32 tEntry;
  1555. ULONG Offset1 = 0;
  1556. ULONG cThread = 0;
  1557. SnapshotBase->ThreadListHead = (PTHREADENTRY32)(BufferWriteAddr - (PUCHAR)SnapshotBase);
  1558. tEntry = (LPTHREADENTRY32)(BufferWriteAddr + cThread * sizeof(THREADENTRY32));
  1559. do {
  1560. ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)&RawProcess[Offset1];
  1561. ThreadInfo = (PSYSTEM_THREAD_INFORMATION)(ProcessInfo + 1);
  1562. for (cThread = 0; cThread < ProcessInfo->NumberOfThreads; cThread++) {
  1563. tEntry->dwSize = sizeof(THREADENTRY32);
  1564. tEntry->th32ThreadID = HandleToUlong(ThreadInfo->ClientId.UniqueThread);
  1565. tEntry->th32OwnerProcessID = HandleToUlong(ThreadInfo->ClientId.UniqueProcess);
  1566. tEntry->tpBasePri = ThreadInfo->BasePriority;
  1567. tEntry->tpDeltaPri = 0;
  1568. tEntry->cntUsage = 0;
  1569. tEntry->dwFlags = 0;
  1570. ++ThreadInfo;
  1571. ++tEntry;
  1572. }
  1573. Offset1 += ProcessInfo->NextEntryOffset;
  1574. } while (ProcessInfo->NextEntryOffset != 0);
  1575. BufferWriteAddr = (PUCHAR)(BufferWriteAddr + cThread * sizeof(THREADENTRY32)); // update the pointer to the write area
  1576. }
  1577. if ((dwFlags & TH32CS_SNAPTHREAD) || (dwFlags & TH32CS_SNAPPROCESS)){
  1578. Size = 0;
  1579. NtFreeVirtualMemory(NtCurrentProcess(),
  1580. &RawProcess,
  1581. &Size,
  1582. MEM_RELEASE);
  1583. }
  1584. NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)SnapshotBase);
  1585. return STATUS_SUCCESS;
  1586. }