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.

1364 lines
40 KiB

  1. /*++
  2. Copyright (c) 1991-2000, Microsoft Corporation All rights reserved.
  3. Module Name:
  4. srvnls.c
  5. Abstract:
  6. This file contains the NLS Server-Side routines.
  7. Author:
  8. Julie Bennett (JulieB) 02-Dec-1992
  9. Revision History:
  10. --*/
  11. //
  12. // Include Files.
  13. //
  14. #include "basesrv.h"
  15. //
  16. // Constant Declarations.
  17. //
  18. #define MAX_PATH_LEN 512 // max length of path name
  19. #define MAX_SMALL_BUF_LEN 32 // C_nlsXXXXX.nls\0 is longest file name (15),
  20. // \NLS\NlsSectionSortkey0000XXXX\0 (31) is longest section name
  21. // Security descriptor buffer is size of SD + size of ACL + size of ACE +
  22. // sizeof SID + sizeof 1 SUB_AUTHORITY.
  23. //
  24. // THIS IS ONLY VALID FOR 1 ACE with 1 SID (SUB_AUTHORITY). If you have more it won't work for you.
  25. //
  26. // ACE is size of ACE_HEADER + size of ACCESS_MASK
  27. // SID includes the first ULONG (pointer) of the PSID_IDENTIFIER_AUTHORITY array, so this
  28. // declaration should be 4 bytes too much for a 1 ACL 1 SID 1 SubAuthority SD.
  29. // This is 52 bytes at the moment, only needs to be 48.
  30. // (I tested this by using -4, which works and -5 which STOPS during the boot.
  31. #define MAX_SMALL_SECURITY_DESCRIPTOR \
  32. (sizeof(SECURITY_DESCRIPTOR) + sizeof(ACL) + \
  33. sizeof(ACE_HEADER) + sizeof(ACCESS_MASK) + \
  34. sizeof(SID) + sizeof(PSID_IDENTIFIER_AUTHORITY ))
  35. #define MAX_KEY_VALUE_PARTINFO \
  36. (FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) + MAX_REG_VAL_SIZE * sizeof(WCHAR))
  37. //
  38. // Get the data pointer for the KEY_VALUE_FULL_INFORMATION structure.
  39. //
  40. #define GET_VALUE_DATA_PTR(p) ((LPWSTR)((PBYTE)(p) + (p)->DataOffset))
  41. //
  42. // Size of stack buffer for PKEY_VALUE_FULL_INFORMATION pointer.
  43. //
  44. #define MAX_KEY_VALUE_FULLINFO \
  45. ( FIELD_OFFSET( KEY_VALUE_FULL_INFORMATION, Name ) + MAX_PATH_LEN )
  46. //
  47. // Typedef Declarations.
  48. //
  49. //
  50. // These MUST remain in the same order as the NLS_USER_INFO structure.
  51. //
  52. LPWSTR pCPanelRegValues[] =
  53. {
  54. L"sLanguage",
  55. L"iCountry",
  56. L"sCountry",
  57. L"sList",
  58. L"iMeasure",
  59. L"iPaperSize",
  60. L"sDecimal",
  61. L"sThousand",
  62. L"sGrouping",
  63. L"iDigits",
  64. L"iLZero",
  65. L"iNegNumber",
  66. L"sNativeDigits",
  67. L"NumShape",
  68. L"sCurrency",
  69. L"sMonDecimalSep",
  70. L"sMonThousandSep",
  71. L"sMonGrouping",
  72. L"iCurrDigits",
  73. L"iCurrency",
  74. L"iNegCurr",
  75. L"sPositiveSign",
  76. L"sNegativeSign",
  77. L"sTimeFormat",
  78. L"sTime",
  79. L"iTime",
  80. L"iTLZero",
  81. L"iTimePrefix",
  82. L"s1159",
  83. L"s2359",
  84. L"sShortDate",
  85. L"sDate",
  86. L"iDate",
  87. L"sYearMonth",
  88. L"sLongDate",
  89. L"iCalendarType",
  90. L"iFirstDayOfWeek",
  91. L"iFirstWeekOfYear",
  92. L"Locale"
  93. };
  94. int NumCPanelRegValues = (sizeof(pCPanelRegValues) / sizeof(LPWSTR));
  95. //
  96. // Global Variables.
  97. //
  98. // Critical Section to protect the NLS cache, which caches the current user settings from registry.
  99. RTL_CRITICAL_SECTION NlsCacheCriticalSection;
  100. HANDLE hCPanelIntlKeyRead = INVALID_HANDLE_VALUE;
  101. HANDLE hCPanelIntlKeyWrite = INVALID_HANDLE_VALUE;
  102. PNLS_USER_INFO pNlsRegUserInfo;
  103. ULONG NlsChangeBuffer;
  104. IO_STATUS_BLOCK IoStatusBlock;
  105. //
  106. // Forward Declarations.
  107. //
  108. ULONG
  109. NlsSetRegAndCache(
  110. LPWSTR pValue,
  111. LPWSTR pCacheString,
  112. LPWSTR pData,
  113. ULONG DataLength);
  114. VOID
  115. NlsUpdateCacheInfo(VOID);
  116. NTSTATUS GetThreadAuthenticationId(
  117. PLUID Luid);
  118. ////////////////////////////////////////////////////////////////////////////
  119. //
  120. // BaseSrvNLSInit
  121. //
  122. // This routine creates the shared heap for the nls information.
  123. // This is called when csrss.exe is initialized.
  124. //
  125. // 08-19-94 JulieB Created.
  126. ////////////////////////////////////////////////////////////////////////////
  127. NTSTATUS
  128. BaseSrvNLSInit(
  129. PBASE_STATIC_SERVER_DATA pStaticServerData)
  130. {
  131. NTSTATUS rc; // return code
  132. //
  133. // Create a critical section to protect the cache.
  134. //
  135. rc = RtlInitializeCriticalSection (&NlsCacheCriticalSection);
  136. if (!NT_SUCCESS(rc))
  137. {
  138. KdPrint(("NLSAPI (BaseSrv): Could NOT Create Cache critical section - %lx.\n", rc));
  139. return (rc);
  140. }
  141. //
  142. // Initialize the cache to zero.
  143. //
  144. pNlsRegUserInfo = &(pStaticServerData->NlsUserInfo);
  145. RtlFillMemory(pNlsRegUserInfo, sizeof(NLS_USER_INFO), (CHAR)NLS_INVALID_INFO_CHAR);
  146. pNlsRegUserInfo->UserLocaleId = 0;
  147. RtlEnterCriticalSection(&NlsCacheCriticalSection);
  148. pNlsRegUserInfo->ulCacheUpdateCount = 0;
  149. RtlLeaveCriticalSection(&NlsCacheCriticalSection);
  150. //
  151. // Make the system locale the user locale.
  152. //
  153. NtQueryDefaultLocale(FALSE, &(pNlsRegUserInfo->UserLocaleId));
  154. //
  155. // Return success.
  156. //
  157. return (STATUS_SUCCESS);
  158. }
  159. ////////////////////////////////////////////////////////////////////////////
  160. //
  161. // BaseSrvNLSConnect
  162. //
  163. // This routine duplicates the mutant handle for the client.
  164. //
  165. // 08-19-94 JulieB Created.
  166. ////////////////////////////////////////////////////////////////////////////
  167. NTSTATUS
  168. BaseSrvNlsConnect(
  169. PCSR_PROCESS Process,
  170. PVOID pConnectionInfo,
  171. PULONG pConnectionInfoLength)
  172. {
  173. return (STATUS_SUCCESS);
  174. }
  175. ////////////////////////////////////////////////////////////////////////////
  176. //
  177. // BaseSrvNlsLogon
  178. //
  179. // This routine initializes the heap for the nls information. If fLogon
  180. // is TRUE, then it opens the registry key, initializes the heap
  181. // information, and registers the key for notification. If fLogon is
  182. // FALSE, then it unregisters the key for notification, zeros out the
  183. // heap information, and closes the registry key.
  184. //
  185. // 08-19-94 JulieB Created.
  186. ////////////////////////////////////////////////////////////////////////////
  187. NTSTATUS
  188. BaseSrvNlsLogon(
  189. BOOL fLogon)
  190. {
  191. HANDLE hKeyRead; // temp handle for read access
  192. HANDLE hKeyWrite; // temp handle for write access
  193. HANDLE hUserHandle; // HKEY_CURRENT_USER equivalent
  194. OBJECT_ATTRIBUTES ObjA; // object attributes structure
  195. UNICODE_STRING ObKeyName; // key name
  196. NTSTATUS rc = STATUS_SUCCESS; // return code
  197. RTL_SOFT_VERIFY(NT_SUCCESS(rc = BaseSrvSxsInvalidateSystemDefaultActivationContextCache()));
  198. if (fLogon)
  199. {
  200. //
  201. // Retreive the currently logged on interactive user's Luid
  202. // authentication id. The currently executing thread is
  203. // impersonating the logged on user.
  204. //
  205. if (pNlsRegUserInfo != NULL)
  206. {
  207. GetThreadAuthenticationId(&pNlsRegUserInfo->InteractiveUserLuid);
  208. //
  209. // Logging ON.
  210. // - open keys
  211. //
  212. // NOTE: Registry Notification is done by the RIT in user server.
  213. //
  214. rc = RtlOpenCurrentUser(MAXIMUM_ALLOWED, &hUserHandle);
  215. if (!NT_SUCCESS(rc))
  216. {
  217. KdPrint(("NLSAPI (BaseSrv): Could NOT Open HKEY_CURRENT_USER - %lx.\n", rc));
  218. return (rc);
  219. }
  220. RtlInitUnicodeString(&ObKeyName, L"Control Panel\\International");
  221. InitializeObjectAttributes( &ObjA,
  222. &ObKeyName,
  223. OBJ_CASE_INSENSITIVE,
  224. hUserHandle,
  225. NULL );
  226. //
  227. // Open key for READ and NOTIFY access.
  228. //
  229. rc = NtOpenKey( &hKeyRead,
  230. KEY_READ | KEY_NOTIFY,
  231. &ObjA );
  232. //
  233. // Open key for WRITE access.
  234. //
  235. if (!NT_SUCCESS(NtOpenKey( &hKeyWrite,
  236. KEY_WRITE,
  237. &ObjA )))
  238. {
  239. KdPrint(("NLSAPI (BaseSrv): Could NOT Open Registry Key %wZ for Write - %lx.\n",
  240. &ObKeyName, rc));
  241. hKeyWrite = INVALID_HANDLE_VALUE;
  242. }
  243. //
  244. // Close the handle to the current user (HKEY_CURRENT_USER).
  245. //
  246. NtClose(hUserHandle);
  247. //
  248. // Check for error from first NtOpenKey.
  249. //
  250. if (!NT_SUCCESS(rc))
  251. {
  252. KdPrint(("NLSAPI (BaseSrv): Could NOT Open Registry Key %wZ for Read - %lx.\n",
  253. &ObKeyName, rc));
  254. if (hKeyWrite != INVALID_HANDLE_VALUE)
  255. {
  256. NtClose(hKeyWrite);
  257. }
  258. return (rc);
  259. }
  260. //
  261. // Enter the critical section so that we don't mess up the public handle.
  262. //
  263. rc = RtlEnterCriticalSection(&NlsCacheCriticalSection);
  264. if (!NT_SUCCESS( rc ))
  265. {
  266. return (rc);
  267. }
  268. //
  269. // Make sure any old handles are closed.
  270. //
  271. if (hCPanelIntlKeyRead != INVALID_HANDLE_VALUE)
  272. {
  273. NtClose(hCPanelIntlKeyRead);
  274. }
  275. if (hCPanelIntlKeyWrite != INVALID_HANDLE_VALUE)
  276. {
  277. NtClose(hCPanelIntlKeyWrite);
  278. }
  279. //
  280. // Save the new handles.
  281. //
  282. hCPanelIntlKeyRead = hKeyRead;
  283. hCPanelIntlKeyWrite = hKeyWrite;
  284. //
  285. // Fill up the cache so that we have the latest intl settings in the registry.
  286. //
  287. NlsUpdateCacheInfo();
  288. RtlLeaveCriticalSection(&NlsCacheCriticalSection);
  289. }
  290. }
  291. else
  292. {
  293. //
  294. // Logging OFF.
  295. // - close keys
  296. // - zero out info
  297. //
  298. //
  299. // This may come as NULL, during stress memory cond for terminal
  300. // server (when NLS cache mutant couldn't be created).
  301. //
  302. if (pNlsRegUserInfo != NULL)
  303. {
  304. rc = RtlEnterCriticalSection(&NlsCacheCriticalSection);
  305. if (!NT_SUCCESS( rc ))
  306. {
  307. return (rc);
  308. }
  309. if (hCPanelIntlKeyRead != INVALID_HANDLE_VALUE)
  310. {
  311. NtClose(hCPanelIntlKeyRead);
  312. hCPanelIntlKeyRead = INVALID_HANDLE_VALUE;
  313. }
  314. if (hCPanelIntlKeyWrite != INVALID_HANDLE_VALUE)
  315. {
  316. NtClose(hCPanelIntlKeyWrite);
  317. hCPanelIntlKeyWrite = INVALID_HANDLE_VALUE;
  318. }
  319. //
  320. // Fill the cache with NLS_INVALID_INFO_CHAR.
  321. //
  322. RtlFillMemory(pNlsRegUserInfo, sizeof(NLS_USER_INFO), (CHAR)NLS_INVALID_INFO_CHAR);
  323. pNlsRegUserInfo->UserLocaleId = 0;
  324. // Reset the cache update count. There is no need to use InterlockedExchange() since
  325. // all updates to ulCacheUpdateCount are protected in the critical section NlsCacheCriticalSection.
  326. pNlsRegUserInfo->ulCacheUpdateCount = 0;
  327. //
  328. // Make the system locale the user locale.
  329. //
  330. NtQueryDefaultLocale(FALSE, &(pNlsRegUserInfo->UserLocaleId));
  331. //
  332. // No need to reset the User's Authentication Id, since it's
  333. // being zero'ed out above.
  334. //
  335. RtlLeaveCriticalSection(&NlsCacheCriticalSection);
  336. }
  337. }
  338. //
  339. // Return success.
  340. //
  341. return (STATUS_SUCCESS);
  342. }
  343. ////////////////////////////////////////////////////////////////////////////
  344. //
  345. // BaseSrvNlsUpdateRegistryCache
  346. //
  347. // This routine updates the NLS cache when a registry notification occurs.
  348. //
  349. // 08-19-94 JulieB Created.
  350. ////////////////////////////////////////////////////////////////////////////
  351. VOID
  352. BaseSrvNlsUpdateRegistryCache(
  353. PVOID ApcContext,
  354. PIO_STATUS_BLOCK pIoStatusBlock)
  355. {
  356. ULONG rc = 0L; // return code
  357. if (hCPanelIntlKeyRead == INVALID_HANDLE_VALUE)
  358. {
  359. return;
  360. }
  361. if (!NT_SUCCESS(RtlEnterCriticalSection(&NlsCacheCriticalSection)))
  362. {
  363. return;
  364. }
  365. if (hCPanelIntlKeyRead == INVALID_HANDLE_VALUE)
  366. {
  367. RtlLeaveCriticalSection( &NlsCacheCriticalSection );
  368. return;
  369. }
  370. //
  371. // Update the cache information.
  372. //
  373. NlsUpdateCacheInfo();
  374. RtlLeaveCriticalSection( &NlsCacheCriticalSection );
  375. //
  376. // Call NtNotifyChangeKey.
  377. //
  378. rc = NtNotifyChangeKey( hCPanelIntlKeyRead,
  379. NULL,
  380. (PIO_APC_ROUTINE)BaseSrvNlsUpdateRegistryCache,
  381. NULL,
  382. &IoStatusBlock,
  383. REG_NOTIFY_CHANGE_LAST_SET | REG_NOTIFY_CHANGE_NAME,
  384. FALSE,
  385. &NlsChangeBuffer,
  386. sizeof(NlsChangeBuffer),
  387. TRUE );
  388. #ifdef DBG
  389. //
  390. // Check for error from NtNotifyChangeKey.
  391. //
  392. if (!NT_SUCCESS(rc))
  393. {
  394. KdPrint(("NLSAPI (BaseSrv): Could NOT Set Notification of Control Panel International Registry Key - %lx.\n",
  395. rc));
  396. }
  397. #endif
  398. }
  399. ////////////////////////////////////////////////////////////////////////////
  400. //
  401. // NlsSetRegAndCache
  402. //
  403. // This routine sets the registry with the appropriate string and then
  404. // updates the cache.
  405. //
  406. // NOTE: Must already own the mutant for the cache before calling this
  407. // routine.
  408. //
  409. // 08-19-94 JulieB Created.
  410. ////////////////////////////////////////////////////////////////////////////
  411. ULONG
  412. NlsSetRegAndCache(
  413. LPWSTR pValue,
  414. LPWSTR pCacheString,
  415. LPWSTR pData,
  416. ULONG DataLength)
  417. {
  418. UNICODE_STRING ObValueName; // value name
  419. ULONG rc; // return code
  420. if (hCPanelIntlKeyWrite != INVALID_HANDLE_VALUE)
  421. {
  422. //
  423. // Validate data length to be set in the registry
  424. //
  425. if (DataLength >= MAX_REG_VAL_SIZE)
  426. {
  427. return ((ULONG)STATUS_INVALID_PARAMETER);
  428. }
  429. RTL_SOFT_VERIFY(NT_SUCCESS(rc = BaseSrvSxsInvalidateSystemDefaultActivationContextCache()));
  430. //
  431. // Set the value in the registry.
  432. //
  433. RtlInitUnicodeString(&ObValueName, pValue);
  434. rc = NtSetValueKey( hCPanelIntlKeyWrite,
  435. &ObValueName,
  436. 0,
  437. REG_SZ,
  438. (PVOID)pData,
  439. DataLength );
  440. //
  441. // Copy the new string to the cache.
  442. //
  443. if (NT_SUCCESS(rc))
  444. {
  445. wcsncpy(pCacheString, pData, DataLength);
  446. pCacheString[DataLength / sizeof(WCHAR)] = 0;
  447. }
  448. //
  449. // Return the result.
  450. //
  451. return (rc);
  452. }
  453. //
  454. // Return access denied, since the key is not open for write access.
  455. //
  456. return ((ULONG)STATUS_ACCESS_DENIED);
  457. }
  458. ////////////////////////////////////////////////////////////////////////////
  459. //
  460. // BaseSrvNlsGetUserInfo
  461. //
  462. // This routine gets all of the values (including ulCacheUpdateCount) in the NLS cache, and copy it
  463. // to the buffer in the capture buffer.
  464. //
  465. // Parameters:
  466. // pData in BASE_NLS_GET_USER_INFO_MSG contains the target buffer to write.
  467. // DataLength in BASE_NLS_GET_USER_INFO_MSG is the size of target buffer. It should be the value of sizeof(NLS_USER_INFO).
  468. //
  469. // When this function returns, the capture buffer will contain the data
  470. // of the specified field.
  471. //
  472. //
  473. // 06-06-2002 YSLin Created.
  474. ////////////////////////////////////////////////////////////////////////////
  475. NTSTATUS
  476. BaseSrvNlsGetUserInfo(
  477. IN OUT PCSR_API_MSG m,
  478. IN OUT PCSR_REPLY_STATUS ReplyStatus)
  479. {
  480. PBASE_NLS_GET_USER_INFO_MSG a =
  481. (PBASE_NLS_GET_USER_INFO_MSG)&m->u.ApiMessageData;
  482. NTSTATUS rc; // return code
  483. LPWSTR pValue; // Points to the cached value.
  484. if (!CsrValidateMessageBuffer(m, &a->pData, a->DataLength, sizeof(BYTE)))
  485. {
  486. return (STATUS_INVALID_PARAMETER);
  487. }
  488. if (a->DataLength != sizeof(NLS_USER_INFO))
  489. {
  490. return (STATUS_INVALID_PARAMETER);
  491. }
  492. rc = RtlEnterCriticalSection(&NlsCacheCriticalSection);
  493. if (!NT_SUCCESS( rc ))
  494. {
  495. return (rc);
  496. }
  497. RtlCopyMemory((LPVOID)a->pData, pNlsRegUserInfo, a->DataLength);
  498. RtlLeaveCriticalSection( &NlsCacheCriticalSection );
  499. //
  500. // Return the result of NtSetValueKey.
  501. //
  502. return (rc);
  503. ReplyStatus; // get rid of unreferenced parameter warning message
  504. }
  505. ////////////////////////////////////////////////////////////////////////////
  506. //
  507. // BaseSrvNlsSetUserInfo
  508. //
  509. // This routine sets a particular value in the NLS cache and updates the
  510. // registry entry.
  511. //
  512. // 08-19-94 JulieB Created.
  513. ////////////////////////////////////////////////////////////////////////////
  514. ULONG
  515. BaseSrvNlsSetUserInfo(
  516. IN OUT PCSR_API_MSG m,
  517. IN OUT PCSR_REPLY_STATUS ReplyStatus)
  518. {
  519. PBASE_NLS_SET_USER_INFO_MSG a =
  520. (PBASE_NLS_SET_USER_INFO_MSG)&m->u.ApiMessageData;
  521. ULONG rc; // return code
  522. LPWSTR pValue;
  523. LPWSTR pCache;
  524. if (!CsrValidateMessageBuffer(m, &a->pData, a->DataLength, sizeof(BYTE)))
  525. {
  526. return (STATUS_INVALID_PARAMETER);
  527. }
  528. RTL_VERIFY(NT_SUCCESS(rc = BaseSrvDelayLoadKernel32()));
  529. ASSERT(pValidateLCType != NULL);
  530. if (0 == (*pValidateLCType)(pNlsRegUserInfo, a->LCType, &pValue, &pCache))
  531. {
  532. return (STATUS_INVALID_PARAMETER);
  533. }
  534. rc = RtlEnterCriticalSection(&NlsCacheCriticalSection);
  535. if (!NT_SUCCESS( rc ))
  536. {
  537. return (rc);
  538. }
  539. //
  540. // Set the value in the registry and update the cache.
  541. //
  542. rc = NlsSetRegAndCache( pValue,
  543. pCache,
  544. a->pData,
  545. a->DataLength );
  546. if (NT_SUCCESS(rc))
  547. {
  548. // Increment the cache update count. There is no need to use InterlockedExchange() since
  549. // all updates to ulCacheUpdateCount are protected in the same critical section.
  550. pNlsRegUserInfo->ulCacheUpdateCount++;
  551. }
  552. RtlLeaveCriticalSection( &NlsCacheCriticalSection );
  553. //
  554. // Return the result of NtSetValueKey.
  555. //
  556. return (rc);
  557. ReplyStatus; // get rid of unreferenced parameter warning message
  558. }
  559. ////////////////////////////////////////////////////////////////////////////
  560. //
  561. // BaseSrvNlsSetMultipleUserInfo
  562. //
  563. // This routine sets the date/time strings in the NLS cache and updates the
  564. // registry entries.
  565. //
  566. // This call is done so that only one client/server transition is needed
  567. // when setting multiple entries.
  568. //
  569. // 08-19-94 JulieB Created.
  570. ////////////////////////////////////////////////////////////////////////////
  571. ULONG
  572. BaseSrvNlsSetMultipleUserInfo(
  573. IN OUT PCSR_API_MSG m,
  574. IN OUT PCSR_REPLY_STATUS ReplyStatus)
  575. {
  576. PBASE_NLS_SET_MULTIPLE_USER_INFO_MSG a =
  577. (PBASE_NLS_SET_MULTIPLE_USER_INFO_MSG)&m->u.ApiMessageData;
  578. BOOL DoNotUpdateCacheCount = FALSE;
  579. ULONG rc = 0L; // return code
  580. if (!CsrValidateMessageBuffer(m, &a->pPicture, a->DataLength, sizeof(BYTE)))
  581. {
  582. return (STATUS_INVALID_PARAMETER);
  583. }
  584. if (!CsrValidateMessageString(m, &a->pSeparator))
  585. {
  586. return (STATUS_INVALID_PARAMETER);
  587. }
  588. if (!CsrValidateMessageString(m, &a->pOrder))
  589. {
  590. return (STATUS_INVALID_PARAMETER);
  591. }
  592. if (!CsrValidateMessageString(m, &a->pTLZero))
  593. {
  594. return (STATUS_INVALID_PARAMETER);
  595. }
  596. if (!CsrValidateMessageString(m, &a->pTimeMarkPosn))
  597. {
  598. return (STATUS_INVALID_PARAMETER);
  599. }
  600. rc = RtlEnterCriticalSection(&NlsCacheCriticalSection);
  601. if (!NT_SUCCESS( rc ))
  602. {
  603. return (rc);
  604. }
  605. switch (a->Flags)
  606. {
  607. case ( LOCALE_STIMEFORMAT ) :
  608. {
  609. rc = NlsSetRegAndCache( NLS_VALUE_STIMEFORMAT,
  610. pNlsRegUserInfo->sTimeFormat,
  611. a->pPicture,
  612. a->DataLength );
  613. if (NT_SUCCESS(rc))
  614. {
  615. rc = NlsSetRegAndCache( NLS_VALUE_STIME,
  616. pNlsRegUserInfo->sTime,
  617. a->pSeparator,
  618. (wcslen(a->pSeparator) + 1) * sizeof(WCHAR) );
  619. }
  620. if (NT_SUCCESS(rc))
  621. {
  622. rc = NlsSetRegAndCache( NLS_VALUE_ITIME,
  623. pNlsRegUserInfo->iTime,
  624. a->pOrder,
  625. (wcslen(a->pOrder) + 1) * sizeof(WCHAR) );
  626. }
  627. if (NT_SUCCESS(rc))
  628. {
  629. rc = NlsSetRegAndCache( NLS_VALUE_ITLZERO,
  630. pNlsRegUserInfo->iTLZero,
  631. a->pTLZero,
  632. (wcslen(a->pTLZero) + 1) * sizeof(WCHAR) );
  633. }
  634. if (NT_SUCCESS(rc))
  635. {
  636. rc = NlsSetRegAndCache( NLS_VALUE_ITIMEMARKPOSN,
  637. pNlsRegUserInfo->iTimeMarkPosn,
  638. a->pTimeMarkPosn,
  639. (wcslen(a->pTimeMarkPosn) + 1) * sizeof(WCHAR) );
  640. }
  641. break;
  642. }
  643. case ( LOCALE_STIME ) :
  644. {
  645. rc = NlsSetRegAndCache( NLS_VALUE_STIME,
  646. pNlsRegUserInfo->sTime,
  647. a->pSeparator,
  648. a->DataLength );
  649. if (NT_SUCCESS(rc))
  650. {
  651. rc = NlsSetRegAndCache( NLS_VALUE_STIMEFORMAT,
  652. pNlsRegUserInfo->sTimeFormat,
  653. a->pPicture,
  654. (wcslen(a->pPicture) + 1) * sizeof(WCHAR) );
  655. }
  656. break;
  657. }
  658. case ( LOCALE_ITIME ) :
  659. {
  660. rc = NlsSetRegAndCache( NLS_VALUE_ITIME,
  661. pNlsRegUserInfo->iTime,
  662. a->pOrder,
  663. a->DataLength );
  664. if (NT_SUCCESS(rc))
  665. {
  666. rc = NlsSetRegAndCache( NLS_VALUE_STIMEFORMAT,
  667. pNlsRegUserInfo->sTimeFormat,
  668. a->pPicture,
  669. (wcslen(a->pPicture) + 1) * sizeof(WCHAR) );
  670. }
  671. break;
  672. }
  673. case ( LOCALE_SSHORTDATE ) :
  674. {
  675. rc = NlsSetRegAndCache( NLS_VALUE_SSHORTDATE,
  676. pNlsRegUserInfo->sShortDate,
  677. a->pPicture,
  678. a->DataLength );
  679. if (NT_SUCCESS(rc))
  680. {
  681. rc = NlsSetRegAndCache( NLS_VALUE_SDATE,
  682. pNlsRegUserInfo->sDate,
  683. a->pSeparator,
  684. (wcslen(a->pSeparator) + 1) * sizeof(WCHAR) );
  685. }
  686. if (NT_SUCCESS(rc))
  687. {
  688. rc = NlsSetRegAndCache( NLS_VALUE_IDATE,
  689. pNlsRegUserInfo->iDate,
  690. a->pOrder,
  691. (wcslen(a->pOrder) + 1) * sizeof(WCHAR) );
  692. }
  693. break;
  694. }
  695. case ( LOCALE_SDATE ) :
  696. {
  697. rc = NlsSetRegAndCache( NLS_VALUE_SDATE,
  698. pNlsRegUserInfo->sDate,
  699. a->pSeparator,
  700. a->DataLength );
  701. if (NT_SUCCESS(rc))
  702. {
  703. rc = NlsSetRegAndCache( NLS_VALUE_SSHORTDATE,
  704. pNlsRegUserInfo->sShortDate,
  705. a->pPicture,
  706. (wcslen(a->pPicture) + 1) * sizeof(WCHAR) );
  707. }
  708. break;
  709. }
  710. default:
  711. {
  712. DoNotUpdateCacheCount = TRUE;
  713. break;
  714. }
  715. }
  716. if (NT_SUCCESS(rc) && (DoNotUpdateCacheCount == FALSE))
  717. {
  718. // Increment the cache update count. There is no need to use InterlockedExchange() since
  719. // all updates to ulCacheUpdateCount are protected in the same critical section.
  720. pNlsRegUserInfo->ulCacheUpdateCount++;
  721. }
  722. RtlLeaveCriticalSection(&NlsCacheCriticalSection);
  723. //
  724. // Return the result.
  725. //
  726. return (rc);
  727. ReplyStatus; // get rid of unreferenced parameter warning message
  728. }
  729. ////////////////////////////////////////////////////////////////////////////
  730. //
  731. // BaseSrvNlsUpdateCacheCount
  732. //
  733. // This routine forces an increment on pNlsUserInfo->ulNlsCacheUpdateCount
  734. //
  735. // 11-29-99 SamerA Created.
  736. ////////////////////////////////////////////////////////////////////////////
  737. ULONG
  738. BaseSrvNlsUpdateCacheCount(
  739. IN OUT PCSR_API_MSG m,
  740. IN OUT PCSR_REPLY_STATUS ReplyStatus)
  741. {
  742. PBASE_NLS_UPDATE_CACHE_COUNT_MSG a =
  743. (PBASE_NLS_UPDATE_CACHE_COUNT_MSG)&m->u.ApiMessageData;
  744. //
  745. // Increment the cache count.
  746. // Use Interlocked operation since we do not use a critical section here.
  747. //
  748. if (pNlsRegUserInfo)
  749. {
  750. RtlEnterCriticalSection(&NlsCacheCriticalSection);
  751. pNlsRegUserInfo->ulCacheUpdateCount++;
  752. RtlLeaveCriticalSection(&NlsCacheCriticalSection);
  753. }
  754. return (0L);
  755. ReplyStatus; // get rid of unreferenced parameter warning message
  756. }
  757. ////////////////////////////////////////////////////////////////////////////
  758. //
  759. // NlsUpdateCacheInfo
  760. //
  761. // This routine updates the NLS cache when a registry notification occurs.
  762. /// It will update every field in the NLS cache which stores value in the
  763. // the registry.
  764. //
  765. // NOTENOTE:
  766. // THE CALLER OF THIS FUNCITON SHOULD BE IN A CRITICAL SECTION
  767. // PROTECTED BY NlsCacheCriticalSection, SINCE THE ulCacheUpdateCount
  768. // AND pNlsRegUserInfo ARE UPDATED IN THIS FUNCTION.
  769. //
  770. // 08-19-94 JulieB Created.
  771. ////////////////////////////////////////////////////////////////////////////
  772. VOID
  773. NlsUpdateCacheInfo()
  774. {
  775. LCID Locale; // locale id
  776. UNICODE_STRING ObKeyName; // key name
  777. LPWSTR pTmp; // tmp string pointer
  778. int ctr; // loop counter
  779. ULONG ResultLength; // result length
  780. ULONG rc = 0L; // return code
  781. BYTE KeyValuePart[MAX_KEY_VALUE_PARTINFO];
  782. PKEY_VALUE_PARTIAL_INFORMATION pValuePart;
  783. //
  784. // NOTE: The caller of this function should already have the
  785. // cache mutant before calling this routine.
  786. //
  787. //
  788. // Update the cache information.
  789. //
  790. pTmp = (LPWSTR)pNlsRegUserInfo;
  791. pValuePart = (PKEY_VALUE_PARTIAL_INFORMATION)KeyValuePart;
  792. for (ctr = 0; ctr < NumCPanelRegValues; ctr++)
  793. {
  794. RtlInitUnicodeString(&ObKeyName, pCPanelRegValues[ctr]);
  795. rc = NtQueryValueKey( hCPanelIntlKeyRead,
  796. &ObKeyName,
  797. KeyValuePartialInformation,
  798. pValuePart,
  799. MAX_KEY_VALUE_PARTINFO,
  800. &ResultLength );
  801. if (NT_SUCCESS(rc))
  802. {
  803. wcsncpy(pTmp, (LPWSTR)(pValuePart->Data), MAX_REG_VAL_SIZE);
  804. // When the length of the string in the registry is greater than or equal to
  805. // MAX_REG_VAL_SIZE, wcsncpy won't put NULL terminiator for us. So we make sure that
  806. // it is NULL terminated at the end of the buffer in the statement below.
  807. pTmp[MAX_REG_VAL_SIZE - 1] = UNICODE_NULL;
  808. }
  809. else
  810. {
  811. *pTmp = NLS_INVALID_INFO_CHAR;
  812. *(pTmp + 1) = UNICODE_NULL;
  813. }
  814. //
  815. // Increment pointer to cache structure.
  816. //
  817. pTmp += MAX_REG_VAL_SIZE;
  818. }
  819. //
  820. // Once we finished reading the reg-data, let's increment
  821. // our global update cache count
  822. //
  823. pNlsRegUserInfo->ulCacheUpdateCount++;
  824. //
  825. // Convert the user locale id string to a dword value and store
  826. // it in the cache.
  827. //
  828. pNlsRegUserInfo->UserLocaleId = (LCID)0;
  829. if ((pNlsRegUserInfo->sLocale)[0] != NLS_INVALID_INFO_CHAR)
  830. {
  831. RtlInitUnicodeString(&ObKeyName, pNlsRegUserInfo->sLocale);
  832. if (NT_SUCCESS(RtlUnicodeStringToInteger(&ObKeyName, 16, &Locale)))
  833. {
  834. pNlsRegUserInfo->UserLocaleId = Locale;
  835. }
  836. }
  837. //
  838. // Make sure the user locale id was found. Otherwise, set it to
  839. // the system locale.
  840. //
  841. if (pNlsRegUserInfo->UserLocaleId == 0)
  842. {
  843. NtQueryDefaultLocale(FALSE, &(pNlsRegUserInfo->UserLocaleId));
  844. }
  845. }
  846. ////////////////////////////////////////////////////////////////////////////
  847. //
  848. // BaseSrvNlsCreateSection
  849. //
  850. ////////////////////////////////////////////////////////////////////////////
  851. ULONG
  852. BaseSrvNlsCreateSection(
  853. IN OUT PCSR_API_MSG m,
  854. IN OUT PCSR_REPLY_STATUS ReplyStatus)
  855. {
  856. PBASE_NLS_CREATE_SECTION_MSG a =
  857. (PBASE_NLS_CREATE_SECTION_MSG)&m->u.ApiMessageData;
  858. UNICODE_STRING ObSecName; // section name
  859. LARGE_INTEGER Size;
  860. WCHAR wszFileName[MAX_SMALL_BUF_LEN]; // file name (Actually l2 chars is max: c_nlsXXXXX.nls\0
  861. WCHAR wszSecName[MAX_SMALL_BUF_LEN]; // section name string
  862. HANDLE hNewSec = (HANDLE)0; // new section handle
  863. HANDLE hProcess = (HANDLE)0; // process handle
  864. OBJECT_ATTRIBUTES ObjA; // object attributes structure
  865. NTSTATUS rc = 0L; // return code
  866. LPWSTR pFile = NULL;
  867. HANDLE hFile = (HANDLE)0; // file handle
  868. ANSI_STRING proc;
  869. PVOID pTemp; // temp pointer
  870. BYTE pSecurityDescriptor[MAX_SMALL_SECURITY_DESCRIPTOR]; // Buffer for our security descriptor
  871. RTL_VERIFY(NT_SUCCESS(rc = BaseSrvDelayLoadKernel32()));
  872. //
  873. // Set the handles to null.
  874. //
  875. a->hNewSection = NULL;
  876. if (a->Locale)
  877. {
  878. if (!(*pValidateLocale)(a->Locale))
  879. {
  880. return (STATUS_INVALID_PARAMETER);
  881. }
  882. }
  883. switch (a->uiType)
  884. {
  885. case (NLS_CREATE_SECTION_UNICODE) :
  886. {
  887. RtlInitUnicodeString(&ObSecName, NLS_SECTION_UNICODE);
  888. pFile = NLS_FILE_UNICODE;
  889. break;
  890. }
  891. case (NLS_CREATE_SECTION_GEO) :
  892. {
  893. RtlInitUnicodeString(&ObSecName, NLS_SECTION_GEO);
  894. pFile = NLS_FILE_GEO;
  895. break;
  896. }
  897. case (NLS_CREATE_SECTION_LOCALE) :
  898. {
  899. RtlInitUnicodeString(&ObSecName, NLS_SECTION_LOCALE);
  900. pFile = NLS_FILE_LOCALE;
  901. break;
  902. }
  903. case (NLS_CREATE_SECTION_CTYPE) :
  904. {
  905. RtlInitUnicodeString(&ObSecName, NLS_SECTION_CTYPE);
  906. pFile = NLS_FILE_CTYPE;
  907. break;
  908. }
  909. case (NLS_CREATE_SECTION_SORTKEY) :
  910. {
  911. RtlInitUnicodeString(&ObSecName, NLS_SECTION_SORTKEY);
  912. pFile = NLS_FILE_SORTKEY;
  913. break;
  914. }
  915. case (NLS_CREATE_SECTION_SORTTBLS) :
  916. {
  917. RtlInitUnicodeString(&ObSecName, NLS_SECTION_SORTTBLS);
  918. pFile = NLS_FILE_SORTTBLS;
  919. break;
  920. }
  921. case (NLS_CREATE_SECTION_DEFAULT_OEMCP) :
  922. {
  923. RtlInitUnicodeString(&ObSecName, NLS_DEFAULT_SECTION_OEMCP);
  924. pFile = NLS_DEFAULT_FILE_OEMCP;
  925. break;
  926. }
  927. case (NLS_CREATE_SECTION_DEFAULT_ACP) :
  928. {
  929. RtlInitUnicodeString(&ObSecName, NLS_DEFAULT_SECTION_ACP);
  930. pFile = NLS_DEFAULT_FILE_ACP;
  931. break;
  932. }
  933. case (NLS_CREATE_SECTION_LANG_EXCEPT) :
  934. {
  935. RtlInitUnicodeString(&ObSecName, NLS_SECTION_LANG_EXCEPT);
  936. pFile = NLS_FILE_LANG_EXCEPT;
  937. break;
  938. }
  939. case (NLS_CREATE_CODEPAGE_SECTION) :
  940. {
  941. // Get the Code Page file name from registry
  942. ASSERT(pGetCPFileNameFromRegistry);
  943. if ( FALSE == (*pGetCPFileNameFromRegistry)( a->Locale,
  944. wszFileName,
  945. MAX_SMALL_BUF_LEN ) )
  946. {
  947. return (STATUS_INVALID_PARAMETER);
  948. }
  949. // Remember we're using this file name
  950. pFile = wszFileName;
  951. // Hmm, we'll need the section name for this section.
  952. // Note that this had better be in sync with what we see
  953. // in winnls\tables.c or else the server will be called needlessly.
  954. ASSERT(pGetNlsSectionName != NULL);
  955. if (!NT_SUCCESS((*pGetNlsSectionName)( a->Locale,
  956. 10,
  957. 0,
  958. NLS_SECTION_CPPREFIX,
  959. wszSecName,
  960. MAX_SMALL_BUF_LEN)))
  961. {
  962. return (rc);
  963. }
  964. // Make it a string we can remember/use later
  965. RtlInitUnicodeString(&ObSecName, wszSecName);
  966. break;
  967. }
  968. case ( NLS_CREATE_SORT_SECTION ) :
  969. {
  970. if (a->Locale == 0)
  971. {
  972. return (STATUS_INVALID_PARAMETER);
  973. }
  974. ASSERT(pGetNlsSectionName != NULL);
  975. if (rc = (*pGetNlsSectionName)( a->Locale,
  976. 16,
  977. 8,
  978. NLS_SECTION_SORTKEY,
  979. wszSecName,
  980. MAX_SMALL_BUF_LEN))
  981. {
  982. return (rc);
  983. }
  984. ASSERT(pGetDefaultSortkeySize != NULL);
  985. (*pGetDefaultSortkeySize)(&Size);
  986. RtlInitUnicodeString(&ObSecName, wszSecName);
  987. break;
  988. }
  989. case ( NLS_CREATE_LANG_EXCEPTION_SECTION ) :
  990. {
  991. if (a->Locale == 0)
  992. {
  993. //
  994. // Creating the default section.
  995. //
  996. RtlInitUnicodeString(&ObSecName, NLS_SECTION_LANG_INTL);
  997. }
  998. else
  999. {
  1000. ASSERT(pGetNlsSectionName != NULL);
  1001. if (rc = (*pGetNlsSectionName)( a->Locale,
  1002. 16,
  1003. 8,
  1004. NLS_SECTION_LANGPREFIX,
  1005. wszSecName,
  1006. MAX_SMALL_BUF_LEN))
  1007. {
  1008. return (rc);
  1009. }
  1010. RtlInitUnicodeString(&ObSecName, wszSecName);
  1011. }
  1012. (*pGetLinguistLangSize)(&Size);
  1013. break;
  1014. }
  1015. default:
  1016. return (STATUS_INVALID_PARAMETER);
  1017. }
  1018. if (pFile)
  1019. {
  1020. //
  1021. // Open the data file.
  1022. //
  1023. ASSERT(pOpenDataFile != NULL);
  1024. if (rc = (*pOpenDataFile)( &hFile,
  1025. pFile ))
  1026. {
  1027. return (rc);
  1028. }
  1029. }
  1030. //
  1031. // Create the NEW Section for Read and Write access.
  1032. // Add a ReadOnly security descriptor so that only the
  1033. // initial creating process may write to the section.
  1034. //
  1035. ASSERT(pCreateNlsSecurityDescriptor);
  1036. rc = (*pCreateNlsSecurityDescriptor)( (PSECURITY_DESCRIPTOR)pSecurityDescriptor,
  1037. MAX_SMALL_SECURITY_DESCRIPTOR,
  1038. GENERIC_READ);
  1039. if (!NT_SUCCESS(rc))
  1040. {
  1041. if (hFile)
  1042. NtClose(hFile);
  1043. return (rc);
  1044. }
  1045. InitializeObjectAttributes( &ObjA,
  1046. &ObSecName,
  1047. OBJ_PERMANENT | OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
  1048. NULL,
  1049. pSecurityDescriptor );
  1050. rc = NtCreateSection( &hNewSec,
  1051. hFile ? SECTION_MAP_READ : SECTION_MAP_READ | SECTION_MAP_WRITE,
  1052. &ObjA,
  1053. hFile? NULL:&Size,
  1054. hFile ? PAGE_READONLY:PAGE_READWRITE,
  1055. SEC_COMMIT,
  1056. hFile );
  1057. NtClose(hFile);
  1058. //
  1059. // Check for error from NtCreateSection.
  1060. //
  1061. if (!NT_SUCCESS(rc))
  1062. {
  1063. // KdPrint(("NLSAPI (BaseSrv): Could NOT Create Section %wZ - %lx.\n", &ObSecName, rc));
  1064. return (rc);
  1065. }
  1066. //
  1067. // Duplicate the new section handle for the client.
  1068. // The client will map a view of the section and fill in the data.
  1069. //
  1070. InitializeObjectAttributes( &ObjA,
  1071. NULL,
  1072. 0,
  1073. NULL,
  1074. NULL );
  1075. rc = NtOpenProcess( &hProcess,
  1076. PROCESS_DUP_HANDLE,
  1077. &ObjA,
  1078. &m->h.ClientId );
  1079. if (!NT_SUCCESS(rc))
  1080. {
  1081. KdPrint(("NLSAPI (BaseSrv): Could NOT Open Process - %lx.\n", rc));
  1082. NtClose(hNewSec);
  1083. return (rc);
  1084. }
  1085. rc = NtDuplicateObject( NtCurrentProcess(),
  1086. hNewSec,
  1087. hProcess,
  1088. &(a->hNewSection),
  1089. 0L,
  1090. 0L,
  1091. DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE );
  1092. //
  1093. // Close the process handle we opened.
  1094. //
  1095. NtClose(hProcess);
  1096. return (rc);
  1097. ReplyStatus; // get rid of unreferenced parameter warning message
  1098. }
  1099. ////////////////////////////////////////////////////////////////////////////
  1100. //
  1101. // GetThreadAuthenticationId
  1102. //
  1103. // Retreives the authentication id of the security context of the
  1104. // currently executing thread.
  1105. //
  1106. // 12-22-98 SamerA Created.
  1107. ////////////////////////////////////////////////////////////////////////////
  1108. NTSTATUS GetThreadAuthenticationId(
  1109. PLUID Luid)
  1110. {
  1111. HANDLE TokenHandle;
  1112. TOKEN_STATISTICS TokenInformation;
  1113. ULONG BytesRequired;
  1114. NTSTATUS NtStatus;
  1115. NtStatus = NtOpenThreadToken( NtCurrentThread(),
  1116. TOKEN_QUERY,
  1117. FALSE,
  1118. &TokenHandle );
  1119. if (!NT_SUCCESS(NtStatus))
  1120. {
  1121. KdPrint(("NLSAPI (BaseSrv) : No thread token in BaseSrvNlsLogon - %lx\n", NtStatus));
  1122. return (NtStatus);
  1123. }
  1124. //
  1125. // Get the LUID.
  1126. //
  1127. NtStatus = NtQueryInformationToken(
  1128. TokenHandle,
  1129. TokenStatistics,
  1130. &TokenInformation,
  1131. sizeof(TokenInformation),
  1132. &BytesRequired );
  1133. if (NT_SUCCESS( NtStatus ))
  1134. {
  1135. RtlCopyLuid(Luid, &TokenInformation.AuthenticationId);
  1136. }
  1137. else
  1138. {
  1139. KdPrint(("NLSAPI (BaseSrv) : Couldn't Query Information for Token %lx. NtStatus = %lx\n", TokenHandle, NtStatus));
  1140. }
  1141. NtClose(TokenHandle);
  1142. return (NtStatus);
  1143. }