add current directory to default search path so programs can find their own dlls
[reactos.git] / reactos / lib / ntdll / ldr / utils.c
index 842821e..19e639b 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: utils.c,v 1.39 2001/02/10 10:04:39 ekohl Exp $
+/* $Id: utils.c,v 1.47 2001/09/01 19:36:30 rex Exp $
  * 
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
@@ -52,6 +52,23 @@ static PVOID LdrGetExportByName(PVOID BaseAddress, PUCHAR SymbolName, USHORT Hin
 
 /* FUNCTIONS *****************************************************************/
 
+
+#ifdef KDBG
+
+VOID LdrLoadModuleSymbols(PLDR_MODULE ModuleObject)
+{
+  NtSystemDebugControl(
+    0xffffffff,
+    (PVOID)ModuleObject,
+    0,
+    NULL,
+    0,
+    NULL);
+}
+
+#endif /* KDBG */
+
+
 /***************************************************************************
  * NAME                                                                LOCAL
  *     LdrAdjustDllName
@@ -155,288 +172,274 @@ LdrLoadDll (IN PWSTR SearchPath OPTIONAL,
            IN PUNICODE_STRING Name,
            OUT PVOID *BaseAddress OPTIONAL)
 {
-       WCHAR                   SearchPathBuffer[MAX_PATH];
-       WCHAR                   FullDosName[MAX_PATH];
-       UNICODE_STRING          AdjustedName;
-       UNICODE_STRING          FullNtFileName;
-       OBJECT_ATTRIBUTES       FileObjectAttributes;
-       char                    BlockBuffer [1024];
-       PIMAGE_DOS_HEADER       DosHeader;
-       NTSTATUS                Status;
-       PIMAGE_NT_HEADERS       NTHeaders;
-       ULONG                   ImageSize;
-       ULONG                   InitialViewSize;
-       PVOID                   ImageBase;
-       HANDLE                  FileHandle;
-       HANDLE                  SectionHandle;
-       PDLLMAIN_FUNC           Entrypoint = NULL;
-       PLDR_MODULE             Module;
-
-       if ( Name == NULL )
-       {
-               *BaseAddress = NtCurrentPeb()->ImageBaseAddress;
-               return STATUS_SUCCESS;
-       }
-
-       *BaseAddress = NULL;
-
-       DPRINT("LdrLoadDll(Name \"%wZ\" BaseAddress %x)\n",
-              Name, BaseAddress);
-
-       /* adjust the full dll name */
-       LdrAdjustDllName (&AdjustedName,
-                         Name,
-                         FALSE);
-       DPRINT("AdjustedName: %wZ\n", &AdjustedName);
-
-       /*
-        * Test if dll is already loaded.
-        */
-       if (LdrFindDll(&Module, &AdjustedName) == STATUS_SUCCESS)
-       {
-               DPRINT1("DLL %wZ already loaded.\n", &AdjustedName);
-               if (Module->LoadCount != -1)
-                       Module->LoadCount++;
-               *BaseAddress = Module->BaseAddress;
-               return STATUS_SUCCESS;
-       }
-       DPRINT("Loading \"%wZ\"\n", Name);
-
-       if (SearchPath == NULL)
-       {
-               PKUSER_SHARED_DATA SharedUserData = 
-                       (PKUSER_SHARED_DATA)USER_SHARED_DATA_BASE;
-
-               SearchPath = SearchPathBuffer;
-               wcscpy (SearchPathBuffer, SharedUserData->NtSystemRoot);
-               wcscat (SearchPathBuffer, L"\\system32;");
-               wcscat (SearchPathBuffer, SharedUserData->NtSystemRoot);
-       }
-
-       DPRINT("SearchPath %S\n", SearchPath);
-
-       if (RtlDosSearchPath_U (SearchPath,
-                               AdjustedName.Buffer,
-                               NULL,
-                               MAX_PATH,
-                               FullDosName,
-                               NULL) == 0)
-               return STATUS_DLL_NOT_FOUND;
-
-       DPRINT("FullDosName %S\n", FullDosName);
-
-       RtlFreeUnicodeString (&AdjustedName);
-
-       if (!RtlDosPathNameToNtPathName_U (FullDosName,
-                                          &FullNtFileName,
-                                          NULL,
-                                          NULL))
-               return STATUS_DLL_NOT_FOUND;
-
-       DPRINT("FullNtFileName %wZ\n", &FullNtFileName);
-
-       InitializeObjectAttributes(
-               & FileObjectAttributes,
-               & FullNtFileName,
-               0,
-               NULL,
-               NULL
-               );
-
-       DPRINT("Opening dll \"%wZ\"\n", &FullNtFileName);
-
-       Status = ZwOpenFile(
-                       & FileHandle,
-                       FILE_ALL_ACCESS,
-                       & FileObjectAttributes, 
-                       NULL,
-                       0,
-                       0
-                       );
-       if (!NT_SUCCESS(Status))
-       {
-               DbgPrint("Dll open of %wZ failed: Status = 0x%08x\n", 
-                        &FullNtFileName, Status);
-               RtlFreeUnicodeString (&FullNtFileName);
-               return Status;
-       }
-       RtlFreeUnicodeString (&FullNtFileName);
-
-       Status = ZwReadFile(
-                       FileHandle,
-                       0,
-                       0,
-                       0,
-                       0,
-                       BlockBuffer,
-                       sizeof BlockBuffer,
-                       0,
-                       0
-                       );
-       if (!NT_SUCCESS(Status))
-       {
-               DPRINT("Dll header read failed: Status = 0x%08x\n", Status);
-               ZwClose(FileHandle);
-               return Status;
-       }
-       /*
-        * Overlay DOS and NT headers structures to the 
-        * buffer with DLL's header raw data.
-        */
-       DosHeader = (PIMAGE_DOS_HEADER) BlockBuffer;
-       NTHeaders = (PIMAGE_NT_HEADERS) (BlockBuffer + DosHeader->e_lfanew);
-       /*
-        * Check it is a PE image file.
-        */
-       if ((DosHeader->e_magic != IMAGE_DOS_MAGIC)
-           || (DosHeader->e_lfanew == 0L)
-           || (*(PULONG)(NTHeaders) != IMAGE_PE_MAGIC))
-       {
-               DPRINT("NTDLL format invalid\n");
-               ZwClose(FileHandle);
-
-               return STATUS_UNSUCCESSFUL;
-       }
-
-       ImageBase = (PVOID) NTHeaders->OptionalHeader.ImageBase;
-       ImageSize = NTHeaders->OptionalHeader.SizeOfImage;
-
-       DPRINT("ImageBase 0x%08x\n", ImageBase);
+  WCHAR                        SearchPathBuffer[MAX_PATH];
+  WCHAR                        FullDosName[MAX_PATH];
+  UNICODE_STRING               AdjustedName;
+  UNICODE_STRING               FullNtFileName;
+  OBJECT_ATTRIBUTES    FileObjectAttributes;
+  char                 BlockBuffer [1024];
+  PIMAGE_DOS_HEADER    DosHeader;
+  NTSTATUS             Status;
+  PIMAGE_NT_HEADERS    NTHeaders;
+  ULONG                        ImageSize;
+  ULONG                        InitialViewSize;
+  PVOID                        ImageBase;
+  HANDLE                       FileHandle;
+  HANDLE                       SectionHandle;
+  PDLLMAIN_FUNC                Entrypoint = NULL;
+  PLDR_MODULE          Module;
+  
+  if (Name == NULL)
+    {
+      *BaseAddress = NtCurrentPeb()->ImageBaseAddress;
+      return STATUS_SUCCESS;
+    }
+  
+  *BaseAddress = NULL;
+  
+  DPRINT("LdrLoadDll(Name \"%wZ\" BaseAddress %x)\n",
+        Name, BaseAddress);
+  
+  /* adjust the full dll name */
+  LdrAdjustDllName (&AdjustedName,
+                   Name,
+                   FALSE);
+  DPRINT("AdjustedName: %wZ\n", &AdjustedName);
+  
+  /*
+   * Test if dll is already loaded.
+   */
+  if (LdrFindDll(&Module, &AdjustedName) == STATUS_SUCCESS)
+    {
+      DPRINT("DLL %wZ already loaded.\n", &AdjustedName);
+      if (Module->LoadCount != -1)
+       Module->LoadCount++;
+      *BaseAddress = Module->BaseAddress;
+      return STATUS_SUCCESS;
+    }
+  DPRINT("Loading \"%wZ\"\n", Name);
+  
+  if (SearchPath == NULL)
+    {
+      PKUSER_SHARED_DATA SharedUserData = 
+       (PKUSER_SHARED_DATA)USER_SHARED_DATA_BASE;
+      
+      SearchPath = SearchPathBuffer;
+      wcscpy (SearchPathBuffer, SharedUserData->NtSystemRoot);
+      wcscat (SearchPathBuffer, L"\\system32;");
+      wcscat (SearchPathBuffer, SharedUserData->NtSystemRoot);
+      wcscat (SearchPathBuffer, L";.");
+    }
+
+  DPRINT("SearchPath %S\n", SearchPath);
+  
+  if (RtlDosSearchPath_U (SearchPath,
+                         AdjustedName.Buffer,
+                         NULL,
+                         MAX_PATH,
+                         FullDosName,
+                         NULL) == 0)
+    return STATUS_DLL_NOT_FOUND;
+  
+  DPRINT("FullDosName %S\n", FullDosName);
+  
+  RtlFreeUnicodeString (&AdjustedName);
+  
+  if (!RtlDosPathNameToNtPathName_U (FullDosName,
+                                    &FullNtFileName,
+                                    NULL,
+                                    NULL))
+    return STATUS_DLL_NOT_FOUND;
+  
+  DPRINT("FullNtFileName %wZ\n", &FullNtFileName);
+  
+  InitializeObjectAttributes(&FileObjectAttributes,
+                            &FullNtFileName,
+                            0,
+                            NULL,
+                            NULL);
+  
+  DPRINT("Opening dll \"%wZ\"\n", &FullNtFileName);
+  
+  Status = ZwOpenFile(&FileHandle,
+                     FILE_ALL_ACCESS,
+                     &FileObjectAttributes, 
+                     NULL,
+                     0,
+                     0);
+  if (!NT_SUCCESS(Status))
+    {
+      DbgPrint("Dll open of %wZ failed: Status = 0x%08x\n", 
+              &FullNtFileName, Status);
+      RtlFreeUnicodeString (&FullNtFileName);
+      return Status;
+    }
+  RtlFreeUnicodeString (&FullNtFileName);
+  
+  Status = ZwReadFile(FileHandle,
+                     0,
+                     0,
+                     0,
+                     0,
+                     BlockBuffer,
+                     sizeof(BlockBuffer),
+                     0,
+                     0);
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT("Dll header read failed: Status = 0x%08x\n", Status);
+      ZwClose(FileHandle);
+      return Status;
+    }
+  /*
+   * Overlay DOS and NT headers structures to the 
+   * buffer with DLL's header raw data.
+   */
+  DosHeader = (PIMAGE_DOS_HEADER) BlockBuffer;
+  NTHeaders = (PIMAGE_NT_HEADERS) (BlockBuffer + DosHeader->e_lfanew);
+  /*
+   * Check it is a PE image file.
+   */
+  if ((DosHeader->e_magic != IMAGE_DOS_MAGIC)
+      || (DosHeader->e_lfanew == 0L)
+      || (*(PULONG)(NTHeaders) != IMAGE_PE_MAGIC))
+    {
+      DPRINT("NTDLL format invalid\n");
+      ZwClose(FileHandle);
+      
+      return STATUS_UNSUCCESSFUL;
+    }
+  
+  ImageBase = (PVOID) NTHeaders->OptionalHeader.ImageBase;
+  ImageSize = NTHeaders->OptionalHeader.SizeOfImage;
+  
+  DPRINT("ImageBase 0x%08x\n", ImageBase);
        
-       /*
-        * Create a section for dll.
-        */
-       Status = ZwCreateSection(
-                       & SectionHandle,
-                       SECTION_ALL_ACCESS,
-                       NULL,
-                       NULL,
-                       PAGE_READWRITE,
-                       MEM_COMMIT,
-                       FileHandle
-                       );
-       if (!NT_SUCCESS(Status))
-       {
-               DPRINT("NTDLL create section failed: Status = 0x%08x\n", Status);
-               ZwClose(FileHandle);
-               return Status;
-       }
-
-       /*
-        * Map the dll into the process.
-        */
-       InitialViewSize =
-               DosHeader->e_lfanew
-               + sizeof (IMAGE_NT_HEADERS)
-               + sizeof (IMAGE_SECTION_HEADER) * NTHeaders->FileHeader.NumberOfSections;
-       Status = ZwMapViewOfSection(
-                       SectionHandle,
-                       NtCurrentProcess(),
-                       (PVOID*)&ImageBase,
-                       0,
-                       InitialViewSize,
-                       NULL,
-                       &InitialViewSize,
-                       0,
-                       MEM_COMMIT,
-                       PAGE_READWRITE
-                       );
-       if (!NT_SUCCESS(Status))
-       {
-               DbgPrint("NTDLL.LDR: map view of section failed (Status %x)\n",
-                      Status);
-               ZwClose(FileHandle);
+  /*
+   * Create a section for dll.
+   */
+  Status = ZwCreateSection(&SectionHandle,
+                          SECTION_ALL_ACCESS,
+                          NULL,
+                          NULL,
+                          PAGE_READWRITE,
+                          SEC_COMMIT | SEC_IMAGE,
+                          FileHandle);
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT("NTDLL create section failed: Status = 0x%08x\n", Status);
+      ZwClose(FileHandle);
+      return Status;
+    }
+  
+  /*
+   * Map the dll into the process.
+   */
+  InitialViewSize = 0;
+  ImageBase = 0;
+  Status = ZwMapViewOfSection(SectionHandle,
+                             NtCurrentProcess(),
+                             &ImageBase,
+                             0,
+                             InitialViewSize,
+                             NULL,
+                             &InitialViewSize,
+                             0,
+                             MEM_COMMIT,
+                             PAGE_READWRITE);
+  if (!NT_SUCCESS(Status))
+    {
+      DbgPrint("NTDLL.LDR: map view of section failed (Status %x)\n",
+              Status);
+      ZwClose(FileHandle);
                return(Status);
-       }
-       ZwClose(FileHandle);
-
-       /* relocate dll and fixup import table */
-       if ((NTHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL) ==
-            IMAGE_FILE_DLL)
-       {
-               Entrypoint =
-               (PDLLMAIN_FUNC) LdrPEStartup(
-                                       ImageBase,
-                                       SectionHandle
-                                       );
-       }
-
-       /* build module entry */
-       Module = RtlAllocateHeap(
-                       RtlGetProcessHeap(),
-                       0,
-                       sizeof (LDR_MODULE)
-                       );
-       Module->BaseAddress = (PVOID)ImageBase;
-       Module->EntryPoint = NTHeaders->OptionalHeader.AddressOfEntryPoint;
-       if (Module->EntryPoint != 0)
-               Module->EntryPoint += (ULONG)Module->BaseAddress;
-       Module->SizeOfImage = ImageSize;
-       if (NtCurrentPeb()->Ldr->Initialized == TRUE)
+    }
+  ZwClose(FileHandle);
+
+  /* relocate dll and fixup import table */
+  if ((NTHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL) ==
+      IMAGE_FILE_DLL)
+    {
+      Entrypoint =
+       (PDLLMAIN_FUNC) LdrPEStartup(ImageBase, SectionHandle);
+    }
+  
+  /* build module entry */
+  Module = RtlAllocateHeap(RtlGetProcessHeap(),
+                          0,
+                          sizeof (LDR_MODULE));
+  Module->BaseAddress = (PVOID)ImageBase;
+  Module->EntryPoint = NTHeaders->OptionalHeader.AddressOfEntryPoint;
+  if (Module->EntryPoint != 0)
+    Module->EntryPoint += (ULONG)Module->BaseAddress;
+  Module->SizeOfImage = ImageSize;
+  if (NtCurrentPeb()->Ldr->Initialized == TRUE)
+    {
+      /* loading while app is running */
+      Module->LoadCount = 1;
+    }
+  else
+    {
+      /*
+       * loading while app is initializing
+       * dll must not be unloaded
+       */
+      Module->LoadCount = -1;
+    }
+
+  Module->TlsIndex = 0;
+  Module->CheckSum = NTHeaders->OptionalHeader.CheckSum;
+  Module->TimeDateStamp = NTHeaders->FileHeader.TimeDateStamp;
+
+  RtlCreateUnicodeString (&Module->FullDllName,
+                         FullDosName);
+  RtlCreateUnicodeString (&Module->BaseDllName,
+                         wcsrchr(FullDosName, L'\\') + 1);
+  DPRINT ("BaseDllName %wZ\n", &Module->BaseDllName);
+  
+  /* FIXME: aquire loader lock */
+  InsertTailList(&NtCurrentPeb()->Ldr->InLoadOrderModuleList,
+                &Module->InLoadOrderModuleList);
+  InsertTailList(&NtCurrentPeb()->Ldr->InInitializationOrderModuleList,
+                &Module->InInitializationOrderModuleList);
+  /* FIXME: release loader lock */
+
+#ifdef KDBG
+  LdrLoadModuleSymbols(Module);
+#endif /* KDBG */
+
+  /* initialize dll */
+  if ((NTHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL) ==
+      IMAGE_FILE_DLL)
+    {
+      if (Module->EntryPoint != 0)
        {
-               /* loading while app is running */
-               Module->LoadCount = 1;
+         Entrypoint = (PDLLMAIN_FUNC)Module->EntryPoint;
+         
+         DPRINT("Calling entry point at 0x%08x\n", Entrypoint);
+         if (FALSE == Entrypoint(Module->BaseAddress,
+                                 DLL_PROCESS_ATTACH,
+                                 NULL))
+           {
+             DPRINT("NTDLL.LDR: DLL \"%wZ\" failed to initialize\n",
+                    &Module->BaseDllName);
+             /* FIXME: should clean up and fail */
+           }
+         else
+           {
+             DPRINT("NTDLL.LDR: DLL \"%wZ\" initialized successfully\n",
+                    &Module->BaseDllName);
+           }
        }
-       else
+      else
        {
-               /*
-                * loading while app is initializing
-                * dll must not be unloaded
-                */
-               Module->LoadCount = -1;
+         DPRINT("NTDLL.LDR: Entrypoint is NULL for \"%wZ\"\n",
+                &Module->BaseDllName);
        }
+    }
 
-       Module->TlsIndex = 0;
-       Module->CheckSum = NTHeaders->OptionalHeader.CheckSum;
-       Module->TimeDateStamp = NTHeaders->FileHeader.TimeDateStamp;
-
-       RtlCreateUnicodeString (&Module->FullDllName,
-                               FullDosName);
-       RtlCreateUnicodeString (&Module->BaseDllName,
-                               wcsrchr(FullDosName, L'\\') + 1);
-       DPRINT ("BaseDllName %wZ\n", &Module->BaseDllName);
-
-       /* FIXME: aquire loader lock */
-       InsertTailList(&NtCurrentPeb()->Ldr->InLoadOrderModuleList,
-                      &Module->InLoadOrderModuleList);
-       InsertTailList(&NtCurrentPeb()->Ldr->InInitializationOrderModuleList,
-                      &Module->InInitializationOrderModuleList);
-       /* FIXME: release loader lock */
-
-       /* initialize dll */
-       if ((NTHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL) ==
-            IMAGE_FILE_DLL)
-       {
-               if (Module->EntryPoint != 0)
-               {
-                       Entrypoint = (PDLLMAIN_FUNC)Module->EntryPoint;
-
-                       DPRINT("Calling entry point at 0x%08x\n", Entrypoint);
-                       if (FALSE == Entrypoint(
-                               Module->BaseAddress,
-                               DLL_PROCESS_ATTACH,
-                               NULL
-                               ))
-                       {
-                               DPRINT("NTDLL.LDR: DLL \"%wZ\" failed to initialize\n",
-                                      &Module->BaseDllName);
-                               /* FIXME: should clean up and fail */
-                       }
-                       else
-                       {
-                               DPRINT("NTDLL.LDR: DLL \"%wZ\" initialized successfully\n",
-                                      &Module->BaseDllName);
-                       }
-               }
-               else
-               {
-                       DPRINT("NTDLL.LDR: Entrypoint is NULL for \"%wZ\"\n",
-                              &Module->BaseDllName);
-               }
-       }
-
-       *BaseAddress = Module->BaseAddress;
-       return STATUS_SUCCESS;
+  *BaseAddress = Module->BaseAddress;
+  return STATUS_SUCCESS;
 }
 
 
@@ -493,84 +496,6 @@ static NTSTATUS LdrFindDll(PLDR_MODULE *Dll, PUNICODE_STRING Name)
    return STATUS_UNSUCCESSFUL;
 }
 
-
-/**********************************************************************
- * NAME
- *     LdrMapSections
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- *
- * RETURN VALUE
- *
- * REVISIONS
- *
- * NOTE
- *
- */
-NTSTATUS LdrMapSections(HANDLE                 ProcessHandle,
-                       PVOID                   ImageBase,
-                       HANDLE                  SectionHandle,
-                       PIMAGE_NT_HEADERS       NTHeaders)
-{
-   ULONG       i;
-   NTSTATUS    Status;
-
-   for (i = 0; (i < NTHeaders->FileHeader.NumberOfSections); i++)
-     {
-       PIMAGE_SECTION_HEADER   Sections;
-       LARGE_INTEGER           Offset;
-       ULONG                   Base;
-       ULONG Size;
-       
-       Sections = (PIMAGE_SECTION_HEADER) SECHDROFFSET(ImageBase);
-       Base = (ULONG) (Sections[i].VirtualAddress + ImageBase);
-       Offset.u.LowPart = Sections[i].PointerToRawData;
-       Offset.u.HighPart = 0;
-       
-       Size = max(Sections[i].Misc.VirtualSize, Sections[i].SizeOfRawData);
-       
-       DPRINT("Mapping section %d offset %x base %x size %x\n",
-               i, Offset.u.LowPart, Base, Sections[i].Misc.VirtualSize);
-       DPRINT("Size %x\n", Sections[i].SizeOfRawData);
-       if( Offset.u.LowPart )
-         { // only map section if it is initialized
-           Status = ZwMapViewOfSection(SectionHandle,
-                                       ProcessHandle,
-                                       (PVOID*)&Base,
-                                       0,
-                                       Size,
-                                       &Offset,
-                                       (PULONG)&Size,
-                                       0,
-                                       MEM_COMMIT,
-                                       PAGE_READWRITE);
-           if (!NT_SUCCESS(Status))
-             {
-               DPRINT1("Failed to map section");
-               return(Status);
-             }
-         }
-       else {
-         // allocate pure memory for uninitialized section
-         Status = NtAllocateVirtualMemory( NtCurrentProcess(),
-                                           (PVOID *)&Base,
-                                           0,
-                                           &Size,
-                                           MEM_COMMIT,
-                                           PAGE_READWRITE );
-         if( !NT_SUCCESS( Status ) )
-           {
-             DPRINT1( "Failed to allocate memory for uninitialized section\n" );
-             return Status;
-           }
-       }
-     }
-   return STATUS_SUCCESS;
-}
-
-
 /**********************************************************************
  * NAME                                                                LOCAL
  *     LdrFixupForward
@@ -613,18 +538,18 @@ LdrFixupForward(PCHAR ForwardName)
                                 0,
                                 &DllName,
                                 &BaseAddress);
-            RtlFreeUnicodeString (&DllName);
             if (!NT_SUCCESS(Status))
               {
                  DbgPrint("LdrFixupForward: failed to load %wZ\n", &DllName);
+                 RtlFreeUnicodeString (&DllName);
                  return NULL;
               }
          }
 
-         RtlFreeUnicodeString (&DllName);
-         DPRINT("BaseAddress: %p\n", BaseAddress);
-
-         return LdrGetExportByName(BaseAddress, p+1, -1);
+       RtlFreeUnicodeString (&DllName);
+       DPRINT("BaseAddress: %p\n", BaseAddress);
+       
+       return LdrGetExportByName(BaseAddress, p+1, -1);
      }
 
    return NULL;
@@ -712,15 +637,20 @@ LdrGetExportByName(PVOID BaseAddress,
    PVOID                       Function;
    ULONG minn, maxn;
    ULONG ExportDirSize;
-
+   
    DPRINT("LdrGetExportByName %x %s %hu\n", BaseAddress, SymbolName, Hint);
-
+   
    ExportDir = (PIMAGE_EXPORT_DIRECTORY)
      RtlImageDirectoryEntryToData(BaseAddress,
                                  TRUE,
                                  IMAGE_DIRECTORY_ENTRY_EXPORT,
                                  &ExportDirSize);
-
+   if (ExportDir == NULL)
+     {
+       DbgPrint("LdrGetExportByName(): no export directory!\n");
+       return NULL;
+     }
+   
    /*
     * Get header pointers
     */
@@ -751,11 +681,12 @@ LdrGetExportByName(PVOID BaseAddress,
               return Function;
          }
      }
-
+   
    /*
     * Try a binary search first
     */
-   minn = 0, maxn = ExportDir->NumberOfFunctions;
+   minn = 0;
+   maxn = ExportDir->NumberOfFunctions;
    while (minn <= maxn)
      {
        ULONG mid;
@@ -778,6 +709,11 @@ LdrGetExportByName(PVOID BaseAddress,
             if (Function != NULL)
               return Function;
          }
+       else if (minn == maxn)
+         {
+            DPRINT("LdrGetExportByName(): binary search failed\n");
+            break;
+         }
        else if (res > 0)
          {
             maxn = mid - 1;
@@ -787,11 +723,11 @@ LdrGetExportByName(PVOID BaseAddress,
             minn = mid + 1;
          }
      }
+   
    /*
     * Fall back on a linear search
     */
-
-   DbgPrint("LDR: Falling back on a linear search of export table\n");
+   DPRINT("LdrGetExportByName(): Falling back on a linear search of export table\n");
    for (i = 0; i < ExportDir->NumberOfFunctions; i++)
      {
        ExName = RVA(BaseAddress, ExNames[i]);
@@ -809,7 +745,7 @@ LdrGetExportByName(PVOID BaseAddress,
             return Function;
          }
      }
-   DbgPrint("LdrGetExportByName() = failed to find %s\n",SymbolName);
+   DbgPrint("LdrGetExportByName(): failed to find %s\n",SymbolName);
    return NULL;
 }
 
@@ -1097,17 +1033,6 @@ PEPFUNC LdrPEStartup (PVOID  ImageBase,
    DosHeader = (PIMAGE_DOS_HEADER) ImageBase;
    NTHeaders = (PIMAGE_NT_HEADERS) (ImageBase + DosHeader->e_lfanew);
 
-   /*
-    * Initialize image sections.
-    */
-   if (SectionHandle != NULL)
-     {
-       LdrMapSections(NtCurrentProcess(),
-                      ImageBase,
-                      SectionHandle,
-                      NTHeaders);
-     }
-
    /*
     * If the base address is different from the
     * one the DLL is actually loaded, perform any
@@ -1172,7 +1097,7 @@ LdrUnloadDll (IN PVOID BaseAddress)
    ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
    Entry = ModuleListHead->Flink;
 
-   while (Entry != ModuleListHead);
+   while (Entry != ModuleListHead)
      {
        Module = CONTAINING_RECORD(Entry, LDR_MODULE, InLoadOrderModuleList);
        if (Module->BaseAddress == BaseAddress)
@@ -1546,7 +1471,7 @@ LdrGetDllHandle (IN ULONG Unknown1,
    if ( DllName == NULL )
      {
        *BaseAddress = NtCurrentPeb()->ImageBaseAddress;
-       DPRINT1("BaseAddress %x\n", *BaseAddress);
+       DPRINT("BaseAddress %x\n", *BaseAddress);
        return STATUS_SUCCESS;
      }
 
@@ -1666,10 +1591,12 @@ LdrShutdownProcess (VOID)
      {
        Module = CONTAINING_RECORD(Entry, LDR_MODULE, InInitializationOrderModuleList);
 
-       DPRINT("  Unloading %wZ\n",
+       DPRINT("  Unloading %S\n",
               &Module->BaseDllName);
-
-       if (Module->EntryPoint != 0)
+       // PJS: only detach from static dlls, they should FreeLibrary() any dlls that
+       // they loaded dynamically, and when the last reference is gone, that lib will
+       // be detached.  
+       if (Module->EntryPoint != 0 && Module->LoadCount == -1)
          {
             PDLLMAIN_FUNC Entrypoint = (PDLLMAIN_FUNC)Module->EntryPoint;