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.

5607 lines
183 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. dllprof.c
  5. Abstract:
  6. This module contains the client side of the Win32 Initialization
  7. File APIs
  8. Author:
  9. Steve Wood (stevewo) 24-Sep-1990
  10. Revision History:
  11. --*/
  12. #include "basedll.h"
  13. #include <limits.h>
  14. #if DBG
  15. BOOLEAN BaseDllDumpIniCalls;
  16. #endif
  17. PINIFILE_MAPPING BaseDllIniFileMapping;
  18. PINIFILE_CACHE BaseDllIniFileCache;
  19. UNICODE_STRING BaseDllIniUserKeyPath;
  20. UNICODE_STRING BaseDllIniSoftwareKeyPath;
  21. ULONG LockFileKey = 1;
  22. struct {
  23. PINIFILE_MAPPING_TARGET MappingTarget;
  24. ULONG MappingFlags;
  25. BOOLEAN WriteAccess;
  26. UNICODE_STRING RegistryPath;
  27. HANDLE RegistryKey;
  28. CRITICAL_SECTION Lock;
  29. } BaseDllRegistryCache;
  30. NTSTATUS
  31. BaseDllInitializeIniFileMappings(
  32. PBASE_STATIC_SERVER_DATA StaticServerData
  33. )
  34. {
  35. BaseDllIniFileMapping = (PINIFILE_MAPPING)StaticServerData->IniFileMapping;
  36. BaseDllIniFileCache = NULL;
  37. #if DBG
  38. BaseDllDumpIniCalls = FALSE;
  39. #endif
  40. // BaseDllDumpIniCalls = TRUE;
  41. RtlInitUnicodeString( &BaseDllIniUserKeyPath, NULL );
  42. RtlInitUnicodeString( &BaseDllIniSoftwareKeyPath, L"\\Registry\\Machine\\Software" );
  43. RtlZeroMemory( &BaseDllRegistryCache, sizeof( BaseDllRegistryCache ) );
  44. BaseDllRegistryCache.RegistryKey = INVALID_HANDLE_VALUE;
  45. InitializeCriticalSection(&BaseDllRegistryCache.Lock);
  46. return STATUS_SUCCESS;
  47. }
  48. NTSTATUS
  49. BaseDllReadWriteIniFile(
  50. IN BOOLEAN Unicode,
  51. IN BOOLEAN WriteOperation,
  52. IN BOOLEAN SectionOperation,
  53. IN PVOID FileName OPTIONAL,
  54. IN PVOID ApplicationName OPTIONAL,
  55. IN PVOID VariableName OPTIONAL,
  56. IN OUT PVOID VariableValue OPTIONAL,
  57. IN OUT PULONG VariableValueLength OPTIONAL
  58. );
  59. DWORD
  60. WINAPI
  61. GetPrivateProfileSectionNamesA(
  62. LPSTR lpszReturnBuffer,
  63. DWORD nSize,
  64. LPCSTR lpFileName
  65. )
  66. {
  67. return GetPrivateProfileStringA( NULL,
  68. NULL,
  69. NULL,
  70. lpszReturnBuffer,
  71. nSize,
  72. lpFileName
  73. );
  74. }
  75. DWORD
  76. WINAPI
  77. GetPrivateProfileSectionNamesW(
  78. LPWSTR lpszReturnBuffer,
  79. DWORD nSize,
  80. LPCWSTR lpFileName
  81. )
  82. {
  83. return GetPrivateProfileStringW( NULL,
  84. NULL,
  85. NULL,
  86. lpszReturnBuffer,
  87. nSize,
  88. lpFileName
  89. );
  90. }
  91. #define NibbleToChar(x) (N2C[x])
  92. #define CharToNibble(x) ((x)>='0'&&(x)<='9' ? (x)-'0' : ((10+(x)-'A')&0x000f))
  93. char N2C[] = {
  94. '0', '1', '2', '3', '4', '5', '6', '7',
  95. '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
  96. };
  97. BOOL
  98. WINAPI
  99. GetPrivateProfileStructA(
  100. LPCSTR lpszSection,
  101. LPCSTR lpszKey,
  102. LPVOID lpStruct,
  103. UINT uSizeStruct,
  104. LPCSTR szFile
  105. )
  106. {
  107. UCHAR szBuf[256];
  108. LPSTR lpBuf, lpBufTemp, lpFreeBuffer;
  109. UINT nLen;
  110. BYTE checksum;
  111. BOOL Result;
  112. if ((INT_MAX - 5) < uSizeStruct) {
  113. SetLastError( ERROR_INVALID_PARAMETER );
  114. return FALSE;
  115. }
  116. nLen = uSizeStruct*2 + 10;
  117. if (nLen > sizeof( szBuf )) {
  118. lpFreeBuffer = (LPSTR)RtlAllocateHeap( RtlProcessHeap(),
  119. 0,
  120. nLen
  121. );
  122. if (!lpFreeBuffer) {
  123. return FALSE;
  124. }
  125. lpBuf = lpFreeBuffer;
  126. } else {
  127. lpFreeBuffer = NULL;
  128. lpBuf = (LPSTR)szBuf;
  129. }
  130. Result = FALSE;
  131. nLen = GetPrivateProfileStringA( lpszSection,
  132. lpszKey,
  133. NULL,
  134. lpBuf,
  135. nLen,
  136. szFile
  137. );
  138. if (nLen == uSizeStruct*2+2) {
  139. /* Room for the one byte check sum */
  140. uSizeStruct+=1;
  141. checksum = 0;
  142. for (lpBufTemp=lpBuf; uSizeStruct!=0; --uSizeStruct) {
  143. BYTE bStruct;
  144. BYTE cTemp;
  145. cTemp = *lpBufTemp++;
  146. bStruct = (BYTE)CharToNibble(cTemp);
  147. cTemp = *lpBufTemp++;
  148. bStruct = (BYTE)((bStruct<<4) | CharToNibble(cTemp));
  149. if (uSizeStruct == 1) {
  150. if (checksum == bStruct) {
  151. Result = TRUE;
  152. } else {
  153. SetLastError( ERROR_INVALID_DATA );
  154. }
  155. break;
  156. }
  157. checksum += bStruct;
  158. *((LPBYTE)lpStruct)++ = bStruct;
  159. }
  160. } else {
  161. SetLastError( ERROR_BAD_LENGTH );
  162. }
  163. if (lpFreeBuffer) {
  164. RtlFreeHeap( RtlProcessHeap(), 0, lpFreeBuffer );
  165. }
  166. return Result;
  167. }
  168. BOOL
  169. WINAPI
  170. GetPrivateProfileStructW(
  171. LPCWSTR lpszSection,
  172. LPCWSTR lpszKey,
  173. LPVOID lpStruct,
  174. UINT uSizeStruct,
  175. LPCWSTR szFile
  176. )
  177. {
  178. WCHAR szBuf[256];
  179. PWSTR lpBuf, lpBufTemp, lpFreeBuffer;
  180. UINT nLen;
  181. BYTE checksum;
  182. BOOL Result;
  183. nLen = uSizeStruct*2 + 10;
  184. if (nLen < uSizeStruct) {
  185. SetLastError( ERROR_INVALID_PARAMETER );
  186. return FALSE;
  187. }
  188. if ((nLen * sizeof( WCHAR )) > sizeof( szBuf )) {
  189. lpFreeBuffer = (PWSTR)RtlAllocateHeap( RtlProcessHeap(),
  190. 0,
  191. nLen * sizeof( WCHAR )
  192. );
  193. if (!lpFreeBuffer) {
  194. return FALSE;
  195. }
  196. lpBuf = lpFreeBuffer;
  197. } else {
  198. lpFreeBuffer = NULL;
  199. lpBuf = (PWSTR)szBuf;
  200. }
  201. Result = FALSE;
  202. nLen = GetPrivateProfileStringW( lpszSection,
  203. lpszKey,
  204. NULL,
  205. lpBuf,
  206. nLen,
  207. szFile
  208. );
  209. if (nLen == uSizeStruct*2+2) {
  210. /* Room for the one byte check sum */
  211. uSizeStruct+=1;
  212. checksum = 0;
  213. for (lpBufTemp=lpBuf; uSizeStruct!=0; --uSizeStruct) {
  214. BYTE bStruct;
  215. WCHAR cTemp;
  216. cTemp = *lpBufTemp++;
  217. bStruct = (BYTE)CharToNibble(cTemp);
  218. cTemp = *lpBufTemp++;
  219. bStruct = (BYTE)((bStruct<<4) | CharToNibble(cTemp));
  220. if (uSizeStruct == 1) {
  221. if (checksum == bStruct) {
  222. Result = TRUE;
  223. } else {
  224. SetLastError( ERROR_INVALID_DATA );
  225. }
  226. break;
  227. }
  228. checksum += bStruct;
  229. *((LPBYTE)lpStruct)++ = bStruct;
  230. }
  231. } else {
  232. SetLastError( ERROR_BAD_LENGTH );
  233. }
  234. if (lpFreeBuffer) {
  235. RtlFreeHeap( RtlProcessHeap(), 0, lpFreeBuffer );
  236. }
  237. return Result;
  238. }
  239. BOOL
  240. WINAPI
  241. WritePrivateProfileStructA(
  242. LPCSTR lpszSection,
  243. LPCSTR lpszKey,
  244. LPVOID lpStruct,
  245. UINT uSizeStruct,
  246. LPCSTR szFile
  247. )
  248. {
  249. UCHAR szBuf[256];
  250. LPSTR lpBuf, lpBufTemp, lpFreeBuffer;
  251. UINT nLen;
  252. BOOL Result;
  253. BYTE checksum;
  254. if (lpStruct == NULL) {
  255. return WritePrivateProfileStringA( lpszSection,
  256. lpszKey,
  257. NULL,
  258. szFile
  259. );
  260. }
  261. nLen = uSizeStruct*2 + 3;
  262. if (nLen < uSizeStruct) {
  263. SetLastError( ERROR_INVALID_PARAMETER );
  264. return FALSE;
  265. }
  266. if (nLen > sizeof( szBuf )) {
  267. lpFreeBuffer = (LPSTR)RtlAllocateHeap( RtlProcessHeap(),
  268. 0,
  269. nLen
  270. );
  271. if (!lpFreeBuffer) {
  272. return FALSE;
  273. }
  274. lpBuf = lpFreeBuffer;
  275. } else {
  276. lpFreeBuffer = NULL;
  277. lpBuf = (LPSTR)szBuf;
  278. }
  279. checksum = 0;
  280. for (lpBufTemp=lpBuf; uSizeStruct != 0; --uSizeStruct) {
  281. BYTE bStruct;
  282. bStruct = *((LPBYTE)lpStruct)++;
  283. checksum = checksum + bStruct;
  284. *lpBufTemp++ = NibbleToChar((bStruct>>4)&0x000f);
  285. *lpBufTemp++ = NibbleToChar(bStruct&0x000f);
  286. }
  287. *lpBufTemp++ = NibbleToChar((checksum>>4)&0x000f);
  288. *lpBufTemp++ = NibbleToChar(checksum&0x000f);
  289. *lpBufTemp = '\0';
  290. Result = WritePrivateProfileStringA( lpszSection,
  291. lpszKey,
  292. lpBuf,
  293. szFile
  294. );
  295. if (lpFreeBuffer) {
  296. RtlFreeHeap( RtlProcessHeap(), 0, lpFreeBuffer );
  297. }
  298. return Result;
  299. }
  300. BOOL
  301. WINAPI
  302. WritePrivateProfileStructW(
  303. LPCWSTR lpszSection,
  304. LPCWSTR lpszKey,
  305. LPVOID lpStruct,
  306. UINT uSizeStruct,
  307. LPCWSTR szFile
  308. )
  309. {
  310. WCHAR szBuf[256];
  311. PWSTR lpBuf, lpBufTemp, lpFreeBuffer;
  312. UINT nLen;
  313. BOOL Result;
  314. BYTE checksum;
  315. if (lpStruct == NULL) {
  316. return WritePrivateProfileStringW( lpszSection,
  317. lpszKey,
  318. NULL,
  319. szFile
  320. );
  321. }
  322. nLen = uSizeStruct*2 + 3;
  323. if (nLen < uSizeStruct) {
  324. SetLastError( ERROR_INVALID_PARAMETER );
  325. return FALSE;
  326. }
  327. if ((nLen * sizeof( WCHAR )) > sizeof( szBuf )) {
  328. lpFreeBuffer = (PWSTR)RtlAllocateHeap( RtlProcessHeap(),
  329. 0,
  330. nLen * sizeof( WCHAR )
  331. );
  332. if (!lpFreeBuffer) {
  333. return FALSE;
  334. }
  335. lpBuf = lpFreeBuffer;
  336. } else {
  337. lpFreeBuffer = NULL;
  338. lpBuf = (PWSTR)szBuf;
  339. }
  340. checksum = 0;
  341. for (lpBufTemp=lpBuf; uSizeStruct != 0; --uSizeStruct) {
  342. BYTE bStruct;
  343. bStruct = *((LPBYTE)lpStruct)++;
  344. checksum = checksum + bStruct;
  345. *lpBufTemp++ = (WCHAR)NibbleToChar((bStruct>>4)&0x000f);
  346. *lpBufTemp++ = (WCHAR)NibbleToChar(bStruct&0x000f);
  347. }
  348. *lpBufTemp++ = (WCHAR)NibbleToChar((checksum>>4)&0x000f);
  349. *lpBufTemp++ = (WCHAR)NibbleToChar(checksum&0x000f);
  350. *lpBufTemp = L'\0';
  351. Result = WritePrivateProfileStringW( lpszSection,
  352. lpszKey,
  353. lpBuf,
  354. szFile
  355. );
  356. if (lpFreeBuffer) {
  357. RtlFreeHeap( RtlProcessHeap(), 0, lpFreeBuffer );
  358. }
  359. return Result;
  360. }
  361. UINT
  362. GetProfileIntA(
  363. LPCSTR lpAppName,
  364. LPCSTR lpKeyName,
  365. INT nDefault
  366. )
  367. {
  368. return( GetPrivateProfileIntA( lpAppName,
  369. lpKeyName,
  370. nDefault,
  371. NULL
  372. )
  373. );
  374. }
  375. DWORD
  376. GetProfileStringA(
  377. LPCSTR lpAppName,
  378. LPCSTR lpKeyName,
  379. LPCSTR lpDefault,
  380. LPSTR lpReturnedString,
  381. DWORD nSize
  382. )
  383. {
  384. return( GetPrivateProfileStringA( lpAppName,
  385. lpKeyName,
  386. lpDefault,
  387. lpReturnedString,
  388. nSize,
  389. NULL
  390. )
  391. );
  392. }
  393. BOOL
  394. WriteProfileStringA(
  395. LPCSTR lpAppName,
  396. LPCSTR lpKeyName,
  397. LPCSTR lpString
  398. )
  399. {
  400. return( WritePrivateProfileStringA( lpAppName,
  401. lpKeyName,
  402. lpString,
  403. NULL
  404. )
  405. );
  406. }
  407. DWORD
  408. GetProfileSectionA(
  409. LPCSTR lpAppName,
  410. LPSTR lpReturnedString,
  411. DWORD nSize
  412. )
  413. {
  414. return( GetPrivateProfileSectionA( lpAppName,
  415. lpReturnedString,
  416. nSize,
  417. NULL
  418. )
  419. );
  420. }
  421. BOOL
  422. WriteProfileSectionA(
  423. LPCSTR lpAppName,
  424. LPCSTR lpString
  425. )
  426. {
  427. return( WritePrivateProfileSectionA( lpAppName,
  428. lpString,
  429. NULL
  430. )
  431. );
  432. }
  433. UINT
  434. APIENTRY
  435. GetProfileIntW(
  436. LPCWSTR lpAppName,
  437. LPCWSTR lpKeyName,
  438. INT nDefault
  439. )
  440. {
  441. return( GetPrivateProfileIntW( lpAppName,
  442. lpKeyName,
  443. nDefault,
  444. NULL
  445. )
  446. );
  447. }
  448. DWORD
  449. APIENTRY
  450. GetProfileStringW(
  451. LPCWSTR lpAppName,
  452. LPCWSTR lpKeyName,
  453. LPCWSTR lpDefault,
  454. LPWSTR lpReturnedString,
  455. DWORD nSize
  456. )
  457. {
  458. return( GetPrivateProfileStringW( lpAppName,
  459. lpKeyName,
  460. lpDefault,
  461. lpReturnedString,
  462. nSize,
  463. NULL
  464. )
  465. );
  466. }
  467. BOOL
  468. APIENTRY
  469. WriteProfileStringW(
  470. LPCWSTR lpAppName,
  471. LPCWSTR lpKeyName,
  472. LPCWSTR lpString
  473. )
  474. {
  475. return( WritePrivateProfileStringW( lpAppName,
  476. lpKeyName,
  477. lpString,
  478. NULL
  479. )
  480. );
  481. }
  482. DWORD
  483. APIENTRY
  484. GetProfileSectionW(
  485. LPCWSTR lpAppName,
  486. LPWSTR lpReturnedString,
  487. DWORD nSize
  488. )
  489. {
  490. return( GetPrivateProfileSectionW( lpAppName,
  491. lpReturnedString,
  492. nSize,
  493. NULL
  494. )
  495. );
  496. }
  497. BOOL
  498. APIENTRY
  499. WriteProfileSectionW(
  500. LPCWSTR lpAppName,
  501. LPCWSTR lpString
  502. )
  503. {
  504. return( WritePrivateProfileSectionW( lpAppName,
  505. lpString,
  506. NULL
  507. )
  508. );
  509. }
  510. UINT
  511. GetPrivateProfileIntA(
  512. LPCSTR lpAppName,
  513. LPCSTR lpKeyName,
  514. INT nDefault,
  515. LPCSTR lpFileName
  516. )
  517. {
  518. NTSTATUS Status;
  519. ULONG ReturnValue;
  520. UCHAR ValueBuffer[ 256 ];
  521. ULONG cb;
  522. ReturnValue = 0;
  523. cb = GetPrivateProfileStringA( lpAppName,
  524. lpKeyName,
  525. NULL,
  526. ValueBuffer,
  527. sizeof( ValueBuffer ),
  528. lpFileName
  529. );
  530. if (cb == 0) {
  531. ReturnValue = nDefault;
  532. } else {
  533. Status = RtlCharToInteger( ValueBuffer, 0, &ReturnValue );
  534. if (!NT_SUCCESS( Status )) {
  535. BaseSetLastNTError( Status );
  536. } else {
  537. SetLastError( NO_ERROR );
  538. }
  539. }
  540. return ReturnValue;
  541. }
  542. DWORD
  543. GetPrivateProfileStringA(
  544. LPCSTR lpAppName,
  545. LPCSTR lpKeyName,
  546. LPCSTR lpDefault,
  547. LPSTR lpReturnedString,
  548. DWORD nSize,
  549. LPCSTR lpFileName
  550. )
  551. {
  552. NTSTATUS Status;
  553. ULONG n;
  554. if (lpDefault == NULL) {
  555. lpDefault = "";
  556. }
  557. n = nSize;
  558. Status = BaseDllReadWriteIniFile( FALSE, // Unicode,
  559. FALSE, // WriteOperation
  560. FALSE, // SectionOperation
  561. RTL_CONST_CAST(PVOID)(lpFileName),
  562. RTL_CONST_CAST(PVOID)(lpAppName),
  563. RTL_CONST_CAST(PVOID)(lpKeyName),
  564. lpReturnedString,
  565. &n
  566. );
  567. if (NT_SUCCESS( Status ) || Status == STATUS_BUFFER_OVERFLOW) {
  568. if (NT_SUCCESS( Status )) {
  569. SetLastError( NO_ERROR );
  570. n--;
  571. } else
  572. if (!lpAppName || !lpKeyName) {
  573. if (nSize >= 2) {
  574. n = nSize - 2;
  575. lpReturnedString[ n+1 ] = '\0';
  576. //
  577. // GetPrivateProfileString(): don't leave 1st byte of double byte char alone
  578. //
  579. lpReturnedString[ n ] = '\0';
  580. if ( n > 0 ) {
  581. LPSTR pc = lpReturnedString;
  582. LPSTR pcEnd = lpReturnedString + n - 1;
  583. //
  584. // if the last character is the 1st byte of
  585. // double byte character, erase it.
  586. //
  587. while ( pc <= pcEnd ) {
  588. pc += IsDBCSLeadByte( *pc ) ? 2 : 1;
  589. }
  590. if ( (pc - pcEnd ) == 2 ) {
  591. *pcEnd = '\0';
  592. }
  593. }
  594. return ( n );
  595. } else {
  596. n = 0;
  597. }
  598. } else {
  599. if (nSize >= 1) {
  600. n = nSize - 1;
  601. } else {
  602. n = 0;
  603. }
  604. }
  605. } else {
  606. n = strlen( lpDefault );
  607. while (n > 0 && lpDefault[n-1] == ' ') {
  608. n -= 1;
  609. }
  610. if (n >= nSize) {
  611. n = nSize;
  612. }
  613. strncpy( lpReturnedString, lpDefault, n );
  614. }
  615. if (n < nSize) {
  616. lpReturnedString[ n ] = '\0';
  617. } else
  618. if (nSize > 0) {
  619. lpReturnedString[ nSize-1 ] = '\0';
  620. }
  621. return( n );
  622. }
  623. BOOL
  624. WritePrivateProfileStringA(
  625. LPCSTR lpAppName,
  626. LPCSTR lpKeyName,
  627. LPCSTR lpString,
  628. LPCSTR lpFileName
  629. )
  630. {
  631. NTSTATUS Status;
  632. Status = BaseDllReadWriteIniFile( FALSE, // Unicode,
  633. TRUE, // WriteOperation
  634. FALSE, // SectionOperation
  635. RTL_CONST_CAST(PVOID)(lpFileName),
  636. RTL_CONST_CAST(PVOID)(lpAppName),
  637. RTL_CONST_CAST(PVOID)(lpKeyName),
  638. RTL_CONST_CAST(PVOID)(lpKeyName == NULL ? NULL : lpString),
  639. NULL
  640. );
  641. if (NT_SUCCESS( Status )) {
  642. return( TRUE );
  643. } else {
  644. if (Status == STATUS_INVALID_IMAGE_FORMAT) {
  645. SetLastError( ERROR_INVALID_DATA );
  646. } else {
  647. BaseSetLastNTError( Status );
  648. }
  649. return( FALSE );
  650. }
  651. }
  652. DWORD
  653. GetPrivateProfileSectionA(
  654. LPCSTR lpAppName,
  655. LPSTR lpReturnedString,
  656. DWORD nSize,
  657. LPCSTR lpFileName
  658. )
  659. {
  660. NTSTATUS Status;
  661. ULONG n;
  662. n = nSize;
  663. Status = BaseDllReadWriteIniFile( FALSE, // Unicode,
  664. FALSE, // WriteOperation
  665. TRUE, // SectionOperation
  666. RTL_CONST_CAST(PVOID)(lpFileName),
  667. RTL_CONST_CAST(PVOID)(lpAppName),
  668. NULL,
  669. lpReturnedString,
  670. &n
  671. );
  672. if (NT_SUCCESS( Status ) || Status == STATUS_BUFFER_OVERFLOW) {
  673. if (NT_SUCCESS( Status )) {
  674. SetLastError( NO_ERROR );
  675. n--;
  676. } else
  677. if (nSize >= 2) {
  678. n = nSize - 2;
  679. lpReturnedString[ n+1 ] = '\0';
  680. } else {
  681. n = 0;
  682. }
  683. } else {
  684. if (Status == STATUS_INVALID_IMAGE_FORMAT) {
  685. SetLastError( ERROR_INVALID_DATA );
  686. } else {
  687. BaseSetLastNTError( Status );
  688. }
  689. n = 0;
  690. }
  691. if (n < nSize) {
  692. lpReturnedString[ n ] = '\0';
  693. } else
  694. if (nSize > 0) {
  695. lpReturnedString[ nSize-1 ] = '\0';
  696. }
  697. return( n );
  698. }
  699. BOOL
  700. WritePrivateProfileSectionA(
  701. LPCSTR lpAppName,
  702. LPCSTR lpString,
  703. LPCSTR lpFileName
  704. )
  705. {
  706. NTSTATUS Status;
  707. Status = BaseDllReadWriteIniFile( FALSE, // Unicode,
  708. TRUE, // WriteOperation
  709. TRUE, // SectionOperation
  710. RTL_CONST_CAST(PVOID)(lpFileName),
  711. RTL_CONST_CAST(PVOID)(lpAppName),
  712. NULL,
  713. RTL_CONST_CAST(PVOID)(lpString),
  714. NULL
  715. );
  716. if (NT_SUCCESS( Status )) {
  717. return( TRUE );
  718. } else {
  719. if (Status == STATUS_INVALID_IMAGE_FORMAT) {
  720. SetLastError( ERROR_INVALID_DATA );
  721. } else {
  722. BaseSetLastNTError( Status );
  723. }
  724. return( FALSE );
  725. }
  726. }
  727. UINT
  728. APIENTRY
  729. GetPrivateProfileIntW(
  730. LPCWSTR lpAppName,
  731. LPCWSTR lpKeyName,
  732. INT nDefault,
  733. LPCWSTR lpFileName
  734. )
  735. {
  736. NTSTATUS Status;
  737. ULONG ReturnValue;
  738. WCHAR ValueBuffer[ 256 ];
  739. UNICODE_STRING Value;
  740. ANSI_STRING AnsiString;
  741. ULONG cb;
  742. ReturnValue = 0;
  743. cb = GetPrivateProfileStringW( lpAppName,
  744. lpKeyName,
  745. NULL,
  746. ValueBuffer,
  747. sizeof( ValueBuffer ) / sizeof( WCHAR ),
  748. lpFileName
  749. );
  750. if (cb == 0) {
  751. ReturnValue = nDefault;
  752. } else {
  753. Value.Buffer = ValueBuffer;
  754. Value.Length = (USHORT)(cb * sizeof( WCHAR ));
  755. Value.MaximumLength = (USHORT)((cb + 1) * sizeof( WCHAR ));
  756. Status = RtlUnicodeStringToAnsiString( &AnsiString,
  757. &Value,
  758. TRUE
  759. );
  760. if (NT_SUCCESS( Status )) {
  761. Status = RtlCharToInteger( AnsiString.Buffer, 0, &ReturnValue );
  762. RtlFreeAnsiString( &AnsiString );
  763. }
  764. if (!NT_SUCCESS( Status )) {
  765. BaseSetLastNTError( Status );
  766. } else {
  767. SetLastError( NO_ERROR );
  768. }
  769. }
  770. return ReturnValue;
  771. }
  772. DWORD
  773. APIENTRY
  774. GetPrivateProfileStringW(
  775. LPCWSTR lpAppName,
  776. LPCWSTR lpKeyName,
  777. LPCWSTR lpDefault,
  778. LPWSTR lpReturnedString,
  779. DWORD nSize,
  780. LPCWSTR lpFileName
  781. )
  782. {
  783. NTSTATUS Status;
  784. ULONG n;
  785. if (lpDefault == NULL) {
  786. lpDefault = L"";
  787. }
  788. n = nSize;
  789. Status = BaseDllReadWriteIniFile( TRUE, // Unicode,
  790. FALSE, // WriteOperation
  791. FALSE, // SectionOperation
  792. RTL_CONST_CAST(PVOID)(lpFileName),
  793. RTL_CONST_CAST(PVOID)(lpAppName),
  794. RTL_CONST_CAST(PVOID)(lpKeyName),
  795. lpReturnedString,
  796. &n
  797. );
  798. if (NT_SUCCESS( Status ) || Status == STATUS_BUFFER_OVERFLOW) {
  799. if (NT_SUCCESS( Status )) {
  800. SetLastError( NO_ERROR );
  801. n--;
  802. } else
  803. if (!lpAppName || !lpKeyName) {
  804. if (nSize >= 2) {
  805. n = nSize - 2;
  806. lpReturnedString[ n+1 ] = UNICODE_NULL;
  807. } else {
  808. n = 0;
  809. }
  810. } else {
  811. if (nSize >= 1) {
  812. n = nSize - 1;
  813. } else {
  814. n = 0;
  815. }
  816. }
  817. } else {
  818. n = wcslen( lpDefault );
  819. while (n > 0 && lpDefault[n-1] == L' ') {
  820. n -= 1;
  821. }
  822. if (n >= nSize) {
  823. n = nSize;
  824. }
  825. wcsncpy( lpReturnedString, lpDefault, n );
  826. }
  827. if (n < nSize) {
  828. lpReturnedString[ n ] = UNICODE_NULL;
  829. } else
  830. if (nSize > 0) {
  831. lpReturnedString[ nSize-1 ] = UNICODE_NULL;
  832. }
  833. return( n );
  834. }
  835. BOOL
  836. APIENTRY
  837. WritePrivateProfileStringW(
  838. LPCWSTR lpAppName,
  839. LPCWSTR lpKeyName,
  840. LPCWSTR lpString,
  841. LPCWSTR lpFileName
  842. )
  843. {
  844. NTSTATUS Status;
  845. Status = BaseDllReadWriteIniFile( TRUE, // Unicode,
  846. TRUE, // WriteOperation
  847. FALSE, // SectionOperation
  848. RTL_CONST_CAST(PVOID)(lpFileName),
  849. RTL_CONST_CAST(PVOID)(lpAppName),
  850. RTL_CONST_CAST(PVOID)(lpKeyName),
  851. RTL_CONST_CAST(PVOID)(lpKeyName == NULL ? NULL : lpString),
  852. NULL
  853. );
  854. if (NT_SUCCESS( Status )) {
  855. return( TRUE );
  856. } else {
  857. if (Status == STATUS_INVALID_IMAGE_FORMAT) {
  858. SetLastError( ERROR_INVALID_DATA );
  859. } else {
  860. BaseSetLastNTError( Status );
  861. }
  862. return( FALSE );
  863. }
  864. }
  865. DWORD
  866. APIENTRY
  867. GetPrivateProfileSectionW(
  868. LPCWSTR lpAppName,
  869. LPWSTR lpReturnedString,
  870. DWORD nSize,
  871. LPCWSTR lpFileName
  872. )
  873. {
  874. NTSTATUS Status;
  875. ULONG n;
  876. n = nSize;
  877. Status = BaseDllReadWriteIniFile( TRUE, // Unicode,
  878. FALSE, // WriteOperation
  879. TRUE, // SectionOperation
  880. RTL_CONST_CAST(PVOID)(lpFileName),
  881. RTL_CONST_CAST(PVOID)(lpAppName),
  882. NULL,
  883. lpReturnedString,
  884. &n
  885. );
  886. if (NT_SUCCESS( Status ) || Status == STATUS_BUFFER_OVERFLOW) {
  887. if (NT_SUCCESS( Status )) {
  888. SetLastError( NO_ERROR );
  889. n--;
  890. } else
  891. if (nSize >= 2) {
  892. n = nSize - 2;
  893. lpReturnedString[ n+1 ] = UNICODE_NULL;
  894. } else {
  895. n = 0;
  896. }
  897. } else {
  898. if (Status == STATUS_INVALID_IMAGE_FORMAT) {
  899. SetLastError( ERROR_INVALID_DATA );
  900. } else {
  901. BaseSetLastNTError( Status );
  902. }
  903. n = 0;
  904. }
  905. if (n < nSize) {
  906. lpReturnedString[ n ] = UNICODE_NULL;
  907. } else
  908. if (nSize > 0) {
  909. lpReturnedString[ nSize-1 ] = UNICODE_NULL;
  910. }
  911. return( n );
  912. }
  913. BOOL
  914. APIENTRY
  915. WritePrivateProfileSectionW(
  916. LPCWSTR lpAppName,
  917. LPCWSTR lpString,
  918. LPCWSTR lpFileName
  919. )
  920. {
  921. NTSTATUS Status;
  922. Status = BaseDllReadWriteIniFile( TRUE, // Unicode,
  923. TRUE, // WriteOperation
  924. TRUE, // SectionOperation
  925. RTL_CONST_CAST(PVOID)(lpFileName),
  926. RTL_CONST_CAST(PVOID)(lpAppName),
  927. NULL,
  928. RTL_CONST_CAST(PVOID)(lpString),
  929. NULL
  930. );
  931. if (NT_SUCCESS( Status )) {
  932. return( TRUE );
  933. } else {
  934. if (Status == STATUS_INVALID_IMAGE_FORMAT) {
  935. SetLastError( ERROR_INVALID_DATA );
  936. } else {
  937. BaseSetLastNTError( Status );
  938. }
  939. return( FALSE );
  940. }
  941. }
  942. VOID
  943. BaseDllFlushRegistryCache( VOID );
  944. BOOL
  945. CloseProfileUserMapping( VOID )
  946. {
  947. BaseDllFlushRegistryCache();
  948. if (BaseDllIniUserKeyPath.Buffer != NULL) {
  949. RtlFreeUnicodeString( &BaseDllIniUserKeyPath );
  950. RtlInitUnicodeString( &BaseDllIniUserKeyPath, NULL );
  951. return TRUE;
  952. } else {
  953. return TRUE;
  954. }
  955. }
  956. BOOL
  957. OpenProfileUserMapping( VOID )
  958. {
  959. NTSTATUS Status;
  960. OBJECT_ATTRIBUTES ObjectAttributes;
  961. HANDLE Key;
  962. BaseDllFlushRegistryCache();
  963. if (BaseDllIniUserKeyPath.Length == 0) {
  964. Status = RtlFormatCurrentUserKeyPath( &BaseDllIniUserKeyPath );
  965. if (NT_SUCCESS( Status )) {
  966. InitializeObjectAttributes( &ObjectAttributes,
  967. &BaseDllIniUserKeyPath,
  968. OBJ_CASE_INSENSITIVE,
  969. NULL,
  970. NULL
  971. );
  972. Status = NtOpenKey( &Key,
  973. GENERIC_READ,
  974. &ObjectAttributes
  975. );
  976. if (NT_SUCCESS( Status )) {
  977. NtClose( Key );
  978. } else {
  979. RtlFreeUnicodeString( &BaseDllIniUserKeyPath );
  980. RtlInitUnicodeString( &BaseDllIniUserKeyPath, NULL );
  981. }
  982. }
  983. if (!NT_SUCCESS( Status )) {
  984. if (!RtlCreateUnicodeString( &BaseDllIniUserKeyPath, L"\\REGISTRY\\USER\\.DEFAULT" )) {
  985. return FALSE;
  986. }
  987. }
  988. }
  989. return TRUE;
  990. }
  991. #if DBG
  992. char *xOperationNames[] = {
  993. "FlushProfiles",
  994. "ReadKeyValue",
  995. "WriteKeyValue",
  996. "DeleteKey",
  997. "ReadKeyNames",
  998. "ReadSectionNames",
  999. "ReadSection",
  1000. "WriteSection",
  1001. "DeleteSection",
  1002. "RefreshIniFileMapping"
  1003. };
  1004. #endif
  1005. NTSTATUS
  1006. BaseDllCaptureIniFileParameters(
  1007. BOOLEAN UnicodeParameters,
  1008. INIFILE_OPERATION Operation,
  1009. BOOLEAN WriteOperation,
  1010. BOOLEAN MultiValueStrings,
  1011. PVOID FileName,
  1012. PVOID ApplicationName,
  1013. PVOID VariableName,
  1014. PVOID VariableValue,
  1015. PULONG ResultMaxChars OPTIONAL,
  1016. PINIFILE_PARAMETERS *ReturnedParameterBlock
  1017. );
  1018. NTSTATUS
  1019. BaseDllReadWriteIniFileViaMapping(
  1020. IN PINIFILE_PARAMETERS a
  1021. );
  1022. NTSTATUS
  1023. BaseDllReadWriteIniFileOnDisk(
  1024. IN PINIFILE_PARAMETERS a
  1025. );
  1026. NTSTATUS
  1027. BaseDllOpenIniFileOnDisk(
  1028. IN PINIFILE_PARAMETERS a
  1029. );
  1030. NTSTATUS
  1031. BaseDllCloseIniFileOnDisk(
  1032. IN PINIFILE_PARAMETERS a
  1033. );
  1034. NTSTATUS
  1035. BaseDllAppendNullToResultBuffer(
  1036. IN PINIFILE_PARAMETERS a
  1037. );
  1038. NTSTATUS
  1039. BaseDllAppendStringToResultBuffer(
  1040. IN PINIFILE_PARAMETERS a,
  1041. IN PANSI_STRING String OPTIONAL,
  1042. IN PUNICODE_STRING StringU OPTIONAL,
  1043. IN BOOLEAN IncludeNull
  1044. );
  1045. NTSTATUS
  1046. BaseDllAppendBufferToResultBuffer(
  1047. IN PINIFILE_PARAMETERS a,
  1048. IN PBYTE Buffer OPTIONAL,
  1049. IN PWSTR BufferU OPTIONAL,
  1050. IN ULONG Chars,
  1051. IN BOOLEAN IncludeNull
  1052. );
  1053. NTSTATUS
  1054. BaseDllReadWriteIniFile(
  1055. IN BOOLEAN Unicode,
  1056. IN BOOLEAN WriteOperation,
  1057. IN BOOLEAN SectionOperation,
  1058. IN PVOID FileName OPTIONAL,
  1059. IN PVOID ApplicationName OPTIONAL,
  1060. IN PVOID VariableName OPTIONAL,
  1061. IN OUT PVOID VariableValue OPTIONAL,
  1062. IN OUT PULONG VariableValueLength OPTIONAL
  1063. )
  1064. {
  1065. BOOLEAN MultiValueStrings;
  1066. INIFILE_OPERATION Operation;
  1067. PINIFILE_PARAMETERS a;
  1068. NTSTATUS Status;
  1069. if (SectionOperation) {
  1070. VariableName = NULL;
  1071. }
  1072. MultiValueStrings = FALSE;
  1073. if (WriteOperation) {
  1074. if (ARGUMENT_PRESENT( ApplicationName )) {
  1075. if (ARGUMENT_PRESENT( VariableName )) {
  1076. if (ARGUMENT_PRESENT( VariableValue )) {
  1077. Operation = WriteKeyValue;
  1078. } else {
  1079. Operation = DeleteKey;
  1080. }
  1081. } else {
  1082. if (ARGUMENT_PRESENT( VariableValue )) {
  1083. Operation = WriteSection;
  1084. MultiValueStrings = TRUE;
  1085. } else {
  1086. Operation = DeleteSection;
  1087. }
  1088. }
  1089. } else {
  1090. #if DBG
  1091. if (ARGUMENT_PRESENT( VariableName ) ||
  1092. ARGUMENT_PRESENT( VariableValue )
  1093. ) {
  1094. return STATUS_INVALID_PARAMETER;
  1095. } else
  1096. #endif
  1097. if (ARGUMENT_PRESENT( FileName )) {
  1098. Operation = RefreshIniFileMapping;
  1099. } else {
  1100. Operation = FlushProfiles;
  1101. }
  1102. }
  1103. } else {
  1104. if (ARGUMENT_PRESENT( ApplicationName )) {
  1105. if (!ARGUMENT_PRESENT( VariableValue )) {
  1106. return STATUS_INVALID_PARAMETER;
  1107. } else
  1108. if (ARGUMENT_PRESENT( VariableName )) {
  1109. Operation = ReadKeyValue;
  1110. } else
  1111. if (SectionOperation) {
  1112. Operation = ReadSection;
  1113. MultiValueStrings = TRUE;
  1114. } else {
  1115. Operation = ReadKeyNames;
  1116. MultiValueStrings = TRUE;
  1117. }
  1118. } else
  1119. if (SectionOperation || !ARGUMENT_PRESENT( VariableValue )) {
  1120. return STATUS_INVALID_PARAMETER;
  1121. } else {
  1122. VariableName = NULL;
  1123. Operation = ReadSectionNames;
  1124. MultiValueStrings = TRUE;
  1125. }
  1126. }
  1127. #if DBG
  1128. if (WriteOperation) {
  1129. ASSERT( Operation == WriteKeyValue || Operation == WriteSection || Operation == DeleteKey || Operation == DeleteSection || Operation == FlushProfiles || Operation == RefreshIniFileMapping );
  1130. } else {
  1131. ASSERT( Operation == ReadKeyValue || Operation == ReadKeyNames || Operation == ReadSectionNames || Operation == ReadSection );
  1132. }
  1133. #endif
  1134. Status = BaseDllCaptureIniFileParameters( Unicode,
  1135. Operation,
  1136. WriteOperation,
  1137. MultiValueStrings,
  1138. FileName,
  1139. ApplicationName,
  1140. VariableName,
  1141. VariableValue,
  1142. VariableValueLength,
  1143. &a
  1144. );
  1145. if (!NT_SUCCESS( Status )) {
  1146. return Status;
  1147. }
  1148. #if DBG
  1149. if (BaseDllDumpIniCalls) {
  1150. DbgPrint( "BASEDLL: called with profile operation\n" );
  1151. DbgPrint( " Operation: %s Write: %u\n", xOperationNames[ a->Operation ], a->WriteOperation );
  1152. DbgPrint( " BaseFileName: %wZ\n", &a->BaseFileName );
  1153. DbgPrint( " IniFileNameMapping: %08x\n", a->IniFileNameMapping );
  1154. DbgPrint( " FileName: %wZ\n", &a->FileName );
  1155. DbgPrint( " NtFileName: %wZ\n", &a->NtFileName );
  1156. DbgPrint( " ApplicationName: %wZ (%Z)\n", &a->ApplicationNameU, &a->ApplicationName );
  1157. DbgPrint( " VariableName: %wZ (%Z)\n", &a->VariableNameU, &a->VariableName );
  1158. if (a->WriteOperation) {
  1159. DbgPrint( " VariableValue: %ws (%s)\n", a->ValueBufferU, a->ValueBuffer );
  1160. }
  1161. }
  1162. #endif // DBG
  1163. if (a->Operation == RefreshIniFileMapping) {
  1164. #if defined(BUILD_WOW6432)
  1165. Status = CsrBasepRefreshIniFileMapping(&a->BaseFileName);
  1166. #else
  1167. BASE_API_MSG m;
  1168. PBASE_REFRESHINIFILEMAPPING_MSG ap = &m.u.RefreshIniFileMapping;
  1169. PCSR_CAPTURE_HEADER CaptureBuffer;
  1170. CaptureBuffer = NULL;
  1171. if (a->BaseFileName.Length > (MAX_PATH * sizeof( WCHAR ))) {
  1172. Status = STATUS_INVALID_PARAMETER;
  1173. } else {
  1174. CaptureBuffer = CsrAllocateCaptureBuffer( 1,
  1175. a->BaseFileName.MaximumLength
  1176. );
  1177. if (CaptureBuffer == NULL) {
  1178. Status = STATUS_NO_MEMORY;
  1179. } else {
  1180. CsrCaptureMessageString( CaptureBuffer,
  1181. (PCHAR)a->BaseFileName.Buffer,
  1182. a->BaseFileName.Length,
  1183. a->BaseFileName.MaximumLength,
  1184. (PSTRING)&ap->IniFileName
  1185. );
  1186. Status = STATUS_SUCCESS;
  1187. }
  1188. }
  1189. if (NT_SUCCESS( Status )) {
  1190. CsrClientCallServer( (PCSR_API_MSG)&m,
  1191. CaptureBuffer,
  1192. CSR_MAKE_API_NUMBER( BASESRV_SERVERDLL_INDEX,
  1193. BasepRefreshIniFileMapping
  1194. ),
  1195. sizeof( *ap )
  1196. );
  1197. Status = (NTSTATUS)m.ReturnValue;
  1198. }
  1199. CsrFreeCaptureBuffer( CaptureBuffer );
  1200. #endif
  1201. } else
  1202. if (a->IniFileNameMapping != NULL) {
  1203. Status = BaseDllReadWriteIniFileViaMapping( a );
  1204. #if DBG
  1205. if (BaseDllDumpIniCalls) {
  1206. if (NT_SUCCESS( Status ) ||
  1207. Status == STATUS_BUFFER_OVERFLOW ||
  1208. Status == STATUS_MORE_PROCESSING_REQUIRED
  1209. ) {
  1210. if (!a->WriteOperation) {
  1211. if (a->Unicode) {
  1212. if (a->Operation == ReadKeyValue) {
  1213. DbgPrint( "BASEDLL: Returning value from registry - '%.*ws' (%u)\n", a->ResultChars, a->ResultBufferU, a->ResultChars );
  1214. } else {
  1215. PWSTR s;
  1216. DbgPrint( "BASEDLL: Return multi-value from registry: (%u)\n", a->ResultChars );
  1217. s = a->ResultBufferU;
  1218. s[ a->ResultChars ] = UNICODE_NULL;
  1219. while (*s) {
  1220. DbgPrint( " %ws\n", s );
  1221. while (*s++) {
  1222. }
  1223. }
  1224. }
  1225. } else {
  1226. if (a->Operation == ReadKeyValue) {
  1227. DbgPrint( "BASEDLL: Returning value from registry - '%.*s' (%u)\n", a->ResultChars, a->ResultBuffer, a->ResultChars );
  1228. } else {
  1229. PBYTE s;
  1230. DbgPrint( "BASEDLL: Return multi-value from registry: (%u)\n", a->ResultChars );
  1231. s = a->ResultBuffer;
  1232. s[ a->ResultChars ] = '\0';
  1233. while (*s) {
  1234. DbgPrint( " (%s)\n", s );
  1235. while (*s++) {
  1236. }
  1237. }
  1238. }
  1239. }
  1240. } else {
  1241. DbgPrint( "BASEDLL: Returning success for above write operation\n" );
  1242. }
  1243. if (Status == STATUS_BUFFER_OVERFLOW) {
  1244. DbgPrint( " *** above result partial as buffer too small.\n" );
  1245. } else
  1246. if (Status == STATUS_MORE_PROCESSING_REQUIRED) {
  1247. DbgPrint( " *** above result partial and will now look on disk.\n" );
  1248. }
  1249. } else {
  1250. DbgPrint( "BASEDLL: Profile operation %s failed: Status == %x\n", xOperationNames[ a->Operation ], Status );
  1251. }
  1252. if (a->ValueBufferAllocated) {
  1253. if (a->Unicode) {
  1254. PWSTR s;
  1255. DbgPrint( "BASEDLL: Remaining Variables to write to disk:\n" );
  1256. s = a->ValueBufferU;
  1257. while (*s) {
  1258. DbgPrint( " %ws\n", s );
  1259. while (*s++) {
  1260. }
  1261. }
  1262. } else {
  1263. PBYTE s;
  1264. DbgPrint( "BASEDLL: Remaining Variables to write to disk:\n" );
  1265. s = a->ValueBuffer;
  1266. while (*s) {
  1267. DbgPrint( " (%s)\n", s );
  1268. while (*s++) {
  1269. }
  1270. }
  1271. }
  1272. }
  1273. }
  1274. #endif // DBG
  1275. } else {
  1276. Status = STATUS_MORE_PROCESSING_REQUIRED;
  1277. }
  1278. if (Status == STATUS_MORE_PROCESSING_REQUIRED) {
  1279. Status = BaseDllReadWriteIniFileOnDisk( a );
  1280. #if DBG
  1281. if (BaseDllDumpIniCalls) {
  1282. if (NT_SUCCESS( Status ) ||
  1283. Status == STATUS_BUFFER_OVERFLOW
  1284. ) {
  1285. if (!a->WriteOperation) {
  1286. if (a->Unicode) {
  1287. if (a->Operation == ReadKeyValue) {
  1288. DbgPrint( "BASEDLL: Returning value from disk - '%.*ws' (%u)\n", a->ResultChars, a->ResultBufferU, a->ResultChars );
  1289. } else {
  1290. PWSTR s;
  1291. DbgPrint( "BASEDLL: Return multi-value from disk: (%u)\n", a->ResultChars );
  1292. s = a->ResultBufferU;
  1293. s[ a->ResultChars ] = UNICODE_NULL;
  1294. while (*s) {
  1295. DbgPrint( " %ws\n", s );
  1296. while (*s++) {
  1297. }
  1298. }
  1299. }
  1300. } else {
  1301. if (a->Operation == ReadKeyValue) {
  1302. DbgPrint( "BASEDLL: Returning value from disk - '%.*s' (%u)\n", a->ResultChars, a->ResultBuffer, a->ResultChars );
  1303. } else {
  1304. PBYTE s;
  1305. DbgPrint( "BASEDLL: Return multi-value from disk: (%u)\n", a->ResultChars );
  1306. s = a->ResultBuffer;
  1307. s[ a->ResultChars ] = '\0';
  1308. while (*s) {
  1309. DbgPrint( " (%s)\n", s );
  1310. while (*s++) {
  1311. }
  1312. }
  1313. }
  1314. }
  1315. if (Status == STATUS_BUFFER_OVERFLOW) {
  1316. DbgPrint( " *** above result partial as buffer too small.\n" );
  1317. }
  1318. } else {
  1319. DbgPrint( "BASEDLL: Returning success for above write operation.\n" );
  1320. }
  1321. } else {
  1322. DbgPrint( "BASEDLL: Profile operation %s failed: Status == %x\n", xOperationNames[ a->Operation ], Status );
  1323. }
  1324. }
  1325. #endif // DBG
  1326. }
  1327. if (BaseRunningInServerProcess || a->Operation == FlushProfiles) {
  1328. BaseDllFlushRegistryCache();
  1329. }
  1330. if (NT_SUCCESS( Status )) {
  1331. if (a->Operation == ReadSectionNames ||
  1332. a->Operation == ReadKeyNames ||
  1333. a->Operation == ReadSection
  1334. ) {
  1335. BaseDllAppendNullToResultBuffer( a );
  1336. }
  1337. }
  1338. if (NT_SUCCESS( Status ) || Status == STATUS_BUFFER_OVERFLOW) {
  1339. if (a->WriteOperation) {
  1340. BaseIniFileUpdateCount++;
  1341. } else
  1342. if (ARGUMENT_PRESENT( VariableValueLength )) {
  1343. *VariableValueLength = a->ResultChars;
  1344. }
  1345. }
  1346. if (a->ValueBufferAllocated) {
  1347. if (a->Unicode) {
  1348. RtlFreeHeap( RtlProcessHeap(), 0, a->ValueBufferU );
  1349. } else {
  1350. RtlFreeHeap( RtlProcessHeap(), 0, a->ValueBuffer );
  1351. }
  1352. }
  1353. RtlFreeHeap( RtlProcessHeap(), 0, a );
  1354. return Status;
  1355. }
  1356. ULONG
  1357. BaseDllIniFileNameLength(
  1358. IN BOOLEAN Unicode,
  1359. IN PVOID *Name
  1360. );
  1361. NTSTATUS
  1362. BaseDllFindIniFileNameMapping(
  1363. IN PUNICODE_STRING FileName,
  1364. IN PUNICODE_STRING BaseFileName,
  1365. OUT PINIFILE_MAPPING_FILENAME *ReturnedFileNameMapping
  1366. );
  1367. BOOLEAN
  1368. BaseDllGetApplicationName(
  1369. IN PINIFILE_PARAMETERS a,
  1370. OUT PANSI_STRING *ApplicationName OPTIONAL,
  1371. OUT PUNICODE_STRING *ApplicationNameU OPTIONAL
  1372. );
  1373. BOOLEAN
  1374. BaseDllGetVariableName(
  1375. IN PINIFILE_PARAMETERS a,
  1376. OUT PANSI_STRING *VariableName OPTIONAL,
  1377. OUT PUNICODE_STRING *VariableNameU OPTIONAL
  1378. );
  1379. BOOLEAN
  1380. BaseDllGetVariableValue(
  1381. IN PINIFILE_PARAMETERS a,
  1382. OUT PBYTE *VariableValue OPTIONAL,
  1383. OUT PWSTR *VariableValueU OPTIONAL,
  1384. OUT PULONG VariableValueLength
  1385. );
  1386. NTSTATUS
  1387. BaseDllCaptureIniFileParameters(
  1388. BOOLEAN Unicode,
  1389. INIFILE_OPERATION Operation,
  1390. BOOLEAN WriteOperation,
  1391. BOOLEAN MultiValueStrings,
  1392. PVOID FileName OPTIONAL,
  1393. PVOID ApplicationName OPTIONAL,
  1394. PVOID VariableName OPTIONAL,
  1395. PVOID VariableValue OPTIONAL,
  1396. PULONG ResultMaxChars OPTIONAL,
  1397. PINIFILE_PARAMETERS *ReturnedParameterBlock
  1398. )
  1399. {
  1400. NTSTATUS Status;
  1401. PBYTE s;
  1402. PWSTR p, p1;
  1403. ULONG TotalSize,
  1404. CharSize,
  1405. NtFileNameLength,
  1406. FileNameLength,
  1407. ApplicationNameLength,
  1408. VariableNameLength,
  1409. VariableValueLength;
  1410. ANSI_STRING AnsiString;
  1411. PINIFILE_PARAMETERS a;
  1412. if (ARGUMENT_PRESENT( FileName )) {
  1413. if (Unicode) {
  1414. FileNameLength = wcslen( FileName );
  1415. } else {
  1416. FileNameLength = strlen( FileName );
  1417. }
  1418. } else {
  1419. FileNameLength = 0;
  1420. }
  1421. if (ARGUMENT_PRESENT( ApplicationName )) {
  1422. ApplicationNameLength = BaseDllIniFileNameLength( Unicode, &ApplicationName );
  1423. } else {
  1424. ApplicationNameLength = 0;
  1425. VariableName = NULL;
  1426. }
  1427. if (ARGUMENT_PRESENT( VariableName )) {
  1428. VariableNameLength = BaseDllIniFileNameLength( Unicode, &VariableName );
  1429. } else {
  1430. VariableNameLength = 0;
  1431. }
  1432. if (ARGUMENT_PRESENT( VariableValue )) {
  1433. if (ARGUMENT_PRESENT( ResultMaxChars )) {
  1434. VariableValueLength = 0;
  1435. } else {
  1436. if (!MultiValueStrings) {
  1437. if (Unicode) {
  1438. VariableValueLength = wcslen( VariableValue );
  1439. } else {
  1440. VariableValueLength = strlen( VariableValue );
  1441. }
  1442. } else {
  1443. if (Unicode) {
  1444. p = (PWSTR)VariableValue;
  1445. while (*p) {
  1446. while (*p++) {
  1447. ;
  1448. }
  1449. }
  1450. VariableValueLength = (ULONG)(p - (PWSTR)VariableValue);
  1451. } else {
  1452. s = (PBYTE)VariableValue;
  1453. while (*s) {
  1454. while (*s++) {
  1455. ;
  1456. }
  1457. }
  1458. VariableValueLength = (ULONG)(s - (PBYTE)VariableValue);
  1459. }
  1460. }
  1461. }
  1462. } else {
  1463. VariableValueLength = 0;
  1464. }
  1465. NtFileNameLength = RtlGetLongestNtPathLength() * sizeof( WCHAR );
  1466. TotalSize = sizeof( *a ) + NtFileNameLength;
  1467. if (!Unicode) {
  1468. TotalSize += (FileNameLength + 1 ) * sizeof( WCHAR );
  1469. }
  1470. // We have to allocate enough buffer for DBCS string.
  1471. CharSize = (Unicode ? sizeof(WORD) : sizeof( WCHAR ));
  1472. TotalSize += (ApplicationNameLength + 1 +
  1473. VariableNameLength + 1 +
  1474. VariableValueLength + 1
  1475. ) * CharSize;
  1476. a = RtlAllocateHeap( RtlProcessHeap(), MAKE_TAG( TMP_TAG ), TotalSize );
  1477. if (a == NULL) {
  1478. KdPrint(( "BASE: Unable to allocate IniFile parameter buffer of %u bytes\n", TotalSize ));
  1479. return STATUS_NO_MEMORY;
  1480. }
  1481. a->Operation = Operation;
  1482. a->WriteOperation = WriteOperation;
  1483. a->Unicode = Unicode;
  1484. a->IniFile = NULL;
  1485. a->ValueBufferAllocated = FALSE;
  1486. a->MultiValueStrings = MultiValueStrings;
  1487. p = (PWSTR)(a + 1);
  1488. a->NtFileName.Buffer = p;
  1489. a->NtFileName.Length = 0;
  1490. a->NtFileName.MaximumLength = (USHORT)NtFileNameLength;
  1491. p = (PWSTR)((PCHAR)p + NtFileNameLength);
  1492. if (ARGUMENT_PRESENT( FileName )) {
  1493. a->FileName.MaximumLength = (USHORT)((FileNameLength + 1) * sizeof( UNICODE_NULL ));
  1494. if (Unicode) {
  1495. a->FileName.Length = (USHORT)(FileNameLength * sizeof( WCHAR ));
  1496. a->FileName.Buffer = FileName;
  1497. } else {
  1498. AnsiString.Buffer = FileName;
  1499. AnsiString.Length = (USHORT)FileNameLength;
  1500. AnsiString.MaximumLength = (USHORT)(AnsiString.Length + 1);
  1501. a->FileName.Buffer = p;
  1502. a->FileName.Length = 0;
  1503. p += FileNameLength + 1;
  1504. Status = Basep8BitStringToUnicodeString( &a->FileName, &AnsiString, FALSE );
  1505. if (!NT_SUCCESS( Status )) {
  1506. RtlFreeHeap( RtlProcessHeap(), 0, a );
  1507. return Status;
  1508. }
  1509. }
  1510. a->BaseFileName.Length = 0;
  1511. p1 = a->FileName.Buffer + FileNameLength;
  1512. if (FileNameLength != 0) {
  1513. while (--p1 > a->FileName.Buffer) {
  1514. if (*p1 == OBJ_NAME_PATH_SEPARATOR ||
  1515. *p1 == L'/' ||
  1516. *p1 == L':'
  1517. ) {
  1518. p1++;
  1519. break;
  1520. }
  1521. }
  1522. }
  1523. a->BaseFileName.Buffer = p1;
  1524. a->BaseFileName.Length = (USHORT)((FileNameLength - (p1 - a->FileName.Buffer)) * sizeof( WCHAR ));
  1525. a->BaseFileName.MaximumLength = (USHORT)(a->BaseFileName.Length + sizeof( UNICODE_NULL ));
  1526. BaseDllFindIniFileNameMapping( &a->FileName,
  1527. &a->BaseFileName,
  1528. &a->IniFileNameMapping
  1529. );
  1530. } else {
  1531. RtlInitUnicodeString( &a->FileName, L"win.ini" );
  1532. a->BaseFileName = a->FileName;
  1533. a->IniFileNameMapping = (PINIFILE_MAPPING_FILENAME)BaseDllIniFileMapping->WinIniFileMapping;
  1534. }
  1535. if (ARGUMENT_PRESENT( ApplicationName )) {
  1536. // We have to keep enough buffer for DBCS string.
  1537. a->ApplicationName.MaximumLength = (USHORT)((ApplicationNameLength * sizeof(WORD)) + 1);
  1538. a->ApplicationNameU.MaximumLength = (USHORT)(a->ApplicationName.MaximumLength * sizeof( UNICODE_NULL ));
  1539. if (Unicode) {
  1540. a->ApplicationNameU.Buffer = ApplicationName;
  1541. a->ApplicationNameU.Length = (USHORT)(ApplicationNameLength * sizeof( UNICODE_NULL ));
  1542. a->ApplicationName.Buffer = (PBYTE)p;
  1543. a->ApplicationName.Length = 0;
  1544. p = (PWSTR)((PCHAR)p + (ApplicationNameLength * sizeof(WORD)) + 1);
  1545. } else {
  1546. a->ApplicationName.Buffer = ApplicationName;
  1547. a->ApplicationName.Length = (USHORT)ApplicationNameLength;
  1548. a->ApplicationNameU.Buffer = p;
  1549. a->ApplicationNameU.Length = 0;
  1550. p += ApplicationNameLength + 1;
  1551. }
  1552. } else {
  1553. RtlInitAnsiString( &a->ApplicationName, NULL );
  1554. RtlInitUnicodeString( &a->ApplicationNameU, NULL );
  1555. }
  1556. if (ARGUMENT_PRESENT( VariableName )) {
  1557. // We have to keep enough buffer for DBCS string.
  1558. a->VariableName.MaximumLength = (USHORT)((VariableNameLength *sizeof(WORD)) + 1);
  1559. a->VariableNameU.MaximumLength = (USHORT)(a->VariableName.MaximumLength * sizeof( UNICODE_NULL ));
  1560. if (Unicode) {
  1561. a->VariableNameU.Buffer = VariableName;
  1562. a->VariableNameU.Length = (USHORT)(VariableNameLength * sizeof( UNICODE_NULL ));
  1563. a->VariableName.Buffer = (PBYTE)p;
  1564. a->VariableName.Length = 0;
  1565. p = (PWSTR)((PCHAR)p + (VariableNameLength * sizeof(WORD)) + 1);
  1566. } else {
  1567. a->VariableName.Buffer = VariableName;
  1568. a->VariableName.Length = (USHORT)VariableNameLength;
  1569. a->VariableNameU.Buffer = p;
  1570. a->VariableNameU.Length = 0;
  1571. p += VariableNameLength + 1;
  1572. }
  1573. } else {
  1574. RtlInitAnsiString( &a->VariableName, NULL );
  1575. RtlInitUnicodeString( &a->VariableNameU, NULL );
  1576. }
  1577. if (ARGUMENT_PRESENT( VariableValue )) {
  1578. if (a->WriteOperation) {
  1579. if (Unicode) {
  1580. a->ValueBufferU = VariableValue;
  1581. a->ValueLengthU = VariableValueLength * sizeof( WCHAR );
  1582. *(PBYTE)p = '\0';
  1583. a->ValueBuffer = (PBYTE)p;
  1584. a->ValueLength = 0;
  1585. } else {
  1586. a->ValueBuffer = VariableValue;
  1587. a->ValueLength = VariableValueLength;
  1588. *p = UNICODE_NULL;
  1589. a->ValueBufferU = p;
  1590. a->ValueLengthU = 0;
  1591. }
  1592. } else {
  1593. if (ARGUMENT_PRESENT( ResultMaxChars )) {
  1594. a->ResultMaxChars = *ResultMaxChars;
  1595. } else {
  1596. a->ResultMaxChars = 0;
  1597. }
  1598. a->ResultChars = 0;
  1599. if (Unicode) {
  1600. a->ResultBufferU = VariableValue;
  1601. a->ResultBuffer = NULL;
  1602. } else {
  1603. a->ResultBuffer = VariableValue;
  1604. a->ResultBufferU = NULL;
  1605. }
  1606. }
  1607. } else {
  1608. if (a->WriteOperation) {
  1609. a->ValueBuffer = NULL;
  1610. a->ValueLength = 0;
  1611. a->ValueBufferU = NULL;
  1612. a->ValueLengthU = 0;
  1613. } else {
  1614. a->ResultMaxChars = 0;
  1615. a->ResultChars = 0;
  1616. a->ResultBufferU = NULL;
  1617. a->ResultBuffer = NULL;
  1618. }
  1619. }
  1620. *ReturnedParameterBlock = a;
  1621. return STATUS_SUCCESS;
  1622. }
  1623. BOOLEAN
  1624. BaseDllGetApplicationName(
  1625. IN PINIFILE_PARAMETERS a,
  1626. OUT PANSI_STRING *ApplicationName OPTIONAL,
  1627. OUT PUNICODE_STRING *ApplicationNameU OPTIONAL
  1628. )
  1629. {
  1630. NTSTATUS Status;
  1631. if (ARGUMENT_PRESENT( ApplicationName )) {
  1632. if (a->ApplicationName.Length == 0) {
  1633. Status = RtlUnicodeStringToAnsiString( &a->ApplicationName, &a->ApplicationNameU, FALSE );
  1634. if (!NT_SUCCESS( Status )) {
  1635. KdPrint(( "BASEDLL: UnicodeToAnsi of %wZ failed (%08x)\n", &a->ApplicationNameU, Status ));
  1636. return FALSE;
  1637. }
  1638. }
  1639. *ApplicationName = &a->ApplicationName;
  1640. return TRUE;
  1641. }
  1642. if (ARGUMENT_PRESENT( ApplicationNameU )) {
  1643. if (a->ApplicationNameU.Length == 0) {
  1644. Status = RtlAnsiStringToUnicodeString( &a->ApplicationNameU, &a->ApplicationName, FALSE );
  1645. if (!NT_SUCCESS( Status )) {
  1646. KdPrint(( "BASEDLL: AnsiToUnicode of %Z failed (%08x)\n", &a->ApplicationName, Status ));
  1647. return FALSE;
  1648. }
  1649. }
  1650. *ApplicationNameU = &a->ApplicationNameU;
  1651. return TRUE;
  1652. }
  1653. return FALSE;
  1654. }
  1655. BOOLEAN
  1656. BaseDllGetVariableName(
  1657. IN PINIFILE_PARAMETERS a,
  1658. OUT PANSI_STRING *VariableName OPTIONAL,
  1659. OUT PUNICODE_STRING *VariableNameU OPTIONAL
  1660. )
  1661. {
  1662. NTSTATUS Status;
  1663. if (ARGUMENT_PRESENT( VariableName )) {
  1664. if (a->VariableName.Length == 0) {
  1665. Status = RtlUnicodeStringToAnsiString( &a->VariableName, &a->VariableNameU, FALSE );
  1666. if (!NT_SUCCESS( Status )) {
  1667. KdPrint(( "BASEDLL: UnicodeToAnsi of %wZ failed (%08x)\n", &a->VariableNameU, Status ));
  1668. return FALSE;
  1669. }
  1670. }
  1671. *VariableName = &a->VariableName;
  1672. return TRUE;
  1673. }
  1674. if (ARGUMENT_PRESENT( VariableNameU )) {
  1675. if (a->VariableNameU.Length == 0) {
  1676. Status = RtlAnsiStringToUnicodeString( &a->VariableNameU, &a->VariableName, FALSE );
  1677. if (!NT_SUCCESS( Status )) {
  1678. KdPrint(( "BASEDLL: AnsiToUnicode of %Z failed (%08x)\n", &a->VariableName, Status ));
  1679. return FALSE;
  1680. }
  1681. }
  1682. *VariableNameU = &a->VariableNameU;
  1683. return TRUE;
  1684. }
  1685. return FALSE;
  1686. }
  1687. BOOLEAN
  1688. BaseDllGetVariableValue(
  1689. IN PINIFILE_PARAMETERS a,
  1690. OUT PBYTE *VariableValue OPTIONAL,
  1691. OUT PWSTR *VariableValueU OPTIONAL,
  1692. OUT PULONG VariableValueLength
  1693. )
  1694. {
  1695. NTSTATUS Status;
  1696. ULONG Index;
  1697. if (ARGUMENT_PRESENT( VariableValue )) {
  1698. if (a->ValueLength == 0) {
  1699. if (a->ValueBufferU == NULL || a->ValueLengthU == 0) {
  1700. *VariableValue = "";
  1701. *VariableValueLength = 1;
  1702. return TRUE;
  1703. }
  1704. a->ValueLength = a->ValueLengthU;
  1705. Status = RtlUnicodeToMultiByteN( a->ValueBuffer,
  1706. a->ValueLength,
  1707. &Index,
  1708. a->ValueBufferU,
  1709. a->ValueLengthU
  1710. );
  1711. if (!NT_SUCCESS( Status )) {
  1712. KdPrint(( "BASEDLL: UnicodeToAnsi of %.*ws failed (%08x)\n",
  1713. a->ValueLengthU / sizeof( WCHAR ), a->ValueBufferU, Status
  1714. ));
  1715. return FALSE;
  1716. }
  1717. // Set real converted size
  1718. a->ValueLength = Index;
  1719. a->ValueBuffer[ Index ] = '\0'; // Null terminate converted value
  1720. } else {
  1721. Index = a->ValueLength;
  1722. }
  1723. *VariableValue = a->ValueBuffer;
  1724. *VariableValueLength = Index + 1;
  1725. return TRUE;
  1726. }
  1727. if (ARGUMENT_PRESENT( VariableValueU )) {
  1728. if (a->ValueLengthU == 0) {
  1729. if (a->ValueBuffer == NULL || a->ValueLength == 0) {
  1730. *VariableValueU = L"";
  1731. *VariableValueLength = sizeof( UNICODE_NULL );
  1732. return TRUE;
  1733. }
  1734. a->ValueLengthU = a->ValueLength * sizeof( WCHAR );
  1735. Status = RtlMultiByteToUnicodeN( a->ValueBufferU,
  1736. a->ValueLengthU,
  1737. &Index,
  1738. a->ValueBuffer,
  1739. a->ValueLength
  1740. );
  1741. if (!NT_SUCCESS( Status )) {
  1742. KdPrint(( "BASEDLL: AnsiToUnicode of %.*s failed (%08x)\n",
  1743. a->ValueLength, a->ValueBuffer, Status
  1744. ));
  1745. return FALSE;
  1746. }
  1747. Index = Index / sizeof( WCHAR );
  1748. a->ValueBufferU[ Index ] = UNICODE_NULL; // Null terminate converted value
  1749. } else {
  1750. Index = a->ValueLengthU / sizeof( WCHAR );
  1751. }
  1752. *VariableValueU = a->ValueBufferU;
  1753. *VariableValueLength = (Index + 1) * sizeof( WCHAR );
  1754. return TRUE;
  1755. }
  1756. return FALSE;
  1757. }
  1758. NTSTATUS
  1759. BaseDllAppendNullToResultBuffer(
  1760. IN PINIFILE_PARAMETERS a
  1761. )
  1762. {
  1763. return BaseDllAppendBufferToResultBuffer( a,
  1764. NULL,
  1765. NULL,
  1766. 0,
  1767. TRUE
  1768. );
  1769. }
  1770. NTSTATUS
  1771. BaseDllAppendStringToResultBuffer(
  1772. IN PINIFILE_PARAMETERS a,
  1773. IN PANSI_STRING String OPTIONAL,
  1774. IN PUNICODE_STRING StringU OPTIONAL,
  1775. IN BOOLEAN IncludeNull
  1776. )
  1777. {
  1778. if (ARGUMENT_PRESENT( String )) {
  1779. if (ARGUMENT_PRESENT( StringU )) {
  1780. return STATUS_INVALID_PARAMETER;
  1781. } else {
  1782. return BaseDllAppendBufferToResultBuffer( a,
  1783. String->Buffer,
  1784. NULL,
  1785. String->Length,
  1786. IncludeNull
  1787. );
  1788. }
  1789. } else
  1790. if (ARGUMENT_PRESENT( StringU )) {
  1791. if (ARGUMENT_PRESENT( String )) {
  1792. return STATUS_INVALID_PARAMETER;
  1793. } else {
  1794. return BaseDllAppendBufferToResultBuffer( a,
  1795. NULL,
  1796. StringU->Buffer,
  1797. StringU->Length / sizeof( WCHAR ),
  1798. IncludeNull
  1799. );
  1800. }
  1801. } else {
  1802. return STATUS_INVALID_PARAMETER;
  1803. }
  1804. }
  1805. NTSTATUS
  1806. BaseDllAppendBufferToResultBuffer(
  1807. IN PINIFILE_PARAMETERS a,
  1808. IN PBYTE Buffer OPTIONAL,
  1809. IN PWSTR BufferU OPTIONAL,
  1810. IN ULONG Chars,
  1811. IN BOOLEAN IncludeNull
  1812. )
  1813. {
  1814. NTSTATUS Status, OverflowStatus;
  1815. ULONG Index;
  1816. OverflowStatus = STATUS_SUCCESS;
  1817. if (ARGUMENT_PRESENT( Buffer )) {
  1818. if (ARGUMENT_PRESENT( BufferU )) {
  1819. return STATUS_INVALID_PARAMETER;
  1820. } else {
  1821. ULONG CharsMbcs = Chars;
  1822. //
  1823. // In this point, Chars does not contains proper value for Unicode.
  1824. // because. Chars was computed based on DBCS string length,
  1825. // This is correct, sources string is DBCS, then
  1826. // if the source is not DBCS. we just adjust it here.
  1827. //
  1828. if (a->Unicode) {
  1829. Status = RtlMultiByteToUnicodeSize(&Chars,Buffer,Chars);
  1830. if (!NT_SUCCESS( Status )) {
  1831. KdPrint(( "BASEDLL: AnsiToUnicodeSize of %.*s failed (%08x)\n", Chars, Buffer, Status ));
  1832. return Status;
  1833. }
  1834. Chars /= sizeof(WCHAR);
  1835. }
  1836. if (a->ResultChars + Chars >= a->ResultMaxChars) {
  1837. OverflowStatus = STATUS_BUFFER_OVERFLOW;
  1838. Chars = a->ResultMaxChars - a->ResultChars;
  1839. if (Chars) {
  1840. Chars -= 1;
  1841. }
  1842. }
  1843. if (Chars) {
  1844. if (a->Unicode) {
  1845. Status = RtlMultiByteToUnicodeN( a->ResultBufferU + a->ResultChars,
  1846. Chars * sizeof( WCHAR ),
  1847. &Index,
  1848. Buffer,
  1849. CharsMbcs
  1850. );
  1851. if (!NT_SUCCESS( Status )) {
  1852. KdPrint(( "BASEDLL: AnsiToUnicode of %.*s failed (%08x)\n", Chars, Buffer, Status ));
  1853. return Status;
  1854. }
  1855. } else {
  1856. memcpy( a->ResultBuffer + a->ResultChars, Buffer, Chars );
  1857. }
  1858. a->ResultChars += Chars;
  1859. }
  1860. }
  1861. } else
  1862. if (ARGUMENT_PRESENT( BufferU )) {
  1863. if (ARGUMENT_PRESENT( Buffer )) {
  1864. return STATUS_INVALID_PARAMETER;
  1865. } else {
  1866. ULONG CharsUnicode = Chars;
  1867. //
  1868. // In this point, Chars does not contains proper value for DBCS.
  1869. // because. Chars was computed by just devide Unicode string length
  1870. // by two. This is correct, sources string is Unicode, then
  1871. // if the source is not Unicode. we just adjust it here.
  1872. //
  1873. if (!(a->Unicode)) {
  1874. Status = RtlUnicodeToMultiByteSize(&Chars,BufferU,Chars * sizeof(WCHAR));
  1875. if (!NT_SUCCESS( Status )) {
  1876. KdPrint(( "BASEDLL: UnicodeToAnsiSize of %.*ws failed (%08x)\n", Chars, BufferU, Status ));
  1877. return Status;
  1878. }
  1879. }
  1880. if (a->ResultChars + Chars >= a->ResultMaxChars) {
  1881. OverflowStatus = STATUS_BUFFER_OVERFLOW;
  1882. Chars = a->ResultMaxChars - a->ResultChars;
  1883. if (Chars) {
  1884. Chars -= 1;
  1885. }
  1886. }
  1887. if (Chars) {
  1888. if (a->Unicode) {
  1889. memcpy( a->ResultBufferU + a->ResultChars, BufferU, Chars * sizeof( WCHAR ) );
  1890. } else {
  1891. Status = RtlUnicodeToMultiByteN( a->ResultBuffer + a->ResultChars,
  1892. Chars,
  1893. &Index,
  1894. BufferU,
  1895. CharsUnicode * sizeof( WCHAR )
  1896. );
  1897. if (!NT_SUCCESS( Status )) {
  1898. KdPrint(( "BASEDLL: UnicodeToAnsi of %.*ws failed (%08x)\n", Chars, BufferU, Status ));
  1899. return Status;
  1900. }
  1901. }
  1902. a->ResultChars += Chars;
  1903. }
  1904. }
  1905. }
  1906. if (IncludeNull) {
  1907. if (a->ResultChars + 1 >= a->ResultMaxChars) {
  1908. return STATUS_BUFFER_OVERFLOW;
  1909. }
  1910. if (a->Unicode) {
  1911. a->ResultBufferU[ a->ResultChars ] = UNICODE_NULL;
  1912. } else {
  1913. a->ResultBuffer[ a->ResultChars ] = '\0';
  1914. }
  1915. a->ResultChars += 1;
  1916. }
  1917. return OverflowStatus;
  1918. }
  1919. ULONG
  1920. BaseDllIniFileNameLength(
  1921. IN BOOLEAN Unicode,
  1922. IN PVOID *Name
  1923. )
  1924. {
  1925. if (Unicode) {
  1926. PWSTR p;
  1927. p = *Name;
  1928. while (*p == L' ') {
  1929. p++;
  1930. }
  1931. *Name = p;
  1932. while (*p != UNICODE_NULL) {
  1933. p++;
  1934. }
  1935. if (p > (PWSTR)*Name) {
  1936. while (*--p == L' ') {
  1937. }
  1938. p++;
  1939. }
  1940. return (ULONG)(p - (PWSTR)*Name);
  1941. } else {
  1942. PCH p;
  1943. p = *Name;
  1944. while (*p == ' ') {
  1945. p++;
  1946. }
  1947. *Name = p;
  1948. while (*p != '\0') {
  1949. p++;
  1950. }
  1951. if (p > (PCH)*Name) {
  1952. while (*--p == ' ') {
  1953. }
  1954. p++;
  1955. }
  1956. return (ULONG)(p - (PCH)*Name);
  1957. }
  1958. }
  1959. NTSTATUS
  1960. BaseDllFindIniFileNameMapping(
  1961. IN PUNICODE_STRING FileName,
  1962. IN PUNICODE_STRING BaseFileName,
  1963. OUT PINIFILE_MAPPING_FILENAME *ReturnedFileNameMapping
  1964. )
  1965. {
  1966. NTSTATUS Status;
  1967. PINIFILE_MAPPING_FILENAME FileNameMapping;
  1968. UNICODE_STRING WinIniString;
  1969. WCHAR TermSrvWindowsPath[MAX_PATH+1];
  1970. UNICODE_STRING TermsrvWindowsDir;
  1971. Status = STATUS_OBJECT_NAME_NOT_FOUND;
  1972. RtlInitUnicodeString(&WinIniString, L"win.ini");
  1973. //
  1974. // Only look in mapping if
  1975. // Unqualified name was specified OR
  1976. // Path specified exactly matches the name of the Windows directory OR
  1977. // Filename is not win.ini (special hack for Windows Sound System, which
  1978. // expects GetPrivateProfileString on C:\SNDSYS\WIN.INI to return the
  1979. // data from the file, not the registry)
  1980. //
  1981. if (gpTermsrvGetWindowsDirectoryW) {
  1982. if (gpTermsrvGetWindowsDirectoryW (TermSrvWindowsPath,MAX_PATH)) {
  1983. RtlInitUnicodeString(&TermsrvWindowsDir,TermSrvWindowsPath);
  1984. } else {
  1985. RtlInitUnicodeString(&TermsrvWindowsDir,L"");
  1986. }
  1987. }
  1988. if ((FileName->Buffer == BaseFileName->Buffer) ||
  1989. RtlPrefixUnicodeString( &BaseWindowsDirectory, FileName, TRUE ) ||
  1990. (!RtlEqualUnicodeString( BaseFileName, &WinIniString, TRUE )) ||
  1991. // Also check for in per user's windows directory
  1992. (IsTerminalServer() && RtlPrefixUnicodeString( &TermsrvWindowsDir, FileName, TRUE ))) {
  1993. FileNameMapping = (PINIFILE_MAPPING_FILENAME)BaseDllIniFileMapping->FileNames;
  1994. while (FileNameMapping != NULL) {
  1995. BASE_READ_REMOTE_STR_TEMP(TempStr);
  1996. if (RtlEqualUnicodeString( BaseFileName,
  1997. BASE_READ_REMOTE_STR(FileNameMapping->Name, TempStr),
  1998. TRUE )) {
  1999. Status = STATUS_SUCCESS;
  2000. break;
  2001. }
  2002. FileNameMapping = (PINIFILE_MAPPING_FILENAME)FileNameMapping->Next;
  2003. }
  2004. if (FileNameMapping == NULL) {
  2005. FileNameMapping = (PINIFILE_MAPPING_FILENAME)BaseDllIniFileMapping->DefaultFileNameMapping;
  2006. }
  2007. *ReturnedFileNameMapping = FileNameMapping;
  2008. } else {
  2009. *ReturnedFileNameMapping = NULL;
  2010. }
  2011. return Status;
  2012. }
  2013. NTSTATUS
  2014. BaseDllOpenMappingTarget(
  2015. IN PINIFILE_PARAMETERS a,
  2016. IN PINIFILE_MAPPING_VARNAME VarNameMapping,
  2017. IN PUNICODE_STRING ApplicationName OPTIONAL,
  2018. IN BOOLEAN WriteAccess,
  2019. OUT PHANDLE Key
  2020. );
  2021. PINIFILE_MAPPING_APPNAME
  2022. BaseDllFindAppNameMapping(
  2023. IN PINIFILE_MAPPING_FILENAME FileNameMapping,
  2024. IN PUNICODE_STRING ApplicationName
  2025. );
  2026. PINIFILE_MAPPING_VARNAME
  2027. BaseDllFindVarNameMapping(
  2028. IN PINIFILE_MAPPING_APPNAME AppNameMapping,
  2029. IN PUNICODE_STRING VariableName
  2030. );
  2031. NTSTATUS
  2032. BaseDllReadApplicationNames(
  2033. IN PINIFILE_PARAMETERS a
  2034. );
  2035. NTSTATUS
  2036. BaseDllCheckKeyNotEmpty(
  2037. IN HANDLE Key,
  2038. IN PUNICODE_STRING SubKeyName
  2039. );
  2040. NTSTATUS
  2041. BaseDllReadVariableNames(
  2042. IN PINIFILE_PARAMETERS a,
  2043. IN PINIFILE_MAPPING_APPNAME AppNameMapping
  2044. );
  2045. NTSTATUS
  2046. BaseDllReadVariableValue(
  2047. IN PINIFILE_PARAMETERS a,
  2048. IN PINIFILE_MAPPING_APPNAME AppNameMapping,
  2049. IN PINIFILE_MAPPING_VARNAME VarNameMapping OPTIONAL,
  2050. IN PUNICODE_STRING VariableName OPTIONAL
  2051. );
  2052. NTSTATUS
  2053. BaseDllReadApplicationVariables(
  2054. IN PINIFILE_PARAMETERS a,
  2055. IN PINIFILE_MAPPING_APPNAME AppNameMapping
  2056. );
  2057. NTSTATUS
  2058. BaseDllDeleteApplicationVariables(
  2059. IN PINIFILE_PARAMETERS a,
  2060. IN PINIFILE_MAPPING_APPNAME AppNameMapping
  2061. );
  2062. NTSTATUS
  2063. BaseDllWriteApplicationVariables(
  2064. IN PINIFILE_PARAMETERS a,
  2065. IN PINIFILE_MAPPING_APPNAME AppNameMapping
  2066. );
  2067. NTSTATUS
  2068. BaseDllWriteVariableValue(
  2069. IN PINIFILE_PARAMETERS a,
  2070. IN PINIFILE_MAPPING_APPNAME AppNameMapping,
  2071. IN PINIFILE_MAPPING_VARNAME VarNameMapping OPTIONAL,
  2072. IN PUNICODE_STRING VariableName OPTIONAL
  2073. );
  2074. NTSTATUS
  2075. BaseDllReadWriteIniFileViaMapping(
  2076. IN PINIFILE_PARAMETERS a
  2077. )
  2078. {
  2079. PINIFILE_MAPPING_APPNAME AppNameMapping;
  2080. PUNICODE_STRING ApplicationNameU;
  2081. if (a->Operation == FlushProfiles) {
  2082. return STATUS_SUCCESS;
  2083. } else
  2084. if (a->Operation == ReadSectionNames) {
  2085. return BaseDllReadApplicationNames( a );
  2086. } else
  2087. if (!BaseDllGetApplicationName( a, NULL, &ApplicationNameU )) {
  2088. return STATUS_INVALID_PARAMETER;
  2089. }
  2090. AppNameMapping = BaseDllFindAppNameMapping( a->IniFileNameMapping, ApplicationNameU );
  2091. if (AppNameMapping == NULL) {
  2092. return STATUS_MORE_PROCESSING_REQUIRED;
  2093. } else
  2094. if (a->Operation == ReadKeyValue) {
  2095. return BaseDllReadVariableValue( a, AppNameMapping, NULL, NULL );
  2096. } else
  2097. if (a->Operation == ReadKeyNames) {
  2098. return BaseDllReadVariableNames( a, AppNameMapping );
  2099. } else
  2100. if (a->Operation == ReadSection) {
  2101. return BaseDllReadApplicationVariables( a, AppNameMapping );
  2102. } else
  2103. if (a->Operation == WriteKeyValue || a->Operation == DeleteKey) {
  2104. return BaseDllWriteVariableValue( a, AppNameMapping, NULL, NULL );
  2105. } else
  2106. if (a->Operation == WriteSection || a->Operation == DeleteSection) {
  2107. return BaseDllWriteApplicationVariables( a, AppNameMapping );
  2108. }
  2109. return STATUS_INVALID_PARAMETER;
  2110. }
  2111. VOID
  2112. BaseDllFlushRegistryCache( VOID )
  2113. {
  2114. RtlEnterCriticalSection(&BaseDllRegistryCache.Lock);
  2115. BaseDllRegistryCache.MappingTarget = NULL;
  2116. BaseDllRegistryCache.MappingFlags = 0;
  2117. if (BaseDllRegistryCache.RegistryPath.Buffer != NULL) {
  2118. RtlFreeHeap( RtlProcessHeap(), 0, BaseDllRegistryCache.RegistryPath.Buffer );
  2119. RtlZeroMemory( &BaseDllRegistryCache.RegistryPath,
  2120. sizeof( BaseDllRegistryCache.RegistryPath )
  2121. );
  2122. }
  2123. if (BaseDllRegistryCache.RegistryKey != INVALID_HANDLE_VALUE) {
  2124. NtClose( BaseDllRegistryCache.RegistryKey );
  2125. BaseDllRegistryCache.RegistryKey = INVALID_HANDLE_VALUE;
  2126. }
  2127. RtlLeaveCriticalSection(&BaseDllRegistryCache.Lock);
  2128. return;
  2129. }
  2130. NTSTATUS
  2131. BaseDllOpenMappingTarget(
  2132. IN PINIFILE_PARAMETERS a,
  2133. IN PINIFILE_MAPPING_VARNAME VarNameMapping,
  2134. IN PUNICODE_STRING ApplicationName OPTIONAL,
  2135. IN BOOLEAN WriteAccess,
  2136. OUT PHANDLE Key
  2137. )
  2138. {
  2139. NTSTATUS Status;
  2140. PINIFILE_MAPPING_TARGET MappingTarget;
  2141. ULONG MappingFlags;
  2142. BOOLEAN AppendApplicationName;
  2143. OBJECT_ATTRIBUTES ObjectAttributes;
  2144. ULONG CreateDisposition;
  2145. PUNICODE_STRING RegistryPathPrefix;
  2146. UNICODE_STRING RegistryPath;
  2147. KEY_BASIC_INFORMATION KeyBasicInfo;
  2148. ULONG ResultLength;
  2149. ULONG n;
  2150. BOOLEAN OperationRetried = FALSE;
  2151. BASE_READ_REMOTE_STR_TEMP(TempStr);
  2152. *Key = INVALID_HANDLE_VALUE;
  2153. MappingTarget = (PINIFILE_MAPPING_TARGET)VarNameMapping->MappingTarget;
  2154. MappingFlags = VarNameMapping->MappingFlags & (INIFILE_MAPPING_APPEND_BASE_NAME |
  2155. INIFILE_MAPPING_APPEND_APPLICATION_NAME |
  2156. INIFILE_MAPPING_SOFTWARE_RELATIVE |
  2157. INIFILE_MAPPING_USER_RELATIVE
  2158. );
  2159. if (MappingTarget == NULL || MappingTarget->RegistryPath.Length == 0) {
  2160. return STATUS_SUCCESS;
  2161. }
  2162. if (ARGUMENT_PRESENT( ApplicationName ) &&
  2163. (MappingFlags & INIFILE_MAPPING_APPEND_APPLICATION_NAME)
  2164. ) {
  2165. AppendApplicationName = TRUE;
  2166. } else {
  2167. AppendApplicationName = FALSE;
  2168. }
  2169. if (MappingFlags & INIFILE_MAPPING_USER_RELATIVE) {
  2170. if (!BaseRunningInServerProcess && BaseDllIniUserKeyPath.Length == 0) {
  2171. OpenProfileUserMapping();
  2172. }
  2173. if (BaseDllIniUserKeyPath.Length == 0) {
  2174. KdPrint(( "BASE: Attempt to access user profile specific portion of .INI file.\n" ));
  2175. KdPrint(( " when there is no current user defined.\n" ));
  2176. KdPrint(( " Path: %wZ\n",
  2177. &MappingTarget->RegistryPath
  2178. ));
  2179. return STATUS_ACCESS_DENIED;
  2180. }
  2181. RegistryPathPrefix = &BaseDllIniUserKeyPath;
  2182. } else
  2183. if (MappingFlags & INIFILE_MAPPING_SOFTWARE_RELATIVE) {
  2184. RegistryPathPrefix = &BaseDllIniSoftwareKeyPath;
  2185. } else {
  2186. RegistryPathPrefix = NULL;
  2187. }
  2188. if (RegistryPathPrefix != NULL) {
  2189. n = RegistryPathPrefix->Length + sizeof( WCHAR );
  2190. } else {
  2191. n = 0;
  2192. }
  2193. n += sizeof( WCHAR ) + MappingTarget->RegistryPath.Length;
  2194. if (MappingFlags & INIFILE_MAPPING_APPEND_BASE_NAME) {
  2195. n += sizeof( WCHAR ) + a->BaseFileName.Length;
  2196. }
  2197. if (AppendApplicationName) {
  2198. n += sizeof( WCHAR ) + ApplicationName->Length;
  2199. }
  2200. n += sizeof( UNICODE_NULL );
  2201. RegistryPath.Buffer = RtlAllocateHeap( RtlProcessHeap(), 0, n );
  2202. if (RegistryPath.Buffer == NULL) {
  2203. KdPrint(( "BASE: Unable to allocate registry path buffer of %u bytes\n", n ));
  2204. return STATUS_NO_MEMORY;
  2205. }
  2206. RegistryPath.Length = 0;
  2207. RegistryPath.MaximumLength = (USHORT)n;
  2208. if (RegistryPathPrefix != NULL) {
  2209. RtlAppendUnicodeStringToString( &RegistryPath, RegistryPathPrefix );
  2210. RtlAppendUnicodeToString( &RegistryPath, L"\\" );
  2211. }
  2212. RtlAppendUnicodeStringToString( &RegistryPath,
  2213. BASE_READ_REMOTE_STR(MappingTarget->RegistryPath, TempStr)
  2214. );
  2215. if (MappingFlags & INIFILE_MAPPING_APPEND_BASE_NAME) {
  2216. RtlAppendUnicodeToString( &RegistryPath, L"\\" );
  2217. RtlAppendUnicodeStringToString( &RegistryPath, &a->BaseFileName );
  2218. }
  2219. if (AppendApplicationName) {
  2220. RtlAppendUnicodeToString( &RegistryPath, L"\\" );
  2221. RtlAppendUnicodeStringToString( &RegistryPath, ApplicationName );
  2222. }
  2223. RtlEnterCriticalSection(&BaseDllRegistryCache.Lock);
  2224. if (BaseDllRegistryCache.RegistryKey != INVALID_HANDLE_VALUE &&
  2225. BaseDllRegistryCache.MappingTarget == MappingTarget &&
  2226. BaseDllRegistryCache.MappingFlags == MappingFlags &&
  2227. BaseDllRegistryCache.WriteAccess == WriteAccess &&
  2228. RtlEqualUnicodeString( &BaseDllRegistryCache.RegistryPath, &RegistryPath, TRUE )
  2229. ) {
  2230. Status = NtQueryKey( BaseDllRegistryCache.RegistryKey,
  2231. KeyBasicInformation,
  2232. &KeyBasicInfo,
  2233. sizeof( KeyBasicInfo ),
  2234. &ResultLength
  2235. );
  2236. if (Status != STATUS_KEY_DELETED) {
  2237. RtlFreeHeap( RtlProcessHeap(), 0, RegistryPath.Buffer );
  2238. *Key = BaseDllRegistryCache.RegistryKey;
  2239. RtlLeaveCriticalSection(&BaseDllRegistryCache.Lock);
  2240. return STATUS_SUCCESS;
  2241. }
  2242. }
  2243. RtlLeaveCriticalSection(&BaseDllRegistryCache.Lock);
  2244. BaseDllFlushRegistryCache();
  2245. InitializeObjectAttributes( &ObjectAttributes,
  2246. &RegistryPath,
  2247. OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
  2248. NULL,
  2249. NULL
  2250. );
  2251. if (WriteAccess) {
  2252. repeatoperation:
  2253. Status = NtCreateKey( Key,
  2254. STANDARD_RIGHTS_WRITE |
  2255. KEY_QUERY_VALUE |
  2256. KEY_ENUMERATE_SUB_KEYS |
  2257. KEY_SET_VALUE |
  2258. KEY_CREATE_SUB_KEY,
  2259. &ObjectAttributes,
  2260. 0,
  2261. NULL,
  2262. 0,
  2263. &CreateDisposition
  2264. );
  2265. //
  2266. // There are cases where dorks delete the virtual ini file in the
  2267. // registry. To handle this, if we get object path not found, attempt
  2268. // to create the containing key and then repeat the operation
  2269. //
  2270. if ( Status == STATUS_OBJECT_NAME_NOT_FOUND && OperationRetried == FALSE ) {
  2271. NTSTATUS RetryStatus;
  2272. OBJECT_ATTRIBUTES RetryObjectAttributes;
  2273. ULONG RetryCreateDisposition;
  2274. UNICODE_STRING RetryRegistryPath;
  2275. HANDLE RetryKey;
  2276. RetryRegistryPath = RegistryPath;
  2277. while ( RetryRegistryPath.Buffer[RetryRegistryPath.Length>>1] != (WCHAR)'\\' ) {
  2278. RetryRegistryPath.Length -= sizeof(WCHAR);
  2279. }
  2280. InitializeObjectAttributes( &RetryObjectAttributes,
  2281. &RetryRegistryPath,
  2282. OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
  2283. NULL,
  2284. NULL
  2285. );
  2286. RetryStatus = NtCreateKey( &RetryKey,
  2287. STANDARD_RIGHTS_WRITE |
  2288. KEY_QUERY_VALUE |
  2289. KEY_ENUMERATE_SUB_KEYS |
  2290. KEY_SET_VALUE |
  2291. KEY_CREATE_SUB_KEY,
  2292. &RetryObjectAttributes,
  2293. 0,
  2294. NULL,
  2295. 0,
  2296. &RetryCreateDisposition
  2297. );
  2298. if ( NT_SUCCESS(RetryStatus) ) {
  2299. NtClose(RetryKey);
  2300. OperationRetried = TRUE;
  2301. goto repeatoperation;
  2302. }
  2303. }
  2304. } else {
  2305. Status = NtOpenKey( Key,
  2306. GENERIC_READ,
  2307. &ObjectAttributes
  2308. );
  2309. }
  2310. if (NT_SUCCESS( Status )) {
  2311. #if DBG
  2312. if (BaseDllDumpIniCalls) {
  2313. KdPrint(( "BASEDLL: Opened %wZ\n", &RegistryPath ));
  2314. }
  2315. #endif
  2316. RtlEnterCriticalSection(&BaseDllRegistryCache.Lock);
  2317. BaseDllRegistryCache.MappingTarget = MappingTarget;
  2318. BaseDllRegistryCache.MappingFlags = MappingFlags;
  2319. BaseDllRegistryCache.WriteAccess = WriteAccess;
  2320. BaseDllRegistryCache.RegistryPath = RegistryPath;
  2321. BaseDllRegistryCache.RegistryKey = *Key;
  2322. RtlLeaveCriticalSection(&BaseDllRegistryCache.Lock);
  2323. } else {
  2324. #if DBG
  2325. if (BaseDllDumpIniCalls || WriteAccess || Status != STATUS_OBJECT_NAME_NOT_FOUND) {
  2326. DbgPrint( "BASEDLL: Failed to open %wZ for %s - Status == %lx\n",
  2327. &RegistryPath,
  2328. WriteAccess ? "write" : "read",
  2329. Status
  2330. );
  2331. }
  2332. #endif
  2333. RtlFreeHeap( RtlProcessHeap(), 0, RegistryPath.Buffer );
  2334. }
  2335. return Status;
  2336. }
  2337. PINIFILE_MAPPING_APPNAME
  2338. BaseDllFindAppNameMapping(
  2339. IN PINIFILE_MAPPING_FILENAME FileNameMapping,
  2340. IN PUNICODE_STRING ApplicationName
  2341. )
  2342. {
  2343. PINIFILE_MAPPING_APPNAME AppNameMapping;
  2344. BASE_READ_REMOTE_STR_TEMP(TempStr);
  2345. AppNameMapping = (PINIFILE_MAPPING_APPNAME)FileNameMapping->ApplicationNames;
  2346. while (AppNameMapping != NULL) {
  2347. if (RtlEqualUnicodeString( BASE_READ_REMOTE_STR(AppNameMapping->Name, TempStr),
  2348. ApplicationName,
  2349. TRUE )) {
  2350. return AppNameMapping;
  2351. }
  2352. AppNameMapping = (PINIFILE_MAPPING_APPNAME)AppNameMapping->Next;
  2353. }
  2354. return (PINIFILE_MAPPING_APPNAME)FileNameMapping->DefaultAppNameMapping;
  2355. }
  2356. PINIFILE_MAPPING_VARNAME
  2357. BaseDllFindVarNameMapping(
  2358. IN PINIFILE_MAPPING_APPNAME AppNameMapping,
  2359. IN PUNICODE_STRING VariableName
  2360. )
  2361. {
  2362. PINIFILE_MAPPING_VARNAME VarNameMapping;
  2363. BASE_READ_REMOTE_STR_TEMP(TempStr);
  2364. VarNameMapping = (PINIFILE_MAPPING_VARNAME)AppNameMapping->VariableNames;
  2365. while (VarNameMapping != NULL) {
  2366. if (RtlEqualUnicodeString( BASE_READ_REMOTE_STR(VarNameMapping->Name,TempStr),
  2367. VariableName,
  2368. TRUE )) {
  2369. return VarNameMapping;
  2370. }
  2371. VarNameMapping = (PINIFILE_MAPPING_VARNAME)VarNameMapping->Next;
  2372. }
  2373. return (PINIFILE_MAPPING_VARNAME)AppNameMapping->DefaultVarNameMapping;
  2374. }
  2375. NTSTATUS
  2376. BaseDllReadApplicationNames(
  2377. IN PINIFILE_PARAMETERS a
  2378. )
  2379. {
  2380. NTSTATUS Status;
  2381. PINIFILE_MAPPING_APPNAME AppNameMapping;
  2382. HANDLE Key;
  2383. WCHAR Buffer[ 256 ];
  2384. PKEY_BASIC_INFORMATION KeyInformation;
  2385. ULONG SubKeyIndex;
  2386. ULONG ResultLength;
  2387. UNICODE_STRING SubKeyName;
  2388. BASE_READ_REMOTE_STR_TEMP(TempStr);
  2389. AppNameMapping = (PINIFILE_MAPPING_APPNAME)a->IniFileNameMapping->ApplicationNames;
  2390. while (AppNameMapping != NULL) {
  2391. Status = BaseDllAppendStringToResultBuffer( a,
  2392. NULL,
  2393. BASE_READ_REMOTE_STR(AppNameMapping->Name,TempStr),
  2394. TRUE
  2395. );
  2396. if (!NT_SUCCESS( Status )) {
  2397. return Status;
  2398. }
  2399. AppNameMapping = (PINIFILE_MAPPING_APPNAME)AppNameMapping->Next;
  2400. }
  2401. AppNameMapping = (PINIFILE_MAPPING_APPNAME)a->IniFileNameMapping->DefaultAppNameMapping;
  2402. if (AppNameMapping == NULL) {
  2403. return STATUS_MORE_PROCESSING_REQUIRED;
  2404. }
  2405. Status = BaseDllOpenMappingTarget( a,
  2406. (PINIFILE_MAPPING_VARNAME)AppNameMapping->DefaultVarNameMapping,
  2407. NULL,
  2408. FALSE,
  2409. &Key
  2410. );
  2411. if (!NT_SUCCESS( Status ) || Key == INVALID_HANDLE_VALUE) {
  2412. return Status;
  2413. }
  2414. KeyInformation = (PKEY_BASIC_INFORMATION)Buffer;
  2415. for (SubKeyIndex = 0; TRUE; SubKeyIndex++) {
  2416. Status = NtEnumerateKey( Key,
  2417. SubKeyIndex,
  2418. KeyBasicInformation,
  2419. KeyInformation,
  2420. sizeof( Buffer ),
  2421. &ResultLength
  2422. );
  2423. if (Status == STATUS_NO_MORE_ENTRIES) {
  2424. break;
  2425. }
  2426. if (NT_SUCCESS( Status )) {
  2427. SubKeyName.Buffer = (PWSTR)&(KeyInformation->Name[0]);
  2428. SubKeyName.Length = (USHORT)KeyInformation->NameLength;
  2429. SubKeyName.MaximumLength = (USHORT)KeyInformation->NameLength;
  2430. Status = BaseDllCheckKeyNotEmpty( Key,
  2431. &SubKeyName
  2432. );
  2433. if (NT_SUCCESS( Status ) ) {
  2434. Status = BaseDllAppendStringToResultBuffer( a, NULL, &SubKeyName, TRUE );
  2435. } else
  2436. if (Status != STATUS_NO_MORE_ENTRIES) {
  2437. break;
  2438. } else {
  2439. Status = STATUS_SUCCESS;
  2440. }
  2441. }
  2442. if (!NT_SUCCESS( Status )) {
  2443. return Status;
  2444. }
  2445. }
  2446. return STATUS_SUCCESS;
  2447. }
  2448. NTSTATUS
  2449. BaseDllCheckKeyNotEmpty(
  2450. IN HANDLE Key,
  2451. IN PUNICODE_STRING SubKeyName
  2452. )
  2453. {
  2454. NTSTATUS Status;
  2455. OBJECT_ATTRIBUTES ObjectAttributes;
  2456. HANDLE SubKey;
  2457. KEY_VALUE_BASIC_INFORMATION KeyValueInformation;
  2458. ULONG ResultLength;
  2459. InitializeObjectAttributes( &ObjectAttributes,
  2460. SubKeyName,
  2461. OBJ_CASE_INSENSITIVE,
  2462. Key,
  2463. NULL
  2464. );
  2465. Status = NtOpenKey( &SubKey,
  2466. GENERIC_READ,
  2467. &ObjectAttributes
  2468. );
  2469. if ( !NT_SUCCESS(Status) ) {
  2470. return Status;
  2471. }
  2472. Status = NtEnumerateValueKey( SubKey,
  2473. 0,
  2474. KeyValueBasicInformation,
  2475. &KeyValueInformation,
  2476. sizeof( KeyValueInformation ),
  2477. &ResultLength
  2478. );
  2479. if (Status == STATUS_BUFFER_OVERFLOW) {
  2480. Status = STATUS_SUCCESS;
  2481. }
  2482. NtClose( SubKey );
  2483. return Status;
  2484. }
  2485. NTSTATUS
  2486. BaseDllReadVariableNames(
  2487. IN PINIFILE_PARAMETERS a,
  2488. IN PINIFILE_MAPPING_APPNAME AppNameMapping
  2489. )
  2490. {
  2491. NTSTATUS Status;
  2492. PINIFILE_MAPPING_VARNAME VarNameMapping;
  2493. PUNICODE_STRING ApplicationNameU;
  2494. WCHAR Buffer[ 256 ];
  2495. PKEY_VALUE_BASIC_INFORMATION KeyValueInformation;
  2496. ULONG ValueIndex;
  2497. ULONG ResultLength;
  2498. UNICODE_STRING VariableName;
  2499. HANDLE Key;
  2500. BASE_READ_REMOTE_STR_TEMP(TempStr);
  2501. VarNameMapping = (PINIFILE_MAPPING_VARNAME)AppNameMapping->VariableNames;
  2502. while (VarNameMapping != NULL) {
  2503. Status = BaseDllAppendStringToResultBuffer( a,
  2504. NULL,
  2505. BASE_READ_REMOTE_STR(VarNameMapping->Name,TempStr),
  2506. TRUE
  2507. );
  2508. if (!NT_SUCCESS( Status )) {
  2509. return Status;
  2510. }
  2511. VarNameMapping = (PINIFILE_MAPPING_VARNAME)VarNameMapping->Next;
  2512. }
  2513. VarNameMapping = (PINIFILE_MAPPING_VARNAME)AppNameMapping->DefaultVarNameMapping;
  2514. if (VarNameMapping == NULL) {
  2515. return STATUS_MORE_PROCESSING_REQUIRED;
  2516. }
  2517. if (!BaseDllGetApplicationName( a, NULL, &ApplicationNameU )) {
  2518. return STATUS_INVALID_PARAMETER;
  2519. }
  2520. Status = BaseDllOpenMappingTarget( a,
  2521. VarNameMapping,
  2522. ApplicationNameU,
  2523. FALSE,
  2524. &Key
  2525. );
  2526. if (!NT_SUCCESS( Status ) || Key == INVALID_HANDLE_VALUE) {
  2527. return Status;
  2528. }
  2529. KeyValueInformation = (PKEY_VALUE_BASIC_INFORMATION)Buffer;
  2530. for (ValueIndex = 0; TRUE; ValueIndex++) {
  2531. Status = NtEnumerateValueKey( Key,
  2532. ValueIndex,
  2533. KeyValueBasicInformation,
  2534. KeyValueInformation,
  2535. sizeof( Buffer ),
  2536. &ResultLength
  2537. );
  2538. if (Status == STATUS_NO_MORE_ENTRIES) {
  2539. break;
  2540. } else
  2541. if (!NT_SUCCESS( Status )) {
  2542. return Status;
  2543. }
  2544. VariableName.Buffer = KeyValueInformation->Name;
  2545. VariableName.Length = (USHORT)KeyValueInformation->NameLength;
  2546. VariableName.MaximumLength = (USHORT)KeyValueInformation->NameLength;
  2547. Status = BaseDllAppendStringToResultBuffer( a, NULL, &VariableName, TRUE );
  2548. if (!NT_SUCCESS( Status )) {
  2549. return Status;
  2550. }
  2551. }
  2552. return STATUS_SUCCESS;
  2553. }
  2554. NTSTATUS
  2555. BaseDllReadVariableValue(
  2556. IN PINIFILE_PARAMETERS a,
  2557. IN PINIFILE_MAPPING_APPNAME AppNameMapping,
  2558. IN PINIFILE_MAPPING_VARNAME VarNameMapping OPTIONAL,
  2559. IN PUNICODE_STRING VariableName OPTIONAL
  2560. )
  2561. {
  2562. NTSTATUS Status;
  2563. PUNICODE_STRING ApplicationNameU;
  2564. KEY_VALUE_PARTIAL_INFORMATION KeyValueInformation;
  2565. PKEY_VALUE_PARTIAL_INFORMATION p;
  2566. ULONG ResultLength;
  2567. UNICODE_STRING Value;
  2568. BOOLEAN OutputVariableName;
  2569. UNICODE_STRING EqualSign;
  2570. PWSTR s;
  2571. HANDLE Key;
  2572. if (ARGUMENT_PRESENT( VariableName )) {
  2573. RtlInitUnicodeString( &EqualSign, L"=" );
  2574. OutputVariableName = TRUE;
  2575. } else {
  2576. if (!BaseDllGetVariableName( a, NULL, &VariableName )) {
  2577. return STATUS_INVALID_PARAMETER;
  2578. }
  2579. OutputVariableName = FALSE;
  2580. }
  2581. if (!ARGUMENT_PRESENT( VarNameMapping )) {
  2582. VarNameMapping = BaseDllFindVarNameMapping( AppNameMapping, VariableName );
  2583. }
  2584. if (VarNameMapping == NULL) {
  2585. return STATUS_MORE_PROCESSING_REQUIRED;
  2586. }
  2587. if (!BaseDllGetApplicationName( a, NULL, &ApplicationNameU )) {
  2588. return STATUS_INVALID_PARAMETER;
  2589. }
  2590. Status = BaseDllOpenMappingTarget( a,
  2591. VarNameMapping,
  2592. ApplicationNameU,
  2593. FALSE,
  2594. &Key
  2595. );
  2596. if (!NT_SUCCESS( Status ) || Key == INVALID_HANDLE_VALUE) {
  2597. return Status;
  2598. }
  2599. Status = NtQueryValueKey( Key,
  2600. VariableName,
  2601. KeyValuePartialInformation,
  2602. &KeyValueInformation,
  2603. sizeof( KeyValueInformation ),
  2604. &ResultLength
  2605. );
  2606. if (!NT_SUCCESS( Status )) {
  2607. if (Status != STATUS_BUFFER_OVERFLOW) {
  2608. return Status;
  2609. }
  2610. p = RtlAllocateHeap( RtlProcessHeap(), MAKE_TAG( TMP_TAG ), ResultLength );
  2611. if (p == NULL) {
  2612. return STATUS_NO_MEMORY;
  2613. }
  2614. Status = NtQueryValueKey( Key,
  2615. VariableName,
  2616. KeyValuePartialInformation,
  2617. p,
  2618. ResultLength,
  2619. &ResultLength
  2620. );
  2621. } else {
  2622. p = &KeyValueInformation;
  2623. }
  2624. if (NT_SUCCESS( Status )) {
  2625. if (p->Type == REG_SZ) {
  2626. if (OutputVariableName) {
  2627. Status = BaseDllAppendStringToResultBuffer( a, NULL, VariableName, FALSE );
  2628. if (NT_SUCCESS( Status )) {
  2629. Status = BaseDllAppendStringToResultBuffer( a, NULL, &EqualSign, FALSE );
  2630. }
  2631. }
  2632. if (NT_SUCCESS( Status )) {
  2633. Value.Buffer = (PWSTR)&p->Data[ 0 ];
  2634. if (p->DataLength < sizeof( UNICODE_NULL )) {
  2635. Value.Length = 0;
  2636. } else {
  2637. Value.Length = (USHORT)(p->DataLength - sizeof( UNICODE_NULL ));
  2638. }
  2639. Value.MaximumLength = (USHORT)(p->DataLength);
  2640. s = (PWSTR)Value.Buffer;
  2641. if (a->Operation == ReadKeyValue &&
  2642. Value.Length >= (2 * sizeof( WCHAR )) &&
  2643. (s[ 0 ] == s[ (Value.Length - sizeof( WCHAR )) / sizeof( WCHAR ) ]) &&
  2644. (s[ 0 ] == L'"' || s[ 0 ] == L'\'')
  2645. ) {
  2646. Value.Buffer += 1;
  2647. Value.Length -= (2 * sizeof( WCHAR ));
  2648. Value.MaximumLength -= (2 * sizeof( WCHAR ));
  2649. }
  2650. Status = BaseDllAppendStringToResultBuffer( a, NULL, &Value, TRUE );
  2651. }
  2652. } else {
  2653. KdPrint(( "BASE: Registry value %wZ not REG_SZ type (%u)\n", VariableName, p->Type ));
  2654. Status = STATUS_OBJECT_TYPE_MISMATCH;
  2655. }
  2656. }
  2657. if (p != &KeyValueInformation) {
  2658. RtlFreeHeap( RtlProcessHeap(), 0, p );
  2659. }
  2660. return Status;
  2661. }
  2662. NTSTATUS
  2663. BaseDllReadApplicationVariables(
  2664. IN PINIFILE_PARAMETERS a,
  2665. IN PINIFILE_MAPPING_APPNAME AppNameMapping
  2666. )
  2667. {
  2668. NTSTATUS Status;
  2669. PINIFILE_MAPPING_VARNAME VarNameMapping;
  2670. PUNICODE_STRING ApplicationNameU;
  2671. WCHAR Buffer[ 256 ];
  2672. PKEY_VALUE_BASIC_INFORMATION KeyValueInformation;
  2673. ULONG ValueIndex;
  2674. ULONG ResultLength;
  2675. UNICODE_STRING VariableName;
  2676. HANDLE Key;
  2677. BASE_READ_REMOTE_STR_TEMP(TempStr);
  2678. VarNameMapping = (PINIFILE_MAPPING_VARNAME)AppNameMapping->VariableNames;
  2679. while (VarNameMapping != NULL) {
  2680. if (VarNameMapping->Name.Length != 0) {
  2681. Status = BaseDllReadVariableValue( a,
  2682. AppNameMapping,
  2683. VarNameMapping,
  2684. BASE_READ_REMOTE_STR(VarNameMapping->Name,TempStr)
  2685. );
  2686. if (!NT_SUCCESS( Status )) {
  2687. if (Status == STATUS_OBJECT_NAME_NOT_FOUND ||
  2688. Status == STATUS_OBJECT_TYPE_MISMATCH
  2689. ) {
  2690. Status = STATUS_SUCCESS;
  2691. } else {
  2692. return Status;
  2693. }
  2694. }
  2695. }
  2696. VarNameMapping = (PINIFILE_MAPPING_VARNAME)VarNameMapping->Next;
  2697. }
  2698. VarNameMapping = (PINIFILE_MAPPING_VARNAME)AppNameMapping->DefaultVarNameMapping;
  2699. if (VarNameMapping == NULL) {
  2700. return STATUS_MORE_PROCESSING_REQUIRED;
  2701. }
  2702. if (!BaseDllGetApplicationName( a, NULL, &ApplicationNameU )) {
  2703. return STATUS_INVALID_PARAMETER;
  2704. }
  2705. Status = BaseDllOpenMappingTarget( a,
  2706. VarNameMapping,
  2707. ApplicationNameU,
  2708. FALSE,
  2709. &Key
  2710. );
  2711. if (!NT_SUCCESS( Status ) || Key == INVALID_HANDLE_VALUE) {
  2712. return Status;
  2713. }
  2714. KeyValueInformation = (PKEY_VALUE_BASIC_INFORMATION)Buffer;
  2715. for (ValueIndex = 0; TRUE; ValueIndex++) {
  2716. Status = NtEnumerateValueKey( Key,
  2717. ValueIndex,
  2718. KeyValueBasicInformation,
  2719. KeyValueInformation,
  2720. sizeof( Buffer ),
  2721. &ResultLength
  2722. );
  2723. if (Status == STATUS_NO_MORE_ENTRIES) {
  2724. break;
  2725. } else
  2726. if (!NT_SUCCESS( Status )) {
  2727. return Status;
  2728. }
  2729. VariableName.Buffer = KeyValueInformation->Name;
  2730. VariableName.Length = (USHORT)KeyValueInformation->NameLength;
  2731. VariableName.MaximumLength = (USHORT)KeyValueInformation->NameLength;
  2732. Status = BaseDllReadVariableValue( a, AppNameMapping, NULL, &VariableName );
  2733. if (!NT_SUCCESS( Status ) &&
  2734. Status != STATUS_OBJECT_NAME_NOT_FOUND &&
  2735. Status != STATUS_OBJECT_TYPE_MISMATCH
  2736. ) {
  2737. return Status;
  2738. }
  2739. }
  2740. return STATUS_SUCCESS;
  2741. }
  2742. NTSTATUS
  2743. BaseDllDeleteApplicationVariables(
  2744. IN PINIFILE_PARAMETERS a,
  2745. IN PINIFILE_MAPPING_APPNAME AppNameMapping
  2746. )
  2747. {
  2748. NTSTATUS Status;
  2749. PINIFILE_MAPPING_VARNAME VarNameMapping;
  2750. WCHAR Buffer[ 256 ];
  2751. HANDLE Key;
  2752. PKEY_VALUE_BASIC_INFORMATION KeyValueInformation;
  2753. ULONG ResultLength;
  2754. PUNICODE_STRING ApplicationNameU;
  2755. UNICODE_STRING VariableName;
  2756. BASE_READ_REMOTE_STR_TEMP(TempStr);
  2757. VarNameMapping = (PINIFILE_MAPPING_VARNAME)AppNameMapping->VariableNames;
  2758. while (VarNameMapping != NULL) {
  2759. if (VarNameMapping->Name.Length != 0) {
  2760. Status = BaseDllWriteVariableValue( a,
  2761. AppNameMapping,
  2762. VarNameMapping,
  2763. BASE_READ_REMOTE_STR(VarNameMapping->Name,TempStr)
  2764. );
  2765. if (!NT_SUCCESS( Status )) {
  2766. if (Status != STATUS_MORE_PROCESSING_REQUIRED) {
  2767. return Status;
  2768. }
  2769. }
  2770. }
  2771. VarNameMapping = (PINIFILE_MAPPING_VARNAME)VarNameMapping->Next;
  2772. }
  2773. VarNameMapping = (PINIFILE_MAPPING_VARNAME)AppNameMapping->DefaultVarNameMapping;
  2774. if (VarNameMapping == NULL) {
  2775. return STATUS_MORE_PROCESSING_REQUIRED;
  2776. }
  2777. if (!BaseDllGetApplicationName( a, NULL, &ApplicationNameU )) {
  2778. return STATUS_INVALID_PARAMETER;
  2779. }
  2780. Status = BaseDllOpenMappingTarget( a,
  2781. VarNameMapping,
  2782. ApplicationNameU,
  2783. TRUE,
  2784. &Key
  2785. );
  2786. if (!NT_SUCCESS( Status ) || Key == INVALID_HANDLE_VALUE) {
  2787. return Status;
  2788. }
  2789. KeyValueInformation = (PKEY_VALUE_BASIC_INFORMATION)Buffer;
  2790. do {
  2791. //
  2792. // Enumerate the 0th key. Since we are deleting as we go
  2793. // this will always be a new key until we are out of entries.
  2794. //
  2795. Status = NtEnumerateValueKey( Key,
  2796. 0,
  2797. KeyValueBasicInformation,
  2798. KeyValueInformation,
  2799. sizeof( Buffer ),
  2800. &ResultLength
  2801. );
  2802. if (NT_SUCCESS( Status )) {
  2803. VariableName.Buffer = KeyValueInformation->Name;
  2804. VariableName.Length = (USHORT)KeyValueInformation->NameLength;
  2805. VariableName.MaximumLength = (USHORT)KeyValueInformation->NameLength;
  2806. Status = NtDeleteValueKey( Key,
  2807. &VariableName
  2808. );
  2809. //
  2810. // If we couldn't find VariableName, then somebody must be deleting
  2811. // at the same time we are and beat us to it, so we just ignore the error.
  2812. //
  2813. if (Status == STATUS_OBJECT_NAME_NOT_FOUND) {
  2814. Status = STATUS_SUCCESS;
  2815. }
  2816. }
  2817. } while (NT_SUCCESS( Status ));
  2818. if (Status == STATUS_NO_MORE_ENTRIES) {
  2819. Status = STATUS_SUCCESS;
  2820. }
  2821. //
  2822. // We can't delete key, as if there are handles open to it,
  2823. // future attempts to recreate it will fail.
  2824. //
  2825. // Status = NtDeleteKey( Key );
  2826. //
  2827. BaseDllFlushRegistryCache();
  2828. return Status;
  2829. }
  2830. NTSTATUS
  2831. BaseDllWriteApplicationVariables(
  2832. IN PINIFILE_PARAMETERS a,
  2833. IN PINIFILE_MAPPING_APPNAME AppNameMapping
  2834. )
  2835. {
  2836. NTSTATUS Status;
  2837. ULONG n;
  2838. PVOID SaveValueBuffer, NewValueBuffer, CurrentValueBuffer, CurrentVariableStart, FreeBuffer;
  2839. ULONG SaveValueLength, NewValueLength, CurrentValueLength, CurrentVariableLength;
  2840. if (a->Operation == DeleteSection) {
  2841. return BaseDllDeleteApplicationVariables( a, AppNameMapping );
  2842. }
  2843. if (a->ValueBuffer != NULL && a->ValueLength != 0) {
  2844. SaveValueBuffer = a->ValueBuffer;
  2845. SaveValueLength = a->ValueLength;
  2846. } else
  2847. if (a->ValueBufferU != NULL && a->ValueLengthU != 0) {
  2848. SaveValueBuffer = a->ValueBufferU;
  2849. SaveValueLength = a->ValueLengthU;
  2850. } else {
  2851. return STATUS_INVALID_PARAMETER;
  2852. }
  2853. NewValueBuffer = RtlAllocateHeap( RtlProcessHeap(), MAKE_TAG( TMP_TAG ), SaveValueLength );
  2854. if (NewValueBuffer == NULL) {
  2855. return STATUS_NO_MEMORY;
  2856. }
  2857. FreeBuffer = NULL;
  2858. try {
  2859. RtlMoveMemory( NewValueBuffer, SaveValueBuffer, NewValueLength = SaveValueLength );
  2860. CurrentValueBuffer = NewValueBuffer;
  2861. CurrentValueLength = NewValueLength;
  2862. NewValueLength = 0;
  2863. while (CurrentValueLength) {
  2864. if (a->Unicode) {
  2865. PWSTR s, s1;
  2866. s = CurrentValueBuffer;
  2867. n = CurrentValueLength / sizeof( WCHAR );
  2868. while (n && *s != UNICODE_NULL && *s <= L' ') {
  2869. n--;
  2870. s++;
  2871. }
  2872. if (!n || *s == UNICODE_NULL) {
  2873. break;
  2874. }
  2875. CurrentVariableStart = s;
  2876. a->VariableNameU.Buffer = s;
  2877. while (n && *s != L'=') {
  2878. n--;
  2879. s++;
  2880. }
  2881. if (!n) {
  2882. break;
  2883. }
  2884. s1 = s++;
  2885. n--;
  2886. while (s1 > a->VariableNameU.Buffer) {
  2887. if (s1[-1] > L' ') {
  2888. break;
  2889. }
  2890. s1 -= 1;
  2891. }
  2892. a->VariableNameU.Length = (USHORT)((PCHAR)s1 - (PCHAR)a->VariableNameU.Buffer);
  2893. if (a->VariableNameU.Length == 0) {
  2894. break;
  2895. }
  2896. a->VariableNameU.MaximumLength = a->VariableNameU.Length + sizeof( UNICODE_NULL );
  2897. while (n && *s == L' ') {
  2898. n--;
  2899. s++;
  2900. }
  2901. a->ValueBufferU = s;
  2902. while (n && *s != UNICODE_NULL) {
  2903. n--;
  2904. s++;
  2905. }
  2906. if (!n) {
  2907. break;
  2908. }
  2909. a->ValueLengthU = (USHORT)((PCHAR)s - (PCHAR)a->ValueBufferU);
  2910. n--;
  2911. s++;
  2912. CurrentVariableLength = (ULONG)((PCHAR)s - (PCHAR)CurrentVariableStart);
  2913. CurrentValueBuffer = s;
  2914. CurrentValueLength = n * sizeof( WCHAR );
  2915. } else {
  2916. PBYTE s, s1;
  2917. s = CurrentValueBuffer;
  2918. n = CurrentValueLength;
  2919. while (n && *s != '\0' && *s <= ' ') {
  2920. n--;
  2921. s++;
  2922. }
  2923. if (!n || *s == '\0') {
  2924. break;
  2925. }
  2926. CurrentVariableStart = s;
  2927. a->VariableName.Buffer = s;
  2928. while (n && *s != '=') {
  2929. n--;
  2930. s++;
  2931. }
  2932. if (!n) {
  2933. break;
  2934. }
  2935. s1 = s++;
  2936. n--;
  2937. while (s1 > a->VariableName.Buffer) {
  2938. if (s1[-1] > ' ') {
  2939. break;
  2940. }
  2941. s1 -= 1;
  2942. }
  2943. a->VariableName.Length = (USHORT)(s1 - a->VariableName.Buffer);
  2944. if (a->VariableName.Length == 0) {
  2945. break;
  2946. }
  2947. a->VariableName.MaximumLength = a->VariableName.Length + 1;
  2948. while (n && *s == ' ') {
  2949. n--;
  2950. s++;
  2951. }
  2952. a->ValueBuffer = s;
  2953. while (n && *s != '\0') {
  2954. n--;
  2955. s++;
  2956. }
  2957. if (!n) {
  2958. break;
  2959. }
  2960. a->ValueLength = (USHORT)(s - a->ValueBuffer);
  2961. n--;
  2962. s++;
  2963. CurrentVariableLength = (ULONG)(s - (PCHAR)CurrentVariableStart);
  2964. CurrentValueBuffer = s;
  2965. CurrentValueLength = n;
  2966. a->VariableNameU.MaximumLength = a->VariableName.MaximumLength * sizeof( WCHAR );
  2967. a->VariableNameU.Length = 0;
  2968. FreeBuffer = RtlAllocateHeap( RtlProcessHeap(),
  2969. MAKE_TAG( TMP_TAG ),
  2970. a->VariableNameU.MaximumLength +
  2971. ((a->ValueLength+1) * sizeof( WCHAR ))
  2972. );
  2973. if (FreeBuffer == NULL) {
  2974. Status = STATUS_NO_MEMORY;
  2975. break;
  2976. }
  2977. a->VariableNameU.Buffer = FreeBuffer;
  2978. a->ValueBufferU = (PWSTR)((PCHAR)FreeBuffer + a->VariableNameU.MaximumLength );
  2979. }
  2980. Status = BaseDllWriteVariableValue( a, AppNameMapping, NULL, NULL );
  2981. if (FreeBuffer != NULL) {
  2982. RtlFreeHeap( RtlProcessHeap(), 0, FreeBuffer );
  2983. FreeBuffer = NULL;
  2984. RtlInitUnicodeString( &a->VariableNameU, NULL );
  2985. a->ValueBufferU = NULL;
  2986. a->ValueLengthU = 0;
  2987. }
  2988. if (!NT_SUCCESS( Status )) {
  2989. if (Status != STATUS_MORE_PROCESSING_REQUIRED) {
  2990. break;
  2991. } else {
  2992. RtlMoveMemory( (PCHAR)NewValueBuffer + NewValueLength,
  2993. CurrentVariableStart,
  2994. CurrentVariableLength
  2995. );
  2996. NewValueLength += CurrentVariableLength;
  2997. Status = STATUS_SUCCESS;
  2998. }
  2999. }
  3000. }
  3001. }
  3002. except( EXCEPTION_EXECUTE_HANDLER ) {
  3003. Status = GetExceptionCode();
  3004. }
  3005. if (NewValueLength) {
  3006. a->ValueBufferAllocated = TRUE;
  3007. if (a->Unicode) {
  3008. a->ValueBufferU = NewValueBuffer;
  3009. a->ValueLengthU = NewValueLength;
  3010. } else {
  3011. a->ValueBuffer = NewValueBuffer;
  3012. a->ValueLength = NewValueLength;
  3013. }
  3014. } else {
  3015. RtlFreeHeap( RtlProcessHeap(), 0, NewValueBuffer );
  3016. }
  3017. return Status;
  3018. }
  3019. NTSTATUS
  3020. BaseDllWriteVariableValue(
  3021. IN PINIFILE_PARAMETERS a,
  3022. IN PINIFILE_MAPPING_APPNAME AppNameMapping,
  3023. IN PINIFILE_MAPPING_VARNAME VarNameMapping OPTIONAL,
  3024. IN PUNICODE_STRING VariableName OPTIONAL
  3025. )
  3026. {
  3027. NTSTATUS Status;
  3028. PUNICODE_STRING ApplicationNameU;
  3029. PWSTR VariableValueU;
  3030. ULONG VariableValueLength;
  3031. HANDLE Key;
  3032. KEY_VALUE_BASIC_INFORMATION KeyValueInformation;
  3033. ULONG ResultLength;
  3034. if (!ARGUMENT_PRESENT( VariableName )) {
  3035. if (!BaseDllGetVariableName( a, NULL, &VariableName )) {
  3036. return STATUS_INVALID_PARAMETER;
  3037. }
  3038. }
  3039. if (!ARGUMENT_PRESENT( VarNameMapping )) {
  3040. VarNameMapping = BaseDllFindVarNameMapping( AppNameMapping, VariableName );
  3041. }
  3042. if (VarNameMapping == NULL) {
  3043. return STATUS_MORE_PROCESSING_REQUIRED;
  3044. }
  3045. if (!BaseDllGetApplicationName( a, NULL, &ApplicationNameU )) {
  3046. return STATUS_INVALID_PARAMETER;
  3047. }
  3048. Status = BaseDllOpenMappingTarget( a,
  3049. VarNameMapping,
  3050. ApplicationNameU,
  3051. TRUE,
  3052. &Key
  3053. );
  3054. if (!NT_SUCCESS( Status ) || Key == INVALID_HANDLE_VALUE) {
  3055. return Status;
  3056. }
  3057. Status = NtQueryValueKey( Key,
  3058. VariableName,
  3059. KeyValueBasicInformation,
  3060. &KeyValueInformation,
  3061. sizeof( KeyValueInformation ),
  3062. &ResultLength
  3063. );
  3064. if (NT_SUCCESS( Status ) || Status == STATUS_BUFFER_OVERFLOW) {
  3065. if (KeyValueInformation.Type != REG_SZ) {
  3066. return STATUS_OBJECT_TYPE_MISMATCH;
  3067. }
  3068. }
  3069. if (a->Operation == WriteKeyValue || a->Operation == WriteSection) {
  3070. if (!BaseDllGetVariableValue( a, NULL, &VariableValueU, &VariableValueLength )) {
  3071. Status = STATUS_INVALID_PARAMETER;
  3072. } else {
  3073. Status = NtSetValueKey( Key,
  3074. VariableName,
  3075. 0,
  3076. REG_SZ,
  3077. VariableValueU,
  3078. VariableValueLength
  3079. );
  3080. }
  3081. } else {
  3082. Status = NtDeleteValueKey( Key,
  3083. VariableName
  3084. );
  3085. if (Status == STATUS_OBJECT_NAME_NOT_FOUND) {
  3086. Status = STATUS_SUCCESS;
  3087. }
  3088. }
  3089. if (NT_SUCCESS( Status ) && (VarNameMapping->MappingFlags & INIFILE_MAPPING_WRITE_TO_INIFILE_TOO)) {
  3090. #if 0
  3091. DbgPrint( "BASEDLL: WriteToProfileToo for [%wZ] %wZ . %wZ\n",
  3092. &a->FileName,
  3093. ApplicationNameU,
  3094. VariableName
  3095. );
  3096. #endif
  3097. return STATUS_MORE_PROCESSING_REQUIRED;
  3098. } else {
  3099. return Status;
  3100. }
  3101. }
  3102. NTSTATUS
  3103. BaseDllReadSectionNames(
  3104. IN PINIFILE_PARAMETERS a
  3105. );
  3106. NTSTATUS
  3107. BaseDllReadKeywordNames(
  3108. IN PINIFILE_PARAMETERS a
  3109. );
  3110. NTSTATUS
  3111. BaseDllReadKeywordValue(
  3112. IN PINIFILE_PARAMETERS a
  3113. );
  3114. NTSTATUS
  3115. BaseDllReadSection(
  3116. IN PINIFILE_PARAMETERS a
  3117. );
  3118. NTSTATUS
  3119. BaseDllWriteSection(
  3120. IN PINIFILE_PARAMETERS a
  3121. );
  3122. NTSTATUS
  3123. BaseDllWriteKeywordValue(
  3124. IN PINIFILE_PARAMETERS a,
  3125. IN PUNICODE_STRING VariableName OPTIONAL
  3126. );
  3127. #define BYTE_ORDER_MARK 0xFEFF
  3128. #define REVERSE_BYTE_ORDER_MARK 0xFFFE
  3129. NTSTATUS
  3130. BaseDllReadWriteIniFileOnDisk(
  3131. IN PINIFILE_PARAMETERS a
  3132. )
  3133. {
  3134. NTSTATUS Status;
  3135. ULONG PartialResultChars;
  3136. if (!a->WriteOperation) {
  3137. PartialResultChars = a->ResultChars;
  3138. }
  3139. Status = BaseDllOpenIniFileOnDisk( a );
  3140. if (NT_SUCCESS( Status )) {
  3141. try {
  3142. a->TextEnd = (PCHAR)a->IniFile->BaseAddress + a->IniFile->EndOfFile;
  3143. a->TextCurrent = a->IniFile->BaseAddress;
  3144. if (a->IniFile->UnicodeFile &&
  3145. ((*(PWCHAR)a->TextCurrent == BYTE_ORDER_MARK) ||
  3146. (*(PWCHAR)a->TextCurrent == REVERSE_BYTE_ORDER_MARK)))
  3147. {
  3148. // Skip past the BOM.
  3149. ((PWCHAR)a->TextCurrent)++;
  3150. }
  3151. if (a->Operation == ReadSectionNames) {
  3152. Status = BaseDllReadSectionNames( a );
  3153. } else
  3154. if (a->Operation == ReadKeyValue) {
  3155. Status = BaseDllReadKeywordValue( a );
  3156. } else
  3157. if (a->Operation == ReadKeyNames) {
  3158. Status = BaseDllReadKeywordNames( a );
  3159. } else
  3160. if (a->Operation == ReadSection) {
  3161. Status = BaseDllReadSection( a );
  3162. } else
  3163. if (a->Operation == WriteKeyValue || a->Operation == DeleteKey) {
  3164. Status = BaseDllWriteKeywordValue( a, NULL );
  3165. } else
  3166. if (a->Operation == WriteSection || a->Operation == DeleteSection) {
  3167. Status = BaseDllWriteSection( a );
  3168. } else {
  3169. Status = STATUS_INVALID_PARAMETER;
  3170. }
  3171. }
  3172. finally {
  3173. NTSTATUS CloseStatus;
  3174. CloseStatus = BaseDllCloseIniFileOnDisk( a );
  3175. if (NT_SUCCESS( Status )) {
  3176. Status = CloseStatus;
  3177. }
  3178. }
  3179. }
  3180. if (IsTerminalServer()) {
  3181. // The entry they were looking for wasn't found, see if we need to sync
  3182. // up the ini file
  3183. if (!NT_SUCCESS(Status) && ((a->Operation == ReadSectionNames) ||
  3184. (a->Operation == ReadKeyValue) ||
  3185. (a->Operation == ReadKeyNames) ||
  3186. (a->Operation == ReadSection))) {
  3187. // Sync up the ini file (if necessary), if we updated it, retry the
  3188. // original request
  3189. if (TermsrvSyncUserIniFile(a)) {
  3190. BaseDllReadWriteIniFileOnDisk(a);
  3191. }
  3192. } else if (NT_SUCCESS(Status) && ((a->Operation == WriteKeyValue) ||
  3193. (a->Operation == DeleteKey) ||
  3194. (a->Operation == WriteSection) ||
  3195. (a->Operation == DeleteSection)) &&
  3196. TermsrvAppInstallMode()) {
  3197. // Update log of installed files
  3198. if (gpTermsrvLogInstallIniFile) {
  3199. gpTermsrvLogInstallIniFile(&a->NtFileName);
  3200. }
  3201. }
  3202. }
  3203. if (Status == STATUS_OBJECT_NAME_NOT_FOUND &&
  3204. !a->WriteOperation &&
  3205. PartialResultChars != 0
  3206. ) {
  3207. Status = STATUS_SUCCESS;
  3208. }
  3209. return Status;
  3210. }
  3211. NTSTATUS
  3212. BaseDllOpenIniFileOnDisk(
  3213. IN PINIFILE_PARAMETERS a
  3214. )
  3215. {
  3216. NTSTATUS Status;
  3217. UNICODE_STRING FullFileName;
  3218. ULONG n;
  3219. PWSTR FilePart;
  3220. PINIFILE_CACHE IniFile;
  3221. OBJECT_ATTRIBUTES ObjectAttributes;
  3222. IO_STATUS_BLOCK IoStatusBlock;
  3223. LARGE_INTEGER ByteOffset, Length;
  3224. a->NtFileName.Length = 0;
  3225. if ((a->FileName.Length > sizeof( WCHAR ) &&
  3226. a->FileName.Buffer[ 1 ] == L':'
  3227. ) ||
  3228. (a->FileName.Length != 0 &&
  3229. wcscspn( a->FileName.Buffer, L"\\/" ) != (a->FileName.Length / sizeof( WCHAR ))
  3230. )
  3231. ) {
  3232. n = GetFullPathNameW( a->FileName.Buffer,
  3233. a->NtFileName.MaximumLength / sizeof( WCHAR ),
  3234. a->NtFileName.Buffer,
  3235. &FilePart
  3236. );
  3237. if (n > a->NtFileName.MaximumLength) {
  3238. Status = STATUS_BUFFER_TOO_SMALL;
  3239. } else {
  3240. a->NtFileName.Length = (USHORT)(n * sizeof( WCHAR ));
  3241. Status = STATUS_SUCCESS;
  3242. }
  3243. /*
  3244. * If the base windows directory was specified,
  3245. * redirect to user's directory
  3246. */
  3247. if (gpTermsrvConvertSysRootToUserDir) {
  3248. gpTermsrvConvertSysRootToUserDir( &a->NtFileName, &BaseWindowsDirectory );
  3249. }
  3250. } else {
  3251. //
  3252. // get user based ini file
  3253. //
  3254. if (!gpTermsrvBuildIniFileName ||
  3255. !(NT_SUCCESS(Status = gpTermsrvBuildIniFileName( &a->NtFileName, &a->BaseFileName )))) {
  3256. RtlCopyUnicodeString( &a->NtFileName,
  3257. &BaseWindowsDirectory
  3258. );
  3259. Status = RtlAppendUnicodeToString( &a->NtFileName,
  3260. L"\\"
  3261. );
  3262. if (NT_SUCCESS( Status )) {
  3263. Status = RtlAppendUnicodeStringToString( &a->NtFileName,
  3264. &a->BaseFileName
  3265. );
  3266. }
  3267. }
  3268. }
  3269. IniFile = NULL;
  3270. if (NT_SUCCESS( Status )) {
  3271. if (RtlDosPathNameToNtPathName_U( a->NtFileName.Buffer,
  3272. &FullFileName,
  3273. &FilePart,
  3274. NULL
  3275. )
  3276. ) {
  3277. RtlCopyUnicodeString( &a->NtFileName, &FullFileName );
  3278. RtlFreeUnicodeString( &FullFileName );
  3279. IniFile = RtlAllocateHeap( RtlProcessHeap(),
  3280. MAKE_TAG( INI_TAG ) | HEAP_ZERO_MEMORY,
  3281. sizeof( *IniFile ) + a->NtFileName.MaximumLength
  3282. );
  3283. if (IniFile == NULL) {
  3284. return STATUS_NO_MEMORY;
  3285. }
  3286. IniFile->NtFileName.Buffer = (PWSTR)(IniFile + 1);
  3287. IniFile->NtFileName.MaximumLength = a->NtFileName.MaximumLength;
  3288. RtlCopyUnicodeString( &IniFile->NtFileName, &a->NtFileName );
  3289. IniFile->FileMapping = a->IniFileNameMapping;
  3290. IniFile->WriteAccess = a->WriteOperation;
  3291. if (gpTermsrvCORIniFile) {
  3292. /*
  3293. * We call a function who handles copy on reference INI files
  3294. * before attempting the open.
  3295. */
  3296. gpTermsrvCORIniFile( &IniFile->NtFileName );
  3297. }
  3298. InitializeObjectAttributes( &ObjectAttributes,
  3299. &IniFile->NtFileName,
  3300. OBJ_CASE_INSENSITIVE,
  3301. NULL,
  3302. NULL
  3303. );
  3304. if (IniFile->WriteAccess) {
  3305. Status = NtCreateFile( &IniFile->FileHandle,
  3306. SYNCHRONIZE | GENERIC_READ | GENERIC_WRITE,
  3307. &ObjectAttributes,
  3308. &IoStatusBlock,
  3309. 0,
  3310. FILE_ATTRIBUTE_NORMAL,
  3311. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  3312. FILE_OPEN_IF,
  3313. FILE_SYNCHRONOUS_IO_NONALERT |
  3314. FILE_NON_DIRECTORY_FILE,
  3315. NULL,
  3316. 0
  3317. );
  3318. } else {
  3319. Status = NtOpenFile( &IniFile->FileHandle,
  3320. SYNCHRONIZE | GENERIC_READ,
  3321. &ObjectAttributes,
  3322. &IoStatusBlock,
  3323. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  3324. FILE_SYNCHRONOUS_IO_NONALERT |
  3325. FILE_NON_DIRECTORY_FILE
  3326. );
  3327. }
  3328. #if DBG
  3329. if (!NT_SUCCESS( Status )) {
  3330. if (BaseDllDumpIniCalls) {
  3331. KdPrint(( "BASEDLL: Unable to open %wZ - Status == %x\n", &a->NtFileName, Status ));
  3332. }
  3333. }
  3334. #endif // DBG
  3335. } else {
  3336. Status = STATUS_OBJECT_PATH_NOT_FOUND;
  3337. }
  3338. }
  3339. if (NT_SUCCESS( Status )) {
  3340. IniFile->LockedFile = FALSE;
  3341. ByteOffset.QuadPart = 0;
  3342. Length.QuadPart = -1;
  3343. Status = NtLockFile( IniFile->FileHandle,
  3344. NULL,
  3345. NULL,
  3346. NULL,
  3347. &IoStatusBlock,
  3348. &ByteOffset,
  3349. &Length,
  3350. LockFileKey,
  3351. FALSE,
  3352. IniFile->WriteAccess
  3353. );
  3354. if (!NT_SUCCESS( Status )) {
  3355. if (Status == STATUS_NOT_SUPPORTED) {
  3356. //
  3357. // Go naked on downlevel servers since they can't do anything useful
  3358. // to help.
  3359. //
  3360. Status = STATUS_SUCCESS;
  3361. }
  3362. } else {
  3363. IniFile->LockedFile = TRUE;
  3364. }
  3365. if (NT_SUCCESS( Status )) {
  3366. Status = NtQueryInformationFile( IniFile->FileHandle,
  3367. &IoStatusBlock,
  3368. &IniFile->StandardInformation,
  3369. sizeof( IniFile->StandardInformation ),
  3370. FileStandardInformation
  3371. );
  3372. if (Status == STATUS_BUFFER_OVERFLOW) {
  3373. Status = STATUS_SUCCESS;
  3374. } else
  3375. if (!NT_SUCCESS( Status )) {
  3376. KdPrint(( "BASEDLL: Unable to QueryInformation for %wZ - Status == %x\n", &a->NtFileName, Status ));
  3377. }
  3378. }
  3379. }
  3380. if (!NT_SUCCESS( Status )) {
  3381. #if DBG
  3382. if (BaseDllDumpIniCalls) {
  3383. KdPrint(( "BASEDLL: Open of %wZ failed - Status == %x\n",
  3384. &IniFile->NtFileName,
  3385. Status
  3386. ));
  3387. }
  3388. #endif // DBG
  3389. if (IniFile != NULL) {
  3390. if (IniFile->LockedFile) {
  3391. ByteOffset.QuadPart = 0;
  3392. Length.QuadPart = -1;
  3393. NtUnlockFile( IniFile->FileHandle,
  3394. &IoStatusBlock,
  3395. &ByteOffset,
  3396. &Length,
  3397. LockFileKey
  3398. );
  3399. }
  3400. NtClose( IniFile->FileHandle );
  3401. RtlFreeHeap( RtlProcessHeap(), 0, IniFile );
  3402. }
  3403. return Status;
  3404. }
  3405. IniFile->EndOfFile = IniFile->StandardInformation.EndOfFile.LowPart;
  3406. IniFile->CommitSize = IniFile->EndOfFile + (4 * (IniFile->UnicodeFile ? sizeof( WCHAR ) : 1));
  3407. IniFile->RegionSize = IniFile->CommitSize + 0x100000; // Room for 256KB of growth
  3408. Status = NtAllocateVirtualMemory( NtCurrentProcess(),
  3409. &IniFile->BaseAddress,
  3410. 0,
  3411. &IniFile->RegionSize,
  3412. MEM_RESERVE,
  3413. PAGE_READWRITE
  3414. );
  3415. if (NT_SUCCESS( Status )) {
  3416. Status = NtAllocateVirtualMemory( NtCurrentProcess(),
  3417. &IniFile->BaseAddress,
  3418. 0,
  3419. &IniFile->CommitSize,
  3420. MEM_COMMIT,
  3421. PAGE_READWRITE
  3422. );
  3423. if (NT_SUCCESS( Status )) {
  3424. Status = NtReadFile( IniFile->FileHandle,
  3425. NULL,
  3426. NULL,
  3427. NULL,
  3428. &IoStatusBlock,
  3429. IniFile->BaseAddress,
  3430. IniFile->EndOfFile,
  3431. NULL,
  3432. &LockFileKey
  3433. );
  3434. if (NT_SUCCESS( Status ) && IoStatusBlock.Information != IniFile->EndOfFile) {
  3435. Status = STATUS_END_OF_FILE;
  3436. }
  3437. }
  3438. }
  3439. if (NT_SUCCESS( Status )) {
  3440. // We would like to check the possibility of IS_TEXT_UNICODE_DBCS_LEADBYTE.
  3441. INT iResult = ~0x0;
  3442. IniFile->UpdateOffset = 0xFFFFFFFF;
  3443. IniFile->UpdateEndOffset = 0;
  3444. IniFile->UnicodeFile = RtlIsTextUnicode( IniFile->BaseAddress, IniFile->EndOfFile, &iResult );
  3445. if (IniFile->UnicodeFile) {
  3446. PWSTR Src;
  3447. Src = (PWSTR)((PCHAR)IniFile->BaseAddress + IniFile->EndOfFile);
  3448. while (Src > (PWSTR)IniFile->BaseAddress && Src[ -1 ] <= L' ') {
  3449. if (Src[-1] == L'\r' || Src[-1] == L'\n') {
  3450. break;
  3451. }
  3452. IniFile->EndOfFile -= sizeof( WCHAR );
  3453. Src -= 1;
  3454. }
  3455. Src = (PWSTR)((PCHAR)IniFile->BaseAddress + IniFile->EndOfFile);
  3456. if (Src > (PWSTR)IniFile->BaseAddress) {
  3457. if (Src[-1] != L'\n') {
  3458. *Src++ = L'\r';
  3459. *Src++ = L'\n';
  3460. IniFile->UpdateOffset = IniFile->EndOfFile;
  3461. IniFile->UpdateEndOffset = IniFile->UpdateOffset + 2 * sizeof( WCHAR );
  3462. IniFile->EndOfFile = IniFile->UpdateEndOffset;
  3463. }
  3464. }
  3465. } else {
  3466. PBYTE Src;
  3467. Src = (PBYTE)((PCHAR)IniFile->BaseAddress + IniFile->EndOfFile);
  3468. while (Src > (PBYTE)IniFile->BaseAddress && Src[ -1 ] <= ' ') {
  3469. if (Src[-1] == '\r' || Src[-1] == '\n') {
  3470. break;
  3471. }
  3472. IniFile->EndOfFile -= 1;
  3473. Src -= 1;
  3474. }
  3475. Src = (PBYTE)((PCHAR)IniFile->BaseAddress + IniFile->EndOfFile);
  3476. if (Src > (PBYTE)IniFile->BaseAddress) {
  3477. if (Src[-1] != '\n') {
  3478. *Src++ = '\r';
  3479. *Src++ = '\n';
  3480. IniFile->UpdateOffset = IniFile->EndOfFile;
  3481. IniFile->UpdateEndOffset = IniFile->UpdateOffset + 2;
  3482. IniFile->EndOfFile = IniFile->UpdateEndOffset;
  3483. }
  3484. }
  3485. }
  3486. a->IniFile = IniFile;
  3487. } else {
  3488. KdPrint(( "BASEDLL: Read of %wZ failed - Status == %x\n",
  3489. &IniFile->NtFileName,
  3490. Status
  3491. ));
  3492. if (IniFile->LockedFile) {
  3493. ByteOffset.QuadPart = 0;
  3494. Length.QuadPart = -1;
  3495. NtUnlockFile( IniFile->FileHandle,
  3496. &IoStatusBlock,
  3497. &ByteOffset,
  3498. &Length,
  3499. LockFileKey
  3500. );
  3501. }
  3502. NtClose( IniFile->FileHandle );
  3503. RtlFreeHeap( RtlProcessHeap(), 0, IniFile );
  3504. }
  3505. return Status;
  3506. }
  3507. NTSTATUS
  3508. BaseDllCloseIniFileOnDisk(
  3509. IN PINIFILE_PARAMETERS a
  3510. )
  3511. {
  3512. PINIFILE_CACHE IniFile;
  3513. NTSTATUS Status;
  3514. NTSTATUS CloseStatus;
  3515. IO_STATUS_BLOCK IoStatusBlock;
  3516. ULONG UpdateLength;
  3517. LARGE_INTEGER ByteOffset, Length;
  3518. Status = STATUS_SUCCESS;
  3519. IniFile = a->IniFile;
  3520. if (IniFile != NULL) {
  3521. ASSERT( IniFile->FileHandle != NULL );
  3522. if (IniFile->BaseAddress != NULL) {
  3523. if (IniFile->UpdateOffset != 0xFFFFFFFF && IniFile->WriteAccess) {
  3524. ByteOffset.HighPart = 0;
  3525. ByteOffset.LowPart = IniFile->UpdateOffset;
  3526. UpdateLength = IniFile->UpdateEndOffset - IniFile->UpdateOffset;
  3527. Status = NtWriteFile( IniFile->FileHandle,
  3528. NULL,
  3529. NULL,
  3530. NULL,
  3531. &IoStatusBlock,
  3532. (PCHAR)(IniFile->BaseAddress) + IniFile->UpdateOffset,
  3533. UpdateLength,
  3534. &ByteOffset,
  3535. &LockFileKey
  3536. );
  3537. if (NT_SUCCESS( Status )) {
  3538. if (IoStatusBlock.Information != UpdateLength) {
  3539. Status = STATUS_DISK_FULL;
  3540. } else {
  3541. Length.QuadPart = IniFile->EndOfFile;
  3542. Status = NtSetInformationFile( IniFile->FileHandle,
  3543. &IoStatusBlock,
  3544. &Length,
  3545. sizeof( Length ),
  3546. FileEndOfFileInformation
  3547. );
  3548. }
  3549. }
  3550. if (!NT_SUCCESS( Status )) {
  3551. KdPrint(( "BASEDLL: Unable to write changes for %wZ to disk - Status == %x\n",
  3552. &IniFile->NtFileName,
  3553. Status
  3554. ));
  3555. }
  3556. }
  3557. NtFreeVirtualMemory( NtCurrentProcess(),
  3558. &IniFile->BaseAddress,
  3559. &IniFile->RegionSize,
  3560. MEM_RELEASE
  3561. );
  3562. IniFile->BaseAddress = NULL;
  3563. IniFile->CommitSize = 0;
  3564. IniFile->RegionSize = 0;
  3565. }
  3566. if (IniFile->LockedFile) {
  3567. ByteOffset.QuadPart = 0;
  3568. Length.QuadPart = -1;
  3569. NtUnlockFile( IniFile->FileHandle,
  3570. &IoStatusBlock,
  3571. &ByteOffset,
  3572. &Length,
  3573. HandleToUlong(NtCurrentTeb()->ClientId.UniqueThread)
  3574. );
  3575. }
  3576. CloseStatus = NtClose( IniFile->FileHandle );
  3577. if (NT_SUCCESS( Status )) {
  3578. Status = CloseStatus;
  3579. }
  3580. IniFile->FileHandle = NULL;
  3581. RtlFreeHeap( RtlProcessHeap(), 0, IniFile );
  3582. }
  3583. return Status;
  3584. }
  3585. #define STOP_AT_SECTION 1
  3586. #define STOP_AT_KEYWORD 2
  3587. #define STOP_AT_NONSECTION 3
  3588. NTSTATUS
  3589. BaseDllFindSection(
  3590. IN PINIFILE_PARAMETERS a
  3591. );
  3592. NTSTATUS
  3593. BaseDllFindKeyword(
  3594. IN PINIFILE_PARAMETERS a
  3595. );
  3596. NTSTATUS
  3597. BaseDllAdvanceTextPointer(
  3598. IN PINIFILE_PARAMETERS a,
  3599. IN ULONG StopAt
  3600. );
  3601. NTSTATUS
  3602. BaseDllReadSectionNames(
  3603. IN PINIFILE_PARAMETERS a
  3604. )
  3605. {
  3606. NTSTATUS Status;
  3607. Status = STATUS_SUCCESS;
  3608. while (NT_SUCCESS( Status )) {
  3609. Status = BaseDllAdvanceTextPointer( a, STOP_AT_SECTION );
  3610. if (Status == STATUS_MORE_ENTRIES) {
  3611. Status = BaseDllAppendStringToResultBuffer( a,
  3612. a->AnsiSectionName,
  3613. a->UnicodeSectionName,
  3614. TRUE
  3615. );
  3616. } else {
  3617. if (Status == STATUS_NO_MORE_ENTRIES) {
  3618. Status = STATUS_SUCCESS;
  3619. }
  3620. break;
  3621. }
  3622. }
  3623. return Status;
  3624. }
  3625. NTSTATUS
  3626. BaseDllReadKeywordNames(
  3627. IN PINIFILE_PARAMETERS a
  3628. )
  3629. {
  3630. NTSTATUS Status;
  3631. Status = BaseDllFindSection( a );
  3632. while (NT_SUCCESS( Status )) {
  3633. Status = BaseDllAdvanceTextPointer( a, STOP_AT_KEYWORD );
  3634. if (Status == STATUS_MORE_ENTRIES) {
  3635. Status = BaseDllAppendStringToResultBuffer( a,
  3636. a->AnsiKeywordName,
  3637. a->UnicodeKeywordName,
  3638. TRUE
  3639. );
  3640. } else {
  3641. if (Status == STATUS_NO_MORE_ENTRIES) {
  3642. Status = STATUS_SUCCESS;
  3643. }
  3644. break;
  3645. }
  3646. }
  3647. return Status;
  3648. }
  3649. NTSTATUS
  3650. BaseDllReadKeywordValue(
  3651. IN PINIFILE_PARAMETERS a
  3652. )
  3653. {
  3654. NTSTATUS Status;
  3655. Status = BaseDllFindSection( a );
  3656. if (!NT_SUCCESS( Status )) {
  3657. return Status;
  3658. }
  3659. Status = BaseDllFindKeyword( a );
  3660. if (!NT_SUCCESS( Status )) {
  3661. return Status;
  3662. }
  3663. if (a->IniFile->UnicodeFile) {
  3664. PWSTR Src;
  3665. Src = (PWSTR)a->UnicodeKeywordValue->Buffer;
  3666. while (*Src <= L' ' && a->UnicodeKeywordValue->Length) {
  3667. Src += 1;
  3668. a->UnicodeKeywordValue->Buffer = Src;
  3669. a->UnicodeKeywordValue->Length -= sizeof( WCHAR );
  3670. a->UnicodeKeywordValue->MaximumLength -= sizeof( WCHAR );
  3671. }
  3672. if (a->UnicodeKeywordValue->Length >= (2 * sizeof( WCHAR )) &&
  3673. (Src[ 0 ] == Src[ (a->UnicodeKeywordValue->Length - sizeof( WCHAR )) / sizeof( WCHAR ) ]) &&
  3674. (Src[ 0 ] == L'"' || Src[ 0 ] == L'\'')
  3675. ) {
  3676. a->UnicodeKeywordValue->Buffer += 1;
  3677. a->UnicodeKeywordValue->Length -= (2 * sizeof( WCHAR ));
  3678. a->UnicodeKeywordValue->MaximumLength -= (2 * sizeof( WCHAR ));
  3679. }
  3680. } else {
  3681. PBYTE Src;
  3682. Src = (PBYTE)a->AnsiKeywordValue->Buffer;
  3683. while (*Src <= ' ' && a->AnsiKeywordValue->Length) {
  3684. Src += 1;
  3685. a->AnsiKeywordValue->Buffer = Src;
  3686. a->AnsiKeywordValue->Length -= sizeof( UCHAR );
  3687. a->AnsiKeywordValue->MaximumLength -= sizeof( UCHAR );
  3688. }
  3689. if (a->AnsiKeywordValue->Length >= (2 * sizeof( UCHAR )) &&
  3690. (Src[ 0 ] == Src[ (a->AnsiKeywordValue->Length - sizeof( UCHAR )) / sizeof( UCHAR ) ]) &&
  3691. (Src[ 0 ] == '"' || Src[ 0 ] == '\'')
  3692. ) {
  3693. a->AnsiKeywordValue->Buffer += 1;
  3694. a->AnsiKeywordValue->Length -= (2 * sizeof( UCHAR ));
  3695. a->AnsiKeywordValue->MaximumLength -= (2 * sizeof( UCHAR ));
  3696. }
  3697. }
  3698. return BaseDllAppendStringToResultBuffer( a,
  3699. a->AnsiKeywordValue,
  3700. a->UnicodeKeywordValue,
  3701. TRUE
  3702. );
  3703. }
  3704. NTSTATUS
  3705. BaseDllReadSection(
  3706. IN PINIFILE_PARAMETERS a
  3707. )
  3708. {
  3709. NTSTATUS Status;
  3710. Status = BaseDllFindSection( a );
  3711. if (!NT_SUCCESS( Status )) {
  3712. return Status;
  3713. }
  3714. while (TRUE) {
  3715. Status = BaseDllAdvanceTextPointer( a, STOP_AT_NONSECTION );
  3716. if (Status == STATUS_MORE_ENTRIES) {
  3717. if (a->AnsiKeywordName || a->UnicodeKeywordName) {
  3718. Status = BaseDllAppendStringToResultBuffer( a,
  3719. a->AnsiKeywordName,
  3720. a->UnicodeKeywordName,
  3721. FALSE
  3722. );
  3723. if (!NT_SUCCESS( Status )) {
  3724. return Status;
  3725. }
  3726. Status = BaseDllAppendBufferToResultBuffer( a,
  3727. a->Unicode ? NULL : "=",
  3728. a->Unicode ? L"=" : NULL,
  3729. 1,
  3730. FALSE
  3731. );
  3732. if (!NT_SUCCESS( Status )) {
  3733. return Status;
  3734. }
  3735. }
  3736. if (a->IniFile->UnicodeFile) {
  3737. PWSTR Src;
  3738. Src = (PWSTR)a->UnicodeKeywordValue->Buffer;
  3739. while (*Src <= L' ' && a->UnicodeKeywordValue->Length) {
  3740. Src += 1;
  3741. a->UnicodeKeywordValue->Buffer = Src;
  3742. a->UnicodeKeywordValue->Length -= sizeof( WCHAR );
  3743. a->UnicodeKeywordValue->MaximumLength -= sizeof( WCHAR );
  3744. }
  3745. } else {
  3746. PBYTE Src;
  3747. Src = (PBYTE)a->AnsiKeywordValue->Buffer;
  3748. while (*Src <= ' ' && a->AnsiKeywordValue->Length) {
  3749. Src += 1;
  3750. a->AnsiKeywordValue->Buffer = Src;
  3751. a->AnsiKeywordValue->Length -= sizeof( UCHAR );
  3752. a->AnsiKeywordValue->MaximumLength -= sizeof( UCHAR );
  3753. }
  3754. }
  3755. Status = BaseDllAppendStringToResultBuffer( a,
  3756. a->AnsiKeywordValue,
  3757. a->UnicodeKeywordValue,
  3758. TRUE
  3759. );
  3760. if (!NT_SUCCESS( Status )) {
  3761. return Status;
  3762. }
  3763. } else {
  3764. if (Status == STATUS_NO_MORE_ENTRIES) {
  3765. Status = STATUS_SUCCESS;
  3766. }
  3767. break;
  3768. }
  3769. }
  3770. return Status;
  3771. }
  3772. NTSTATUS
  3773. BaseDllModifyMappedFile(
  3774. IN PINIFILE_PARAMETERS a,
  3775. IN PVOID AddressInFile,
  3776. IN ULONG SizeToRemove,
  3777. IN PVOID InsertBuffer,
  3778. IN ULONG InsertAmount
  3779. );
  3780. NTSTATUS
  3781. BaseDllWriteSection(
  3782. IN PINIFILE_PARAMETERS a
  3783. )
  3784. {
  3785. NTSTATUS Status;
  3786. BOOLEAN InsertSectionName;
  3787. PVOID InsertBuffer;
  3788. ULONG InsertAmount, n;
  3789. PANSI_STRING AnsiSectionName;
  3790. PUNICODE_STRING UnicodeSectionName;
  3791. PBYTE AnsiKeywordValue, s;
  3792. PWSTR UnicodeKeywordValue, w;
  3793. ULONG ValueLength, SizeToRemove;
  3794. PVOID AddressInFile;
  3795. InsertAmount = 0;
  3796. Status = BaseDllFindSection( a );
  3797. if (!NT_SUCCESS( Status )) {
  3798. if (a->Operation == DeleteSection) {
  3799. return STATUS_SUCCESS;
  3800. }
  3801. AddressInFile = a->TextEnd;
  3802. if (a->IniFile->UnicodeFile) {
  3803. if (!BaseDllGetApplicationName( a, NULL, &UnicodeSectionName )) {
  3804. return STATUS_INVALID_PARAMETER;
  3805. }
  3806. //
  3807. // Add in size of [SectionName]\r\n
  3808. //
  3809. InsertAmount += (1 + 1 + 2) * sizeof( WCHAR );
  3810. InsertAmount += UnicodeSectionName->Length;
  3811. } else {
  3812. if (!BaseDllGetApplicationName( a, &AnsiSectionName, NULL )) {
  3813. return STATUS_INVALID_PARAMETER;
  3814. }
  3815. //
  3816. // Add in size of [SectionName]\r\n
  3817. //
  3818. InsertAmount += (1 + 1 + 2) * sizeof( UCHAR );
  3819. InsertAmount += AnsiSectionName->Length;
  3820. }
  3821. InsertSectionName = TRUE;
  3822. SizeToRemove = 0;
  3823. } else {
  3824. if (a->Operation == DeleteSection) {
  3825. AddressInFile = a->TextStart;
  3826. } else {
  3827. AddressInFile = a->TextCurrent;
  3828. }
  3829. while (TRUE) {
  3830. //
  3831. // For delete operations need to iterate all lines in section,
  3832. // not just those that have an = on them. Otherwise sections like
  3833. // [foo]
  3834. // a
  3835. // b = c
  3836. // d
  3837. //
  3838. // don't get deleted properly.
  3839. //
  3840. Status = BaseDllAdvanceTextPointer(
  3841. a,
  3842. (a->Operation == DeleteSection) ? STOP_AT_NONSECTION : STOP_AT_KEYWORD
  3843. );
  3844. if (Status == STATUS_MORE_ENTRIES) {
  3845. } else
  3846. if (Status == STATUS_NO_MORE_ENTRIES) {
  3847. SizeToRemove = (ULONG)((PCHAR)a->TextCurrent - (PCHAR)AddressInFile);
  3848. break;
  3849. } else {
  3850. return Status;
  3851. }
  3852. }
  3853. InsertSectionName = FALSE;
  3854. }
  3855. if (a->Operation == DeleteSection) {
  3856. InsertBuffer = NULL;
  3857. } else {
  3858. if (a->IniFile->UnicodeFile) {
  3859. if (!BaseDllGetVariableValue( a, NULL, &UnicodeKeywordValue, &ValueLength )) {
  3860. return STATUS_INVALID_PARAMETER;
  3861. }
  3862. ValueLength -= sizeof( WCHAR );
  3863. //
  3864. // Add in size of value, + \r\n for each line
  3865. //
  3866. w = UnicodeKeywordValue;
  3867. InsertAmount += ValueLength;
  3868. while (*w) {
  3869. while (*w++) {
  3870. }
  3871. InsertAmount += (2-1) * sizeof( WCHAR ); // Subtract out NULL byte already in ValueLength
  3872. }
  3873. } else {
  3874. if (!BaseDllGetVariableValue( a, &AnsiKeywordValue, NULL, &ValueLength )) {
  3875. return STATUS_INVALID_PARAMETER;
  3876. }
  3877. ValueLength -= sizeof( UCHAR );
  3878. //
  3879. // Add in size of value, + \r\n for each line
  3880. //
  3881. s = AnsiKeywordValue;
  3882. InsertAmount += ValueLength;
  3883. while (*s) {
  3884. while (*s++) {
  3885. }
  3886. InsertAmount += 2 - 1; // Subtract out NULL byte already in ValueLength
  3887. }
  3888. }
  3889. InsertBuffer = RtlAllocateHeap( RtlProcessHeap(), MAKE_TAG( TMP_TAG ), InsertAmount + sizeof( UNICODE_NULL ) );
  3890. if (InsertBuffer == NULL) {
  3891. return STATUS_NO_MEMORY;
  3892. }
  3893. if (a->IniFile->UnicodeFile) {
  3894. PWSTR Src, Dst;
  3895. Dst = InsertBuffer;
  3896. if (InsertSectionName) {
  3897. *Dst++ = L'[';
  3898. Src = UnicodeSectionName->Buffer;
  3899. n = UnicodeSectionName->Length / sizeof( WCHAR );
  3900. while (n--) {
  3901. *Dst++ = *Src++;
  3902. }
  3903. *Dst++ = L']';
  3904. *Dst++ = L'\r';
  3905. *Dst++ = L'\n';
  3906. }
  3907. Src = UnicodeKeywordValue;
  3908. while (*Src) {
  3909. while (*Dst = *Src++) {
  3910. Dst += 1;
  3911. }
  3912. *Dst++ = L'\r';
  3913. *Dst++ = L'\n';
  3914. }
  3915. } else {
  3916. PBYTE Src, Dst;
  3917. Dst = InsertBuffer;
  3918. if (InsertSectionName) {
  3919. *Dst++ = '[';
  3920. Src = AnsiSectionName->Buffer;
  3921. n = AnsiSectionName->Length;
  3922. while (n--) {
  3923. *Dst++ = *Src++;
  3924. }
  3925. *Dst++ = ']';
  3926. *Dst++ = '\r';
  3927. *Dst++ = '\n';
  3928. }
  3929. Src = AnsiKeywordValue;
  3930. while (*Src) {
  3931. while (*Dst = *Src++) {
  3932. Dst += 1;
  3933. }
  3934. *Dst++ = '\r';
  3935. *Dst++ = '\n';
  3936. }
  3937. }
  3938. }
  3939. Status = BaseDllModifyMappedFile( a,
  3940. AddressInFile,
  3941. SizeToRemove,
  3942. InsertBuffer,
  3943. InsertAmount
  3944. );
  3945. RtlFreeHeap( RtlProcessHeap(), 0, InsertBuffer );
  3946. return Status;
  3947. }
  3948. NTSTATUS
  3949. BaseDllCalculateDeleteLength(
  3950. IN PINIFILE_PARAMETERS a
  3951. )
  3952. {
  3953. ULONG DeleteLength;
  3954. if (a->IniFile->UnicodeFile) {
  3955. DeleteLength = (ULONG)((PCHAR)a->TextCurrent -
  3956. (PCHAR)a->UnicodeKeywordName->Buffer);
  3957. } else {
  3958. DeleteLength = (ULONG)((PCHAR)a->TextCurrent -
  3959. a->AnsiKeywordName->Buffer);
  3960. }
  3961. return DeleteLength;
  3962. }
  3963. NTSTATUS
  3964. BaseDllWriteKeywordValue(
  3965. IN PINIFILE_PARAMETERS a,
  3966. IN PUNICODE_STRING VariableName OPTIONAL
  3967. )
  3968. {
  3969. NTSTATUS Status;
  3970. BOOLEAN InsertSectionName;
  3971. BOOLEAN InsertKeywordName;
  3972. PVOID InsertBuffer;
  3973. ULONG InsertAmount, n;
  3974. PANSI_STRING AnsiSectionName;
  3975. PANSI_STRING AnsiKeywordName;
  3976. PUNICODE_STRING UnicodeSectionName;
  3977. PUNICODE_STRING UnicodeKeywordName;
  3978. PBYTE AnsiKeywordValue;
  3979. PWSTR UnicodeKeywordValue;
  3980. ULONG ValueLength;
  3981. ULONG DeleteLength;
  3982. PVOID AddressInFile;
  3983. InsertAmount = 0;
  3984. Status = BaseDllFindSection( a );
  3985. if (!NT_SUCCESS( Status )) {
  3986. if (a->Operation == DeleteKey) {
  3987. return STATUS_SUCCESS;
  3988. }
  3989. AddressInFile = a->TextEnd;
  3990. if (a->IniFile->UnicodeFile) {
  3991. if (!BaseDllGetApplicationName( a, NULL, &UnicodeSectionName )) {
  3992. return STATUS_INVALID_PARAMETER;
  3993. }
  3994. //
  3995. // Add in size of [SectionName]\r\n
  3996. //
  3997. InsertAmount += (1 + 1 + 2) * sizeof( WCHAR );
  3998. InsertAmount += UnicodeSectionName->Length;
  3999. } else {
  4000. if (!BaseDllGetApplicationName( a, &AnsiSectionName, NULL )) {
  4001. return STATUS_INVALID_PARAMETER;
  4002. }
  4003. //
  4004. // Add in size of [SectionName]\r\n
  4005. //
  4006. InsertAmount += (1 + 1 + 2) * sizeof( UCHAR );
  4007. InsertAmount += AnsiSectionName->Length;
  4008. }
  4009. InsertSectionName = TRUE;
  4010. } else {
  4011. InsertSectionName = FALSE;
  4012. Status = BaseDllFindKeyword( a );
  4013. }
  4014. if (!NT_SUCCESS( Status )) {
  4015. if (a->Operation == DeleteKey) {
  4016. return STATUS_SUCCESS;
  4017. }
  4018. if (!InsertSectionName) {
  4019. AddressInFile = a->TextCurrent;
  4020. }
  4021. if (a->IniFile->UnicodeFile) {
  4022. if (!BaseDllGetVariableName( a, NULL, &UnicodeKeywordName )) {
  4023. return STATUS_INVALID_PARAMETER;
  4024. }
  4025. //
  4026. // Add in size of Keyword=\r\n
  4027. //
  4028. InsertAmount += (1 + 2) * sizeof( WCHAR );
  4029. InsertAmount += UnicodeKeywordName->Length;
  4030. } else {
  4031. if (!BaseDllGetVariableName( a, &AnsiKeywordName, NULL )) {
  4032. return STATUS_INVALID_PARAMETER;
  4033. }
  4034. //
  4035. // Add in size of Keyword=\r\n
  4036. //
  4037. InsertAmount += (1 + 2) * sizeof( UCHAR );
  4038. InsertAmount += AnsiKeywordName->Length;
  4039. }
  4040. InsertKeywordName = TRUE;
  4041. } else {
  4042. if (a->IniFile->UnicodeFile) {
  4043. if (a->Operation == DeleteKey) {
  4044. DeleteLength = BaseDllCalculateDeleteLength( a );
  4045. return BaseDllModifyMappedFile( a,
  4046. a->UnicodeKeywordName->Buffer,
  4047. DeleteLength,
  4048. NULL,
  4049. 0
  4050. );
  4051. } else {
  4052. AddressInFile = a->UnicodeKeywordValue->Buffer;
  4053. }
  4054. } else {
  4055. if (a->Operation == DeleteKey) {
  4056. DeleteLength = BaseDllCalculateDeleteLength( a );
  4057. return BaseDllModifyMappedFile( a,
  4058. a->AnsiKeywordName->Buffer,
  4059. DeleteLength,
  4060. NULL,
  4061. 0
  4062. );
  4063. } else {
  4064. AddressInFile = a->AnsiKeywordValue->Buffer;
  4065. }
  4066. }
  4067. InsertKeywordName = FALSE;
  4068. }
  4069. if (a->IniFile->UnicodeFile) {
  4070. if (!BaseDllGetVariableValue( a, NULL, &UnicodeKeywordValue, &ValueLength )) {
  4071. return STATUS_INVALID_PARAMETER;
  4072. }
  4073. ValueLength -= sizeof( WCHAR );
  4074. if (InsertAmount == 0) {
  4075. return BaseDllModifyMappedFile( a,
  4076. a->UnicodeKeywordValue->Buffer,
  4077. a->UnicodeKeywordValue->Length,
  4078. UnicodeKeywordValue,
  4079. ValueLength
  4080. );
  4081. }
  4082. //
  4083. // Add in size of value
  4084. //
  4085. InsertAmount += ValueLength;
  4086. } else {
  4087. if (!BaseDllGetVariableValue( a, &AnsiKeywordValue, NULL, &ValueLength )) {
  4088. return STATUS_INVALID_PARAMETER;
  4089. }
  4090. ValueLength -= sizeof( UCHAR );
  4091. if (InsertAmount == 0) {
  4092. return BaseDllModifyMappedFile( a,
  4093. a->AnsiKeywordValue->Buffer,
  4094. a->AnsiKeywordValue->Length,
  4095. AnsiKeywordValue,
  4096. ValueLength
  4097. );
  4098. }
  4099. //
  4100. // Add in size of value
  4101. //
  4102. InsertAmount += ValueLength;
  4103. }
  4104. InsertBuffer = RtlAllocateHeap( RtlProcessHeap(), MAKE_TAG( TMP_TAG ), InsertAmount + sizeof( UNICODE_NULL ) );
  4105. if (InsertBuffer == NULL) {
  4106. return STATUS_NO_MEMORY;
  4107. }
  4108. if (a->IniFile->UnicodeFile) {
  4109. PWSTR Src, Dst;
  4110. Dst = InsertBuffer;
  4111. if (InsertSectionName) {
  4112. *Dst++ = L'[';
  4113. Src = UnicodeSectionName->Buffer;
  4114. n = UnicodeSectionName->Length / sizeof( WCHAR );
  4115. while (n--) {
  4116. *Dst++ = *Src++;
  4117. }
  4118. *Dst++ = L']';
  4119. *Dst++ = L'\r';
  4120. *Dst++ = L'\n';
  4121. }
  4122. if (InsertKeywordName) {
  4123. Src = UnicodeKeywordName->Buffer;
  4124. n = UnicodeKeywordName->Length / sizeof( WCHAR );
  4125. while (n--) {
  4126. *Dst++ = *Src++;
  4127. }
  4128. *Dst++ = L'=';
  4129. }
  4130. Src = UnicodeKeywordValue;
  4131. n = ValueLength / sizeof( WCHAR );
  4132. while (n--) {
  4133. *Dst++ = *Src++;
  4134. }
  4135. if (InsertKeywordName) {
  4136. *Dst++ = L'\r';
  4137. *Dst++ = L'\n';
  4138. }
  4139. } else {
  4140. PBYTE Src, Dst;
  4141. Dst = InsertBuffer;
  4142. if (InsertSectionName) {
  4143. *Dst++ = '[';
  4144. Src = AnsiSectionName->Buffer;
  4145. n = AnsiSectionName->Length;
  4146. while (n--) {
  4147. *Dst++ = *Src++;
  4148. }
  4149. *Dst++ = ']';
  4150. *Dst++ = '\r';
  4151. *Dst++ = '\n';
  4152. }
  4153. if (InsertKeywordName) {
  4154. Src = AnsiKeywordName->Buffer;
  4155. n = AnsiKeywordName->Length;
  4156. while (n--) {
  4157. *Dst++ = *Src++;
  4158. }
  4159. *Dst++ = '=';
  4160. }
  4161. Src = AnsiKeywordValue;
  4162. n = ValueLength;
  4163. while (n--) {
  4164. *Dst++ = *Src++;
  4165. }
  4166. if (InsertKeywordName) {
  4167. *Dst++ = '\r';
  4168. *Dst++ = '\n';
  4169. }
  4170. }
  4171. Status = BaseDllModifyMappedFile( a,
  4172. AddressInFile,
  4173. 0,
  4174. InsertBuffer,
  4175. InsertAmount
  4176. );
  4177. RtlFreeHeap( RtlProcessHeap(), 0, InsertBuffer );
  4178. return Status;
  4179. }
  4180. NTSTATUS
  4181. BaseDllFindSection(
  4182. IN PINIFILE_PARAMETERS a
  4183. )
  4184. {
  4185. NTSTATUS Status;
  4186. PANSI_STRING AnsiSectionName;
  4187. PUNICODE_STRING UnicodeSectionName;
  4188. BOOL FreeAnsiBuffer;
  4189. while (TRUE) {
  4190. Status = BaseDllAdvanceTextPointer( a, STOP_AT_SECTION );
  4191. if (Status == STATUS_MORE_ENTRIES) {
  4192. FreeAnsiBuffer = FALSE;
  4193. if (a->AnsiSectionName) {
  4194. // Ansi ini file -- get the ansi parm
  4195. if (!BaseDllGetApplicationName( a, &AnsiSectionName, NULL )) {
  4196. return STATUS_INVALID_PARAMETER;
  4197. }
  4198. } else {
  4199. // Unicode ini file
  4200. if (a->Unicode) {
  4201. // Unicode parm - we just need the unicode section name...
  4202. if (!BaseDllGetApplicationName( a, NULL, &UnicodeSectionName )) {
  4203. return STATUS_INVALID_PARAMETER;
  4204. }
  4205. } else {
  4206. // ansi parm - convert the unicode section name to ansi
  4207. if (!BaseDllGetApplicationName( a, &AnsiSectionName, NULL ))
  4208. return STATUS_INVALID_PARAMETER;
  4209. a->AnsiSectionName = &a->SectionName;
  4210. Status = RtlUnicodeStringToAnsiString( a->AnsiSectionName,
  4211. a->UnicodeSectionName,
  4212. TRUE
  4213. );
  4214. if (!NT_SUCCESS( Status )) {
  4215. KdPrint(( "BASEDLL: UnicodeToAnsi of %wZ failed (%08x)\n", a->UnicodeSectionName, Status ));
  4216. return Status;
  4217. }
  4218. FreeAnsiBuffer = TRUE;
  4219. }
  4220. }
  4221. if (a->AnsiSectionName == NULL && a->Unicode) {
  4222. if (RtlEqualUnicodeString( UnicodeSectionName,
  4223. a->UnicodeSectionName,
  4224. TRUE
  4225. )
  4226. ) {
  4227. Status = STATUS_SUCCESS;
  4228. } else {
  4229. Status = STATUS_MORE_ENTRIES;
  4230. }
  4231. } else {
  4232. if (RtlEqualString( AnsiSectionName, a->AnsiSectionName, TRUE )) {
  4233. Status = STATUS_SUCCESS;
  4234. } else {
  4235. Status = STATUS_MORE_ENTRIES;
  4236. }
  4237. }
  4238. if (FreeAnsiBuffer) {
  4239. RtlFreeAnsiString( a->AnsiSectionName );
  4240. }
  4241. if (Status != STATUS_MORE_ENTRIES) {
  4242. return Status;
  4243. }
  4244. } else {
  4245. return STATUS_OBJECT_NAME_NOT_FOUND;
  4246. }
  4247. }
  4248. }
  4249. NTSTATUS
  4250. BaseDllFindKeyword(
  4251. IN PINIFILE_PARAMETERS a
  4252. )
  4253. {
  4254. NTSTATUS Status;
  4255. PANSI_STRING AnsiKeywordName;
  4256. PUNICODE_STRING UnicodeKeywordName;
  4257. BOOL FreeAnsiBuffer;
  4258. while (TRUE) {
  4259. Status = BaseDllAdvanceTextPointer( a, STOP_AT_KEYWORD );
  4260. if (Status == STATUS_MORE_ENTRIES) {
  4261. FreeAnsiBuffer = FALSE;
  4262. // Here's the deal. We don't want to compare in Unicode
  4263. // unless both the ini and the input parm are Unicode,
  4264. // because we want to avoid the round-trip problem (we
  4265. // lose data when we convert Unicode -> Ansi (on disk) ->
  4266. // Unicode; since we don't get back the original Unicode
  4267. // string, lookups of previously stored data fail -- bug
  4268. // 426754). So if both are Unicode, great! -- use Unicode.
  4269. // Otherwise, use ansi for everything.
  4270. if (a->AnsiKeywordName) {
  4271. // Ansi ini file -- get the ansi parm
  4272. if (!BaseDllGetVariableName( a, &AnsiKeywordName, NULL )) {
  4273. return STATUS_INVALID_PARAMETER;
  4274. }
  4275. } else {
  4276. // Unicode ini
  4277. if (a->Unicode) {
  4278. // Unicode parm - great, get the Unicode parm.
  4279. if (!BaseDllGetVariableName( a, NULL, &UnicodeKeywordName )) {
  4280. return STATUS_INVALID_PARAMETER;
  4281. }
  4282. } else {
  4283. // Ansi parm - convert the unicode ini keyword to ansi.
  4284. if (!BaseDllGetVariableName( a, &AnsiKeywordName, NULL )) {
  4285. return STATUS_INVALID_PARAMETER;
  4286. }
  4287. a->AnsiKeywordName = &a->KeywordName;
  4288. Status = RtlUnicodeStringToAnsiString( a->AnsiKeywordName,
  4289. a->UnicodeKeywordName,
  4290. TRUE
  4291. );
  4292. if (!NT_SUCCESS( Status )) {
  4293. KdPrint(( "BASEDLL: UnicodeToAnsi of %wZ failed (%08x)\n", a->UnicodeKeywordName, Status ));
  4294. return Status;
  4295. }
  4296. FreeAnsiBuffer = TRUE;
  4297. }
  4298. }
  4299. if (a->AnsiKeywordName == NULL && a->Unicode) {
  4300. if (RtlEqualUnicodeString( UnicodeKeywordName,
  4301. a->UnicodeKeywordName,
  4302. TRUE
  4303. )
  4304. ) {
  4305. Status = STATUS_SUCCESS;
  4306. } else {
  4307. Status = STATUS_MORE_ENTRIES;
  4308. }
  4309. } else {
  4310. if (RtlEqualString( AnsiKeywordName, a->AnsiKeywordName, TRUE )) {
  4311. Status = STATUS_SUCCESS;
  4312. } else {
  4313. Status = STATUS_MORE_ENTRIES;
  4314. }
  4315. }
  4316. if (FreeAnsiBuffer) {
  4317. RtlFreeAnsiString( a->AnsiKeywordName );
  4318. }
  4319. if (Status != STATUS_MORE_ENTRIES) {
  4320. return Status;
  4321. }
  4322. } else {
  4323. return STATUS_OBJECT_NAME_NOT_FOUND;
  4324. }
  4325. }
  4326. }
  4327. NTSTATUS
  4328. BaseDllAdvanceTextPointer(
  4329. IN PINIFILE_PARAMETERS a,
  4330. IN ULONG StopAt
  4331. )
  4332. {
  4333. BOOLEAN AllowNoEquals;
  4334. if (StopAt == STOP_AT_NONSECTION) {
  4335. StopAt = STOP_AT_KEYWORD;
  4336. AllowNoEquals = TRUE;
  4337. } else {
  4338. AllowNoEquals = FALSE;
  4339. }
  4340. if (a->IniFile->UnicodeFile) {
  4341. PWSTR Src, EndOfLine, EqualSign, EndOfFile;
  4342. PWSTR Name, EndOfName, Value, EndOfValue;
  4343. #define INI_TEXT(quote) L##quote
  4344. Src = a->TextCurrent;
  4345. EndOfFile = a->TextEnd;
  4346. while (Src < EndOfFile) {
  4347. //
  4348. // Find first non-blank character on a line. Skip blank lines
  4349. //
  4350. while (Src < EndOfFile && *Src <= INI_TEXT(' ')) {
  4351. Src++;
  4352. }
  4353. if (Src >= EndOfFile) {
  4354. a->TextCurrent = Src;
  4355. break;
  4356. }
  4357. EndOfLine = Src;
  4358. EqualSign = NULL;
  4359. a->TextStart = Src;
  4360. while (EndOfLine < EndOfFile) {
  4361. if (EqualSign == NULL && *EndOfLine == INI_TEXT('=')) {
  4362. EqualSign = ++EndOfLine;
  4363. } else
  4364. if (*EndOfLine == INI_TEXT('\r') || *EndOfLine == INI_TEXT('\n')) {
  4365. if (*EndOfLine == INI_TEXT('\r')) {
  4366. EndOfLine++;
  4367. }
  4368. if (*EndOfLine == INI_TEXT('\n')) {
  4369. EndOfLine++;
  4370. }
  4371. break;
  4372. } else {
  4373. EndOfLine++;
  4374. }
  4375. }
  4376. if (*Src != INI_TEXT(';')) {
  4377. if (*Src == INI_TEXT('[')) {
  4378. Name = Src + 1;
  4379. while (Name < EndOfLine && *Name <= INI_TEXT(' ')) {
  4380. Name++;
  4381. }
  4382. EndOfName = Name;
  4383. while (EndOfName < EndOfLine && *EndOfName != INI_TEXT(']')) {
  4384. EndOfName++;
  4385. }
  4386. while (EndOfName > Name && EndOfName[ -1 ] <= INI_TEXT(' ')) {
  4387. EndOfName--;
  4388. }
  4389. a->SectionNameU.Buffer = Name;
  4390. a->SectionNameU.Length = (USHORT)((PCHAR)EndOfName - (PCHAR)Name);
  4391. a->SectionNameU.MaximumLength = a->SectionNameU.Length;
  4392. a->AnsiSectionName = NULL;
  4393. a->UnicodeSectionName = &a->SectionNameU;
  4394. if (StopAt == STOP_AT_SECTION) {
  4395. a->TextCurrent = EndOfLine;
  4396. return STATUS_MORE_ENTRIES;
  4397. } else
  4398. if (StopAt == STOP_AT_KEYWORD) {
  4399. return STATUS_NO_MORE_ENTRIES;
  4400. }
  4401. } else
  4402. if (AllowNoEquals || (EqualSign != NULL) ) {
  4403. if (EqualSign != NULL) {
  4404. Name = Src;
  4405. EndOfName = EqualSign - 1;
  4406. while (EndOfName > Name && EndOfName[ -1 ] <= INI_TEXT(' ')) {
  4407. EndOfName--;
  4408. }
  4409. a->KeywordNameU.Buffer = Name;
  4410. a->KeywordNameU.Length = (USHORT)((PCHAR)EndOfName - (PCHAR)Name);
  4411. a->KeywordNameU.MaximumLength = a->KeywordNameU.Length;
  4412. a->AnsiKeywordName = NULL;
  4413. a->UnicodeKeywordName = &a->KeywordNameU;
  4414. Value = EqualSign;
  4415. } else {
  4416. Value = Src;
  4417. a->AnsiKeywordName = NULL;
  4418. a->UnicodeKeywordName = NULL;
  4419. }
  4420. EndOfValue = EndOfLine;
  4421. while (EndOfValue > Value && EndOfValue[ -1 ] <= INI_TEXT(' ')) {
  4422. EndOfValue--;
  4423. }
  4424. a->KeywordValueU.Buffer = Value;
  4425. a->KeywordValueU.Length = (USHORT)((PCHAR)EndOfValue - (PCHAR)Value);
  4426. a->KeywordValueU.MaximumLength = a->KeywordValueU.Length;
  4427. a->AnsiKeywordValue = NULL;
  4428. a->UnicodeKeywordValue = &a->KeywordValueU;
  4429. if (StopAt == STOP_AT_KEYWORD) {
  4430. a->TextCurrent = EndOfLine;
  4431. return STATUS_MORE_ENTRIES;
  4432. }
  4433. }
  4434. }
  4435. Src = EndOfLine;
  4436. }
  4437. } else {
  4438. PBYTE Src, EndOfLine, EqualSign, EndOfFile;
  4439. PBYTE Name, EndOfName, Value, EndOfValue;
  4440. #undef INI_TEXT
  4441. #define INI_TEXT(quote) quote
  4442. Src = a->TextCurrent;
  4443. EndOfFile = a->TextEnd;
  4444. while (Src < EndOfFile) {
  4445. //
  4446. // Find first non-blank character on a line. Skip blank lines
  4447. //
  4448. while (Src < EndOfFile && *Src <= INI_TEXT(' ')) {
  4449. Src++;
  4450. }
  4451. if (Src >= EndOfFile) {
  4452. a->TextCurrent = Src;
  4453. break;
  4454. }
  4455. EndOfLine = Src;
  4456. EqualSign = NULL;
  4457. a->TextStart = Src;
  4458. while (EndOfLine < EndOfFile) {
  4459. if (EqualSign == NULL && *EndOfLine == INI_TEXT('=')) {
  4460. EqualSign = ++EndOfLine;
  4461. } else
  4462. if (*EndOfLine == INI_TEXT('\r') || *EndOfLine == INI_TEXT('\n')) {
  4463. if (*EndOfLine == INI_TEXT('\r')) {
  4464. EndOfLine++;
  4465. }
  4466. if (*EndOfLine == INI_TEXT('\n')) {
  4467. EndOfLine++;
  4468. }
  4469. break;
  4470. } else {
  4471. EndOfLine++;
  4472. }
  4473. }
  4474. if (*Src != INI_TEXT(';')) {
  4475. if (*Src == INI_TEXT('[')) {
  4476. Name = Src + 1;
  4477. while (Name < EndOfLine && *Name <= INI_TEXT(' ')) {
  4478. Name++;
  4479. }
  4480. EndOfName = Name;
  4481. while (EndOfName < EndOfLine) {
  4482. if (*EndOfName == INI_TEXT(']')) {
  4483. break;
  4484. }
  4485. if (IsDBCSLeadByte(*EndOfName)) {
  4486. EndOfName++;
  4487. }
  4488. EndOfName++;
  4489. }
  4490. while (EndOfName > Name && EndOfName[ -1 ] <= INI_TEXT(' ')) {
  4491. EndOfName--;
  4492. }
  4493. a->SectionName.Buffer = Name;
  4494. a->SectionName.Length = (USHORT)((PCHAR)EndOfName - (PCHAR)Name);
  4495. a->SectionName.MaximumLength = a->SectionName.Length;
  4496. a->AnsiSectionName = &a->SectionName;
  4497. a->UnicodeSectionName = NULL;
  4498. if (StopAt == STOP_AT_SECTION) {
  4499. a->TextCurrent = EndOfLine;
  4500. return STATUS_MORE_ENTRIES;
  4501. } else
  4502. if (StopAt == STOP_AT_KEYWORD) {
  4503. return STATUS_NO_MORE_ENTRIES;
  4504. }
  4505. } else
  4506. if (AllowNoEquals || (EqualSign != NULL)) {
  4507. if (EqualSign != NULL) {
  4508. Name = Src;
  4509. EndOfName = EqualSign - 1;
  4510. while (EndOfName > Name && EndOfName[ -1 ] <= INI_TEXT(' ')) {
  4511. EndOfName--;
  4512. }
  4513. a->KeywordName.Buffer = Name;
  4514. a->KeywordName.Length = (USHORT)((PCHAR)EndOfName - (PCHAR)Name);
  4515. a->KeywordName.MaximumLength = a->KeywordName.Length;
  4516. a->AnsiKeywordName = &a->KeywordName;
  4517. a->UnicodeKeywordName = NULL;
  4518. Value = EqualSign;
  4519. } else {
  4520. Value = Src;
  4521. a->AnsiKeywordName = NULL;
  4522. a->UnicodeKeywordName = NULL;
  4523. }
  4524. EndOfValue = EndOfLine;
  4525. while (EndOfValue > Value && EndOfValue[ -1 ] <= INI_TEXT(' ')) {
  4526. EndOfValue--;
  4527. }
  4528. a->KeywordValue.Buffer = Value;
  4529. a->KeywordValue.Length = (USHORT)((PCHAR)EndOfValue - (PCHAR)Value);
  4530. a->KeywordValue.MaximumLength = a->KeywordValue.Length;
  4531. a->AnsiKeywordValue = &a->KeywordValue;
  4532. a->UnicodeKeywordValue = NULL;
  4533. if (StopAt == STOP_AT_KEYWORD) {
  4534. a->TextCurrent = EndOfLine;
  4535. return STATUS_MORE_ENTRIES;
  4536. }
  4537. }
  4538. }
  4539. Src = EndOfLine;
  4540. }
  4541. }
  4542. return STATUS_NO_MORE_ENTRIES;
  4543. }
  4544. NTSTATUS
  4545. BaseDllModifyMappedFile(
  4546. IN PINIFILE_PARAMETERS a,
  4547. IN PVOID AddressInFile,
  4548. IN ULONG SizeToRemove,
  4549. IN PVOID InsertBuffer,
  4550. IN ULONG InsertAmount
  4551. )
  4552. {
  4553. NTSTATUS Status;
  4554. ULONG NewEndOfFile, UpdateOffset, UpdateLength;
  4555. NewEndOfFile = a->IniFile->EndOfFile - SizeToRemove + InsertAmount;
  4556. if (NewEndOfFile > a->IniFile->CommitSize) {
  4557. if (NewEndOfFile > a->IniFile->RegionSize) {
  4558. return STATUS_BUFFER_OVERFLOW;
  4559. }
  4560. a->IniFile->CommitSize = NewEndOfFile;
  4561. Status = NtAllocateVirtualMemory( NtCurrentProcess(),
  4562. &a->IniFile->BaseAddress,
  4563. 0,
  4564. &a->IniFile->CommitSize,
  4565. MEM_COMMIT,
  4566. PAGE_READWRITE
  4567. );
  4568. if (!NT_SUCCESS( Status )) {
  4569. KdPrint(( "BASEDLL: Unable to allocate memory to grow %wZ - Status == %x\n",
  4570. &a->IniFile->NtFileName,
  4571. Status
  4572. ));
  4573. return Status;
  4574. }
  4575. a->IniFile->EndOfFile = NewEndOfFile;
  4576. }
  4577. UpdateOffset = (ULONG)((PCHAR)AddressInFile - (PCHAR)(a->IniFile->BaseAddress)),
  4578. UpdateLength = (ULONG)((PCHAR)a->TextEnd - (PCHAR)AddressInFile) + InsertAmount - SizeToRemove;
  4579. //
  4580. // Are we deleting more than we are inserting?
  4581. //
  4582. if (SizeToRemove > InsertAmount) {
  4583. //
  4584. // Yes copy over insert string.
  4585. //
  4586. RtlMoveMemory( AddressInFile, InsertBuffer, InsertAmount );
  4587. //
  4588. // Delete remaining text after insertion string by moving it
  4589. // up
  4590. //
  4591. RtlMoveMemory( (PCHAR)AddressInFile + InsertAmount,
  4592. (PCHAR)AddressInFile + SizeToRemove,
  4593. UpdateLength - InsertAmount
  4594. );
  4595. } else
  4596. if (InsertAmount > 0) {
  4597. //
  4598. // Are we deleting less than we are inserting?
  4599. //
  4600. if (SizeToRemove < InsertAmount) {
  4601. //
  4602. // Move text down to make room for insertion
  4603. //
  4604. RtlMoveMemory( (PCHAR)AddressInFile + InsertAmount - SizeToRemove,
  4605. (PCHAR)AddressInFile,
  4606. UpdateLength - InsertAmount + SizeToRemove
  4607. );
  4608. } else {
  4609. //
  4610. // Deleting and inserting same amount, update just that text as
  4611. // no shifting was done.
  4612. //
  4613. UpdateLength = InsertAmount;
  4614. }
  4615. //
  4616. // Copy over insert string
  4617. //
  4618. RtlMoveMemory( AddressInFile, InsertBuffer, InsertAmount );
  4619. } else {
  4620. //
  4621. // Nothing to change, as InsertAmount and SizeToRemove are zero
  4622. //
  4623. return STATUS_SUCCESS;
  4624. }
  4625. if (a->IniFile->EndOfFile != NewEndOfFile) {
  4626. a->IniFile->EndOfFile = NewEndOfFile;
  4627. }
  4628. if (UpdateOffset < a->IniFile->UpdateOffset) {
  4629. a->IniFile->UpdateOffset = UpdateOffset;
  4630. }
  4631. if ((UpdateOffset + UpdateLength) > a->IniFile->UpdateEndOffset) {
  4632. a->IniFile->UpdateEndOffset = UpdateOffset + UpdateLength;
  4633. }
  4634. return STATUS_SUCCESS;
  4635. }
  4636. VOID
  4637. BaseDllCheckInitFromIniFile(
  4638. IN DWORD Flags,
  4639. IN ULONG MappingFlags,
  4640. IN PUNICODE_STRING FileName,
  4641. IN PUNICODE_STRING ApplicationName,
  4642. IN PUNICODE_STRING KeyName,
  4643. IN OUT PWSTR *Buffer,
  4644. IN OUT PULONG Size
  4645. );
  4646. BOOL
  4647. QueryWin31IniFilesMappedToRegistry(
  4648. IN DWORD Flags,
  4649. OUT PWSTR Buffer,
  4650. IN DWORD cchBuffer,
  4651. OUT LPDWORD cchUsed
  4652. )
  4653. {
  4654. BOOL Result;
  4655. PINIFILE_MAPPING_FILENAME FileNameMapping;
  4656. PINIFILE_MAPPING_APPNAME AppNameMapping;
  4657. PINIFILE_MAPPING_VARNAME VarNameMapping;
  4658. UNICODE_STRING NullString;
  4659. ULONG Size;
  4660. *cchUsed = 0;
  4661. RtlInitUnicodeString( &NullString, NULL );
  4662. Result = TRUE;
  4663. Size = cchBuffer * sizeof( WCHAR );
  4664. FileNameMapping = (PINIFILE_MAPPING_FILENAME)BaseDllIniFileMapping->DefaultFileNameMapping;
  4665. if (FileNameMapping != NULL) {
  4666. AppNameMapping = (PINIFILE_MAPPING_APPNAME)FileNameMapping->DefaultAppNameMapping;
  4667. VarNameMapping = (PINIFILE_MAPPING_VARNAME)AppNameMapping->DefaultVarNameMapping;
  4668. BaseDllCheckInitFromIniFile( Flags,
  4669. VarNameMapping->MappingFlags,
  4670. &NullString,
  4671. &NullString,
  4672. &NullString,
  4673. &Buffer,
  4674. &Size
  4675. );
  4676. }
  4677. FileNameMapping = (PINIFILE_MAPPING_FILENAME)BaseDllIniFileMapping->FileNames;
  4678. while (FileNameMapping) {
  4679. AppNameMapping = (PINIFILE_MAPPING_APPNAME)FileNameMapping->DefaultAppNameMapping;
  4680. if (AppNameMapping != NULL) {
  4681. BASE_READ_REMOTE_STR_TEMP(TempStr);
  4682. VarNameMapping = (PINIFILE_MAPPING_VARNAME)AppNameMapping->DefaultVarNameMapping;
  4683. BaseDllCheckInitFromIniFile( Flags,
  4684. VarNameMapping->MappingFlags,
  4685. BASE_READ_REMOTE_STR(FileNameMapping->Name,TempStr),
  4686. &NullString,
  4687. &NullString,
  4688. &Buffer,
  4689. &Size
  4690. );
  4691. }
  4692. AppNameMapping = (PINIFILE_MAPPING_APPNAME)FileNameMapping->ApplicationNames;
  4693. while (AppNameMapping) {
  4694. VarNameMapping = (PINIFILE_MAPPING_VARNAME)AppNameMapping->DefaultVarNameMapping;
  4695. if (VarNameMapping != NULL) {
  4696. BASE_READ_REMOTE_STR_TEMP(TempStr1);
  4697. BASE_READ_REMOTE_STR_TEMP(TempStr2);
  4698. BaseDllCheckInitFromIniFile( Flags,
  4699. VarNameMapping->MappingFlags,
  4700. BASE_READ_REMOTE_STR(FileNameMapping->Name, TempStr1),
  4701. BASE_READ_REMOTE_STR(AppNameMapping->Name, TempStr2),
  4702. &NullString,
  4703. &Buffer,
  4704. &Size
  4705. );
  4706. }
  4707. VarNameMapping = (PINIFILE_MAPPING_VARNAME)AppNameMapping->VariableNames;
  4708. while (VarNameMapping) {
  4709. BASE_READ_REMOTE_STR_TEMP(TempStr1);
  4710. BASE_READ_REMOTE_STR_TEMP(TempStr2);
  4711. BASE_READ_REMOTE_STR_TEMP(TempStr3);
  4712. BaseDllCheckInitFromIniFile( Flags,
  4713. VarNameMapping->MappingFlags,
  4714. BASE_READ_REMOTE_STR(FileNameMapping->Name,TempStr1),
  4715. BASE_READ_REMOTE_STR(AppNameMapping->Name,TempStr2),
  4716. BASE_READ_REMOTE_STR(VarNameMapping->Name,TempStr3),
  4717. &Buffer,
  4718. &Size
  4719. );
  4720. VarNameMapping = (PINIFILE_MAPPING_VARNAME)VarNameMapping->Next;
  4721. }
  4722. AppNameMapping = (PINIFILE_MAPPING_APPNAME)AppNameMapping->Next;
  4723. }
  4724. FileNameMapping = (PINIFILE_MAPPING_FILENAME)FileNameMapping->Next;
  4725. }
  4726. if (Result) {
  4727. *cchUsed = (((cchBuffer * sizeof( WCHAR )) - Size) / sizeof( WCHAR )) + 1;
  4728. }
  4729. return Result;
  4730. }
  4731. VOID
  4732. BaseDllCheckInitFromIniFile(
  4733. IN DWORD Flags,
  4734. IN ULONG MappingFlags,
  4735. IN PUNICODE_STRING FileName,
  4736. IN PUNICODE_STRING ApplicationName,
  4737. IN PUNICODE_STRING KeyName,
  4738. IN OUT PWSTR *Buffer,
  4739. IN OUT PULONG Size
  4740. )
  4741. {
  4742. PWSTR s;
  4743. ULONG cb;
  4744. if (MappingFlags & INIFILE_MAPPING_INIT_FROM_INIFILE) {
  4745. cb = FileName->Length + sizeof( UNICODE_NULL ) +
  4746. ApplicationName->Length + sizeof( UNICODE_NULL ) +
  4747. KeyName->Length + sizeof( UNICODE_NULL );
  4748. if (MappingFlags & INIFILE_MAPPING_USER_RELATIVE) {
  4749. if (!(Flags & WIN31_INIFILES_MAPPED_TO_USER)) {
  4750. return;
  4751. }
  4752. } else
  4753. if (!(Flags & WIN31_INIFILES_MAPPED_TO_SYSTEM)) {
  4754. return;
  4755. }
  4756. if ((cb+sizeof( UNICODE_NULL )) < *Size) {
  4757. *Size = *Size - cb;
  4758. s = *Buffer;
  4759. if (FileName->Length) {
  4760. RtlMoveMemory( s, FileName->Buffer, FileName->Length );
  4761. s = (PWSTR)((PCHAR)s + FileName->Length);
  4762. }
  4763. *s++ = UNICODE_NULL;
  4764. if (ApplicationName->Length) {
  4765. RtlMoveMemory( s, ApplicationName->Buffer, ApplicationName->Length );
  4766. s = (PWSTR)((PCHAR)s + ApplicationName->Length);
  4767. }
  4768. *s++ = UNICODE_NULL;
  4769. if (KeyName->Length) {
  4770. RtlMoveMemory( s, KeyName->Buffer, KeyName->Length );
  4771. s = (PWSTR)((PCHAR)s + KeyName->Length);
  4772. }
  4773. *s++ = UNICODE_NULL;
  4774. *s = UNICODE_NULL;
  4775. *Buffer = s;
  4776. }
  4777. }
  4778. return;
  4779. }
  4780. #if DBG
  4781. VOID
  4782. BaseDllDumpIniFileMappings(
  4783. PINIFILE_MAPPING IniFileMapping
  4784. );
  4785. VOID
  4786. BaseDllPrintMappingTarget(
  4787. IN PINIFILE_MAPPING_VARNAME VarNameMapping
  4788. );
  4789. VOID
  4790. BaseDllDumpIniFileMappings(
  4791. PINIFILE_MAPPING IniFileMapping
  4792. )
  4793. {
  4794. PINIFILE_MAPPING_FILENAME FileNameMapping;
  4795. PINIFILE_MAPPING_APPNAME AppNameMapping;
  4796. PINIFILE_MAPPING_VARNAME VarNameMapping;
  4797. DbgPrint( "IniFileMapping\n" );
  4798. FileNameMapping = (PINIFILE_MAPPING_FILENAME)IniFileMapping->DefaultFileNameMapping;
  4799. if (FileNameMapping != NULL) {
  4800. AppNameMapping = (PINIFILE_MAPPING_APPNAME)FileNameMapping->DefaultAppNameMapping;
  4801. VarNameMapping = (PINIFILE_MAPPING_VARNAME)AppNameMapping->DefaultVarNameMapping;
  4802. DbgPrint( " " );
  4803. BaseDllPrintMappingTarget( VarNameMapping );
  4804. }
  4805. FileNameMapping = (PINIFILE_MAPPING_FILENAME)IniFileMapping->FileNames;
  4806. while (FileNameMapping) {
  4807. BASE_READ_REMOTE_STR_TEMP(TempStr);
  4808. DbgPrint( " %wZ\n",
  4809. BASE_READ_REMOTE_STR(FileNameMapping->Name,TempStr)
  4810. );
  4811. AppNameMapping = (PINIFILE_MAPPING_APPNAME)FileNameMapping->DefaultAppNameMapping;
  4812. if (AppNameMapping != NULL) {
  4813. VarNameMapping = (PINIFILE_MAPPING_VARNAME)AppNameMapping->DefaultVarNameMapping;
  4814. DbgPrint( " " );
  4815. BaseDllPrintMappingTarget( VarNameMapping );
  4816. }
  4817. AppNameMapping = (PINIFILE_MAPPING_APPNAME)FileNameMapping->ApplicationNames;
  4818. while (AppNameMapping) {
  4819. BASE_READ_REMOTE_STR_TEMP(TempStr);
  4820. DbgPrint( " %wZ\n",
  4821. BASE_READ_REMOTE_STR(AppNameMapping->Name,TempStr)
  4822. );
  4823. VarNameMapping = (PINIFILE_MAPPING_VARNAME)AppNameMapping->DefaultVarNameMapping;
  4824. if (VarNameMapping != NULL) {
  4825. DbgPrint( " " );
  4826. BaseDllPrintMappingTarget( VarNameMapping );
  4827. }
  4828. VarNameMapping = (PINIFILE_MAPPING_VARNAME)AppNameMapping->VariableNames;
  4829. while (VarNameMapping) {
  4830. BASE_READ_REMOTE_STR_TEMP(TempStr);
  4831. DbgPrint( " %wZ ",
  4832. BASE_READ_REMOTE_STR(VarNameMapping->Name, TempStr) );
  4833. BaseDllPrintMappingTarget( VarNameMapping );
  4834. VarNameMapping = (PINIFILE_MAPPING_VARNAME)VarNameMapping->Next;
  4835. }
  4836. AppNameMapping = (PINIFILE_MAPPING_APPNAME)AppNameMapping->Next;
  4837. }
  4838. FileNameMapping = (PINIFILE_MAPPING_FILENAME)FileNameMapping->Next;
  4839. }
  4840. return;
  4841. }
  4842. VOID
  4843. BaseDllPrintMappingTarget(
  4844. IN PINIFILE_MAPPING_VARNAME VarNameMapping
  4845. )
  4846. {
  4847. DbgPrint( "= " );
  4848. if (VarNameMapping->MappingFlags &INIFILE_MAPPING_WRITE_TO_INIFILE_TOO) {
  4849. DbgPrint( "!" );
  4850. }
  4851. if (VarNameMapping->MappingFlags &INIFILE_MAPPING_INIT_FROM_INIFILE) {
  4852. DbgPrint( "#" );
  4853. }
  4854. if (VarNameMapping->MappingFlags &INIFILE_MAPPING_READ_FROM_REGISTRY_ONLY) {
  4855. DbgPrint( "@" );
  4856. }
  4857. if (VarNameMapping->MappingFlags &INIFILE_MAPPING_USER_RELATIVE) {
  4858. DbgPrint( "USR:" );
  4859. }
  4860. if (VarNameMapping->MappingFlags &INIFILE_MAPPING_SOFTWARE_RELATIVE) {
  4861. DbgPrint( "SYS:" );
  4862. }
  4863. if (VarNameMapping->MappingTarget) {
  4864. BASE_READ_REMOTE_STR_TEMP(TempStr);
  4865. DbgPrint( "%wZ",
  4866. BASE_READ_REMOTE_STR((((PINIFILE_MAPPING_TARGET)(VarNameMapping->MappingTarget))->RegistryPath), TempStr)
  4867. );
  4868. }
  4869. if (VarNameMapping->MappingFlags &INIFILE_MAPPING_APPEND_BASE_NAME) {
  4870. DbgPrint( " (Append Base Name)" );
  4871. }
  4872. if (VarNameMapping->MappingFlags &INIFILE_MAPPING_APPEND_APPLICATION_NAME) {
  4873. DbgPrint( " (Append App Name)" );
  4874. }
  4875. DbgPrint( "\n" );
  4876. }
  4877. #endif // DBG