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.

1345 lines
42 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: profile.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * This module contains code to emulate ini file mapping.
  7. *
  8. * History:
  9. * 30-Nov-1993 SanfordS Created.
  10. \***************************************************************************/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. /***************************************************************************\
  14. * aFastRegMap[]
  15. *
  16. * This array maps section ids (PMAP_) to cached registry keys and section
  17. * addresses within the registry. IF INI FILE MAPPING CHANGES ARE MADE,
  18. * THIS TABLE MUST BE UPDATED.
  19. *
  20. * The first character of the szSection field indicates what root the
  21. * section is in. (or locked open status)
  22. * M = LocalMachine
  23. * U = CurrentUser
  24. * L = Locked open - used only on M mappings.
  25. *
  26. * History:
  27. \***************************************************************************/
  28. #define PROOT_CPANEL 0
  29. #define PROOT_ACCESS 1
  30. #define PROOT_CURRENTM 2
  31. #define PROOT_CURRENTU 3
  32. #define PROOT_CONTROL 4
  33. #define PROOT_SERVICES 5
  34. #define PROOT_KEYBOARD 6
  35. #define PROOT_SYSTEM 7
  36. typedef struct tagFASTREGMAP {
  37. UINT idRoot;
  38. PCWSTR szSection;
  39. } FASTREGMAP, *PFASTREGMAP;
  40. CONST PCWSTR aFastRegRoot[] = {
  41. L"UControl Panel\\", // PROOT_CPANEL
  42. L"UControl Panel\\Accessibility\\", // PROOT_ACCESS
  43. L"MSoftware\\Microsoft\\Windows NT\\CurrentVersion\\", // PROOT_CURRENTM
  44. L"USoftware\\Microsoft\\Windows NT\\CurrentVersion\\", // PROOT_CURRENTU
  45. L"MSystem\\CurrentControlSet\\Control\\", // PROOT_CONTROL
  46. L"MSystem\\CurrentControlSet\\Services\\", // PROOT_SERVICES
  47. L"UKeyboard Layout\\", // PROOT_KEYBOARD
  48. L"MSystem\\", // PROOT_SYSTEM
  49. };
  50. CONST FASTREGMAP aFastRegMap[PMAP_LAST + 1] = {
  51. { PROOT_CPANEL, L"Colors" }, // PMAP_COLORS
  52. { PROOT_CPANEL, L"Cursors" }, // PMAP_CURSORS
  53. { PROOT_CURRENTM, L"Windows" }, // PMAP_WINDOWSM
  54. { PROOT_CURRENTU, L"Windows" }, // PMAP_WINDOWSU
  55. { PROOT_CPANEL, L"Desktop" }, // PMAP_DESKTOP
  56. { PROOT_CPANEL, L"Icons" }, // PMAP_ICONS
  57. { PROOT_CURRENTM, L"Fonts" }, // PMAP_FONTS
  58. { PROOT_CURRENTU, L"TrueType" }, // PMAP_TRUETYPE
  59. { PROOT_CONTROL, L"Keyboard Layout" }, // PMAP_KBDLAYOUT
  60. { PROOT_SERVICES, L"RIT" }, // PMAP_INPUT
  61. { PROOT_CURRENTM, L"Compatibility" }, // PMAP_COMPAT
  62. { PROOT_CONTROL, L"Session Manager\\SubSystems" }, // PMAP_SUBSYSTEMS
  63. { PROOT_CPANEL, L"Sound" }, // PMAP_BEEP
  64. { PROOT_CPANEL, L"Mouse" }, // PMAP_MOUSE
  65. { PROOT_CPANEL, L"Keyboard" }, // PMAP_KEYBOARD
  66. { PROOT_ACCESS, L"StickyKeys" }, // PMAP_STICKYKEYS
  67. { PROOT_ACCESS, L"Keyboard Response" }, // PMAP_KEYBOARDRESPONSE
  68. { PROOT_ACCESS, L"MouseKeys" }, // PMAP_MOUSEKEYS
  69. { PROOT_ACCESS, L"ToggleKeys" }, // PMAP_TOGGLEKEYS
  70. { PROOT_ACCESS, L"TimeOut" }, // PMAP_TIMEOUT
  71. { PROOT_ACCESS, L"SoundSentry" }, // PMAP_SOUNDSENTRY
  72. { PROOT_ACCESS, L"ShowSounds" }, // PMAP_SHOWSOUNDS
  73. { PROOT_CURRENTM, L"AeDebug" }, // PMAP_AEDEBUG
  74. { PROOT_CONTROL, L"NetworkProvider" }, // PMAP_NETWORK
  75. { PROOT_CPANEL, L"Desktop\\WindowMetrics" }, // PMAP_METRICS
  76. { PROOT_KEYBOARD, L"" }, // PMAP_UKBDLAYOUT
  77. { PROOT_KEYBOARD, L"Toggle" }, // PMAP_UKBDLAYOUTTOGGLE
  78. { PROOT_CURRENTM, L"Winlogon" }, // PMAP_WINLOGON
  79. { PROOT_ACCESS, L"Keyboard Preference" }, // PMAP_KEYBOARDPREF
  80. { PROOT_ACCESS, L"Blind Access" }, // PMAP_SCREENREADER
  81. { PROOT_ACCESS, L"HighContrast" }, // PMAP_HIGHCONTRAST
  82. { PROOT_CURRENTM, L"IME Compatibility" }, // PMAP_IMECOMPAT
  83. { PROOT_CURRENTM, L"IMM" }, // PMAP_IMM
  84. { PROOT_CONTROL, L"Session Manager\\SubSystems\\Pool" }, // PMAP_POOLLIMITS
  85. { PROOT_CURRENTM, L"Compatibility32" }, // PMAP_COMPAT32
  86. { PROOT_CURRENTM, L"WOW\\SetupPrograms" }, // PMAP_SETUPPROGRAMNAMES
  87. { PROOT_CPANEL, L"Input Method" }, // PMAP_INPUTMETHOD
  88. { PROOT_CURRENTM, L"Compatibility2" }, // PMAP_COMPAT2
  89. { PROOT_SERVICES, L"Mouclass\\Parameters" }, // PMAP_MOUCLASS_PARAMS
  90. { PROOT_SERVICES, L"Kbdclass\\Parameters" }, // PMAP_KBDCLASS_PARAMS
  91. { PROOT_CONTROL, L"ComputerName\\ComputerName" }, // PMAP_COMPUTERNAME
  92. { PROOT_CONTROL, L"Terminal Server" }, // PMAP_TS
  93. { PROOT_SYSTEM, L"WPA\\TabletPC" }, // PMAP_TABLETPC
  94. { PROOT_SYSTEM, L"WPA\\MediaCenter" }, // PMAP_MEDIACENTER
  95. { PROOT_CURRENTM, L"Windows" }, // PMAP_TS_EXCLUDE_DESKTOP_VERSION
  96. };
  97. WCHAR PreviousUserStringBuf[256];
  98. UNICODE_STRING PreviousUserString = {0, sizeof PreviousUserStringBuf, PreviousUserStringBuf};
  99. LUID luidPrevious;
  100. CONST WCHAR wszDefaultUser[] = L"\\Registry\\User\\.Default";
  101. UNICODE_STRING DefaultUserString = {sizeof wszDefaultUser - sizeof(WCHAR), sizeof wszDefaultUser, (WCHAR *)wszDefaultUser};
  102. void InitPreviousUserString(void) {
  103. UNICODE_STRING UserString;
  104. LUID luidCaller;
  105. CheckCritIn();
  106. /*
  107. * Speed hack, check if luid of this process == system or previous to
  108. * save work.
  109. */
  110. if (NT_SUCCESS(GetProcessLuid(NULL, &luidCaller))) {
  111. if (RtlEqualLuid(&luidCaller, &luidPrevious)) {
  112. return; // same as last time - no work.
  113. }
  114. luidPrevious = luidCaller;
  115. if (RtlEqualLuid(&luidCaller, &luidSystem))
  116. goto DefaultUser;
  117. } else {
  118. luidPrevious = RtlConvertLongToLuid(0);
  119. }
  120. /*
  121. * Set up current user registry base string.
  122. */
  123. if (!NT_SUCCESS(RtlFormatCurrentUserKeyPath(&UserString))) {
  124. DefaultUser:
  125. RtlCopyUnicodeString(&PreviousUserString, &DefaultUserString);
  126. } else {
  127. UserAssert(sizeof(PreviousUserStringBuf) >= UserString.Length + 4);
  128. RtlCopyUnicodeString(&PreviousUserString, &UserString);
  129. RtlFreeUnicodeString(&UserString);
  130. }
  131. RtlAppendUnicodeToString(&PreviousUserString, L"\\");
  132. }
  133. typedef struct tagPROFILEUSERNAME {
  134. WCHAR awcName[MAXPROFILEBUF];
  135. UNICODE_STRING NameString;
  136. } PROFILEUSERNAME, *PPROFILEUSERNAME;
  137. PUNICODE_STRING CreateProfileUserName(TL *ptl)
  138. {
  139. PPROFILEUSERNAME pMapName;
  140. CheckCritIn();
  141. pMapName = UserAllocPoolWithQuota(sizeof (PROFILEUSERNAME), TAG_PROFILEUSERNAME);
  142. if (!pMapName) {
  143. RIPMSG0(RIP_WARNING, "CreateProfileUserName: Allocation failed");
  144. return NULL;
  145. }
  146. ThreadLockPool(PtiCurrent(), pMapName, ptl);
  147. pMapName->NameString.Length = 0;
  148. pMapName->NameString.MaximumLength = sizeof (pMapName->awcName);
  149. pMapName->NameString.Buffer = pMapName->awcName;
  150. InitPreviousUserString();
  151. RtlCopyUnicodeString(&pMapName->NameString, &PreviousUserString);
  152. return &(pMapName->NameString);
  153. }
  154. void FreeProfileUserName(PUNICODE_STRING pProfileUserName,TL *ptl) {
  155. UNREFERENCED_PARAMETER(ptl);
  156. CheckCritIn();
  157. if (pProfileUserName) {
  158. ThreadUnlockAndFreePool(PtiCurrent(), ptl);
  159. }
  160. }
  161. /*****************************************************************************\
  162. * OpenCacheKeyEx
  163. *
  164. * Attempts to open a cached key for a given section. If we are calling
  165. * for a client thread, we must check the access rights for the key after
  166. * opening it.
  167. *
  168. * Returns fSuccess.
  169. *
  170. * Note -- param 1 can be NULL. If the section name is a per-user registry
  171. * section, we ill use the first parameter if available or set up
  172. * and use the cached one if the first parameter is NULL.
  173. *
  174. * History:
  175. * 03-Dec-1993 SanfordS Created.
  176. \*****************************************************************************/
  177. HANDLE OpenCacheKeyEx(
  178. PUNICODE_STRING pMapName OPTIONAL,
  179. UINT idSection,
  180. ACCESS_MASK amRequest,
  181. PDWORD pdwPolicyFlags
  182. )
  183. {
  184. OBJECT_ATTRIBUTES OA;
  185. WCHAR UnicodeStringBuf[256];
  186. WCHAR pszSessionId[13];
  187. UNICODE_STRING UnicodeString;
  188. LONG Status;
  189. HANDLE hKey = NULL;
  190. PEPROCESS peCurrent = PsGetCurrentProcess();
  191. DWORD dwPolicyFlags;
  192. CheckCritIn();
  193. UserAssert(idSection <= PMAP_LAST);
  194. /*
  195. * If we're opening the desktop or CPL\keyboard key for read access, we should be checking
  196. * for relevant policy.
  197. */
  198. if ((amRequest == KEY_READ) && (idSection == PMAP_DESKTOP)) {
  199. UserAssert(pdwPolicyFlags);
  200. UserAssert(!(*pdwPolicyFlags & ~POLICY_VALID));
  201. dwPolicyFlags = *pdwPolicyFlags;
  202. } else {
  203. /*
  204. * if we are here because Policy was changed and there is not POLICY_ flags set then return.
  205. */
  206. if (pdwPolicyFlags && (*pdwPolicyFlags & POLICY_ONLY)) {
  207. *pdwPolicyFlags = 0;
  208. UserAssert(FALSE);
  209. return NULL;
  210. }
  211. dwPolicyFlags = POLICY_NONE;
  212. }
  213. TryAgain:
  214. UnicodeString.Length = 0;
  215. UnicodeString.MaximumLength = sizeof(UnicodeStringBuf);
  216. UnicodeString.Buffer = UnicodeStringBuf;
  217. if (dwPolicyFlags & POLICY_MACHINE) {
  218. dwPolicyFlags &= ~POLICY_MACHINE;
  219. RtlAppendUnicodeToString(&UnicodeString,
  220. L"\\Registry\\Machine\\");
  221. RtlAppendUnicodeToString(&UnicodeString,
  222. L"Software\\Policies\\Microsoft\\Windows\\");
  223. } else {
  224. if (aFastRegRoot[aFastRegMap[idSection].idRoot][0] == L'M') {
  225. RtlAppendUnicodeToString(&UnicodeString, L"\\Registry\\Machine\\");
  226. } else {
  227. if (!pMapName) {
  228. InitPreviousUserString();
  229. RtlAppendUnicodeStringToString(
  230. &UnicodeString,
  231. &PreviousUserString);
  232. } else {
  233. RtlAppendUnicodeStringToString(
  234. &UnicodeString,
  235. pMapName);
  236. }
  237. }
  238. if (dwPolicyFlags & POLICY_USER) {
  239. dwPolicyFlags &= ~POLICY_USER;
  240. RtlAppendUnicodeToString(&UnicodeString,
  241. L"Software\\Policies\\Microsoft\\Windows\\");
  242. }
  243. else if (dwPolicyFlags & POLICY_REMOTE) {
  244. dwPolicyFlags &= ~POLICY_REMOTE;
  245. RtlAppendUnicodeToString(&UnicodeString,
  246. L"Remote\\");
  247. swprintf(pszSessionId, L"%ld\\", gSessionId);
  248. RtlAppendUnicodeToString(&UnicodeString, pszSessionId);
  249. } else {
  250. /*
  251. * if we are here because Policy was changed then do not try preferences.
  252. */
  253. if (pdwPolicyFlags && (*pdwPolicyFlags & POLICY_ONLY)) {
  254. *pdwPolicyFlags = 0;
  255. return NULL;
  256. }
  257. dwPolicyFlags &= ~POLICY_NONE;
  258. }
  259. }
  260. RtlAppendUnicodeToString(&UnicodeString,
  261. (PWSTR)&aFastRegRoot[aFastRegMap[idSection].idRoot][1]);
  262. RtlAppendUnicodeToString(&UnicodeString,
  263. (PWSTR)aFastRegMap[idSection].szSection);
  264. /*
  265. * Open the key for kernel mode access
  266. */
  267. InitializeObjectAttributes(&OA,
  268. &UnicodeString,
  269. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  270. NULL,
  271. NULL);
  272. Status = ZwOpenKey(&hKey, amRequest, &OA);
  273. if (
  274. (amRequest == KEY_READ) || /*
  275. * We must be able to read
  276. * our registry settings.
  277. */
  278. (peCurrent == gpepCSRSS) ||
  279. (peCurrent == gpepInit)
  280. ) {
  281. } else {
  282. /*
  283. * Now check if the user has access to the key
  284. */
  285. if (NT_SUCCESS(Status)) {
  286. PVOID pKey;
  287. NTSTATUS Status2;
  288. Status2 = ObReferenceObjectByHandle(hKey,
  289. amRequest,
  290. NULL,
  291. KernelMode,
  292. &pKey,
  293. NULL);
  294. if (NT_SUCCESS(Status2)) {
  295. if (!AccessCheckObject(pKey, amRequest, UserMode, &KeyMapping)) {
  296. ZwClose(hKey);
  297. Status = STATUS_ACCESS_DENIED;
  298. }
  299. ObDereferenceObject(pKey);
  300. } else {
  301. ZwClose(hKey);
  302. Status = STATUS_ACCESS_DENIED;
  303. }
  304. }
  305. }
  306. #if DBG
  307. if (!NT_SUCCESS(Status)) {
  308. UnicodeStringBuf[UnicodeString.Length / 2] = 0;
  309. if (PsGetCurrentProcessId() != gpidLogon) {
  310. if (Status != STATUS_OBJECT_NAME_NOT_FOUND) {
  311. RIPMSG1(RIP_WARNING | RIP_THERESMORE, "OpenCacheKeyEx failed with Status = %lx key:", Status);
  312. RIPMSG1(RIP_WARNING | RIP_THERESMORE | RIP_NONAME | RIP_NONEWLINE, " %ws\\", UnicodeStringBuf);
  313. }
  314. }
  315. }
  316. #endif
  317. /*
  318. * If we didn't succeed and we're not down to bottom of policy chain, try again.
  319. */
  320. if (!NT_SUCCESS(Status) && dwPolicyFlags) {
  321. goto TryAgain;
  322. }
  323. /*
  324. * Update policy level
  325. */
  326. if (pdwPolicyFlags) {
  327. *pdwPolicyFlags = dwPolicyFlags;
  328. }
  329. return (NT_SUCCESS(Status) ? hKey : NULL);
  330. }
  331. /*****************************************************************************\
  332. * CheckDesktopPolicy
  333. *
  334. * Check if a desktop value has an associated policy.
  335. *
  336. * Returns TRUE if there is a policy, FALSE otherwise.
  337. *
  338. * History:
  339. * 07-Feb-2000 JerrySh Created.
  340. \*****************************************************************************/
  341. BOOL CheckDesktopPolicy(
  342. PUNICODE_STRING pProfileUserName OPTIONAL,
  343. PCWSTR lpKeyName
  344. )
  345. {
  346. WCHAR szKey[80];
  347. HANDLE hKey;
  348. DWORD cbSize;
  349. NTSTATUS Status;
  350. UNICODE_STRING UnicodeString;
  351. KEY_VALUE_BASIC_INFORMATION KeyInfo;
  352. DWORD dwPolicyFlags = gdwPolicyFlags & (POLICY_MACHINE | POLICY_USER);
  353. /*
  354. * If there is no policy or the caller is winlogon, let it go.
  355. */
  356. if (!dwPolicyFlags || PsGetCurrentProcessId() == gpidLogon) {
  357. return FALSE;
  358. }
  359. /*
  360. * Convert the ID to a string if we need to.
  361. */
  362. if (!IS_PTR(lpKeyName)) {
  363. ServerLoadString(hModuleWin, PTR_TO_ID(lpKeyName), szKey, ARRAY_SIZE(szKey));
  364. lpKeyName = szKey;
  365. }
  366. TryAgain:
  367. /*
  368. * Try to open a key.
  369. */
  370. if ((hKey = OpenCacheKeyEx(pProfileUserName,
  371. PMAP_DESKTOP,
  372. KEY_READ,
  373. &dwPolicyFlags)) == NULL) {
  374. return FALSE;
  375. }
  376. /*
  377. * See if the value exists.
  378. */
  379. RtlInitUnicodeString(&UnicodeString, lpKeyName);
  380. Status = ZwQueryValueKey(hKey,
  381. &UnicodeString,
  382. KeyValueBasicInformation,
  383. &KeyInfo,
  384. sizeof(KeyInfo),
  385. &cbSize);
  386. ZwClose(hKey);
  387. if (!NT_ERROR(Status)) {
  388. return TRUE;
  389. } else if (dwPolicyFlags) {
  390. goto TryAgain;
  391. } else {
  392. return FALSE;
  393. }
  394. }
  395. /*****************************************************************************\
  396. * CheckDesktopPolicyChange
  397. *
  398. * Check if policy has changed since last time we checked.
  399. *
  400. * Returns TRUE if policy changed, FASLE otherwise.
  401. *
  402. * History:
  403. * 07-Feb-2000 JerrySh Created.
  404. \*****************************************************************************/
  405. BOOL CheckDesktopPolicyChange(
  406. PUNICODE_STRING pProfileUserName OPTIONAL
  407. )
  408. {
  409. static LARGE_INTEGER LastMachineWriteTime;
  410. static LARGE_INTEGER LastUserWriteTime;
  411. KEY_BASIC_INFORMATION KeyInfo;
  412. BOOL bPolicyChanged = FALSE;
  413. HANDLE hKey;
  414. DWORD cbSize;
  415. DWORD dwPolicyFlags;
  416. /*
  417. * Check if machine policy has changed since last time we checked.
  418. */
  419. dwPolicyFlags = POLICY_MACHINE;
  420. KeyInfo.LastWriteTime.QuadPart = 0;
  421. hKey = OpenCacheKeyEx(pProfileUserName,
  422. PMAP_DESKTOP,
  423. KEY_READ,
  424. &dwPolicyFlags);
  425. if (hKey) {
  426. if (hKey) {
  427. ZwQueryKey(hKey,
  428. KeyValueBasicInformation,
  429. &KeyInfo,
  430. sizeof(KeyInfo),
  431. &cbSize);
  432. ZwClose(hKey);
  433. }
  434. gdwPolicyFlags |= POLICY_MACHINE;
  435. } else {
  436. gdwPolicyFlags &= ~POLICY_MACHINE;
  437. }
  438. if (LastMachineWriteTime.QuadPart != KeyInfo.LastWriteTime.QuadPart) {
  439. LastMachineWriteTime.QuadPart = KeyInfo.LastWriteTime.QuadPart;
  440. bPolicyChanged = TRUE;
  441. }
  442. /*
  443. * Check if user policy has changed since last time we checked.
  444. */
  445. dwPolicyFlags = POLICY_USER;
  446. KeyInfo.LastWriteTime.QuadPart = 0;
  447. hKey = OpenCacheKeyEx(pProfileUserName,
  448. PMAP_DESKTOP,
  449. KEY_READ,
  450. &dwPolicyFlags);
  451. if (hKey) {
  452. ZwQueryKey(hKey,
  453. KeyValueBasicInformation,
  454. &KeyInfo,
  455. sizeof(KeyInfo),
  456. &cbSize);
  457. ZwClose(hKey);
  458. gdwPolicyFlags |= POLICY_USER;
  459. } else {
  460. gdwPolicyFlags &= ~POLICY_USER;
  461. }
  462. if (LastUserWriteTime.QuadPart != KeyInfo.LastWriteTime.QuadPart) {
  463. LastUserWriteTime.QuadPart = KeyInfo.LastWriteTime.QuadPart;
  464. bPolicyChanged = TRUE;
  465. }
  466. return bPolicyChanged;
  467. }
  468. /*****************************************************************************\
  469. * FastGetProfileDwordW
  470. *
  471. * Reads a REG_DWORD type key from the registry.
  472. *
  473. * returns value read or default value on failure.
  474. *
  475. * History:
  476. * 02-Dec-1993 SanfordS Created.
  477. \*****************************************************************************/
  478. BOOL FastGetProfileDwordW(PUNICODE_STRING pProfileUserName OPTIONAL,
  479. UINT idSection,
  480. LPCWSTR lpKeyName,
  481. DWORD dwDefault,
  482. PDWORD pdwReturn,
  483. DWORD dwPolicyOnly
  484. )
  485. {
  486. HANDLE hKey;
  487. DWORD cbSize;
  488. DWORD dwRet;
  489. LONG Status;
  490. UNICODE_STRING UnicodeString;
  491. BYTE Buf[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(DWORD)];
  492. DWORD dwPolicyFlags = gdwPolicyFlags | dwPolicyOnly;
  493. UserAssert(idSection <= PMAP_LAST);
  494. TryAgain:
  495. if ((hKey = OpenCacheKeyEx(pProfileUserName,
  496. idSection,
  497. KEY_READ,
  498. &dwPolicyFlags)) == NULL) {
  499. RIPMSG1(RIP_WARNING | RIP_NONAME, "%ws", lpKeyName);
  500. if (dwPolicyOnly & POLICY_ONLY) {
  501. return FALSE;
  502. }
  503. if (pdwReturn) {
  504. *pdwReturn = dwDefault;
  505. }
  506. return TRUE;
  507. }
  508. RtlInitUnicodeString(&UnicodeString, lpKeyName);
  509. Status = ZwQueryValueKey(hKey,
  510. &UnicodeString,
  511. KeyValuePartialInformation,
  512. (PKEY_VALUE_PARTIAL_INFORMATION)Buf,
  513. sizeof(Buf),
  514. &cbSize);
  515. dwRet = dwDefault;
  516. if (NT_SUCCESS(Status)) {
  517. dwRet = *((PDWORD)((PKEY_VALUE_PARTIAL_INFORMATION)Buf)->Data);
  518. } else if (dwPolicyFlags) {
  519. ZwClose(hKey);
  520. goto TryAgain;
  521. } else if (Status != STATUS_OBJECT_NAME_NOT_FOUND) {
  522. RIPMSG1(RIP_WARNING,
  523. "FastGetProfileDwordW: ObjectName not found: %ws",
  524. lpKeyName);
  525. }
  526. ZwClose(hKey);
  527. if (pdwReturn) {
  528. *pdwReturn = dwRet;
  529. }
  530. return TRUE;
  531. }
  532. /*****************************************************************************\
  533. * FastGetProfileKeysW()
  534. *
  535. * Reads all key names in the given section.
  536. *
  537. * History:
  538. * 15-Dec-1994 JimA Created.
  539. \*****************************************************************************/
  540. DWORD FastGetProfileKeysW(PUNICODE_STRING pProfileUserName OPTIONAL,
  541. UINT idSection,
  542. LPCWSTR lpDefault,
  543. LPWSTR *lpReturnedString
  544. )
  545. {
  546. HANDLE hKey;
  547. DWORD cchSize;
  548. DWORD cchKey;
  549. LONG Status;
  550. WCHAR Buffer[256 + 6];
  551. PKEY_VALUE_BASIC_INFORMATION pKeyInfo;
  552. ULONG iValue;
  553. LPWSTR lpTmp;
  554. LPWSTR lpKeys = NULL;
  555. DWORD dwPoolSize;
  556. UserAssert(idSection <= PMAP_LAST);
  557. if ((hKey = OpenCacheKeyEx(pProfileUserName,
  558. idSection,
  559. KEY_READ,
  560. NULL)) == NULL) {
  561. RIPMSG0(RIP_WARNING | RIP_NONAME, "");
  562. goto DefExit;
  563. }
  564. pKeyInfo = (PKEY_VALUE_BASIC_INFORMATION)Buffer;
  565. cchSize = 0;
  566. *lpReturnedString = NULL;
  567. iValue = 0;
  568. while (TRUE) {
  569. #if DBG
  570. wcscpy(Buffer + 256, L"DON'T");
  571. #endif
  572. Status = ZwEnumerateValueKey(hKey,
  573. iValue,
  574. KeyValueBasicInformation,
  575. pKeyInfo,
  576. sizeof(Buffer),
  577. &cchKey);
  578. UserAssert(_wcsicmp(Buffer + 256, L"DON'T") == 0);
  579. if (Status == STATUS_NO_MORE_ENTRIES) {
  580. break;
  581. } else if (!NT_SUCCESS(Status)) {
  582. if (lpKeys) {
  583. UserFreePool(lpKeys);
  584. lpKeys = NULL;
  585. }
  586. goto DefExit;
  587. }
  588. UserAssert(pKeyInfo->NameLength * sizeof(WCHAR) <=
  589. sizeof(Buffer) - sizeof(KEY_VALUE_BASIC_INFORMATION));
  590. UserAssert(cchKey <= sizeof(Buffer));
  591. /*
  592. * A key was found. Allocate space for it. Note that
  593. * NameLength is in bytes.
  594. */
  595. cchKey = cchSize;
  596. cchSize += pKeyInfo->NameLength + sizeof(WCHAR);
  597. if (lpKeys == NULL) {
  598. dwPoolSize = cchSize + sizeof(WCHAR);
  599. lpKeys = UserAllocPoolWithQuota(dwPoolSize, TAG_PROFILE);
  600. } else {
  601. lpTmp = lpKeys;
  602. lpKeys = UserReAllocPoolWithQuota(lpTmp,
  603. dwPoolSize,
  604. cchSize + sizeof(WCHAR),
  605. TAG_PROFILE);
  606. /*
  607. * Free the original buffer if the allocation fails
  608. */
  609. if (lpKeys == NULL) {
  610. UserFreePool(lpTmp);
  611. }
  612. dwPoolSize = cchSize + sizeof(WCHAR);
  613. }
  614. /*
  615. * Check for out of memory.
  616. */
  617. if (lpKeys == NULL)
  618. goto DefExit;
  619. /*
  620. * NULL terminate the string and append it to
  621. * the key list.
  622. */
  623. UserAssert(pKeyInfo->NameLength < sizeof(Buffer) - sizeof(KEY_VALUE_BASIC_INFORMATION));
  624. RtlCopyMemory(&lpKeys[cchKey / sizeof(WCHAR)], pKeyInfo->Name, pKeyInfo->NameLength);
  625. lpKeys[(cchKey + pKeyInfo->NameLength) / sizeof(WCHAR)] = 0;
  626. iValue++;
  627. }
  628. /*
  629. * If no keys were found, return the default.
  630. */
  631. if (iValue == 0) {
  632. DefExit:
  633. cchSize = wcslen(lpDefault)+1;
  634. lpKeys = UserAllocPoolWithQuota((cchSize+1) * sizeof(WCHAR), TAG_PROFILE);
  635. if (lpKeys)
  636. wcscpy(lpKeys, lpDefault);
  637. else
  638. cchSize = 0;
  639. } else {
  640. /*
  641. * Turn the byte count into a char count.
  642. */
  643. cchSize /= sizeof(WCHAR);
  644. }
  645. /*
  646. * Make sure hKey is closed.
  647. */
  648. if (hKey)
  649. ZwClose(hKey);
  650. /*
  651. * Append the ending NULL.
  652. */
  653. if (lpKeys)
  654. lpKeys[cchSize] = 0;
  655. *lpReturnedString = lpKeys;
  656. return cchSize;
  657. }
  658. /*****************************************************************************\
  659. * FastGetProfileStringW()
  660. *
  661. * Implements a fast version of the standard API using predefined registry
  662. * section indecies (PMAP_) that reference lazy-opened, cached registry
  663. * handles. FastCloseProfileUserMapping() should be called to clean up
  664. * cached entries when fast profile calls are completed.
  665. *
  666. * This api does NOT implement the NULL lpKeyName feature of the real API.
  667. *
  668. * History:
  669. * 02-Dec-1993 SanfordS Created.
  670. \*****************************************************************************/
  671. DWORD FastGetProfileStringW(PUNICODE_STRING pProfileUserName OPTIONAL,
  672. UINT idSection,
  673. LPCWSTR lpKeyName,
  674. LPCWSTR lpDefault,
  675. LPWSTR lpReturnedString,
  676. DWORD cchBuf,
  677. DWORD dwPolicyOnly
  678. )
  679. {
  680. HANDLE hKey = NULL;
  681. DWORD cbSize;
  682. LONG Status;
  683. UNICODE_STRING UnicodeString;
  684. PKEY_VALUE_PARTIAL_INFORMATION pKeyInfo;
  685. DWORD dwPolicyFlags = gdwPolicyFlags | dwPolicyOnly;
  686. UserAssert(idSection <= PMAP_LAST);
  687. UserAssert(lpKeyName != NULL);
  688. TryAgain:
  689. if ((hKey = OpenCacheKeyEx(pProfileUserName,
  690. idSection,
  691. KEY_READ,
  692. &dwPolicyFlags)) == NULL) {
  693. #if DBG
  694. if (PsGetCurrentProcessId() != gpidLogon) {
  695. RIPMSG1(RIP_WARNING | RIP_NONAME, "%ws", lpKeyName);
  696. }
  697. #endif
  698. if (dwPolicyOnly & POLICY_ONLY) {
  699. return 0;
  700. }
  701. goto DefExit;
  702. }
  703. cbSize = (cchBuf * sizeof(WCHAR)) +
  704. FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
  705. if ((pKeyInfo = UserAllocPoolWithQuota(cbSize, TAG_PROFILE)) == NULL) {
  706. goto DefExit;
  707. }
  708. RtlInitUnicodeString(&UnicodeString, lpKeyName);
  709. Status = ZwQueryValueKey(hKey,
  710. &UnicodeString,
  711. KeyValuePartialInformation,
  712. pKeyInfo,
  713. cbSize,
  714. &cbSize);
  715. if (Status == STATUS_BUFFER_OVERFLOW) {
  716. RIPMSG0(RIP_WARNING, "FastGetProfileStringW: Buffer overflow");
  717. Status = STATUS_SUCCESS;
  718. }
  719. UserAssert(NT_SUCCESS(Status) || (Status == STATUS_OBJECT_NAME_NOT_FOUND));
  720. if (NT_SUCCESS(Status)) {
  721. if (pKeyInfo->DataLength >= sizeof(WCHAR)) {
  722. ((LPWSTR)(pKeyInfo->Data))[cchBuf - 1] = L'\0';
  723. wcscpy(lpReturnedString, (LPWSTR)pKeyInfo->Data);
  724. } else {
  725. /*
  726. * Appears to be a bug with empty strings - only first
  727. * byte is set to NULL. (SAS)
  728. */
  729. lpReturnedString[0] = TEXT('\0');
  730. }
  731. cchBuf = pKeyInfo->DataLength;
  732. UserFreePool(pKeyInfo);
  733. ZwClose(hKey);
  734. /*
  735. * data length includes terminating zero [bodind]
  736. */
  737. return (cchBuf / sizeof(WCHAR));
  738. } else if (dwPolicyFlags) {
  739. UserFreePool(pKeyInfo);
  740. ZwClose(hKey);
  741. goto TryAgain;
  742. }
  743. UserFreePool(pKeyInfo);
  744. DefExit:
  745. /*
  746. * Make sure the key is closed.
  747. */
  748. if (hKey)
  749. ZwClose(hKey);
  750. /*
  751. * wcscopy copies terminating zero, but the length returned by
  752. * wcslen does not, so add 1 to be consistent with success
  753. * return [bodind]
  754. */
  755. if (lpDefault != NULL) {
  756. cchBuf = wcslen(lpDefault) + 1;
  757. RtlCopyMemory(lpReturnedString, lpDefault, cchBuf * sizeof(WCHAR));
  758. return cchBuf;
  759. }
  760. return 0;
  761. }
  762. /*****************************************************************************\
  763. * FastGetProfileIntW()
  764. *
  765. * Implements a fast version of the standard API using predefined registry
  766. * section indecies (PMAP_) that reference lazy-opened, cached registry
  767. * handles. FastCloseProfileUserMapping() should be called to clean up
  768. * cached entries when fast profile calls are completed.
  769. *
  770. * History:
  771. * 02-Dec-1993 SanfordS Created.
  772. \*****************************************************************************/
  773. BOOL FastGetProfileIntW(PUNICODE_STRING pProfileUserName OPTIONAL,
  774. UINT idSection,
  775. LPCWSTR lpKeyName,
  776. UINT nDefault,
  777. PUINT puiReturn,
  778. DWORD dwPolicyOnly
  779. )
  780. {
  781. WCHAR ValueBuf[40];
  782. UNICODE_STRING Value;
  783. UINT ReturnValue;
  784. UserAssert(idSection <= PMAP_LAST);
  785. UserAssert(puiReturn);
  786. if (!FastGetProfileStringW(pProfileUserName,
  787. idSection,
  788. lpKeyName,
  789. NULL,
  790. ValueBuf,
  791. sizeof(ValueBuf) / sizeof(WCHAR),
  792. dwPolicyOnly
  793. )) {
  794. if (dwPolicyOnly & POLICY_ONLY) {
  795. return FALSE;
  796. }
  797. *puiReturn = nDefault;
  798. return TRUE;
  799. }
  800. /*
  801. * Convert string to int.
  802. */
  803. RtlInitUnicodeString(&Value, ValueBuf);
  804. RtlUnicodeStringToInteger(&Value, 10, &ReturnValue);
  805. *puiReturn = ReturnValue;
  806. return TRUE;
  807. }
  808. /*****************************************************************************\
  809. * FastWriteProfileStringW
  810. *
  811. * Implements a fast version of the standard API using predefined registry
  812. * section indecies (PMAP_) that reference lazy-opened, cached registry
  813. * handles. FastCloseProfileUserMapping() should be called to clean up
  814. * cached entries when fast profile calls are completed.
  815. *
  816. * History:
  817. * 02-Dec-1993 SanfordS Created.
  818. \*****************************************************************************/
  819. BOOL FastWriteProfileStringW(PUNICODE_STRING pProfileUserName OPTIONAL,
  820. UINT idSection,
  821. LPCWSTR lpKeyName,
  822. LPCWSTR lpString
  823. )
  824. {
  825. HANDLE hKey;
  826. LONG Status;
  827. UNICODE_STRING UnicodeString;
  828. UserAssert(idSection <= PMAP_LAST);
  829. /*
  830. * We shouldn't be writing values that are controlled by policy.
  831. */
  832. if (idSection == PMAP_DESKTOP) {
  833. UserAssert(!CheckDesktopPolicy(pProfileUserName, lpKeyName));
  834. }
  835. if ((hKey = OpenCacheKeyEx(pProfileUserName,
  836. idSection,
  837. KEY_WRITE,
  838. NULL)) == NULL) {
  839. RIPMSG1(RIP_WARNING | RIP_NONAME, "%ws", lpKeyName);
  840. return FALSE;
  841. }
  842. RtlInitUnicodeString(&UnicodeString, lpKeyName);
  843. Status = ZwSetValueKey(hKey,
  844. &UnicodeString,
  845. 0,
  846. REG_SZ,
  847. (PVOID)lpString,
  848. (wcslen(lpString) + 1) * sizeof(WCHAR));
  849. ZwClose(hKey);
  850. return (NT_SUCCESS(Status));
  851. }
  852. /*****************************************************************************\
  853. * FastGetProfileIntFromID
  854. *
  855. * Just like FastGetProfileIntW except it reads the USER string table for the
  856. * key name.
  857. *
  858. * History:
  859. * 02-Dec-1993 SanfordS Created.
  860. * 25-Feb-1995 BradG Added TWIPS -> Pixel conversion.
  861. \*****************************************************************************/
  862. BOOL FastGetProfileIntFromID(PUNICODE_STRING pProfileUserName OPTIONAL,
  863. UINT idSection,
  864. UINT idKey,
  865. int def,
  866. PINT pResult,
  867. DWORD dwPolicyOnly
  868. )
  869. {
  870. int result;
  871. WCHAR szKey[80];
  872. UserAssert(idSection <= PMAP_LAST);
  873. ServerLoadString(hModuleWin, idKey, szKey, ARRAY_SIZE(szKey));
  874. if (FastGetProfileIntW(pProfileUserName,idSection, szKey, def, &result, dwPolicyOnly))
  875. {
  876. /*
  877. * If you change the below list of STR_* make sure you make a
  878. * corresponding change in SetWindowMetricInt (rare.c)
  879. */
  880. switch (idKey) {
  881. case STR_BORDERWIDTH:
  882. case STR_SCROLLWIDTH:
  883. case STR_SCROLLHEIGHT:
  884. case STR_CAPTIONWIDTH:
  885. case STR_CAPTIONHEIGHT:
  886. case STR_SMCAPTIONWIDTH:
  887. case STR_SMCAPTIONHEIGHT:
  888. case STR_MENUWIDTH:
  889. case STR_MENUHEIGHT:
  890. case STR_ICONHORZSPACING:
  891. case STR_ICONVERTSPACING:
  892. case STR_MINWIDTH:
  893. case STR_MINHORZGAP:
  894. case STR_MINVERTGAP:
  895. /*
  896. * Convert any registry values stored in TWIPS back to pixels
  897. */
  898. if (result < 0)
  899. result = MultDiv(-result, gpsi->dmLogPixels, 72 * 20);
  900. break;
  901. }
  902. if (pResult) {
  903. *pResult = result;
  904. }
  905. return TRUE;
  906. }
  907. return FALSE;
  908. }
  909. /*****************************************************************************\
  910. * FastGetProfileIntFromID
  911. *
  912. * Just like FastGetProfileStringW except it reads the USER string table for
  913. * the key name.
  914. *
  915. * History:
  916. * 02-Dec-1993 SanfordS Created.
  917. \*****************************************************************************/
  918. DWORD FastGetProfileStringFromIDW(PUNICODE_STRING pProfileUserName OPTIONAL,
  919. UINT idSection,
  920. UINT idKey,
  921. LPCWSTR lpDefault,
  922. LPWSTR lpReturnedString,
  923. DWORD cch,
  924. DWORD dwPolicyOnly
  925. )
  926. {
  927. WCHAR szKey[80];
  928. UserAssert(idSection <= PMAP_LAST);
  929. ServerLoadString(hModuleWin, idKey, szKey, ARRAY_SIZE(szKey));
  930. return FastGetProfileStringW(pProfileUserName,
  931. idSection,
  932. szKey,
  933. lpDefault,
  934. lpReturnedString,
  935. cch,
  936. dwPolicyOnly);
  937. }
  938. /*****************************************************************************\
  939. * FastWriteProfileValue
  940. *
  941. * History:
  942. * 06/10/96 GerardoB Renamed and added uType parameter
  943. \*****************************************************************************/
  944. BOOL FastWriteProfileValue(PUNICODE_STRING pProfileUserName OPTIONAL,
  945. UINT idSection,
  946. LPCWSTR lpKeyName,
  947. UINT uType,
  948. LPBYTE lpStruct,
  949. UINT cbSizeStruct
  950. )
  951. {
  952. HANDLE hKey;
  953. LONG Status;
  954. UNICODE_STRING UnicodeString;
  955. WCHAR szKey[SERVERSTRINGMAXSIZE];
  956. UserAssert(idSection <= PMAP_LAST);
  957. if (!IS_PTR(lpKeyName)) {
  958. *szKey = (WCHAR)0;
  959. ServerLoadString(hModuleWin, PTR_TO_ID(lpKeyName), szKey, ARRAY_SIZE(szKey));
  960. UserAssert(*szKey != (WCHAR)0);
  961. lpKeyName = szKey;
  962. }
  963. /*
  964. * We shouldn't be writing values that are controlled by policy.
  965. */
  966. if (idSection == PMAP_DESKTOP) {
  967. UserAssert(!CheckDesktopPolicy(pProfileUserName, lpKeyName));
  968. }
  969. if ((hKey = OpenCacheKeyEx(pProfileUserName,
  970. idSection,
  971. KEY_WRITE,
  972. NULL)) == NULL) {
  973. RIPMSG1(RIP_WARNING, "FastWriteProfileValue: Failed to open cache-key (%ws)", lpKeyName);
  974. return FALSE;
  975. }
  976. RtlInitUnicodeString(&UnicodeString, lpKeyName);
  977. Status = ZwSetValueKey(hKey,
  978. &UnicodeString,
  979. 0,
  980. uType,
  981. lpStruct,
  982. cbSizeStruct);
  983. ZwClose(hKey);
  984. #if DBG
  985. if (!NT_SUCCESS(Status)) {
  986. RIPMSG3 (RIP_WARNING, "FastWriteProfileValue: ZwSetValueKey Failed. Status:%#lx idSection:%#lx KeyName:%s",
  987. Status, idSection, UnicodeString.Buffer);
  988. }
  989. #endif
  990. return (NT_SUCCESS(Status));
  991. }
  992. /*****************************************************************************\
  993. * FastGetProfileValue
  994. *
  995. * If cbSizeReturn is 0, just return the size of the data
  996. *
  997. * History:
  998. * 06/10/96 GerardoB Renamed
  999. \*****************************************************************************/
  1000. DWORD FastGetProfileValue(PUNICODE_STRING pProfileUserName OPTIONAL,
  1001. UINT idSection,
  1002. LPCWSTR lpKeyName,
  1003. LPBYTE lpDefault,
  1004. LPBYTE lpReturn,
  1005. UINT cbSizeReturn,
  1006. DWORD dwPolicyOnly
  1007. )
  1008. {
  1009. HANDLE hKey;
  1010. UINT cbSize;
  1011. LONG Status;
  1012. UNICODE_STRING UnicodeString;
  1013. PKEY_VALUE_PARTIAL_INFORMATION pKeyInfo;
  1014. WCHAR szKey[SERVERSTRINGMAXSIZE];
  1015. KEY_VALUE_PARTIAL_INFORMATION KeyInfo;
  1016. DWORD dwPolicyFlags = gdwPolicyFlags | dwPolicyOnly;
  1017. UserAssert(idSection <= PMAP_LAST);
  1018. if (!IS_PTR(lpKeyName)) {
  1019. *szKey = (WCHAR)0;
  1020. ServerLoadString(hModuleWin, PTR_TO_ID(lpKeyName), szKey, ARRAY_SIZE(szKey));
  1021. UserAssert(*szKey != (WCHAR)0);
  1022. lpKeyName = szKey;
  1023. }
  1024. TryAgain:
  1025. if ((hKey = OpenCacheKeyEx(pProfileUserName,
  1026. idSection,
  1027. KEY_READ,
  1028. &dwPolicyFlags)) == NULL) {
  1029. // if hi-word of lpKeName is 0, it is a resource number not a string
  1030. if (!IS_PTR(lpKeyName))
  1031. RIPMSG1(RIP_WARNING, "FastGetProfileValue: Failed to open cache-key (%08x)", lpKeyName);
  1032. else
  1033. RIPMSG1(RIP_WARNING | RIP_NONAME, "%ws", lpKeyName);
  1034. if (dwPolicyOnly & POLICY_ONLY) {
  1035. return 0;
  1036. }
  1037. goto DefExit;
  1038. }
  1039. if (cbSizeReturn == 0) {
  1040. cbSize = sizeof(KeyInfo);
  1041. pKeyInfo = &KeyInfo;
  1042. } else {
  1043. cbSize = cbSizeReturn + FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
  1044. if ((pKeyInfo = UserAllocPoolWithQuota(cbSize, TAG_PROFILE)) == NULL) {
  1045. goto DefExit;
  1046. }
  1047. }
  1048. RtlInitUnicodeString(&UnicodeString, lpKeyName);
  1049. Status = ZwQueryValueKey(hKey,
  1050. &UnicodeString,
  1051. KeyValuePartialInformation,
  1052. pKeyInfo,
  1053. cbSize,
  1054. &cbSize);
  1055. if (NT_SUCCESS(Status)) {
  1056. UserAssert(cbSizeReturn >= pKeyInfo->DataLength);
  1057. cbSize = pKeyInfo->DataLength;
  1058. RtlCopyMemory(lpReturn, pKeyInfo->Data, cbSize);
  1059. if (cbSizeReturn != 0) {
  1060. UserFreePool(pKeyInfo);
  1061. }
  1062. ZwClose(hKey);
  1063. return cbSize;
  1064. } else if ((Status == STATUS_BUFFER_OVERFLOW) && (cbSizeReturn == 0)) {
  1065. ZwClose(hKey);
  1066. return pKeyInfo->DataLength;
  1067. } else if (dwPolicyFlags) {
  1068. if (cbSizeReturn != 0) {
  1069. UserFreePool(pKeyInfo);
  1070. }
  1071. ZwClose(hKey);
  1072. goto TryAgain;
  1073. }
  1074. #if DBG
  1075. if (Status != STATUS_OBJECT_NAME_NOT_FOUND) {
  1076. RIPMSG3 (RIP_WARNING, "FastGetProfileValue: ZwQueryValueKey Failed. Status:%#lx idSection:%#lx KeyName:%s",
  1077. Status, idSection, UnicodeString.Buffer);
  1078. }
  1079. #endif
  1080. if (cbSizeReturn != 0) {
  1081. UserFreePool(pKeyInfo);
  1082. }
  1083. DefExit:
  1084. if (hKey)
  1085. ZwClose(hKey);
  1086. if (lpDefault) {
  1087. RtlMoveMemory(lpReturn, lpDefault, cbSizeReturn);
  1088. return cbSizeReturn;
  1089. }
  1090. return 0;
  1091. }
  1092. /*****************************************************************************\
  1093. * UT_FastGetProfileIntsW
  1094. *
  1095. * Repeatedly calls FastGetProfileIntW on the given table.
  1096. *
  1097. * History:
  1098. * 02-Dec-1993 SanfordS Created.
  1099. \*****************************************************************************/
  1100. BOOL FastGetProfileIntsW(PUNICODE_STRING pProfileUserName OPTIONAL,
  1101. PPROFINTINFO ppii,
  1102. DWORD dwPolicyOnly
  1103. )
  1104. {
  1105. WCHAR szKey[40];
  1106. while (ppii->idSection != 0) {
  1107. ServerLoadString(hModuleWin,
  1108. PTR_TO_ID(ppii->lpKeyName),
  1109. szKey,
  1110. ARRAY_SIZE(szKey));
  1111. FastGetProfileIntW(pProfileUserName,
  1112. ppii->idSection,
  1113. szKey,
  1114. ppii->nDefault,
  1115. ppii->puResult,
  1116. dwPolicyOnly);
  1117. ppii++;
  1118. }
  1119. return TRUE;
  1120. }
  1121. /***************************************************************************\
  1122. * UpdateWinIni
  1123. *
  1124. * Handles impersonation stuff and writes the given value to the registry.
  1125. *
  1126. * History:
  1127. * 28-Jun-1991 MikeHar Ported.
  1128. * 03-Dec-1993 SanfordS Used FastProfile calls, moved to profile.c
  1129. \***************************************************************************/
  1130. BOOL FastUpdateWinIni(PUNICODE_STRING pProfileUserName OPTIONAL,
  1131. UINT idSection,
  1132. UINT wKeyNameId,
  1133. LPWSTR lpszValue
  1134. )
  1135. {
  1136. WCHAR szKeyName[40];
  1137. BOOL bResult = FALSE;
  1138. UserAssert(idSection <= PMAP_LAST);
  1139. ServerLoadString(hModuleWin,
  1140. wKeyNameId,
  1141. szKeyName,
  1142. ARRAY_SIZE(szKeyName));
  1143. bResult = FastWriteProfileStringW(pProfileUserName,
  1144. idSection, szKeyName, lpszValue);
  1145. return bResult;
  1146. }