Author: fireball Date: Wed Apr 6 21:49:04 2011 New Revision: 51272
URL: http://svn.reactos.org/svn/reactos?rev=51272&view=rev Log: [KERNEL32] - Finish the ldr.c rewrite. Properly implement LoadLibraryExW (which contained some good code pieces added by Alex). Implement BasepLoadLibraryAsDatafile, however it doesn't support redirection yet and a call to load alternate resource module is commented out (it's totally absent in the existing ntdll/ldr API now). - Mark GetDllLoadPath as deprecated, should be removed when SearchPathW is rewritten (or at least, reviewed). The new function to use is BasepGetDllPath.
Modified: trunk/reactos/dll/win32/kernel32/include/kernel32.h trunk/reactos/dll/win32/kernel32/misc/ldr.c
Modified: trunk/reactos/dll/win32/kernel32/include/kernel32.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/include/... ============================================================================== --- trunk/reactos/dll/win32/kernel32/include/kernel32.h [iso-8859-1] (original) +++ trunk/reactos/dll/win32/kernel32/include/kernel32.h [iso-8859-1] Wed Apr 6 21:49:04 2011 @@ -96,6 +96,7 @@ extern UNICODE_STRING BaseDllDirectory; extern UNICODE_STRING BaseDefaultPath; extern UNICODE_STRING BaseDefaultPathAppend; +extern PLDR_DATA_TABLE_ENTRY BasepExeLdrEntry;
extern LPTOP_LEVEL_EXCEPTION_FILTER GlobalTopLevelExceptionFilter;
Modified: trunk/reactos/dll/win32/kernel32/misc/ldr.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/misc/ldr... ============================================================================== --- trunk/reactos/dll/win32/kernel32/misc/ldr.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/kernel32/misc/ldr.c [iso-8859-1] Wed Apr 6 21:49:04 2011 @@ -1,10 +1,9 @@ /* * COPYRIGHT: See COPYING in the top level directory - * PROJECT : ReactOS user mode libraries + * PROJECT : ReactOS system libraries * MODULE : kernel32.dll * FILE : reactos/dll/win32/kernel32/misc/ldr.c * AUTHOR : Aleksey Bragin aleksey@reactos.org - * Ariadne */
#include <k32.h> @@ -26,6 +25,12 @@ #define BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_ERROR 1 #define BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_SUCCESS 2 #define BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_CONTINUE 3 + +VOID +NTAPI +BasepLocateExeLdrEntry(IN PLDR_DATA_TABLE_ENTRY Entry, + IN PVOID Context, + OUT BOOLEAN *StopEnumeration);
/* FUNCTIONS ****************************************************************/
@@ -101,6 +106,8 @@ LPCWSTR lpModuleEnd = NULL; UNICODE_STRING ModuleName; DWORD LastError = GetLastError(); /* GetEnvironmentVariable changes LastError */ + + // FIXME: This function is used only by SearchPathW, and is deprecated and will be deleted ASAP.
if ((lpModule != NULL) && (wcslen(lpModule) > 2) && (lpModule[1] == ':')) { @@ -261,69 +268,113 @@
static NTSTATUS -LoadLibraryAsDatafile(PWSTR path, LPCWSTR name, HMODULE* hmod) -{ - static const WCHAR dotDLL[] = {'.','d','l','l',0}; - - WCHAR filenameW[MAX_PATH]; +BasepLoadLibraryAsDatafile(PWSTR Path, LPCWSTR Name, HMODULE *hModule) +{ + WCHAR FilenameW[MAX_PATH]; HANDLE hFile = INVALID_HANDLE_VALUE; - HANDLE mapping; - HMODULE module; - - *hmod = 0; - - if (!SearchPathW( path, name, dotDLL, sizeof(filenameW) / sizeof(filenameW[0]), - filenameW, NULL )) - { + HANDLE hMapping; + NTSTATUS Status; + PVOID lpBaseAddress; + SIZE_T ViewSize; + //PUNICODE_STRING OriginalName; + //UNICODE_STRING dotDLL = RTL_CONSTANT_STRING(L".DLL"); + + /* Zero out handle value */ + *hModule = 0; + + /*Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE, + Name, + &dotDLL, + RedirName, + RedirName2, + &OriginalName2, + NULL, + NULL, + NULL);*/ + + /* Try to search for it */ + if (!SearchPathW(Path, + Name, + L".DLL", + sizeof(FilenameW) / sizeof(FilenameW[0]), + FilenameW, + NULL)) + { + /* Return last status value directly */ return NtCurrentTeb()->LastStatusValue; }
- hFile = CreateFileW( filenameW, GENERIC_READ, FILE_SHARE_READ, - NULL, OPEN_EXISTING, 0, 0 ); - + /* Open this file we found */ + hFile = CreateFileW(FilenameW, + GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_DELETE, + NULL, + OPEN_EXISTING, + 0, + 0); + + /* If opening failed - return last status value */ if (hFile == INVALID_HANDLE_VALUE) return NtCurrentTeb()->LastStatusValue;
- mapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY, 0, 0, NULL ); - CloseHandle( hFile ); - if (!mapping) return NtCurrentTeb()->LastStatusValue; - - module = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 ); - CloseHandle( mapping ); - if (!module) return NtCurrentTeb()->LastStatusValue; - - /* make sure it's a valid PE file */ - if (!RtlImageNtHeader(module)) - { - UnmapViewOfFile( module ); + /* Create file mapping */ + hMapping = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL); + + /* Close the file handle */ + CloseHandle(hFile); + + /* If creating file mapping failed - return last status value */ + if (!hMapping) return NtCurrentTeb()->LastStatusValue; + + /* Map view of section */ + Status = NtMapViewOfSection(hMapping, + NtCurrentProcess(), + &lpBaseAddress, + 0, + 0, + 0, + &ViewSize, + ViewShare, + 0, + PAGE_READONLY); + + /* Close handle to the section */ + CloseHandle(hMapping); + + /* If mapping view of section failed - return last status value */ + if (!NT_SUCCESS(Status)) return NtCurrentTeb()->LastStatusValue; + + /* Make sure it's a valid PE file */ + if (!RtlImageNtHeader(lpBaseAddress)) + { + /* Unmap the view and return failure status */ + UnmapViewOfFile(lpBaseAddress); return STATUS_INVALID_IMAGE_FORMAT; } - *hmod = (HMODULE)((char *)module + 1); /* set low bit of handle to indicate datafile module */ + + /* Set low bit of handle to indicate datafile module */ + *hModule = (HMODULE)((ULONG_PTR)lpBaseAddress | 1); + + /* Load alternate resource module */ + //LdrLoadAlternateResourceModule(*hModule, FilenameW); + return STATUS_SUCCESS; }
- /* * @implemented */ HINSTANCE WINAPI -LoadLibraryExW ( - LPCWSTR lpLibFileName, - HANDLE hFile, - DWORD dwFlags - ) -{ - UNICODE_STRING DllName; - HINSTANCE hInst; - NTSTATUS Status; - PWSTR SearchPath; +LoadLibraryExW(LPCWSTR lpLibFileName, + HANDLE hFile, + DWORD dwFlags) +{ + UNICODE_STRING DllName; + HINSTANCE hInst; + NTSTATUS Status; + PWSTR SearchPath; ULONG DllCharacteristics = 0; - BOOL FreeString = FALSE; - - (void)hFile; - - if ( lpLibFileName == NULL ) - return NULL; + BOOL FreeString = FALSE;
/* Check for any flags LdrLoadDll might be interested in */ if (dwFlags & DONT_RESOLVE_DLL_REFERENCES) @@ -332,67 +383,101 @@ DllCharacteristics = IMAGE_FILE_EXECUTABLE_IMAGE; }
- dwFlags &= - DONT_RESOLVE_DLL_REFERENCES | - LOAD_LIBRARY_AS_DATAFILE | - LOAD_WITH_ALTERED_SEARCH_PATH; - - SearchPath = GetDllLoadPath( - dwFlags & LOAD_WITH_ALTERED_SEARCH_PATH ? lpLibFileName : NULL); - - RtlInitUnicodeString(&DllName, (LPWSTR)lpLibFileName); - - if (DllName.Buffer[DllName.Length/sizeof(WCHAR) - 1] == L' ') - { - RtlCreateUnicodeString(&DllName, (LPWSTR)lpLibFileName); - while (DllName.Length > sizeof(WCHAR) && - DllName.Buffer[DllName.Length/sizeof(WCHAR) - 1] == L' ') - { - DllName.Length -= sizeof(WCHAR); - } - DllName.Buffer[DllName.Length/sizeof(WCHAR)] = UNICODE_NULL; - FreeString = TRUE; - } - - if (dwFlags & LOAD_LIBRARY_AS_DATAFILE) - { - Status = LdrGetDllHandle(SearchPath, NULL, &DllName, (PVOID*)&hInst); - if (!NT_SUCCESS(Status)) - { - /* The method in load_library_as_datafile allows searching for the - * 'native' libraries only - */ - Status = LoadLibraryAsDatafile(SearchPath, DllName.Buffer, &hInst); - goto done; - } - } - - /* HACK!!! FIXME */ - if (InWindows) - { - /* Call the API Properly */ - Status = LdrLoadDll(SearchPath, - &DllCharacteristics, - &DllName, - (PVOID*)&hInst); - } - else - { - /* Call the ROS API. NOTE: Don't fix this, I have a patch to merge later. */ - Status = LdrLoadDll(SearchPath, &dwFlags, &DllName, (PVOID*)&hInst); - } + /* Build up a unicode dll name from null-terminated string */ + RtlInitUnicodeString(&DllName, (LPWSTR)lpLibFileName); + + /* Lazy-initialize BasepExeLdrEntry */ + if (!BasepExeLdrEntry) + LdrEnumerateLoadedModules(0, BasepLocateExeLdrEntry, NtCurrentPeb()->ImageBaseAddress); + + /* Check if that module is our exe*/ + if (BasepExeLdrEntry && !(dwFlags & LOAD_LIBRARY_AS_DATAFILE) && + DllName.Length == BasepExeLdrEntry->FullDllName.Length) + { + /* Lengths match and it's not a datafile, so perform name comparison */ + if (RtlEqualUnicodeString(&DllName, &BasepExeLdrEntry->FullDllName, TRUE)) + { + /* That's us! */ + return BasepExeLdrEntry->DllBase; + } + } + + /* Check for trailing spaces and remove them if necessary */ + if (DllName.Buffer[DllName.Length/sizeof(WCHAR) - 1] == L' ') + { + RtlCreateUnicodeString(&DllName, (LPWSTR)lpLibFileName); + while (DllName.Length > sizeof(WCHAR) && + DllName.Buffer[DllName.Length/sizeof(WCHAR) - 1] == L' ') + { + DllName.Length -= sizeof(WCHAR); + } + DllName.Buffer[DllName.Length/sizeof(WCHAR)] = UNICODE_NULL; + FreeString = TRUE; + } + + /* Compute the load path */ + SearchPath = BasepGetDllPath((dwFlags & LOAD_WITH_ALTERED_SEARCH_PATH) ? (LPWSTR)lpLibFileName : NULL, + NULL); + + if (!SearchPath) + { + /* Getting DLL path failed, so set last error, free mem and return */ + BaseSetLastNTError(STATUS_NO_MEMORY); + if (FreeString) RtlFreeUnicodeString(&DllName); + return NULL; + } + + _SEH2_TRY + { + if (dwFlags & LOAD_LIBRARY_AS_DATAFILE) + { + /* If the image is loaded as a datafile, try to get its handle */ + Status = LdrGetDllHandle(SearchPath, NULL, &DllName, (PVOID*)&hInst); + if (!NT_SUCCESS(Status)) + { + /* It's not loaded yet - so load it up */ + Status = BasepLoadLibraryAsDatafile(SearchPath, DllName.Buffer, &hInst); + _SEH2_YIELD(goto done;) + } + } + + /* HACK!!! FIXME */ + if (InWindows) + { + /* Call the API Properly */ + Status = LdrLoadDll(SearchPath, + &DllCharacteristics, + &DllName, + (PVOID*)&hInst); + } + else + { + /* Call the ROS API. NOTE: Don't fix this, I have a patch to merge later. */ + Status = LdrLoadDll(SearchPath, &dwFlags, &DllName, (PVOID*)&hInst); + } + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Status = _SEH2_GetExceptionCode(); + } _SEH2_END +
done: - RtlFreeHeap(RtlGetProcessHeap(), 0, SearchPath); - if (FreeString) - RtlFreeUnicodeString(&DllName); - if ( !NT_SUCCESS(Status)) - { - SetLastErrorByStatus (Status); - return NULL; - } - - return hInst; + /* Free SearchPath buffer */ + RtlFreeHeap(RtlGetProcessHeap(), 0, SearchPath); + + /* Free DllName string if it was dynamically allocated */ + if (FreeString) RtlFreeUnicodeString(&DllName); + + /* Set last error in failure case */ + if ( !NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return NULL; + } + + /* Return loaded module handle */ + return hInst; }