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.

1086 lines
28 KiB

  1. /*++ BUILD Version: 0001 // Increment this if a change has global effects
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. prflibva.c
  5. Abstract:
  6. Virtual address space counter evaluation routines
  7. computes the process and image virtual address space usage for return
  8. via Perfmon API
  9. Author:
  10. Stolen from the "internal" PVIEW SDK program and adapted for Perfmon by:
  11. a-robw (Bob Watson) 11/29/92
  12. Revision History:
  13. --*/
  14. //
  15. // define routine's "personality"
  16. //
  17. #define UNICODE 1
  18. //
  19. // Include files
  20. //
  21. #include <assert.h>
  22. #include <stdio.h>
  23. #include <string.h>
  24. #include <memory.h>
  25. #include <nt.h>
  26. #include <ntrtl.h>
  27. #include <nturtl.h>
  28. #include <windows.h>
  29. #include <winperf.h>
  30. #include <perfutil.h>
  31. #include "perfsprc.h"
  32. #define DEFAULT_INCR (64*1024)
  33. #ifdef _WIN64
  34. #define STOP_AT (PVOID)(0xFFFFFFFF80000000)
  35. #else
  36. #define STOP_AT (PVOID)(0x80000000)
  37. #endif
  38. // Function Prototypes
  39. PPROCESS_VA_INFO
  40. GetProcessVaData (
  41. IN PSYSTEM_PROCESS_INFORMATION
  42. );
  43. PMODINFO
  44. GetModuleVaData (
  45. PLDR_DATA_TABLE_ENTRY, // module information structure
  46. PPROCESS_VA_INFO // process data structure
  47. );
  48. BOOL
  49. FreeProcessVaData (
  50. IN PPROCESS_VA_INFO
  51. );
  52. BOOL
  53. FreeModuleVaData (
  54. IN PMODINFO
  55. );
  56. PMODINFO
  57. LocateModInfo(
  58. IN PMODINFO,
  59. IN PVOID,
  60. IN SIZE_T
  61. );
  62. DWORD
  63. ProtectionToIndex(
  64. IN ULONG
  65. );
  66. DWORD dwProcessCount;
  67. DWORD dwModuleCount;
  68. PPROCESS_VA_INFO
  69. GetSystemVaData (
  70. IN PSYSTEM_PROCESS_INFORMATION pFirstProcess
  71. )
  72. /*++
  73. GetSystemVaData
  74. Obtains the Process and Image Virtual Address information for all
  75. processes running on the system. (note that the routines called by
  76. this function allocate data structures consequently the corresponding
  77. FreeSystemVaData must be called to prevent memory "leaks")
  78. Arguments
  79. IN PSYSTEM_PROCESS_INFORMATION
  80. pFirstProcess
  81. Pointer to first process in list of process structures returned
  82. by NtQuerySystemInformation service
  83. Return Value
  84. Pointer to first process in list of processes
  85. or NULL if unable to obtain data
  86. --*/
  87. {
  88. PSYSTEM_PROCESS_INFORMATION pThisProcess;
  89. PPROCESS_VA_INFO pReturnValue = NULL;
  90. PPROCESS_VA_INFO pLastProcess;
  91. PPROCESS_VA_INFO pNewProcess;
  92. DWORD dwStartTime;
  93. BOOL bMoreProcesses;
  94. dwProcessCount = 0;
  95. dwModuleCount = 0;
  96. if (pFirstProcess != NULL) {
  97. pThisProcess = pFirstProcess;
  98. pLastProcess = NULL;
  99. bMoreProcesses = TRUE;
  100. while ( bMoreProcesses ) { // loop exit is at bottom of loop
  101. dwStartTime = GetTickCount ();
  102. pNewProcess = GetProcessVaData(
  103. pThisProcess); // pointer to process Info structure
  104. if (pNewProcess) { // process data found OK
  105. pNewProcess->LookUpTime = GetTickCount() - dwStartTime;
  106. dwProcessCount++;
  107. if (!pLastProcess) { // this is the first process returned
  108. pReturnValue = pNewProcess; // save return value here
  109. } else {
  110. pLastProcess->pNextProcess = pNewProcess;
  111. }
  112. pLastProcess = pNewProcess;
  113. }
  114. if ( pThisProcess->NextEntryOffset == 0 ) {
  115. bMoreProcesses = FALSE; // this is the last entry
  116. } else { // point to the next process info structure
  117. pThisProcess = (PSYSTEM_PROCESS_INFORMATION)
  118. ((PBYTE)pThisProcess + pThisProcess->NextEntryOffset);
  119. }
  120. }
  121. return pReturnValue; // return pointer to first list entry
  122. } else {
  123. return NULL;
  124. }
  125. }
  126. PPROCESS_VA_INFO
  127. GetProcessVaData (
  128. IN PSYSTEM_PROCESS_INFORMATION pProcess
  129. )
  130. /*++
  131. GetProcessVaData
  132. Gets the Virtual Memory usage details for the process passed in the
  133. argument list. Collects the data for all images in use by the process.
  134. Note that this routine allocates data structures that must be freed
  135. (using the FreeProcessVaData routine) when finished with them.
  136. Arguments
  137. IN HANDLE hProcess
  138. handle to the process to collect data for
  139. Return Value
  140. Pointer to completed Process VA info structure or
  141. NULL if unable to collect data
  142. --*/
  143. {
  144. NTSTATUS Status;
  145. HANDLE hProcess;
  146. PPROCESS_VA_INFO pThisProcess;
  147. PPEB pPeb;
  148. PPEB_LDR_DATA Ldr;
  149. PLIST_ENTRY LdrHead, LdrNext;
  150. LDR_DATA_TABLE_ENTRY LdrEntryData, *pLdrEntry;
  151. PMODINFO pNewModule, pLastModule;
  152. PVOID pBaseAddress;
  153. MEMORY_BASIC_INFORMATION VaBasicInfo;
  154. DWORD dwProtection;
  155. PMODINFO pMod;
  156. SIZE_T dwRegionSize;
  157. OBJECT_ATTRIBUTES obProcess;
  158. CLIENT_ID ClientId;
  159. PUNICODE_STRING pProcessNameBuffer;
  160. // get handle to process
  161. ClientId.UniqueThread = (HANDLE)NULL;
  162. ClientId.UniqueProcess = pProcess->UniqueProcessId;
  163. InitializeObjectAttributes(
  164. &obProcess,
  165. NULL,
  166. 0,
  167. NULL,
  168. NULL
  169. );
  170. Status = NtOpenProcess(
  171. &hProcess,
  172. (ACCESS_MASK)PROCESS_ALL_ACCESS,
  173. &obProcess,
  174. &ClientId);
  175. if (! NT_SUCCESS(Status)){
  176. // unable to open the process, but still want to
  177. // create pThisProcess so we will not mess up
  178. // the process sequence.
  179. hProcess = 0;
  180. // return NULL; // unable to open process
  181. }
  182. // allocate structure
  183. pThisProcess = ALLOCMEM (
  184. hLibHeap,
  185. HEAP_ZERO_MEMORY,
  186. sizeof (PROCESS_VA_INFO));
  187. if (pThisProcess) { // allocation successful
  188. // initialize fields
  189. pThisProcess->BasicInfo = ALLOCMEM (
  190. hLibHeap,
  191. HEAP_ZERO_MEMORY,
  192. sizeof (PROCESS_BASIC_INFORMATION));
  193. if (!pThisProcess->BasicInfo) {
  194. // Bailout if unable to allocate memory
  195. goto PBailOut;
  196. }
  197. // zero process counters
  198. pThisProcess->MappedGuard = 0;
  199. pThisProcess->PrivateGuard = 0;
  200. pThisProcess->ImageReservedBytes = 0;
  201. pThisProcess->ImageFreeBytes = 0;
  202. pThisProcess->ReservedBytes = 0;
  203. pThisProcess->FreeBytes = 0;
  204. // get process short name from Process Info Structure
  205. // alloc a new buffer since GetProcessShortName reuses the name
  206. // buffer
  207. pThisProcess->pProcessName = ALLOCMEM (hLibHeap,
  208. HEAP_ZERO_MEMORY, (sizeof(UNICODE_STRING) + MAX_PROCESS_NAME_LENGTH));
  209. if (pThisProcess->pProcessName != NULL) {
  210. pThisProcess->pProcessName->Length = 0;
  211. pThisProcess->pProcessName->MaximumLength = MAX_PROCESS_NAME_LENGTH;
  212. pThisProcess->pProcessName->Buffer = (PWSTR)(&pThisProcess->pProcessName[1]);
  213. if (lProcessNameCollectionMethod == PNCM_MODULE_FILE) {
  214. pProcessNameBuffer = GetProcessSlowName (pProcess);
  215. } else {
  216. pProcessNameBuffer = GetProcessShortName (pProcess);
  217. }
  218. RtlCopyUnicodeString (pThisProcess->pProcessName,
  219. pProcessNameBuffer);
  220. } else {
  221. pThisProcess->pProcessName = NULL;
  222. }
  223. pThisProcess->dwProcessId = HandleToUlong(pProcess->UniqueProcessId);
  224. pThisProcess->hProcess = hProcess;
  225. // zero list pointers
  226. pThisProcess->pMemBlockInfo = NULL;
  227. pThisProcess->pNextProcess = NULL;
  228. if (hProcess) {
  229. Status = NtQueryInformationProcess (
  230. hProcess,
  231. ProcessBasicInformation,
  232. pThisProcess->BasicInfo,
  233. sizeof (PROCESS_BASIC_INFORMATION),
  234. NULL);
  235. if (!NT_SUCCESS(Status)){
  236. // if error reading data, then bail out
  237. goto SuccessExit;
  238. }
  239. // get pointer to the Process Environment Block
  240. pPeb = pThisProcess->BasicInfo->PebBaseAddress;
  241. // read address of loader information structure
  242. Status = NtReadVirtualMemory (
  243. hProcess,
  244. &pPeb->Ldr,
  245. &Ldr,
  246. sizeof (Ldr),
  247. NULL);
  248. // bail out if unable to read information
  249. if (!NT_SUCCESS(Status)){
  250. // if error reading data, then bail out
  251. goto SuccessExit;
  252. }
  253. //
  254. // get head pointer to linked list of memory modules used by
  255. // this process
  256. //
  257. LdrHead = &Ldr->InMemoryOrderModuleList;
  258. // Get address of next list entry
  259. Status = NtReadVirtualMemory (
  260. hProcess,
  261. &LdrHead->Flink,
  262. &LdrNext,
  263. sizeof (LdrNext),
  264. NULL);
  265. // bail out if unable to read information
  266. if (!NT_SUCCESS(Status)){
  267. // if error reading data, then bail out
  268. goto SuccessExit;
  269. }
  270. pLastModule = NULL;
  271. // walk down the list of modules until back at the top.
  272. // to list all the images in use by this process
  273. while ( LdrNext != LdrHead ) {
  274. // get record attached to list entry
  275. pLdrEntry = CONTAINING_RECORD(LdrNext,
  276. LDR_DATA_TABLE_ENTRY,
  277. InMemoryOrderLinks);
  278. Status = NtReadVirtualMemory(
  279. hProcess,
  280. pLdrEntry,
  281. &LdrEntryData,
  282. sizeof(LdrEntryData),
  283. NULL
  284. );
  285. // if unable to read memory, then give up rest of search
  286. // and return what we have already.
  287. if ( !NT_SUCCESS(Status) ) {
  288. goto SuccessExit;
  289. }
  290. pNewModule = GetModuleVaData (
  291. &LdrEntryData,
  292. pThisProcess);
  293. if (pNewModule) { // if structure returned...
  294. dwModuleCount++;
  295. if (!pLastModule) { // if this is the first module...
  296. // then set list head pointer
  297. pThisProcess->pMemBlockInfo = pNewModule;
  298. } else {
  299. // otherwise link to list
  300. pLastModule->pNextModule = pNewModule;
  301. }
  302. pLastModule = pNewModule;
  303. }
  304. LdrNext = LdrEntryData.InMemoryOrderLinks.Flink;
  305. } // end while not at end of list
  306. // now that we have a list of all images, query the process'
  307. // virtual memory for the list of memory blocks in use by this
  308. // process and assign them to the appropriate category of memory
  309. pBaseAddress = NULL; // start at 0 and go to end of User VA space
  310. while (pBaseAddress < STOP_AT) { // truncate to 32-bit if necessary
  311. Status = NtQueryVirtualMemory (
  312. hProcess,
  313. pBaseAddress,
  314. MemoryBasicInformation,
  315. &VaBasicInfo,
  316. sizeof(VaBasicInfo),
  317. NULL);
  318. if (!NT_SUCCESS(Status)) {
  319. goto SuccessExit;
  320. } else {
  321. // get protection type for index into counter array
  322. dwRegionSize = VaBasicInfo.RegionSize;
  323. switch (VaBasicInfo.State) {
  324. case MEM_COMMIT:
  325. // if the memory is for an IMAGE, then search the image list
  326. // for the corresponding image to update
  327. dwProtection = ProtectionToIndex(VaBasicInfo.Protect);
  328. if (VaBasicInfo.Type == MEM_IMAGE) {
  329. // update process total
  330. pThisProcess->MemTotals.CommitVector[dwProtection] += dwRegionSize;
  331. pMod = LocateModInfo (pThisProcess->pMemBlockInfo, pBaseAddress, dwRegionSize);
  332. if (pMod) { // if matching image found, then update
  333. pMod->CommitVector[dwProtection] += dwRegionSize;
  334. pMod->TotalCommit += dwRegionSize;
  335. } else { // otherwise update orphan total
  336. pThisProcess->OrphanTotals.CommitVector[dwProtection] += dwRegionSize;
  337. }
  338. } else {
  339. // if not assigned to an image, then update the process
  340. // counters
  341. if (VaBasicInfo.Type == MEM_MAPPED) {
  342. pThisProcess->MappedCommit[dwProtection] += dwRegionSize;
  343. } else {
  344. pThisProcess->PrivateCommit[dwProtection] += dwRegionSize;
  345. }
  346. }
  347. break;
  348. case MEM_RESERVE:
  349. if (VaBasicInfo.Type == MEM_IMAGE) {
  350. pThisProcess->ImageReservedBytes += dwRegionSize;
  351. } else {
  352. pThisProcess->ReservedBytes += dwRegionSize;
  353. }
  354. break;
  355. case MEM_FREE:
  356. if (VaBasicInfo.Type == MEM_IMAGE) {
  357. pThisProcess->ImageFreeBytes += dwRegionSize;
  358. } else {
  359. pThisProcess->FreeBytes += dwRegionSize;
  360. }
  361. break;
  362. default:
  363. break;
  364. } // end switch (VaBasicInfo.State)
  365. } // endif QueryVM ok
  366. // go to next memory block
  367. pBaseAddress = (PVOID)((ULONG_PTR)pBaseAddress + dwRegionSize);
  368. } // end whil not at the end of memory
  369. } // endif hProcess not NULL
  370. } // endif pThisProcess not NULL
  371. SuccessExit:
  372. if (hProcess) CloseHandle(hProcess);
  373. return pThisProcess;
  374. //
  375. // error recovery section, called when the routine is unable to
  376. // complete successfully to clean up before leaving
  377. //
  378. PBailOut:
  379. if (pThisProcess->BasicInfo) {
  380. FREEMEM (
  381. hLibHeap,
  382. 0,
  383. pThisProcess->BasicInfo);
  384. }
  385. FREEMEM (
  386. hLibHeap,
  387. 0,
  388. pThisProcess);
  389. if (hProcess) CloseHandle(hProcess);
  390. return NULL;
  391. }
  392. PMODINFO
  393. GetModuleVaData (
  394. PLDR_DATA_TABLE_ENTRY ModuleListEntry, // module information structure
  395. PPROCESS_VA_INFO pProcess // process data structure
  396. )
  397. /*++
  398. GetModuleVaData
  399. Gets the Virtual Memory usage details for the module pointed to by the
  400. Process Memory Module List Entry argument in the argument list
  401. Note that this routine allocates data structures that must be freed
  402. (using the FreeModuleVaData routine) when finished with them.
  403. Arguments
  404. IN HANDLE ModuleListEntry
  405. Return Value
  406. Pointer to completed Module VA info structure or
  407. NULL if unable to collect data
  408. --*/
  409. {
  410. PMODINFO pThisModule = NULL; // module structure that is returned
  411. PUNICODE_STRING pusInstanceName = NULL; // process->image
  412. PUNICODE_STRING pusLongInstanceName = NULL; // process->fullimagepath
  413. UNICODE_STRING usImageFileName = {0,0, NULL}; // image file name
  414. UNICODE_STRING usExeFileName = {0,0, NULL}; // short name
  415. UNICODE_STRING usNtFileName = {0,0, NULL}; // full Nt File Name
  416. PWCHAR p,p1;
  417. PWCHAR ImageNameBuffer = NULL;
  418. NTSTATUS Status;
  419. HANDLE hFile;
  420. HANDLE hMappedFile;
  421. WORD wStringSize;
  422. PVOID MappedAddress;
  423. PVOID MapBase;
  424. SIZE_T dwMappedSize;
  425. PIMAGE_DOS_HEADER DosHeader;
  426. PIMAGE_NT_HEADERS FileHeader;
  427. LARGE_INTEGER liSectionSize;
  428. PLARGE_INTEGER pliSectionSize;
  429. LARGE_INTEGER liSectionOffset;
  430. OBJECT_ATTRIBUTES obFile;
  431. IO_STATUS_BLOCK IoStatusBlock;
  432. BOOL bRetCode;
  433. USHORT wBufOffset;
  434. USHORT wDiffSize;
  435. // allocate this item's memory
  436. pThisModule = ALLOCMEM (
  437. hLibHeap,
  438. HEAP_ZERO_MEMORY,
  439. sizeof (MODINFO));
  440. if (!pThisModule) {
  441. return NULL;
  442. }
  443. // allocate this items Instance Name Buffer
  444. wStringSize = (WORD)(ModuleListEntry->BaseDllName.MaximumLength +
  445. sizeof (UNICODE_NULL));
  446. pusInstanceName = ALLOCMEM (
  447. hLibHeap,
  448. HEAP_ZERO_MEMORY,
  449. wStringSize + sizeof(UNICODE_STRING)) ;
  450. if (!pusInstanceName) {
  451. goto MBailOut;
  452. }
  453. pusInstanceName->Length = 0;
  454. pusInstanceName->MaximumLength = wStringSize;
  455. pusInstanceName->Buffer = (PWCHAR)&pusInstanceName[1];
  456. // save instance name using full file path
  457. wStringSize = (WORD)(ModuleListEntry->FullDllName.MaximumLength +
  458. sizeof (UNICODE_NULL));
  459. pusLongInstanceName = ALLOCMEM (
  460. hLibHeap,
  461. HEAP_ZERO_MEMORY,
  462. wStringSize + sizeof (UNICODE_STRING));
  463. if (!pusLongInstanceName) {
  464. goto MBailOut;
  465. }
  466. pusLongInstanceName->Length = 0;
  467. pusLongInstanceName->MaximumLength = wStringSize;
  468. pusLongInstanceName->Buffer = (PWCHAR)&pusLongInstanceName[1];
  469. // allocate temporary buffer for image name
  470. usImageFileName.Length = ModuleListEntry->FullDllName.Length;
  471. usImageFileName.MaximumLength = ModuleListEntry->FullDllName.MaximumLength;
  472. ImageNameBuffer = usImageFileName.Buffer = ALLOCMEM(
  473. hLibHeap,
  474. HEAP_ZERO_MEMORY,
  475. usImageFileName.MaximumLength);
  476. if ( !usImageFileName.Buffer ) {
  477. goto MBailOut;
  478. }
  479. // allocate temporary buffer for exe name
  480. usExeFileName.Length = ModuleListEntry->BaseDllName.Length;
  481. usExeFileName.MaximumLength = ModuleListEntry->BaseDllName.MaximumLength;
  482. usExeFileName.Buffer = ALLOCMEM(
  483. hLibHeap,
  484. HEAP_ZERO_MEMORY,
  485. usExeFileName.MaximumLength);
  486. if ( !usExeFileName.Buffer ) {
  487. goto MBailOut;
  488. }
  489. // read base .exe/.dll name of image
  490. Status = NtReadVirtualMemory(
  491. pProcess->hProcess,
  492. ModuleListEntry->BaseDllName.Buffer,
  493. usExeFileName.Buffer,
  494. usExeFileName.MaximumLength,
  495. NULL
  496. );
  497. if ( !NT_SUCCESS(Status) ) {
  498. goto MBailOut;
  499. }
  500. // read full name of image
  501. Status = NtReadVirtualMemory(
  502. pProcess->hProcess,
  503. ModuleListEntry->FullDllName.Buffer,
  504. usImageFileName.Buffer,
  505. usImageFileName.MaximumLength,
  506. NULL
  507. );
  508. if ( !NT_SUCCESS(Status) ) {
  509. goto MBailOut;
  510. }
  511. // make a DOS filename to convert to NT again
  512. wDiffSize = wBufOffset = 0;
  513. p = p1 = usImageFileName.Buffer;
  514. while (*p != (WCHAR)0){
  515. if (*p == L':'){
  516. p1 = p;
  517. wDiffSize = wBufOffset;
  518. }
  519. wBufOffset += sizeof(WCHAR);
  520. p++;
  521. }
  522. if (p1 != usImageFileName.Buffer) {
  523. // move pointer
  524. usImageFileName.Buffer = --p1;
  525. // adjust length fields
  526. wDiffSize -= (USHORT)(sizeof(WCHAR));
  527. usImageFileName.Length = usImageFileName.Length - wDiffSize;
  528. usImageFileName.MaximumLength = usImageFileName.MaximumLength - wDiffSize;
  529. }
  530. // Create/copy a NT filename for Nt file operation
  531. bRetCode = RtlDosPathNameToNtPathName_U (
  532. usImageFileName.Buffer,
  533. &usNtFileName,
  534. NULL,
  535. NULL);
  536. if ( !bRetCode ) {
  537. goto MBailOut;
  538. }
  539. // get handle to file
  540. InitializeObjectAttributes(
  541. &obFile,
  542. &usNtFileName,
  543. FILE_ATTRIBUTE_NORMAL | OBJ_CASE_INSENSITIVE,
  544. NULL,
  545. NULL
  546. );
  547. Status = NtCreateFile (
  548. &hFile,
  549. (ACCESS_MASK)GENERIC_READ | SYNCHRONIZE | FILE_READ_ATTRIBUTES,
  550. &obFile,
  551. &IoStatusBlock,
  552. NULL,
  553. FILE_ATTRIBUTE_NORMAL & FILE_ATTRIBUTE_VALID_FLAGS,
  554. FILE_SHARE_READ,
  555. FILE_OPEN,
  556. 0,
  557. NULL,
  558. 0);
  559. if (!NT_SUCCESS(Status)) {
  560. goto MBailOut;
  561. }
  562. pliSectionSize = &liSectionSize;
  563. liSectionSize.HighPart = 0;
  564. liSectionSize.LowPart = 0;
  565. InitializeObjectAttributes (
  566. &obFile,
  567. NULL,
  568. 0,
  569. NULL,
  570. NULL);
  571. Status = NtCreateSection (
  572. &hMappedFile,
  573. SECTION_QUERY | SECTION_MAP_READ,
  574. &obFile,
  575. pliSectionSize,
  576. PAGE_READONLY,
  577. SEC_COMMIT,
  578. hFile);
  579. if ( ! NT_SUCCESS(Status)) {
  580. CloseHandle(hFile);
  581. goto MBailOut;
  582. }
  583. // get pointer to mapped memory
  584. MappedAddress = MapBase = NULL;
  585. dwMappedSize = 0;
  586. liSectionOffset.LowPart = 0;
  587. liSectionOffset.HighPart = 0;
  588. Status = NtMapViewOfSection (
  589. hMappedFile,
  590. NtCurrentProcess(),
  591. &MapBase,
  592. 0L,
  593. 0L,
  594. &liSectionOffset,
  595. &dwMappedSize,
  596. ViewShare,
  597. 0L,
  598. PAGE_READONLY);
  599. CloseHandle(hMappedFile);
  600. if (NT_SUCCESS(Status)) {
  601. MappedAddress = MapBase;
  602. } else {
  603. CloseHandle(hFile);
  604. goto MBailOut;
  605. }
  606. // check for dos image signature (if a dos file)
  607. DosHeader = (PIMAGE_DOS_HEADER)MappedAddress;
  608. if ( DosHeader->e_magic != IMAGE_DOS_SIGNATURE ) {
  609. UnmapViewOfFile(MappedAddress);
  610. CloseHandle(hFile);
  611. goto MBailOut;
  612. }
  613. FileHeader = (PIMAGE_NT_HEADERS)((UINT_PTR)DosHeader + DosHeader->e_lfanew);
  614. if ( FileHeader->Signature != IMAGE_NT_SIGNATURE ) {
  615. UnmapViewOfFile(MappedAddress);
  616. CloseHandle(hFile);
  617. goto MBailOut;
  618. }
  619. // get base address for this module and save in local data structure
  620. pThisModule->BaseAddress = ModuleListEntry->DllBase;
  621. // get image name
  622. RtlCopyUnicodeString (
  623. pusInstanceName,
  624. &usExeFileName);
  625. RtlCopyUnicodeString (
  626. pusLongInstanceName,
  627. &usImageFileName);
  628. pThisModule->InstanceName = pusInstanceName;
  629. pThisModule->LongInstanceName = pusLongInstanceName;
  630. pThisModule->pNextModule = NULL;
  631. pThisModule->TotalCommit = 0;
  632. memset (
  633. &pThisModule->CommitVector[0], 0,
  634. sizeof (pThisModule->CommitVector));
  635. pThisModule->VirtualSize = FileHeader->OptionalHeader.SizeOfImage;
  636. // close file handles
  637. UnmapViewOfFile(MappedAddress);
  638. CloseHandle(hFile);
  639. // free local memory
  640. FREEMEM (
  641. RtlProcessHeap(), // this is allocated by an RTL function
  642. 0,
  643. usNtFileName.Buffer);
  644. // FREEMEM (
  645. // hLibHeap,
  646. // 0,
  647. // RelativeName.RelativeName.Buffer);
  648. FREEMEM (
  649. hLibHeap,
  650. 0,
  651. ImageNameBuffer);
  652. FREEMEM (
  653. hLibHeap,
  654. 0,
  655. usExeFileName.Buffer);
  656. return (pThisModule); // return pointer to completed module structure
  657. //
  658. // Module bail out point, called when the routine is unable to continue
  659. // for some reason. This cleans up any allocated memory, etc.
  660. //
  661. MBailOut:
  662. if (pThisModule) {
  663. FREEMEM (
  664. hLibHeap,
  665. 0,
  666. pThisModule);
  667. }
  668. if (usNtFileName.Buffer) {
  669. FREEMEM (
  670. RtlProcessHeap(), // this is allocated by an RTL function
  671. 0,
  672. usNtFileName.Buffer);
  673. }
  674. // if (RelativeName.RelativeName.Buffer) {
  675. // FREEMEM (
  676. // hLibHeap,
  677. // 0,
  678. // RelativeName.RelativeName.Buffer);
  679. // }
  680. if (pusInstanceName) {
  681. FREEMEM (
  682. hLibHeap,
  683. 0,
  684. pusInstanceName);
  685. }
  686. if (pusLongInstanceName) {
  687. FREEMEM (
  688. hLibHeap,
  689. 0,
  690. pusLongInstanceName);
  691. }
  692. if (ImageNameBuffer) {
  693. FREEMEM (
  694. hLibHeap,
  695. 0,
  696. ImageNameBuffer);
  697. }
  698. if (usExeFileName.Buffer){
  699. FREEMEM (
  700. hLibHeap,
  701. 0,
  702. usExeFileName.Buffer);
  703. }
  704. return NULL;
  705. }
  706. PMODINFO
  707. LocateModInfo(
  708. IN PMODINFO pFirstMod,
  709. IN PVOID pAddress,
  710. IN SIZE_T dwExtent
  711. )
  712. /*++
  713. LocateModInfo
  714. Locates the images associated with the address passed in the argument list
  715. Arguments
  716. IN PMODINFO pFirstMod,
  717. first module entry in process list
  718. IN PVOID Address
  719. Address to search for in list
  720. Return Value
  721. Pointer to matching image or
  722. NULL if no match found
  723. --*/
  724. {
  725. PMODINFO pThisMod;
  726. pThisMod = pFirstMod;
  727. while (pThisMod) { // go to end of list or match is found
  728. // match criteria are:
  729. // address >= Module BaseAddress and
  730. // address+extent between base and base+image_extent
  731. if (pAddress >= pThisMod->BaseAddress) {
  732. if ((PVOID)((PDWORD)pAddress + dwExtent) <=
  733. (PVOID)((ULONG_PTR)pThisMod->BaseAddress+pThisMod->VirtualSize)) {
  734. return (pThisMod);
  735. }
  736. }
  737. pThisMod = pThisMod->pNextModule;
  738. }
  739. return NULL;
  740. }
  741. DWORD
  742. ProtectionToIndex(
  743. IN ULONG Protection
  744. )
  745. /*++
  746. ProtectionToIndex
  747. Determine the memory access protection type and return local code
  748. Arguments
  749. IN ULONG
  750. Protection
  751. Process memory protection mask
  752. Return Value
  753. Local value of protection type
  754. --*/
  755. {
  756. Protection &= (PAGE_NOACCESS |
  757. PAGE_READONLY |
  758. PAGE_READWRITE |
  759. PAGE_WRITECOPY |
  760. PAGE_EXECUTE |
  761. PAGE_EXECUTE_READ |
  762. PAGE_EXECUTE_READWRITE |
  763. PAGE_EXECUTE_WRITECOPY);
  764. switch ( Protection ) {
  765. case PAGE_NOACCESS:
  766. return NOACCESS;
  767. case PAGE_READONLY:
  768. return READONLY;
  769. case PAGE_READWRITE:
  770. return READWRITE;
  771. case PAGE_WRITECOPY:
  772. return WRITECOPY;
  773. case PAGE_EXECUTE:
  774. return EXECUTE;
  775. case PAGE_EXECUTE_READ:
  776. return EXECUTEREAD;
  777. case PAGE_EXECUTE_READWRITE:
  778. return EXECUTEREADWRITE;
  779. case PAGE_EXECUTE_WRITECOPY:
  780. return EXECUTEWRITECOPY;
  781. default:
  782. return 0xFFFFFFFF;
  783. }
  784. }
  785. BOOL
  786. FreeSystemVaData (
  787. IN PPROCESS_VA_INFO pFirstProcess
  788. )
  789. {
  790. PPROCESS_VA_INFO pThisProcess, pNextProcess;
  791. pThisProcess = pFirstProcess;
  792. while (pThisProcess) {
  793. pNextProcess = pThisProcess->pNextProcess; // save pointer to next
  794. FreeProcessVaData (pThisProcess);
  795. pThisProcess = pNextProcess; // do next until NULL pointer
  796. }
  797. return (FALSE);
  798. }
  799. BOOL
  800. FreeProcessVaData (
  801. IN PPROCESS_VA_INFO pProcess
  802. )
  803. {
  804. PMODINFO pThisModule, pNextModule;
  805. if (pProcess) {
  806. if (pProcess->pProcessName) {
  807. FREEMEM (
  808. hLibHeap,
  809. 0,
  810. pProcess->pProcessName);
  811. pProcess->pProcessName = NULL;
  812. }
  813. if (pProcess->BasicInfo) {
  814. FREEMEM (
  815. hLibHeap,
  816. 0,
  817. pProcess->BasicInfo);
  818. pProcess->BasicInfo = NULL;
  819. }
  820. pThisModule = pProcess->pMemBlockInfo;
  821. while (pThisModule) {
  822. pNextModule = pThisModule->pNextModule;
  823. FreeModuleVaData (pThisModule);
  824. pThisModule = pNextModule;
  825. }
  826. //
  827. // and finally throw ourselves away
  828. //
  829. FREEMEM (
  830. hLibHeap,
  831. 0,
  832. pProcess);
  833. }
  834. return FALSE;
  835. }
  836. BOOL
  837. FreeModuleVaData (
  838. IN PMODINFO pModule
  839. )
  840. {
  841. if (pModule) {
  842. if (pModule->InstanceName) {
  843. FREEMEM(
  844. hLibHeap,
  845. 0,
  846. pModule->InstanceName);
  847. pModule->InstanceName = NULL;
  848. }
  849. if (pModule->LongInstanceName) {
  850. FREEMEM(
  851. hLibHeap,
  852. 0,
  853. pModule->LongInstanceName);
  854. pModule->LongInstanceName = NULL;
  855. }
  856. FREEMEM (
  857. hLibHeap,
  858. 0,
  859. pModule);
  860. }
  861. return FALSE;
  862. }