Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1190 lines
32 KiB

  1. /*++
  2. Copyright (c) 1991-2000, Microsoft Corporation All rights reserved.
  3. Module Name:
  4. section.c
  5. Abstract:
  6. This file contains functions that deal with creating, opening, or
  7. mapping a section for data table files for the NLS API.
  8. External Routines found in this file:
  9. CreateNlsObjectDirectory
  10. CreateRegKey
  11. OpenRegKey
  12. QueryRegValue
  13. SetRegValue
  14. CreateSectionFromReg
  15. CreateSectionOneValue
  16. CreateSectionTemp
  17. OpenSection
  18. MapSection
  19. UnMapSection
  20. GetNlsSectionName
  21. GetCodePageDLLPathName
  22. Revision History:
  23. 05-31-91 JulieB Created.
  24. --*/
  25. //
  26. // Include Files.
  27. //
  28. #include "nls.h"
  29. //
  30. // Forward Declarations.
  31. //
  32. ULONG
  33. OpenDataFile(
  34. HANDLE *phFile,
  35. LPWSTR pFile);
  36. ULONG
  37. GetNTFileName(
  38. LPWSTR pFile,
  39. PUNICODE_STRING pFileName);
  40. ULONG
  41. CreateNlsSecurityDescriptor(
  42. PSECURITY_DESCRIPTOR pSecurityDescriptor,
  43. UINT SecurityDescriptorSize,
  44. ACCESS_MASK AccessMask);
  45. ULONG
  46. AppendAccessAllowedACE(
  47. PSECURITY_DESCRIPTOR pSecurityDescriptor,
  48. ACCESS_MASK AccessMask);
  49. //-------------------------------------------------------------------------//
  50. // INTERNAL MACROS //
  51. //-------------------------------------------------------------------------//
  52. ////////////////////////////////////////////////////////////////////////////
  53. //
  54. // NLS_REG_BUFFER_ALLOC
  55. //
  56. // Allocates the buffer used by the registry enumeration and query calls
  57. // and sets the pKeyValueFull variable to point at the newly created buffer.
  58. //
  59. // NOTE: This macro may return if an error is encountered.
  60. //
  61. // DEFINED AS A MACRO.
  62. //
  63. // 05-31-91 JulieB Created.
  64. ////////////////////////////////////////////////////////////////////////////
  65. #define NLS_REG_BUFFER_ALLOC( pKeyValueFull, \
  66. BufSize, \
  67. pBuffer, \
  68. CritSect ) \
  69. { \
  70. if ((pBuffer = (PVOID)NLS_ALLOC_MEM(BufSize)) == NULL) \
  71. { \
  72. KdPrint(("NLSAPI: Could NOT Allocate Memory.\n")); \
  73. if (CritSect) \
  74. { \
  75. RtlLeaveCriticalSection(&gcsTblPtrs); \
  76. } \
  77. return ((ULONG)STATUS_NO_MEMORY); \
  78. } \
  79. \
  80. pKeyValueFull = (PKEY_VALUE_FULL_INFORMATION)pBuffer; \
  81. }
  82. ////////////////////////////////////////////////////////////////////////////
  83. //
  84. // NLS_REG_BUFFER_FREE
  85. //
  86. // Frees the buffer used by the registry enumeration and query calls.
  87. //
  88. // DEFINED AS A MACRO.
  89. //
  90. // 05-31-91 JulieB Created.
  91. ////////////////////////////////////////////////////////////////////////////
  92. #define NLS_REG_BUFFER_FREE(pBuffer) (NLS_FREE_MEM(pBuffer))
  93. //-------------------------------------------------------------------------//
  94. // EXTERNAL ROUTINES //
  95. //-------------------------------------------------------------------------//
  96. ////////////////////////////////////////////////////////////////////////////
  97. //
  98. // CreateNlsObjectDirectory
  99. //
  100. // This routine creates the object directory for the NLS memory mapped
  101. // sections.
  102. //
  103. // 05-31-91 JulieB Created.
  104. ////////////////////////////////////////////////////////////////////////////
  105. ULONG CreateNlsObjectDirectory()
  106. {
  107. BYTE pSecurityDescriptor[MAX_SECURITY_BUF_LEN]; // security descriptor buffer (currently we use like 60 bytes or so of this)
  108. UNICODE_STRING ObDirName; // directory name
  109. OBJECT_ATTRIBUTES ObjA; // object attributes structure
  110. HANDLE hDirHandle; // directory handle
  111. ULONG rc = 0L; // return code
  112. //
  113. // Create the security descriptor with READ access to the world.
  114. //
  115. rc = CreateNlsSecurityDescriptor( pSecurityDescriptor,
  116. MAX_SECURITY_BUF_LEN,
  117. DIRECTORY_QUERY | DIRECTORY_TRAVERSE );
  118. if (!NT_SUCCESS(rc))
  119. {
  120. return (rc);
  121. }
  122. //
  123. // Add Admin Access for Query.
  124. //
  125. rc = AppendAccessAllowedACE( pSecurityDescriptor,
  126. DIRECTORY_QUERY |
  127. DIRECTORY_TRAVERSE |
  128. DIRECTORY_CREATE_OBJECT );
  129. if (!NT_SUCCESS(rc))
  130. {
  131. return (rc);
  132. }
  133. //
  134. // Create the object directory.
  135. //
  136. RtlInitUnicodeString(&ObDirName, NLS_OBJECT_DIRECTORY_NAME);
  137. InitializeObjectAttributes( &ObjA,
  138. &ObDirName,
  139. OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
  140. NULL,
  141. pSecurityDescriptor );
  142. rc = NtCreateDirectoryObject( &hDirHandle,
  143. DIRECTORY_TRAVERSE | DIRECTORY_CREATE_OBJECT,
  144. &ObjA );
  145. //
  146. // Close the directory handle.
  147. //
  148. NtClose(hDirHandle);
  149. //
  150. // Check for error from NtCreateDirectoryObject.
  151. //
  152. if (!NT_SUCCESS(rc))
  153. {
  154. KdPrint(("NLSAPI: Could NOT Create Object Directory %wZ - %lx.\n",
  155. &ObDirName, rc));
  156. return (rc);
  157. }
  158. //
  159. // Return success.
  160. //
  161. return (NO_ERROR);
  162. }
  163. ////////////////////////////////////////////////////////////////////////////
  164. //
  165. // CreateRegKey
  166. //
  167. // This routine creates a key in the registry.
  168. //
  169. // 12-17-97 JulieB Created.
  170. ////////////////////////////////////////////////////////////////////////////
  171. ULONG CreateRegKey(
  172. PHANDLE phKeyHandle,
  173. LPWSTR pBaseName,
  174. LPWSTR pKey,
  175. ULONG fAccess)
  176. {
  177. WCHAR pwszKeyName[MAX_PATH_LEN]; // ptr to the full key name
  178. HANDLE UserKeyHandle; // HKEY_CURRENT_USER equivalent
  179. OBJECT_ATTRIBUTES ObjA; // object attributes structure
  180. UNICODE_STRING ObKeyName; // key name
  181. ULONG rc = 0L; // return code
  182. //
  183. // Get the full key name.
  184. //
  185. if (pBaseName == NULL)
  186. {
  187. //
  188. // Get current user's key handle.
  189. //
  190. rc = RtlOpenCurrentUser(MAXIMUM_ALLOWED, &UserKeyHandle);
  191. if (!NT_SUCCESS(rc))
  192. {
  193. KdPrint(("NLSAPI: Could NOT Open HKEY_CURRENT_USER - %lx.\n", rc));
  194. return (rc);
  195. }
  196. pwszKeyName[0] = UNICODE_NULL;
  197. }
  198. else
  199. {
  200. //
  201. // Base name exists, so not current user.
  202. //
  203. UserKeyHandle = NULL;
  204. NlsStrCpyW(pwszKeyName, pBaseName);
  205. }
  206. NlsStrCatW(pwszKeyName, pKey);
  207. //
  208. // Create the registry key.
  209. //
  210. RtlInitUnicodeString(&ObKeyName, pwszKeyName);
  211. InitializeObjectAttributes( &ObjA,
  212. &ObKeyName,
  213. OBJ_CASE_INSENSITIVE,
  214. UserKeyHandle,
  215. NULL );
  216. rc = NtCreateKey( phKeyHandle,
  217. fAccess,
  218. &ObjA,
  219. 0,
  220. NULL,
  221. REG_OPTION_NON_VOLATILE,
  222. NULL );
  223. //
  224. // Close the current user handle, if necessary.
  225. //
  226. if (UserKeyHandle != NULL)
  227. {
  228. NtClose(UserKeyHandle);
  229. }
  230. //
  231. // Check for error from NtCreateKey.
  232. //
  233. if (!NT_SUCCESS(rc))
  234. {
  235. *phKeyHandle = NULL;
  236. }
  237. //
  238. // Return the status from NtCreateKey.
  239. //
  240. return (rc);
  241. }
  242. ////////////////////////////////////////////////////////////////////////////
  243. //
  244. // OpenRegKey
  245. //
  246. // This routine opens a key in the registry.
  247. //
  248. // 08-02-93 JulieB Created.
  249. ////////////////////////////////////////////////////////////////////////////
  250. ULONG OpenRegKey(
  251. PHANDLE phKeyHandle,
  252. LPWSTR pBaseName,
  253. LPWSTR pKey,
  254. ULONG fAccess)
  255. {
  256. WCHAR pwszKeyName[MAX_PATH_LEN]; // ptr to the full key name
  257. HANDLE UserKeyHandle; // HKEY_CURRENT_USER equivalent
  258. OBJECT_ATTRIBUTES ObjA; // object attributes structure
  259. UNICODE_STRING ObKeyName; // key name
  260. ULONG rc = 0L; // return code
  261. //
  262. // Get the full key name.
  263. //
  264. if (pBaseName == NULL)
  265. {
  266. //
  267. // Get current user's key handle.
  268. //
  269. rc = RtlOpenCurrentUser(MAXIMUM_ALLOWED, &UserKeyHandle);
  270. if (!NT_SUCCESS(rc))
  271. {
  272. KdPrint(("NLSAPI: Could NOT Open HKEY_CURRENT_USER - %lx.\n", rc));
  273. return (rc);
  274. }
  275. pwszKeyName[0] = UNICODE_NULL;
  276. }
  277. else
  278. {
  279. //
  280. // Base name exists, so not current user.
  281. //
  282. UserKeyHandle = NULL;
  283. NlsStrCpyW(pwszKeyName, pBaseName);
  284. }
  285. if (pKey)
  286. {
  287. NlsStrCatW(pwszKeyName, pKey);
  288. }
  289. //
  290. // Open the registry key.
  291. //
  292. RtlInitUnicodeString(&ObKeyName, pwszKeyName);
  293. InitializeObjectAttributes( &ObjA,
  294. &ObKeyName,
  295. OBJ_CASE_INSENSITIVE,
  296. UserKeyHandle,
  297. NULL );
  298. rc = NtOpenKey( phKeyHandle,
  299. fAccess,
  300. &ObjA );
  301. //
  302. // Close the current user handle, if necessary.
  303. //
  304. if (UserKeyHandle != NULL)
  305. {
  306. NtClose(UserKeyHandle);
  307. }
  308. //
  309. // Check for error from NtOpenKey.
  310. //
  311. if (!NT_SUCCESS(rc))
  312. {
  313. *phKeyHandle = NULL;
  314. }
  315. //
  316. // Return the status from NtOpenKey.
  317. //
  318. return (rc);
  319. }
  320. ////////////////////////////////////////////////////////////////////////////
  321. //
  322. // QueryRegValue
  323. //
  324. // This routine queries the given value from the registry.
  325. //
  326. // NOTE: If pIfAlloc is NULL, then no buffer will be allocated.
  327. // If this routine is successful, the CALLER must free the
  328. // ppKeyValueFull information buffer if *pIfAlloc is TRUE.
  329. //
  330. // 05-31-91 JulieB Created.
  331. ////////////////////////////////////////////////////////////////////////////
  332. ULONG QueryRegValue(
  333. HANDLE hKeyHandle,
  334. LPWSTR pValue,
  335. PKEY_VALUE_FULL_INFORMATION *ppKeyValueFull,
  336. ULONG Length,
  337. LPBOOL pIfAlloc)
  338. {
  339. UNICODE_STRING ObValueName; // value name
  340. PVOID pBuffer; // ptr to buffer for enum
  341. ULONG ResultLength; // # bytes written
  342. ULONG rc = 0L; // return code
  343. //
  344. // Set contents of pIfAlloc to FALSE to show that we did NOT do a
  345. // memory allocation (yet).
  346. //
  347. if (pIfAlloc)
  348. {
  349. *pIfAlloc = FALSE;
  350. }
  351. //
  352. // Query the value from the registry.
  353. //
  354. RtlInitUnicodeString(&ObValueName, pValue);
  355. RtlZeroMemory(*ppKeyValueFull, Length);
  356. rc = NtQueryValueKey( hKeyHandle,
  357. &ObValueName,
  358. KeyValueFullInformation,
  359. *ppKeyValueFull,
  360. Length,
  361. &ResultLength );
  362. //
  363. // Check the error code. If the buffer is too small, allocate
  364. // a new one and try the query again.
  365. //
  366. if ((rc == STATUS_BUFFER_OVERFLOW) && (pIfAlloc))
  367. {
  368. //
  369. // Buffer is too small, so allocate a new one.
  370. //
  371. NLS_REG_BUFFER_ALLOC(*ppKeyValueFull, ResultLength, pBuffer, FALSE);
  372. RtlZeroMemory(*ppKeyValueFull, ResultLength);
  373. rc = NtQueryValueKey( hKeyHandle,
  374. &ObValueName,
  375. KeyValueFullInformation,
  376. *ppKeyValueFull,
  377. ResultLength,
  378. &ResultLength );
  379. //
  380. // Set contents of pIfAlloc to TRUE to show that we DID do
  381. // a memory allocation.
  382. //
  383. *pIfAlloc = TRUE;
  384. }
  385. //
  386. // If there is an error at this point, then the query failed.
  387. //
  388. if (rc != NO_ERROR)
  389. {
  390. if ((pIfAlloc) && (*pIfAlloc))
  391. {
  392. NLS_REG_BUFFER_FREE(pBuffer);
  393. }
  394. return (rc);
  395. }
  396. //
  397. // Return success.
  398. //
  399. return (NO_ERROR);
  400. }
  401. ////////////////////////////////////////////////////////////////////////////
  402. //
  403. // SetRegValue
  404. //
  405. // This routine sets the given value in the registry.
  406. //
  407. // 12-17-97 JulieB Created.
  408. ////////////////////////////////////////////////////////////////////////////
  409. ULONG SetRegValue(
  410. HANDLE hKeyHandle,
  411. LPCWSTR pValue,
  412. LPCWSTR pData,
  413. ULONG DataLength)
  414. {
  415. UNICODE_STRING ObValueName; // value name
  416. //
  417. // Set the value in the registry.
  418. //
  419. RtlInitUnicodeString(&ObValueName, pValue);
  420. return (NtSetValueKey( hKeyHandle,
  421. &ObValueName,
  422. 0,
  423. REG_SZ,
  424. (PVOID)pData,
  425. DataLength ));
  426. }
  427. ////////////////////////////////////////////////////////////////////////////
  428. //
  429. // CreateSectionTemp
  430. //
  431. // This routine creates a temporary memory mapped section for the given file
  432. // name and returns the handle to the section.
  433. //
  434. // 09-01-93 JulieB Created.
  435. ////////////////////////////////////////////////////////////////////////////
  436. ULONG CreateSectionTemp(
  437. HANDLE *phSec,
  438. LPWSTR pwszFileName)
  439. {
  440. HANDLE hFile = (HANDLE)0; // file handle
  441. OBJECT_ATTRIBUTES ObjA; // object attributes structure
  442. ULONG rc = 0L; // return code
  443. //
  444. // Make sure we're in the critical section when entering this call.
  445. //
  446. ASSERT(NtCurrentTeb()->ClientId.UniqueThread == gcsTblPtrs.OwningThread);
  447. //
  448. // Open the data file.
  449. //
  450. if (rc = OpenDataFile( &hFile,
  451. pwszFileName ))
  452. {
  453. return (rc);
  454. }
  455. //
  456. // Create the section.
  457. //
  458. InitializeObjectAttributes( &ObjA,
  459. NULL,
  460. 0,
  461. NULL,
  462. NULL );
  463. rc = NtCreateSection( phSec,
  464. SECTION_MAP_READ,
  465. &ObjA,
  466. NULL,
  467. PAGE_READONLY,
  468. SEC_COMMIT,
  469. hFile );
  470. //
  471. // Close the file.
  472. //
  473. NtClose(hFile);
  474. //
  475. // Check for error from NtCreateSection.
  476. //
  477. if (!NT_SUCCESS(rc))
  478. {
  479. KdPrint(("NLSAPI: Could NOT Create Temp Section for %ws - %lx.\n",
  480. pwszFileName, rc));
  481. }
  482. //
  483. // Return success.
  484. //
  485. return (rc);
  486. }
  487. ////////////////////////////////////////////////////////////////////////////
  488. //
  489. // OpenSection
  490. //
  491. // This routine opens the named memory mapped section for the given section
  492. // name and returns the handle to the section.
  493. //
  494. // 05-31-91 JulieB Created.
  495. ////////////////////////////////////////////////////////////////////////////
  496. ULONG OpenSection(
  497. HANDLE *phSec,
  498. PUNICODE_STRING pObSectionName,
  499. PVOID *ppBaseAddr,
  500. ULONG AccessMask,
  501. BOOL bCloseHandle)
  502. {
  503. OBJECT_ATTRIBUTES ObjA; // object attributes structure
  504. ULONG rc = 0L; // return code
  505. //
  506. // Make sure we're in the critical section when entering this call.
  507. //
  508. ASSERT(NtCurrentTeb()->ClientId.UniqueThread == gcsTblPtrs.OwningThread);
  509. //
  510. // Open the Section.
  511. //
  512. InitializeObjectAttributes( &ObjA,
  513. pObSectionName,
  514. OBJ_CASE_INSENSITIVE,
  515. NULL,
  516. NULL );
  517. rc = NtOpenSection( phSec,
  518. AccessMask,
  519. &ObjA );
  520. //
  521. // Check for error from NtOpenSection.
  522. //
  523. if (!NT_SUCCESS(rc))
  524. {
  525. return (rc);
  526. }
  527. //
  528. // Map a View of the Section.
  529. //
  530. if (rc = MapSection( *phSec,
  531. ppBaseAddr,
  532. PAGE_READONLY,
  533. FALSE ))
  534. {
  535. NtClose(*phSec);
  536. return (rc);
  537. }
  538. //
  539. // Close the handle to the section. Once the section has been mapped,
  540. // the pointer to the base address will remain valid until the section
  541. // is unmapped. It is not necessary to leave the handle to the section
  542. // around.
  543. //
  544. if (bCloseHandle)
  545. {
  546. NtClose(*phSec);
  547. }
  548. //
  549. // Return success.
  550. //
  551. return (NO_ERROR);
  552. }
  553. ////////////////////////////////////////////////////////////////////////////
  554. //
  555. // MapSection
  556. //
  557. // This routine maps a view of the section to the current process and adds
  558. // the appropriate information to the hash table.
  559. //
  560. // 05-31-91 JulieB Created.
  561. ////////////////////////////////////////////////////////////////////////////
  562. ULONG MapSection(
  563. HANDLE hSec,
  564. PVOID *ppBaseAddr,
  565. ULONG PageProtection,
  566. BOOL bCloseHandle)
  567. {
  568. SIZE_T ViewSize; // view size of mapped section
  569. ULONG rc = 0L; // return code
  570. //
  571. // Make sure we're in the critical section when entering this call.
  572. //
  573. ASSERT(NtCurrentTeb()->ClientId.UniqueThread == gcsTblPtrs.OwningThread);
  574. //
  575. // Map a View of the Section.
  576. //
  577. *ppBaseAddr = (PVOID)NULL;
  578. ViewSize = 0L;
  579. rc = NtMapViewOfSection( hSec,
  580. NtCurrentProcess(),
  581. ppBaseAddr,
  582. 0L,
  583. 0L,
  584. NULL,
  585. &ViewSize,
  586. ViewUnmap,
  587. 0L,
  588. PageProtection );
  589. //
  590. // Close the handle to the section. Once the section has been mapped,
  591. // the pointer to the base address will remain valid until the section
  592. // is unmapped. It is not necessary to leave the handle to the section
  593. // around.
  594. //
  595. if (bCloseHandle)
  596. {
  597. NtClose(hSec);
  598. }
  599. //
  600. // Check for error from NtMapViewOfSection.
  601. //
  602. if (!NT_SUCCESS(rc))
  603. {
  604. KdPrint(("NLSAPI: Could NOT Map View of Section - %lx.\n", rc));
  605. return (rc);
  606. }
  607. //
  608. // Return success.
  609. //
  610. return (NO_ERROR);
  611. }
  612. ////////////////////////////////////////////////////////////////////////////
  613. //
  614. // UnMapSection
  615. //
  616. // This routine unmaps a view of the given section to the current process.
  617. //
  618. // 05-31-91 JulieB Created.
  619. ////////////////////////////////////////////////////////////////////////////
  620. ULONG UnMapSection(
  621. PVOID pBaseAddr)
  622. {
  623. ULONG rc = 0L; // return code
  624. //
  625. // Make sure we're in the critical section when entering this call.
  626. //
  627. ASSERT(NtCurrentTeb()->ClientId.UniqueThread == gcsTblPtrs.OwningThread);
  628. //
  629. // UnMap a View of the Section.
  630. //
  631. rc = NtUnmapViewOfSection( NtCurrentProcess(),
  632. pBaseAddr );
  633. //
  634. // Check for error from NtUnmapViewOfSection.
  635. //
  636. if (!NT_SUCCESS(rc))
  637. {
  638. KdPrint(("NLSAPI: Could NOT Unmap View of Section - %lx.\n", rc));
  639. return (rc);
  640. }
  641. //
  642. // Return success.
  643. //
  644. return (NO_ERROR);
  645. }
  646. ////////////////////////////////////////////////////////////////////////////
  647. //
  648. // GetNlsSectionName
  649. //
  650. // This routine returns a section name by concatenating the given
  651. // section prefix and the given integer value converted to a string.
  652. //
  653. // 05-31-1991 JulieB Created.
  654. // 06-04-2002 ShawnSte Added more security
  655. ////////////////////////////////////////////////////////////////////////////
  656. ULONG GetNlsSectionName(
  657. UINT Value,
  658. UINT Base,
  659. UINT Padding,
  660. LPWSTR pwszPrefix,
  661. LPWSTR pwszSecName,
  662. UINT cchSecName)
  663. {
  664. size_t cchUsed;
  665. //
  666. // Create section name string.
  667. //
  668. NlsStrCpyW(pwszSecName, pwszPrefix);
  669. // See how much we used already
  670. cchUsed = NlsStrLenW(pwszPrefix);
  671. // Now convert the number, passing along the used buffer length
  672. return ( NlsConvertIntegerToString( Value,
  673. Base,
  674. Padding,
  675. pwszSecName + NlsStrLenW(pwszSecName),
  676. cchSecName - cchUsed )); // Some characters are already used
  677. }
  678. ////////////////////////////////////////////////////////////////////////////
  679. //
  680. // GetCodePageDLLPathName
  681. //
  682. // This routine returns the full path name for the DLL file found in
  683. // the CodePage section of the registry for the given code page value.
  684. //
  685. // 10-23-96 JulieB Created.
  686. ////////////////////////////////////////////////////////////////////////////
  687. ULONG GetCodePageDLLPathName(
  688. UINT CodePage,
  689. LPWSTR pDllName,
  690. USHORT cchLen)
  691. {
  692. WCHAR pTmpBuf[MAX_SMALL_BUF_LEN]; // temp buffer
  693. PKEY_VALUE_FULL_INFORMATION pKeyValueFull; // ptr to query info
  694. BYTE pStatic[MAX_KEY_VALUE_FULLINFO]; // ptr to static buffer
  695. BOOL IfAlloc = FALSE; // if buffer was allocated
  696. ULONG rc = 0L; // return code
  697. //
  698. // Open the CodePage registry key.
  699. //
  700. OPEN_CODEPAGE_KEY(ERROR_BADDB);
  701. //
  702. // Convert the code page value to a unicode string.
  703. //
  704. if (rc = NlsConvertIntegerToString( CodePage,
  705. 10,
  706. 0,
  707. pTmpBuf,
  708. MAX_SMALL_BUF_LEN ))
  709. {
  710. return (rc);
  711. }
  712. //
  713. // Query the registry for the code page value.
  714. //
  715. pKeyValueFull = (PKEY_VALUE_FULL_INFORMATION)pStatic;
  716. if (rc = QueryRegValue( hCodePageKey,
  717. pTmpBuf,
  718. &pKeyValueFull,
  719. MAX_KEY_VALUE_FULLINFO,
  720. &IfAlloc ))
  721. {
  722. return (rc);
  723. }
  724. //
  725. // Make sure there is data with this value.
  726. //
  727. if (pKeyValueFull->DataLength > 2)
  728. {
  729. //
  730. // Get the full path name for the DLL file.
  731. //
  732. GetSystemDirectoryW(pDllName, cchLen / 2);
  733. NlsStrCatW(pDllName, L"\\");
  734. NlsStrCatW(pDllName, GET_VALUE_DATA_PTR(pKeyValueFull));
  735. }
  736. else
  737. {
  738. rc = ERROR_INVALID_PARAMETER;
  739. }
  740. //
  741. // Free the buffer used for the query.
  742. //
  743. if (IfAlloc)
  744. {
  745. NLS_FREE_MEM(pKeyValueFull);
  746. }
  747. //
  748. // Return.
  749. //
  750. return (rc);
  751. }
  752. //-------------------------------------------------------------------------//
  753. // INTERNAL ROUTINES //
  754. //-------------------------------------------------------------------------//
  755. ////////////////////////////////////////////////////////////////////////////
  756. //
  757. // OpenDataFile
  758. //
  759. // This routine opens the data file for the specified file name and
  760. // returns the handle to the file.
  761. //
  762. // 05-31-91 JulieB Created.
  763. ////////////////////////////////////////////////////////////////////////////
  764. ULONG OpenDataFile(
  765. HANDLE *phFile,
  766. LPWSTR pFile)
  767. {
  768. UNICODE_STRING ObFileName; // file name
  769. OBJECT_ATTRIBUTES ObjA; // object attributes structure
  770. IO_STATUS_BLOCK iosb; // IO status block
  771. ULONG rc = 0L; // return code
  772. //
  773. // Get the NT file name.
  774. //
  775. if (rc = GetNTFileName( pFile,
  776. &ObFileName ))
  777. {
  778. return (rc);
  779. }
  780. //
  781. // Open the file.
  782. //
  783. InitializeObjectAttributes( &ObjA,
  784. &ObFileName,
  785. OBJ_CASE_INSENSITIVE,
  786. NULL,
  787. NULL );
  788. rc = NtOpenFile( phFile,
  789. FILE_READ_DATA | SYNCHRONIZE,
  790. &ObjA,
  791. &iosb,
  792. FILE_SHARE_READ,
  793. FILE_SYNCHRONOUS_IO_NONALERT );
  794. //
  795. // Check for error from NtOpenFile.
  796. //
  797. if (!NT_SUCCESS(rc))
  798. {
  799. KdPrint(("NLSAPI: Could NOT Open File %wZ - %lx.\n", &ObFileName, rc));
  800. RtlFreeHeap(RtlProcessHeap(), 0, ObFileName.Buffer);
  801. return (rc);
  802. }
  803. if (!NT_SUCCESS(iosb.Status))
  804. {
  805. KdPrint(("NLSAPI: Could NOT Open File %wZ - Status = %lx.\n",
  806. &ObFileName, iosb.Status));
  807. RtlFreeHeap(RtlProcessHeap(), 0, ObFileName.Buffer);
  808. return ((ULONG)iosb.Status);
  809. }
  810. //
  811. // Return success.
  812. //
  813. RtlFreeHeap(RtlProcessHeap(), 0, ObFileName.Buffer);
  814. return (NO_ERROR);
  815. }
  816. ////////////////////////////////////////////////////////////////////////////
  817. //
  818. // GetNTFileName
  819. //
  820. // This routine returns the full path name for the data file found in
  821. // the given registry information buffer.
  822. //
  823. // NOTE: The pFileName parameter will contain a newly allocated buffer
  824. // that must be freed by the caller (pFileName->buffer).
  825. //
  826. // 05-31-91 JulieB Created.
  827. ////////////////////////////////////////////////////////////////////////////
  828. ULONG GetNTFileName(
  829. LPWSTR pFile,
  830. PUNICODE_STRING pFileName)
  831. {
  832. WCHAR pwszFilePath[MAX_PATH_LEN]; // ptr to file path string
  833. UNICODE_STRING ObFileName; // file name
  834. ULONG rc = 0L; // return code
  835. //
  836. // Get the full path name for the file.
  837. //
  838. pwszFilePath[0] = L'\0';
  839. GetSystemDirectoryW(pwszFilePath, MAX_PATH_LEN);
  840. NlsStrCatW(pwszFilePath, L"\\");
  841. NlsStrCatW(pwszFilePath, pFile);
  842. //
  843. // Make the file name an NT path name.
  844. //
  845. RtlInitUnicodeString(&ObFileName, pwszFilePath);
  846. if (!RtlDosPathNameToNtPathName_U( ObFileName.Buffer,
  847. pFileName,
  848. NULL,
  849. NULL ))
  850. {
  851. KdPrint(("NLSAPI: Could NOT convert %wZ to NT path name - %lx.\n",
  852. &ObFileName, rc));
  853. return (ERROR_FILE_NOT_FOUND);
  854. }
  855. //
  856. // Return success.
  857. //
  858. return (NO_ERROR);
  859. }
  860. ////////////////////////////////////////////////////////////////////////////
  861. //
  862. // CreateNlsSecurityDescriptor
  863. //
  864. // This routine creates the security descriptor needed to create the
  865. // memory mapped section for a data file and returns the world SID.
  866. //
  867. // 05-31-91 JulieB Created.
  868. ////////////////////////////////////////////////////////////////////////////
  869. ULONG CreateNlsSecurityDescriptor(
  870. PSECURITY_DESCRIPTOR pSecurityDescriptor,
  871. UINT SecurityDescriptorSize,
  872. ACCESS_MASK AccessMask)
  873. {
  874. ULONG rc = STATUS_SUCCESS; // return code (positive thinking)
  875. PACL pAclBuffer; // ptr to ACL buffer
  876. PSID pWorldSid = NULL; // ptr to world SID
  877. SID_IDENTIFIER_AUTHORITY SidAuth = SECURITY_WORLD_SID_AUTHORITY;
  878. //
  879. // Create World SID.
  880. //
  881. rc = RtlAllocateAndInitializeSid( &SidAuth,
  882. 1,
  883. SECURITY_WORLD_RID,
  884. 0, 0, 0, 0, 0, 0, 0,
  885. &pWorldSid );
  886. if (!NT_SUCCESS(rc))
  887. {
  888. KdPrint(("NLSAPI: Could NOT Create SID - %lx.\n", rc));
  889. goto CSD_Exit;
  890. }
  891. //
  892. // Initialize Security Descriptor.
  893. //
  894. rc = RtlCreateSecurityDescriptor( pSecurityDescriptor,
  895. SECURITY_DESCRIPTOR_REVISION );
  896. if (!NT_SUCCESS(rc))
  897. {
  898. KdPrint(("NLSAPI: Could NOT Create Security Descriptor - %lx.\n", rc));
  899. goto CSD_Exit;
  900. }
  901. //
  902. // Initialize ACL.
  903. //
  904. pAclBuffer = (PACL)((PBYTE)pSecurityDescriptor + SECURITY_DESCRIPTOR_MIN_LENGTH);
  905. rc = RtlCreateAcl( (PACL)pAclBuffer,
  906. SecurityDescriptorSize - SECURITY_DESCRIPTOR_MIN_LENGTH,
  907. ACL_REVISION2 );
  908. if (!NT_SUCCESS(rc))
  909. {
  910. KdPrint(("NLSAPI: Could NOT Create ACL - %lx.\n", rc));
  911. goto CSD_Exit;
  912. }
  913. //
  914. // Add an ACE to the ACL that allows World GENERIC_READ to the
  915. // section object.
  916. //
  917. rc = RtlAddAccessAllowedAce( (PACL)pAclBuffer,
  918. ACL_REVISION2,
  919. AccessMask,
  920. pWorldSid );
  921. if (!NT_SUCCESS(rc))
  922. {
  923. KdPrint(("NLSAPI: Could NOT Add Access Allowed ACE - %lx.\n", rc));
  924. goto CSD_Exit;
  925. }
  926. //
  927. // Assign the DACL to the security descriptor.
  928. //
  929. rc = RtlSetDaclSecurityDescriptor( (PSECURITY_DESCRIPTOR)pSecurityDescriptor,
  930. (BOOLEAN)TRUE,
  931. (PACL)pAclBuffer,
  932. (BOOLEAN)FALSE );
  933. if (!NT_SUCCESS(rc))
  934. {
  935. KdPrint(("NLSAPI: Could NOT Set DACL Security Descriptor - %lx.\n", rc));
  936. goto CSD_Exit;
  937. }
  938. CSD_Exit:
  939. //
  940. // Free the Sid.
  941. //
  942. if (pWorldSid) RtlFreeHeap(RtlProcessHeap(), 0, pWorldSid);
  943. //
  944. // Return the result.
  945. //
  946. return (rc);
  947. }
  948. ////////////////////////////////////////////////////////////////////////////
  949. //
  950. // AppendAccessAllowedACE
  951. //
  952. // This routine adds an ACE to the ACL for administrators.
  953. //
  954. // 03-08-93 JulieB Created.
  955. ////////////////////////////////////////////////////////////////////////////
  956. ULONG AppendAccessAllowedACE(
  957. PSECURITY_DESCRIPTOR pSecurityDescriptor,
  958. ACCESS_MASK AccessMask)
  959. {
  960. ULONG rc = STATUS_SUCCESS; // return code (positive thinking)
  961. PACL pDaclBuffer; // ptr to DACL buffer
  962. ULONG SidLength; // length of SID - 2 sub authorities
  963. PSID pLocalSystemSid = NULL; // ptr to local system SID
  964. SID_IDENTIFIER_AUTHORITY SidAuth = SECURITY_NT_AUTHORITY;
  965. BOOLEAN DaclPresent;
  966. BOOLEAN DaclDefaulted;
  967. //
  968. // Create Local System Account SID.
  969. //
  970. rc = RtlAllocateAndInitializeSid( &SidAuth,
  971. 1,
  972. SECURITY_LOCAL_SYSTEM_RID,
  973. 0, 0, 0, 0, 0, 0, 0,
  974. &pLocalSystemSid );
  975. if (!NT_SUCCESS(rc))
  976. {
  977. KdPrint(("NLSAPI: Could NOT Create SID - %lx.\n", rc));
  978. goto AAA_EXIT;
  979. }
  980. //
  981. // Get DACL.
  982. //
  983. rc = RtlGetDaclSecurityDescriptor( pSecurityDescriptor,
  984. &DaclPresent,
  985. &pDaclBuffer,
  986. &DaclDefaulted );
  987. if (!NT_SUCCESS(rc) || !pDaclBuffer || !DaclPresent)
  988. {
  989. KdPrint(("NLSAPI: Could NOT Get DACL Security Descriptor - %lx.\n", rc));
  990. goto AAA_EXIT;
  991. }
  992. //
  993. // Add an ACE to the ACL that allows Admin query access to the
  994. // section object.
  995. //
  996. rc = RtlAddAccessAllowedAce( (PACL)pDaclBuffer,
  997. ACL_REVISION2,
  998. AccessMask,
  999. pLocalSystemSid );
  1000. if (!NT_SUCCESS(rc))
  1001. {
  1002. KdPrint(("NLSAPI: Could NOT Add Access Allowed ACE - %lx.\n", rc));
  1003. goto AAA_EXIT;
  1004. }
  1005. AAA_EXIT:
  1006. //
  1007. // Free SID.
  1008. //
  1009. if (pLocalSystemSid) RtlFreeHeap(RtlProcessHeap(), 0, pLocalSystemSid);
  1010. //
  1011. // Return condition.
  1012. //
  1013. return rc;
  1014. }