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/ld…
==============================================================================
--- 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(a)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;
}