1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * LICENSE: See LGPL.txt in the top level directory 4 * PROJECT: ReactOS system libraries 5 * FILE: reactos/lib/epsapi/enum/module.c 6 * PURPOSE: Enumerate process modules 7 * PROGRAMMER: KJK::Hyperion <noog@libero.it> 8 * UPDATE HISTORY: 9 * 10/06/2002: Created 10 * 29/08/2002: Generalized the interface to improve reusability, 11 * more efficient use of memory operations 12 * 12/02/2003: malloc and free renamed to PsaiMalloc and PsaiFree, 13 * for better reusability 14 * 02/04/2003: System modules enumeration moved into its own file 15 * 12/04/2003: internal PSAPI renamed EPSAPI (Extended PSAPI) and 16 * isolated in its own library to clear the confusion 17 * and improve reusability 18 */ 19 20 #include "precomp.h" 21 22 #include <ndk/mmfuncs.h> 23 #include <ndk/psfuncs.h> 24 #include <ndk/rtlfuncs.h> 25 26 #define NDEBUG 27 #include <debug.h> 28 29 NTSTATUS NTAPI 30 PsaEnumerateProcessModules(IN HANDLE ProcessHandle, 31 IN PPROCMOD_ENUM_ROUTINE Callback, 32 IN OUT PVOID CallbackContext) 33 { 34 NTSTATUS Status; 35 36 /* current process - use direct memory copy */ 37 /* FIXME - compare process id instead of a handle */ 38 if(ProcessHandle == NtCurrentProcess()) 39 { 40 PLIST_ENTRY ListHead, Current; 41 42 #if 0 43 __try 44 { 45 #endif 46 ListHead = &(NtCurrentPeb()->Ldr->InLoadOrderModuleList); 47 Current = ListHead->Flink; 48 49 while(Current != ListHead) 50 { 51 PLDR_DATA_TABLE_ENTRY LoaderModule = CONTAINING_RECORD(Current, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); 52 53 /* return the current module to the callback */ 54 Status = Callback(ProcessHandle, LoaderModule, CallbackContext); 55 56 if(!NT_SUCCESS(Status)) 57 { 58 goto Failure; 59 } 60 61 Current = LoaderModule->InLoadOrderLinks.Flink; 62 } 63 #if 0 64 } 65 __except(EXCEPTION_EXECUTE_HANDLER) 66 { 67 return GetExceptionCode(); 68 } 69 #endif 70 } 71 else 72 { 73 PROCESS_BASIC_INFORMATION BasicInformation; 74 PPEB_LDR_DATA LoaderData; 75 LDR_DATA_TABLE_ENTRY LoaderModule; 76 PLIST_ENTRY ListHead, Current; 77 78 /* query the process basic information (includes the PEB address) */ 79 Status = NtQueryInformationProcess(ProcessHandle, 80 ProcessBasicInformation, 81 &BasicInformation, 82 sizeof(BasicInformation), 83 NULL); 84 85 if(!NT_SUCCESS(Status)) 86 { 87 DPRINT(FAILED_WITH_STATUS, "NtQueryInformationProcess", Status); 88 goto Failure; 89 } 90 91 /* get the address of the PE Loader data */ 92 Status = NtReadVirtualMemory(ProcessHandle, 93 &(BasicInformation.PebBaseAddress->Ldr), 94 &LoaderData, 95 sizeof(LoaderData), 96 NULL); 97 98 if(!NT_SUCCESS(Status)) 99 { 100 DPRINT(FAILED_WITH_STATUS, "NtReadVirtualMemory", Status); 101 goto Failure; 102 } 103 104 /* head of the module list: the last element in the list will point to this */ 105 ListHead = &LoaderData->InLoadOrderModuleList; 106 107 /* get the address of the first element in the list */ 108 Status = NtReadVirtualMemory(ProcessHandle, 109 &(LoaderData->InLoadOrderModuleList.Flink), 110 &Current, 111 sizeof(Current), 112 NULL); 113 114 while(Current != ListHead) 115 { 116 /* read the current module */ 117 Status = NtReadVirtualMemory(ProcessHandle, 118 CONTAINING_RECORD(Current, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks), 119 &LoaderModule, 120 sizeof(LoaderModule), 121 NULL); 122 123 if(!NT_SUCCESS(Status)) 124 { 125 DPRINT(FAILED_WITH_STATUS, "NtReadVirtualMemory", Status); 126 goto Failure; 127 } 128 129 /* return the current module to the callback */ 130 Status = Callback(ProcessHandle, &LoaderModule, CallbackContext); 131 132 if(!NT_SUCCESS(Status)) 133 { 134 goto Failure; 135 } 136 137 /* address of the next module in the list */ 138 Current = LoaderModule.InLoadOrderLinks.Flink; 139 } 140 } 141 142 return STATUS_SUCCESS; 143 144 Failure: 145 return Status; 146 } 147 148 /* EOF */ 149