diff --git a/reactos/include/ntdll/ldr.h b/reactos/include/ntdll/ldr.h index 25545686231..7886313351e 100644 --- a/reactos/include/ntdll/ldr.h +++ b/reactos/include/ntdll/ldr.h @@ -1,18 +1,26 @@ typedef NTSTATUS (*PEPFUNC)(PPEB); -typedef struct _DLL +typedef struct _LDR_MODULE { - PIMAGE_NT_HEADERS Headers; - PVOID BaseAddress; - HANDLE SectionHandle; - struct _DLL* Prev; - struct _DLL* Next; - UINT ReferenceCount; -} DLL, *PDLL; + LIST_ENTRY InLoadOrderModuleList; + LIST_ENTRY InMemoryOrderModuleList; // not used + LIST_ENTRY InInitializationOrderModuleList; // not used + PVOID BaseAddress; + ULONG EntryPoint; + ULONG SizeOfImage; + UNICODE_STRING FullDllName; + UNICODE_STRING BaseDllName; + ULONG Flags; + SHORT LoadCount; + SHORT TlsIndex; + HANDLE SectionHandle; + ULONG CheckSum; + ULONG TimeDateStamp; +} LDR_MODULE, *PLDR_MODULE; + #define RVA(m, b) ((ULONG)b + m) -extern DLL LdrDllListHead; PEPFUNC LdrPEStartup(PVOID ImageBase, HANDLE SectionHandle); NTSTATUS LdrMapSections(HANDLE ProcessHandle, @@ -25,8 +33,7 @@ NTSTATUS LdrMapNTDllForProcess(HANDLE ProcessHandle, NTSTATUS STDCALL -LdrDisableThreadCalloutsForDll (IN PVOID BaseAddress, - IN BOOLEAN Disable); +LdrDisableThreadCalloutsForDll (IN PVOID BaseAddress); NTSTATUS STDCALL LdrGetDllHandle (IN ULONG Unknown1, @@ -52,6 +59,12 @@ LdrLoadDll (IN PWSTR SearchPath OPTIONAL, IN PUNICODE_STRING Name, OUT PVOID *BaseAddress OPTIONAL); +NTSTATUS STDCALL +LdrShutdownProcess (VOID); + +NTSTATUS STDCALL +LdrShutdownThread (VOID); + NTSTATUS STDCALL LdrUnloadDll (IN PVOID BaseAddress); diff --git a/reactos/include/ntdll/ntdll.h b/reactos/include/ntdll/ntdll.h index 1921722e586..99a2b67df6e 100644 --- a/reactos/include/ntdll/ntdll.h +++ b/reactos/include/ntdll/ntdll.h @@ -3,6 +3,12 @@ #define UNIMPLEMENTED DbgPrint("%s in %s:%d is unimplemented\n",__FUNCTION__,__FILE__,__LINE__); +#ifndef NASSERT +#define assert(x) if (!(x)) {DbgPrint("Assertion "#x" failed at %s:%d\n", __FILE__,__LINE__); for(;;);} +#else +#define assert(x) +#endif + #ifdef NDEBUG #define DPRINT(args...) #define CHECKPOINT diff --git a/reactos/lib/kernel32/misc/ldr.c b/reactos/lib/kernel32/misc/ldr.c index d1e115c9c7b..50cf456f537 100644 --- a/reactos/lib/kernel32/misc/ldr.c +++ b/reactos/lib/kernel32/misc/ldr.c @@ -1,4 +1,4 @@ -/* $Id: ldr.c,v 1.8 2000/08/27 22:37:45 ekohl Exp $ +/* $Id: ldr.c,v 1.9 2000/09/01 17:09:19 ekohl Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT : ReactOS user mode libraries @@ -18,6 +18,24 @@ /* FUNCTIONS ****************************************************************/ +WINBOOL +STDCALL +DisableThreadLibraryCalls ( + HMODULE hLibModule + ) +{ + NTSTATUS Status; + + Status = LdrDisableThreadCalloutsForDll ((PVOID)hLibModule); + if (!NT_SUCCESS (Status)) + { + SetLastErrorByStatus (Status); + return FALSE; + } + return TRUE; +} + + HINSTANCE STDCALL LoadLibraryA ( @@ -38,7 +56,8 @@ LoadLibraryExA ( { UNICODE_STRING LibFileNameU; ANSI_STRING LibFileName; - HINSTANCE hInstance; + HINSTANCE hInst; + NTSTATUS Status; RtlInitAnsiString (&LibFileName, (LPSTR)lpLibFileName); @@ -53,13 +72,20 @@ LoadLibraryExA ( &LibFileName, TRUE); - hInstance = LoadLibraryExW (LibFileNameU.Buffer, - hFile, - dwFlags); + Status = LdrLoadDll(NULL, + dwFlags, + &LibFileNameU, + (PVOID*)&hInst); RtlFreeUnicodeString (&LibFileNameU); - return hInstance; + if ( !NT_SUCCESS(Status)) + { + SetLastErrorByStatus (Status); + return NULL; + } + + return hInst; } @@ -81,42 +107,15 @@ LoadLibraryExW ( DWORD dwFlags ) { - HINSTANCE hInst; - int i; - LPWSTR lpDllName; - NTSTATUS Status; UNICODE_STRING DllName; + HINSTANCE hInst; + NTSTATUS Status; if ( lpLibFileName == NULL ) return NULL; - i = wcslen (lpLibFileName); -// full path specified - if ( lpLibFileName[2] == L':' ) { - lpDllName = HeapAlloc(GetProcessHeap(),0,(i+3)*sizeof(WCHAR)); - wcscpy (lpDllName,L"\\??\\"); - wcscat (lpDllName,lpLibFileName); - } -// point at the end means no extension - else if ( lpLibFileName[i-1] == L'.' ) { - lpDllName = HeapAlloc(GetProcessHeap(),0,(i+1)*sizeof(WCHAR)); - wcscpy (lpDllName,lpLibFileName); - lpDllName[i-1] = 0; - } -// no extension - else if (i > 3 && lpLibFileName[i-3] != L'.' ) { - lpDllName = HeapAlloc(GetProcessHeap(),0,(i+4)*sizeof(WCHAR)); - wcscpy (lpDllName,lpLibFileName); - wcscat (lpDllName,L".dll"); - } - else { - lpDllName = HeapAlloc(GetProcessHeap(),0,(i+1)*sizeof(WCHAR)); - wcscpy (lpDllName,lpLibFileName); - } - - RtlInitUnicodeString (&DllName, lpDllName); + RtlInitUnicodeString (&DllName, (LPWSTR)lpLibFileName); Status = LdrLoadDll(NULL, dwFlags, &DllName, (PVOID*)&hInst); - HeapFree(GetProcessHeap(), 0, lpDllName); if ( !NT_SUCCESS(Status)) { SetLastErrorByStatus (Status); @@ -171,30 +170,158 @@ FreeLibraryAndExitThread ( DWORD dwExitCode ) { - if ( FreeLibrary(hLibModule) ) ExitThread(dwExitCode); return; } +DWORD +STDCALL +GetModuleFileNameA ( + HINSTANCE hModule, + LPSTR lpFilename, + DWORD nSize + ) +{ + ANSI_STRING FileName; + PLIST_ENTRY ModuleListHead; + PLIST_ENTRY Entry; + PLDR_MODULE Module; + PPEB Peb; + ULONG Length = 0; + + Peb = NtCurrentPeb (); + RtlEnterCriticalSection (Peb->LoaderLock); + + ModuleListHead = &Peb->Ldr->InLoadOrderModuleList; + Entry = ModuleListHead->Flink; + + while (Entry != ModuleListHead) + { + Module = CONTAINING_RECORD(Entry, LDR_MODULE, InLoadOrderModuleList); + if (Module->BaseAddress == (PVOID)hModule) + { + if (nSize * sizeof(WCHAR) < Module->FullDllName.Length) + { + SetLastErrorByStatus (STATUS_BUFFER_TOO_SMALL); + } + else + { + FileName.Length = 0; + FileName.MaximumLength = nSize * sizeof(WCHAR); + FileName.Buffer = lpFilename; + + /* convert unicode string to ansi (or oem) */ + if (bIsFileApiAnsi) + RtlUnicodeStringToAnsiString (&FileName, + &Module->FullDllName, + FALSE); + else + RtlUnicodeStringToOemString (&FileName, + &Module->FullDllName, + FALSE); + Length = Module->FullDllName.Length / sizeof(WCHAR); + } + + RtlLeaveCriticalSection (Peb->LoaderLock); + return Length; + } + + Entry = Entry->Flink; + } + + SetLastErrorByStatus (STATUS_DLL_NOT_FOUND); + RtlLeaveCriticalSection (Peb->LoaderLock); + + + return 0; +} + + +DWORD +STDCALL +GetModuleFileNameW ( + HINSTANCE hModule, + LPWSTR lpFilename, + DWORD nSize + ) +{ + UNICODE_STRING FileName; + PLIST_ENTRY ModuleListHead; + PLIST_ENTRY Entry; + PLDR_MODULE Module; + PPEB Peb; + ULONG Length = 0; + + Peb = NtCurrentPeb (); + RtlEnterCriticalSection (Peb->LoaderLock); + + ModuleListHead = &Peb->Ldr->InLoadOrderModuleList; + Entry = ModuleListHead->Flink; + while (Entry != ModuleListHead) + { + Module = CONTAINING_RECORD(Entry, LDR_MODULE, InLoadOrderModuleList); + + if (Module->BaseAddress == (PVOID)hModule) + { + if (nSize * sizeof(WCHAR) < Module->FullDllName.Length) + { + SetLastErrorByStatus (STATUS_BUFFER_TOO_SMALL); + } + else + { + FileName.Length = 0; + FileName.MaximumLength = nSize * sizeof(WCHAR); + FileName.Buffer = lpFilename; + + RtlCopyUnicodeString (&FileName, + &Module->FullDllName); + Length = Module->FullDllName.Length / sizeof(WCHAR); + } + + RtlLeaveCriticalSection (Peb->LoaderLock); + return Length; + } + + Entry = Entry->Flink; + } + + SetLastErrorByStatus (STATUS_DLL_NOT_FOUND); + RtlLeaveCriticalSection (Peb->LoaderLock); + + return 0; +} + + HMODULE STDCALL GetModuleHandleA ( LPCSTR lpModuleName ) { - UNICODE_STRING ModuleName; + UNICODE_STRING UnicodeName; + ANSI_STRING ModuleName; PVOID BaseAddress; NTSTATUS Status; - RtlCreateUnicodeStringFromAsciiz (&ModuleName, - (LPSTR)lpModuleName); + RtlInitAnsiString (&ModuleName, + (LPSTR)lpModuleName); + + /* convert ansi (or oem) string to unicode */ + if (bIsFileApiAnsi) + RtlAnsiStringToUnicodeString (&UnicodeName, + &ModuleName, + TRUE); + else + RtlOemStringToUnicodeString (&UnicodeName, + &ModuleName, + TRUE); Status = LdrGetDllHandle (0, 0, - &ModuleName, + &UnicodeName, &BaseAddress); - RtlFreeUnicodeString (&ModuleName); + RtlFreeUnicodeString (&UnicodeName); if (!NT_SUCCESS(Status)) { diff --git a/reactos/lib/kernel32/misc/stubs.c b/reactos/lib/kernel32/misc/stubs.c index 2672d3caa98..8cd3b6d5754 100644 --- a/reactos/lib/kernel32/misc/stubs.c +++ b/reactos/lib/kernel32/misc/stubs.c @@ -1,4 +1,4 @@ -/* $Id: stubs.c,v 1.20 2000/08/27 22:37:45 ekohl Exp $ +/* $Id: stubs.c,v 1.21 2000/09/01 17:09:19 ekohl Exp $ * * KERNEL32.DLL stubs (unimplemented functions) * Remove from this file, if you implement them. @@ -1485,32 +1485,6 @@ GetMailslotInfo ( } -DWORD -STDCALL -GetModuleFileNameW ( - HINSTANCE hModule, - LPWSTR lpFilename, - DWORD nSize - ) -{ - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return 0; -} - - -DWORD -STDCALL -GetModuleFileNameA ( - HINSTANCE hModule, - LPSTR lpFilename, - DWORD nSize - ) -{ - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return 0; -} - - WINBOOL STDCALL GetNamedPipeHandleStateW ( diff --git a/reactos/lib/kernel32/thread/thread.c b/reactos/lib/kernel32/thread/thread.c index 3a71d2e4e11..8baeafcc7f9 100644 --- a/reactos/lib/kernel32/thread/thread.c +++ b/reactos/lib/kernel32/thread/thread.c @@ -1,4 +1,4 @@ -/* $Id: thread.c,v 1.17 2000/07/01 17:07:02 ea Exp $ +/* $Id: thread.c,v 1.18 2000/09/01 17:09:50 ekohl Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries @@ -364,28 +364,4 @@ int STDCALL GetThreadPriority(HANDLE hThread) return ThreadBasic.BasePriority; } - -/* FIXME */ -WINBOOL -STDCALL -DisableThreadLibraryCalls ( - HMODULE hLibModule - ) -{ - NTSTATUS Status; - - Status = LdrDisableThreadCalloutsForDll ( - (PVOID) hLibModule, - TRUE - ); - if (!NT_SUCCESS (Status)) - { - SetLastErrorByStatus (Status); - return FALSE; - } - return TRUE; -} - - - /* EOF */ diff --git a/reactos/lib/ntdll/def/ntdll.def b/reactos/lib/ntdll/def/ntdll.def index e735bef1678..ddcca286f7e 100644 --- a/reactos/lib/ntdll/def/ntdll.def +++ b/reactos/lib/ntdll/def/ntdll.def @@ -1,4 +1,4 @@ -; $Id: ntdll.def,v 1.63 2000/08/28 21:46:55 ekohl Exp $ +; $Id: ntdll.def,v 1.64 2000/09/01 17:04:47 ekohl Exp $ ; ; ReactOS Operating System ; @@ -33,7 +33,7 @@ DbgUserBreakPoint@0 ;KiUserCallbackDispatcher ;KiUserExceptionDispatcher LdrAccessResource@16 -LdrDisableThreadCalloutsForDll@8 +LdrDisableThreadCalloutsForDll@4 ;LdrEnumResources ;LdrFindEntryForAddress ;LdrFindResourceDirectory_U @@ -45,10 +45,10 @@ LdrLoadDll@16 ;LdrProcessRelocationBlock ;LdrQueryImageFileExecutionOptions ;LdrQueryProcessModuleInformation -;LdrShutdownProcess -;LdrShutdownThread +LdrShutdownProcess@0 +LdrShutdownThread@0 LdrUnloadDll@4 -;LdrVerifyImageMatchesChecksum +;LdrVerifyImageMatchesChecksum@16 NlsAnsiCodePage DATA NlsMbCodePageTag DATA NlsMbOemCodePageTag DATA @@ -395,7 +395,7 @@ RtlFindClearBits@12 RtlFindClearBitsAndSet@12 RtlFindLongestRunClear@8 RtlFindLongestRunSet@8 -;RtlFindMessage +;RtlFindMessage@20 RtlFindSetBits@12 RtlFindSetBitsAndClear@12 RtlFirstFreeAce@8 diff --git a/reactos/lib/ntdll/def/ntdll.edf b/reactos/lib/ntdll/def/ntdll.edf index 4a732d91649..9e5387206cc 100644 --- a/reactos/lib/ntdll/def/ntdll.edf +++ b/reactos/lib/ntdll/def/ntdll.edf @@ -1,4 +1,4 @@ -; $Id: ntdll.edf,v 1.52 2000/08/28 21:46:55 ekohl Exp $ +; $Id: ntdll.edf,v 1.53 2000/09/01 17:04:47 ekohl Exp $ ; ; ReactOS Operating System ; @@ -33,7 +33,7 @@ DbgUserBreakPoint=DbgUserBreakPoint@0 ;KiUserCallbackDispatcher ;KiUserExceptionDispatcher LdrAccessResource=LdrAccessResource@16 -LdrDisableThreadCalloutsForDll=LdrDisableThreadCalloutsForDll@8 +LdrDisableThreadCalloutsForDll=LdrDisableThreadCalloutsForDll@4 ;LdrEnumResources ;LdrFindEntryForAddress ;LdrFindResourceDirectory_U @@ -45,10 +45,10 @@ LdrLoadDll=LdrLoadDll@16 ;LdrProcessRelocationBlock ;LdrQueryImageFileExecutionOptions ;LdrQueryProcessModuleInformation -;LdrShutdownProcess -;LdrShutdownThread +LdrShutdownProcess=LdrShutdownProcess@0 +LdrShutdownThread=LdrShutdownThread@0 LdrUnloadDll=LdrUnloadDll@4 -;LdrVerifyImageMatchesChecksum +;LdrVerifyImageMatchesChecksum@16 NlsAnsiCodePage DATA NlsMbCodePageTag DATA NlsMbOemCodePageTag DATA diff --git a/reactos/lib/ntdll/ldr/startup.c b/reactos/lib/ntdll/ldr/startup.c index 863f1ce0c0a..1667b0cbf3d 100644 --- a/reactos/lib/ntdll/ldr/startup.c +++ b/reactos/lib/ntdll/ldr/startup.c @@ -1,4 +1,4 @@ -/* $Id: startup.c,v 1.29 2000/08/12 19:33:18 dwelch Exp $ +/* $Id: startup.c,v 1.30 2000/09/01 17:05:09 ekohl Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -17,6 +17,7 @@ #include #include #include +#include #define NDEBUG #include @@ -26,10 +27,11 @@ VOID RtlInitializeHeapManager (VOID); /* GLOBALS *******************************************************************/ -DLL LdrDllListHead; + extern unsigned int _image_base__; static CRITICAL_SECTION PebLock; +static CRITICAL_SECTION LoaderLock; ULONG NtGlobalFlag = 0; @@ -42,23 +44,20 @@ LdrInitializeThunk (ULONG Unknown1, ULONG Unknown3, ULONG Unknown4) { + PIMAGE_NT_HEADERS NTHeaders; PEPFUNC EntryPoint; PIMAGE_DOS_HEADER PEDosHeader; NTSTATUS Status; - PIMAGE_NT_HEADERS NTHeaders; PVOID ImageBase; PPEB Peb; + PLDR_MODULE NtModule; // ntdll + PLDR_MODULE ExeModule; // executable + PKUSER_SHARED_DATA SharedUserData = + (PKUSER_SHARED_DATA)USER_SHARED_DATA_BASE; + WCHAR FullNtDllPath[MAX_PATH]; DPRINT("LdrInitializeThunk()\n"); - LdrDllListHead.BaseAddress = (PVOID)&_image_base__; - LdrDllListHead.Prev = &LdrDllListHead; - LdrDllListHead.Next = &LdrDllListHead; - LdrDllListHead.SectionHandle = NULL; - PEDosHeader = (PIMAGE_DOS_HEADER)LdrDllListHead.BaseAddress; - LdrDllListHead.Headers = (PIMAGE_NT_HEADERS)(LdrDllListHead.BaseAddress + - PEDosHeader->e_lfanew); - Peb = (PPEB)(PEB_BASE); DPRINT("Peb %x\n", Peb); ImageBase = Peb->ImageBaseAddress; @@ -116,7 +115,107 @@ LdrInitializeThunk (ULONG Unknown1, Peb->FastPebLockRoutine = (PPEBLOCKROUTINE)RtlEnterCriticalSection; Peb->FastPebUnlockRoutine = (PPEBLOCKROUTINE)RtlLeaveCriticalSection; + /* initalize loader lock */ + RtlInitializeCriticalSection (&LoaderLock); + Peb->LoaderLock = &LoaderLock; + + /* create loader information */ + Peb->Ldr = (PPEB_LDR_DATA)RtlAllocateHeap (Peb->ProcessHeap, + 0, + sizeof(PEB_LDR_DATA)); + if (Peb->Ldr == NULL) + { + DbgPrint("Failed to create loader data\n"); + ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL); + } + Peb->Ldr->Length = sizeof(PEB_LDR_DATA); + Peb->Ldr->Initialized = FALSE; + Peb->Ldr->SsHandle = NULL; + InitializeListHead(&Peb->Ldr->InLoadOrderModuleList); + InitializeListHead(&Peb->Ldr->InMemoryOrderModuleList); + InitializeListHead(&Peb->Ldr->InInitializationOrderModuleList); + + /* build full ntdll path */ + wcscpy (FullNtDllPath, SharedUserData->NtSystemRoot); + wcscat (FullNtDllPath, L"\\system32\\ntdll.dll"); + + /* add entry for ntdll */ + NtModule = (PLDR_MODULE)RtlAllocateHeap (Peb->ProcessHeap, + 0, + sizeof(LDR_MODULE)); + if (NtModule == NULL) + { + DbgPrint("Failed to create loader module entry (NTDLL)\n"); + ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL); + } + + NtModule->BaseAddress = (PVOID)&_image_base__; + NtModule->EntryPoint = 0; /* no entry point */ + RtlCreateUnicodeString (&NtModule->FullDllName, + FullNtDllPath); + RtlCreateUnicodeString (&NtModule->BaseDllName, + L"ntdll.dll"); + NtModule->Flags = 0; + NtModule->LoadCount = -1; /* don't unload */ + NtModule->TlsIndex = 0; + NtModule->SectionHandle = NULL; + NtModule->CheckSum = 0; + + NTHeaders = RtlImageNtHeader (NtModule->BaseAddress); + NtModule->SizeOfImage = NTHeaders->OptionalHeader.SizeOfImage; + NtModule->TimeDateStamp = NTHeaders->FileHeader.TimeDateStamp; + + InsertTailList(&Peb->Ldr->InLoadOrderModuleList, + &NtModule->InLoadOrderModuleList); + + + /* add entry for executable (becomes first list entry) */ + ExeModule = (PLDR_MODULE)RtlAllocateHeap (Peb->ProcessHeap, + 0, + sizeof(LDR_MODULE)); + if (ExeModule == NULL) + { + DbgPrint("Failed to create loader module infomation\n"); + ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL); + } + ExeModule->BaseAddress = Peb->ImageBaseAddress; + + if ((Peb->ProcessParameters != NULL) && + (Peb->ProcessParameters->ImagePathName.Length != 0)) + { + RtlCreateUnicodeString (&ExeModule->FullDllName, + Peb->ProcessParameters->ImagePathName.Buffer); + RtlCreateUnicodeString (&ExeModule->BaseDllName, + wcsrchr(ExeModule->FullDllName.Buffer, L'\\') + 1); + } + else + { + /* FIXME(???): smss.exe doesn't have a process parameter block */ + RtlCreateUnicodeString (&ExeModule->BaseDllName, + L"smss.exe"); + RtlCreateUnicodeString (&ExeModule->FullDllName, + L"C:\\reactos\\system32\\smss.exe"); + } + + ExeModule->Flags = 0; + ExeModule->LoadCount = -1; /* don't unload */ + ExeModule->TlsIndex = 0; + ExeModule->SectionHandle = NULL; + ExeModule->CheckSum = 0; + + NTHeaders = RtlImageNtHeader (ExeModule->BaseAddress); + ExeModule->SizeOfImage = NTHeaders->OptionalHeader.SizeOfImage; + ExeModule->TimeDateStamp = NTHeaders->FileHeader.TimeDateStamp; + + InsertHeadList(&Peb->Ldr->InLoadOrderModuleList, + &ExeModule->InLoadOrderModuleList); + EntryPoint = LdrPEStartup((PVOID)ImageBase, NULL); + ExeModule->EntryPoint = (ULONG)EntryPoint; + + /* all required dlls are loaded now */ + Peb->Ldr->Initialized = TRUE; + if (EntryPoint == NULL) { DbgPrint("Failed to initialize image\n"); diff --git a/reactos/lib/ntdll/ldr/utils.c b/reactos/lib/ntdll/ldr/utils.c index 2b3b446ecf1..4769b4b6eee 100644 --- a/reactos/lib/ntdll/ldr/utils.c +++ b/reactos/lib/ntdll/ldr/utils.c @@ -1,4 +1,4 @@ -/* $Id: utils.c,v 1.31 2000/08/28 21:47:34 ekohl Exp $ +/* $Id: utils.c,v 1.32 2000/09/01 17:05:09 ekohl Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -8,6 +8,13 @@ * Rex Jolliff (rex@lvcablemodem.com) */ +/* + * TODO: + * - Fix calling of entry points + * - Handle loading flags correctly + * - any more ?? + */ + /* INCLUDES *****************************************************************/ #include @@ -17,13 +24,15 @@ #include #include #include +#include + #ifdef DBG_NTDLL_LDR_UTILS #define NDEBUG #endif #include -/* FUNCTIONS *****************************************************************/ +/* PROTOTYPES ****************************************************************/ /* Type for a DLL's entry point */ @@ -31,18 +40,101 @@ typedef WINBOOL STDCALL (* PDLLMAIN_FUNC) ( - HANDLE hInst, + HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved ); static NTSTATUS -LdrFindDll (PDLL* Dll,PUNICODE_STRING Name); -//LdrFindDll (PDLL* Dll,PCHAR Name); +LdrFindDll (PLDR_MODULE *Dll,PUNICODE_STRING Name); -/********************************************************************** - * NAME + +/* FUNCTIONS *****************************************************************/ + +/*************************************************************************** + * NAME LOCAL + * LdrAdjustDllName + * + * DESCRIPTION + * Adjusts the name of a dll to a fully qualified name. + * + * ARGUMENTS + * FullDllName: Pointer to caller supplied storage for the fully + * qualified dll name. + * DllName: Pointer to the dll name. + * BaseName: TRUE: Only the file name is passed to FullDllName + * FALSE: The full path is preserved in FullDllName + * + * RETURN VALUE + * None + * + * REVISIONS + * + * NOTE + * A given path is not affected by the adjustment, but the file + * name only: + * ntdll --> ntdll.dll + * ntdll. --> ntdll + * ntdll.xyz --> ntdll.xyz + */ + +static VOID +LdrAdjustDllName (PUNICODE_STRING FullDllName, + PUNICODE_STRING DllName, + BOOLEAN BaseName) +{ + WCHAR Buffer[MAX_PATH]; + ULONG Length; + PWCHAR Extension; + PWCHAR Pointer; + + Length = DllName->Length / sizeof(WCHAR); + + if (BaseName == TRUE) + { + /* get the base dll name */ + Pointer = DllName->Buffer + Length; + Extension = Pointer; + + do + { + --Pointer; + } + while (Pointer >= DllName->Buffer && *Pointer != L'\\' && *Pointer != L'/'); + + Pointer++; + Length = Extension - Pointer; + memmove (Buffer, Pointer, Length * sizeof(WCHAR)); + } + else + { + /* get the full dll name */ + memmove (Buffer, DllName->Buffer, DllName->Length); + } + + /* Build the DLL's absolute name */ + Extension = wcsrchr (Buffer, L'.'); + if ((Extension != NULL) && (*Extension == L'.')) + { + /* with extension - remove dot if it's the last character */ + if (Buffer[Length - 1] == L'.') + Length--; + Buffer[Length] = 0; + } + else + { + /* name without extension - assume that it is .dll */ + memmove (Buffer + Length, L".dll", 10); + } + + RtlCreateUnicodeString (FullDllName, + Buffer); +} + + +/*************************************************************************** + * NAME EXPORTED * LdrLoadDll * * DESCRIPTION @@ -63,8 +155,10 @@ LdrLoadDll (IN PWSTR SearchPath OPTIONAL, IN PUNICODE_STRING Name, OUT PVOID *BaseAddress OPTIONAL) { - WCHAR fqname [255] = L"\\SystemRoot\\system32\\"; - UNICODE_STRING UnicodeString; + WCHAR SearchPathBuffer[MAX_PATH]; + WCHAR FullDosName[MAX_PATH]; + UNICODE_STRING AdjustedName; + UNICODE_STRING FullNtFileName; OBJECT_ATTRIBUTES FileObjectAttributes; char BlockBuffer [1024]; PIMAGE_DOS_HEADER DosHeader; @@ -76,11 +170,11 @@ LdrLoadDll (IN PWSTR SearchPath OPTIONAL, HANDLE FileHandle; HANDLE SectionHandle; PDLLMAIN_FUNC Entrypoint = NULL; - PDLL Dll; + PLDR_MODULE Module; if ( Name == NULL ) { - *BaseAddress = LdrDllListHead.BaseAddress; + *BaseAddress = NtCurrentPeb()->ImageBaseAddress; return STATUS_SUCCESS; } @@ -89,42 +183,67 @@ LdrLoadDll (IN PWSTR SearchPath OPTIONAL, DPRINT("LdrLoadDll(Name \"%wZ\" BaseAddress %x)\n", Name, BaseAddress); - /* - * Build the DLL's absolute name - */ - - if (wcsncmp(Name->Buffer, L"\\??\\", 3) != 0) - { - wcscat(fqname, Name->Buffer); - } - else - wcsncpy(fqname, Name->Buffer, 256); - - DPRINT("fqname \"%S\"\n", fqname); + /* adjust the full dll name */ + LdrAdjustDllName (&AdjustedName, + Name, + FALSE); + DPRINT("AdjustedName: %wZ\n", &AdjustedName); /* - * Open the DLL's image file. + * Test if dll is already loaded. */ - if (LdrFindDll(&Dll, Name) == STATUS_SUCCESS) + if (LdrFindDll(&Module, &AdjustedName) == STATUS_SUCCESS) { - DPRINT ("DLL %wZ already loaded.\n", Name); - *BaseAddress = Dll->BaseAddress; + DPRINT("DLL %wZ already loaded.\n", &AdjustedName); + if (Module->LoadCount != -1) + Module->LoadCount++; + *BaseAddress = Module->BaseAddress; return STATUS_SUCCESS; } - RtlInitUnicodeString(&UnicodeString, - fqname); + 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, - & UnicodeString, + & FullNtFileName, 0, NULL, NULL ); - DPRINT("Opening dll \"%wZ\"\n", &UnicodeString); - + DPRINT("Opening dll \"%wZ\"\n", &FullNtFileName); + Status = ZwOpenFile( & FileHandle, FILE_ALL_ACCESS, @@ -136,9 +255,12 @@ LdrLoadDll (IN PWSTR SearchPath OPTIONAL, if (!NT_SUCCESS(Status)) { DbgPrint("Dll open of %wZ failed: Status = 0x%08x\n", - &UnicodeString, Status); + &FullNtFileName, Status); + RtlFreeUnicodeString (&FullNtFileName); return Status; } + RtlFreeUnicodeString (&FullNtFileName); + Status = ZwReadFile( FileHandle, 0, @@ -198,6 +320,7 @@ LdrLoadDll (IN PWSTR SearchPath OPTIONAL, ZwClose(FileHandle); return Status; } + /* * Map the dll into the process. */ @@ -226,34 +349,55 @@ LdrLoadDll (IN PWSTR SearchPath OPTIONAL, } ZwClose(FileHandle); - Dll = RtlAllocateHeap( + Module = RtlAllocateHeap( RtlGetProcessHeap(), 0, - sizeof (DLL) + sizeof (LDR_MODULE) ); - Dll->Headers = NTHeaders; - Dll->BaseAddress = (PVOID)ImageBase; - Dll->Next = LdrDllListHead.Next; - Dll->Prev = & LdrDllListHead; - Dll->ReferenceCount = 1; - LdrDllListHead.Next->Prev = Dll; - LdrDllListHead.Next = Dll; + Module->BaseAddress = (PVOID)ImageBase; + 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 = 0; // ??? + Module->TimeDateStamp = NTHeaders->FileHeader.TimeDateStamp; - if ((Dll->Headers->FileHeader.Characteristics & IMAGE_FILE_DLL) == - IMAGE_FILE_DLL) - { + RtlCreateUnicodeString (&Module->FullDllName, + FullDosName); + RtlCreateUnicodeString (&Module->BaseDllName, + wcsrchr(FullDosName, L'\\') + 1); + InsertTailList(&NtCurrentPeb()->Ldr->InLoadOrderModuleList, + &Module->InLoadOrderModuleList); + + DPRINT ("BaseDllName %wZ\n", &Module->BaseDllName); + + if ((NTHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL) == + IMAGE_FILE_DLL) + { Entrypoint = (PDLLMAIN_FUNC) LdrPEStartup( ImageBase, SectionHandle ); + if (Entrypoint != NULL) { DPRINT("Calling entry point at 0x%08x\n", Entrypoint); if (FALSE == Entrypoint( - Dll->BaseAddress, + Module->BaseAddress, DLL_PROCESS_ATTACH, NULL )) @@ -272,12 +416,14 @@ LdrLoadDll (IN PWSTR SearchPath OPTIONAL, } } - *BaseAddress = Dll->BaseAddress; + Module->EntryPoint = (ULONG)Entrypoint; + + *BaseAddress = Module->BaseAddress; return STATUS_SUCCESS; } -/********************************************************************** +/*************************************************************************** * NAME LOCAL * LdrFindDll * @@ -292,56 +438,38 @@ LdrLoadDll (IN PWSTR SearchPath OPTIONAL, * NOTE * */ -static NTSTATUS LdrFindDll(PDLL* Dll, PUNICODE_STRING Name) +static NTSTATUS LdrFindDll(PLDR_MODULE *Dll, PUNICODE_STRING Name) { - PIMAGE_EXPORT_DIRECTORY ExportDir; - PIMAGE_OPTIONAL_HEADER OptionalHeader; - DLL * current; - UNICODE_STRING DllName; + PLIST_ENTRY ModuleListHead; + PLIST_ENTRY Entry; + PLDR_MODULE Module; DPRINT("NTDLL.LdrFindDll(Name %wZ)\n", Name); - current = & LdrDllListHead; + ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList; + Entry = ModuleListHead->Flink; // NULL is the current process - if ( Name == NULL ) { - *Dll = current; + *Dll = CONTAINING_RECORD(Entry, LDR_MODULE, InLoadOrderModuleList); return STATUS_SUCCESS; } - do + while (Entry != ModuleListHead) { - OptionalHeader = & current->Headers->OptionalHeader; - ExportDir = (PIMAGE_EXPORT_DIRECTORY) - OptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT] - .VirtualAddress; - ExportDir = (PIMAGE_EXPORT_DIRECTORY) - ((ULONG)ExportDir + (ULONG)current->BaseAddress); + Module = CONTAINING_RECORD(Entry, LDR_MODULE, InLoadOrderModuleList); - DPRINT("Scanning %x %x %x\n",ExportDir->Name, - current->BaseAddress, - (ExportDir->Name + current->BaseAddress)); + DPRINT("Scanning %wZ %wZ\n", &Module->BaseDllName, Name); - RtlCreateUnicodeStringFromAsciiz (&DllName, - ExportDir->Name + current->BaseAddress); - - DPRINT("Scanning %wZ %wZ\n", &DllName, Name); - - if (RtlCompareUnicodeString(&DllName, Name, TRUE) == 0) + if (RtlCompareUnicodeString(&Module->BaseDllName, Name, TRUE) == 0) { - *Dll = current; - current->ReferenceCount++; - RtlFreeUnicodeString (&DllName); + *Dll = Module; return STATUS_SUCCESS; } - current = current->Next; - - } while (current != & LdrDllListHead); - - RtlFreeUnicodeString (&DllName); + Entry = Entry->Flink; + } DPRINT("Failed to find dll %wZ\n", Name); @@ -811,14 +939,13 @@ static NTSTATUS LdrFixupImports(PIMAGE_NT_HEADERS NTHeaders, * NOTE * */ -PEPFUNC LdrPEStartup (PVOID ImageBase, +PEPFUNC LdrPEStartup (PVOID ImageBase, HANDLE SectionHandle) { NTSTATUS Status; PEPFUNC EntryPoint = NULL; PIMAGE_DOS_HEADER DosHeader; PIMAGE_NT_HEADERS NTHeaders; - /* * Overlay DOS and WNT headers structures @@ -885,35 +1012,44 @@ PEPFUNC LdrPEStartup (PVOID ImageBase, NTSTATUS STDCALL LdrUnloadDll (IN PVOID BaseAddress) { + PIMAGE_NT_HEADERS NtHeaders; PDLLMAIN_FUNC Entrypoint; - PDLL Dll; + PLIST_ENTRY ModuleListHead; + PLIST_ENTRY Entry; + PLDR_MODULE Module; NTSTATUS Status; if (BaseAddress == NULL) return STATUS_SUCCESS; - Dll = &LdrDllListHead; + ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList; + Entry = ModuleListHead->Flink; - do + while (Entry != ModuleListHead); { - if (Dll->BaseAddress == BaseAddress) + Module = CONTAINING_RECORD(Entry, LDR_MODULE, InLoadOrderModuleList); + if (Module->BaseAddress == BaseAddress) { - - if ( Dll->ReferenceCount > 1 ) + if (Module->LoadCount == -1) { - Dll->ReferenceCount--; + /* never unload this dll */ + return STATUS_SUCCESS; + } + else if (Module->LoadCount > 1) + { + Module->LoadCount--; return STATUS_SUCCESS; } - - if ((Dll->Headers->FileHeader.Characteristics & IMAGE_FILE_DLL ) == IMAGE_FILE_DLL) + NtHeaders = RtlImageNtHeader (Module->BaseAddress); + if ((NtHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL) == IMAGE_FILE_DLL) { - Entrypoint = (PDLLMAIN_FUNC) LdrPEStartup(Dll->BaseAddress, - Dll->SectionHandle); + Entrypoint = (PDLLMAIN_FUNC) LdrPEStartup(Module->BaseAddress, + Module->SectionHandle); if (Entrypoint != NULL) { DPRINT("Calling entry point at 0x%08x\n", Entrypoint); - Entrypoint(Dll->BaseAddress, + Entrypoint(Module->BaseAddress, DLL_PROCESS_DETACH, NULL); } @@ -923,14 +1059,20 @@ LdrUnloadDll (IN PVOID BaseAddress) } } Status = ZwUnmapViewOfSection (NtCurrentProcess (), - Dll->BaseAddress); + Module->BaseAddress); + ZwClose (Module->SectionHandle); + + /* remove the module entry from the list */ + RtlFreeUnicodeString (&Module->FullDllName); + RtlFreeUnicodeString (&Module->BaseDllName); + RemoveEntryList (Entry); + RtlFreeHeap (RtlGetProcessHeap (), 0, Module); - ZwClose (Dll->SectionHandle); return Status; } - Dll = Dll->Next; - } while (Dll != & LdrDllListHead); + Entry = Entry->Flink; + } DPRINT("NTDLL.LDR: Dll not found\n") @@ -1104,16 +1246,36 @@ LdrAccessResource(IN PVOID BaseAddress, } -NTSTATUS -STDCALL -LdrDisableThreadCalloutsForDll ( - IN PVOID BaseAddress, - IN BOOLEAN Disable - ) +NTSTATUS STDCALL +LdrDisableThreadCalloutsForDll (IN PVOID BaseAddress) { - /* FIXME: implement it! */ + PLIST_ENTRY ModuleListHead; + PLIST_ENTRY Entry; + PLDR_MODULE Module; + NTSTATUS Status; - return STATUS_SUCCESS; + Status = STATUS_DLL_NOT_FOUND; + + ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList; + Entry = ModuleListHead->Flink; + + while (Entry != ModuleListHead); + { + Module = CONTAINING_RECORD(Entry, LDR_MODULE, InLoadOrderModuleList); + if (Module->BaseAddress == BaseAddress) + { + if (Module->TlsIndex == 0) + { + Module->Flags |= 0x00040000; + Status = STATUS_SUCCESS; + } + return Status; + } + + Entry = Entry->Flink; + } + + return Status; } @@ -1218,58 +1380,52 @@ LdrGetDllHandle (IN ULONG Unknown1, IN PUNICODE_STRING DllName, OUT PVOID *BaseAddress) { - PIMAGE_EXPORT_DIRECTORY ExportDir; - PIMAGE_OPTIONAL_HEADER OptionalHeader; - ANSI_STRING AnsiName; - DLL *current; + UNICODE_STRING FullDllName; + PLIST_ENTRY ModuleListHead; + PLIST_ENTRY Entry; + PLDR_MODULE Module; DPRINT("LdrGetDllHandle (Unknown1 %x Unknown2 %x DllName %wZ BaseAddress %p)\n", Unknown1, Unknown2, DllName, BaseAddress); - current = &LdrDllListHead; - - // NULL is the current process + /* NULL is the current executable */ if ( DllName == NULL ) { - *BaseAddress = current->BaseAddress; + *BaseAddress = NtCurrentPeb()->ImageBaseAddress; DPRINT1("BaseAddress %x\n", *BaseAddress); return STATUS_SUCCESS; } - RtlUnicodeStringToAnsiString (&AnsiName, DllName, TRUE); + LdrAdjustDllName (&FullDllName, + DllName, + TRUE); - do + ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList; + Entry = ModuleListHead->Flink; + + while (Entry != ModuleListHead) { - OptionalHeader = & current->Headers->OptionalHeader; - ExportDir = (PIMAGE_EXPORT_DIRECTORY) - OptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT] - .VirtualAddress; - ExportDir = (PIMAGE_EXPORT_DIRECTORY) - ((ULONG)ExportDir + (ULONG)current->BaseAddress); + Module = CONTAINING_RECORD(Entry, LDR_MODULE, InLoadOrderModuleList); - DPRINT("Scanning %x %x %x\n",ExportDir->Name, - current->BaseAddress, - (ExportDir->Name + current->BaseAddress)); - DPRINT("Scanning %s %s\n", - ExportDir->Name + current->BaseAddress, AnsiName.Buffer); + DPRINT("Scanning %wZ %wZ\n", + &Module->BaseDllName, + FullDllName); - if (!_stricmp(ExportDir->Name + current->BaseAddress, AnsiName.Buffer)) + if (!RtlCompareUnicodeString(&Module->BaseDllName, &FullDllName, TRUE)) { - RtlFreeAnsiString (&AnsiName); - *BaseAddress = current->BaseAddress; - DPRINT1("BaseAddress %x\n", *BaseAddress); + RtlFreeUnicodeString (&FullDllName); + *BaseAddress = Module->BaseAddress; + DPRINT("BaseAddress %x\n", *BaseAddress); return STATUS_SUCCESS; } - current = current->Next; - - } while (current != & LdrDllListHead); + Entry = Entry->Flink; + } - DbgPrint("Failed to find dll %s\n", AnsiName.Buffer); - RtlFreeAnsiString (&AnsiName); + DbgPrint("Failed to find dll %wZ\n", &FullDllName); + RtlFreeUnicodeString (&FullDllName); *BaseAddress = NULL; - - return STATUS_UNSUCCESSFUL; + return STATUS_DLL_NOT_FOUND; } @@ -1333,4 +1489,20 @@ LdrGetProcedureAddress (IN PVOID BaseAddress, return STATUS_PROCEDURE_NOT_FOUND; } + +NTSTATUS STDCALL +LdrShutdownProcess (VOID) +{ + + return STATUS_SUCCESS; +} + + +NTSTATUS STDCALL +LdrShutdownThread (VOID) +{ + + return STATUS_SUCCESS; +} + /* EOF */ diff --git a/reactos/lib/ntdll/rtl/path.c b/reactos/lib/ntdll/rtl/path.c index b554a998f2d..1c49e61cf9b 100644 --- a/reactos/lib/ntdll/rtl/path.c +++ b/reactos/lib/ntdll/rtl/path.c @@ -1,4 +1,4 @@ -/* $Id: path.c,v 1.5 2000/07/05 18:05:21 ekohl Exp $ +/* $Id: path.c,v 1.6 2000/09/01 17:05:46 ekohl Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries @@ -811,6 +811,10 @@ RtlDoesFileExists_U ( CURDIR CurDir; PWSTR Buffer; + /* only used by replacement code */ + HANDLE FileHandle; + IO_STATUS_BLOCK StatusBlock; + if (!RtlDosPathNameToNtPathName_U (FileName, &NtFileName, NULL, @@ -831,7 +835,19 @@ RtlDoesFileExists_U ( CurDir.Handle, NULL); - Status = NtQueryAttributesFile (&Attr, NULL); + /* FIXME: not implemented yet */ +// Status = NtQueryAttributesFile (&Attr, NULL); + + /* REPLACEMENT start */ + Status = NtOpenFile (&FileHandle, + 0x10001, + &Attr, + &StatusBlock, + 1, + FILE_SYNCHRONOUS_IO_NONALERT); + if (NT_SUCCESS(Status)) + NtClose (FileHandle); + /* REPLACEMENT end */ RtlFreeHeap (RtlGetProcessHeap (), 0, diff --git a/reactos/lib/ntdll/stubs/stubs.c b/reactos/lib/ntdll/stubs/stubs.c index e2fd9635e23..87fececec16 100644 --- a/reactos/lib/ntdll/stubs/stubs.c +++ b/reactos/lib/ntdll/stubs/stubs.c @@ -34,8 +34,6 @@ STUB(LdrFindResourceDirectory_U) STUB(LdrProcessRelocationBlock) STUB(LdrQueryImageFileExecutionOptions) STUB(LdrQueryProcessModuleInformation) -STUB(LdrShutdownProcess) -STUB(LdrShutdownThread) STUB(LdrVerifyImageMatchesChecksum) STUB(NPXEMULATORTABLE) STUB(PfxFindPrefix)