implemented GetModuleHandleExA/W(), LdrAddRefDll() and RtlPcToFileHeader() (untested)
Modified: trunk/reactos/include/ndk/ldrtypes.h
Modified: trunk/reactos/include/ndk/umfuncs.h
Modified: trunk/reactos/lib/kernel32/misc/ldr.c
Modified: trunk/reactos/lib/kernel32/misc/stubs.c
Modified: trunk/reactos/lib/ntdll/def/ntdll.def
Modified: trunk/reactos/lib/ntdll/ldr/utils.c

Modified: trunk/reactos/include/ndk/ldrtypes.h
--- trunk/reactos/include/ndk/ldrtypes.h	2006-01-12 01:16:57 UTC (rev 20801)
+++ trunk/reactos/include/ndk/ldrtypes.h	2006-01-12 04:31:37 UTC (rev 20802)
@@ -106,4 +106,9 @@
     ULONG Language;
 } LDR_RESOURCE_INFO, *PLDR_RESOURCE_INFO;
 
+//
+// LdrAddRef Flags
+//
+#define LDR_PIN_MODULE                  0x00000001
+
 #endif

Modified: trunk/reactos/include/ndk/umfuncs.h
--- trunk/reactos/include/ndk/umfuncs.h	2006-01-12 01:16:57 UTC (rev 20801)
+++ trunk/reactos/include/ndk/umfuncs.h	2006-01-12 04:31:37 UTC (rev 20802)
@@ -161,8 +161,16 @@
 //
 // Loader Functions
 //
+
 NTSTATUS
 NTAPI
+LdrAddRefDll(
+    IN ULONG Flags,
+    IN PVOID BaseAddress
+);
+
+NTSTATUS
+NTAPI
 LdrDisableThreadCalloutsForDll(
     IN PVOID BaseAddress
 );
@@ -210,6 +218,13 @@
     OUT PVOID *BaseAddress OPTIONAL
 );
 
+PVOID
+NTAPI
+RtlPcToFileHeader(
+    IN PVOID PcValue,
+    PVOID* BaseOfImage
+);
+
 PIMAGE_BASE_RELOCATION
 NTAPI
 LdrProcessRelocationBlock(

Modified: trunk/reactos/lib/kernel32/misc/ldr.c
--- trunk/reactos/lib/kernel32/misc/ldr.c	2006-01-12 01:16:57 UTC (rev 20801)
+++ trunk/reactos/lib/kernel32/misc/ldr.c	2006-01-12 04:31:37 UTC (rev 20802)
@@ -483,6 +483,129 @@
 /*
  * @implemented
  */
+BOOL
+STDCALL
+GetModuleHandleExW(IN DWORD dwFlags,
+                   IN LPCWSTR lpModuleName  OPTIONAL,
+                   OUT HMODULE* phModule)
+{
+    HMODULE hModule;
+    NTSTATUS Status;
+    BOOL Ret = FALSE;
+
+    if (phModule == NULL ||
+        ((dwFlags & (GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT)) ==
+         (GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT)))
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    if (lpModuleName == NULL)
+    {
+        hModule = NtCurrentPeb()->ImageBaseAddress;
+    }
+    else
+    {
+        if (dwFlags & GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS)
+        {
+            hModule = (HMODULE)RtlPcToFileHeader((PVOID)lpModuleName,
+                                                 (PVOID*)&hModule);
+            if (hModule == NULL)
+            {
+                SetLastErrorByStatus(STATUS_DLL_NOT_FOUND);
+            }
+        }
+        else
+        {
+            hModule = GetModuleHandleW(lpModuleName);
+        }
+    }
+
+    if (hModule != NULL)
+    {
+        if (!(dwFlags & GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT))
+        {
+            Status = LdrAddRefDll((dwFlags & GET_MODULE_HANDLE_EX_FLAG_PIN) ? LDR_PIN_MODULE : 0,
+                                  hModule);
+
+            if (NT_SUCCESS(Status))
+            {
+                Ret = TRUE;
+            }
+            else
+            {
+                SetLastErrorByStatus(Status);
+                hModule = NULL;
+            }
+        }
+        else
+            Ret = TRUE;
+    }
+
+    *phModule = hModule;
+    return Ret;
+}
+
+/*
+ * @implemented
+ */
+BOOL
+STDCALL
+GetModuleHandleExA(IN DWORD dwFlags,
+                   IN LPCSTR lpModuleName  OPTIONAL,
+                   OUT HMODULE* phModule)
+{
+    UNICODE_STRING UnicodeName;
+    ANSI_STRING ModuleName;
+    LPCWSTR lpModuleNameW;
+    NTSTATUS Status;
+    BOOL Ret;
+
+    if (dwFlags & GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS)
+    {
+        lpModuleNameW = (LPCWSTR)lpModuleName;
+    }
+    else
+    {
+        RtlInitAnsiString(&ModuleName,
+                          (LPSTR)lpModuleName);
+
+        /* convert ansi (or oem) string to unicode */
+        if (bIsFileApiAnsi)
+            Status = RtlAnsiStringToUnicodeString(&UnicodeName,
+                                                  &ModuleName,
+                                                  TRUE);
+        else
+            Status = RtlOemStringToUnicodeString(&UnicodeName,
+                                                 &ModuleName,
+                                                 TRUE);
+
+        if (!NT_SUCCESS(Status))
+        {
+            SetLastErrorByStatus(Status);
+            return FALSE;
+        }
+
+        lpModuleNameW = UnicodeName.Buffer;
+    }
+
+    Ret = GetModuleHandleExW(dwFlags,
+                             lpModuleNameW,
+                             phModule);
+
+    if (!(dwFlags & GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS))
+    {
+        RtlFreeUnicodeString(&UnicodeName);
+    }
+
+    return Ret;
+}
+
+
+/*
+ * @implemented
+ */
 DWORD
 STDCALL
 LoadModule (

Modified: trunk/reactos/lib/kernel32/misc/stubs.c
--- trunk/reactos/lib/kernel32/misc/stubs.c	2006-01-12 01:16:57 UTC (rev 20801)
+++ trunk/reactos/lib/kernel32/misc/stubs.c	2006-01-12 04:31:37 UTC (rev 20802)
@@ -1087,28 +1087,11 @@
     return 0;
 }
 
-
-
 /*
  * @unimplemented
  */
 BOOL
 STDCALL
-GetModuleHandleExW(
-    DWORD        dwFlags,
-    LPCWSTR     lpModuleName,
-    HMODULE*    phModule
-    )
-{
-    STUB;
-    return 0;
-}
-
-/*
- * @unimplemented
- */
-BOOL
-STDCALL
 GetVolumePathNameW(
     LPCWSTR lpszFileName,
     LPWSTR lpszVolumePathName,
@@ -1286,28 +1269,11 @@
     return 0;
 }
 
-
-
 /*
  * @unimplemented
  */
 BOOL
 STDCALL
-GetModuleHandleExA(
-    DWORD        dwFlags,
-    LPCSTR     lpModuleName,
-    HMODULE*    phModule
-    )
-{
-    STUB;
-    return 0;
-}
-
-/*
- * @unimplemented
- */
-BOOL
-STDCALL
 GetVolumeNameForVolumeMountPointA(
     LPCSTR lpszVolumeMountPoint,
     LPSTR lpszVolumeName,

Modified: trunk/reactos/lib/ntdll/def/ntdll.def
--- trunk/reactos/lib/ntdll/def/ntdll.def	2006-01-12 01:16:57 UTC (rev 20801)
+++ trunk/reactos/lib/ntdll/def/ntdll.def	2006-01-12 04:31:37 UTC (rev 20802)
@@ -35,6 +35,7 @@
 KiUserCallbackDispatcher@12
 KiUserExceptionDispatcher@8
 LdrAccessResource@16
+LdrAddRefDll@8
 LdrDisableThreadCalloutsForDll@4
 LdrEnumResources@20
 LdrFindEntryForAddress@8
@@ -576,7 +577,7 @@
 RtlOemStringToUnicodeString@12
 RtlOemToUnicodeN@20
 RtlOpenCurrentUser@8
-;RtlPcToFileHeader
+RtlPcToFileHeader@8
 RtlPinAtomInAtomTable@8
 RtlPrefixString@12
 RtlPrefixUnicodeString@12

Modified: trunk/reactos/lib/ntdll/ldr/utils.c
--- trunk/reactos/lib/ntdll/ldr/utils.c	2006-01-12 01:16:57 UTC (rev 20801)
+++ trunk/reactos/lib/ntdll/ldr/utils.c	2006-01-12 04:31:37 UTC (rev 20802)
@@ -2135,7 +2135,7 @@
      {
        /* ?????????????????? */
      }
-   else if (LoadCount == 1)
+   else if (!(Module->Flags & LDRP_STATIC_LINK) && LoadCount == 1)
      {
        BoundImportDescriptor = (PIMAGE_BOUND_IMPORT_DESCRIPTOR)
                                  RtlImageDirectoryEntryToData(Module->DllBase,
@@ -2207,7 +2207,11 @@
 
    if (Unload)
      {
-       LdrpDetachProcess(FALSE);
+       if (!(Module->Flags & LDRP_STATIC_LINK))
+         {
+           LdrpDetachProcess(FALSE);
+         }
+
        RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
      }
    return STATUS_SUCCESS;
@@ -2316,10 +2320,87 @@
     return STATUS_DLL_NOT_FOUND;
 }
 
+/*
+ * @implemented
+ */
+NTSTATUS NTAPI
+LdrAddRefDll(IN ULONG Flags,
+             IN PVOID BaseAddress)
+{
+    PLIST_ENTRY ModuleListHead;
+    PLIST_ENTRY Entry;
+    PLDR_DATA_TABLE_ENTRY Module;
+    NTSTATUS Status;
 
+    if (Flags & ~(LDR_PIN_MODULE))
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    Status = STATUS_DLL_NOT_FOUND;
+    RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
+    ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
+    Entry = ModuleListHead->Flink;
+    while (Entry != ModuleListHead)
+    {
+        Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderModuleList);
+
+        if (Module->DllBase == BaseAddress)
+        {
+            if (Flags & LDR_PIN_MODULE)
+            {
+                Module->Flags |= LDRP_STATIC_LINK;
+            }
+            else
+            {
+                LdrpIncrementLoadCount(Module,
+                                       FALSE);
+            }
+            Status = STATUS_SUCCESS;
+            break;
+        }
+        Entry = Entry->Flink;
+    }
+    RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
+    return Status;
+}
+
 /*
  * @implemented
  */
+PVOID NTAPI
+RtlPcToFileHeader(IN PVOID PcValue,
+                  PVOID* BaseOfImage)
+{
+    PLIST_ENTRY ModuleListHead;
+    PLIST_ENTRY Entry;
+    PLDR_DATA_TABLE_ENTRY Module;
+    PVOID ImageBase = NULL;
+
+    RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
+    ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
+    Entry = ModuleListHead->Flink;
+    while (Entry != ModuleListHead)
+      {
+        Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderModuleList);
+
+        if ((ULONG_PTR)PcValue >= (ULONG_PTR)Module->DllBase &&
+            (ULONG_PTR)PcValue < (ULONG_PTR)Module->DllBase + Module->SizeOfImage)
+          {
+            ImageBase = Module->DllBase;
+            break;
+          }
+        Entry = Entry->Flink;
+      }
+    RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
+
+    *BaseOfImage = ImageBase;
+    return ImageBase;
+}
+
+/*
+ * @implemented
+ */
 NTSTATUS NTAPI
 LdrGetProcedureAddress (IN PVOID BaseAddress,
                         IN PANSI_STRING Name,