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.

867 lines
26 KiB

  1. /*++
  2. Copyright (c) 1991-2000, Microsoft Corporation All rights reserved.
  3. Module Name:
  4. security.c
  5. Abstract:
  6. This file handles the management of the NLS per-thread and process cache.
  7. The cache is only established when hitting an API that needs it. The process
  8. NLS cache is used when accessing NLS info for a process NOT running in the
  9. context of the interactive logged on user. The per-thread NLS cache is used
  10. when accssing NLS info and the thread is doing a user impersonation.
  11. External Routines found in this file:
  12. NlsFlushProcessCache
  13. NlsGetCurrentUserNlsInfo
  14. NlsIsInteractiveUserProcess
  15. NlsCheckForInteractiveUser
  16. NlsGetUserLocale
  17. Revision History:
  18. 03-29-1999 SamerA Created.
  19. --*/
  20. //
  21. // Include Files.
  22. //
  23. #include "nls.h"
  24. #include "nlssafe.h"
  25. //
  26. // Global Variables.
  27. //
  28. //
  29. // Process Nls Cache.
  30. //
  31. PNLS_LOCAL_CACHE gpNlsProcessCache;
  32. //
  33. // Whether the current running process is the same as the
  34. // interactive logged on user.
  35. //
  36. BOOL gInteractiveLogonUserProcess = (BOOL)-1;
  37. //
  38. // Forward Declarations.
  39. //
  40. NTSTATUS FASTCALL
  41. NlsGetCacheBuffer(
  42. PNLS_USER_INFO pNlsUserInfo,
  43. LCTYPE LCType,
  44. PWSTR *ppCache);
  45. void FASTCALL
  46. NlsInvalidateCache(
  47. PNLS_USER_INFO pNlsUserInfo);
  48. //-------------------------------------------------------------------------//
  49. // EXTERNAL ROUTINES //
  50. //-------------------------------------------------------------------------//
  51. ////////////////////////////////////////////////////////////////////////////
  52. //
  53. // NlsFlushProcessCache
  54. //
  55. // Invalidates an entry in the NLS process cache.
  56. //
  57. // 05-22-99 SamerA Created.
  58. ////////////////////////////////////////////////////////////////////////////
  59. NTSTATUS NlsFlushProcessCache(
  60. LCTYPE LCType)
  61. {
  62. PWSTR pOutputCache;
  63. NTSTATUS NtStatus = STATUS_SUCCESS;
  64. //
  65. // If there is no thread impersonation, then flush the
  66. // process entry cache.
  67. //
  68. if (NtCurrentTeb()->IsImpersonating != 0)
  69. {
  70. return (NtStatus);
  71. }
  72. if (gpNlsProcessCache)
  73. {
  74. NtStatus = NlsGetCacheBuffer( &gpNlsProcessCache->NlsInfo,
  75. LCType,
  76. &pOutputCache );
  77. if (NT_SUCCESS(NtStatus))
  78. {
  79. RtlEnterCriticalSection(&gcsNlsProcessCache);
  80. pOutputCache[0] = NLS_INVALID_INFO_CHAR;
  81. RtlLeaveCriticalSection(&gcsNlsProcessCache);
  82. }
  83. }
  84. return (NtStatus);
  85. }
  86. ////////////////////////////////////////////////////////////////////////////
  87. //
  88. // NlsGetCurrentUserNlsInfo
  89. //
  90. // Retreive the NLS info correponding to the current security context.
  91. //
  92. // 03-29-99 SamerA Created.
  93. ////////////////////////////////////////////////////////////////////////////
  94. NTSTATUS NlsGetCurrentUserNlsInfo(
  95. LCID Locale,
  96. LCTYPE LCType,
  97. PWSTR RegistryValue,
  98. PWSTR pOutputBuffer,
  99. size_t cchOutputBuffer,
  100. BOOL IgnoreLocaleValue)
  101. {
  102. NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;
  103. PNLS_LOCAL_CACHE pNlsThreadCache;
  104. PWSTR pOutputCache;
  105. //
  106. // Possible NtCurrentTeb()->IsImpersonating values :
  107. //
  108. // 0 : Thread isn't impersonating any user.
  109. //
  110. // 1 : Thread has just started to do impersonation.
  111. // Per thread cache needs to be allocated now.
  112. //
  113. // 2 : Thread is calling the NLS apis while its
  114. // a context other than the interactive logged on user.
  115. //
  116. switch (NtCurrentTeb()->IsImpersonating)
  117. {
  118. case ( 0 ) :
  119. {
  120. //
  121. // Thread is NOT impersonating any user. We check if the process
  122. // belongs to the interactive user, then we retreive the info from
  123. // the NLS cache in CSR. Otherwise if the process is running in
  124. // the context of a different user, then we retreive the NLS info
  125. // from the process cache.
  126. //
  127. if (gInteractiveLogonUserProcess == (BOOL)-1)
  128. {
  129. NlsIsInteractiveUserProcess();
  130. }
  131. if (gInteractiveLogonUserProcess == FALSE)
  132. {
  133. if ((IgnoreLocaleValue) ||
  134. (GetUserDefaultLCID() == Locale))
  135. {
  136. if (!gpNlsProcessCache)
  137. {
  138. //
  139. // Allocate and invalidate the NLS process cache.
  140. //
  141. RtlEnterCriticalSection(&gcsNlsProcessCache);
  142. if (!gpNlsProcessCache)
  143. {
  144. gpNlsProcessCache = RtlAllocateHeap(
  145. RtlProcessHeap(),
  146. 0,
  147. sizeof(NLS_LOCAL_CACHE) );
  148. if (gpNlsProcessCache)
  149. {
  150. NlsInvalidateCache(&gpNlsProcessCache->NlsInfo);
  151. gpNlsProcessCache->CurrentUserKeyHandle = NULL;
  152. }
  153. }
  154. RtlLeaveCriticalSection(&gcsNlsProcessCache);
  155. }
  156. if (gpNlsProcessCache)
  157. {
  158. NtStatus = NlsGetCacheBuffer( &gpNlsProcessCache->NlsInfo,
  159. LCType,
  160. &pOutputCache);
  161. if (NT_SUCCESS(NtStatus))
  162. {
  163. //
  164. // See if it is a valid cache.
  165. //
  166. if (pOutputCache[0] == NLS_INVALID_INFO_CHAR)
  167. {
  168. RtlEnterCriticalSection(&gcsNlsProcessCache);
  169. if (GetUserInfoFromRegistry( RegistryValue,
  170. pOutputCache,
  171. MAX_REG_VAL_SIZE, 0 ) == FALSE)
  172. {
  173. NtStatus = STATUS_UNSUCCESSFUL;
  174. pOutputCache[0] = NLS_INVALID_INFO_CHAR;
  175. }
  176. RtlLeaveCriticalSection(&gcsNlsProcessCache);
  177. }
  178. if (NT_SUCCESS(NtStatus))
  179. {
  180. if(FAILED((StringCchCopyW(pOutputBuffer, cchOutputBuffer, pOutputCache))))
  181. {
  182. NtStatus = STATUS_UNSUCCESSFUL;
  183. }
  184. }
  185. }
  186. }
  187. }
  188. }
  189. break;
  190. }
  191. case ( 1 ) :
  192. {
  193. //
  194. // Thread started to do impersonation.
  195. //
  196. pNlsThreadCache = NtCurrentTeb()->NlsCache;
  197. if (!pNlsThreadCache)
  198. {
  199. pNlsThreadCache = RtlAllocateHeap( RtlProcessHeap(),
  200. 0,
  201. sizeof(NLS_LOCAL_CACHE) );
  202. if (pNlsThreadCache)
  203. {
  204. pNlsThreadCache->CurrentUserKeyHandle = NULL;
  205. }
  206. NtCurrentTeb()->NlsCache = (PVOID) pNlsThreadCache;
  207. }
  208. if (pNlsThreadCache)
  209. {
  210. NlsInvalidateCache(&pNlsThreadCache->NlsInfo);
  211. }
  212. NtCurrentTeb()->IsImpersonating = 2;
  213. //
  214. // Fall Thru...
  215. //
  216. }
  217. case ( 2 ) :
  218. {
  219. //
  220. // Thread is impersonating a particular user.
  221. //
  222. pNlsThreadCache = NtCurrentTeb()->NlsCache;
  223. if (pNlsThreadCache)
  224. {
  225. if ((IgnoreLocaleValue) ||
  226. (GetUserDefaultLCID() == Locale))
  227. {
  228. NtStatus = NlsGetCacheBuffer( &pNlsThreadCache->NlsInfo,
  229. LCType,
  230. &pOutputCache );
  231. if (NT_SUCCESS(NtStatus))
  232. {
  233. if (pOutputCache[0] == NLS_INVALID_INFO_CHAR)
  234. {
  235. //
  236. // Don't cache key handles - this will break
  237. // profile unload.
  238. //
  239. OPEN_CPANEL_INTL_KEY( pNlsThreadCache->CurrentUserKeyHandle,
  240. STATUS_UNSUCCESSFUL,
  241. KEY_READ );
  242. NtStatus = NlsQueryCurrentUserInfo( pNlsThreadCache,
  243. RegistryValue,
  244. pOutputCache,
  245. MAX_REG_VAL_SIZE );
  246. CLOSE_REG_KEY(pNlsThreadCache->CurrentUserKeyHandle);
  247. if (!NT_SUCCESS(NtStatus))
  248. {
  249. pOutputCache[0] = NLS_INVALID_INFO_CHAR;
  250. }
  251. }
  252. if (NT_SUCCESS(NtStatus))
  253. {
  254. if(FAILED((StringCchCopyW(pOutputBuffer, cchOutputBuffer, pOutputCache))))
  255. {
  256. NtStatus = STATUS_UNSUCCESSFUL;
  257. }
  258. }
  259. }
  260. }
  261. }
  262. break;
  263. }
  264. }
  265. return (NtStatus);
  266. }
  267. ////////////////////////////////////////////////////////////////////////////
  268. //
  269. // NlsIsInteractiveUserProcess
  270. //
  271. // Read the process's authetication id out of its access token object and
  272. // cache it since it never changes.
  273. //
  274. // 12-27-98 SamerA Created.
  275. ////////////////////////////////////////////////////////////////////////////
  276. NTSTATUS NlsIsInteractiveUserProcess()
  277. {
  278. NTSTATUS NtStatus;
  279. TOKEN_STATISTICS TokenInformation;
  280. HANDLE TokenHandle;
  281. ULONG BytesRequired;
  282. BOOL IsInteractiveProcess = TRUE;
  283. //
  284. // Get the process access token.
  285. //
  286. NtStatus = NtOpenProcessToken( NtCurrentProcess(),
  287. TOKEN_QUERY,
  288. &TokenHandle );
  289. if (NT_SUCCESS(NtStatus))
  290. {
  291. //
  292. // Get the LUID.
  293. //
  294. NtStatus = NtQueryInformationToken( TokenHandle,
  295. TokenStatistics,
  296. &TokenInformation,
  297. sizeof(TokenInformation),
  298. &BytesRequired );
  299. if (NT_SUCCESS(NtStatus))
  300. {
  301. if (RtlEqualLuid( &pNlsUserInfo->InteractiveUserLuid,
  302. &TokenInformation.AuthenticationId ) == FALSE)
  303. {
  304. IsInteractiveProcess = FALSE;
  305. }
  306. }
  307. NtClose(TokenHandle);
  308. }
  309. gInteractiveLogonUserProcess = IsInteractiveProcess;
  310. return (NtStatus);
  311. }
  312. ////////////////////////////////////////////////////////////////////////////
  313. //
  314. // NlsCheckForInteractiveUser
  315. //
  316. // This function makes sure that the current thread isn't impersonating
  317. // anybody, but the interactive. It compares the authentication-id of the
  318. // interactive user -cached in CSRSS at logon time- with the
  319. // authentication-id of the current thread or process. It returns failure
  320. // ONLY if the current security context -session- isn't the same as the
  321. // interactive logged-on user.
  322. //
  323. // 12-16-98 SamerA Created.
  324. ////////////////////////////////////////////////////////////////////////////
  325. NTSTATUS NlsCheckForInteractiveUser()
  326. {
  327. NTSTATUS NtStatus, ReturnStatus = STATUS_SUCCESS;
  328. TOKEN_STATISTICS TokenInformation;
  329. HANDLE TokenHandle;
  330. ULONG BytesRequired;
  331. PLUID InteractiveUserLuid = &pNlsUserInfo->InteractiveUserLuid;
  332. //
  333. // Get the Token Handle.
  334. // Fast optimization to detect if a thread hasn't started to do any
  335. // impersonation, which is the case for most GUI user apps.
  336. //
  337. if (NtCurrentTeb()->IsImpersonating == 0)
  338. {
  339. NtStatus = STATUS_NO_TOKEN;
  340. }
  341. else
  342. {
  343. NtStatus = NtOpenThreadToken( NtCurrentThread(),
  344. TOKEN_QUERY,
  345. FALSE,
  346. &TokenHandle );
  347. }
  348. if (!NT_SUCCESS(NtStatus))
  349. {
  350. if (NtStatus != STATUS_NO_TOKEN)
  351. {
  352. KdPrint(("NLSAPI: Couldn't retreive thread token - %lx.\n", NtStatus));
  353. return (STATUS_SUCCESS);
  354. }
  355. //
  356. // Get the process access token.
  357. //
  358. if (gInteractiveLogonUserProcess == (BOOL)-1)
  359. {
  360. NtStatus = NlsIsInteractiveUserProcess();
  361. if (!NT_SUCCESS(NtStatus))
  362. {
  363. KdPrint(("NLSAPI: Couldn't retreive process token - %lx\n", NtStatus));
  364. return (STATUS_SUCCESS);
  365. }
  366. }
  367. if (gInteractiveLogonUserProcess == FALSE)
  368. {
  369. ReturnStatus = STATUS_UNSUCCESSFUL;
  370. }
  371. }
  372. else
  373. {
  374. //
  375. // Get the AuthenticationId of the current thread's security context.
  376. //
  377. NtStatus = NtQueryInformationToken( TokenHandle,
  378. TokenStatistics,
  379. &TokenInformation,
  380. sizeof(TokenInformation),
  381. &BytesRequired );
  382. //
  383. // Close the thread token here.
  384. //
  385. NtClose(TokenHandle);
  386. if (NT_SUCCESS(NtStatus))
  387. {
  388. if (RtlEqualLuid( InteractiveUserLuid,
  389. &TokenInformation.AuthenticationId ) == FALSE)
  390. {
  391. ReturnStatus = STATUS_UNSUCCESSFUL;
  392. }
  393. }
  394. }
  395. return (ReturnStatus);
  396. }
  397. ////////////////////////////////////////////////////////////////////////////
  398. //
  399. // NlsGetUserLocale
  400. //
  401. // Retreives the user locale from the registry of the current security
  402. // context. It is called ONLY when the running security context is
  403. // different from the interactive logged-on security context-(user).
  404. //
  405. // 12-16-98 SamerA Created.
  406. ////////////////////////////////////////////////////////////////////////////
  407. NTSTATUS NlsGetUserLocale(
  408. LCID *Lcid)
  409. {
  410. NTSTATUS NtStatus;
  411. WCHAR wszLocale[MAX_REG_VAL_SIZE];
  412. UNICODE_STRING ObLocaleString;
  413. PNLS_LOCAL_CACHE pNlsCache = NtCurrentTeb()->NlsCache;
  414. //
  415. // Get the current user locale.
  416. //
  417. NtStatus = NlsGetCurrentUserNlsInfo( LOCALE_USER_DEFAULT,
  418. (LCTYPE)LOCALE_SLOCALE,
  419. L"Locale",
  420. wszLocale,
  421. ARRAYSIZE(wszLocale),
  422. TRUE );
  423. if ((NT_SUCCESS(NtStatus)) ||
  424. (GetUserInfoFromRegistry(L"Locale", wszLocale, ARRAYSIZE(wszLocale), 0)))
  425. {
  426. RtlInitUnicodeString(&ObLocaleString, wszLocale);
  427. NtStatus = RtlUnicodeStringToInteger( &ObLocaleString,
  428. 16,
  429. (PULONG)Lcid);
  430. }
  431. return (NtStatus);
  432. }
  433. //-------------------------------------------------------------------------//
  434. // INTERNAL ROUTINES //
  435. //-------------------------------------------------------------------------//
  436. ////////////////////////////////////////////////////////////////////////////
  437. //
  438. // NlsGetCacheBuffer
  439. //
  440. // Get a buffer pointer inside the cache for this LCTYPE.
  441. //
  442. // 03-29-99 SamerA Created.
  443. ////////////////////////////////////////////////////////////////////////////
  444. NTSTATUS FASTCALL NlsGetCacheBuffer(
  445. PNLS_USER_INFO pNlsUserInfo,
  446. LCTYPE LCType,
  447. PWSTR *ppCache)
  448. {
  449. NTSTATUS NtStatus = STATUS_SUCCESS;
  450. switch (LCType)
  451. {
  452. case ( LOCALE_SLANGUAGE ) :
  453. {
  454. *ppCache = pNlsUserInfo->sAbbrevLangName;
  455. break;
  456. }
  457. case ( LOCALE_ICOUNTRY ) :
  458. {
  459. *ppCache = pNlsUserInfo->iCountry;
  460. break;
  461. }
  462. case ( LOCALE_SCOUNTRY ) :
  463. {
  464. *ppCache = pNlsUserInfo->sCountry;
  465. break;
  466. }
  467. case ( LOCALE_SLIST ) :
  468. {
  469. *ppCache = pNlsUserInfo->sList;
  470. break;
  471. }
  472. case ( LOCALE_IMEASURE ) :
  473. {
  474. *ppCache = pNlsUserInfo->iMeasure;
  475. break;
  476. }
  477. case ( LOCALE_IPAPERSIZE ) :
  478. {
  479. *ppCache = pNlsUserInfo->iPaperSize;
  480. break;
  481. }
  482. case ( LOCALE_SDECIMAL ) :
  483. {
  484. *ppCache = pNlsUserInfo->sDecimal;
  485. break;
  486. }
  487. case ( LOCALE_STHOUSAND ) :
  488. {
  489. *ppCache = pNlsUserInfo->sThousand;
  490. break;
  491. }
  492. case ( LOCALE_SGROUPING ) :
  493. {
  494. *ppCache = pNlsUserInfo->sGrouping;
  495. break;
  496. }
  497. case ( LOCALE_IDIGITS ) :
  498. {
  499. *ppCache = pNlsUserInfo->iDigits;
  500. break;
  501. }
  502. case ( LOCALE_ILZERO ) :
  503. {
  504. *ppCache = pNlsUserInfo->iLZero;
  505. break;
  506. }
  507. case ( LOCALE_INEGNUMBER ) :
  508. {
  509. *ppCache = pNlsUserInfo->iNegNumber;
  510. break;
  511. }
  512. case ( LOCALE_SNATIVEDIGITS ) :
  513. {
  514. *ppCache = pNlsUserInfo->sNativeDigits;
  515. break;
  516. }
  517. case ( LOCALE_IDIGITSUBSTITUTION ) :
  518. {
  519. *ppCache = pNlsUserInfo->iDigitSubstitution;
  520. break;
  521. }
  522. case ( LOCALE_SCURRENCY ) :
  523. {
  524. *ppCache = pNlsUserInfo->sCurrency;
  525. break;
  526. }
  527. case ( LOCALE_SMONDECIMALSEP ) :
  528. {
  529. *ppCache = pNlsUserInfo->sMonDecSep;
  530. break;
  531. }
  532. case ( LOCALE_SMONTHOUSANDSEP ) :
  533. {
  534. *ppCache = pNlsUserInfo->sMonThouSep;
  535. break;
  536. }
  537. case ( LOCALE_SMONGROUPING ) :
  538. {
  539. *ppCache = pNlsUserInfo->sMonGrouping;
  540. break;
  541. }
  542. case ( LOCALE_ICURRDIGITS ) :
  543. {
  544. *ppCache = pNlsUserInfo->iCurrDigits;
  545. break;
  546. }
  547. case ( LOCALE_ICURRENCY ) :
  548. {
  549. *ppCache = pNlsUserInfo->iCurrency;
  550. break;
  551. }
  552. case ( LOCALE_INEGCURR ) :
  553. {
  554. *ppCache = pNlsUserInfo->iNegCurr;
  555. break;
  556. }
  557. case ( LOCALE_SPOSITIVESIGN ) :
  558. {
  559. *ppCache = pNlsUserInfo->sPosSign;
  560. break;
  561. }
  562. case ( LOCALE_SNEGATIVESIGN ) :
  563. {
  564. *ppCache = pNlsUserInfo->sNegSign;
  565. break;
  566. }
  567. case ( LOCALE_STIMEFORMAT ) :
  568. {
  569. *ppCache = pNlsUserInfo->sTimeFormat;
  570. break;
  571. }
  572. case ( LOCALE_STIME ) :
  573. {
  574. *ppCache = pNlsUserInfo->sTime;
  575. break;
  576. }
  577. case ( LOCALE_ITIME ) :
  578. {
  579. *ppCache = pNlsUserInfo->iTime;
  580. break;
  581. }
  582. case ( LOCALE_ITLZERO ) :
  583. {
  584. *ppCache = pNlsUserInfo->iTLZero;
  585. break;
  586. }
  587. case ( LOCALE_ITIMEMARKPOSN ) :
  588. {
  589. *ppCache = pNlsUserInfo->iTimeMarkPosn;
  590. break;
  591. }
  592. case ( LOCALE_S1159 ) :
  593. {
  594. *ppCache = pNlsUserInfo->s1159;
  595. break;
  596. }
  597. case ( LOCALE_S2359 ) :
  598. {
  599. *ppCache = pNlsUserInfo->s2359;
  600. break;
  601. }
  602. case ( LOCALE_SSHORTDATE ) :
  603. {
  604. *ppCache = pNlsUserInfo->sShortDate;
  605. break;
  606. }
  607. case ( LOCALE_SDATE ) :
  608. {
  609. *ppCache = pNlsUserInfo->sDate;
  610. break;
  611. }
  612. case ( LOCALE_IDATE ) :
  613. {
  614. *ppCache = pNlsUserInfo->iDate;
  615. break;
  616. }
  617. case ( LOCALE_SYEARMONTH ) :
  618. {
  619. *ppCache = pNlsUserInfo->sYearMonth;
  620. break;
  621. }
  622. case ( LOCALE_SLONGDATE ) :
  623. {
  624. *ppCache = pNlsUserInfo->sLongDate;
  625. break;
  626. }
  627. case ( LOCALE_ICALENDARTYPE ) :
  628. {
  629. *ppCache = pNlsUserInfo->iCalType;
  630. break;
  631. }
  632. case ( LOCALE_IFIRSTDAYOFWEEK ) :
  633. {
  634. *ppCache = pNlsUserInfo->iFirstDay;
  635. break;
  636. }
  637. case ( LOCALE_IFIRSTWEEKOFYEAR ) :
  638. {
  639. *ppCache = pNlsUserInfo->iFirstWeek;
  640. break;
  641. }
  642. case ( LOCALE_SLOCALE ) :
  643. {
  644. *ppCache = pNlsUserInfo->sLocale;
  645. break;
  646. }
  647. default :
  648. {
  649. NtStatus = STATUS_UNSUCCESSFUL;
  650. break;
  651. }
  652. }
  653. return (NtStatus);
  654. }
  655. ////////////////////////////////////////////////////////////////////////////
  656. //
  657. // NlsQueryCurrentUserInfo
  658. //
  659. // Retreive the NLS info from the registry using a cached key.
  660. //
  661. // 04-07-99 SamerA Created.
  662. ////////////////////////////////////////////////////////////////////////////
  663. NTSTATUS NlsQueryCurrentUserInfo(
  664. PNLS_LOCAL_CACHE pNlsCache,
  665. LPWSTR pValue,
  666. LPWSTR pOutput,
  667. size_t cchOutput)
  668. {
  669. PKEY_VALUE_FULL_INFORMATION pKeyValueFull; // ptr to query info
  670. BYTE pStatic[MAX_KEY_VALUE_FULLINFO]; // ptr to static buffer
  671. ULONG rc;
  672. //
  673. // Initialize the output string.
  674. //
  675. *pOutput = 0;
  676. //
  677. // Query the registry value.
  678. //
  679. pKeyValueFull = (PKEY_VALUE_FULL_INFORMATION)pStatic;
  680. rc = QueryRegValue( pNlsCache->CurrentUserKeyHandle,
  681. pValue,
  682. &pKeyValueFull,
  683. MAX_KEY_VALUE_FULLINFO,
  684. NULL );
  685. //
  686. // If the query failed or if the output buffer is not large enough,
  687. // then return failure.
  688. //
  689. if ((rc != NO_ERROR) ||
  690. (pKeyValueFull->DataLength > (MAX_REG_VAL_SIZE * sizeof(WCHAR))))
  691. {
  692. return (STATUS_UNSUCCESSFUL);
  693. }
  694. //
  695. // Save the string in pOutput.
  696. //
  697. if(FAILED(StringCchCopyW(pOutput, MAX_REG_VAL_SIZE, GET_VALUE_DATA_PTR(pKeyValueFull))))
  698. {
  699. return (STATUS_UNSUCCESSFUL);
  700. }
  701. //
  702. // Return success.
  703. //
  704. return (STATUS_SUCCESS);
  705. }
  706. ////////////////////////////////////////////////////////////////////////////
  707. //
  708. // NlsInvalidateCache
  709. //
  710. // Invalidate an NLS Cache.
  711. //
  712. // 03-29-99 SamerA Created.
  713. ////////////////////////////////////////////////////////////////////////////
  714. void FASTCALL NlsInvalidateCache(
  715. PNLS_USER_INFO pNlsUserInfo)
  716. {
  717. pNlsUserInfo->sAbbrevLangName[0] = NLS_INVALID_INFO_CHAR;
  718. pNlsUserInfo->iCountry[0] = NLS_INVALID_INFO_CHAR;
  719. pNlsUserInfo->sCountry[0] = NLS_INVALID_INFO_CHAR;
  720. pNlsUserInfo->sList[0] = NLS_INVALID_INFO_CHAR;
  721. pNlsUserInfo->iMeasure[0] = NLS_INVALID_INFO_CHAR;
  722. pNlsUserInfo->iPaperSize[0] = NLS_INVALID_INFO_CHAR;
  723. pNlsUserInfo->sDecimal[0] = NLS_INVALID_INFO_CHAR;
  724. pNlsUserInfo->sThousand[0] = NLS_INVALID_INFO_CHAR;
  725. pNlsUserInfo->sGrouping[0] = NLS_INVALID_INFO_CHAR;
  726. pNlsUserInfo->iDigits[0] = NLS_INVALID_INFO_CHAR;
  727. pNlsUserInfo->iLZero[0] = NLS_INVALID_INFO_CHAR;
  728. pNlsUserInfo->iNegNumber[0] = NLS_INVALID_INFO_CHAR;
  729. pNlsUserInfo->sNativeDigits[0] = NLS_INVALID_INFO_CHAR;
  730. pNlsUserInfo->iDigitSubstitution[0] = NLS_INVALID_INFO_CHAR;
  731. pNlsUserInfo->sCurrency[0] = NLS_INVALID_INFO_CHAR;
  732. pNlsUserInfo->sMonDecSep[0] = NLS_INVALID_INFO_CHAR;
  733. pNlsUserInfo->sMonThouSep[0] = NLS_INVALID_INFO_CHAR;
  734. pNlsUserInfo->sMonGrouping[0] = NLS_INVALID_INFO_CHAR;
  735. pNlsUserInfo->iCurrDigits[0] = NLS_INVALID_INFO_CHAR;
  736. pNlsUserInfo->iCurrency[0] = NLS_INVALID_INFO_CHAR;
  737. pNlsUserInfo->iNegCurr[0] = NLS_INVALID_INFO_CHAR;
  738. pNlsUserInfo->sPosSign[0] = NLS_INVALID_INFO_CHAR;
  739. pNlsUserInfo->sNegSign[0] = NLS_INVALID_INFO_CHAR;
  740. pNlsUserInfo->sTimeFormat[0] = NLS_INVALID_INFO_CHAR;
  741. pNlsUserInfo->sTime[0] = NLS_INVALID_INFO_CHAR;
  742. pNlsUserInfo->iTime[0] = NLS_INVALID_INFO_CHAR;
  743. pNlsUserInfo->iTLZero[0] = NLS_INVALID_INFO_CHAR;
  744. pNlsUserInfo->iTimeMarkPosn[0] = NLS_INVALID_INFO_CHAR;
  745. pNlsUserInfo->s1159[0] = NLS_INVALID_INFO_CHAR;
  746. pNlsUserInfo->s2359[0] = NLS_INVALID_INFO_CHAR;
  747. pNlsUserInfo->sShortDate[0] = NLS_INVALID_INFO_CHAR;
  748. pNlsUserInfo->sDate[0] = NLS_INVALID_INFO_CHAR;
  749. pNlsUserInfo->iDate[0] = NLS_INVALID_INFO_CHAR;
  750. pNlsUserInfo->sYearMonth[0] = NLS_INVALID_INFO_CHAR;
  751. pNlsUserInfo->sLongDate[0] = NLS_INVALID_INFO_CHAR;
  752. pNlsUserInfo->iCalType[0] = NLS_INVALID_INFO_CHAR;
  753. pNlsUserInfo->iFirstDay[0] = NLS_INVALID_INFO_CHAR;
  754. pNlsUserInfo->iFirstWeek[0] = NLS_INVALID_INFO_CHAR;
  755. pNlsUserInfo->sLocale[0] = NLS_INVALID_INFO_CHAR;
  756. return;
  757. }