Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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