Leaked source code of windows server 2003
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.

661 lines
18 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. avrfutil.cpp
  5. Abstract:
  6. This module implements the code for manipulating the AppVerifier log file.
  7. Author:
  8. dmunsil created 04/26/2001
  9. Revision History:
  10. 08/14/2001 robkenny Moved code inside the ShimLib namespace.
  11. 09/21/2001 rparsons Logging code now uses NT calls.
  12. 09/25/2001 rparsons Added critical section.
  13. --*/
  14. #include "avrfutil.h"
  15. #include "strsafe.h"
  16. namespace ShimLib
  17. {
  18. HANDLE
  19. AVCreateKeyPath(
  20. LPCWSTR pwszPath
  21. )
  22. /*++
  23. Return: The handle to the registry key created.
  24. Desc: Given a path to the key, open/create it.
  25. The key returns the handle to the key or NULL on failure.
  26. --*/
  27. {
  28. UNICODE_STRING ustrKey;
  29. HANDLE KeyHandle = NULL;
  30. NTSTATUS Status;
  31. OBJECT_ATTRIBUTES ObjectAttributes;
  32. ULONG CreateDisposition;
  33. RtlInitUnicodeString(&ustrKey, pwszPath);
  34. InitializeObjectAttributes(&ObjectAttributes,
  35. &ustrKey,
  36. OBJ_CASE_INSENSITIVE,
  37. NULL,
  38. NULL);
  39. Status = NtCreateKey(&KeyHandle,
  40. STANDARD_RIGHTS_WRITE |
  41. KEY_QUERY_VALUE |
  42. KEY_ENUMERATE_SUB_KEYS |
  43. KEY_SET_VALUE |
  44. KEY_CREATE_SUB_KEY,
  45. &ObjectAttributes,
  46. 0,
  47. NULL,
  48. REG_OPTION_NON_VOLATILE,
  49. &CreateDisposition);
  50. if (!NT_SUCCESS(Status)) {
  51. KeyHandle = NULL;
  52. goto out;
  53. }
  54. out:
  55. return KeyHandle;
  56. }
  57. BOOL SaveShimSettingDWORD(
  58. LPCWSTR szShim,
  59. LPCWSTR szExe,
  60. LPCWSTR szSetting,
  61. DWORD dwSetting
  62. )
  63. {
  64. WCHAR szKey[MAX_PATH * 2];
  65. UNICODE_STRING ustrKey;
  66. UNICODE_STRING ustrSetting;
  67. NTSTATUS Status;
  68. OBJECT_ATTRIBUTES ObjectAttributes;
  69. HANDLE KeyHandle;
  70. BOOL bRet = FALSE;
  71. ULONG CreateDisposition;
  72. HRESULT hr;
  73. if (!szShim || !szSetting || !szExe) {
  74. goto out;
  75. }
  76. //
  77. // we have to ensure all the sub-keys are created
  78. //
  79. hr = StringCchCopyW(szKey, ARRAYSIZE(szKey), APPCOMPAT_KEY_PATH_MACHINE);
  80. if (FAILED(hr)) {
  81. goto out;
  82. }
  83. KeyHandle = AVCreateKeyPath(szKey);
  84. if (!KeyHandle) {
  85. goto out;
  86. }
  87. NtClose(KeyHandle);
  88. hr = StringCchCopyW(szKey, ARRAYSIZE(szKey), AV_KEY);
  89. if (FAILED(hr)) {
  90. goto out;
  91. }
  92. KeyHandle = AVCreateKeyPath(szKey);
  93. if (!KeyHandle) {
  94. goto out;
  95. }
  96. NtClose(KeyHandle);
  97. hr = StringCchCatW(szKey, ARRAYSIZE(szKey), L"\\");
  98. if (FAILED(hr)) {
  99. goto out;
  100. }
  101. hr = StringCchCatW(szKey, ARRAYSIZE(szKey), szExe);
  102. if (FAILED(hr)) {
  103. goto out;
  104. }
  105. KeyHandle = AVCreateKeyPath(szKey);
  106. if (!KeyHandle) {
  107. goto out;
  108. }
  109. NtClose(KeyHandle);
  110. hr = StringCchCatW(szKey, ARRAYSIZE(szKey), L"\\");
  111. if (FAILED(hr)) {
  112. goto out;
  113. }
  114. hr = StringCchCatW(szKey, ARRAYSIZE(szKey), szShim);
  115. if (FAILED(hr)) {
  116. goto out;
  117. }
  118. KeyHandle = AVCreateKeyPath(szKey);
  119. if (!KeyHandle) {
  120. goto out;
  121. }
  122. RtlInitUnicodeString(&ustrSetting, szSetting);
  123. Status = NtSetValueKey(KeyHandle,
  124. &ustrSetting,
  125. 0,
  126. REG_DWORD,
  127. (PVOID)&dwSetting,
  128. sizeof(dwSetting));
  129. NtClose(KeyHandle);
  130. if (!NT_SUCCESS(Status)) {
  131. goto out;
  132. }
  133. bRet = TRUE;
  134. out:
  135. return bRet;
  136. }
  137. DWORD GetShimSettingDWORD(
  138. LPCWSTR szShim,
  139. LPCWSTR szExe,
  140. LPCWSTR szSetting,
  141. DWORD dwDefault
  142. )
  143. {
  144. WCHAR szKey[MAX_PATH * 2];
  145. UNICODE_STRING ustrKey;
  146. UNICODE_STRING ustrSetting;
  147. NTSTATUS Status;
  148. OBJECT_ATTRIBUTES ObjectAttributes;
  149. HANDLE KeyHandle;
  150. PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation;
  151. ULONG KeyValueBuffer[256];
  152. ULONG KeyValueLength;
  153. if (!szShim || !szSetting || !szExe) {
  154. goto out;
  155. }
  156. //
  157. // not checking error return because it will fail anyway
  158. // if the string is truncated
  159. //
  160. StringCchCopyW(szKey, ARRAYSIZE(szKey), AV_KEY);
  161. StringCchCatW(szKey, ARRAYSIZE(szKey), L"\\");
  162. StringCchCatW(szKey, ARRAYSIZE(szKey), szExe);
  163. StringCchCatW(szKey, ARRAYSIZE(szKey), L"\\");
  164. StringCchCatW(szKey, ARRAYSIZE(szKey), szShim);
  165. RtlInitUnicodeString(&ustrKey, szKey);
  166. RtlInitUnicodeString(&ustrSetting, szSetting);
  167. InitializeObjectAttributes(&ObjectAttributes,
  168. &ustrKey,
  169. OBJ_CASE_INSENSITIVE,
  170. NULL,
  171. NULL);
  172. Status = NtOpenKey(&KeyHandle,
  173. GENERIC_READ,
  174. &ObjectAttributes);
  175. if (!NT_SUCCESS(Status)) {
  176. //
  177. // OK, didn't find a specific one for this exe, try the default setting
  178. //
  179. StringCchCopyW(szKey, ARRAYSIZE(szKey), AV_KEY);
  180. StringCchCatW(szKey, ARRAYSIZE(szKey), L"\\");
  181. StringCchCatW(szKey, ARRAYSIZE(szKey), AVRF_DEFAULT_SETTINGS_NAME_W);
  182. StringCchCatW(szKey, ARRAYSIZE(szKey), L"\\");
  183. StringCchCatW(szKey, ARRAYSIZE(szKey), szShim);
  184. RtlInitUnicodeString(&ustrKey, szKey);
  185. RtlInitUnicodeString(&ustrSetting, szSetting);
  186. InitializeObjectAttributes(&ObjectAttributes,
  187. &ustrKey,
  188. OBJ_CASE_INSENSITIVE,
  189. NULL,
  190. NULL);
  191. Status = NtOpenKey(&KeyHandle,
  192. GENERIC_READ,
  193. &ObjectAttributes);
  194. if (!NT_SUCCESS(Status)) {
  195. goto out;
  196. }
  197. }
  198. KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)KeyValueBuffer;
  199. Status = NtQueryValueKey(KeyHandle,
  200. &ustrSetting,
  201. KeyValuePartialInformation,
  202. KeyValueInformation,
  203. sizeof(KeyValueBuffer),
  204. &KeyValueLength);
  205. NtClose(KeyHandle);
  206. if (!NT_SUCCESS(Status)) {
  207. goto out;
  208. }
  209. //
  210. // Check for the value type.
  211. //
  212. if (KeyValueInformation->Type != REG_DWORD) {
  213. goto out;
  214. }
  215. dwDefault = *(DWORD*)(&KeyValueInformation->Data);
  216. out:
  217. return dwDefault;
  218. }
  219. BOOL SaveShimSettingString(
  220. LPCWSTR szShim,
  221. LPCWSTR szExe,
  222. LPCWSTR szSetting,
  223. LPCWSTR szValue
  224. )
  225. {
  226. WCHAR szKey[MAX_PATH * 2];
  227. UNICODE_STRING ustrKey;
  228. UNICODE_STRING ustrSetting;
  229. NTSTATUS Status;
  230. OBJECT_ATTRIBUTES ObjectAttributes;
  231. HANDLE KeyHandle;
  232. BOOL bRet = FALSE;
  233. ULONG CreateDisposition;
  234. HRESULT hr;
  235. if (!szShim || !szSetting || !szValue || !szExe) {
  236. goto out;
  237. }
  238. //
  239. // we have to ensure all the sub-keys are created
  240. //
  241. hr = StringCchCopyW(szKey, ARRAYSIZE(szKey), APPCOMPAT_KEY_PATH_MACHINE);
  242. if (FAILED(hr)) {
  243. goto out;
  244. }
  245. KeyHandle = AVCreateKeyPath(szKey);
  246. if (!KeyHandle) {
  247. goto out;
  248. }
  249. NtClose(KeyHandle);
  250. hr = StringCchCopyW(szKey, ARRAYSIZE(szKey), AV_KEY);
  251. if (FAILED(hr)) {
  252. goto out;
  253. }
  254. KeyHandle = AVCreateKeyPath(szKey);
  255. if (!KeyHandle) {
  256. goto out;
  257. }
  258. NtClose(KeyHandle);
  259. hr = StringCchCatW(szKey, ARRAYSIZE(szKey), L"\\");
  260. if (FAILED(hr)) {
  261. goto out;
  262. }
  263. hr = StringCchCatW(szKey, ARRAYSIZE(szKey), szExe);
  264. if (FAILED(hr)) {
  265. goto out;
  266. }
  267. KeyHandle = AVCreateKeyPath(szKey);
  268. if (!KeyHandle) {
  269. goto out;
  270. }
  271. NtClose(KeyHandle);
  272. hr = StringCchCatW(szKey, ARRAYSIZE(szKey), L"\\");
  273. if (FAILED(hr)) {
  274. goto out;
  275. }
  276. hr = StringCchCatW(szKey, ARRAYSIZE(szKey), szShim);
  277. if (FAILED(hr)) {
  278. goto out;
  279. }
  280. KeyHandle = AVCreateKeyPath(szKey);
  281. if (!KeyHandle) {
  282. goto out;
  283. }
  284. RtlInitUnicodeString(&ustrSetting, szSetting);
  285. Status = NtSetValueKey(KeyHandle,
  286. &ustrSetting,
  287. 0,
  288. REG_SZ,
  289. (PVOID)szValue,
  290. (wcslen(szValue) + 1) * sizeof(WCHAR));
  291. NtClose(KeyHandle);
  292. if (!NT_SUCCESS(Status)) {
  293. goto out;
  294. }
  295. bRet = TRUE;
  296. out:
  297. return bRet;
  298. }
  299. BOOL GetShimSettingString(
  300. LPCWSTR szShim,
  301. LPCWSTR szExe,
  302. LPCWSTR szSetting,
  303. LPWSTR szResult,
  304. DWORD dwBufferLen // in WCHARs
  305. )
  306. {
  307. WCHAR szKey[MAX_PATH * 2];
  308. UNICODE_STRING ustrKey;
  309. UNICODE_STRING ustrSetting;
  310. NTSTATUS Status;
  311. OBJECT_ATTRIBUTES ObjectAttributes;
  312. HANDLE KeyHandle;
  313. PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation;
  314. ULONG KeyValueBuffer[256];
  315. ULONG KeyValueLength;
  316. BOOL bRet = FALSE;
  317. if (!szShim || !szSetting || !szResult || !szExe) {
  318. goto out;
  319. }
  320. //
  321. // not checking error return because it will fail anyway
  322. // if the string is truncated
  323. //
  324. StringCchCopyW(szKey, ARRAYSIZE(szKey), AV_KEY);
  325. StringCchCatW(szKey, ARRAYSIZE(szKey), L"\\");
  326. StringCchCatW(szKey, ARRAYSIZE(szKey), szExe);
  327. StringCchCatW(szKey, ARRAYSIZE(szKey), L"\\");
  328. StringCchCatW(szKey, ARRAYSIZE(szKey), szShim);
  329. RtlInitUnicodeString(&ustrKey, szKey);
  330. RtlInitUnicodeString(&ustrSetting, szSetting);
  331. InitializeObjectAttributes(&ObjectAttributes,
  332. &ustrKey,
  333. OBJ_CASE_INSENSITIVE,
  334. NULL,
  335. NULL);
  336. Status = NtOpenKey(&KeyHandle,
  337. GENERIC_READ,
  338. &ObjectAttributes);
  339. if (!NT_SUCCESS(Status)) {
  340. //
  341. // OK, didn't find a specific one for this exe, try the default setting
  342. //
  343. StringCchCopyW(szKey, ARRAYSIZE(szKey), AV_KEY);
  344. StringCchCatW(szKey, ARRAYSIZE(szKey), L"\\");
  345. StringCchCatW(szKey, ARRAYSIZE(szKey), AVRF_DEFAULT_SETTINGS_NAME_W);
  346. StringCchCatW(szKey, ARRAYSIZE(szKey), L"\\");
  347. StringCchCatW(szKey, ARRAYSIZE(szKey), szShim);
  348. RtlInitUnicodeString(&ustrKey, szKey);
  349. RtlInitUnicodeString(&ustrSetting, szSetting);
  350. InitializeObjectAttributes(&ObjectAttributes,
  351. &ustrKey,
  352. OBJ_CASE_INSENSITIVE,
  353. NULL,
  354. NULL);
  355. Status = NtOpenKey(&KeyHandle,
  356. GENERIC_READ,
  357. &ObjectAttributes);
  358. if (!NT_SUCCESS(Status)) {
  359. goto out;
  360. }
  361. }
  362. KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)KeyValueBuffer;
  363. Status = NtQueryValueKey(KeyHandle,
  364. &ustrSetting,
  365. KeyValuePartialInformation,
  366. KeyValueInformation,
  367. sizeof(KeyValueBuffer),
  368. &KeyValueLength);
  369. NtClose(KeyHandle);
  370. if (!NT_SUCCESS(Status)) {
  371. goto out;
  372. }
  373. //
  374. // Check for the value type.
  375. //
  376. if (KeyValueInformation->Type != REG_SZ) {
  377. goto out;
  378. }
  379. //
  380. // check to see if the datalength is bigger than our local nbuffer
  381. //
  382. if (KeyValueInformation->DataLength > (sizeof(KeyValueBuffer) - sizeof(KEY_VALUE_PARTIAL_INFORMATION))) {
  383. KeyValueInformation->DataLength = sizeof(KeyValueBuffer) - sizeof(KEY_VALUE_PARTIAL_INFORMATION);
  384. }
  385. //
  386. // change the buffer length to correspond to the data length, if necessary
  387. //
  388. if (KeyValueInformation->DataLength < (dwBufferLen * sizeof(WCHAR))) {
  389. dwBufferLen = (KeyValueInformation->DataLength / sizeof(WCHAR));
  390. }
  391. RtlCopyMemory(szResult, KeyValueInformation->Data, dwBufferLen * sizeof(WCHAR));
  392. szResult[dwBufferLen - 1] = 0;
  393. bRet = TRUE;
  394. out:
  395. return bRet;
  396. }
  397. DWORD
  398. GetAppVerifierLogPath(
  399. LPWSTR pwszBuffer,
  400. DWORD cchBufferSize
  401. )
  402. /*++
  403. Return: On success, pwszBuffer receives the expanded path.
  404. Desc: Returns the path where AppVerifier log files are stored.
  405. --*/
  406. {
  407. return ExpandEnvironmentStrings(L"%ALLUSERSPROFILE%\\Documents\\AppVerifierLogs",
  408. pwszBuffer,
  409. cchBufferSize);
  410. }
  411. BOOL
  412. IsInternalModeEnabled(
  413. void
  414. )
  415. /*++
  416. Return: TRUE if internal mode is enabled, FALSE otherwise.
  417. Desc: This function is used to determine if the AppVerifier
  418. is being used internally (within Microsoft) or externally.
  419. If the value is not present, we return FALSE as external
  420. is the default.
  421. --*/
  422. {
  423. NTSTATUS Status;
  424. OBJECT_ATTRIBUTES ObjectAttributes;
  425. UNICODE_STRING ustrKey;
  426. UNICODE_STRING ustrSetting;
  427. HANDLE KeyHandle;
  428. DWORD dwReturn = 0;
  429. ULONG KeyValueLength;
  430. PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation;
  431. ULONG KeyValueBuffer[256];
  432. RtlInitUnicodeString(&ustrKey, AV_KEY);
  433. RtlInitUnicodeString(&ustrSetting, AV_INTERNALMODE);
  434. InitializeObjectAttributes(&ObjectAttributes,
  435. &ustrKey,
  436. OBJ_CASE_INSENSITIVE,
  437. NULL,
  438. NULL);
  439. Status = NtOpenKey(&KeyHandle,
  440. GENERIC_READ,
  441. &ObjectAttributes);
  442. if (NT_SUCCESS(Status)) {
  443. KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)KeyValueBuffer;
  444. Status = NtQueryValueKey(KeyHandle,
  445. &ustrSetting,
  446. KeyValuePartialInformation,
  447. KeyValueInformation,
  448. sizeof(KeyValueBuffer),
  449. &KeyValueLength);
  450. NtClose(KeyHandle);
  451. if (!NT_SUCCESS(Status)) {
  452. //
  453. // Either the value doesn't exist or an error occured.
  454. //
  455. return FALSE;
  456. }
  457. //
  458. // Check for the value type.
  459. //
  460. if (KeyValueInformation->Type != REG_DWORD) {
  461. //
  462. // Not a DWORD - not our value.
  463. //
  464. return FALSE;
  465. }
  466. dwReturn = *(DWORD*)(&KeyValueInformation->Data);
  467. }
  468. return (BOOL)dwReturn;
  469. }
  470. BOOL
  471. EnableDisableInternalMode(
  472. DWORD dwSetting
  473. )
  474. /*++
  475. Return: TRUE on success, FALSE otherwise.
  476. Desc: This function is used to enable or disable the
  477. internal mode setting used by the AppVerifier.
  478. --*/
  479. {
  480. NTSTATUS Status;
  481. HANDLE KeyHandle;
  482. HRESULT hr;
  483. UNICODE_STRING ustrSetting;
  484. UNICODE_STRING ustrKey;
  485. OBJECT_ATTRIBUTES ObjectAttributes;
  486. BOOL bRet = FALSE;
  487. WCHAR szKey[MAX_PATH * 2];
  488. //
  489. // Ensure that our entire key path exists.
  490. //
  491. hr = StringCchCopyW(szKey, ARRAYSIZE(szKey), APPCOMPAT_KEY_PATH_MACHINE);
  492. if (FAILED(hr)) {
  493. goto out;
  494. }
  495. KeyHandle = AVCreateKeyPath(szKey);
  496. if (!KeyHandle) {
  497. goto out;
  498. }
  499. NtClose(KeyHandle);
  500. hr = StringCchCopyW(szKey, ARRAYSIZE(szKey), AV_KEY);
  501. if (FAILED(hr)) {
  502. goto out;
  503. }
  504. KeyHandle = AVCreateKeyPath(szKey);
  505. if (!KeyHandle) {
  506. goto out;
  507. }
  508. NtClose(KeyHandle);
  509. RtlInitUnicodeString(&ustrKey, AV_KEY);
  510. RtlInitUnicodeString(&ustrSetting, AV_INTERNALMODE);
  511. InitializeObjectAttributes(&ObjectAttributes,
  512. &ustrKey,
  513. OBJ_CASE_INSENSITIVE,
  514. NULL,
  515. NULL);
  516. Status = NtOpenKey(&KeyHandle,
  517. GENERIC_WRITE,
  518. &ObjectAttributes);
  519. if (!NT_SUCCESS(Status)) {
  520. goto out;
  521. }
  522. Status = NtSetValueKey(KeyHandle,
  523. &ustrSetting,
  524. 0,
  525. REG_DWORD,
  526. (PVOID)&dwSetting,
  527. sizeof(dwSetting));
  528. NtClose(KeyHandle);
  529. if (!NT_SUCCESS(Status)) {
  530. goto out;
  531. }
  532. bRet = TRUE;
  533. out:
  534. return bRet;
  535. }
  536. } // end of namespace ShimLib