windows-nt/Source/XPSP1/NT/windows/appcompat/shims/verifier/logregistrychanges.h
2020-09-26 16:20:57 +08:00

396 lines
10 KiB
C++

/*++
Copyright (c) 2001 Microsoft Corporation
Module Name:
LogRegistryChanges.h
Abstract:
This AppVerifier shim hooks all the registry APIs
that change the state of the system and logs their
associated data to a text file.
Notes:
This is a general purpose shim.
History:
08/17/2001 rparsons Created
--*/
#ifndef __APPVERIFIER_LOGREGISTRYCHANGES_H_
#define __APPVERIFIER_LOGREGISTRYCHANGES_H_
#include "precomp.h"
//
// Length (in characters) of our initial buffer for logging data.
//
#define TEMP_BUFFER_SIZE 1024
//
// Length (in characters) of the longest value name we expect.
//
#define MAX_VALUENAME_SIZE 260
//
// Length (in characters) of any empty element used for key modifications.
//
#define KEY_ELEMENT_SIZE 64
//
// Length (in characters) of an empty element used for value modifications.
//
#define VALUE_ELEMENT_SIZE 640
//
// Length (in characters) of a predefined key handle.
//
#define MAX_ROOT_LENGTH 22
//
// Length (in characters) of the longest data type (i.e., REG_EXPAND_SZ)
//
#define MAX_DATA_TYPE_LENGTH 14
//
// Length (in characters) of the longest operation type (i.e., ReplaceKey)
//
#define MAX_OPERATION_LENGTH 11
//
// Count of predefined key handles that we refer to.
//
#define NUM_PREDEFINED_HANDLES 7
//
// Delta for memory allocations.
//
#define BUFFER_ALLOCATION_DELTA 1024
//
// Macros for memory allocation/deallocation.
//
#define MemAlloc(s) RtlAllocateHeap(RtlProcessHeap(), HEAP_ZERO_MEMORY, (s))
#define MemReAlloc(b,s) RtlReAllocateHeap(RtlProcessHeap(), HEAP_ZERO_MEMORY, (b), (s))
#define MemFree(b) RtlFreeHeap(RtlProcessHeap(), 0, (b))
//
// Macro that returns TRUE if the given registry handle is predefined.
//
#define IsPredefinedRegistryHandle( h ) \
(( ( h == HKEY_CLASSES_ROOT ) \
|| ( h == HKEY_CURRENT_USER ) \
|| ( h == HKEY_LOCAL_MACHINE ) \
|| ( h == HKEY_USERS ) \
|| ( h == HKEY_CURRENT_CONFIG ) \
|| ( h == HKEY_PERFORMANCE_DATA ) \
|| ( h == HKEY_DYN_DATA )) \
? TRUE \
: FALSE )
//
// A doubly linked list of all the values associated with a particular key path.
//
typedef struct _KEY_DATA {
LIST_ENTRY Entry;
DWORD dwFlags; // flags that relate to the state of the value
DWORD dwOriginalValueType; // value type of original key data
DWORD dwFinalValueType; // value type of final key data
WCHAR wszValueName[MAX_VALUENAME_SIZE]; // value name
PVOID pOriginalData; // original key data (stored on the heap)
PVOID pFinalData; // final key data (stored on the heap)
DWORD cbOriginalDataSize; // original key data buffer size (in bytes)
DWORD cbFinalDataSize; // final key data buffer size (in bytes)
} KEY_DATA, *PKEY_DATA;
//
// Maximum number of key handles we can track for a single registry path.
//
#define MAX_NUM_HANDLES 64
//
// We keep a doubly linked list of keys currently open so we know how to
// resolve a key handle to a full key path.
//
typedef struct _LOG_OPEN_KEY {
LIST_ENTRY Entry;
LIST_ENTRY KeyData; // points to the data (if any) associated with this key
HKEY hKeyBase[MAX_NUM_HANDLES]; // array of key handles
HKEY hKeyRoot; // handle to predefined key
DWORD dwFlags; // flags that relate to the state of the key
LPWSTR pwszFullKeyPath; // HKEY_LOCAL_MACHINE\Software\Microsoft\Windows...
LPWSTR pwszSubKeyPath; // Software\Microsoft\Windows...
UINT cHandles; // number of handles open for this key path
} LOG_OPEN_KEY, *PLOG_OPEN_KEY;
//
// Flags that indicate what state the key is in.
//
#define LRC_EXISTING_KEY 0x00000001
#define LRC_DELETED_KEY 0x00000002
//
// Flags that indicate what state the value is in.
//
#define LRC_EXISTING_VALUE 0x00000001
#define LRC_DELETED_VALUE 0x00000002
#define LRC_MODIFIED_VALUE 0x00000004
//
// Enumeration for updating the key information.
//
typedef enum {
eAddKeyHandle = 0,
eRemoveKeyHandle,
eDeletedKey,
eStartModifyValue,
eEndModifyValue,
eStartDeleteValue,
eEndDeleteValue
} UpdateType;
//
// The reg class that does all the real work.
//
class CLogRegistry {
public:
LONG CreateKeyExA(
HKEY hKey,
LPCSTR pszSubKey,
DWORD Reserved,
LPSTR pszClass,
DWORD dwOptions,
REGSAM samDesired,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
PHKEY phkResult,
LPDWORD lpdwDisposition
);
LONG CreateKeyExW(
HKEY hKey,
LPCWSTR pwszSubKey,
DWORD Reserved,
LPWSTR pwszClass,
DWORD dwOptions,
REGSAM samDesired,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
PHKEY phkResult,
LPDWORD lpdwDisposition
);
LONG OpenKeyExA(
HKEY hKey,
LPCSTR pszSubKey,
DWORD ulOptions,
REGSAM samDesired,
PHKEY phkResult
);
LONG OpenKeyExW(
HKEY hKey,
LPCWSTR pwszSubKey,
DWORD ulOptions,
REGSAM samDesired,
PHKEY phkResult
);
LONG OpenCurrentUser(
REGSAM samDesired,
PHKEY phkResult
);
LONG OpenUserClassesRoot(
HANDLE hToken,
DWORD dwOptions,
REGSAM samDesired,
PHKEY phkResult
);
LONG SetValueA(
HKEY hKey,
LPCSTR pszSubKey,
DWORD dwType,
LPCSTR pszData,
DWORD cbData
);
LONG SetValueW(
HKEY hKey,
LPCWSTR pwszSubKey,
DWORD dwType,
LPCWSTR lpData,
DWORD cbData
);
LONG SetValueExA(
HKEY hKey,
LPCSTR pszValueName,
DWORD Reserved,
DWORD dwType,
CONST BYTE* lpData,
DWORD cbData
);
LONG SetValueExW(
HKEY hKey,
LPCWSTR pwszValueName,
DWORD Reserved,
DWORD dwType,
CONST BYTE* lpData,
DWORD cbData
);
LONG CloseKey(
HKEY hKey
);
LONG DeleteKeyA(
HKEY hKey,
LPCSTR pszSubKey
);
LONG DeleteKeyW(
HKEY hKey,
LPCWSTR pwszSubKey
);
LONG DeleteValueA(
HKEY hKey,
LPCSTR pszValueName
);
LONG DeleteValueW(
HKEY hKey,
LPCWSTR pwszValueName
);
private:
BOOL GetOriginalDataForKey(
IN PLOG_OPEN_KEY pLogOpenKey,
IN PKEY_DATA pKeyData,
IN LPCWSTR pwszValueName
);
BOOL GetFinalDataForKey(
IN PLOG_OPEN_KEY pLogOpenKey,
IN PKEY_DATA pKeyData,
IN LPCWSTR pwszValueName
);
PLOG_OPEN_KEY AddSpecialKeyHandleToList(
IN HKEY hKeyRoot,
IN HKEY hKeyNew
);
PKEY_DATA AddValueNameToList(
IN PLOG_OPEN_KEY pLogOpenKey,
IN LPCWSTR pwszValueName
);
HKEY ForceSubKeyIntoList(
IN HKEY hKeyPredefined,
IN LPCWSTR pwszSubKey
);
PKEY_DATA FindValueNameInList(
IN LPCWSTR pwszValueName,
IN PLOG_OPEN_KEY pOpenKey
);
PLOG_OPEN_KEY FindKeyPathInList(
IN LPCWSTR pwszKeyPath
);
PLOG_OPEN_KEY RemoveKeyHandleFromArray(
IN HKEY hKey
);
PLOG_OPEN_KEY FindKeyHandleInArray(
IN HKEY hKey
);
PLOG_OPEN_KEY AddKeyHandleToList(
IN HKEY hKey,
IN HKEY hKeyNew,
IN LPCWSTR pwszSubKeyPath,
IN BOOL fExisting
);
PLOG_OPEN_KEY UpdateKeyList(
IN HKEY hKeyRoot,
IN HKEY hKeyNew,
IN LPCWSTR pwszSubKey,
IN LPCWSTR pwszValueName,
IN BOOL fExisting,
IN UpdateType eType
);
};
//
// Keep us safe while we're playing with linked lists and shared resources.
//
static BOOL g_bInitialized = FALSE;
CRITICAL_SECTION g_csLogging;
class CLock
{
public:
CLock()
{
if (!g_bInitialized)
{
InitializeCriticalSection(&g_csLogging);
g_bInitialized = TRUE;
}
EnterCriticalSection(&g_csLogging);
}
~CLock()
{
LeaveCriticalSection(&g_csLogging);
}
};
APIHOOK_ENUM_BEGIN
APIHOOK_ENUM_ENTRY(RegOpenKeyA)
APIHOOK_ENUM_ENTRY(RegOpenKeyW)
APIHOOK_ENUM_ENTRY(RegOpenKeyExA)
APIHOOK_ENUM_ENTRY(RegOpenKeyExW)
APIHOOK_ENUM_ENTRY(RegOpenCurrentUser)
APIHOOK_ENUM_ENTRY(RegOpenUserClassesRoot)
APIHOOK_ENUM_ENTRY(RegCreateKeyA)
APIHOOK_ENUM_ENTRY(RegCreateKeyW)
APIHOOK_ENUM_ENTRY(RegCreateKeyExA)
APIHOOK_ENUM_ENTRY(RegCreateKeyExW)
APIHOOK_ENUM_ENTRY(RegCloseKey)
APIHOOK_ENUM_ENTRY(RegQueryValueA)
APIHOOK_ENUM_ENTRY(RegQueryValueW)
APIHOOK_ENUM_ENTRY(RegQueryValueExA)
APIHOOK_ENUM_ENTRY(RegQueryValueExW)
APIHOOK_ENUM_ENTRY(RegQueryInfoKeyA)
APIHOOK_ENUM_ENTRY(RegQueryInfoKeyW)
APIHOOK_ENUM_ENTRY(RegSetValueA)
APIHOOK_ENUM_ENTRY(RegSetValueW)
APIHOOK_ENUM_ENTRY(RegSetValueExA)
APIHOOK_ENUM_ENTRY(RegSetValueExW)
APIHOOK_ENUM_ENTRY(RegDeleteKeyA)
APIHOOK_ENUM_ENTRY(RegDeleteKeyW)
APIHOOK_ENUM_ENTRY(RegDeleteValueA)
APIHOOK_ENUM_ENTRY(RegDeleteValueW)
APIHOOK_ENUM_ENTRY(WriteProfileStringA)
APIHOOK_ENUM_ENTRY(WriteProfileStringW)
APIHOOK_ENUM_ENTRY(WriteProfileSectionA)
APIHOOK_ENUM_ENTRY(WriteProfileSectionW)
APIHOOK_ENUM_END
#endif // __APPVERIFIER_LOGREGISTRYCHANGES_H_