Author: fireball
Date: Sun Apr 3 21:46:42 2011
New Revision: 51246
URL:
http://svn.reactos.org/svn/reactos?rev=51246&view=rev
Log:
[KERNEL32]
- Implement BasepMapModuleHandle and use it in GetModuleFileNameW. Later, it'll be
used by other module and loader related functions in kernel32.
- Wrap a call to RtlImageNtHeader into SEH, because winetest and for some reason FF
installer call it with incorrect handle and expect it to not crash (Windows also has SEH,
but inside RtlImageNtHeader).
- Fix null-termination problems in GetModuleFileNameA, and incorrect calculation of
characters returned in GetModuleFileNameW.
- Various smaller improvements to the rewritten code (missing parenthesis, better variable
names, use pretty LDR_ macros from
http://msdn.microsoft.com/en-us/library/ms684179(v=vs.85).aspx ).
- Thanks for your feedback!
See issue #6079 for more details.
Modified:
trunk/reactos/dll/win32/kernel32/misc/ldr.c
trunk/reactos/include/ndk/ldrtypes.h
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] Sun Apr 3 21:46:42 2011
@@ -41,8 +41,8 @@
if (dwFlags & ~(GET_MODULE_HANDLE_EX_FLAG_PIN |
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT |
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS) ||
- (dwFlags & GET_MODULE_HANDLE_EX_FLAG_PIN &&
- dwFlags & GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT) ||
+ ((dwFlags & GET_MODULE_HANDLE_EX_FLAG_PIN) &&
+ (dwFlags & GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT)) ||
(!lpwModuleName && (dwFlags &
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS))
)
{
@@ -67,6 +67,21 @@
*phModule = (HMODULE)NtCurrentPeb()->ImageBaseAddress;
return BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_SUCCESS;
+}
+
+PVOID
+WINAPI
+BasepMapModuleHandle(HMODULE hModule, BOOLEAN AsDataFile)
+{
+ /* If no handle is provided - use current image base address */
+ if (!hModule) return NtCurrentPeb()->ImageBaseAddress;
+
+ /* Check if it's a normal or a datafile one */
+ if (LDR_IS_DATAFILE(hModule) && !AsDataFile)
+ return NULL;
+
+ /* It'a a normal DLL, just return its handle */
+ return hModule;
}
/**
@@ -394,11 +409,22 @@
BOOL WINAPI FreeLibrary(HINSTANCE hLibModule)
{
NTSTATUS Status;
-
- if ((ULONG_PTR)hLibModule & 1)
- {
- /* This is a LOAD_LIBRARY_AS_DATAFILE module */
- if (RtlImageNtHeader((PVOID)((ULONG_PTR)hLibModule & ~1)))
+ PIMAGE_NT_HEADERS NtHeaders;
+
+ if (LDR_IS_DATAFILE(hLibModule))
+ {
+ // FIXME: This SEH should go inside RtlImageNtHeader instead
+ _SEH2_TRY
+ {
+ /* This is a LOAD_LIBRARY_AS_DATAFILE module, check if it's a valid one
*/
+ NtHeaders = RtlImageNtHeader((PVOID)((ULONG_PTR)hLibModule & ~1));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ NtHeaders = NULL;
+ } _SEH2_END
+
+ if (NtHeaders)
{
/* Unmap view */
Status = NtUnmapViewOfSection(NtCurrentProcess(),
(PVOID)((ULONG_PTR)hLibModule & ~1));
@@ -440,7 +466,7 @@
{
NTSTATUS Status;
- if ((ULONG_PTR)hLibModule & 1)
+ if (LDR_IS_DATAFILE(hLibModule))
{
/* This is a LOAD_LIBRARY_AS_DATAFILE module */
if (RtlImageNtHeader((PVOID)((ULONG_PTR)hLibModule & ~1)))
@@ -472,51 +498,53 @@
LPSTR lpFilename,
DWORD nSize)
{
- UNICODE_STRING filenameW;
+ UNICODE_STRING FilenameW;
ANSI_STRING FilenameA;
NTSTATUS Status;
- DWORD Length = 0;
+ DWORD Length = 0, LengthToCopy;
/* Allocate a unicode buffer */
- filenameW.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, nSize * sizeof(WCHAR));
- if (!filenameW.Buffer)
+ FilenameW.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, nSize * sizeof(WCHAR));
+ if (!FilenameW.Buffer)
{
BaseSetLastNTError(STATUS_NO_MEMORY);
return 0;
}
/* Call unicode API */
- filenameW.Length = GetModuleFileNameW(hModule, filenameW.Buffer, nSize) *
sizeof(WCHAR);
- filenameW.MaximumLength = filenameW.Length + sizeof(WCHAR);
-
- if (filenameW.Length)
+ FilenameW.Length = GetModuleFileNameW(hModule, FilenameW.Buffer, nSize) *
sizeof(WCHAR);
+ FilenameW.MaximumLength = FilenameW.Length + sizeof(WCHAR);
+
+ if (FilenameW.Length)
{
/* Convert to ansi string */
- Status = BasepUnicodeStringTo8BitString(&FilenameA, &filenameW, TRUE);
+ Status = BasepUnicodeStringTo8BitString(&FilenameA, &FilenameW, TRUE);
if (!NT_SUCCESS(Status))
{
/* Set last error, free string and retun failure */
BaseSetLastNTError(Status);
- RtlFreeUnicodeString(&filenameW);
+ RtlFreeUnicodeString(&FilenameW);
return 0;
}
/* Calculate size to copy */
Length = min(nSize, FilenameA.Length);
- /* Remove terminating zero */
- if (Length == FilenameA.Length)
- Length--;
+ /* Include terminating zero */
+ if (nSize > Length)
+ LengthToCopy = Length + 1;
+ else
+ LengthToCopy = nSize;
/* Now copy back to the caller amount he asked */
- RtlMoveMemory(lpFilename, FilenameA.Buffer, Length);
+ RtlMoveMemory(lpFilename, FilenameA.Buffer, LengthToCopy);
/* Free ansi filename */
RtlFreeAnsiString(&FilenameA);
}
/* Free unicode filename */
- RtlFreeHeap(RtlGetProcessHeap(), 0, filenameW.Buffer);
+ RtlFreeHeap(RtlGetProcessHeap(), 0, FilenameW.Buffer);
/* Return length copied */
return Length;
@@ -537,6 +565,8 @@
ULONG Cookie;
PPEB Peb;
+ hModule = BasepMapModuleHandle(hModule, FALSE);
+
/* Upscale nSize from chars to bytes */
nSize *= sizeof(WCHAR);
@@ -587,7 +617,7 @@
/* Release the loader lock */
LdrUnlockLoaderLock(LDR_LOCK_LOADER_LOCK_FLAG_RAISE_STATUS, Cookie);
- return Length;
+ return Length / sizeof(WCHAR);
}
HMODULE
Modified: trunk/reactos/include/ndk/ldrtypes.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/include/ndk/ldrtypes.h?rev…
==============================================================================
--- trunk/reactos/include/ndk/ldrtypes.h [iso-8859-1] (original)
+++ trunk/reactos/include/ndk/ldrtypes.h [iso-8859-1] Sun Apr 3 21:46:42 2011
@@ -78,6 +78,13 @@
// FIXME: THIS SHOULD *NOT* BE USED!
//
#define IMAGE_SCN_TYPE_NOLOAD 0x00000002
+
+//
+// Loader datafile/imagemapping macros
+//
+#define LDR_IS_DATAFILE(handle) (((ULONG_PTR)(handle)) & (ULONG_PTR)1)
+#define LDR_IS_IMAGEMAPPING(handle) (((ULONG_PTR)(handle)) & (ULONG_PTR)2)
+#define LDR_IS_RESOURCE(handle) (LDR_IS_IMAGEMAPPING(handle) ||
LDR_IS_DATAFILE(handle))
//
// Loader Data stored in the PEB