Author: tkreuzer
Date: Mon Nov 11 20:01:13 2013
New Revision: 60951
URL:
http://svn.reactos.org/svn/reactos?rev=60951&view=rev
Log:
[NTOSKRNL]
Fix MmLoadSystemImage, to check the system32\drivers path for import modules as well. This
should normally only be done for session loaded images, but since we don't support
that yet, we do it for all images, until this is fixed. Simplify (flatten) the code by
adding a common failure label and use goto where appropriate. Stop leaking memory in
failure case (MissingDriverName was never freed. It is leaked on windows 2003 as well)
Modified:
trunk/reactos/ntoskrnl/mm/ARM3/sysldr.c
Modified: trunk/reactos/ntoskrnl/mm/ARM3/sysldr.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/sysldr.c?…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/sysldr.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/sysldr.c [iso-8859-1] Mon Nov 11 20:01:13 2013
@@ -984,6 +984,7 @@
OUT PWCHAR *MissingDriver,
OUT PLOAD_IMPORTS *LoadImports)
{
+ static UNICODE_STRING DriversFolderName =
RTL_CONSTANT_STRING(L"drivers\\");
PCHAR MissingApiBuffer = *MissingApi, ImportName;
PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor, CurrentImport;
ULONG ImportSize, ImportCount = 0, LoadedImportsSize, ExportSize;
@@ -1002,6 +1003,9 @@
DPRINT("%s - ImageBase: %p. ImageFileDirectory: %wZ\n",
__FUNCTION__, ImageBase, ImageFileDirectory);
+ /* No name string buffer yet */
+ NameString.Buffer = NULL;
+
/* Assume no imports */
*LoadImports = MM_SYSLDR_NO_IMPORTS;
@@ -1064,12 +1068,8 @@
if ((GdiLink) && (NormalLink))
{
/* It's not, it's importing stuff it shouldn't be! */
- if (LoadedImports)
- {
- MiDereferenceImports(LoadedImports);
- ExFreePoolWithTag(LoadedImports, TAG_LDR_IMPORTS);
- }
- return STATUS_PROCEDURE_NOT_FOUND;
+ Status = STATUS_PROCEDURE_NOT_FOUND;
+ goto Failure;
}
/* Check for user-mode printer or video card drivers, which don't belong */
@@ -1081,12 +1081,8 @@
!(_strnicmp(ImportName, "gdi32", sizeof("gdi32") - 1)))
{
/* This is not kernel code */
- if (LoadedImports)
- {
- MiDereferenceImports(LoadedImports);
- ExFreePoolWithTag(LoadedImports, TAG_LDR_IMPORTS);
- }
- return STATUS_PROCEDURE_NOT_FOUND;
+ Status = STATUS_PROCEDURE_NOT_FOUND;
+ goto Failure;
}
/* Check if this is a "core" import, which doesn't get referenced
*/
@@ -1109,12 +1105,7 @@
if (!NT_SUCCESS(Status))
{
/* Failed */
- if (LoadedImports)
- {
- MiDereferenceImports(LoadedImports);
- ExFreePoolWithTag(LoadedImports, TAG_LDR_IMPORTS);
- }
- return Status;
+ goto Failure;
}
/* We don't support name prefixes yet */
@@ -1169,78 +1160,108 @@
DllName.Buffer = ExAllocatePoolWithTag(NonPagedPool,
DllName.MaximumLength,
TAG_LDR_WSTR);
- if (DllName.Buffer)
+ if (!DllName.Buffer)
{
- /* Setup the base length and copy it */
- DllName.Length = ImageFileDirectory->Length;
+ /* We're out of resources */
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto Failure;
+ }
+
+ /* Setup the base length and copy it */
+ DllName.Length = ImageFileDirectory->Length;
+ RtlCopyMemory(DllName.Buffer,
+ ImageFileDirectory->Buffer,
+ ImageFileDirectory->Length);
+
+ /* Now add the import name and null-terminate it */
+ RtlAppendUnicodeStringToString(&DllName,
+ &NameString);
+ DllName.Buffer[DllName.Length / sizeof(WCHAR)] = UNICODE_NULL;
+
+ /* Load the image */
+ Status = MmLoadSystemImage(&DllName,
+ NamePrefix,
+ NULL,
+ FALSE,
+ (PVOID)&DllEntry,
+ &DllBase);
+
+ /* win32k / GDI drivers can also import from system32 folder */
+ if ((Status == STATUS_OBJECT_NAME_NOT_FOUND) &&
+ (MI_IS_SESSION_ADDRESS(ImageBase) || 1)) // HACK
+ {
+ /* Free the old name buffer */
+ ExFreePoolWithTag(DllName.Buffer, TAG_LDR_WSTR);
+
+ /* Calculate size for a string the adds 'drivers\' */
+ DllName.MaximumLength += DriversFolderName.Length;
+
+ /* Allocate the new buffer */
+ DllName.Buffer = ExAllocatePoolWithTag(NonPagedPool,
+ DllName.MaximumLength,
+ TAG_LDR_WSTR);
+ if (!DllName.Buffer)
+ {
+ /* We're out of resources */
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto Failure;
+ }
+
+ /* Copy the image directory */
RtlCopyMemory(DllName.Buffer,
ImageFileDirectory->Buffer,
ImageFileDirectory->Length);
+ DllName.Length = ImageFileDirectory->Length;
+
+ /* Append 'drivers\' folder name */
+ RtlAppendUnicodeStringToString(&DllName, &DriversFolderName);
/* Now add the import name and null-terminate it */
- RtlAppendUnicodeStringToString(&DllName,
- &NameString);
+ RtlAppendUnicodeStringToString(&DllName, &NameString);
DllName.Buffer[DllName.Length / sizeof(WCHAR)] = UNICODE_NULL;
- /* Load the image */
+ /* Try once again to load the image */
Status = MmLoadSystemImage(&DllName,
NamePrefix,
NULL,
FALSE,
(PVOID)&DllEntry,
&DllBase);
- if (NT_SUCCESS(Status))
- {
- /* We can free the DLL Name */
- ExFreePoolWithTag(DllName.Buffer, TAG_LDR_WSTR);
- }
- else
- {
- /* Fill out the information for the error */
- *MissingDriver = DllName.Buffer;
- *(PULONG)MissingDriver |= 1;
- *MissingApi = NULL;
-
- DPRINT1("Failed to load dependency: %wZ\n", &DllName);
- }
}
- else
- {
- /* We're out of resources */
- Status = STATUS_INSUFFICIENT_RESOURCES;
- }
-
- /* Check if we're OK until now */
- if (NT_SUCCESS(Status))
- {
- /* We're now loaded */
- Loaded = TRUE;
-
- /* Sanity check */
- ASSERT(DllBase == DllEntry->DllBase);
-
- /* Call the initialization routines */
- Status = MmCallDllInitialize(DllEntry, &PsLoadedModuleList);
- if (!NT_SUCCESS(Status))
- {
- /* We failed, unload the image */
- MmUnloadSystemImage(DllEntry);
- ERROR_DBGBREAK("MmCallDllInitialize failed with status
0x%x\n", Status);
- Loaded = FALSE;
- }
- }
-
- /* Check if we failed by here */
+
if (!NT_SUCCESS(Status))
{
+ /* Fill out the information for the error */
+ *MissingDriver = DllName.Buffer;
+ *(PULONG)MissingDriver |= 1;
+ *MissingApi = NULL;
+
+ /* Don't free the name */
+ DllName.Buffer = NULL;
+
/* Cleanup and return */
- RtlFreeUnicodeString(&NameString);
- if (LoadedImports)
- {
- MiDereferenceImports(LoadedImports);
- ExFreePoolWithTag(LoadedImports, TAG_LDR_IMPORTS);
- }
- return Status;
+ DPRINT1("Failed to load dependency: %wZ\n", &DllName);
+ goto Failure;
+ }
+
+ /* We can free the DLL Name */
+ ExFreePoolWithTag(DllName.Buffer, TAG_LDR_WSTR);
+ DllName.Buffer = NULL;
+
+ /* We're now loaded */
+ Loaded = TRUE;
+
+ /* Sanity check */
+ ASSERT(DllBase == DllEntry->DllBase);
+
+ /* Call the initialization routines */
+ Status = MmCallDllInitialize(DllEntry, &PsLoadedModuleList);
+ if (!NT_SUCCESS(Status))
+ {
+ /* We failed, unload the image */
+ MmUnloadSystemImage(DllEntry);
+ ERROR_DBGBREAK("MmCallDllInitialize failed with status 0x%x\n",
Status);
+ Loaded = FALSE;
}
/* Loop again to make sure that everything is OK */
@@ -1271,13 +1292,9 @@
if (!ExportDirectory)
{
/* Cleanup and return */
- if (LoadedImports)
- {
- MiDereferenceImports(LoadedImports);
- ExFreePoolWithTag(LoadedImports, TAG_LDR_IMPORTS);
- }
DPRINT1("Warning: Driver failed to load, %S not found\n",
*MissingDriver);
- return STATUS_DRIVER_ENTRYPOINT_NOT_FOUND;
+ Status = STATUS_DRIVER_ENTRYPOINT_NOT_FOUND;
+ goto Failure;
}
/* Make sure we have an IAT */
@@ -1304,12 +1321,7 @@
if (!NT_SUCCESS(Status))
{
/* Cleanup and return */
- if (LoadedImports)
- {
- MiDereferenceImports(LoadedImports);
- ExFreePoolWithTag(LoadedImports, TAG_LDR_IMPORTS);
- }
- return Status;
+ goto Failure;
}
/* Reset the buffer */
@@ -1386,6 +1398,22 @@
/* Return success */
return STATUS_SUCCESS;
+
+Failure:
+
+ /* Cleanup and return */
+ if (NameString.Buffer != NULL)
+ {
+ ExFreePoolWithTag(NameString.Buffer, TAG_LDR_WSTR);
+ }
+
+ if (LoadedImports)
+ {
+ MiDereferenceImports(LoadedImports);
+ ExFreePoolWithTag(LoadedImports, TAG_LDR_IMPORTS);
+ }
+
+ return Status;
}
VOID
@@ -3177,6 +3205,7 @@
/* Resolve imports */
MissingApiName = Buffer;
+ MissingDriverName = NULL;
Status = MiResolveImageReferences(ModuleLoadBase,
&BaseDirectory,
NULL,
@@ -3186,6 +3215,13 @@
if (!NT_SUCCESS(Status))
{
DPRINT1("MiResolveImageReferences failed with status 0x%x\n", Status);
+ DPRINT1(" Missing driver '%ws', missing API '%s'\n",
+ MissingDriverName, MissingApiName);
+
+ if (MissingDriverName != NULL)
+ {
+ ExFreePoolWithTag(MissingDriverName, TAG_LDR_WSTR);
+ }
/* Fail */
MiProcessLoaderEntry(LdrEntry, FALSE);