update for HEAD-2003050101
[reactos.git] / lib / epsapi / enum / modules.c
1 /* $Id$
2 */
3 /*
4  * COPYRIGHT:   See COPYING in the top level directory
5  * LICENSE:     See LGPL.txt in the top level directory
6  * PROJECT:     ReactOS system libraries
7  * FILE:        reactos/lib/epsapi/enum/module.c
8  * PURPOSE:     Enumerate process modules
9  * PROGRAMMER:  KJK::Hyperion <noog@libero.it>
10  * UPDATE HISTORY:
11  *              10/06/2002: Created
12  *              29/08/2002: Generalized the interface to improve reusability,
13  *                          more efficient use of memory operations
14  *              12/02/2003: malloc and free renamed to PsaiMalloc and PsaiFree,
15  *                          for better reusability
16  *              02/04/2003: System modules enumeration moved into its own file
17  *              12/04/2003: internal PSAPI renamed EPSAPI (Extended PSAPI) and
18  *                          isolated in its own library to clear the confusion
19  *                          and improve reusability
20  */
21
22 #include <ddk/ntddk.h>
23 #include <debug.h>
24 #include <ntdll/ldr.h>
25
26 #include <epsapi.h>
27
28 NTSTATUS
29 NTAPI
30 PsaEnumerateProcessModules
31 (
32  IN HANDLE ProcessHandle,
33  IN PPROCMOD_ENUM_ROUTINE Callback,
34  IN OUT PVOID CallbackContext
35 )
36 {
37  register NTSTATUS nErrCode;
38
39  /* current process - use direct memory copy */
40  if(ProcessHandle == NtCurrentProcess())
41  {
42   register PLIST_ENTRY pleListHead;
43   register PLIST_ENTRY pleCurEntry;
44
45 #if 0
46   /* FIXME: activate this when GCC supports SEH */
47   __try
48   {
49 #endif
50    pleListHead = &(NtCurrentPeb()->Ldr->InLoadOrderModuleList);
51    pleCurEntry = pleListHead->Flink;
52  
53    while(pleCurEntry != pleListHead)
54    {
55     register PLDR_MODULE plmModule = CONTAINING_RECORD
56     (
57      pleCurEntry,
58      LDR_MODULE,
59      InLoadOrderModuleList
60     );
61    
62     /* return the current module to the callback */
63     nErrCode = Callback(ProcessHandle, plmModule, CallbackContext);
64     
65     if(!NT_SUCCESS(nErrCode))
66      /* failure */
67      goto epm_Failure;
68     
69     pleCurEntry = plmModule->InLoadOrderModuleList.Flink;
70    }
71 #if 0
72   /* FIXME: activate this when GCC supports SEH */
73   }
74   __except(EXCEPTION_EXECUTE_HANDLER)
75   {
76    return GetExceptionCode();
77   }
78 #endif
79  }
80  /* another process */
81  else
82  {
83   PROCESS_BASIC_INFORMATION pbiInfo;
84   PPEB_LDR_DATA ppldLdrData;
85   LDR_MODULE lmModule;
86   PLIST_ENTRY pleListHead;
87   PLIST_ENTRY pleCurEntry;
88  
89   /* query the process basic information (includes the PEB address) */
90   nErrCode = NtQueryInformationProcess
91   (
92    ProcessHandle,
93    ProcessBasicInformation,
94    &pbiInfo,
95    sizeof(pbiInfo),
96    NULL
97   );
98  
99   if(!NT_SUCCESS(nErrCode))
100   {
101    /* failure */
102    DPRINT(FAILED_WITH_STATUS, "NtQueryInformationProcess", nErrCode);
103    goto epm_Failure;
104   }
105  
106   /* get the address of the PE Loader data */
107   nErrCode = NtReadVirtualMemory
108   (
109    ProcessHandle,
110    &(pbiInfo.PebBaseAddress->Ldr),
111    &ppldLdrData,
112    sizeof(ppldLdrData),
113    NULL
114   );
115  
116   if(!NT_SUCCESS(nErrCode))
117   {
118    /* failure */
119    DPRINT(FAILED_WITH_STATUS, "NtReadVirtualMemory", nErrCode);
120    goto epm_Failure;
121   }
122  
123   /* head of the module list: the last element in the list will point to this */
124   pleListHead = &ppldLdrData->InLoadOrderModuleList;
125  
126   /* get the address of the first element in the list */
127   nErrCode = NtReadVirtualMemory
128   (
129    ProcessHandle,
130    &(ppldLdrData->InLoadOrderModuleList.Flink),
131    &pleCurEntry,
132    sizeof(pleCurEntry),
133    NULL
134   );
135  
136   while(pleCurEntry != pleListHead)
137   {
138    /* read the current module */
139    nErrCode = NtReadVirtualMemory
140    (
141     ProcessHandle,
142     CONTAINING_RECORD(pleCurEntry, LDR_MODULE, InLoadOrderModuleList),
143     &lmModule,
144     sizeof(lmModule),
145     NULL
146    );
147  
148    if(!NT_SUCCESS(nErrCode))
149    {
150     /* failure */
151     DPRINT(FAILED_WITH_STATUS, "NtReadVirtualMemory", nErrCode);
152     goto epm_Failure;
153    }
154
155    /* return the current module to the callback */
156    nErrCode = Callback(ProcessHandle, &lmModule, CallbackContext);
157    
158    if(!NT_SUCCESS(nErrCode))
159     /* failure */
160     goto epm_Failure;
161     
162    /* address of the next module in the list */
163    pleCurEntry = lmModule.InLoadOrderModuleList.Flink;
164   }
165  
166  }
167
168  /* success */
169  return (STATUS_SUCCESS);
170
171 epm_Failure:
172  /* failure */
173  return (nErrCode);
174 }
175
176 /* EOF */