[NTDLL/LDR]
authorAleksey Bragin <aleksey@reactos.org>
Wed, 23 Feb 2011 22:38:55 +0000 (22:38 +0000)
committerAleksey Bragin <aleksey@reactos.org>
Wed, 23 Feb 2011 22:38:55 +0000 (22:38 +0000)
- 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

reactos/dll/ntdll/ldr/ldrinit.c [new file with mode: 0644]
reactos/dll/ntdll/ldr/utils.c
reactos/dll/ntdll/ntdll.rbuild

diff --git a/reactos/dll/ntdll/ldr/ldrinit.c b/reactos/dll/ntdll/ldr/ldrinit.c
new file mode 100644 (file)
index 0000000..77baa0a
--- /dev/null
@@ -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 */
index 4482f93..345d159 100644 (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(
index 2a0b910..30a97ef 100644 (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>