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?re…
==============================================================================
--- 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(a)relsoft.net)
+ * Aleksey Bragin (aleksey(a)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=…
==============================================================================
--- 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>