update for HEAD-2003050101
[reactos.git] / lib / epsapi / enum / modules.c
diff --git a/lib/epsapi/enum/modules.c b/lib/epsapi/enum/modules.c
new file mode 100644 (file)
index 0000000..fa4b17f
--- /dev/null
@@ -0,0 +1,176 @@
+/* $Id$
+*/
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * LICENSE:     See LGPL.txt in the top level directory
+ * PROJECT:     ReactOS system libraries
+ * FILE:        reactos/lib/epsapi/enum/module.c
+ * PURPOSE:     Enumerate process modules
+ * PROGRAMMER:  KJK::Hyperion <noog@libero.it>
+ * UPDATE HISTORY:
+ *              10/06/2002: Created
+ *              29/08/2002: Generalized the interface to improve reusability,
+ *                          more efficient use of memory operations
+ *              12/02/2003: malloc and free renamed to PsaiMalloc and PsaiFree,
+ *                          for better reusability
+ *              02/04/2003: System modules enumeration moved into its own file
+ *              12/04/2003: internal PSAPI renamed EPSAPI (Extended PSAPI) and
+ *                          isolated in its own library to clear the confusion
+ *                          and improve reusability
+ */
+
+#include <ddk/ntddk.h>
+#include <debug.h>
+#include <ntdll/ldr.h>
+
+#include <epsapi.h>
+
+NTSTATUS
+NTAPI
+PsaEnumerateProcessModules
+(
+ IN HANDLE ProcessHandle,
+ IN PPROCMOD_ENUM_ROUTINE Callback,
+ IN OUT PVOID CallbackContext
+)
+{
+ register NTSTATUS nErrCode;
+
+ /* current process - use direct memory copy */
+ if(ProcessHandle == NtCurrentProcess())
+ {
+  register PLIST_ENTRY pleListHead;
+  register PLIST_ENTRY pleCurEntry;
+
+#if 0
+  /* FIXME: activate this when GCC supports SEH */
+  __try
+  {
+#endif
+   pleListHead = &(NtCurrentPeb()->Ldr->InLoadOrderModuleList);
+   pleCurEntry = pleListHead->Flink;
+   while(pleCurEntry != pleListHead)
+   {
+    register PLDR_MODULE plmModule = CONTAINING_RECORD
+    (
+     pleCurEntry,
+     LDR_MODULE,
+     InLoadOrderModuleList
+    );
+   
+    /* return the current module to the callback */
+    nErrCode = Callback(ProcessHandle, plmModule, CallbackContext);
+    
+    if(!NT_SUCCESS(nErrCode))
+     /* failure */
+     goto epm_Failure;
+    
+    pleCurEntry = plmModule->InLoadOrderModuleList.Flink;
+   }
+#if 0
+  /* FIXME: activate this when GCC supports SEH */
+  }
+  __except(EXCEPTION_EXECUTE_HANDLER)
+  {
+   return GetExceptionCode();
+  }
+#endif
+ }
+ /* another process */
+ else
+ {
+  PROCESS_BASIC_INFORMATION pbiInfo;
+  PPEB_LDR_DATA ppldLdrData;
+  LDR_MODULE lmModule;
+  PLIST_ENTRY pleListHead;
+  PLIST_ENTRY pleCurEntry;
+  /* query the process basic information (includes the PEB address) */
+  nErrCode = NtQueryInformationProcess
+  (
+   ProcessHandle,
+   ProcessBasicInformation,
+   &pbiInfo,
+   sizeof(pbiInfo),
+   NULL
+  );
+  if(!NT_SUCCESS(nErrCode))
+  {
+   /* failure */
+   DPRINT(FAILED_WITH_STATUS, "NtQueryInformationProcess", nErrCode);
+   goto epm_Failure;
+  }
+  /* get the address of the PE Loader data */
+  nErrCode = NtReadVirtualMemory
+  (
+   ProcessHandle,
+   &(pbiInfo.PebBaseAddress->Ldr),
+   &ppldLdrData,
+   sizeof(ppldLdrData),
+   NULL
+  );
+  if(!NT_SUCCESS(nErrCode))
+  {
+   /* failure */
+   DPRINT(FAILED_WITH_STATUS, "NtReadVirtualMemory", nErrCode);
+   goto epm_Failure;
+  }
+  /* head of the module list: the last element in the list will point to this */
+  pleListHead = &ppldLdrData->InLoadOrderModuleList;
+  /* get the address of the first element in the list */
+  nErrCode = NtReadVirtualMemory
+  (
+   ProcessHandle,
+   &(ppldLdrData->InLoadOrderModuleList.Flink),
+   &pleCurEntry,
+   sizeof(pleCurEntry),
+   NULL
+  );
+  while(pleCurEntry != pleListHead)
+  {
+   /* read the current module */
+   nErrCode = NtReadVirtualMemory
+   (
+    ProcessHandle,
+    CONTAINING_RECORD(pleCurEntry, LDR_MODULE, InLoadOrderModuleList),
+    &lmModule,
+    sizeof(lmModule),
+    NULL
+   );
+   if(!NT_SUCCESS(nErrCode))
+   {
+    /* failure */
+    DPRINT(FAILED_WITH_STATUS, "NtReadVirtualMemory", nErrCode);
+    goto epm_Failure;
+   }
+
+   /* return the current module to the callback */
+   nErrCode = Callback(ProcessHandle, &lmModule, CallbackContext);
+   
+   if(!NT_SUCCESS(nErrCode))
+    /* failure */
+    goto epm_Failure;
+    
+   /* address of the next module in the list */
+   pleCurEntry = lmModule.InLoadOrderModuleList.Flink;
+  }
+ }
+
+ /* success */
+ return (STATUS_SUCCESS);
+
+epm_Failure:
+ /* failure */
+ return (nErrCode);
+}
+
+/* EOF */