diff --git a/reactos/lib/ntdll/ldr/startup.c b/reactos/lib/ntdll/ldr/startup.c index 004c1cd4908..bc1b5ed8728 100644 --- a/reactos/lib/ntdll/ldr/startup.c +++ b/reactos/lib/ntdll/ldr/startup.c @@ -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); diff --git a/reactos/lib/ntdll/ldr/utils.c b/reactos/lib/ntdll/ldr/utils.c index c7767e86d78..cb4a272865d 100644 --- a/reactos/lib/ntdll/ldr/utils.c +++ b/reactos/lib/ntdll/ldr/utils.c @@ -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 @@ -31,6 +31,12 @@ #endif #include +/* 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; diff --git a/reactos/subsys/smss/init.c b/reactos/subsys/smss/init.c index 8443b1c8fba..61b164aa222 100644 --- a/reactos/subsys/smss/init.c +++ b/reactos/subsys/smss/init.c @@ -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 -SmPreloadDlls(VOID) +static NTSTATUS STDCALL +SmKnownDllsQueryRoutine(PWSTR ValueName, + ULONG ValueType, + PVOID ValueData, + ULONG ValueLength, + PVOID Context, + PVOID EntryContext) { -#ifndef NDEBUG - PrintString("SmPreloadDlls() called\n"); -#endif - - /* FIXME: implement it! */ + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + UNICODE_STRING ImageName; + HANDLE FileHandle; + HANDLE SectionHandle; + NTSTATUS Status; #ifndef NDEBUG - PrintString("SmPreloadDlls() done\n"); + PrintString("ValueName '%S' Type %lu Length %lu\n", ValueName, ValueType, ValueLength); + PrintString("ValueData '%S' Context %p EntryContext %p\n", (PWSTR)ValueData, Context, EntryContext); #endif - return(STATUS_SUCCESS); + /* 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 +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("SmLoadKnownDlls() called\n"); +#endif + + /* 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("RtlQueryRegistryValues() failed (Status %lx)\n", Status); +#endif + return Status; + } + +#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,