479 lines
10 KiB
C
479 lines
10 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1989 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
settings.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
This module implements interfaces for enabling application
|
||
|
verifier flags persistently (registry).
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Silviu Calinoiu (SilviuC) 17-Apr-2001
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
//
|
||
|
// IMPORTANT NOTE.
|
||
|
//
|
||
|
// This dll cannot contain non-ntdll dependencies. This way it allows
|
||
|
// verifier to be run system wide including for processes like smss and csrss.
|
||
|
//
|
||
|
// This explains why we load dynamically advapi32 dll and pick up the functions
|
||
|
// for registry manipulation. It is safe to do that for interfaces that set
|
||
|
// flags because they are called only in contexts where it is safe to load
|
||
|
// additional dlls.
|
||
|
//
|
||
|
|
||
|
#include "pch.h"
|
||
|
|
||
|
#include "verifier.h"
|
||
|
#include "settings.h"
|
||
|
|
||
|
//
|
||
|
// Handy functions exported by ntdll.dll
|
||
|
//
|
||
|
int __cdecl sscanf(const char *, const char *, ...);
|
||
|
int __cdecl swprintf(wchar_t *, const wchar_t *, ...);
|
||
|
|
||
|
//
|
||
|
// Signatures for registry functions
|
||
|
//
|
||
|
|
||
|
typedef LONG (APIENTRY * PFN_REG_CREATE_KEY) (HKEY, LPCWSTR, DWORD, LPWSTR, DWORD, REGSAM, LPSECURITY_ATTRIBUTES, PHKEY, LPDWORD);
|
||
|
typedef LONG (APIENTRY * PFN_REG_CLOSE_KEY)(HKEY);
|
||
|
typedef LONG (APIENTRY * PFN_REG_QUERY_VALUE) (HKEY, LPCWSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD);
|
||
|
typedef LONG (APIENTRY * PFN_REG_SET_VALUE) (HKEY, LPCWSTR, DWORD, DWORD, CONST BYTE *, DWORD);
|
||
|
typedef LONG (APIENTRY * PFN_REG_DELETE_VALUE) (HKEY, LPCWSTR);
|
||
|
|
||
|
//
|
||
|
// Dynamically detected registry functions
|
||
|
//
|
||
|
|
||
|
PFN_REG_CREATE_KEY FnRegCreateKey;
|
||
|
PFN_REG_CLOSE_KEY FnRegCloseKey;
|
||
|
PFN_REG_QUERY_VALUE FnRegQueryValue;
|
||
|
PFN_REG_SET_VALUE FnRegSetValue;
|
||
|
PFN_REG_DELETE_VALUE FnRegDeleteValue;
|
||
|
|
||
|
//
|
||
|
// Registry path to `image file execution options' key
|
||
|
//
|
||
|
|
||
|
#define EXECUTION_OPTIONS_KEY L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\"
|
||
|
|
||
|
//
|
||
|
// Internal functions
|
||
|
//
|
||
|
|
||
|
NTSTATUS
|
||
|
AVrfpGetRegistryInterfaces (
|
||
|
PVOID DllHandle
|
||
|
);
|
||
|
|
||
|
HKEY
|
||
|
AVrfpOpenImageKey (
|
||
|
PWSTR Name
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
AVrfpCloseImageKey (
|
||
|
HKEY Key
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
AVrfpReadGlobalFlags (
|
||
|
HKEY Key,
|
||
|
PDWORD Value
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
AVrfpWriteGlobalFlags (
|
||
|
HKEY Key,
|
||
|
DWORD Value
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
AVrfpDeleteGlobalFlags (
|
||
|
HKEY Key
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
AVrfpReadVerifierFlags (
|
||
|
HKEY Key,
|
||
|
PDWORD Value
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
AVrfpWriteVerifierFlags (
|
||
|
HKEY Key,
|
||
|
DWORD Value
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
AVrfpDeleteVerifierFlags (
|
||
|
HKEY Key
|
||
|
);
|
||
|
|
||
|
|
||
|
NTSTATUS
|
||
|
VerifierSetFlags (
|
||
|
PUNICODE_STRING ApplicationName,
|
||
|
ULONG VerifierFlags,
|
||
|
PVOID Details
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine enables persistently (through registry) application
|
||
|
verifier flags for a specified application.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
ApplicationName - name of the application to be verifier. The path should
|
||
|
not be included. The extension should be included. Some examples of
|
||
|
correct names are: `services.exe', `logon.scr'. Incorrect examples are:
|
||
|
`c:\winnt\system32\notepad.exe' or just `notepad'. If we persist a setting
|
||
|
for `xxx.exe' then every time a process whose binary is xxx.exe is launched
|
||
|
application verifier will kick in no matter in what user context or from what
|
||
|
disk location this happens.
|
||
|
|
||
|
VerifierFlags - bit field with verifier flags to be enabled. The legal bits are
|
||
|
declared in sdk\inc\nturtl.h (and winnt.h) as constants names RTL_VRF_FLG_XXX.
|
||
|
For example RTL_VRF_FLG_FULL_PAGE_HEAP. If a zero value is used then all
|
||
|
registry values related to verifier will b e deleted from registry.
|
||
|
|
||
|
Details - Ignored right now. In the future this structure will support various
|
||
|
extensions of the API (e.g. page heap flags, per dll page heap settings, etc.).
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
STATUS_SUCCESS if all flags requested have been enabled. It can return
|
||
|
STATUS_NOT_IMPLEMENTED if one of the flags requested is not yet implemented
|
||
|
or we decided to block it internally due to a bug. It can also return
|
||
|
STATUS_INVALID_PARAMETER if the application name or other parameters
|
||
|
are ill-formed.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
NTSTATUS Status;
|
||
|
UNICODE_STRING AdvapiName;
|
||
|
PVOID AdvapiHandle;
|
||
|
HKEY Key;
|
||
|
DWORD Flags;
|
||
|
|
||
|
if (ApplicationName == NULL || ApplicationName->Buffer == NULL) {
|
||
|
return STATUS_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Load advapi32.dll and get registry manipulation functions.
|
||
|
//
|
||
|
|
||
|
RtlInitUnicodeString (&AdvapiName, L"advapi32.dll");
|
||
|
Status = LdrLoadDll (NULL, NULL, &AdvapiName, &AdvapiHandle);
|
||
|
|
||
|
if (!NT_SUCCESS(Status)) {
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
Status = AVrfpGetRegistryInterfaces (AdvapiHandle);
|
||
|
|
||
|
if (!NT_SUCCESS(Status)) {
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Open `image file execution options\xxx.exe' key. If the key does not
|
||
|
// exist it will be created.
|
||
|
//
|
||
|
|
||
|
Key = AVrfpOpenImageKey (ApplicationName->Buffer);
|
||
|
|
||
|
if (Key == NULL) {
|
||
|
Status = STATUS_INVALID_PARAMETER;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Create verifier settings.
|
||
|
//
|
||
|
|
||
|
if (VerifierFlags == 0) {
|
||
|
|
||
|
Flags = 0;
|
||
|
AVrfpReadGlobalFlags (Key, &Flags);
|
||
|
Flags &= ~FLG_APPLICATION_VERIFIER;
|
||
|
|
||
|
if (Flags == 0) {
|
||
|
AVrfpDeleteGlobalFlags (Key);
|
||
|
}
|
||
|
else {
|
||
|
AVrfpWriteGlobalFlags (Key, Flags);
|
||
|
}
|
||
|
|
||
|
AVrfpDeleteVerifierFlags (Key);
|
||
|
}
|
||
|
else {
|
||
|
|
||
|
Flags = 0;
|
||
|
AVrfpReadGlobalFlags (Key, &Flags);
|
||
|
Flags |= FLG_APPLICATION_VERIFIER;
|
||
|
AVrfpWriteGlobalFlags (Key, Flags);
|
||
|
|
||
|
Flags = VerifierFlags;
|
||
|
AVrfpWriteVerifierFlags (Key, Flags);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Cleanup and return.
|
||
|
//
|
||
|
|
||
|
AVrfpCloseImageKey (Key);
|
||
|
|
||
|
Exit:
|
||
|
|
||
|
LdrUnloadDll (AdvapiHandle);
|
||
|
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
NTSTATUS
|
||
|
AVrfpGetRegistryInterfaces (
|
||
|
PVOID AdvapiHandle
|
||
|
)
|
||
|
{
|
||
|
NTSTATUS Status;
|
||
|
ANSI_STRING FunctionName;
|
||
|
PVOID FunctionAddress;
|
||
|
|
||
|
RtlInitAnsiString (&FunctionName, "RegCreateKeyExW");
|
||
|
Status = LdrGetProcedureAddress (AdvapiHandle, &FunctionName, 0, &FunctionAddress);
|
||
|
|
||
|
if (!NT_SUCCESS(Status)) {
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
FnRegCreateKey = (PFN_REG_CREATE_KEY)FunctionAddress;
|
||
|
|
||
|
RtlInitAnsiString (&FunctionName, "RegCloseKey");
|
||
|
Status = LdrGetProcedureAddress (AdvapiHandle, &FunctionName, 0, &FunctionAddress);
|
||
|
|
||
|
if (!NT_SUCCESS(Status)) {
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
FnRegCloseKey = (PFN_REG_CLOSE_KEY)FunctionAddress;
|
||
|
|
||
|
RtlInitAnsiString (&FunctionName, "RegQueryValueExW");
|
||
|
Status = LdrGetProcedureAddress (AdvapiHandle, &FunctionName, 0, &FunctionAddress);
|
||
|
|
||
|
if (!NT_SUCCESS(Status)) {
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
FnRegQueryValue = (PFN_REG_QUERY_VALUE)FunctionAddress;
|
||
|
|
||
|
RtlInitAnsiString (&FunctionName, "RegSetValueExW");
|
||
|
Status = LdrGetProcedureAddress (AdvapiHandle, &FunctionName, 0, &FunctionAddress);
|
||
|
|
||
|
if (!NT_SUCCESS(Status)) {
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
FnRegSetValue = (PFN_REG_SET_VALUE)FunctionAddress;
|
||
|
|
||
|
RtlInitAnsiString (&FunctionName, "RegDeleteValueW");
|
||
|
Status = LdrGetProcedureAddress (AdvapiHandle, &FunctionName, 0, &FunctionAddress);
|
||
|
|
||
|
if (!NT_SUCCESS(Status)) {
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
FnRegDeleteValue = (PFN_REG_DELETE_VALUE)FunctionAddress;
|
||
|
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
HKEY
|
||
|
AVrfpOpenImageKey (
|
||
|
PWSTR Name
|
||
|
)
|
||
|
{
|
||
|
HKEY Key;
|
||
|
LONG Result;
|
||
|
WCHAR Buffer [MAX_PATH];
|
||
|
|
||
|
wcscpy (Buffer, EXECUTION_OPTIONS_KEY);
|
||
|
wcscat (Buffer, Name);
|
||
|
|
||
|
Result = FnRegCreateKey (HKEY_LOCAL_MACHINE,
|
||
|
Buffer,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
KEY_ALL_ACCESS,
|
||
|
NULL,
|
||
|
&Key,
|
||
|
NULL);
|
||
|
|
||
|
if (Result != ERROR_SUCCESS) {
|
||
|
return NULL;
|
||
|
}
|
||
|
else {
|
||
|
return Key;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
AVrfpCloseImageKey (
|
||
|
HKEY Key
|
||
|
)
|
||
|
{
|
||
|
FnRegCloseKey (Key);
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
AVrfpReadGlobalFlags (
|
||
|
HKEY Key,
|
||
|
PDWORD Value
|
||
|
)
|
||
|
{
|
||
|
LONG Result;
|
||
|
DWORD Type;
|
||
|
BYTE Buffer[32];
|
||
|
BYTE Buffer2[32];
|
||
|
DWORD BytesRead;
|
||
|
DWORD FlagValue;
|
||
|
DWORD I;
|
||
|
|
||
|
BytesRead = sizeof Buffer;
|
||
|
|
||
|
Result = FnRegQueryValue (Key,
|
||
|
L"GlobalFlag",
|
||
|
0,
|
||
|
&Type,
|
||
|
(LPBYTE)Buffer,
|
||
|
&BytesRead);
|
||
|
|
||
|
if (Result != ERROR_SUCCESS || Type != REG_SZ) {
|
||
|
|
||
|
DbgPrint ("Result %u \n", Result);
|
||
|
return FALSE;
|
||
|
}
|
||
|
else {
|
||
|
|
||
|
for (I = 0; Buffer[2 * I] != L'\0'; I += 1) {
|
||
|
Buffer2[I] = Buffer[2 * I];
|
||
|
}
|
||
|
|
||
|
Buffer2[I] = 0;
|
||
|
FlagValue = 0;
|
||
|
|
||
|
sscanf (Buffer2, "%x", &FlagValue);
|
||
|
|
||
|
if (Value) {
|
||
|
*Value = FlagValue;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
AVrfpWriteGlobalFlags (
|
||
|
HKEY Key,
|
||
|
DWORD Value
|
||
|
)
|
||
|
{
|
||
|
LONG Result;
|
||
|
WCHAR Buffer[16];
|
||
|
DWORD Length;
|
||
|
|
||
|
swprintf (Buffer, L"0x%08X", Value);
|
||
|
Length = (wcslen(Buffer) + 1) * sizeof (WCHAR);
|
||
|
|
||
|
Result = FnRegSetValue (Key,
|
||
|
L"GlobalFlag",
|
||
|
0,
|
||
|
REG_SZ,
|
||
|
(LPBYTE)Buffer,
|
||
|
Length);
|
||
|
|
||
|
return (Result == ERROR_SUCCESS);
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
AVrfpDeleteGlobalFlags (
|
||
|
HKEY Key
|
||
|
)
|
||
|
{
|
||
|
LONG Result;
|
||
|
|
||
|
Result = FnRegDeleteValue (Key, L"GlobalFlag");
|
||
|
return (Result == ERROR_SUCCESS);
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
AVrfpReadVerifierFlags (
|
||
|
HKEY Key,
|
||
|
PDWORD Value
|
||
|
)
|
||
|
{
|
||
|
LONG Result;
|
||
|
DWORD Type;
|
||
|
DWORD BytesRead;
|
||
|
|
||
|
BytesRead = sizeof *Value;
|
||
|
|
||
|
Result = FnRegQueryValue (Key,
|
||
|
L"VerifierValue",
|
||
|
0,
|
||
|
&Type,
|
||
|
(LPBYTE)Value,
|
||
|
&BytesRead);
|
||
|
|
||
|
return (Result == ERROR_SUCCESS && Type != REG_DWORD);
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
AVrfpWriteVerifierFlags (
|
||
|
HKEY Key,
|
||
|
DWORD Value
|
||
|
)
|
||
|
{
|
||
|
LONG Result;
|
||
|
|
||
|
Result = FnRegSetValue (Key,
|
||
|
L"VerifierFlags",
|
||
|
0,
|
||
|
REG_DWORD,
|
||
|
(LPBYTE)(&Value),
|
||
|
sizeof Value);
|
||
|
|
||
|
return (Result == ERROR_SUCCESS);
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
AVrfpDeleteVerifierFlags (
|
||
|
HKEY Key
|
||
|
)
|
||
|
{
|
||
|
LONG Result;
|
||
|
|
||
|
Result = FnRegDeleteValue (Key, L"VerifierFlags");
|
||
|
return (Result == ERROR_SUCCESS);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|