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.

2559 lines
68 KiB

  1. /*****************************************************************************/
  2. /*
  3. /* Copyright (c) 2001 Microsoft Corporation, All Rights Reserved /
  4. /*
  5. /*****************************************************************************/
  6. #include "precomp.h"
  7. #include "WMI_FilePrivateProfile.h"
  8. #define STOP_AT_SECTION 1
  9. #define STOP_AT_KEYWORD 2
  10. #define STOP_AT_NONSECTION 3
  11. #define BYTE_ORDER_MARK 0xFEFF
  12. #define REVERSE_BYTE_ORDER_MARK 0xFFFE
  13. ULONG LockFileKey = 1;
  14. DWORD
  15. APIENTRY
  16. WMI_FILE_GetPrivateProfileStringW(
  17. LPCWSTR lpAppName,
  18. LPCWSTR lpKeyName,
  19. LPCWSTR lpDefault,
  20. LPWSTR lpReturnedString,
  21. DWORD nSize,
  22. LPCWSTR lpFileName
  23. )
  24. {
  25. NTSTATUS Status;
  26. ULONG n;
  27. if (lpDefault == NULL) {
  28. lpDefault = L"";
  29. }
  30. n = nSize;
  31. Status = CWMI_FILE_IniFile::ReadWriteIniFile(FALSE, // WriteOperation
  32. FALSE, // SectionOperation
  33. lpFileName,
  34. lpAppName,
  35. lpKeyName,
  36. lpReturnedString,
  37. &n
  38. );
  39. if (NT_SUCCESS( Status ) || Status == STATUS_BUFFER_OVERFLOW) {
  40. if (NT_SUCCESS( Status )) {
  41. SetLastError( NO_ERROR );
  42. n--;
  43. } else
  44. if (!lpAppName || !lpKeyName) {
  45. if (nSize >= 2) {
  46. n = nSize - 2;
  47. lpReturnedString[ n+1 ] = UNICODE_NULL;
  48. } else {
  49. n = 0;
  50. }
  51. } else {
  52. if (nSize >= 1) {
  53. n = nSize - 1;
  54. } else {
  55. n = 0;
  56. }
  57. }
  58. } else {
  59. n = wcslen( lpDefault );
  60. while (n > 0 && lpDefault[n-1] == L' ') {
  61. n -= 1;
  62. }
  63. if (n >= nSize) {
  64. n = nSize;
  65. }
  66. wcsncpy( lpReturnedString, lpDefault, n );
  67. }
  68. if (n < nSize) {
  69. lpReturnedString[ n ] = UNICODE_NULL;
  70. } else
  71. if (nSize > 0) {
  72. lpReturnedString[ nSize-1 ] = UNICODE_NULL;
  73. }
  74. return( n );
  75. }
  76. UINT
  77. APIENTRY
  78. WMI_FILE_GetPrivateProfileIntW(
  79. LPCWSTR lpAppName,
  80. LPCWSTR lpKeyName,
  81. INT nDefault,
  82. LPCWSTR lpFileName
  83. )
  84. {
  85. NTSTATUS Status;
  86. ULONG ReturnValue;
  87. WCHAR ValueBuffer[ 256 ];
  88. UNICODE_STRING Value;
  89. ANSI_STRING AnsiString;
  90. ULONG cb;
  91. ReturnValue = 0;
  92. cb = WMI_FILE_GetPrivateProfileStringW(lpAppName,
  93. lpKeyName,
  94. NULL,
  95. ValueBuffer,
  96. sizeof( ValueBuffer ) / sizeof( WCHAR ),
  97. lpFileName
  98. );
  99. if (cb == 0)
  100. {
  101. ReturnValue = nDefault;
  102. }
  103. else
  104. {
  105. Value.Buffer = ValueBuffer;
  106. Value.Length = (USHORT)(cb * sizeof( WCHAR ));
  107. Value.MaximumLength = (USHORT)((cb + 1) * sizeof( WCHAR ));
  108. Status = RtlUnicodeStringToAnsiString( &AnsiString,
  109. &Value,
  110. TRUE
  111. );
  112. if (NT_SUCCESS( Status ))
  113. {
  114. Status = RtlCharToInteger( AnsiString.Buffer, 0, &ReturnValue );
  115. RtlFreeAnsiString( &AnsiString );
  116. }
  117. if (!NT_SUCCESS( Status ))
  118. {
  119. SetLastError( Status );
  120. }
  121. else
  122. {
  123. SetLastError( NO_ERROR );
  124. }
  125. }
  126. return ReturnValue;
  127. }
  128. BOOL
  129. APIENTRY
  130. WMI_FILE_WritePrivateProfileStringW(
  131. LPCWSTR lpAppName,
  132. LPCWSTR lpKeyName,
  133. LPCWSTR lpString,
  134. LPCWSTR lpFileName
  135. )
  136. {
  137. NTSTATUS Status;
  138. Status = CWMI_FILE_IniFile::ReadWriteIniFile(TRUE, // WriteOperation
  139. FALSE, // SectionOperation
  140. lpFileName,
  141. lpAppName,
  142. lpKeyName,
  143. (LPWSTR)(lpKeyName == NULL ? NULL : lpString),
  144. NULL
  145. );
  146. if (NT_SUCCESS( Status )) {
  147. return( TRUE );
  148. } else {
  149. if (Status == STATUS_INVALID_IMAGE_FORMAT) {
  150. SetLastError( ERROR_INVALID_DATA );
  151. } else {
  152. SetLastError( Status );
  153. }
  154. return( FALSE );
  155. }
  156. }
  157. DWORD
  158. APIENTRY
  159. WMI_FILE_GetPrivateProfileSectionW(
  160. LPCWSTR lpAppName,
  161. LPWSTR lpReturnedString,
  162. DWORD nSize,
  163. LPCWSTR lpFileName
  164. )
  165. {
  166. NTSTATUS Status;
  167. ULONG n;
  168. n = nSize;
  169. Status = CWMI_FILE_IniFile::ReadWriteIniFile(FALSE, // WriteOperation
  170. TRUE, // SectionOperation
  171. lpFileName,
  172. lpAppName,
  173. NULL,
  174. lpReturnedString,
  175. &n
  176. );
  177. if (NT_SUCCESS( Status ) || Status == STATUS_BUFFER_OVERFLOW) {
  178. if (NT_SUCCESS( Status )) {
  179. SetLastError( NO_ERROR );
  180. n--;
  181. } else
  182. if (nSize >= 2) {
  183. n = nSize - 2;
  184. lpReturnedString[ n+1 ] = UNICODE_NULL;
  185. } else {
  186. n = 0;
  187. }
  188. } else {
  189. if (Status == STATUS_INVALID_IMAGE_FORMAT) {
  190. SetLastError( ERROR_INVALID_DATA );
  191. } else {
  192. SetLastError( Status );
  193. }
  194. n = 0;
  195. }
  196. if (n < nSize) {
  197. lpReturnedString[ n ] = UNICODE_NULL;
  198. } else
  199. if (nSize > 0) {
  200. lpReturnedString[ nSize-1 ] = UNICODE_NULL;
  201. }
  202. return( n );
  203. }
  204. BOOL
  205. APIENTRY
  206. WMI_FILE_WritePrivateProfileSectionW(
  207. LPCWSTR lpAppName,
  208. LPCWSTR lpString,
  209. LPCWSTR lpFileName
  210. )
  211. {
  212. NTSTATUS Status;
  213. Status = CWMI_FILE_IniFile::ReadWriteIniFile(TRUE, // WriteOperation
  214. TRUE, // SectionOperation
  215. lpFileName,
  216. lpAppName,
  217. NULL,
  218. (LPWSTR)lpString,
  219. NULL
  220. );
  221. if (NT_SUCCESS( Status ))
  222. {
  223. return( TRUE );
  224. }
  225. else
  226. {
  227. if (Status == STATUS_INVALID_IMAGE_FORMAT)
  228. {
  229. SetLastError( ERROR_INVALID_DATA );
  230. }
  231. else
  232. {
  233. SetLastError( Status );
  234. }
  235. return( FALSE );
  236. }
  237. }
  238. CWMI_FILE_IniFileObject::CWMI_FILE_IniFileObject()
  239. {
  240. m_EnvironmentUpdateCount = 0;
  241. m_FileHandle = INVALID_HANDLE_VALUE;
  242. m_WriteAccess = FALSE;
  243. m_UnicodeFile = FALSE;
  244. m_LockedFile = FALSE;
  245. m_EndOfFile = 0;
  246. m_BaseAddress = NULL;
  247. m_CommitSize = 0;
  248. m_RegionSize = 0;
  249. m_UpdateOffset = 0;
  250. m_UpdateEndOffset = 0;
  251. m_DirectoryInformationLength = 0;
  252. }
  253. CWMI_FILE_IniFileObject::~CWMI_FILE_IniFileObject()
  254. {
  255. if ((m_FileHandle != INVALID_HANDLE_VALUE) && (m_FileHandle != NULL))
  256. {
  257. NtClose(m_FileHandle);
  258. m_FileHandle = INVALID_HANDLE_VALUE;
  259. }
  260. }
  261. CWMI_FILE_IniFile::CWMI_FILE_IniFile()
  262. {
  263. RtlInitAnsiString( &m_VariableName, NULL );
  264. RtlInitUnicodeString( &m_VariableNameU, NULL );
  265. RtlInitAnsiString( &m_ApplicationName, NULL );
  266. RtlInitUnicodeString( &m_ApplicationNameU, NULL );
  267. m_Operation = Enum_ReadKeyValueOp;
  268. m_IsWriteOperation = FALSE;
  269. m_FileName = NULL;
  270. m_IsMultiValueStrings = FALSE;
  271. m_ValueBuffer = NULL;
  272. m_ValueLength = 0;
  273. m_ValueBufferU = NULL;
  274. m_ValueLengthU = 0;
  275. m_ResultChars = 0;
  276. m_ResultMaxChars = 0;
  277. m_ResultBufferU = NULL;
  278. m_TextCurrent = NULL;
  279. m_TextStart = NULL;
  280. m_TextEnd = NULL;
  281. }
  282. CWMI_FILE_IniFile::~CWMI_FILE_IniFile()
  283. {
  284. if (m_VariableName.Buffer)
  285. {
  286. delete [] m_VariableName.Buffer;
  287. m_VariableName.Buffer = NULL;
  288. }
  289. if (m_ApplicationName.Buffer)
  290. {
  291. delete [] m_ApplicationName.Buffer;
  292. m_ApplicationName.Buffer = NULL;
  293. }
  294. if (m_ValueBuffer)
  295. {
  296. delete [] m_ValueBuffer;
  297. m_ValueBuffer = NULL;
  298. }
  299. }
  300. NTSTATUS CWMI_FILE_IniFile::ReadWriteIniFile(
  301. IN BOOL WriteOperation,
  302. IN BOOL SectionOperation,
  303. IN LPCWSTR FileName,
  304. IN LPCWSTR ApplicationName,
  305. IN LPCWSTR VariableName,
  306. IN OUT LPWSTR VariableValue,
  307. IN OUT PULONG VariableValueLength
  308. )
  309. {
  310. NTSTATUS Status = STATUS_SUCCESS;
  311. BOOL MultiValueStrings = FALSE;;
  312. INIFILE_OPERATION Operation;
  313. if (SectionOperation) {
  314. VariableName = NULL;
  315. }
  316. MultiValueStrings = FALSE;
  317. if (WriteOperation)
  318. {
  319. if (ApplicationName)
  320. {
  321. if (VariableName)
  322. {
  323. if (VariableValue)
  324. {
  325. Operation = Enum_WriteKeyValueOp;
  326. }
  327. else
  328. {
  329. Status = STATUS_INVALID_PARAMETER;
  330. }
  331. }
  332. else
  333. {
  334. if (VariableValue)
  335. {
  336. Operation = Enum_WriteSectionOp;
  337. MultiValueStrings = TRUE;
  338. }
  339. else
  340. {
  341. Status = STATUS_INVALID_PARAMETER;
  342. }
  343. }
  344. }
  345. else
  346. {
  347. Status = STATUS_INVALID_PARAMETER;
  348. }
  349. }
  350. else
  351. {
  352. if (ApplicationName)
  353. {
  354. if (!ARGUMENT_PRESENT( VariableValue ))
  355. {
  356. Status = STATUS_INVALID_PARAMETER;
  357. }
  358. else
  359. {
  360. if (VariableName)
  361. {
  362. Operation = Enum_ReadKeyValueOp;
  363. }
  364. else
  365. {
  366. if (SectionOperation)
  367. {
  368. Operation = Enum_ReadSectionOp;
  369. MultiValueStrings = TRUE;
  370. }
  371. else
  372. {
  373. Operation = Enum_ReadKeyNamesOp;
  374. MultiValueStrings = TRUE;
  375. }
  376. }
  377. }
  378. }
  379. else
  380. {
  381. if ( ! ( SectionOperation || !ARGUMENT_PRESENT( VariableValue ) ) )
  382. {
  383. Operation = Enum_ReadSectionNamesOp;
  384. MultiValueStrings = TRUE;
  385. }
  386. else
  387. {
  388. Status = STATUS_INVALID_PARAMETER;
  389. }
  390. }
  391. }
  392. if (NT_SUCCESS( Status ))
  393. {
  394. CWMI_FILE_IniFile myIni;
  395. Status = myIni.CaptureIniFileParameters(Operation,
  396. WriteOperation,
  397. MultiValueStrings,
  398. FileName,
  399. ApplicationName,
  400. VariableName,
  401. VariableValue,
  402. VariableValueLength
  403. );
  404. if (NT_SUCCESS( Status ))
  405. {
  406. Status = myIni.ReadWriteIniFileOnDisk();
  407. if (NT_SUCCESS( Status ))
  408. {
  409. if (myIni.m_Operation == Enum_ReadSectionNamesOp ||
  410. myIni.m_Operation == Enum_ReadKeyNamesOp ||
  411. myIni.m_Operation == Enum_ReadSectionOp )
  412. {
  413. myIni.AppendNullToResultBuffer();
  414. }
  415. }
  416. if (NT_SUCCESS( Status ) || Status == STATUS_BUFFER_OVERFLOW)
  417. {
  418. if (!myIni.m_IsWriteOperation)
  419. {
  420. if (ARGUMENT_PRESENT( VariableValueLength ))
  421. {
  422. *VariableValueLength = myIni.m_ResultChars;
  423. }
  424. }
  425. }
  426. }
  427. }
  428. return Status;
  429. }
  430. NTSTATUS CWMI_FILE_IniFile::CaptureIniFileParameters(
  431. INIFILE_OPERATION a_Operation,
  432. BOOL a_WriteOperation,
  433. BOOL a_MultiValueStrings,
  434. LPCWSTR a_FileName,
  435. LPCWSTR a_ApplicationName,
  436. LPCWSTR a_VariableName,
  437. LPWSTR a_VariableValue,
  438. PULONG a_ResultMaxChars
  439. )
  440. {
  441. NTSTATUS Status = STATUS_SUCCESS;
  442. m_Operation = a_Operation;
  443. m_IsWriteOperation = a_WriteOperation;
  444. m_IsMultiValueStrings = a_MultiValueStrings;
  445. if (a_FileName)
  446. {
  447. m_FileName = a_FileName;
  448. }
  449. if (a_ApplicationName)
  450. {
  451. RtlInitUnicodeString(&m_ApplicationNameU, a_ApplicationName);
  452. }
  453. if (a_VariableName)
  454. {
  455. RtlInitUnicodeString(&m_VariableNameU, a_VariableName);
  456. }
  457. ULONG uVariableValueLength = 0;
  458. if (a_VariableValue )
  459. {
  460. if (!a_ResultMaxChars)
  461. {
  462. if (!a_MultiValueStrings)
  463. {
  464. uVariableValueLength = wcslen( a_VariableValue );
  465. }
  466. else
  467. {
  468. LPWSTR p = a_VariableValue;
  469. while (*p)
  470. {
  471. while (*p++)
  472. {
  473. }
  474. }
  475. uVariableValueLength = (ULONG)(p - a_VariableValue);
  476. }
  477. }
  478. if (m_IsWriteOperation)
  479. {
  480. m_ValueBufferU = a_VariableValue;
  481. m_ValueLengthU = uVariableValueLength * sizeof( WCHAR );
  482. m_ValueBuffer = NULL;
  483. m_ValueLength = 0;
  484. }
  485. else
  486. {
  487. if (a_ResultMaxChars)
  488. {
  489. m_ResultMaxChars = *a_ResultMaxChars;
  490. }
  491. m_ResultChars = 0;
  492. m_ResultBufferU = a_VariableValue;
  493. }
  494. }
  495. return Status;
  496. }
  497. NTSTATUS CWMI_FILE_IniFile::OpenIniFileOnDisk()
  498. {
  499. NTSTATUS Status = STATUS_SUCCESS;
  500. UNICODE_STRING FullFileName;
  501. OBJECT_ATTRIBUTES ObjectAttributes;
  502. IO_STATUS_BLOCK IoStatusBlock;
  503. LARGE_INTEGER ByteOffset;
  504. LARGE_INTEGER Length;
  505. m_IniFile.m_WriteAccess = m_IsWriteOperation;
  506. RtlInitUnicodeString(&FullFileName, NULL);
  507. if (!RtlDosPathNameToNtPathName_U( m_FileName,
  508. &FullFileName,
  509. NULL,
  510. NULL
  511. )
  512. )
  513. {
  514. return STATUS_OBJECT_PATH_NOT_FOUND;
  515. }
  516. try
  517. {
  518. InitializeObjectAttributes( &ObjectAttributes,
  519. &FullFileName,
  520. OBJ_CASE_INSENSITIVE,
  521. NULL,
  522. NULL
  523. );
  524. if (m_IniFile.m_WriteAccess)
  525. {
  526. Status = NtCreateFile( &m_IniFile.m_FileHandle,
  527. SYNCHRONIZE | GENERIC_READ | GENERIC_WRITE,
  528. &ObjectAttributes,
  529. &IoStatusBlock,
  530. 0,
  531. FILE_ATTRIBUTE_NORMAL,
  532. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  533. FILE_OPEN_IF,
  534. FILE_SYNCHRONOUS_IO_NONALERT |
  535. FILE_NON_DIRECTORY_FILE,
  536. NULL,
  537. 0
  538. );
  539. }
  540. else
  541. {
  542. Status = NtOpenFile( &m_IniFile.m_FileHandle,
  543. SYNCHRONIZE | GENERIC_READ,
  544. &ObjectAttributes,
  545. &IoStatusBlock,
  546. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  547. FILE_SYNCHRONOUS_IO_NONALERT |
  548. FILE_NON_DIRECTORY_FILE
  549. );
  550. }
  551. }
  552. catch(...)
  553. {
  554. RtlFreeUnicodeString(&FullFileName);
  555. RtlInitUnicodeString(&FullFileName, NULL);
  556. throw;
  557. }
  558. RtlFreeUnicodeString( &FullFileName );
  559. RtlInitUnicodeString(&FullFileName, NULL);
  560. if (NT_SUCCESS( Status ))
  561. {
  562. ByteOffset.QuadPart = 0;
  563. Length.QuadPart = -1;
  564. Status = NtLockFile( m_IniFile.m_FileHandle,
  565. NULL,
  566. NULL,
  567. NULL,
  568. &IoStatusBlock,
  569. &ByteOffset,
  570. &Length,
  571. LockFileKey,
  572. FALSE,
  573. (BOOLEAN)m_IniFile.m_WriteAccess
  574. );
  575. if (NT_SUCCESS( Status ))
  576. {
  577. m_IniFile.m_LockedFile = TRUE;
  578. }
  579. if (NT_SUCCESS( Status ))
  580. {
  581. Status = NtQueryInformationFile( m_IniFile.m_FileHandle,
  582. &IoStatusBlock,
  583. &m_IniFile.m_StandardInformation,
  584. sizeof( m_IniFile.m_StandardInformation ),
  585. FileStandardInformation
  586. );
  587. if (Status == STATUS_BUFFER_OVERFLOW)
  588. {
  589. Status = STATUS_SUCCESS;
  590. }
  591. }
  592. }
  593. if (!NT_SUCCESS( Status ))
  594. {
  595. if ((m_IniFile.m_FileHandle != INVALID_HANDLE_VALUE) && (m_IniFile.m_FileHandle != NULL))
  596. {
  597. if (m_IniFile.m_LockedFile)
  598. {
  599. m_IniFile.m_LockedFile = FALSE;
  600. ByteOffset.QuadPart = 0;
  601. Length.QuadPart = -1;
  602. NtUnlockFile( m_IniFile.m_FileHandle,
  603. &IoStatusBlock,
  604. &ByteOffset,
  605. &Length,
  606. LockFileKey
  607. );
  608. }
  609. NtClose( m_IniFile.m_FileHandle );
  610. m_IniFile.m_FileHandle = INVALID_HANDLE_VALUE;
  611. }
  612. return Status;
  613. }
  614. else
  615. {
  616. m_IniFile.m_EndOfFile = m_IniFile.m_StandardInformation.EndOfFile.LowPart;
  617. m_IniFile.m_CommitSize = m_IniFile.m_EndOfFile + (4 * (m_IniFile.m_UnicodeFile ? sizeof( WCHAR ) : 1));
  618. m_IniFile.m_RegionSize = m_IniFile.m_CommitSize + 0x100000; // Room for 256KB of growth
  619. Status = NtAllocateVirtualMemory( NtCurrentProcess(),
  620. &m_IniFile.m_BaseAddress,
  621. 0,
  622. &m_IniFile.m_RegionSize,
  623. MEM_RESERVE,
  624. PAGE_READWRITE
  625. );
  626. if (NT_SUCCESS( Status ))
  627. {
  628. Status = NtAllocateVirtualMemory( NtCurrentProcess(),
  629. &m_IniFile.m_BaseAddress,
  630. 0,
  631. &m_IniFile.m_CommitSize,
  632. MEM_COMMIT,
  633. PAGE_READWRITE
  634. );
  635. if (NT_SUCCESS( Status )) {
  636. Status = NtReadFile( m_IniFile.m_FileHandle,
  637. NULL,
  638. NULL,
  639. NULL,
  640. &IoStatusBlock,
  641. m_IniFile.m_BaseAddress,
  642. m_IniFile.m_EndOfFile,
  643. NULL,
  644. &LockFileKey
  645. );
  646. if (NT_SUCCESS( Status ) && IoStatusBlock.Information != m_IniFile.m_EndOfFile) {
  647. Status = STATUS_END_OF_FILE;
  648. }
  649. }
  650. }
  651. }
  652. if (NT_SUCCESS( Status ))
  653. {
  654. // We would like to check the possibility of IS_TEXT_UNICODE_DBCS_LEADBYTE.
  655. INT iResult = ~0x0;
  656. m_IniFile.m_UpdateOffset = 0xFFFFFFFF;
  657. m_IniFile.m_UpdateEndOffset = 0;
  658. m_IniFile.m_UnicodeFile = RtlIsTextUnicode( m_IniFile.m_BaseAddress, m_IniFile.m_EndOfFile, (PULONG)&iResult );
  659. if (m_IniFile.m_UnicodeFile)
  660. {
  661. LPWSTR Src = (LPWSTR)((PCHAR)m_IniFile.m_BaseAddress + m_IniFile.m_EndOfFile);
  662. while (Src > (LPWSTR)m_IniFile.m_BaseAddress && Src[ -1 ] <= L' ')
  663. {
  664. if (Src[-1] == L'\r' || Src[-1] == L'\n')
  665. {
  666. break;
  667. }
  668. m_IniFile.m_EndOfFile -= sizeof( WCHAR );
  669. Src -= 1;
  670. }
  671. Src = (LPWSTR)((PCHAR)m_IniFile.m_BaseAddress + m_IniFile.m_EndOfFile);
  672. if (Src > (LPWSTR)m_IniFile.m_BaseAddress)
  673. {
  674. if (Src[-1] != L'\n')
  675. {
  676. *Src++ = L'\r';
  677. *Src++ = L'\n';
  678. m_IniFile.m_UpdateOffset = m_IniFile.m_EndOfFile;
  679. m_IniFile.m_UpdateEndOffset = m_IniFile.m_UpdateOffset + 2 * sizeof( WCHAR );
  680. m_IniFile.m_EndOfFile = m_IniFile.m_UpdateEndOffset;
  681. }
  682. }
  683. }
  684. else
  685. {
  686. LPBYTE Src = (PBYTE)((PCHAR)m_IniFile.m_BaseAddress + m_IniFile.m_EndOfFile);
  687. while (Src > (PBYTE)m_IniFile.m_BaseAddress && Src[ -1 ] <= ' ')
  688. {
  689. if (Src[-1] == '\r' || Src[-1] == '\n') {
  690. break;
  691. }
  692. m_IniFile.m_EndOfFile -= 1;
  693. Src -= 1;
  694. }
  695. Src = (PBYTE)((PCHAR)m_IniFile.m_BaseAddress + m_IniFile.m_EndOfFile);
  696. if (Src > (PBYTE)m_IniFile.m_BaseAddress)
  697. {
  698. if (Src[-1] != '\n') {
  699. *Src++ = '\r';
  700. *Src++ = '\n';
  701. m_IniFile.m_UpdateOffset = m_IniFile.m_EndOfFile;
  702. m_IniFile.m_UpdateEndOffset = m_IniFile.m_UpdateOffset + 2;
  703. m_IniFile.m_EndOfFile = m_IniFile.m_UpdateEndOffset;
  704. }
  705. }
  706. }
  707. }
  708. else
  709. {
  710. if ((m_IniFile.m_FileHandle != INVALID_HANDLE_VALUE) && (m_IniFile.m_FileHandle != NULL))
  711. {
  712. if (m_IniFile.m_LockedFile)
  713. {
  714. m_IniFile.m_LockedFile = FALSE;
  715. ByteOffset.QuadPart = 0;
  716. Length.QuadPart = -1;
  717. NtUnlockFile( m_IniFile.m_FileHandle,
  718. &IoStatusBlock,
  719. &ByteOffset,
  720. &Length,
  721. LockFileKey
  722. );
  723. }
  724. NtClose( m_IniFile.m_FileHandle );
  725. m_IniFile.m_FileHandle = INVALID_HANDLE_VALUE;
  726. }
  727. }
  728. return Status;
  729. }
  730. NTSTATUS CWMI_FILE_IniFile::ReadWriteIniFileOnDisk()
  731. {
  732. NTSTATUS Status;
  733. ULONG PartialResultChars = 0;
  734. if (!m_IsWriteOperation) {
  735. PartialResultChars = m_ResultChars;
  736. }
  737. Status = OpenIniFileOnDisk();
  738. if (NT_SUCCESS( Status ))
  739. {
  740. try
  741. {
  742. m_TextEnd = (PCHAR)m_IniFile.m_BaseAddress + m_IniFile.m_EndOfFile;
  743. m_TextCurrent = m_IniFile.m_BaseAddress;
  744. if (m_IniFile.m_UnicodeFile &&
  745. ((*(PWCHAR)m_TextCurrent == BYTE_ORDER_MARK) ||
  746. (*(PWCHAR)m_TextCurrent == REVERSE_BYTE_ORDER_MARK)))
  747. {
  748. // Skip past the BOM.
  749. PWCHAR foo = (PWCHAR)m_TextCurrent;
  750. foo++;
  751. m_TextCurrent = (PVOID)foo;
  752. }
  753. if ( m_Operation == Enum_ReadSectionNamesOp )
  754. {
  755. Status = ReadSectionNames();
  756. }
  757. else if (m_Operation == Enum_ReadKeyValueOp)
  758. {
  759. Status = ReadKeywordValue();
  760. }
  761. else if (m_Operation == Enum_ReadKeyNamesOp)
  762. {
  763. Status = ReadKeywordNames();
  764. }
  765. else if (m_Operation == Enum_ReadSectionOp)
  766. {
  767. Status = ReadSection();
  768. }
  769. else if (m_Operation == Enum_WriteKeyValueOp)
  770. {
  771. Status = WriteKeywordValue(NULL );
  772. }
  773. else if (m_Operation == Enum_WriteSectionOp)
  774. {
  775. Status = WriteSection();
  776. }
  777. else
  778. {
  779. Status = STATUS_INVALID_PARAMETER;
  780. }
  781. NTSTATUS CloseStatus;
  782. CloseStatus = CloseIniFileOnDisk();
  783. if (NT_SUCCESS( Status ))
  784. {
  785. Status = CloseStatus;
  786. }
  787. }
  788. catch (...)
  789. {
  790. NTSTATUS CloseStatus;
  791. CloseStatus = CloseIniFileOnDisk();
  792. if (NT_SUCCESS( Status ))
  793. {
  794. Status = CloseStatus;
  795. }
  796. }
  797. }
  798. if (Status == STATUS_OBJECT_NAME_NOT_FOUND &&
  799. !m_IsWriteOperation &&
  800. PartialResultChars != 0
  801. )
  802. {
  803. Status = STATUS_SUCCESS;
  804. }
  805. return Status;
  806. }
  807. NTSTATUS CWMI_FILE_IniFile::CloseIniFileOnDisk()
  808. {
  809. NTSTATUS Status = STATUS_SUCCESS;
  810. NTSTATUS CloseStatus = STATUS_SUCCESS;
  811. IO_STATUS_BLOCK IoStatusBlock;
  812. ULONG UpdateLength = 0;
  813. LARGE_INTEGER ByteOffset;
  814. LARGE_INTEGER Length;
  815. if ((m_IniFile.m_FileHandle != INVALID_HANDLE_VALUE) && (m_IniFile.m_FileHandle != NULL))
  816. {
  817. if (m_IniFile.m_BaseAddress != NULL)
  818. {
  819. if (m_IniFile.m_UpdateOffset != 0xFFFFFFFF && m_IniFile.m_WriteAccess)
  820. {
  821. ByteOffset.HighPart = 0;
  822. ByteOffset.LowPart = m_IniFile.m_UpdateOffset;
  823. UpdateLength = m_IniFile.m_UpdateEndOffset - m_IniFile.m_UpdateOffset;
  824. Status = NtWriteFile( m_IniFile.m_FileHandle,
  825. NULL,
  826. NULL,
  827. NULL,
  828. &IoStatusBlock,
  829. (PCHAR)(m_IniFile.m_BaseAddress) + m_IniFile.m_UpdateOffset,
  830. UpdateLength,
  831. &ByteOffset,
  832. &LockFileKey
  833. );
  834. if (NT_SUCCESS( Status ))
  835. {
  836. if (IoStatusBlock.Information != UpdateLength)
  837. {
  838. Status = STATUS_DISK_FULL;
  839. }
  840. else
  841. {
  842. Length.QuadPart = m_IniFile.m_EndOfFile;
  843. Status = NtSetInformationFile( m_IniFile.m_FileHandle,
  844. &IoStatusBlock,
  845. &Length,
  846. sizeof( Length ),
  847. FileEndOfFileInformation
  848. );
  849. }
  850. }
  851. }
  852. NtFreeVirtualMemory( NtCurrentProcess(),
  853. &m_IniFile.m_BaseAddress,
  854. &m_IniFile.m_RegionSize,
  855. MEM_RELEASE
  856. );
  857. m_IniFile.m_BaseAddress = NULL;
  858. m_IniFile.m_CommitSize = 0;
  859. m_IniFile.m_RegionSize = 0;
  860. }
  861. if (m_IniFile.m_LockedFile)
  862. {
  863. m_IniFile.m_LockedFile = FALSE;
  864. ByteOffset.QuadPart = 0;
  865. Length.QuadPart = -1;
  866. NtUnlockFile( m_IniFile.m_FileHandle,
  867. &IoStatusBlock,
  868. &ByteOffset,
  869. &Length,
  870. LockFileKey
  871. );
  872. }
  873. CloseStatus = NtClose( m_IniFile.m_FileHandle );
  874. m_IniFile.m_FileHandle = INVALID_HANDLE_VALUE;
  875. if (NT_SUCCESS( Status ))
  876. {
  877. Status = CloseStatus;
  878. }
  879. }
  880. return Status;
  881. }
  882. NTSTATUS CWMI_FILE_IniFile::ReadSectionNames()
  883. {
  884. NTSTATUS Status;
  885. Status = STATUS_SUCCESS;
  886. while (NT_SUCCESS( Status ))
  887. {
  888. Status = AdvanceTextPointer( STOP_AT_SECTION );
  889. if (Status == STATUS_MORE_ENTRIES) {
  890. Status = AppendStringToResultBuffer(m_AnsiSectionName,
  891. m_UnicodeSectionName,
  892. TRUE
  893. );
  894. }
  895. else
  896. {
  897. if (Status == STATUS_NO_MORE_ENTRIES)
  898. {
  899. Status = STATUS_SUCCESS;
  900. }
  901. break;
  902. }
  903. }
  904. return Status;
  905. }
  906. NTSTATUS CWMI_FILE_IniFile::ReadKeywordNames()
  907. {
  908. NTSTATUS Status;
  909. Status = FindSection();
  910. while (NT_SUCCESS( Status ))
  911. {
  912. Status = AdvanceTextPointer( STOP_AT_KEYWORD );
  913. if (Status == STATUS_MORE_ENTRIES)
  914. {
  915. Status = AppendStringToResultBuffer( m_AnsiKeywordName,
  916. m_UnicodeKeywordName,
  917. TRUE
  918. );
  919. }
  920. else
  921. {
  922. if (Status == STATUS_NO_MORE_ENTRIES)
  923. {
  924. Status = STATUS_SUCCESS;
  925. }
  926. break;
  927. }
  928. }
  929. return Status;
  930. }
  931. NTSTATUS CWMI_FILE_IniFile::ReadKeywordValue()
  932. {
  933. NTSTATUS Status = FindSection();
  934. if (!NT_SUCCESS( Status ))
  935. {
  936. return Status;
  937. }
  938. Status = FindKeyword();
  939. if (!NT_SUCCESS( Status ))
  940. {
  941. return Status;
  942. }
  943. if (m_IniFile.m_UnicodeFile)
  944. {
  945. LPWSTR Src = (LPWSTR)m_UnicodeKeywordValue->Buffer;
  946. while (*Src <= L' ' && m_UnicodeKeywordValue->Length)
  947. {
  948. Src += 1;
  949. m_UnicodeKeywordValue->Buffer = Src;
  950. m_UnicodeKeywordValue->Length -= sizeof( WCHAR );
  951. m_UnicodeKeywordValue->MaximumLength -= sizeof( WCHAR );
  952. }
  953. if (m_UnicodeKeywordValue->Length >= (2 * sizeof( WCHAR )) &&
  954. (Src[ 0 ] == Src[ (m_UnicodeKeywordValue->Length - sizeof( WCHAR )) / sizeof( WCHAR ) ]) &&
  955. (Src[ 0 ] == L'"' || Src[ 0 ] == L'\'')
  956. ) {
  957. m_UnicodeKeywordValue->Buffer += 1;
  958. m_UnicodeKeywordValue->Length -= (2 * sizeof( WCHAR ));
  959. m_UnicodeKeywordValue->MaximumLength -= (2 * sizeof( WCHAR ));
  960. }
  961. }
  962. else
  963. {
  964. PBYTE Src;
  965. Src = (PBYTE)m_AnsiKeywordValue->Buffer;
  966. while (*Src <= ' ' && m_AnsiKeywordValue->Length) {
  967. Src += 1;
  968. m_AnsiKeywordValue->Buffer = (PCHAR)Src;
  969. m_AnsiKeywordValue->Length -= sizeof( UCHAR );
  970. m_AnsiKeywordValue->MaximumLength -= sizeof( UCHAR );
  971. }
  972. if (m_AnsiKeywordValue->Length >= (2 * sizeof( UCHAR )) &&
  973. (Src[ 0 ] == Src[ (m_AnsiKeywordValue->Length - sizeof( UCHAR )) / sizeof( UCHAR ) ]) &&
  974. (Src[ 0 ] == '"' || Src[ 0 ] == '\'')
  975. ) {
  976. m_AnsiKeywordValue->Buffer += 1;
  977. m_AnsiKeywordValue->Length -= (2 * sizeof( UCHAR ));
  978. m_AnsiKeywordValue->MaximumLength -= (2 * sizeof( UCHAR ));
  979. }
  980. }
  981. return AppendStringToResultBuffer(m_AnsiKeywordValue,
  982. m_UnicodeKeywordValue,
  983. TRUE
  984. );
  985. }
  986. NTSTATUS CWMI_FILE_IniFile::ReadSection()
  987. {
  988. NTSTATUS Status;
  989. Status = FindSection();
  990. if (!NT_SUCCESS( Status )) {
  991. return Status;
  992. }
  993. while (TRUE) {
  994. Status = AdvanceTextPointer( STOP_AT_NONSECTION );
  995. if (Status == STATUS_MORE_ENTRIES) {
  996. if (m_AnsiKeywordName || m_UnicodeKeywordName) {
  997. Status = AppendStringToResultBuffer(m_AnsiKeywordName,
  998. m_UnicodeKeywordName,
  999. FALSE
  1000. );
  1001. if (!NT_SUCCESS( Status )) {
  1002. return Status;
  1003. }
  1004. Status = AppendBufferToResultBuffer(NULL,
  1005. L"=",
  1006. 1,
  1007. FALSE
  1008. );
  1009. if (!NT_SUCCESS( Status )) {
  1010. return Status;
  1011. }
  1012. }
  1013. if (m_IniFile.m_UnicodeFile) {
  1014. LPWSTR Src;
  1015. Src = (LPWSTR)m_UnicodeKeywordValue->Buffer;
  1016. while (*Src <= L' ' && m_UnicodeKeywordValue->Length) {
  1017. Src += 1;
  1018. m_UnicodeKeywordValue->Buffer = Src;
  1019. m_UnicodeKeywordValue->Length -= sizeof( WCHAR );
  1020. m_UnicodeKeywordValue->MaximumLength -= sizeof( WCHAR );
  1021. }
  1022. } else {
  1023. PBYTE Src;
  1024. Src = (PBYTE)m_AnsiKeywordValue->Buffer;
  1025. while (*Src <= ' ' && m_AnsiKeywordValue->Length) {
  1026. Src += 1;
  1027. m_AnsiKeywordValue->Buffer = (PCHAR)Src;
  1028. m_AnsiKeywordValue->Length -= sizeof( UCHAR );
  1029. m_AnsiKeywordValue->MaximumLength -= sizeof( UCHAR );
  1030. }
  1031. }
  1032. Status = AppendStringToResultBuffer(m_AnsiKeywordValue,
  1033. m_UnicodeKeywordValue,
  1034. TRUE
  1035. );
  1036. if (!NT_SUCCESS( Status )) {
  1037. return Status;
  1038. }
  1039. } else {
  1040. if (Status == STATUS_NO_MORE_ENTRIES) {
  1041. Status = STATUS_SUCCESS;
  1042. }
  1043. break;
  1044. }
  1045. }
  1046. return Status;
  1047. }
  1048. NTSTATUS CWMI_FILE_IniFile::FindSection()
  1049. {
  1050. NTSTATUS Status;
  1051. PANSI_STRING AnsiSectionName;
  1052. PUNICODE_STRING UnicodeSectionName;
  1053. while (TRUE)
  1054. {
  1055. Status = AdvanceTextPointer(STOP_AT_SECTION );
  1056. if (Status == STATUS_MORE_ENTRIES)
  1057. {
  1058. if (m_AnsiSectionName)
  1059. {
  1060. // Ansi ini file -- get the ansi parm
  1061. if (!GetApplicationName(&AnsiSectionName, NULL ))
  1062. {
  1063. return STATUS_INVALID_PARAMETER;
  1064. }
  1065. }
  1066. else
  1067. {
  1068. // we just need the unicode section name...
  1069. if (!GetApplicationName(NULL, &UnicodeSectionName ))
  1070. {
  1071. return STATUS_INVALID_PARAMETER;
  1072. }
  1073. }
  1074. if (m_AnsiSectionName == NULL)
  1075. {
  1076. if (RtlEqualUnicodeString( UnicodeSectionName,
  1077. m_UnicodeSectionName,
  1078. TRUE
  1079. )
  1080. )
  1081. {
  1082. Status = STATUS_SUCCESS;
  1083. }
  1084. else
  1085. {
  1086. Status = STATUS_MORE_ENTRIES;
  1087. }
  1088. }
  1089. else
  1090. {
  1091. if (RtlEqualString( AnsiSectionName, m_AnsiSectionName, TRUE ))
  1092. {
  1093. Status = STATUS_SUCCESS;
  1094. }
  1095. else
  1096. {
  1097. Status = STATUS_MORE_ENTRIES;
  1098. }
  1099. }
  1100. if (Status != STATUS_MORE_ENTRIES)
  1101. {
  1102. return Status;
  1103. }
  1104. }
  1105. else
  1106. {
  1107. return STATUS_OBJECT_NAME_NOT_FOUND;
  1108. }
  1109. }
  1110. }
  1111. NTSTATUS CWMI_FILE_IniFile::FindKeyword()
  1112. {
  1113. NTSTATUS Status = STATUS_SUCCESS;
  1114. PANSI_STRING AnsiKeywordName;
  1115. PUNICODE_STRING UnicodeKeywordName;
  1116. while (TRUE) {
  1117. Status = AdvanceTextPointer(STOP_AT_KEYWORD);
  1118. if (Status == STATUS_MORE_ENTRIES) {
  1119. // Here's the deal. We don't want to compare in Unicode
  1120. // unless both the ini and the input parm are Unicode,
  1121. // because we want to avoid the round-trip problem (we
  1122. // lose data when we convert Unicode -> Ansi (on disk) ->
  1123. // Unicode; since we don't get back the original Unicode
  1124. // string, lookups of previously stored data fail -- bug
  1125. // 426754). So if both are Unicode, great! -- use Unicode.
  1126. // Otherwise, use ansi for everything.
  1127. if (m_AnsiKeywordName) {
  1128. // Ansi ini file -- get the ansi parm
  1129. if (!GetVariableName(&AnsiKeywordName, NULL )) {
  1130. return STATUS_INVALID_PARAMETER;
  1131. }
  1132. } else {
  1133. //great, get the Unicode parm.
  1134. if (!GetVariableName(NULL, &UnicodeKeywordName )) {
  1135. return STATUS_INVALID_PARAMETER;
  1136. }
  1137. }
  1138. if (m_AnsiKeywordName == NULL) {
  1139. if (RtlEqualUnicodeString( UnicodeKeywordName,
  1140. m_UnicodeKeywordName,
  1141. TRUE
  1142. )
  1143. ) {
  1144. Status = STATUS_SUCCESS;
  1145. } else {
  1146. Status = STATUS_MORE_ENTRIES;
  1147. }
  1148. } else {
  1149. if (RtlEqualString( AnsiKeywordName, m_AnsiKeywordName, TRUE )) {
  1150. Status = STATUS_SUCCESS;
  1151. } else {
  1152. Status = STATUS_MORE_ENTRIES;
  1153. }
  1154. }
  1155. if (Status != STATUS_MORE_ENTRIES) {
  1156. return Status;
  1157. }
  1158. } else {
  1159. return STATUS_OBJECT_NAME_NOT_FOUND;
  1160. }
  1161. }
  1162. }
  1163. NTSTATUS CWMI_FILE_IniFile::AdvanceTextPointer( IN ULONG StopAt )
  1164. {
  1165. BOOL AllowNoEquals = FALSE;
  1166. if (StopAt == STOP_AT_NONSECTION)
  1167. {
  1168. StopAt = STOP_AT_KEYWORD;
  1169. AllowNoEquals = TRUE;
  1170. }
  1171. if (m_IniFile.m_UnicodeFile)
  1172. {
  1173. LPWSTR Name, EndOfName, Value, EndOfValue;
  1174. #undef INI_TEXT
  1175. #define INI_TEXT(quote) L##quote
  1176. LPWSTR Src = (LPWSTR)m_TextCurrent;
  1177. LPWSTR EndOfFile = (LPWSTR)m_TextEnd;
  1178. while (Src < EndOfFile)
  1179. {
  1180. //
  1181. // Find first non-blank character on a line. Skip blank lines
  1182. //
  1183. while (Src < EndOfFile && *Src <= INI_TEXT(' '))
  1184. {
  1185. Src++;
  1186. }
  1187. if (Src >= EndOfFile)
  1188. {
  1189. m_TextCurrent = Src;
  1190. break;
  1191. }
  1192. LPWSTR EndOfLine = Src;
  1193. LPWSTR EqualSign = NULL;
  1194. m_TextStart = Src;
  1195. while (EndOfLine < EndOfFile)
  1196. {
  1197. if (EqualSign == NULL && *EndOfLine == INI_TEXT('='))
  1198. {
  1199. EqualSign = ++EndOfLine;
  1200. }
  1201. else if (*EndOfLine == INI_TEXT('\r') || *EndOfLine == INI_TEXT('\n'))
  1202. {
  1203. if (*EndOfLine == INI_TEXT('\r'))
  1204. {
  1205. EndOfLine++;
  1206. }
  1207. if (*EndOfLine == INI_TEXT('\n'))
  1208. {
  1209. EndOfLine++;
  1210. }
  1211. break;
  1212. }
  1213. else
  1214. {
  1215. EndOfLine++;
  1216. }
  1217. }
  1218. if (*Src != INI_TEXT(';'))
  1219. {
  1220. if (*Src == INI_TEXT('['))
  1221. {
  1222. Name = Src + 1;
  1223. while (Name < EndOfLine && *Name <= INI_TEXT(' '))
  1224. {
  1225. Name++;
  1226. }
  1227. EndOfName = Name;
  1228. while (EndOfName < EndOfLine && *EndOfName != INI_TEXT(']'))
  1229. {
  1230. EndOfName++;
  1231. }
  1232. while (EndOfName > Name && EndOfName[ -1 ] <= INI_TEXT(' '))
  1233. {
  1234. EndOfName--;
  1235. }
  1236. m_SectionNameU.Buffer = Name;
  1237. m_SectionNameU.Length = (USHORT)((PCHAR)EndOfName - (PCHAR)Name);
  1238. m_SectionNameU.MaximumLength = m_SectionNameU.Length;
  1239. m_AnsiSectionName = NULL;
  1240. m_UnicodeSectionName = &m_SectionNameU;
  1241. if (StopAt == STOP_AT_SECTION)
  1242. {
  1243. m_TextCurrent = EndOfLine;
  1244. return STATUS_MORE_ENTRIES;
  1245. }
  1246. else if (StopAt == STOP_AT_KEYWORD)
  1247. {
  1248. return STATUS_NO_MORE_ENTRIES;
  1249. }
  1250. }
  1251. else if (AllowNoEquals || (EqualSign != NULL) )
  1252. {
  1253. if (EqualSign != NULL)
  1254. {
  1255. Name = Src;
  1256. EndOfName = EqualSign - 1;
  1257. while (EndOfName > Name && EndOfName[ -1 ] <= INI_TEXT(' '))
  1258. {
  1259. EndOfName--;
  1260. }
  1261. m_KeywordNameU.Buffer = Name;
  1262. m_KeywordNameU.Length = (USHORT)((PCHAR)EndOfName - (PCHAR)Name);
  1263. m_KeywordNameU.MaximumLength = m_KeywordNameU.Length;
  1264. m_AnsiKeywordName = NULL;
  1265. m_UnicodeKeywordName = &m_KeywordNameU;
  1266. Value = EqualSign;
  1267. }
  1268. else
  1269. {
  1270. Value = Src;
  1271. m_AnsiKeywordName = NULL;
  1272. m_UnicodeKeywordName = NULL;
  1273. }
  1274. EndOfValue = EndOfLine;
  1275. while (EndOfValue > Value && EndOfValue[ -1 ] <= INI_TEXT(' '))
  1276. {
  1277. EndOfValue--;
  1278. }
  1279. m_KeywordValueU.Buffer = Value;
  1280. m_KeywordValueU.Length = (USHORT)((PCHAR)EndOfValue - (PCHAR)Value);
  1281. m_KeywordValueU.MaximumLength = m_KeywordValueU.Length;
  1282. m_AnsiKeywordValue = NULL;
  1283. m_UnicodeKeywordValue = &m_KeywordValueU;
  1284. if (StopAt == STOP_AT_KEYWORD)
  1285. {
  1286. m_TextCurrent = EndOfLine;
  1287. return STATUS_MORE_ENTRIES;
  1288. }
  1289. }
  1290. }
  1291. Src = EndOfLine;
  1292. }
  1293. }
  1294. else
  1295. {
  1296. PBYTE Src, EndOfLine, EqualSign, EndOfFile;
  1297. PBYTE Name, EndOfName, Value, EndOfValue;
  1298. #undef INI_TEXT
  1299. #define INI_TEXT(quote) quote
  1300. Src = (PBYTE)m_TextCurrent;
  1301. EndOfFile = (PBYTE)m_TextEnd;
  1302. while (Src < EndOfFile)
  1303. {
  1304. //
  1305. // Find first non-blank character on a line. Skip blank lines
  1306. //
  1307. while (Src < EndOfFile && *Src <= INI_TEXT(' '))
  1308. {
  1309. Src++;
  1310. }
  1311. if (Src >= EndOfFile)
  1312. {
  1313. m_TextCurrent = Src;
  1314. break;
  1315. }
  1316. EndOfLine = Src;
  1317. EqualSign = NULL;
  1318. m_TextStart = Src;
  1319. while (EndOfLine < EndOfFile)
  1320. {
  1321. if (EqualSign == NULL && *EndOfLine == INI_TEXT('='))
  1322. {
  1323. EqualSign = ++EndOfLine;
  1324. }
  1325. else if (*EndOfLine == INI_TEXT('\r') || *EndOfLine == INI_TEXT('\n'))
  1326. {
  1327. if (*EndOfLine == INI_TEXT('\r'))
  1328. {
  1329. EndOfLine++;
  1330. }
  1331. if (*EndOfLine == INI_TEXT('\n')) {
  1332. EndOfLine++;
  1333. }
  1334. break;
  1335. }
  1336. else
  1337. {
  1338. EndOfLine++;
  1339. }
  1340. }
  1341. if (*Src != INI_TEXT(';'))
  1342. {
  1343. if (*Src == INI_TEXT('['))
  1344. {
  1345. Name = Src + 1;
  1346. while (Name < EndOfLine && *Name <= INI_TEXT(' '))
  1347. {
  1348. Name++;
  1349. }
  1350. EndOfName = Name;
  1351. while (EndOfName < EndOfLine)
  1352. {
  1353. if (*EndOfName == INI_TEXT(']'))
  1354. {
  1355. break;
  1356. }
  1357. if (IsDBCSLeadByte(*EndOfName))
  1358. {
  1359. EndOfName++;
  1360. }
  1361. EndOfName++;
  1362. }
  1363. while (EndOfName > Name && EndOfName[ -1 ] <= INI_TEXT(' '))
  1364. {
  1365. EndOfName--;
  1366. }
  1367. m_SectionName.Buffer = (PCHAR)Name;
  1368. m_SectionName.Length = (USHORT)((PCHAR)EndOfName - (PCHAR)Name);
  1369. m_SectionName.MaximumLength = m_SectionName.Length;
  1370. m_AnsiSectionName = &m_SectionName;
  1371. m_UnicodeSectionName = NULL;
  1372. if (StopAt == STOP_AT_SECTION)
  1373. {
  1374. m_TextCurrent = EndOfLine;
  1375. return STATUS_MORE_ENTRIES;
  1376. }
  1377. else if (StopAt == STOP_AT_KEYWORD)
  1378. {
  1379. return STATUS_NO_MORE_ENTRIES;
  1380. }
  1381. }
  1382. else if (AllowNoEquals || (EqualSign != NULL))
  1383. {
  1384. if (EqualSign != NULL)
  1385. {
  1386. Name = Src;
  1387. EndOfName = EqualSign - 1;
  1388. while (EndOfName > Name && EndOfName[ -1 ] <= INI_TEXT(' '))
  1389. {
  1390. EndOfName--;
  1391. }
  1392. m_KeywordName.Buffer = (PCHAR)Name;
  1393. m_KeywordName.Length = (USHORT)((PCHAR)EndOfName - (PCHAR)Name);
  1394. m_KeywordName.MaximumLength = m_KeywordName.Length;
  1395. m_AnsiKeywordName = &m_KeywordName;
  1396. m_UnicodeKeywordName = NULL;
  1397. Value = EqualSign;
  1398. }
  1399. else
  1400. {
  1401. Value = Src;
  1402. m_AnsiKeywordName = NULL;
  1403. m_UnicodeKeywordName = NULL;
  1404. }
  1405. EndOfValue = EndOfLine;
  1406. while (EndOfValue > Value && EndOfValue[ -1 ] <= INI_TEXT(' '))
  1407. {
  1408. EndOfValue--;
  1409. }
  1410. m_KeywordValue.Buffer = (PCHAR)Value;
  1411. m_KeywordValue.Length = (USHORT)((PCHAR)EndOfValue - (PCHAR)Value);
  1412. m_KeywordValue.MaximumLength = m_KeywordValue.Length;
  1413. m_AnsiKeywordValue = &m_KeywordValue;
  1414. m_UnicodeKeywordValue = NULL;
  1415. if (StopAt == STOP_AT_KEYWORD)
  1416. {
  1417. m_TextCurrent = EndOfLine;
  1418. return STATUS_MORE_ENTRIES;
  1419. }
  1420. }
  1421. }
  1422. Src = EndOfLine;
  1423. }
  1424. }
  1425. return STATUS_NO_MORE_ENTRIES;
  1426. }
  1427. BOOL CWMI_FILE_IniFile::GetApplicationName(
  1428. OUT PANSI_STRING *ApplicationName OPTIONAL,
  1429. OUT PUNICODE_STRING *ApplicationNameU OPTIONAL
  1430. )
  1431. {
  1432. NTSTATUS Status;
  1433. if (ApplicationName)
  1434. {
  1435. if (m_ApplicationName.Length == 0)
  1436. {
  1437. m_ApplicationName.Buffer = new char[(m_ApplicationNameU.Length * sizeof(WORD)) + 1]; //MBCS strings
  1438. m_ApplicationName.MaximumLength = (m_ApplicationNameU.Length * sizeof(WORD)) + 1;
  1439. Status = RtlUnicodeStringToAnsiString( &m_ApplicationName, &m_ApplicationNameU, FALSE );
  1440. if (!NT_SUCCESS( Status ))
  1441. {
  1442. return FALSE;
  1443. }
  1444. }
  1445. *ApplicationName = &m_ApplicationName;
  1446. return TRUE;
  1447. }
  1448. if (ApplicationNameU)
  1449. {
  1450. if (m_ApplicationNameU.Length == 0)
  1451. {
  1452. return FALSE;
  1453. }
  1454. *ApplicationNameU = &m_ApplicationNameU;
  1455. return TRUE;
  1456. }
  1457. return FALSE;
  1458. }
  1459. BOOL CWMI_FILE_IniFile::GetVariableName(
  1460. OUT PANSI_STRING *VariableName OPTIONAL,
  1461. OUT PUNICODE_STRING *VariableNameU OPTIONAL
  1462. )
  1463. {
  1464. NTSTATUS Status;
  1465. if (ARGUMENT_PRESENT( VariableName ))
  1466. {
  1467. if (m_VariableName.Length == 0)
  1468. {
  1469. m_VariableName.Buffer = new char[(m_VariableNameU.Length * sizeof(WORD)) + 1]; //MBCS strings
  1470. m_VariableName.MaximumLength = (m_VariableNameU.Length * sizeof(WORD)) + 1;
  1471. Status = RtlUnicodeStringToAnsiString( &m_VariableName, &m_VariableNameU, FALSE );
  1472. if (!NT_SUCCESS( Status ))
  1473. {
  1474. return FALSE;
  1475. }
  1476. }
  1477. *VariableName = &m_VariableName;
  1478. return TRUE;
  1479. }
  1480. if (ARGUMENT_PRESENT( VariableNameU ))
  1481. {
  1482. if (m_VariableNameU.Length == 0)
  1483. {
  1484. return FALSE;
  1485. }
  1486. *VariableNameU = &m_VariableNameU;
  1487. return TRUE;
  1488. }
  1489. return FALSE;
  1490. }
  1491. BOOL CWMI_FILE_IniFile::GetVariableValue(
  1492. OUT PBYTE *VariableValue OPTIONAL,
  1493. OUT LPWSTR *VariableValueU OPTIONAL,
  1494. OUT PULONG VariableValueLength
  1495. )
  1496. {
  1497. NTSTATUS Status;
  1498. ULONG Index;
  1499. if (VariableValue)
  1500. {
  1501. if (m_ValueLength == 0)
  1502. {
  1503. if (m_ValueBufferU == NULL || m_ValueLengthU == 0)
  1504. {
  1505. *VariableValue = NULL;
  1506. *VariableValueLength = sizeof ( UCHAR );
  1507. return TRUE;
  1508. }
  1509. m_ValueBuffer = new char[m_ValueLengthU + 1]; //DBCS
  1510. m_ValueLength = m_ValueLengthU;
  1511. Status = RtlUnicodeToMultiByteN( (PCHAR)m_ValueBuffer,
  1512. m_ValueLength,
  1513. &Index,
  1514. m_ValueBufferU,
  1515. m_ValueLengthU
  1516. );
  1517. if (!NT_SUCCESS( Status ))
  1518. {
  1519. return FALSE;
  1520. }
  1521. // Set real converted size
  1522. m_ValueLength = Index;
  1523. m_ValueBuffer[ Index ] = '\0'; // Null terminate converted value
  1524. }
  1525. else
  1526. {
  1527. Index = m_ValueLength;
  1528. }
  1529. *VariableValue = (PBYTE)m_ValueBuffer;
  1530. *VariableValueLength = Index + 1;
  1531. return TRUE;
  1532. }
  1533. if (VariableValueU)
  1534. {
  1535. if (m_ValueLengthU == 0)
  1536. {
  1537. if (m_ValueBuffer == NULL || m_ValueLength == 0)
  1538. {
  1539. *VariableValueU = NULL;
  1540. *VariableValueLength = sizeof ( WCHAR );
  1541. return TRUE;
  1542. }
  1543. else
  1544. {
  1545. return FALSE;
  1546. }
  1547. }
  1548. else
  1549. {
  1550. Index = m_ValueLengthU / sizeof( WCHAR );
  1551. }
  1552. *VariableValueU = m_ValueBufferU;
  1553. *VariableValueLength = (Index + 1) * sizeof( WCHAR );
  1554. return TRUE;
  1555. }
  1556. return FALSE;
  1557. }
  1558. NTSTATUS CWMI_FILE_IniFile::AppendStringToResultBuffer(
  1559. IN PANSI_STRING String OPTIONAL,
  1560. IN PUNICODE_STRING StringU OPTIONAL,
  1561. IN BOOL IncludeNull
  1562. )
  1563. {
  1564. if (String)
  1565. {
  1566. if (StringU)
  1567. {
  1568. return STATUS_INVALID_PARAMETER;
  1569. }
  1570. else
  1571. {
  1572. return AppendBufferToResultBuffer((PBYTE)String->Buffer,
  1573. NULL,
  1574. String->Length,
  1575. IncludeNull
  1576. );
  1577. }
  1578. }
  1579. else if (StringU)
  1580. {
  1581. if (String)
  1582. {
  1583. return STATUS_INVALID_PARAMETER;
  1584. }
  1585. else
  1586. {
  1587. return AppendBufferToResultBuffer(NULL,
  1588. StringU->Buffer,
  1589. StringU->Length / sizeof( WCHAR ),
  1590. IncludeNull
  1591. );
  1592. }
  1593. }
  1594. else
  1595. {
  1596. return STATUS_INVALID_PARAMETER;
  1597. }
  1598. }
  1599. NTSTATUS CWMI_FILE_IniFile::AppendBufferToResultBuffer(
  1600. IN PBYTE Buffer OPTIONAL,
  1601. IN LPWSTR BufferU OPTIONAL,
  1602. IN ULONG Chars,
  1603. IN BOOL IncludeNull
  1604. )
  1605. {
  1606. NTSTATUS Status, OverflowStatus;
  1607. ULONG Index;
  1608. OverflowStatus = STATUS_SUCCESS;
  1609. if (Buffer)
  1610. {
  1611. if (BufferU)
  1612. {
  1613. return STATUS_INVALID_PARAMETER;
  1614. }
  1615. else
  1616. {
  1617. ULONG CharsMbcs = Chars;
  1618. //
  1619. // In this point, Chars does not contains proper value for Unicode.
  1620. // because. Chars was computed based on DBCS string length,
  1621. // This is correct, sources string is DBCS, then
  1622. // if the source is not DBCS. we just adjust it here.
  1623. //
  1624. Status = RtlMultiByteToUnicodeSize(&Chars,(PCSTR)Buffer,Chars);
  1625. if (!NT_SUCCESS( Status ))
  1626. {
  1627. return Status;
  1628. }
  1629. Chars /= sizeof(WCHAR);
  1630. if (m_ResultChars + Chars >= m_ResultMaxChars)
  1631. {
  1632. OverflowStatus = STATUS_BUFFER_OVERFLOW;
  1633. Chars = m_ResultMaxChars - m_ResultChars;
  1634. if (Chars) {
  1635. Chars -= 1;
  1636. }
  1637. }
  1638. if (Chars)
  1639. {
  1640. Status = RtlMultiByteToUnicodeN( (PWSTR)(m_ResultBufferU + m_ResultChars),
  1641. Chars * sizeof( WCHAR ),
  1642. &Index,
  1643. (PCSTR)Buffer,
  1644. CharsMbcs
  1645. );
  1646. if (!NT_SUCCESS( Status ))
  1647. {
  1648. return Status;
  1649. }
  1650. m_ResultChars += Chars;
  1651. }
  1652. }
  1653. }
  1654. else if (BufferU)
  1655. {
  1656. if (Buffer)
  1657. {
  1658. return STATUS_INVALID_PARAMETER;
  1659. }
  1660. else
  1661. {
  1662. ULONG CharsUnicode = Chars;
  1663. if (m_ResultChars + Chars >= m_ResultMaxChars)
  1664. {
  1665. OverflowStatus = STATUS_BUFFER_OVERFLOW;
  1666. Chars = m_ResultMaxChars - m_ResultChars;
  1667. if (Chars)
  1668. {
  1669. Chars -= 1;
  1670. }
  1671. }
  1672. if (Chars)
  1673. {
  1674. memcpy( (LPVOID)(m_ResultBufferU + m_ResultChars), BufferU, Chars * sizeof( WCHAR ) );
  1675. m_ResultChars += Chars;
  1676. }
  1677. }
  1678. }
  1679. if (IncludeNull)
  1680. {
  1681. if (m_ResultChars + 1 >= m_ResultMaxChars)
  1682. {
  1683. return STATUS_BUFFER_OVERFLOW;
  1684. }
  1685. m_ResultBufferU[ m_ResultChars ] = L'\0';
  1686. m_ResultChars += 1;
  1687. }
  1688. return OverflowStatus;
  1689. }
  1690. NTSTATUS CWMI_FILE_IniFile::WriteKeywordValue(
  1691. IN PUNICODE_STRING VariableName OPTIONAL
  1692. )
  1693. {
  1694. NTSTATUS Status;
  1695. BOOL InsertSectionName;
  1696. BOOL InsertKeywordName;
  1697. ULONG InsertAmount, n;
  1698. PANSI_STRING AnsiSectionName;
  1699. PANSI_STRING AnsiKeywordName;
  1700. PUNICODE_STRING UnicodeSectionName;
  1701. PUNICODE_STRING UnicodeKeywordName;
  1702. PBYTE AnsiKeywordValue;
  1703. LPWSTR UnicodeKeywordValue;
  1704. ULONG ValueLength;
  1705. ULONG DeleteLength;
  1706. PVOID AddressInFile;
  1707. InsertAmount = 0;
  1708. Status = FindSection( );
  1709. if (!NT_SUCCESS( Status ))
  1710. {
  1711. AddressInFile = m_TextEnd;
  1712. if (m_IniFile.m_UnicodeFile)
  1713. {
  1714. if (!GetApplicationName(NULL, &UnicodeSectionName ))
  1715. {
  1716. return STATUS_INVALID_PARAMETER;
  1717. }
  1718. //
  1719. // Add in size of [SectionName]\r\n
  1720. //
  1721. InsertAmount += (1 + 1 + 2) * sizeof( WCHAR );
  1722. InsertAmount += UnicodeSectionName->Length;
  1723. }
  1724. else
  1725. {
  1726. if (!GetApplicationName(&AnsiSectionName, NULL ))
  1727. {
  1728. return STATUS_INVALID_PARAMETER;
  1729. }
  1730. //
  1731. // Add in size of [SectionName]\r\n
  1732. //
  1733. InsertAmount += (1 + 1 + 2) * sizeof( UCHAR );
  1734. InsertAmount += AnsiSectionName->Length;
  1735. }
  1736. InsertSectionName = TRUE;
  1737. }
  1738. else
  1739. {
  1740. InsertSectionName = FALSE;
  1741. Status = FindKeyword( );
  1742. }
  1743. if (!NT_SUCCESS( Status ))
  1744. {
  1745. if (!InsertSectionName)
  1746. {
  1747. AddressInFile = m_TextCurrent;
  1748. }
  1749. if (m_IniFile.m_UnicodeFile)
  1750. {
  1751. if (!GetVariableName(NULL, &UnicodeKeywordName ))
  1752. {
  1753. return STATUS_INVALID_PARAMETER;
  1754. }
  1755. //
  1756. // Add in size of Keyword=\r\n
  1757. //
  1758. InsertAmount += (1 + 2) * sizeof( WCHAR );
  1759. InsertAmount += UnicodeKeywordName->Length;
  1760. }
  1761. else
  1762. {
  1763. if (!GetVariableName(&AnsiKeywordName, NULL ))
  1764. {
  1765. return STATUS_INVALID_PARAMETER;
  1766. }
  1767. //
  1768. // Add in size of Keyword=\r\n
  1769. //
  1770. InsertAmount += (1 + 2) * sizeof( UCHAR );
  1771. InsertAmount += AnsiKeywordName->Length;
  1772. }
  1773. InsertKeywordName = TRUE;
  1774. }
  1775. else
  1776. {
  1777. if (m_IniFile.m_UnicodeFile)
  1778. {
  1779. AddressInFile = m_UnicodeKeywordValue->Buffer;
  1780. }
  1781. else
  1782. {
  1783. AddressInFile = m_AnsiKeywordValue->Buffer;
  1784. }
  1785. InsertKeywordName = FALSE;
  1786. }
  1787. if (m_IniFile.m_UnicodeFile)
  1788. {
  1789. if (!GetVariableValue( NULL, &UnicodeKeywordValue, &ValueLength ))
  1790. {
  1791. return STATUS_INVALID_PARAMETER;
  1792. }
  1793. ValueLength -= sizeof( WCHAR );
  1794. if (InsertAmount == 0)
  1795. {
  1796. return ModifyMappedFile(m_UnicodeKeywordValue->Buffer,
  1797. m_UnicodeKeywordValue->Length,
  1798. UnicodeKeywordValue,
  1799. ValueLength
  1800. );
  1801. }
  1802. //
  1803. // Add in size of value
  1804. //
  1805. InsertAmount += ValueLength;
  1806. }
  1807. else
  1808. {
  1809. if (!GetVariableValue(&AnsiKeywordValue, NULL, &ValueLength ))
  1810. {
  1811. return STATUS_INVALID_PARAMETER;
  1812. }
  1813. ValueLength -= sizeof( UCHAR );
  1814. if (InsertAmount == 0)
  1815. {
  1816. return ModifyMappedFile(m_AnsiKeywordValue->Buffer,
  1817. m_AnsiKeywordValue->Length,
  1818. AnsiKeywordValue,
  1819. ValueLength
  1820. );
  1821. }
  1822. //
  1823. // Add in size of value
  1824. //
  1825. InsertAmount += ValueLength;
  1826. }
  1827. PVOID InsertBuffer = NULL;
  1828. InsertBuffer = (PVOID) new BYTE[InsertAmount + sizeof( L'\0' )];
  1829. try
  1830. {
  1831. if (m_IniFile.m_UnicodeFile)
  1832. {
  1833. LPWSTR Src, Dst;
  1834. Dst = (LPWSTR)InsertBuffer;
  1835. if (InsertSectionName)
  1836. {
  1837. *Dst++ = L'[';
  1838. Src = UnicodeSectionName->Buffer;
  1839. n = UnicodeSectionName->Length / sizeof( WCHAR );
  1840. while (n--)
  1841. {
  1842. *Dst++ = *Src++;
  1843. }
  1844. *Dst++ = L']';
  1845. *Dst++ = L'\r';
  1846. *Dst++ = L'\n';
  1847. }
  1848. if (InsertKeywordName)
  1849. {
  1850. Src = UnicodeKeywordName->Buffer;
  1851. n = UnicodeKeywordName->Length / sizeof( WCHAR );
  1852. while (n--)
  1853. {
  1854. *Dst++ = *Src++;
  1855. }
  1856. *Dst++ = L'=';
  1857. }
  1858. Src = UnicodeKeywordValue;
  1859. n = ValueLength / sizeof( WCHAR );
  1860. while (n--)
  1861. {
  1862. *Dst++ = *Src++;
  1863. }
  1864. if (InsertKeywordName)
  1865. {
  1866. *Dst++ = L'\r';
  1867. *Dst++ = L'\n';
  1868. }
  1869. }
  1870. else
  1871. {
  1872. PBYTE Src, Dst;
  1873. Dst = (PBYTE)InsertBuffer;
  1874. if (InsertSectionName)
  1875. {
  1876. *Dst++ = '[';
  1877. Src = (PBYTE)AnsiSectionName->Buffer;
  1878. n = AnsiSectionName->Length;
  1879. while (n--)
  1880. {
  1881. *Dst++ = *Src++;
  1882. }
  1883. *Dst++ = ']';
  1884. *Dst++ = '\r';
  1885. *Dst++ = '\n';
  1886. }
  1887. if (InsertKeywordName)
  1888. {
  1889. Src = (PBYTE)AnsiKeywordName->Buffer;
  1890. n = AnsiKeywordName->Length;
  1891. while (n--)
  1892. {
  1893. *Dst++ = *Src++;
  1894. }
  1895. *Dst++ = '=';
  1896. }
  1897. Src = AnsiKeywordValue;
  1898. n = ValueLength;
  1899. while (n--)
  1900. {
  1901. *Dst++ = *Src++;
  1902. }
  1903. if (InsertKeywordName)
  1904. {
  1905. *Dst++ = '\r';
  1906. *Dst++ = '\n';
  1907. }
  1908. }
  1909. Status = ModifyMappedFile(AddressInFile,
  1910. 0,
  1911. InsertBuffer,
  1912. InsertAmount
  1913. );
  1914. delete [] ((BYTE*) InsertBuffer);
  1915. InsertBuffer = NULL;
  1916. }
  1917. catch(...)
  1918. {
  1919. if (InsertBuffer)
  1920. {
  1921. delete [] ((BYTE*) InsertBuffer);
  1922. InsertBuffer = NULL;
  1923. }
  1924. throw;
  1925. }
  1926. return Status;
  1927. }
  1928. NTSTATUS CWMI_FILE_IniFile::ModifyMappedFile(
  1929. IN PVOID AddressInFile,
  1930. IN ULONG SizeToRemove,
  1931. IN PVOID InsertBuffer,
  1932. IN ULONG InsertAmount
  1933. )
  1934. {
  1935. NTSTATUS Status;
  1936. ULONG NewEndOfFile, UpdateOffset, UpdateLength;
  1937. NewEndOfFile = m_IniFile.m_EndOfFile - SizeToRemove + InsertAmount;
  1938. if (NewEndOfFile > m_IniFile.m_CommitSize)
  1939. {
  1940. if (NewEndOfFile > m_IniFile.m_RegionSize)
  1941. {
  1942. return STATUS_BUFFER_OVERFLOW;
  1943. }
  1944. m_IniFile.m_CommitSize = NewEndOfFile;
  1945. Status = NtAllocateVirtualMemory( NtCurrentProcess(),
  1946. &m_IniFile.m_BaseAddress,
  1947. 0,
  1948. &m_IniFile.m_CommitSize,
  1949. MEM_COMMIT,
  1950. PAGE_READWRITE
  1951. );
  1952. if (!NT_SUCCESS( Status )) {
  1953. return Status;
  1954. }
  1955. m_IniFile.m_EndOfFile = NewEndOfFile;
  1956. }
  1957. UpdateOffset = (ULONG)((PCHAR)AddressInFile - (PCHAR)(m_IniFile.m_BaseAddress)),
  1958. UpdateLength = (ULONG)((PCHAR)m_TextEnd - (PCHAR)AddressInFile) + InsertAmount - SizeToRemove;
  1959. //
  1960. // Are we deleting more than we are inserting?
  1961. //
  1962. if (SizeToRemove > InsertAmount)
  1963. {
  1964. //
  1965. // Yes copy over insert string.
  1966. //
  1967. RtlMoveMemory( AddressInFile, InsertBuffer, InsertAmount );
  1968. //
  1969. // Delete remaining text after insertion string by moving it
  1970. // up
  1971. //
  1972. RtlMoveMemory( (PCHAR)AddressInFile + InsertAmount,
  1973. (PCHAR)AddressInFile + SizeToRemove,
  1974. UpdateLength - InsertAmount
  1975. );
  1976. }
  1977. else if (InsertAmount > 0)
  1978. {
  1979. //
  1980. // Are we deleting less than we are inserting?
  1981. //
  1982. if (SizeToRemove < InsertAmount)
  1983. {
  1984. //
  1985. // Move text down to make room for insertion
  1986. //
  1987. RtlMoveMemory( (PCHAR)AddressInFile + InsertAmount - SizeToRemove,
  1988. (PCHAR)AddressInFile,
  1989. UpdateLength - InsertAmount + SizeToRemove
  1990. );
  1991. }
  1992. else
  1993. {
  1994. //
  1995. // Deleting and inserting same amount, update just that text as
  1996. // no shifting was done.
  1997. //
  1998. UpdateLength = InsertAmount;
  1999. }
  2000. //
  2001. // Copy over insert string
  2002. //
  2003. RtlMoveMemory( AddressInFile, InsertBuffer, InsertAmount );
  2004. }
  2005. else
  2006. {
  2007. //
  2008. // Nothing to change, as InsertAmount and SizeToRemove are zero
  2009. //
  2010. return STATUS_SUCCESS;
  2011. }
  2012. if (m_IniFile.m_EndOfFile != NewEndOfFile)
  2013. {
  2014. m_IniFile.m_EndOfFile = NewEndOfFile;
  2015. }
  2016. if (UpdateOffset < m_IniFile.m_UpdateOffset)
  2017. {
  2018. m_IniFile.m_UpdateOffset = UpdateOffset;
  2019. }
  2020. if ((UpdateOffset + UpdateLength) > m_IniFile.m_UpdateEndOffset)
  2021. {
  2022. m_IniFile.m_UpdateEndOffset = UpdateOffset + UpdateLength;
  2023. }
  2024. return STATUS_SUCCESS;
  2025. }
  2026. NTSTATUS CWMI_FILE_IniFile::WriteSection()
  2027. {
  2028. NTSTATUS Status;
  2029. BOOLEAN InsertSectionName;
  2030. ULONG InsertAmount, n;
  2031. PANSI_STRING AnsiSectionName;
  2032. PUNICODE_STRING UnicodeSectionName;
  2033. PBYTE AnsiKeywordValue, s;
  2034. PWSTR UnicodeKeywordValue, w;
  2035. ULONG ValueLength, SizeToRemove;
  2036. PVOID AddressInFile;
  2037. InsertAmount = 0;
  2038. Status = FindSection();
  2039. if (!NT_SUCCESS( Status ))
  2040. {
  2041. AddressInFile = m_TextEnd;
  2042. if (m_IniFile.m_UnicodeFile)
  2043. {
  2044. if (!GetApplicationName(NULL, &UnicodeSectionName ))
  2045. {
  2046. return STATUS_INVALID_PARAMETER;
  2047. }
  2048. //
  2049. // Add in size of [SectionName]\r\n
  2050. //
  2051. InsertAmount += (1 + 1 + 2) * sizeof( WCHAR );
  2052. InsertAmount += UnicodeSectionName->Length;
  2053. }
  2054. else
  2055. {
  2056. if (!GetApplicationName(&AnsiSectionName, NULL ))
  2057. {
  2058. return STATUS_INVALID_PARAMETER;
  2059. }
  2060. //
  2061. // Add in size of [SectionName]\r\n
  2062. //
  2063. InsertAmount += (1 + 1 + 2) * sizeof( UCHAR );
  2064. InsertAmount += AnsiSectionName->Length;
  2065. }
  2066. InsertSectionName = TRUE;
  2067. SizeToRemove = 0;
  2068. }
  2069. else
  2070. {
  2071. AddressInFile = m_TextCurrent;
  2072. while (TRUE)
  2073. {
  2074. //
  2075. // For delete operations need to iterate all lines in section,
  2076. // not just those that have an = on them. Otherwise sections like
  2077. // [foo]
  2078. // a
  2079. // b = c
  2080. // d
  2081. //
  2082. // don't get deleted properly.
  2083. //
  2084. Status = AdvanceTextPointer(STOP_AT_KEYWORD);
  2085. if (Status == STATUS_MORE_ENTRIES)
  2086. {
  2087. }
  2088. else if (Status == STATUS_NO_MORE_ENTRIES)
  2089. {
  2090. SizeToRemove = (ULONG)((PCHAR)m_TextCurrent - (PCHAR)AddressInFile);
  2091. break;
  2092. }
  2093. else
  2094. {
  2095. return Status;
  2096. }
  2097. }
  2098. InsertSectionName = FALSE;
  2099. }
  2100. if (m_IniFile.m_UnicodeFile)
  2101. {
  2102. if (!GetVariableValue(NULL, &UnicodeKeywordValue, &ValueLength ))
  2103. {
  2104. return STATUS_INVALID_PARAMETER;
  2105. }
  2106. ValueLength -= sizeof( WCHAR );
  2107. //
  2108. // Add in size of value, + \r\n for each line
  2109. //
  2110. w = UnicodeKeywordValue;
  2111. InsertAmount += ValueLength;
  2112. while (w && *w)
  2113. {
  2114. while (*w++)
  2115. {
  2116. }
  2117. InsertAmount += (2-1) * sizeof( WCHAR ); // Subtract out NULL byte already in ValueLength
  2118. }
  2119. }
  2120. else
  2121. {
  2122. if (!GetVariableValue(&AnsiKeywordValue, NULL, &ValueLength ))
  2123. {
  2124. return STATUS_INVALID_PARAMETER;
  2125. }
  2126. ValueLength -= sizeof( UCHAR );
  2127. //
  2128. // Add in size of value, + \r\n for each line
  2129. //
  2130. s = AnsiKeywordValue;
  2131. InsertAmount += ValueLength;
  2132. while (s && *s)
  2133. {
  2134. while (*s++)
  2135. {
  2136. }
  2137. InsertAmount += 2 - 1; // Subtract out NULL byte already in ValueLength
  2138. }
  2139. }
  2140. PVOID InsertBuffer = NULL;
  2141. InsertBuffer = (PVOID) new BYTE[InsertAmount + sizeof( L'\0' )];
  2142. try
  2143. {
  2144. if (m_IniFile.m_UnicodeFile)
  2145. {
  2146. PWSTR Src, Dst;
  2147. Dst = (PWSTR)InsertBuffer;
  2148. if (InsertSectionName)
  2149. {
  2150. *Dst++ = L'[';
  2151. Src = UnicodeSectionName->Buffer;
  2152. n = UnicodeSectionName->Length / sizeof( WCHAR );
  2153. while (n--)
  2154. {
  2155. *Dst++ = *Src++;
  2156. }
  2157. *Dst++ = L']';
  2158. *Dst++ = L'\r';
  2159. *Dst++ = L'\n';
  2160. }
  2161. Src = UnicodeKeywordValue;
  2162. while (*Src)
  2163. {
  2164. while (*Dst = *Src++)
  2165. {
  2166. Dst += 1;
  2167. }
  2168. *Dst++ = L'\r';
  2169. *Dst++ = L'\n';
  2170. }
  2171. }
  2172. else
  2173. {
  2174. PBYTE Src, Dst;
  2175. Dst = (PBYTE)InsertBuffer;
  2176. if (InsertSectionName) {
  2177. *Dst++ = '[';
  2178. Src = (PBYTE)AnsiSectionName->Buffer;
  2179. n = AnsiSectionName->Length;
  2180. while (n--) {
  2181. *Dst++ = *Src++;
  2182. }
  2183. *Dst++ = ']';
  2184. *Dst++ = '\r';
  2185. *Dst++ = '\n';
  2186. }
  2187. Src = AnsiKeywordValue;
  2188. while (*Src)
  2189. {
  2190. while (*Dst = *Src++)
  2191. {
  2192. Dst += 1;
  2193. }
  2194. *Dst++ = '\r';
  2195. *Dst++ = '\n';
  2196. }
  2197. }
  2198. Status = ModifyMappedFile(AddressInFile,
  2199. SizeToRemove,
  2200. InsertBuffer,
  2201. InsertAmount
  2202. );
  2203. delete [] ((BYTE*) InsertBuffer);
  2204. InsertBuffer = NULL;
  2205. }
  2206. catch(...)
  2207. {
  2208. if (InsertBuffer)
  2209. {
  2210. delete [] ((BYTE*) InsertBuffer);
  2211. InsertBuffer = NULL;
  2212. }
  2213. throw;
  2214. }
  2215. return Status;
  2216. }