From e6ab8c821096e946ce78b12b3de81103a87b3a7e Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Mon, 11 Nov 2013 20:01:13 +0000 Subject: [PATCH] [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) svn path=/trunk/; revision=60951 --- reactos/ntoskrnl/mm/ARM3/sysldr.c | 202 ++++++++++++++++++------------ 1 file changed, 119 insertions(+), 83 deletions(-) diff --git a/reactos/ntoskrnl/mm/ARM3/sysldr.c b/reactos/ntoskrnl/mm/ARM3/sysldr.c index ce872bf62df..c77cc99bc12 100644 --- a/reactos/ntoskrnl/mm/ARM3/sysldr.c +++ b/reactos/ntoskrnl/mm/ARM3/sysldr.c @@ -984,6 +984,7 @@ MiResolveImageReferences(IN PVOID ImageBase, 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 @@ MiResolveImageReferences(IN PVOID ImageBase, 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 @@ MiResolveImageReferences(IN PVOID ImageBase, 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 @@ MiResolveImageReferences(IN PVOID ImageBase, !(_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 @@ MiResolveImageReferences(IN PVOID ImageBase, 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 @@ CheckDllState: 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 @@ CheckDllState: 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 @@ CheckDllState: 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 @@ CheckDllState: /* 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 @@ LoaderScan: /* Resolve imports */ MissingApiName = Buffer; + MissingDriverName = NULL; Status = MiResolveImageReferences(ModuleLoadBase, &BaseDirectory, NULL, @@ -3186,6 +3215,13 @@ LoaderScan: 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);