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.

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