[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.

svn path=/trunk/; revision=50884
This commit is contained in:
Aleksey Bragin 2011-02-23 22:38:55 +00:00
parent c16c4ace2b
commit 55300c6ce0
3 changed files with 321 additions and 156 deletions

View file

@ -0,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 */

View file

@ -3289,162 +3289,6 @@ LdrVerifyImageMatchesChecksum (IN HANDLE FileHandle,
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(

View file

@ -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>