xref: /reactos/sdk/lib/epsapi/enum/modules.c (revision 7e22dc05)
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