Implemented dll preloading and mapping.
authorEric Kohl <eric.kohl@reactos.org>
Mon, 12 May 2003 19:47:53 +0000 (19:47 +0000)
committerEric Kohl <eric.kohl@reactos.org>
Mon, 12 May 2003 19:47:53 +0000 (19:47 +0000)
svn path=/trunk/; revision=4681

reactos/lib/ntdll/ldr/startup.c
reactos/lib/ntdll/ldr/utils.c
reactos/subsys/smss/init.c

index 004c1cd..bc1b5ed 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: startup.c,v 1.50 2003/04/27 14:45:52 chorns Exp $
+/* $Id: startup.c,v 1.51 2003/05/12 19:47:53 ekohl Exp $
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
@@ -24,6 +24,8 @@
 
 
 VOID RtlInitializeHeapManager (VOID);
+VOID LdrpInitLoader(VOID);
+
 
 /* GLOBALS *******************************************************************/
 
@@ -259,6 +261,8 @@ __true_LdrInitializeThunk (ULONG Unknown1,
    InsertHeadList(&Peb->Ldr->InLoadOrderModuleList,
                   &ExeModule->InLoadOrderModuleList);
 
+  LdrpInitLoader();
+
 #ifdef DBG
 
   LdrpLoadUserModuleSymbols(ExeModule);
index c7767e8..cb4a272 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: utils.c,v 1.64 2003/04/30 22:04:12 gvg Exp $
+/* $Id: utils.c,v 1.65 2003/05/12 19:47:53 ekohl Exp $
  * 
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
 #endif
 #include <ntdll/ntdll.h>
 
+/* GLOBALS *******************************************************************/
+
+static HANDLE LdrpKnownDllsDirHandle = NULL;
+static UNICODE_STRING LdrpKnownDllPath = {0, 0, NULL};
+
+
 /* PROTOTYPES ****************************************************************/
 
 static NTSTATUS LdrFindEntryForName(PUNICODE_STRING Name, PLDR_MODULE *Module);
@@ -58,6 +64,87 @@ LdrpLoadUserModuleSymbols(PLDR_MODULE LdrModule)
 #endif /* DBG */
 
 
+VOID
+LdrpInitLoader(VOID)
+{
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  UNICODE_STRING LinkTarget;
+  UNICODE_STRING Name;
+  HANDLE LinkHandle;
+  ULONG Length;
+  NTSTATUS Status;
+
+  DPRINT("LdrpInitLoader() called\n");
+
+  /* Get handle to the 'KnownDlls' directory */
+  RtlInitUnicodeString(&Name,
+                      L"\\KnownDlls");
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &Name,
+                            OBJ_CASE_INSENSITIVE,
+                            NULL,
+                            NULL);
+  Status = NtOpenDirectoryObject(&LdrpKnownDllsDirHandle,
+                                DIRECTORY_QUERY | DIRECTORY_TRAVERSE,
+                                &ObjectAttributes);
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT("NtOpenDirectoryObject() failed (Status %lx)\n", Status);
+      LdrpKnownDllsDirHandle = NULL;
+      return;
+    }
+
+  /* Allocate target name string */
+  LinkTarget.Length = 0;
+  LinkTarget.MaximumLength = MAX_PATH * sizeof(WCHAR);
+  LinkTarget.Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
+                                     0,
+                                     MAX_PATH * sizeof(WCHAR));
+  if (LinkTarget.Buffer == NULL)
+    {
+      NtClose(LdrpKnownDllsDirHandle);
+      LdrpKnownDllsDirHandle = NULL;
+      return;
+    }
+
+  RtlInitUnicodeString(&Name,
+                      L"KnownDllPath");
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &Name,
+                            OBJ_CASE_INSENSITIVE | OBJ_OPENLINK,
+                            LdrpKnownDllsDirHandle,
+                            NULL);
+  Status = NtOpenSymbolicLinkObject(&LinkHandle,
+                                   SYMBOLIC_LINK_ALL_ACCESS,
+                                   &ObjectAttributes);
+  if (!NT_SUCCESS(Status))
+    {
+      RtlFreeUnicodeString(&LinkTarget);
+      NtClose(LdrpKnownDllsDirHandle);
+      LdrpKnownDllsDirHandle = NULL;
+      return;
+    }
+
+  Status = NtQuerySymbolicLinkObject(LinkHandle,
+                                    &LinkTarget,
+                                    &Length);
+  NtClose(LinkHandle);
+  if (!NT_SUCCESS(Status))
+    {
+      RtlFreeUnicodeString(&LinkTarget);
+      NtClose(LdrpKnownDllsDirHandle);
+      LdrpKnownDllsDirHandle = NULL;
+    }
+
+  RtlCreateUnicodeString(&LdrpKnownDllPath,
+                        LinkTarget.Buffer);
+
+  RtlFreeUnicodeString(&LinkTarget);
+
+  DPRINT("LdrpInitLoader() done\n");
+}
+
+
 /***************************************************************************
  * NAME                                                         LOCAL
  *      LdrAdjustDllName
@@ -140,8 +227,9 @@ LdrAdjustDllName (PUNICODE_STRING FullDllName,
 }
 
 PLDR_MODULE
-LdrAddModuleEntry(PVOID ImageBase, PIMAGE_NT_HEADERS NTHeaders,
-                  PWSTR FullDosName)
+LdrAddModuleEntry(PVOID ImageBase,
+                 PIMAGE_NT_HEADERS NTHeaders,
+                 PWSTR FullDosName)
 {
   PLDR_MODULE           Module;
   Module = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof (LDR_MODULE));
@@ -183,75 +271,83 @@ LdrAddModuleEntry(PVOID ImageBase, PIMAGE_NT_HEADERS NTHeaders,
   return(Module);
 }
 
-/***************************************************************************
- * NAME                                                         EXPORTED
- *      LdrLoadDll
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- *
- * RETURN VALUE
- *
- * REVISIONS
- *
- * NOTE
- *
- */
 
-NTSTATUS STDCALL
-LdrLoadDll (IN PWSTR SearchPath OPTIONAL,
-            IN ULONG LoadFlags,
-            IN PUNICODE_STRING Name,
-            OUT PVOID *BaseAddress OPTIONAL)
+static NTSTATUS
+LdrpMapKnownDll(IN PUNICODE_STRING DllName,
+               OUT PUNICODE_STRING FullDosName,
+               OUT PHANDLE SectionHandle)
+{
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  UNICODE_STRING ObjectDirName;
+  NTSTATUS Status;
+
+  DPRINT("LdrpMapKnownDll() called\n");
+
+  if (LdrpKnownDllsDirHandle == NULL)
+    {
+      DPRINT("Invalid 'KnownDlls' directory\n");
+      return STATUS_UNSUCCESSFUL;
+    }
+
+  DPRINT("LdrpKnownDllPath '%wZ'\n", &LdrpKnownDllPath);
+
+  InitializeObjectAttributes(&ObjectAttributes,
+                            DllName,
+                            OBJ_CASE_INSENSITIVE,
+                            LdrpKnownDllsDirHandle,
+                            NULL);
+  Status = NtOpenSection(SectionHandle,
+                        SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE,
+                        &ObjectAttributes);
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT("NtOpenSection() failed for '%wZ' (Status %lx)\n", DllName, Status);
+      return Status;
+    }
+
+  FullDosName->Length = LdrpKnownDllPath.Length + DllName->Length + sizeof(WCHAR);
+  FullDosName->MaximumLength = FullDosName->Length + sizeof(WCHAR);
+  FullDosName->Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
+                                       0,
+                                       FullDosName->MaximumLength);
+  if (FullDosName->Buffer == NULL)
+    {
+      FullDosName->Length = 0;
+      FullDosName->MaximumLength = 0;
+      return STATUS_SUCCESS;
+    }
+
+  wcscpy(FullDosName->Buffer, LdrpKnownDllPath.Buffer);
+  wcscat(FullDosName->Buffer, L"\\");
+  wcscat(FullDosName->Buffer, DllName->Buffer);
+
+  DPRINT("FullDosName '%wZ'\n", FullDosName);
+
+  DPRINT("LdrpMapKnownDll() done\n");
+
+  return STATUS_SUCCESS;
+}
+
+
+static NTSTATUS
+LdrpMapDllImageFile(IN PWSTR SearchPath OPTIONAL,
+                   IN PUNICODE_STRING DllName,
+                   OUT PUNICODE_STRING FullDosName,
+                   OUT PHANDLE SectionHandle)
 {
   WCHAR                 SearchPathBuffer[MAX_PATH];
-  WCHAR                 FullDosName[MAX_PATH];
-  UNICODE_STRING        AdjustedName;
+  WCHAR                 DosName[MAX_PATH];
   UNICODE_STRING        FullNtFileName;
   OBJECT_ATTRIBUTES     FileObjectAttributes;
+  HANDLE                FileHandle;
   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;
-    }
+  ULONG                 ImageSize;
+  NTSTATUS Status;
 
-
-  *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 (LdrFindEntryForName(&AdjustedName, &Module) == 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);
+  DPRINT("LdrpMapDllImageFile() called\n");
 
   if (SearchPath == NULL)
     {
@@ -263,38 +359,36 @@ LdrLoadDll (IN PWSTR SearchPath OPTIONAL,
     }
 
   DPRINT("SearchPath %S\n", SearchPath);
-  
+
   if (RtlDosSearchPath_U (SearchPath,
-                          AdjustedName.Buffer,
+                          DllName->Buffer,
                           NULL,
                           MAX_PATH,
-                          FullDosName,
+                          DosName,
                           NULL) == 0)
     return STATUS_DLL_NOT_FOUND;
-  
-  DPRINT("FullDosName %S\n", FullDosName);
-  
-  RtlFreeUnicodeString (&AdjustedName);
-  
-  if (!RtlDosPathNameToNtPathName_U (FullDosName,
+
+  DPRINT("DosName %S\n", DosName);
+
+  if (!RtlDosPathNameToNtPathName_U (DosName,
                                      &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, 
+                      &FileObjectAttributes,
                       NULL,
                       0,
                       0);
@@ -306,7 +400,7 @@ LdrLoadDll (IN PWSTR SearchPath OPTIONAL,
       return Status;
     }
   RtlFreeUnicodeString (&FullNtFileName);
-  
+
   Status = ZwReadFile(FileHandle,
                       0,
                       0,
@@ -345,46 +439,147 @@ LdrLoadDll (IN PWSTR SearchPath OPTIONAL,
   ImageSize = NTHeaders->OptionalHeader.SizeOfImage;
   
   DPRINT("ImageBase 0x%08x\n", ImageBase);
-        
+  
   /*
    * Create a section for dll.
    */
-  Status = ZwCreateSection(&SectionHandle,
+  Status = ZwCreateSection(SectionHandle,
                            SECTION_ALL_ACCESS,
                            NULL,
                            NULL,
                            PAGE_READWRITE,
                            SEC_COMMIT | SEC_IMAGE,
                            FileHandle);
+  ZwClose(FileHandle);
+
   if (!NT_SUCCESS(Status))
     {
       DPRINT("NTDLL create section failed: Status = 0x%08x\n", Status);
-      ZwClose(FileHandle);
       return Status;
     }
-  
+
+  RtlCreateUnicodeString(FullDosName,
+                        DosName);
+
+  return Status;
+}
+
+
+
+/***************************************************************************
+ * NAME                                                         EXPORTED
+ *      LdrLoadDll
+ *
+ * DESCRIPTION
+ *
+ * ARGUMENTS
+ *
+ * RETURN VALUE
+ *
+ * REVISIONS
+ *
+ * NOTE
+ *
+ */
+
+NTSTATUS STDCALL
+LdrLoadDll (IN PWSTR SearchPath OPTIONAL,
+            IN ULONG LoadFlags,
+            IN PUNICODE_STRING Name,
+            OUT PVOID *BaseAddress OPTIONAL)
+{
+  UNICODE_STRING        FullDosName;
+  UNICODE_STRING        AdjustedName;
+  NTSTATUS              Status;
+  PIMAGE_NT_HEADERS     NTHeaders;
+  ULONG                 ViewSize;
+  PVOID                 ImageBase;
+  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 (LdrFindEntryForName(&AdjustedName, &Module) == 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);
+
+  /* Open or create dll image section */
+  Status = LdrpMapKnownDll(&AdjustedName,
+                          &FullDosName,
+                          &SectionHandle);
+  if (!NT_SUCCESS(Status))
+    {
+      Status = LdrpMapDllImageFile(SearchPath,
+                                  &AdjustedName,
+                                  &FullDosName,
+                                  &SectionHandle);
+    }
+
+  RtlFreeUnicodeString(&AdjustedName);
+
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT1("Failed to create or open dll section (Status %lx)\n", Status);
+      return Status;
+    }
+
   /*
    * Map the dll into the process.
    */
-  InitialViewSize = 0;
+  ViewSize = 0;
   ImageBase = 0;
-  Status = ZwMapViewOfSection(SectionHandle,
+  Status = NtMapViewOfSection(SectionHandle,
                               NtCurrentProcess(),
                               &ImageBase,
                               0,
-                              InitialViewSize,
+                              0,
                               NULL,
-                              &InitialViewSize,
+                              &ViewSize,
                               0,
                               MEM_COMMIT,
                               PAGE_READWRITE);
   if (!NT_SUCCESS(Status))
     {
       DbgPrint("NTDLL.LDR: map view of section failed (Status %x)\n", Status);
-      ZwClose(FileHandle);
+      RtlFreeUnicodeString(&FullDosName);
+      NtClose(SectionHandle);
       return(Status);
     }
-  ZwClose(FileHandle);
+
+  /* Get and check the NT headers */
+  NTHeaders = RtlImageNtHeader(ImageBase);
+  if (NTHeaders == NULL)
+    {
+      DPRINT1("RtlImageNtHeaders() failed\n");
+      RtlFreeUnicodeString(&FullDosName);
+      return STATUS_UNSUCCESSFUL;
+    }
 
   /* relocate dll and fixup import table */
   if ((NTHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL) ==
@@ -392,13 +587,16 @@ LdrLoadDll (IN PWSTR SearchPath OPTIONAL,
     {
       Entrypoint =
         (PDLLMAIN_FUNC) LdrPEStartup(ImageBase, SectionHandle, &Module,
-                                     FullDosName);
+                                     FullDosName.Buffer);
       if (Entrypoint == NULL)
         {
+          RtlFreeUnicodeString(&FullDosName);
           return(STATUS_UNSUCCESSFUL);
         }
     }
-  
+
+  RtlFreeUnicodeString(&FullDosName);
+
 #ifdef DBG
 
   LdrpLoadUserModuleSymbols(Module);
@@ -1355,174 +1553,6 @@ LdrUnloadDll (IN PVOID BaseAddress)
    return STATUS_UNSUCCESSFUL;
 }
 
-#if 0 /*MOVED_TO_FILE_RES_C*/
-
-NTSTATUS STDCALL
-LdrFindResource_U(PVOID BaseAddress,
-                  PLDR_RESOURCE_INFO ResourceInfo,
-                  ULONG Level,
-                  PIMAGE_RESOURCE_DATA_ENTRY *ResourceDataEntry)
-{
-   PIMAGE_RESOURCE_DIRECTORY ResDir;
-   PIMAGE_RESOURCE_DIRECTORY ResBase;
-   PIMAGE_RESOURCE_DIRECTORY_ENTRY ResEntry;
-   NTSTATUS Status = STATUS_SUCCESS;
-   ULONG EntryCount;
-   PWCHAR ws;
-   ULONG i;
-   ULONG Id;
-
-   DPRINT ("LdrFindResource_U()\n");
-
-   /* Get the pointer to the resource directory */
-   ResDir = (PIMAGE_RESOURCE_DIRECTORY)
-        RtlImageDirectoryEntryToData (BaseAddress,
-                                      TRUE,
-                                      IMAGE_DIRECTORY_ENTRY_RESOURCE,
-                                      &i);
-   if (ResDir == NULL)
-     {
-        return STATUS_RESOURCE_DATA_NOT_FOUND;
-     }
-
-   DPRINT("ResourceDirectory: %x\n", (ULONG)ResDir);
-
-   ResBase = ResDir;
-
-   /* Let's go into resource tree */
-   for (i = 0; i < Level; i++)
-     {
-        DPRINT("ResDir: %x\n", (ULONG)ResDir);
-        Id = ((PULONG)ResourceInfo)[i];
-        EntryCount = ResDir->NumberOfNamedEntries;
-        ResEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(ResDir + 1);
-        DPRINT("ResEntry %x\n", (ULONG)ResEntry);
-        if (Id & 0xFFFF0000)
-          {
-             /* Resource name is a unicode string */
-             for (; EntryCount--; ResEntry++)
-               {
-                  /* Scan entries for equal name */
-                  if (ResEntry->Name & 0x80000000)
-                    {
-                       ws = (PWCHAR)((ULONG)ResDir + (ResEntry->Name & 0x7FFFFFFF));
-                       if (!wcsncmp((PWCHAR)Id, ws + 1, *ws ) &&
-                           wcslen((PWCHAR)Id) == (int)*ws )
-                         {
-                            goto found;
-                         }
-                    }
-               }
-          }
-        else
-          {
-             /* We use ID number instead of string */
-             ResEntry += EntryCount;
-             EntryCount = ResDir->NumberOfIdEntries;
-             for (; EntryCount--; ResEntry++)
-               {
-                  /* Scan entries for equal name */
-                  if (ResEntry->Name == Id)
-                    {
-                     DPRINT("ID entry found %x\n", Id);
-                     goto found;
-                    }
-               }
-          }
-        DPRINT("Error %lu\n", i);
-
-          switch (i)
-          {
-             case 0:
-                return STATUS_RESOURCE_TYPE_NOT_FOUND;
-
-             case 1:
-                return STATUS_RESOURCE_NAME_NOT_FOUND;
-
-             case 2:
-                if (ResDir->NumberOfNamedEntries || ResDir->NumberOfIdEntries)
-                  {
-                     /* Use the first available language */
-                     ResEntry = (IMAGE_RESOURCE_DIRECTORY_ENTRY*)(ResDir + 1);
-                     break;
-                  }
-                return STATUS_RESOURCE_LANG_NOT_FOUND;
-
-             case 3:
-                return STATUS_RESOURCE_DATA_NOT_FOUND;
-
-             default:
-                return STATUS_INVALID_PARAMETER;
-          }
-found:;
-        ResDir = (PIMAGE_RESOURCE_DIRECTORY)((ULONG)ResBase +
-                (ResEntry->OffsetToData & 0x7FFFFFFF));
-     }
-   DPRINT("ResourceDataEntry: %x\n", (ULONG)ResDir);
-
-   if (ResourceDataEntry)
-     {
-        *ResourceDataEntry = (PVOID)ResDir;
-     }
-
-  return Status;
-}
-
-
-NTSTATUS STDCALL
-LdrAccessResource(IN  PVOID BaseAddress,
-                  IN  PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry,
-                  OUT PVOID *Resource OPTIONAL,
-                  OUT PULONG Size OPTIONAL)
-{
-   PIMAGE_SECTION_HEADER Section;
-   PIMAGE_NT_HEADERS NtHeader;
-   ULONG SectionRva;
-   ULONG SectionVa;
-   ULONG DataSize;
-   ULONG Offset = 0;
-   ULONG Data;
-
-   Data = (ULONG)RtlImageDirectoryEntryToData (BaseAddress,
-                                               TRUE,
-                                               IMAGE_DIRECTORY_ENTRY_RESOURCE,
-                                               &DataSize);
-   if (Data == 0)
-        return STATUS_RESOURCE_DATA_NOT_FOUND;
-
-   if ((ULONG)BaseAddress & 1)
-     {
-        /* loaded as ordinary file */
-        NtHeader = RtlImageNtHeader((PVOID)((ULONG)BaseAddress & ~1UL));
-        Offset = (ULONG)BaseAddress - Data + NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
-        Section = RtlImageRvaToSection (NtHeader, BaseAddress, NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress);
-        if (Section == NULL)
-          {
-             return STATUS_RESOURCE_DATA_NOT_FOUND;
-          }
-
-        if (Section->Misc.VirtualSize < ResourceDataEntry->OffsetToData)
-          {
-             SectionRva = RtlImageRvaToSection (NtHeader, BaseAddress, ResourceDataEntry->OffsetToData)->VirtualAddress;
-             SectionVa = RtlImageRvaToVa(NtHeader, BaseAddress, SectionRva, NULL);
-             Offset = SectionRva - SectionVa + Data - Section->VirtualAddress;
-          }
-     }
-
-   if (Resource)
-     {
-        *Resource = (PVOID)(ResourceDataEntry->OffsetToData - Offset + (ULONG)BaseAddress);
-     }
-
-   if (Size)
-     {
-        *Size = ResourceDataEntry->Size;
-     }
-
-   return STATUS_SUCCESS;
-}
-
-#endif /*MOVED_TO_FILE_RES_C*/
 
 NTSTATUS STDCALL
 LdrDisableThreadCalloutsForDll(IN PVOID BaseAddress)
@@ -1554,106 +1584,8 @@ LdrDisableThreadCalloutsForDll(IN PVOID BaseAddress)
     return Status;
 }
 
-#if 0 /*MOVED_TO_FILE_RES_C*/
 
 NTSTATUS STDCALL
-LdrFindResourceDirectory_U (IN PVOID BaseAddress,
-                            WCHAR **name,
-                            DWORD level,
-                            OUT PVOID *addr)
-{
-   PIMAGE_RESOURCE_DIRECTORY ResDir;
-   PIMAGE_RESOURCE_DIRECTORY_ENTRY ResEntry;
-   ULONG EntryCount;
-   ULONG i;
-   NTSTATUS Status = STATUS_SUCCESS;
-   WCHAR *ws;
-
-   /* Get the pointer to the resource directory */
-   ResDir = (PIMAGE_RESOURCE_DIRECTORY)
-        RtlImageDirectoryEntryToData (BaseAddress,
-                                      TRUE,
-                                      IMAGE_DIRECTORY_ENTRY_RESOURCE,
-                                      &i);
-   if (ResDir == NULL)
-     {
-        return STATUS_RESOURCE_DATA_NOT_FOUND;
-     }
-
-   /* Let's go into resource tree */
-   for (i = 0; i < level; i++, name++)
-     {
-        EntryCount = ResDir->NumberOfNamedEntries;
-        ResEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(ResDir + 1);
-        if ((ULONG)(*name) & 0xFFFF0000)
-          {
-             /* Resource name is a unicode string */
-             for (; EntryCount--; ResEntry++)
-               {
-                  /* Scan entries for equal name */
-                  if (ResEntry->Name & 0x80000000)
-                    {
-                       ws = (WCHAR*)((ULONG)ResDir + (ResEntry->Name & 0x7FFFFFFF));
-                       if (!wcsncmp( *name, ws + 1, *ws ) && wcslen( *name ) == (int)*ws )
-                         {
-                            goto found;
-                         }
-                    }
-               }
-          }
-        else
-          {
-             /* We use ID number instead of string */
-             ResEntry += EntryCount;
-             EntryCount = ResDir->NumberOfIdEntries;
-             for (; EntryCount--; ResEntry++)
-               {
-                  /* Scan entries for equal name */
-                  if (ResEntry->Name == (ULONG)(*name))
-                     goto found;
-               }
-          }
-
-          switch (i)
-          {
-             case 0:
-                return STATUS_RESOURCE_TYPE_NOT_FOUND;
-
-             case 1:
-                return STATUS_RESOURCE_NAME_NOT_FOUND;
-
-             case 2:
-                Status = STATUS_RESOURCE_LANG_NOT_FOUND;
-                /* Just use first language entry */
-                if (ResDir->NumberOfNamedEntries || ResDir->NumberOfIdEntries)
-                  {
-                     ResEntry = (IMAGE_RESOURCE_DIRECTORY_ENTRY*)(ResDir + 1);
-                     break;
-                  }
-                return Status;
-
-             case 3:
-                return STATUS_RESOURCE_DATA_NOT_FOUND;
-
-             default:
-                return STATUS_INVALID_PARAMETER;
-          }
-found:;
-        ResDir = (PIMAGE_RESOURCE_DIRECTORY)((ULONG)ResDir + ResEntry->OffsetToData);
-     }
-
-   if (addr)
-     {
-        *addr = (PVOID)ResDir;
-     }
-
-  return Status;
-}
-
-#endif /*MOVED_TO_FILE_RES_C*/
-
-NTSTATUS
-STDCALL
 LdrGetDllHandle(IN ULONG Unknown1,
                 IN ULONG Unknown2,
                 IN PUNICODE_STRING DllName,
@@ -1867,7 +1799,6 @@ NTSTATUS STDCALL
 LdrQueryProcessModuleInformation(IN PMODULE_INFORMATION ModuleInformation OPTIONAL,
                                  IN ULONG Size OPTIONAL,
                                  OUT PULONG ReturnedSize)
-
 {
   PLIST_ENTRY ModuleListHead;
   PLIST_ENTRY Entry;
index 8443b1c..61b164a 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: init.c,v 1.45 2003/02/25 23:08:52 gvg Exp $
+/* $Id: init.c,v 1.46 2003/05/12 19:46:17 ekohl Exp $
  *
  * init.c - Session Manager initialization
  * 
@@ -357,20 +357,227 @@ SmProcessFileRenameList(VOID)
 }
 
 
+static NTSTATUS STDCALL
+SmKnownDllsQueryRoutine(PWSTR ValueName,
+                       ULONG ValueType,
+                       PVOID ValueData,
+                       ULONG ValueLength,
+                       PVOID Context,
+                       PVOID EntryContext)
+{
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  IO_STATUS_BLOCK IoStatusBlock;
+  UNICODE_STRING ImageName;
+  HANDLE FileHandle;
+  HANDLE SectionHandle;
+  NTSTATUS Status;
+
+#ifndef NDEBUG
+  PrintString("ValueName '%S'  Type %lu  Length %lu\n", ValueName, ValueType, ValueLength);
+  PrintString("ValueData '%S'  Context %p  EntryContext %p\n", (PWSTR)ValueData, Context, EntryContext);
+#endif
+
+  /* Ignore the 'DllDirectory' value */
+  if (!_wcsicmp(ValueName, L"DllDirectory"))
+    return STATUS_SUCCESS;
+
+  /* Open the DLL image file */
+  RtlInitUnicodeString(&ImageName,
+                      ValueData);
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &ImageName,
+                            OBJ_CASE_INSENSITIVE,
+                            (HANDLE)Context,
+                            NULL);
+  Status = NtOpenFile(&FileHandle,
+                     SYNCHRONIZE | FILE_EXECUTE,
+                     &ObjectAttributes,
+                     &IoStatusBlock,
+                     FILE_SHARE_READ,
+                     FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE);
+  if (!NT_SUCCESS(Status))
+    {
+#ifndef NDEBUG
+      PrintString("NtOpenFile() failed (Status %lx)\n", Status);
+#endif
+      return STATUS_SUCCESS;
+    }
+
+#ifndef NDEBUG
+  PrintString("Opened file %wZ successfully\n", &ImageName);
+#endif
+
+
+  /* FIXME: Check dll image file */
+
+
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &ImageName,
+                            OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
+                            (HANDLE)EntryContext,
+                            NULL);
+  Status = NtCreateSection(&SectionHandle,
+                          SECTION_ALL_ACCESS,
+                          &ObjectAttributes,
+                          NULL,
+                          PAGE_EXECUTE,
+                          SEC_IMAGE,
+                          FileHandle);
+  if (NT_SUCCESS(Status))
+    {
+#ifndef NDEBUG
+      PrintString("Created section successfully\n");
+#endif
+      NtClose(SectionHandle);
+    }
+
+  NtClose(FileHandle);
+
+  return STATUS_SUCCESS;
+}
+
+
 static NTSTATUS
-SmPreloadDlls(VOID)
+SmLoadKnownDlls(VOID)
 {
+  RTL_QUERY_REGISTRY_TABLE QueryTable[2];
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  IO_STATUS_BLOCK IoStatusBlock;
+  UNICODE_STRING DllDosPath;
+  UNICODE_STRING DllNtPath;
+  UNICODE_STRING Name;
+  HANDLE ObjectDirHandle;
+  HANDLE FileDirHandle;
+  HANDLE SymlinkHandle;
+  NTSTATUS Status;
+
 #ifndef NDEBUG
-  PrintString("SmPreloadDlls() called\n");
+  PrintString("SmLoadKnownDlls() called\n");
 #endif
 
-  /* FIXME: implement it! */
+  /* Create 'KnownDlls' object directory */
+  RtlInitUnicodeString(&Name,
+                      L"\\KnownDlls");
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &Name,
+                            OBJ_PERMANENT | OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
+                            NULL,
+                            NULL);
+  Status = NtCreateDirectoryObject(&ObjectDirHandle,
+                                  DIRECTORY_ALL_ACCESS,
+                                  &ObjectAttributes);
+  if (!NT_SUCCESS(Status))
+    {
+#ifndef NDEBUG
+      PrintString("NtCreateDirectoryObject() failed (Status %lx)\n", Status);
+#endif
+      return Status;
+    }
+
+  RtlInitUnicodeString(&DllDosPath, NULL);
+
+  RtlZeroMemory(&QueryTable,
+               sizeof(QueryTable));
 
+  QueryTable[0].Name = L"DllDirectory";
+  QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
+  QueryTable[0].EntryContext = &DllDosPath;
+
+  Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
+                                 L"\\Session Manager\\KnownDlls",
+                                 QueryTable,
+                                 NULL,
+                                 SmSystemEnvironment);
+  if (!NT_SUCCESS(Status))
+    {
 #ifndef NDEBUG
-  PrintString("SmPreloadDlls() done\n");
+      PrintString("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
 #endif
+      return Status;
+    }
 
-  return(STATUS_SUCCESS);
+#ifndef NDEBUG
+  PrintString("DllDosPath: '%wZ'\n", &DllDosPath);
+#endif
+
+  if (!RtlDosPathNameToNtPathName_U(DllDosPath.Buffer,
+                                   &DllNtPath,
+                                   NULL,
+                                   NULL))
+    {
+#ifndef NDEBUG
+      PrintString("RtlDosPathNameToNtPathName_U() failed\n");
+#endif
+      return STATUS_OBJECT_NAME_INVALID;
+    }
+
+  PrintString("DllNtPath: '%wZ'\n", &DllNtPath);
+
+  /* Open the dll path directory */
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &DllNtPath,
+                            OBJ_CASE_INSENSITIVE,
+                            NULL,
+                            NULL);
+  Status = NtOpenFile(&FileDirHandle,
+                     SYNCHRONIZE | FILE_READ_DATA,
+                     &ObjectAttributes,
+                     &IoStatusBlock,
+                     FILE_SHARE_READ | FILE_SHARE_WRITE,
+                     FILE_SYNCHRONOUS_IO_NONALERT | FILE_DIRECTORY_FILE);
+  if (!NT_SUCCESS(Status))
+    {
+#ifndef NDEBUG
+      PrintString("NtOpenFile() failed (Status %lx)\n", Status);
+#endif
+      return Status;
+    }
+
+  /* Link 'KnownDllPath' the dll path directory */
+  RtlInitUnicodeString(&Name,
+                      L"KnownDllPath");
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &Name,
+                            OBJ_PERMANENT | OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
+                            ObjectDirHandle,
+                            NULL);
+  Status = NtCreateSymbolicLinkObject(&SymlinkHandle,
+                                     SYMBOLIC_LINK_ALL_ACCESS,
+                                     &ObjectAttributes,
+                                     &DllDosPath);
+  if (!NT_SUCCESS(Status))
+    {
+#ifndef NDEBUG
+      PrintString("NtCreateSymbolicLink() failed (Status %lx)\n", Status);
+#endif
+      return Status;
+    }
+
+  NtClose(SymlinkHandle);
+
+  RtlZeroMemory(&QueryTable,
+               sizeof(QueryTable));
+
+  QueryTable[0].QueryRoutine = SmKnownDllsQueryRoutine;
+  QueryTable[0].EntryContext = ObjectDirHandle;
+
+  Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
+                                 L"\\Session Manager\\KnownDlls",
+                                 QueryTable,
+                                 (PVOID)FileDirHandle,
+                                 NULL);
+  if (!NT_SUCCESS(Status))
+    {
+#ifndef NDEBUG
+      PrintString("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
+#endif
+    }
+
+#ifndef NDEBUG
+  PrintString("SmLoadKnownDlls() done\n");
+#endif
+
+  return Status;
 }
 
 
@@ -418,15 +625,15 @@ SmPagingFilesQueryRoutine(PWSTR ValueName,
       MaximumSize.QuadPart = 80 * 4096;
     }
 
-  if (!RtlDosPathNameToNtPathName_U ((LPWSTR)ValueData, 
+  if (!RtlDosPathNameToNtPathName_U ((LPWSTR)ValueData,
                                     &FileName,
                                     NULL,
                                     NULL))
     {
       return (STATUS_SUCCESS);
-    }  
+    }
 
-  DbgPrint("SMSS: Created paging file %wZ with size %dKB\n", 
+  DbgPrint("SMSS: Created paging file %wZ with size %dKB\n",
           &FileName, InitialSize.QuadPart / 1024);
   Status = NtCreatePagingFile(&FileName,
                              &InitialSize,
@@ -516,7 +723,7 @@ SmSetEnvironmentVariables(VOID)
   wcscpy(ValueBuffer,
         SharedUserData->NtSystemRoot);
 
-  /* Cet SystemRoot = "C:\reactos" */
+  /* Set SystemRoot = "C:\reactos" */
   RtlInitUnicodeStringFromLiteral(&EnvVariable,
                       L"SystemRoot");
   RtlInitUnicodeString(&EnvValue,
@@ -618,6 +825,14 @@ InitSessionManager(HANDLE Children[])
       return(Status);
     }
 
+  /* Set environment variables */
+  Status = SmSetEnvironmentVariables();
+  if (!NT_SUCCESS(Status))
+    {
+      PrintString("SM: Failed to set system environment variables (Status %lx)\n", Status);
+      return(Status);
+    }
+
   /* Define symbolic links to kernel devices (MS-DOS names) */
   Status = SmInitDosDevices();
   if (!NT_SUCCESS(Status))
@@ -643,7 +858,7 @@ InitSessionManager(HANDLE Children[])
     }
 
   /* Load the well known DLLs */
-  Status = SmPreloadDlls();
+  Status = SmLoadKnownDlls();
   if (!NT_SUCCESS(Status))
     {
       PrintString("SM: Failed to preload system DLLs (Status %lx)\n", Status);
@@ -662,12 +877,14 @@ InitSessionManager(HANDLE Children[])
   NtInitializeRegistry(FALSE);
 
   /* Set environment variables from registry */
-  Status = SmSetEnvironmentVariables();
+#if 0
+  Status = SmUpdateEnvironment();
   if (!NT_SUCCESS(Status))
     {
-      PrintString("SM: Failed to set system environment variables (Status %lx)\n", Status);
+      PrintString("SM: Failed to update environment variables (Status %lx)\n", Status);
       return(Status);
     }
+#endif
 
   /* Load the subsystems */
   Status = SmLoadSubsystems();
@@ -679,7 +896,7 @@ InitSessionManager(HANDLE Children[])
 
   /* Run csrss.exe */
   RtlInitUnicodeStringFromLiteral(&UnicodeString,
-                      L"\\CsrssInitDone");
+                                 L"\\CsrssInitDone");
   InitializeObjectAttributes(&ObjectAttributes,
                             &UnicodeString,
                             EVENT_ALL_ACCESS,