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.

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