Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

395 lines
10 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. LogRegistryChanges.h
  5. Abstract:
  6. This AppVerifier shim hooks all the registry APIs
  7. that change the state of the system and logs their
  8. associated data to a text file.
  9. Notes:
  10. This is a general purpose shim.
  11. History:
  12. 08/17/2001 rparsons Created
  13. --*/
  14. #ifndef __APPVERIFIER_LOGREGISTRYCHANGES_H_
  15. #define __APPVERIFIER_LOGREGISTRYCHANGES_H_
  16. #include "precomp.h"
  17. //
  18. // Length (in characters) of our initial buffer for logging data.
  19. //
  20. #define TEMP_BUFFER_SIZE 1024
  21. //
  22. // Length (in characters) of the longest value name we expect.
  23. //
  24. #define MAX_VALUENAME_SIZE 260
  25. //
  26. // Length (in characters) of any empty element used for key modifications.
  27. //
  28. #define KEY_ELEMENT_SIZE 64
  29. //
  30. // Length (in characters) of an empty element used for value modifications.
  31. //
  32. #define VALUE_ELEMENT_SIZE 640
  33. //
  34. // Length (in characters) of a predefined key handle.
  35. //
  36. #define MAX_ROOT_LENGTH 22
  37. //
  38. // Length (in characters) of the longest data type (i.e., REG_EXPAND_SZ)
  39. //
  40. #define MAX_DATA_TYPE_LENGTH 14
  41. //
  42. // Length (in characters) of the longest operation type (i.e., ReplaceKey)
  43. //
  44. #define MAX_OPERATION_LENGTH 11
  45. //
  46. // Count of predefined key handles that we refer to.
  47. //
  48. #define NUM_PREDEFINED_HANDLES 7
  49. //
  50. // Delta for memory allocations.
  51. //
  52. #define BUFFER_ALLOCATION_DELTA 1024
  53. //
  54. // Macros for memory allocation/deallocation.
  55. //
  56. #define MemAlloc(s) RtlAllocateHeap(RtlProcessHeap(), HEAP_ZERO_MEMORY, (s))
  57. #define MemReAlloc(b,s) RtlReAllocateHeap(RtlProcessHeap(), HEAP_ZERO_MEMORY, (b), (s))
  58. #define MemFree(b) RtlFreeHeap(RtlProcessHeap(), 0, (b))
  59. //
  60. // Macro that returns TRUE if the given registry handle is predefined.
  61. //
  62. #define IsPredefinedRegistryHandle( h ) \
  63. (( ( h == HKEY_CLASSES_ROOT ) \
  64. || ( h == HKEY_CURRENT_USER ) \
  65. || ( h == HKEY_LOCAL_MACHINE ) \
  66. || ( h == HKEY_USERS ) \
  67. || ( h == HKEY_CURRENT_CONFIG ) \
  68. || ( h == HKEY_PERFORMANCE_DATA ) \
  69. || ( h == HKEY_DYN_DATA )) \
  70. ? TRUE \
  71. : FALSE )
  72. //
  73. // A doubly linked list of all the values associated with a particular key path.
  74. //
  75. typedef struct _KEY_DATA {
  76. LIST_ENTRY Entry;
  77. DWORD dwFlags; // flags that relate to the state of the value
  78. DWORD dwOriginalValueType; // value type of original key data
  79. DWORD dwFinalValueType; // value type of final key data
  80. WCHAR wszValueName[MAX_VALUENAME_SIZE]; // value name
  81. PVOID pOriginalData; // original key data (stored on the heap)
  82. PVOID pFinalData; // final key data (stored on the heap)
  83. DWORD cbOriginalDataSize; // original key data buffer size (in bytes)
  84. DWORD cbFinalDataSize; // final key data buffer size (in bytes)
  85. } KEY_DATA, *PKEY_DATA;
  86. //
  87. // Maximum number of key handles we can track for a single registry path.
  88. //
  89. #define MAX_NUM_HANDLES 64
  90. //
  91. // We keep a doubly linked list of keys currently open so we know how to
  92. // resolve a key handle to a full key path.
  93. //
  94. typedef struct _LOG_OPEN_KEY {
  95. LIST_ENTRY Entry;
  96. LIST_ENTRY KeyData; // points to the data (if any) associated with this key
  97. HKEY hKeyBase[MAX_NUM_HANDLES]; // array of key handles
  98. HKEY hKeyRoot; // handle to predefined key
  99. DWORD dwFlags; // flags that relate to the state of the key
  100. LPWSTR pwszFullKeyPath; // HKEY_LOCAL_MACHINE\Software\Microsoft\Windows...
  101. LPWSTR pwszSubKeyPath; // Software\Microsoft\Windows...
  102. UINT cHandles; // number of handles open for this key path
  103. } LOG_OPEN_KEY, *PLOG_OPEN_KEY;
  104. //
  105. // Flags that indicate what state the key is in.
  106. //
  107. #define LRC_EXISTING_KEY 0x00000001
  108. #define LRC_DELETED_KEY 0x00000002
  109. //
  110. // Flags that indicate what state the value is in.
  111. //
  112. #define LRC_EXISTING_VALUE 0x00000001
  113. #define LRC_DELETED_VALUE 0x00000002
  114. #define LRC_MODIFIED_VALUE 0x00000004
  115. //
  116. // Enumeration for updating the key information.
  117. //
  118. typedef enum {
  119. eAddKeyHandle = 0,
  120. eRemoveKeyHandle,
  121. eDeletedKey,
  122. eStartModifyValue,
  123. eEndModifyValue,
  124. eStartDeleteValue,
  125. eEndDeleteValue
  126. } UpdateType;
  127. //
  128. // The reg class that does all the real work.
  129. //
  130. class CLogRegistry {
  131. public:
  132. LONG CreateKeyExA(
  133. HKEY hKey,
  134. LPCSTR pszSubKey,
  135. DWORD Reserved,
  136. LPSTR pszClass,
  137. DWORD dwOptions,
  138. REGSAM samDesired,
  139. LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  140. PHKEY phkResult,
  141. LPDWORD lpdwDisposition
  142. );
  143. LONG CreateKeyExW(
  144. HKEY hKey,
  145. LPCWSTR pwszSubKey,
  146. DWORD Reserved,
  147. LPWSTR pwszClass,
  148. DWORD dwOptions,
  149. REGSAM samDesired,
  150. LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  151. PHKEY phkResult,
  152. LPDWORD lpdwDisposition
  153. );
  154. LONG OpenKeyExA(
  155. HKEY hKey,
  156. LPCSTR pszSubKey,
  157. DWORD ulOptions,
  158. REGSAM samDesired,
  159. PHKEY phkResult
  160. );
  161. LONG OpenKeyExW(
  162. HKEY hKey,
  163. LPCWSTR pwszSubKey,
  164. DWORD ulOptions,
  165. REGSAM samDesired,
  166. PHKEY phkResult
  167. );
  168. LONG OpenCurrentUser(
  169. REGSAM samDesired,
  170. PHKEY phkResult
  171. );
  172. LONG OpenUserClassesRoot(
  173. HANDLE hToken,
  174. DWORD dwOptions,
  175. REGSAM samDesired,
  176. PHKEY phkResult
  177. );
  178. LONG SetValueA(
  179. HKEY hKey,
  180. LPCSTR pszSubKey,
  181. DWORD dwType,
  182. LPCSTR pszData,
  183. DWORD cbData
  184. );
  185. LONG SetValueW(
  186. HKEY hKey,
  187. LPCWSTR pwszSubKey,
  188. DWORD dwType,
  189. LPCWSTR lpData,
  190. DWORD cbData
  191. );
  192. LONG SetValueExA(
  193. HKEY hKey,
  194. LPCSTR pszValueName,
  195. DWORD Reserved,
  196. DWORD dwType,
  197. CONST BYTE* lpData,
  198. DWORD cbData
  199. );
  200. LONG SetValueExW(
  201. HKEY hKey,
  202. LPCWSTR pwszValueName,
  203. DWORD Reserved,
  204. DWORD dwType,
  205. CONST BYTE* lpData,
  206. DWORD cbData
  207. );
  208. LONG CloseKey(
  209. HKEY hKey
  210. );
  211. LONG DeleteKeyA(
  212. HKEY hKey,
  213. LPCSTR pszSubKey
  214. );
  215. LONG DeleteKeyW(
  216. HKEY hKey,
  217. LPCWSTR pwszSubKey
  218. );
  219. LONG DeleteValueA(
  220. HKEY hKey,
  221. LPCSTR pszValueName
  222. );
  223. LONG DeleteValueW(
  224. HKEY hKey,
  225. LPCWSTR pwszValueName
  226. );
  227. private:
  228. BOOL GetOriginalDataForKey(
  229. IN PLOG_OPEN_KEY pLogOpenKey,
  230. IN PKEY_DATA pKeyData,
  231. IN LPCWSTR pwszValueName
  232. );
  233. BOOL GetFinalDataForKey(
  234. IN PLOG_OPEN_KEY pLogOpenKey,
  235. IN PKEY_DATA pKeyData,
  236. IN LPCWSTR pwszValueName
  237. );
  238. PLOG_OPEN_KEY AddSpecialKeyHandleToList(
  239. IN HKEY hKeyRoot,
  240. IN HKEY hKeyNew
  241. );
  242. PKEY_DATA AddValueNameToList(
  243. IN PLOG_OPEN_KEY pLogOpenKey,
  244. IN LPCWSTR pwszValueName
  245. );
  246. HKEY ForceSubKeyIntoList(
  247. IN HKEY hKeyPredefined,
  248. IN LPCWSTR pwszSubKey
  249. );
  250. PKEY_DATA FindValueNameInList(
  251. IN LPCWSTR pwszValueName,
  252. IN PLOG_OPEN_KEY pOpenKey
  253. );
  254. PLOG_OPEN_KEY FindKeyPathInList(
  255. IN LPCWSTR pwszKeyPath
  256. );
  257. PLOG_OPEN_KEY RemoveKeyHandleFromArray(
  258. IN HKEY hKey
  259. );
  260. PLOG_OPEN_KEY FindKeyHandleInArray(
  261. IN HKEY hKey
  262. );
  263. PLOG_OPEN_KEY AddKeyHandleToList(
  264. IN HKEY hKey,
  265. IN HKEY hKeyNew,
  266. IN LPCWSTR pwszSubKeyPath,
  267. IN BOOL fExisting
  268. );
  269. PLOG_OPEN_KEY UpdateKeyList(
  270. IN HKEY hKeyRoot,
  271. IN HKEY hKeyNew,
  272. IN LPCWSTR pwszSubKey,
  273. IN LPCWSTR pwszValueName,
  274. IN BOOL fExisting,
  275. IN UpdateType eType
  276. );
  277. };
  278. //
  279. // Keep us safe while we're playing with linked lists and shared resources.
  280. //
  281. static BOOL g_bInitialized = FALSE;
  282. CRITICAL_SECTION g_csLogging;
  283. class CLock
  284. {
  285. public:
  286. CLock()
  287. {
  288. if (!g_bInitialized)
  289. {
  290. InitializeCriticalSection(&g_csLogging);
  291. g_bInitialized = TRUE;
  292. }
  293. EnterCriticalSection(&g_csLogging);
  294. }
  295. ~CLock()
  296. {
  297. LeaveCriticalSection(&g_csLogging);
  298. }
  299. };
  300. APIHOOK_ENUM_BEGIN
  301. APIHOOK_ENUM_ENTRY(RegOpenKeyA)
  302. APIHOOK_ENUM_ENTRY(RegOpenKeyW)
  303. APIHOOK_ENUM_ENTRY(RegOpenKeyExA)
  304. APIHOOK_ENUM_ENTRY(RegOpenKeyExW)
  305. APIHOOK_ENUM_ENTRY(RegOpenCurrentUser)
  306. APIHOOK_ENUM_ENTRY(RegOpenUserClassesRoot)
  307. APIHOOK_ENUM_ENTRY(RegCreateKeyA)
  308. APIHOOK_ENUM_ENTRY(RegCreateKeyW)
  309. APIHOOK_ENUM_ENTRY(RegCreateKeyExA)
  310. APIHOOK_ENUM_ENTRY(RegCreateKeyExW)
  311. APIHOOK_ENUM_ENTRY(RegCloseKey)
  312. APIHOOK_ENUM_ENTRY(RegQueryValueA)
  313. APIHOOK_ENUM_ENTRY(RegQueryValueW)
  314. APIHOOK_ENUM_ENTRY(RegQueryValueExA)
  315. APIHOOK_ENUM_ENTRY(RegQueryValueExW)
  316. APIHOOK_ENUM_ENTRY(RegQueryInfoKeyA)
  317. APIHOOK_ENUM_ENTRY(RegQueryInfoKeyW)
  318. APIHOOK_ENUM_ENTRY(RegSetValueA)
  319. APIHOOK_ENUM_ENTRY(RegSetValueW)
  320. APIHOOK_ENUM_ENTRY(RegSetValueExA)
  321. APIHOOK_ENUM_ENTRY(RegSetValueExW)
  322. APIHOOK_ENUM_ENTRY(RegDeleteKeyA)
  323. APIHOOK_ENUM_ENTRY(RegDeleteKeyW)
  324. APIHOOK_ENUM_ENTRY(RegDeleteValueA)
  325. APIHOOK_ENUM_ENTRY(RegDeleteValueW)
  326. APIHOOK_ENUM_ENTRY(WriteProfileStringA)
  327. APIHOOK_ENUM_ENTRY(WriteProfileStringW)
  328. APIHOOK_ENUM_ENTRY(WriteProfileSectionA)
  329. APIHOOK_ENUM_ENTRY(WriteProfileSectionW)
  330. APIHOOK_ENUM_END
  331. #endif // __APPVERIFIER_LOGREGISTRYCHANGES_H_