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.

478 lines
10 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. settings.c
  5. Abstract:
  6. This module implements interfaces for enabling application
  7. verifier flags persistently (registry).
  8. Author:
  9. Silviu Calinoiu (SilviuC) 17-Apr-2001
  10. Revision History:
  11. --*/
  12. //
  13. // IMPORTANT NOTE.
  14. //
  15. // This dll cannot contain non-ntdll dependencies. This way it allows
  16. // verifier to be run system wide including for processes like smss and csrss.
  17. //
  18. // This explains why we load dynamically advapi32 dll and pick up the functions
  19. // for registry manipulation. It is safe to do that for interfaces that set
  20. // flags because they are called only in contexts where it is safe to load
  21. // additional dlls.
  22. //
  23. #include "pch.h"
  24. #include "verifier.h"
  25. #include "settings.h"
  26. //
  27. // Handy functions exported by ntdll.dll
  28. //
  29. int __cdecl sscanf(const char *, const char *, ...);
  30. int __cdecl swprintf(wchar_t *, const wchar_t *, ...);
  31. //
  32. // Signatures for registry functions
  33. //
  34. typedef LONG (APIENTRY * PFN_REG_CREATE_KEY) (HKEY, LPCWSTR, DWORD, LPWSTR, DWORD, REGSAM, LPSECURITY_ATTRIBUTES, PHKEY, LPDWORD);
  35. typedef LONG (APIENTRY * PFN_REG_CLOSE_KEY)(HKEY);
  36. typedef LONG (APIENTRY * PFN_REG_QUERY_VALUE) (HKEY, LPCWSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD);
  37. typedef LONG (APIENTRY * PFN_REG_SET_VALUE) (HKEY, LPCWSTR, DWORD, DWORD, CONST BYTE *, DWORD);
  38. typedef LONG (APIENTRY * PFN_REG_DELETE_VALUE) (HKEY, LPCWSTR);
  39. //
  40. // Dynamically detected registry functions
  41. //
  42. PFN_REG_CREATE_KEY FnRegCreateKey;
  43. PFN_REG_CLOSE_KEY FnRegCloseKey;
  44. PFN_REG_QUERY_VALUE FnRegQueryValue;
  45. PFN_REG_SET_VALUE FnRegSetValue;
  46. PFN_REG_DELETE_VALUE FnRegDeleteValue;
  47. //
  48. // Registry path to `image file execution options' key
  49. //
  50. #define EXECUTION_OPTIONS_KEY L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\"
  51. //
  52. // Internal functions
  53. //
  54. NTSTATUS
  55. AVrfpGetRegistryInterfaces (
  56. PVOID DllHandle
  57. );
  58. HKEY
  59. AVrfpOpenImageKey (
  60. PWSTR Name
  61. );
  62. VOID
  63. AVrfpCloseImageKey (
  64. HKEY Key
  65. );
  66. BOOL
  67. AVrfpReadGlobalFlags (
  68. HKEY Key,
  69. PDWORD Value
  70. );
  71. BOOL
  72. AVrfpWriteGlobalFlags (
  73. HKEY Key,
  74. DWORD Value
  75. );
  76. BOOL
  77. AVrfpDeleteGlobalFlags (
  78. HKEY Key
  79. );
  80. BOOL
  81. AVrfpReadVerifierFlags (
  82. HKEY Key,
  83. PDWORD Value
  84. );
  85. BOOL
  86. AVrfpWriteVerifierFlags (
  87. HKEY Key,
  88. DWORD Value
  89. );
  90. BOOL
  91. AVrfpDeleteVerifierFlags (
  92. HKEY Key
  93. );
  94. NTSTATUS
  95. VerifierSetFlags (
  96. PUNICODE_STRING ApplicationName,
  97. ULONG VerifierFlags,
  98. PVOID Details
  99. )
  100. /*++
  101. Routine Description:
  102. This routine enables persistently (through registry) application
  103. verifier flags for a specified application.
  104. Arguments:
  105. ApplicationName - name of the application to be verifier. The path should
  106. not be included. The extension should be included. Some examples of
  107. correct names are: `services.exe', `logon.scr'. Incorrect examples are:
  108. `c:\winnt\system32\notepad.exe' or just `notepad'. If we persist a setting
  109. for `xxx.exe' then every time a process whose binary is xxx.exe is launched
  110. application verifier will kick in no matter in what user context or from what
  111. disk location this happens.
  112. VerifierFlags - bit field with verifier flags to be enabled. The legal bits are
  113. declared in sdk\inc\nturtl.h (and winnt.h) as constants names RTL_VRF_FLG_XXX.
  114. For example RTL_VRF_FLG_FULL_PAGE_HEAP. If a zero value is used then all
  115. registry values related to verifier will b e deleted from registry.
  116. Details - Ignored right now. In the future this structure will support various
  117. extensions of the API (e.g. page heap flags, per dll page heap settings, etc.).
  118. Return Value:
  119. STATUS_SUCCESS if all flags requested have been enabled. It can return
  120. STATUS_NOT_IMPLEMENTED if one of the flags requested is not yet implemented
  121. or we decided to block it internally due to a bug. It can also return
  122. STATUS_INVALID_PARAMETER if the application name or other parameters
  123. are ill-formed.
  124. --*/
  125. {
  126. NTSTATUS Status;
  127. UNICODE_STRING AdvapiName;
  128. PVOID AdvapiHandle;
  129. HKEY Key;
  130. DWORD Flags;
  131. if (ApplicationName == NULL || ApplicationName->Buffer == NULL) {
  132. return STATUS_INVALID_PARAMETER;
  133. }
  134. //
  135. // Load advapi32.dll and get registry manipulation functions.
  136. //
  137. RtlInitUnicodeString (&AdvapiName, L"advapi32.dll");
  138. Status = LdrLoadDll (NULL, NULL, &AdvapiName, &AdvapiHandle);
  139. if (!NT_SUCCESS(Status)) {
  140. return Status;
  141. }
  142. Status = AVrfpGetRegistryInterfaces (AdvapiHandle);
  143. if (!NT_SUCCESS(Status)) {
  144. goto Exit;
  145. }
  146. //
  147. // Open `image file execution options\xxx.exe' key. If the key does not
  148. // exist it will be created.
  149. //
  150. Key = AVrfpOpenImageKey (ApplicationName->Buffer);
  151. if (Key == NULL) {
  152. Status = STATUS_INVALID_PARAMETER;
  153. goto Exit;
  154. }
  155. //
  156. // Create verifier settings.
  157. //
  158. if (VerifierFlags == 0) {
  159. Flags = 0;
  160. AVrfpReadGlobalFlags (Key, &Flags);
  161. Flags &= ~FLG_APPLICATION_VERIFIER;
  162. if (Flags == 0) {
  163. AVrfpDeleteGlobalFlags (Key);
  164. }
  165. else {
  166. AVrfpWriteGlobalFlags (Key, Flags);
  167. }
  168. AVrfpDeleteVerifierFlags (Key);
  169. }
  170. else {
  171. Flags = 0;
  172. AVrfpReadGlobalFlags (Key, &Flags);
  173. Flags |= FLG_APPLICATION_VERIFIER;
  174. AVrfpWriteGlobalFlags (Key, Flags);
  175. Flags = VerifierFlags;
  176. AVrfpWriteVerifierFlags (Key, Flags);
  177. }
  178. //
  179. // Cleanup and return.
  180. //
  181. AVrfpCloseImageKey (Key);
  182. Exit:
  183. LdrUnloadDll (AdvapiHandle);
  184. return Status;
  185. }
  186. NTSTATUS
  187. AVrfpGetRegistryInterfaces (
  188. PVOID AdvapiHandle
  189. )
  190. {
  191. NTSTATUS Status;
  192. ANSI_STRING FunctionName;
  193. PVOID FunctionAddress;
  194. RtlInitAnsiString (&FunctionName, "RegCreateKeyExW");
  195. Status = LdrGetProcedureAddress (AdvapiHandle, &FunctionName, 0, &FunctionAddress);
  196. if (!NT_SUCCESS(Status)) {
  197. return Status;
  198. }
  199. FnRegCreateKey = (PFN_REG_CREATE_KEY)FunctionAddress;
  200. RtlInitAnsiString (&FunctionName, "RegCloseKey");
  201. Status = LdrGetProcedureAddress (AdvapiHandle, &FunctionName, 0, &FunctionAddress);
  202. if (!NT_SUCCESS(Status)) {
  203. return Status;
  204. }
  205. FnRegCloseKey = (PFN_REG_CLOSE_KEY)FunctionAddress;
  206. RtlInitAnsiString (&FunctionName, "RegQueryValueExW");
  207. Status = LdrGetProcedureAddress (AdvapiHandle, &FunctionName, 0, &FunctionAddress);
  208. if (!NT_SUCCESS(Status)) {
  209. return Status;
  210. }
  211. FnRegQueryValue = (PFN_REG_QUERY_VALUE)FunctionAddress;
  212. RtlInitAnsiString (&FunctionName, "RegSetValueExW");
  213. Status = LdrGetProcedureAddress (AdvapiHandle, &FunctionName, 0, &FunctionAddress);
  214. if (!NT_SUCCESS(Status)) {
  215. return Status;
  216. }
  217. FnRegSetValue = (PFN_REG_SET_VALUE)FunctionAddress;
  218. RtlInitAnsiString (&FunctionName, "RegDeleteValueW");
  219. Status = LdrGetProcedureAddress (AdvapiHandle, &FunctionName, 0, &FunctionAddress);
  220. if (!NT_SUCCESS(Status)) {
  221. return Status;
  222. }
  223. FnRegDeleteValue = (PFN_REG_DELETE_VALUE)FunctionAddress;
  224. return Status;
  225. }
  226. HKEY
  227. AVrfpOpenImageKey (
  228. PWSTR Name
  229. )
  230. {
  231. HKEY Key;
  232. LONG Result;
  233. WCHAR Buffer [MAX_PATH];
  234. wcscpy (Buffer, EXECUTION_OPTIONS_KEY);
  235. wcscat (Buffer, Name);
  236. Result = FnRegCreateKey (HKEY_LOCAL_MACHINE,
  237. Buffer,
  238. 0,
  239. 0,
  240. 0,
  241. KEY_ALL_ACCESS,
  242. NULL,
  243. &Key,
  244. NULL);
  245. if (Result != ERROR_SUCCESS) {
  246. return NULL;
  247. }
  248. else {
  249. return Key;
  250. }
  251. }
  252. VOID
  253. AVrfpCloseImageKey (
  254. HKEY Key
  255. )
  256. {
  257. FnRegCloseKey (Key);
  258. }
  259. BOOL
  260. AVrfpReadGlobalFlags (
  261. HKEY Key,
  262. PDWORD Value
  263. )
  264. {
  265. LONG Result;
  266. DWORD Type;
  267. BYTE Buffer[32];
  268. BYTE Buffer2[32];
  269. DWORD BytesRead;
  270. DWORD FlagValue;
  271. DWORD I;
  272. BytesRead = sizeof Buffer;
  273. Result = FnRegQueryValue (Key,
  274. L"GlobalFlag",
  275. 0,
  276. &Type,
  277. (LPBYTE)Buffer,
  278. &BytesRead);
  279. if (Result != ERROR_SUCCESS || Type != REG_SZ) {
  280. DbgPrint ("Result %u \n", Result);
  281. return FALSE;
  282. }
  283. else {
  284. for (I = 0; Buffer[2 * I] != L'\0'; I += 1) {
  285. Buffer2[I] = Buffer[2 * I];
  286. }
  287. Buffer2[I] = 0;
  288. FlagValue = 0;
  289. sscanf (Buffer2, "%x", &FlagValue);
  290. if (Value) {
  291. *Value = FlagValue;
  292. }
  293. return TRUE;
  294. }
  295. }
  296. BOOL
  297. AVrfpWriteGlobalFlags (
  298. HKEY Key,
  299. DWORD Value
  300. )
  301. {
  302. LONG Result;
  303. WCHAR Buffer[16];
  304. DWORD Length;
  305. swprintf (Buffer, L"0x%08X", Value);
  306. Length = (wcslen(Buffer) + 1) * sizeof (WCHAR);
  307. Result = FnRegSetValue (Key,
  308. L"GlobalFlag",
  309. 0,
  310. REG_SZ,
  311. (LPBYTE)Buffer,
  312. Length);
  313. return (Result == ERROR_SUCCESS);
  314. }
  315. BOOL
  316. AVrfpDeleteGlobalFlags (
  317. HKEY Key
  318. )
  319. {
  320. LONG Result;
  321. Result = FnRegDeleteValue (Key, L"GlobalFlag");
  322. return (Result == ERROR_SUCCESS);
  323. }
  324. BOOL
  325. AVrfpReadVerifierFlags (
  326. HKEY Key,
  327. PDWORD Value
  328. )
  329. {
  330. LONG Result;
  331. DWORD Type;
  332. DWORD BytesRead;
  333. BytesRead = sizeof *Value;
  334. Result = FnRegQueryValue (Key,
  335. L"VerifierValue",
  336. 0,
  337. &Type,
  338. (LPBYTE)Value,
  339. &BytesRead);
  340. return (Result == ERROR_SUCCESS && Type != REG_DWORD);
  341. }
  342. BOOL
  343. AVrfpWriteVerifierFlags (
  344. HKEY Key,
  345. DWORD Value
  346. )
  347. {
  348. LONG Result;
  349. Result = FnRegSetValue (Key,
  350. L"VerifierFlags",
  351. 0,
  352. REG_DWORD,
  353. (LPBYTE)(&Value),
  354. sizeof Value);
  355. return (Result == ERROR_SUCCESS);
  356. }
  357. BOOL
  358. AVrfpDeleteVerifierFlags (
  359. HKEY Key
  360. )
  361. {
  362. LONG Result;
  363. Result = FnRegDeleteValue (Key, L"VerifierFlags");
  364. return (Result == ERROR_SUCCESS);
  365. }