Author: fireball Date: Wed Feb 23 22:38:55 2011 New Revision: 50884
URL: http://svn.reactos.org/svn/reactos?rev=50884&view=rev Log: [NTDLL/LDR] - DPH could be selectively enabled for a specific application by means of Image File Execution options. Commit a rewrite of LdrQueryImageFileExecution* APIs based on a quite old patch by Alex Ionescu along with my fixes. - This is a forced measure to commit first step of an ntdll/ldr rewrite. This particular commit should not introduce any regressions, because previously that code part just barely worked.
Added: trunk/reactos/dll/ntdll/ldr/ldrinit.c (with props) Modified: trunk/reactos/dll/ntdll/ldr/utils.c trunk/reactos/dll/ntdll/ntdll.rbuild
Added: trunk/reactos/dll/ntdll/ldr/ldrinit.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/ntdll/ldr/ldrinit.c?rev... ============================================================================== --- trunk/reactos/dll/ntdll/ldr/ldrinit.c (added) +++ trunk/reactos/dll/ntdll/ldr/ldrinit.c [iso-8859-1] Wed Feb 23 22:38:55 2011 @@ -1,0 +1,320 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS NT User-Mode Library + * FILE: dll/ntdll/ldr/ldrinit.c + * PURPOSE: User-Mode Process/Thread Startup + * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) + * Aleksey Bragin (aleksey@reactos.org) + */ + +/* INCLUDES *****************************************************************/ + +#include <ntdll.h> +#define NDEBUG +#include <debug.h> + +/* GLOBALS *******************************************************************/ + +HKEY ImageExecOptionsKey; +HKEY Wow64ExecOptionsKey; +UNICODE_STRING ImageExecOptionsString = RTL_CONSTANT_STRING(L"\Registry\Machine\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options"); +UNICODE_STRING Wow64OptionsString = RTL_CONSTANT_STRING(L""); + +/* FUNCTIONS *****************************************************************/ + +/* + * @implemented + */ +NTSTATUS +NTAPI +LdrOpenImageFileOptionsKey(IN PUNICODE_STRING SubKey, + IN BOOLEAN Wow64, + OUT PHKEY NewKeyHandle) +{ + PHKEY RootKeyLocation; + HANDLE RootKey; + UNICODE_STRING SubKeyString; + OBJECT_ATTRIBUTES ObjectAttributes; + NTSTATUS Status; + PWCHAR p1; + + /* Check which root key to open */ + if (Wow64) + RootKeyLocation = &Wow64ExecOptionsKey; + else + RootKeyLocation = &ImageExecOptionsKey; + + /* Get the current key */ + RootKey = *RootKeyLocation; + + /* Setup the object attributes */ + InitializeObjectAttributes(&ObjectAttributes, + Wow64 ? + &Wow64OptionsString : &ImageExecOptionsString, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + /* Open the root key */ + Status = ZwOpenKey(&RootKey, KEY_ENUMERATE_SUB_KEYS, &ObjectAttributes); + if (NT_SUCCESS(Status)) + { + /* Write the key handle */ + if (_InterlockedCompareExchange((LONG*)RootKeyLocation, (LONG)RootKey, 0) != 0) + { + /* Someone already opened it, use it instead */ + NtClose(RootKey); + RootKey = *RootKeyLocation; + } + + /* Extract the name */ + SubKeyString = *SubKey; + p1 = (PWCHAR)((ULONG_PTR)SubKeyString.Buffer + SubKeyString.Length); + while (SubKey->Length) + { + if (p1[-1] == L'\') break; + p1--; + SubKeyString.Length -= sizeof(*p1); + } + SubKeyString.Buffer = p1; + SubKeyString.Length = SubKeyString.MaximumLength - SubKeyString.Length - sizeof(WCHAR); + + /* Setup the object attributes */ + InitializeObjectAttributes(&ObjectAttributes, + &SubKeyString, + OBJ_CASE_INSENSITIVE, + RootKey, + NULL); + + /* Open the setting key */ + Status = ZwOpenKey((PHANDLE)NewKeyHandle, GENERIC_READ, &ObjectAttributes); + } + + /* Return to caller */ + return Status; +} + +/* + * @implemented + */ +NTSTATUS +NTAPI +LdrQueryImageFileKeyOption(IN HKEY KeyHandle, + IN PCWSTR ValueName, + IN ULONG Type, + OUT PVOID Buffer, + IN ULONG BufferSize, + OUT PULONG ReturnedLength OPTIONAL) +{ + ULONG KeyInfo[256]; + UNICODE_STRING ValueNameString, IntegerString; + ULONG KeyInfoSize, ResultSize; + PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)&KeyInfo; + BOOLEAN FreeHeap = FALSE; + NTSTATUS Status; + + /* Build a string for the value name */ + Status = RtlInitUnicodeStringEx(&ValueNameString, ValueName); + if (!NT_SUCCESS(Status)) return Status; + + /* Query the value */ + Status = NtQueryValueKey(KeyHandle, + &ValueNameString, + KeyValuePartialInformation, + KeyValueInformation, + sizeof(KeyInfo), + &ResultSize); + if (Status == STATUS_BUFFER_OVERFLOW) + { + /* Our local buffer wasn't enough, allocate one */ + KeyInfoSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + + KeyValueInformation->DataLength; + KeyValueInformation = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + KeyInfoSize); + if (KeyInfo == NULL) + { + /* Give up this time */ + Status = STATUS_NO_MEMORY; + } + + /* Try again */ + Status = NtQueryValueKey(KeyHandle, + &ValueNameString, + KeyValuePartialInformation, + KeyValueInformation, + KeyInfoSize, + &ResultSize); + FreeHeap = TRUE; + } + + /* Check for success */ + if (NT_SUCCESS(Status)) + { + /* Handle binary data */ + if (KeyValueInformation->Type == REG_BINARY) + { + /* Check validity */ + if ((Buffer) && (KeyValueInformation->DataLength <= BufferSize)) + { + /* Copy into buffer */ + RtlMoveMemory(Buffer, + &KeyValueInformation->Data, + KeyValueInformation->DataLength); + } + else + { + Status = STATUS_BUFFER_OVERFLOW; + } + + /* Copy the result length */ + if (ReturnedLength) *ReturnedLength = KeyValueInformation->DataLength; + } + else if (KeyValueInformation->Type == REG_DWORD) + { + /* Check for valid type */ + if (KeyValueInformation->Type != Type) + { + /* Error */ + Status = STATUS_OBJECT_TYPE_MISMATCH; + } + else + { + /* Check validity */ + if ((Buffer) && + (BufferSize == sizeof(ULONG)) && + (KeyValueInformation->DataLength <= BufferSize)) + { + /* Copy into buffer */ + RtlMoveMemory(Buffer, + &KeyValueInformation->Data, + KeyValueInformation->DataLength); + } + else + { + Status = STATUS_BUFFER_OVERFLOW; + } + + /* Copy the result length */ + if (ReturnedLength) *ReturnedLength = KeyValueInformation->DataLength; + } + } + else if (KeyValueInformation->Type != REG_SZ) + { + /* We got something weird */ + Status = STATUS_OBJECT_TYPE_MISMATCH; + } + else + { + /* String, check what you requested */ + if (Type == REG_DWORD) + { + /* Validate */ + if (BufferSize != sizeof(ULONG)) + { + /* Invalid size */ + BufferSize = 0; + Status = STATUS_INFO_LENGTH_MISMATCH; + } + else + { + /* OK, we know what you want... */ + IntegerString.Buffer = (PWSTR)KeyValueInformation->Data; + IntegerString.Length = KeyValueInformation->DataLength - + sizeof(WCHAR); + IntegerString.MaximumLength = KeyValueInformation->DataLength; + Status = RtlUnicodeStringToInteger(&IntegerString, 0, (PULONG)Buffer); + } + } + else + { + /* Validate */ + if (KeyValueInformation->DataLength > BufferSize) + { + /* Invalid */ + Status = STATUS_BUFFER_OVERFLOW; + } + else + { + /* Set the size */ + BufferSize = KeyValueInformation->DataLength; + } + + /* Copy the string */ + RtlMoveMemory(Buffer, &KeyValueInformation->Data, BufferSize); + } + + /* Copy the result length */ + if (ReturnedLength) *ReturnedLength = KeyValueInformation->DataLength; + } + } + + /* Check if buffer was in heap */ + if (FreeHeap) RtlFreeHeap(RtlGetProcessHeap(), 0, KeyValueInformation); + + /* Close key and return */ + NtClose(KeyHandle); + return Status; +} + +/* + * @implemented + */ +NTSTATUS +NTAPI +LdrQueryImageFileExecutionOptionsEx(IN PUNICODE_STRING SubKey, + IN PCWSTR ValueName, + IN ULONG Type, + OUT PVOID Buffer, + IN ULONG BufferSize, + OUT PULONG ReturnedLength OPTIONAL, + IN BOOLEAN Wow64) +{ + NTSTATUS Status; + HKEY KeyHandle; + + /* Open a handle to the key */ + Status = LdrOpenImageFileOptionsKey(SubKey, Wow64, &KeyHandle); + + /* Check for success */ + if (NT_SUCCESS(Status)) + { + /* Query the data */ + Status = LdrQueryImageFileKeyOption(KeyHandle, + ValueName, + Type, + Buffer, + BufferSize, + ReturnedLength); + + /* Close the key */ + NtClose(KeyHandle); + } + + /* Return to caller */ + return Status; +} + +/* + * @implemented + */ +NTSTATUS +NTAPI +LdrQueryImageFileExecutionOptions(IN PUNICODE_STRING SubKey, + IN PCWSTR ValueName, + IN ULONG Type, + OUT PVOID Buffer, + IN ULONG BufferSize, + OUT PULONG ReturnedLength OPTIONAL) +{ + /* Call the newer function */ + return LdrQueryImageFileExecutionOptionsEx(SubKey, + ValueName, + Type, + Buffer, + BufferSize, + ReturnedLength, + FALSE); +} + +/* EOF */
Propchange: trunk/reactos/dll/ntdll/ldr/ldrinit.c ------------------------------------------------------------------------------ svn:eol-style = native
Modified: trunk/reactos/dll/ntdll/ldr/utils.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/ntdll/ldr/utils.c?rev=5... ============================================================================== --- trunk/reactos/dll/ntdll/ldr/utils.c [iso-8859-1] (original) +++ trunk/reactos/dll/ntdll/ldr/utils.c [iso-8859-1] Wed Feb 23 22:38:55 2011 @@ -3289,162 +3289,6 @@ return Status; }
- -/*************************************************************************** - * NAME EXPORTED - * LdrQueryImageFileExecutionOptions - * - * DESCRIPTION - * - * ARGUMENTS - * - * RETURN VALUE - * - * REVISIONS - * - * NOTE - * - * @implemented - */ -NTSTATUS NTAPI -LdrQueryImageFileExecutionOptions(IN PUNICODE_STRING SubKey, - IN PCWSTR ValueName, - IN ULONG Type, - OUT PVOID Buffer, - IN ULONG BufferSize, - OUT PULONG ReturnedLength OPTIONAL) -{ - PKEY_VALUE_PARTIAL_INFORMATION KeyInfo; - CHAR KeyInfoBuffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 32]; - OBJECT_ATTRIBUTES ObjectAttributes; - UNICODE_STRING ValueNameString; - UNICODE_STRING KeyName; - WCHAR NameBuffer[256]; - HANDLE KeyHandle; - ULONG KeyInfoSize; - ULONG ResultSize; - PWCHAR Ptr; - NTSTATUS Status; - - wcscpy (NameBuffer, - L"\Registry\Machine\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\"); - Ptr = wcsrchr (SubKey->Buffer, L'\'); - if (Ptr == NULL) - { - Ptr = SubKey->Buffer; - } - else - { - Ptr++; - } - wcscat (NameBuffer, Ptr); - RtlInitUnicodeString (&KeyName, - NameBuffer); - - InitializeObjectAttributes(&ObjectAttributes, - &KeyName, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - - Status = NtOpenKey(&KeyHandle, - KEY_READ, - &ObjectAttributes); - if (!NT_SUCCESS(Status)) - { - DPRINT ("NtOpenKey() failed (Status %lx)\n", Status); - return Status; - } - - KeyInfoSize = sizeof(KeyInfoBuffer); - KeyInfo = (PKEY_VALUE_PARTIAL_INFORMATION)KeyInfoBuffer; - - RtlInitUnicodeString(&ValueNameString, - (PWSTR)ValueName); - Status = NtQueryValueKey(KeyHandle, - &ValueNameString, - KeyValuePartialInformation, - KeyInfo, - KeyInfoSize, - &ResultSize); - if (Status == STATUS_BUFFER_OVERFLOW) - { - /* We can allocate only if there is a process heap already */ - if (!RtlGetProcessHeap()) - { - NtClose (KeyHandle); - return STATUS_NO_MEMORY; - } - KeyInfoSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + KeyInfo->DataLength; - KeyInfo = RtlAllocateHeap (RtlGetProcessHeap(), - HEAP_ZERO_MEMORY, - KeyInfoSize); - if (KeyInfo == NULL) - { - NtClose (KeyHandle); - return STATUS_INSUFFICIENT_RESOURCES; - } - - Status = NtQueryValueKey (KeyHandle, - &ValueNameString, - KeyValuePartialInformation, - KeyInfo, - KeyInfoSize, - &ResultSize); - } - NtClose (KeyHandle); - - if (!NT_SUCCESS(Status)) - { - if ((PCHAR)KeyInfo != KeyInfoBuffer) - { - RtlFreeHeap (RtlGetProcessHeap(), - 0, - KeyInfo); - } - return Status; - } - - if (KeyInfo->Type != Type) - { - if ((PCHAR)KeyInfo != KeyInfoBuffer) - { - RtlFreeHeap (RtlGetProcessHeap(), - 0, - KeyInfo); - } - return STATUS_OBJECT_TYPE_MISMATCH; - } - - ResultSize = BufferSize; - if (ResultSize < KeyInfo->DataLength) - { - Status = STATUS_BUFFER_OVERFLOW; - } - else - { - ResultSize = KeyInfo->DataLength; - } - RtlCopyMemory (Buffer, - &KeyInfo->Data, - ResultSize); - - if ((PCHAR)KeyInfo != KeyInfoBuffer) - { - RtlFreeHeap (RtlGetProcessHeap(), - 0, - KeyInfo); - } - - if (ReturnedLength != NULL) - { - *ReturnedLength = ResultSize; - } - - return Status; -} - - PIMAGE_BASE_RELOCATION NTAPI LdrProcessRelocationBlock(
Modified: trunk/reactos/dll/ntdll/ntdll.rbuild URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/ntdll/ntdll.rbuild?rev=... ============================================================================== --- trunk/reactos/dll/ntdll/ntdll.rbuild [iso-8859-1] (original) +++ trunk/reactos/dll/ntdll/ntdll.rbuild [iso-8859-1] Wed Feb 23 22:38:55 2011 @@ -47,6 +47,7 @@ <pch>ntdll.h</pch> </directory> <directory name="ldr"> + <file>ldrinit.c</file> <file>startup.c</file> <file>utils.c</file> <file>actctx.c</file>