mirror of
https://github.com/reactos/reactos.git
synced 2024-09-22 18:45:51 +00:00
785bea480a
- Sync with trunk r51050. svn path=/branches/cmake-bringup/; revision=51154
321 lines
10 KiB
C
321 lines
10 KiB
C
/*
|
|
* 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 */
|