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.

2527 lines
58 KiB

  1. // Copyright (c) 2001 Microsoft Corporation, All Rights Reserved
  2. #include "precomp.h"
  3. #include <nt.h>
  4. #include <ntrtl.h>
  5. #include <nturtl.h>
  6. #include <windows.h>
  7. #include <objbase.h>
  8. #include "profilestring.h"
  9. #include "profilestringimpl.h"
  10. /////////////////////////////////////////////////////////////////////////////////////////
  11. // TOOLS
  12. /////////////////////////////////////////////////////////////////////////////////////////
  13. DWORD WMIREG_GetBaseFileName ( IN LPCWSTR FileName, OUT LPWSTR* BaseFileName )
  14. {
  15. DWORD Status = ERROR_INVALID_PARAMETER;
  16. if ( FileName && BaseFileName )
  17. {
  18. *BaseFileName = NULL;
  19. LPWSTR wsz = NULL;
  20. wsz = const_cast < LPWSTR > ( FileName ) + wcslen ( FileName );
  21. while ( --wsz > FileName )
  22. {
  23. if ( *wsz == OBJ_NAME_PATH_SEPARATOR || *wsz == L'/' || *wsz == L':' )
  24. {
  25. wsz++;
  26. break;
  27. }
  28. }
  29. if ( wsz )
  30. {
  31. try
  32. {
  33. if ( ( *BaseFileName = new WCHAR [ wcslen ( wsz ) + 1 ] ) != NULL )
  34. {
  35. wcscpy ( *BaseFileName, wsz );
  36. Status = ERROR_SUCCESS;
  37. }
  38. else
  39. {
  40. Status = ERROR_NOT_ENOUGH_MEMORY;
  41. }
  42. }
  43. catch ( ... )
  44. {
  45. if ( *BaseFileName )
  46. {
  47. delete [] *BaseFileName;
  48. *BaseFileName = NULL;
  49. }
  50. Status = ERROR_GEN_FAILURE;
  51. }
  52. }
  53. }
  54. return Status;
  55. }
  56. BOOLEAN WMIREG_GetApplicationName (
  57. IN PREGISTRY_PARAMETERS a,
  58. OUT LPCWSTR *ApplicationNameU
  59. )
  60. {
  61. if ( ApplicationNameU )
  62. {
  63. *ApplicationNameU = a->ApplicationName;
  64. return TRUE;
  65. }
  66. return FALSE;
  67. }
  68. BOOLEAN WMIREG_GetVariableName (
  69. IN PREGISTRY_PARAMETERS a,
  70. OUT LPCWSTR *VariableNameU
  71. )
  72. {
  73. if ( VariableNameU )
  74. {
  75. *VariableNameU = a->VariableName;
  76. return TRUE;
  77. }
  78. return FALSE;
  79. }
  80. // get appname mapping
  81. PREGISTRY_MAPPING_NAME WMIREG_FindMapping (
  82. IN PREGISTRY_MAPPING_NAME NameMapping,
  83. IN LPCWSTR MappingName
  84. )
  85. {
  86. PREGISTRY_MAPPING_NAME Mapping = NULL;
  87. Mapping = NameMapping;
  88. while ( Mapping != NULL )
  89. {
  90. try
  91. {
  92. if ( wcslen( Mapping->Name ) == wcslen( MappingName ) )
  93. {
  94. if ( _wcsnicmp ( Mapping->Name, MappingName, wcslen( MappingName ) ) == 0 )
  95. {
  96. break;
  97. }
  98. }
  99. Mapping = (PREGISTRY_MAPPING_NAME)Mapping->Next;
  100. }
  101. catch ( ... )
  102. {
  103. Mapping = NULL;
  104. }
  105. }
  106. return Mapping;
  107. }
  108. // get appname mapping
  109. PREGISTRY_MAPPING_APPNAME WMIREG_FindAppNameMapping (
  110. IN PREGISTRY_MAPPING_NAME NameMapping,
  111. IN LPCWSTR ApplicationName
  112. )
  113. {
  114. PREGISTRY_MAPPING_APPNAME AppNameMapping = NULL;
  115. AppNameMapping = (PREGISTRY_MAPPING_APPNAME)NameMapping->ApplicationNames;
  116. while ( AppNameMapping != NULL )
  117. {
  118. try
  119. {
  120. if ( wcslen( AppNameMapping->Name ) == wcslen( ApplicationName ) )
  121. {
  122. if ( _wcsnicmp ( AppNameMapping->Name, ApplicationName, wcslen( ApplicationName ) ) == 0 )
  123. {
  124. break;
  125. }
  126. }
  127. AppNameMapping = (PREGISTRY_MAPPING_APPNAME)AppNameMapping->Next;
  128. }
  129. catch ( ... )
  130. {
  131. AppNameMapping = NULL;
  132. }
  133. }
  134. if ( !AppNameMapping )
  135. {
  136. AppNameMapping = (PREGISTRY_MAPPING_APPNAME)NameMapping->DefaultAppNameMapping;
  137. }
  138. return AppNameMapping;
  139. }
  140. //get varname mapping
  141. PREGISTRY_MAPPING_VARNAME WMIREG_FindVarNameMapping (
  142. IN PREGISTRY_MAPPING_APPNAME AppNameMapping,
  143. IN LPCWSTR VariableName
  144. )
  145. {
  146. PREGISTRY_MAPPING_VARNAME VarNameMapping = NULL;
  147. VarNameMapping = (PREGISTRY_MAPPING_VARNAME)AppNameMapping->VariableNames;
  148. while ( VarNameMapping != NULL )
  149. {
  150. try
  151. {
  152. if ( wcslen ( VarNameMapping->Name ) == wcslen( VariableName ) )
  153. {
  154. if ( _wcsnicmp ( VarNameMapping->Name, VariableName, wcslen( VariableName ) ) == 0 )
  155. {
  156. break;
  157. }
  158. }
  159. VarNameMapping = (PREGISTRY_MAPPING_VARNAME)VarNameMapping->Next;
  160. }
  161. catch ( ... )
  162. {
  163. VarNameMapping = NULL;
  164. }
  165. }
  166. if ( !VarNameMapping )
  167. {
  168. VarNameMapping = (PREGISTRY_MAPPING_VARNAME)AppNameMapping->DefaultVarNameMapping;
  169. }
  170. return VarNameMapping;
  171. }
  172. // get string representing user's registry
  173. BOOL WMIREG_UserPROFILE ( UNICODE_STRING * UserKeyPath )
  174. {
  175. OBJECT_ATTRIBUTES ObjectAttributes;
  176. HANDLE Key = NULL;
  177. if ( NT_SUCCESS ( RtlFormatCurrentUserKeyPath( UserKeyPath ) ) )
  178. {
  179. InitializeObjectAttributes ( &ObjectAttributes,
  180. UserKeyPath,
  181. OBJ_CASE_INSENSITIVE,
  182. NULL,
  183. NULL
  184. );
  185. if ( NT_SUCCESS ( NtOpenKey( &Key, GENERIC_READ, &ObjectAttributes ) ) )
  186. {
  187. NtClose( Key );
  188. }
  189. else
  190. {
  191. RtlFreeUnicodeString( UserKeyPath );
  192. RtlInitUnicodeString( UserKeyPath, NULL );
  193. }
  194. }
  195. if ( UserKeyPath->Length == 0)
  196. {
  197. if ( !RtlCreateUnicodeString ( UserKeyPath, L"\\REGISTRY\\USER\\.DEFAULT" ) )
  198. {
  199. return FALSE;
  200. }
  201. }
  202. return TRUE;
  203. }
  204. // open registry key
  205. DWORD WMIREG_OpenMappingTarget (
  206. IN PREGISTRY_PARAMETERS a,
  207. IN PREGISTRY_MAPPING_VARNAME VarNameMapping,
  208. IN LPCWSTR ApplicationName,
  209. OUT PHANDLE Key
  210. )
  211. {
  212. DWORD Status = ERROR_INVALID_PARAMETER;
  213. PREGISTRY_MAPPING_TARGET MappingTarget = NULL;
  214. ULONG MappingFlags = 0L;
  215. BOOLEAN AppendApplicationName = FALSE;
  216. OBJECT_ATTRIBUTES ObjectAttributes;
  217. PUNICODE_STRING RegistryPathPrefix = NULL;
  218. UNICODE_STRING RegistryPath;
  219. UNICODE_STRING UserKeyPath;
  220. UNICODE_STRING SoftwareKeyPath;
  221. // initialization of strings
  222. RtlInitUnicodeString( &UserKeyPath, NULL );
  223. RtlInitUnicodeString( &SoftwareKeyPath, L"\\Registry\\Machine\\Software" );
  224. // temporary unicode_string
  225. UNICODE_STRING temp;
  226. ULONG n = 0L; // size of reg key
  227. // init key
  228. *Key = INVALID_HANDLE_VALUE;
  229. // get mapping
  230. MappingTarget = (PREGISTRY_MAPPING_TARGET)VarNameMapping->MappingTarget;
  231. MappingFlags = VarNameMapping->MappingFlags & ( REGISTRY_MAPPING_APPEND_BASE_NAME |
  232. REGISTRY_MAPPING_APPEND_APPLICATION_NAME |
  233. REGISTRY_MAPPING_SOFTWARE_RELATIVE |
  234. REGISTRY_MAPPING_USER_RELATIVE
  235. );
  236. if ( MappingTarget != NULL && MappingTarget->RegistryPath )
  237. {
  238. // everything's ok
  239. Status = ERROR_SUCCESS;
  240. if ( ApplicationName && ( MappingFlags & REGISTRY_MAPPING_APPEND_APPLICATION_NAME ) )
  241. {
  242. AppendApplicationName = TRUE;
  243. }
  244. else
  245. {
  246. AppendApplicationName = FALSE;
  247. }
  248. if ( MappingFlags & REGISTRY_MAPPING_USER_RELATIVE )
  249. {
  250. if ( WMIREG_UserPROFILE ( &UserKeyPath ) )
  251. {
  252. if ( UserKeyPath.Length == 0 )
  253. {
  254. Status = ERROR_ACCESS_DENIED;
  255. }
  256. }
  257. else
  258. {
  259. Status = ERROR_INVALID_PARAMETER;
  260. }
  261. if ( Status == ERROR_SUCCESS )
  262. {
  263. RegistryPathPrefix = &UserKeyPath;
  264. }
  265. }
  266. else
  267. if ( MappingFlags & REGISTRY_MAPPING_SOFTWARE_RELATIVE )
  268. {
  269. RegistryPathPrefix = &SoftwareKeyPath;
  270. }
  271. else
  272. {
  273. RegistryPathPrefix = NULL;
  274. }
  275. if ( Status == ERROR_SUCCESS )
  276. {
  277. LPWSTR BaseFileName = NULL;
  278. if ( MappingFlags & REGISTRY_MAPPING_APPEND_BASE_NAME )
  279. {
  280. Status = WMIREG_GetBaseFileName ( a->FileName, &BaseFileName );
  281. }
  282. if ( Status == ERROR_SUCCESS )
  283. {
  284. if ( RegistryPathPrefix )
  285. {
  286. n = RegistryPathPrefix->Length + sizeof( WCHAR );
  287. }
  288. n += sizeof( WCHAR ) + wcslen ( MappingTarget->RegistryPath ) * sizeof ( WCHAR );
  289. if ( MappingFlags & REGISTRY_MAPPING_APPEND_BASE_NAME )
  290. {
  291. n += sizeof( WCHAR ) + wcslen ( BaseFileName ) * sizeof ( WCHAR );
  292. }
  293. if (AppendApplicationName)
  294. {
  295. n += sizeof( WCHAR ) + wcslen ( ApplicationName ) * sizeof ( WCHAR );
  296. }
  297. n += sizeof( UNICODE_NULL );
  298. RegistryPath.Buffer = reinterpret_cast < LPWSTR > ( RtlAllocateHeap( RtlProcessHeap(), 0, n ) );
  299. if (RegistryPath.Buffer == NULL)
  300. {
  301. Status = ERROR_NOT_ENOUGH_MEMORY;
  302. }
  303. if ( Status == ERROR_SUCCESS )
  304. {
  305. RegistryPath.Length = 0;
  306. RegistryPath.MaximumLength = (USHORT)n;
  307. if (RegistryPathPrefix != NULL)
  308. {
  309. RtlAppendUnicodeStringToString( &RegistryPath, RegistryPathPrefix );
  310. RtlAppendUnicodeToString( &RegistryPath, L"\\" );
  311. }
  312. RtlInitUnicodeString( &temp, MappingTarget->RegistryPath );
  313. RtlAppendUnicodeStringToString( &RegistryPath, &temp );
  314. RtlInitUnicodeString( &temp, NULL );
  315. if (MappingFlags & REGISTRY_MAPPING_APPEND_BASE_NAME)
  316. {
  317. RtlAppendUnicodeToString( &RegistryPath, L"\\" );
  318. RtlInitUnicodeString( &temp, BaseFileName );
  319. RtlAppendUnicodeStringToString( &RegistryPath, &temp );
  320. RtlInitUnicodeString( &temp, NULL );
  321. }
  322. if (AppendApplicationName)
  323. {
  324. RtlAppendUnicodeToString( &RegistryPath, L"\\" );
  325. RtlInitUnicodeString( &temp, ApplicationName );
  326. RtlAppendUnicodeStringToString( &RegistryPath, &temp );
  327. RtlInitUnicodeString( &temp, NULL );
  328. }
  329. // open real registry
  330. InitializeObjectAttributes ( &ObjectAttributes,
  331. &RegistryPath,
  332. OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
  333. NULL,
  334. NULL
  335. );
  336. Status = NtOpenKey ( Key, GENERIC_READ, &ObjectAttributes );
  337. // clear registry path
  338. RtlFreeHeap( RtlProcessHeap(), 0, RegistryPath.Buffer );
  339. }
  340. }
  341. // clear use string
  342. if ( UserKeyPath.Length )
  343. {
  344. RtlFreeUnicodeString ( &UserKeyPath );
  345. }
  346. if ( BaseFileName )
  347. {
  348. delete [] BaseFileName;
  349. }
  350. }
  351. }
  352. return Status;
  353. }
  354. // append string to result buffer
  355. DWORD REGISTRY_AppendBufferToResultBuffer (
  356. IN PREGISTRY_PARAMETERS a,
  357. IN PUNICODE_STRING Buffer,
  358. IN BOOLEAN IncludeNull
  359. )
  360. {
  361. DWORD OverflowStatus = ERROR_INVALID_PARAMETER;
  362. if ( Buffer )
  363. {
  364. ULONG Chars = Buffer->Length / sizeof( WCHAR );
  365. if ( a->ResultChars + Chars >= a->ResultMaxChars )
  366. {
  367. OverflowStatus = ERROR_MORE_DATA;
  368. Chars = a->ResultMaxChars - a->ResultChars;
  369. if ( Chars )
  370. {
  371. Chars -= 1;
  372. }
  373. }
  374. if ( Chars )
  375. {
  376. memcpy( reinterpret_cast < PBYTE > ( a->ResultBuffer ) + ( a->ResultChars * sizeof( WCHAR ) ), Buffer->Buffer, Chars * sizeof( WCHAR ) );
  377. a->ResultChars += Chars;
  378. }
  379. if ( OverflowStatus != ERROR_MORE_DATA )
  380. {
  381. OverflowStatus = ERROR_SUCCESS;
  382. }
  383. }
  384. if (IncludeNull)
  385. {
  386. if ( a->ResultChars + 1 >= a->ResultMaxChars )
  387. {
  388. OverflowStatus = ERROR_MORE_DATA;
  389. }
  390. else
  391. {
  392. a->ResultBuffer[ a->ResultChars ] = L'\0';
  393. a->ResultChars += 1;
  394. }
  395. }
  396. return OverflowStatus;
  397. }
  398. DWORD REGISTRY_AppendNULLToResultBuffer ( IN PREGISTRY_PARAMETERS a )
  399. {
  400. return REGISTRY_AppendBufferToResultBuffer( a, NULL, TRUE );
  401. }
  402. NTSTATUS REGISTRY_CheckSubKeyNotEmpty ( IN HANDLE Key, IN PUNICODE_STRING SubKeyName )
  403. {
  404. NTSTATUS Status = STATUS_SUCCESS;
  405. OBJECT_ATTRIBUTES ObjectAttributes;
  406. HANDLE SubKey = INVALID_HANDLE_VALUE;
  407. KEY_VALUE_BASIC_INFORMATION KeyValueInformation;
  408. ULONG ResultLength;
  409. InitializeObjectAttributes( &ObjectAttributes,
  410. SubKeyName,
  411. OBJ_CASE_INSENSITIVE,
  412. Key,
  413. NULL
  414. );
  415. Status = NtOpenKey( &SubKey, GENERIC_READ, &ObjectAttributes );
  416. if ( NT_SUCCESS ( Status ) )
  417. {
  418. Status = NtEnumerateValueKey ( SubKey,
  419. 0,
  420. KeyValueBasicInformation,
  421. &KeyValueInformation,
  422. sizeof( KeyValueInformation ),
  423. &ResultLength
  424. );
  425. if ( Status == STATUS_BUFFER_OVERFLOW )
  426. {
  427. Status = STATUS_SUCCESS;
  428. }
  429. NtClose( SubKey );
  430. }
  431. return Status;
  432. }
  433. /////////////////////////////////////////////////////////////////////////////////////////
  434. // REAL REGISTRY FUNCTIONALITY
  435. /////////////////////////////////////////////////////////////////////////////////////////
  436. DWORD REGISTRY_ReadVariableValue (
  437. IN PREGISTRY_PARAMETERS a,
  438. PREGISTRY_MAPPING_APPNAME AppNameMapping,
  439. PREGISTRY_MAPPING_VARNAME VarNameMapping,
  440. LPCWSTR VariableName
  441. )
  442. {
  443. DWORD Status = ERROR_INVALID_PARAMETER;
  444. LPCWSTR ApplicationName = NULL;
  445. BOOLEAN OutputVariableName = FALSE;
  446. UNICODE_STRING EqualSign;
  447. if ( VariableName )
  448. {
  449. RtlInitUnicodeString ( &EqualSign, L"=" );
  450. OutputVariableName = TRUE;
  451. }
  452. if ( !VariableName )
  453. {
  454. if ( ! WMIREG_GetVariableName ( a, &VariableName ) )
  455. {
  456. VariableName = NULL;
  457. }
  458. }
  459. if ( VariableName != NULL )
  460. {
  461. if ( ! VarNameMapping )
  462. {
  463. VarNameMapping = WMIREG_FindVarNameMapping ( AppNameMapping, VariableName );
  464. }
  465. if ( VarNameMapping != NULL )
  466. {
  467. if ( WMIREG_GetApplicationName ( a, &ApplicationName ) )
  468. {
  469. HANDLE Key = INVALID_HANDLE_VALUE;
  470. Status = WMIREG_OpenMappingTarget ( a,
  471. VarNameMapping,
  472. ApplicationName,
  473. &Key
  474. );
  475. if ( Status == ERROR_SUCCESS && Key != INVALID_HANDLE_VALUE )
  476. {
  477. NTSTATUS NtStatus;
  478. KEY_VALUE_PARTIAL_INFORMATION KeyValueInformation;
  479. PKEY_VALUE_PARTIAL_INFORMATION p = NULL;
  480. DWORD ResultLength = 0L;
  481. UNICODE_STRING temp;
  482. RtlInitUnicodeString ( &temp, VariableName );
  483. NtStatus = NtQueryValueKey ( Key,
  484. &temp,
  485. KeyValuePartialInformation,
  486. &KeyValueInformation,
  487. sizeof( KeyValueInformation ),
  488. &ResultLength
  489. );
  490. if ( ! NT_SUCCESS ( NtStatus ) )
  491. {
  492. if ( NtStatus == STATUS_BUFFER_OVERFLOW )
  493. {
  494. p = reinterpret_cast < PKEY_VALUE_PARTIAL_INFORMATION > ( RtlAllocateHeap ( RtlProcessHeap(), HEAP_ZERO_MEMORY, ResultLength ) );
  495. if ( p != NULL )
  496. {
  497. NtStatus = NtQueryValueKey ( Key,
  498. &temp,
  499. KeyValuePartialInformation,
  500. p,
  501. ResultLength,
  502. &ResultLength
  503. );
  504. Status = NtStatus;
  505. }
  506. else
  507. {
  508. Status = ERROR_NOT_ENOUGH_MEMORY;
  509. }
  510. }
  511. else
  512. {
  513. Status = NtStatus;
  514. }
  515. }
  516. else
  517. {
  518. p = &KeyValueInformation;
  519. }
  520. // create results
  521. if ( Status == ERROR_SUCCESS )
  522. {
  523. if ( OutputVariableName )
  524. {
  525. Status = REGISTRY_AppendBufferToResultBuffer( a, &temp, FALSE );
  526. if ( Status == ERROR_SUCCESS )
  527. {
  528. Status = REGISTRY_AppendBufferToResultBuffer( a, &EqualSign, FALSE );
  529. }
  530. }
  531. if ( Status == ERROR_SUCCESS )
  532. {
  533. if ( p->Type == REG_SZ )
  534. {
  535. UNICODE_STRING Value;
  536. LPWSTR s = NULL;
  537. Value.Buffer = reinterpret_cast < LPWSTR > ( &p->Data[ 0 ] );
  538. if ( p->DataLength >= sizeof( UNICODE_NULL ) )
  539. {
  540. Value.Length = static_cast< USHORT > ( p->DataLength - sizeof ( UNICODE_NULL ) );
  541. }
  542. else
  543. {
  544. Value.Length = 0;
  545. }
  546. Value.MaximumLength = static_cast < USHORT > (p->DataLength);
  547. s = reinterpret_cast < LPWSTR > ( Value.Buffer );
  548. if ( a->Operation == Registry_ReadKeyValue &&
  549. Value.Length >= ( 2 * sizeof( WCHAR ) ) &&
  550. ( s[ 0 ] == s[ ( Value.Length - sizeof( WCHAR ) ) / sizeof( WCHAR ) ] ) &&
  551. ( s[ 0 ] == L'"' || s[ 0 ] == L'\'' )
  552. )
  553. {
  554. Value.Buffer += 1;
  555. Value.Length -= (2 * sizeof( WCHAR ));
  556. }
  557. Status = REGISTRY_AppendBufferToResultBuffer( a, &Value, TRUE );
  558. }
  559. else
  560. {
  561. Status = STATUS_OBJECT_TYPE_MISMATCH;
  562. }
  563. }
  564. }
  565. // clear buffer
  566. if ( p && p != &KeyValueInformation )
  567. {
  568. RtlFreeHeap( RtlProcessHeap(), 0, p );
  569. }
  570. NtClose ( Key );
  571. }
  572. }
  573. }
  574. }
  575. return Status;
  576. }
  577. DWORD REGISTRY_ReadVariableName ( IN PREGISTRY_PARAMETERS a, PREGISTRY_MAPPING_APPNAME AppNameMapping )
  578. {
  579. DWORD Status = ERROR_SUCCESS;
  580. PREGISTRY_MAPPING_VARNAME VarNameMapping = NULL;
  581. LPCWSTR ApplicationName = NULL;
  582. HANDLE Key = INVALID_HANDLE_VALUE;
  583. WCHAR Buffer[ 256 ];
  584. PKEY_VALUE_BASIC_INFORMATION KeyValueInformation = NULL;
  585. // temporary unicode strings
  586. UNICODE_STRING temp;
  587. VarNameMapping = (PREGISTRY_MAPPING_VARNAME)AppNameMapping->VariableNames;
  588. while ( VarNameMapping != NULL && Status == ERROR_SUCCESS )
  589. {
  590. RtlInitUnicodeString ( &temp, VarNameMapping->Name );
  591. Status = REGISTRY_AppendBufferToResultBuffer( a, &temp, TRUE );
  592. if ( Status == ERROR_SUCCESS )
  593. {
  594. VarNameMapping = (PREGISTRY_MAPPING_VARNAME)VarNameMapping->Next;
  595. }
  596. }
  597. if ( Status == ERROR_SUCCESS )
  598. {
  599. VarNameMapping = (PREGISTRY_MAPPING_VARNAME)AppNameMapping->DefaultVarNameMapping;
  600. if ( VarNameMapping != NULL )
  601. {
  602. if ( WMIREG_GetApplicationName ( a, &ApplicationName ) )
  603. {
  604. Status = WMIREG_OpenMappingTarget ( a,
  605. VarNameMapping,
  606. ApplicationName,
  607. &Key
  608. );
  609. if ( Status == ERROR_SUCCESS && Key != INVALID_HANDLE_VALUE )
  610. {
  611. KeyValueInformation = (PKEY_VALUE_BASIC_INFORMATION)Buffer;
  612. for ( ULONG ValueIndex = 0; Status == ERROR_SUCCESS; ValueIndex++ )
  613. {
  614. ULONG ResultLength = 0L;
  615. Status = NtEnumerateValueKey( Key,
  616. ValueIndex,
  617. KeyValueBasicInformation,
  618. KeyValueInformation,
  619. sizeof( Buffer ),
  620. &ResultLength
  621. );
  622. if ( Status == STATUS_NO_MORE_ENTRIES )
  623. {
  624. break;
  625. }
  626. if ( NT_SUCCESS ( Status ) )
  627. {
  628. temp.Buffer = KeyValueInformation->Name;
  629. temp.Length = (USHORT)KeyValueInformation->NameLength;
  630. temp.MaximumLength = (USHORT)KeyValueInformation->NameLength;
  631. Status = REGISTRY_AppendBufferToResultBuffer( a, &temp, TRUE );
  632. }
  633. }
  634. if ( Status == STATUS_NO_MORE_ENTRIES )
  635. {
  636. Status = ERROR_SUCCESS;
  637. }
  638. NtClose ( Key );
  639. }
  640. }
  641. else
  642. {
  643. Status = ERROR_INVALID_PARAMETER;
  644. }
  645. }
  646. }
  647. return Status;
  648. }
  649. DWORD REGISTRY_ReadSectionValue ( IN PREGISTRY_PARAMETERS a, PREGISTRY_MAPPING_APPNAME AppNameMapping )
  650. {
  651. DWORD Status = ERROR_SUCCESS;
  652. PREGISTRY_MAPPING_VARNAME VarNameMapping = NULL;
  653. LPCWSTR ApplicationName= NULL;
  654. WCHAR Buffer[ 256 ];
  655. PKEY_VALUE_BASIC_INFORMATION KeyValueInformation = NULL;
  656. HANDLE Key = INVALID_HANDLE_VALUE;
  657. VarNameMapping = (PREGISTRY_MAPPING_VARNAME)AppNameMapping->VariableNames;
  658. while ( VarNameMapping != NULL && Status == ERROR_SUCCESS )
  659. {
  660. if ( VarNameMapping->Name )
  661. {
  662. Status = REGISTRY_ReadVariableValue ( a, AppNameMapping, VarNameMapping, VarNameMapping->Name );
  663. if ( Status != ERROR_SUCCESS )
  664. {
  665. if ( Status == STATUS_OBJECT_TYPE_MISMATCH )
  666. {
  667. Status = STATUS_SUCCESS;
  668. }
  669. }
  670. }
  671. if ( Status == ERROR_SUCCESS )
  672. {
  673. VarNameMapping = (PREGISTRY_MAPPING_VARNAME)VarNameMapping->Next;
  674. }
  675. }
  676. if ( Status == ERROR_SUCCESS )
  677. {
  678. VarNameMapping = (PREGISTRY_MAPPING_VARNAME)AppNameMapping->DefaultVarNameMapping;
  679. if ( VarNameMapping != NULL)
  680. {
  681. if ( WMIREG_GetApplicationName ( a, &ApplicationName ) )
  682. {
  683. Status = WMIREG_OpenMappingTarget ( a,
  684. VarNameMapping,
  685. ApplicationName,
  686. &Key
  687. );
  688. if ( Status == ERROR_SUCCESS && Key != INVALID_HANDLE_VALUE )
  689. {
  690. KeyValueInformation = (PKEY_VALUE_BASIC_INFORMATION)Buffer;
  691. for ( ULONG ValueIndex = 0; Status == ERROR_SUCCESS; ValueIndex++ )
  692. {
  693. ULONG ResultLength = 0L;
  694. Status = NtEnumerateValueKey( Key,
  695. ValueIndex,
  696. KeyValueBasicInformation,
  697. KeyValueInformation,
  698. sizeof( Buffer ),
  699. &ResultLength
  700. );
  701. if ( Status == STATUS_NO_MORE_ENTRIES )
  702. {
  703. break;
  704. }
  705. if ( NT_SUCCESS ( Status ) )
  706. {
  707. LPWSTR VariableName = NULL;
  708. try
  709. {
  710. if ( ( VariableName = new WCHAR [ KeyValueInformation->NameLength / sizeof ( WCHAR ) + 1 ] ) != NULL )
  711. {
  712. wcsncpy ( VariableName, (LPWSTR)&(KeyValueInformation->Name[0]), KeyValueInformation->NameLength / sizeof ( WCHAR ) );
  713. VariableName [ KeyValueInformation->NameLength / sizeof ( WCHAR ) ] = L'\0';
  714. }
  715. else
  716. {
  717. Status = ERROR_NOT_ENOUGH_MEMORY;
  718. }
  719. }
  720. catch ( ... )
  721. {
  722. if ( VariableName )
  723. {
  724. delete [] VariableName;
  725. VariableName = NULL;
  726. }
  727. Status = ERROR_GEN_FAILURE;
  728. }
  729. if ( Status == ERROR_SUCCESS )
  730. {
  731. Status = REGISTRY_ReadVariableValue( a, AppNameMapping, NULL, VariableName );
  732. delete [] VariableName;
  733. VariableName = NULL;
  734. if ( Status != ERROR_SUCCESS )
  735. {
  736. if ( Status == STATUS_OBJECT_TYPE_MISMATCH )
  737. {
  738. Status = STATUS_SUCCESS;
  739. }
  740. }
  741. }
  742. }
  743. }
  744. if ( Status == STATUS_NO_MORE_ENTRIES )
  745. {
  746. Status = ERROR_SUCCESS;
  747. }
  748. NtClose ( Key );
  749. }
  750. }
  751. }
  752. }
  753. return Status;
  754. }
  755. DWORD REGISTRY_ReadSectionName ( IN PREGISTRY_PARAMETERS a )
  756. {
  757. DWORD Status = ERROR_SUCCESS;
  758. PREGISTRY_MAPPING_APPNAME AppNameMapping = NULL;
  759. HANDLE Key = INVALID_HANDLE_VALUE;
  760. WCHAR Buffer[ 256 ];
  761. PKEY_BASIC_INFORMATION KeyInformation = NULL;
  762. // temporary unicode strings
  763. UNICODE_STRING temp;
  764. PREGISTRY_MAPPING_NAME Mapping = NULL;
  765. LPWSTR BaseFileName = NULL;
  766. Status = WMIREG_GetBaseFileName ( a->FileName, &BaseFileName );
  767. if ( Status == ERROR_SUCCESS && BaseFileName )
  768. {
  769. Mapping = WMIREG_FindMapping ( a->Mapping, BaseFileName );
  770. delete [] BaseFileName;
  771. BaseFileName = NULL;
  772. }
  773. if ( Mapping )
  774. {
  775. AppNameMapping = (PREGISTRY_MAPPING_APPNAME)Mapping->ApplicationNames;
  776. while ( AppNameMapping != NULL && Status == ERROR_SUCCESS )
  777. {
  778. RtlInitUnicodeString ( &temp, AppNameMapping->Name );
  779. Status = REGISTRY_AppendBufferToResultBuffer( a, &temp, TRUE );
  780. if ( Status == ERROR_SUCCESS )
  781. {
  782. AppNameMapping = (PREGISTRY_MAPPING_APPNAME)AppNameMapping->Next;
  783. }
  784. }
  785. if ( Status == ERROR_SUCCESS )
  786. {
  787. AppNameMapping = (PREGISTRY_MAPPING_APPNAME)a->Mapping->DefaultAppNameMapping;
  788. if ( AppNameMapping != NULL )
  789. {
  790. Status = WMIREG_OpenMappingTarget ( a,
  791. reinterpret_cast < PREGISTRY_MAPPING_VARNAME > ( AppNameMapping->DefaultVarNameMapping ),
  792. NULL,
  793. &Key
  794. );
  795. if ( Status == ERROR_SUCCESS && Key != INVALID_HANDLE_VALUE )
  796. {
  797. KeyInformation = (PKEY_BASIC_INFORMATION)Buffer;
  798. for ( ULONG SubKeyIndex = 0; Status == ERROR_SUCCESS; SubKeyIndex++ )
  799. {
  800. ULONG ResultLength = 0L;
  801. Status = NtEnumerateKey( Key,
  802. SubKeyIndex,
  803. KeyBasicInformation,
  804. KeyInformation,
  805. sizeof( Buffer ),
  806. &ResultLength
  807. );
  808. if ( Status == STATUS_NO_MORE_ENTRIES )
  809. {
  810. break;
  811. }
  812. if ( NT_SUCCESS ( Status ) )
  813. {
  814. temp.Buffer = (PWSTR)&(KeyInformation->Name[0]);
  815. temp.Length = (USHORT)KeyInformation->NameLength;
  816. temp.MaximumLength = (USHORT)KeyInformation->NameLength;
  817. Status = REGISTRY_CheckSubKeyNotEmpty( Key, &temp );
  818. if ( NT_SUCCESS ( Status ) )
  819. {
  820. Status = REGISTRY_AppendBufferToResultBuffer( a, &temp, TRUE );
  821. }
  822. else
  823. if ( Status != STATUS_NO_MORE_ENTRIES )
  824. {
  825. break;
  826. }
  827. else
  828. {
  829. Status = STATUS_SUCCESS;
  830. }
  831. }
  832. }
  833. if ( Status == STATUS_NO_MORE_ENTRIES )
  834. {
  835. Status = ERROR_SUCCESS;
  836. }
  837. NtClose ( Key );
  838. }
  839. }
  840. }
  841. }
  842. return Status;
  843. }
  844. /////////////////////////////////////////////////////////////////////////////////////////
  845. // IMPLEMENTATION
  846. /////////////////////////////////////////////////////////////////////////////////////////
  847. DWORD WMIRegistry_Mapping ( IN PREGISTRY_PARAMETERS a )
  848. {
  849. DWORD Status = ERROR_INVALID_PARAMETER;
  850. if ( a )
  851. {
  852. if ( a->Operation == Registry_ReadSectionName )
  853. {
  854. Status = REGISTRY_ReadSectionName ( a );
  855. }
  856. else
  857. {
  858. LPCWSTR ApplicationName = NULL;
  859. if ( WMIREG_GetApplicationName ( a, &ApplicationName ) )
  860. {
  861. PREGISTRY_MAPPING_NAME Mapping = NULL;
  862. LPWSTR BaseFileName = NULL;
  863. Status = WMIREG_GetBaseFileName ( a->FileName, &BaseFileName );
  864. if ( Status == ERROR_SUCCESS && BaseFileName )
  865. {
  866. Mapping = WMIREG_FindMapping ( a->Mapping, BaseFileName );
  867. delete [] BaseFileName;
  868. BaseFileName = NULL;
  869. }
  870. if ( Mapping )
  871. {
  872. PREGISTRY_MAPPING_APPNAME AppNameMapping = NULL;
  873. AppNameMapping = WMIREG_FindAppNameMapping ( Mapping, ApplicationName );
  874. if ( AppNameMapping )
  875. {
  876. if ( a->Operation == Registry_ReadKeyValue )
  877. {
  878. Status = REGISTRY_ReadVariableValue ( a, AppNameMapping, NULL, NULL );
  879. }
  880. else
  881. if ( a->Operation == Registry_ReadKeyName )
  882. {
  883. Status = REGISTRY_ReadVariableName ( a, AppNameMapping );
  884. }
  885. else
  886. if ( a->Operation == Registry_ReadSectionValue )
  887. {
  888. Status = REGISTRY_ReadSectionValue ( a, AppNameMapping );
  889. }
  890. else
  891. {
  892. // not supported operation
  893. // possible write ?
  894. Status = ERROR_INVALID_PARAMETER;
  895. }
  896. }
  897. else
  898. {
  899. // no registry for this section
  900. // you should use file function
  901. Status = STATUS_MORE_PROCESSING_REQUIRED;
  902. }
  903. }
  904. }
  905. }
  906. }
  907. return Status;
  908. }
  909. ///////////////////////////////////////////////////////////////////////////////
  910. // ALLOCATION of reg structures
  911. ///////////////////////////////////////////////////////////////////////////////
  912. PREGISTRY_MAPPING_TARGET MappingTargetAlloc (
  913. IN LPCWSTR RegistryPath,
  914. OUT PULONG MappingFlags
  915. )
  916. {
  917. BOOLEAN RelativePath = FALSE;
  918. UNICODE_STRING RegistryPathString;
  919. PREGISTRY_MAPPING_TARGET MappingTarget = NULL;
  920. LPCWSTR SaveRegistryPath = RegistryPath;
  921. ULONG Flags = 0L;
  922. // simulate result
  923. *MappingFlags = Flags;
  924. BOOLEAN Continue = TRUE;
  925. while ( Continue )
  926. {
  927. try
  928. {
  929. if ( *RegistryPath == L'!' )
  930. {
  931. Flags |= REGISTRY_MAPPING_WRITE_TO_INIFILE_TOO;
  932. RegistryPath += 1;
  933. }
  934. else
  935. if ( *RegistryPath == L'#' )
  936. {
  937. Flags |= REGISTRY_MAPPING_INIT_FROM_INIFILE;
  938. RegistryPath += 1;
  939. }
  940. else
  941. if ( *RegistryPath == L'@' )
  942. {
  943. Flags |= REGISTRY_MAPPING_READ_FROM_REGISTRY_ONLY;
  944. RegistryPath += 1;
  945. }
  946. else
  947. if ( !_wcsnicmp ( RegistryPath, L"USR:", 4 ) )
  948. {
  949. Flags |= REGISTRY_MAPPING_USER_RELATIVE;
  950. RegistryPath += 4;
  951. break;
  952. }
  953. else
  954. if ( !_wcsnicmp ( RegistryPath, L"SYS:", 4 ) )
  955. {
  956. Flags |= REGISTRY_MAPPING_SOFTWARE_RELATIVE;
  957. RegistryPath += 4;
  958. break;
  959. }
  960. else
  961. {
  962. break;
  963. }
  964. }
  965. catch ( ... )
  966. {
  967. Continue = FALSE;
  968. }
  969. }
  970. if ( Continue )
  971. {
  972. if ( Flags & ( REGISTRY_MAPPING_USER_RELATIVE | REGISTRY_MAPPING_SOFTWARE_RELATIVE ) )
  973. {
  974. RelativePath = TRUE;
  975. }
  976. if ( ( RelativePath && *RegistryPath != OBJ_NAME_PATH_SEPARATOR ) ||
  977. ( !RelativePath && *RegistryPath == OBJ_NAME_PATH_SEPARATOR )
  978. )
  979. {
  980. RtlInitUnicodeString( &RegistryPathString, RegistryPath );
  981. }
  982. else
  983. if ( !RelativePath && *RegistryPath == UNICODE_NULL )
  984. {
  985. RtlInitUnicodeString( &RegistryPathString, NULL );
  986. }
  987. else
  988. {
  989. Continue = FALSE;
  990. }
  991. if ( Continue )
  992. {
  993. MappingTarget = reinterpret_cast < PREGISTRY_MAPPING_TARGET > ( RtlAllocateHeap( RtlProcessHeap (), HEAP_ZERO_MEMORY, sizeof( REGISTRY_MAPPING_TARGET ) ) );
  994. if ( MappingTarget != NULL )
  995. {
  996. *MappingFlags = Flags;
  997. MappingTarget->RegistryPath = NULL;
  998. if ( RegistryPathString.Length != 0 )
  999. {
  1000. try
  1001. {
  1002. if ( ( MappingTarget->RegistryPath = new WCHAR [ RegistryPathString.Length / sizeof ( WCHAR ) + 1 ] ) != NULL )
  1003. {
  1004. wcsncpy ( MappingTarget->RegistryPath, RegistryPathString.Buffer, RegistryPathString.Length / sizeof ( WCHAR ) );
  1005. MappingTarget->RegistryPath [RegistryPathString.Length / sizeof ( WCHAR )] = L'\0';
  1006. }
  1007. }
  1008. catch ( ... )
  1009. {
  1010. if ( MappingTarget->RegistryPath )
  1011. {
  1012. delete [] MappingTarget->RegistryPath;
  1013. MappingTarget->RegistryPath = NULL;
  1014. }
  1015. }
  1016. }
  1017. }
  1018. }
  1019. }
  1020. return MappingTarget;
  1021. }
  1022. DWORD MappingTargetFree ( IN PREGISTRY_MAPPING_TARGET MappingTarget )
  1023. {
  1024. DWORD Status = ERROR_INVALID_PARAMETER;
  1025. if ( MappingTarget )
  1026. {
  1027. PREGISTRY_MAPPING_TARGET MappingTargetNext = NULL;
  1028. MappingTargetNext = reinterpret_cast < PREGISTRY_MAPPING_TARGET > ( MappingTarget->Next );
  1029. if ( MappingTargetNext )
  1030. {
  1031. MappingTargetFree ( MappingTargetNext );
  1032. }
  1033. if ( MappingTarget->RegistryPath )
  1034. {
  1035. delete [] MappingTarget->RegistryPath;
  1036. MappingTarget->RegistryPath = NULL;
  1037. }
  1038. RtlFreeHeap( RtlProcessHeap(), 0, MappingTarget );
  1039. // success
  1040. Status = ERROR_SUCCESS;
  1041. }
  1042. return Status;
  1043. }
  1044. DWORD MappingVarNameFree ( IN PREGISTRY_MAPPING_VARNAME VarNameMapping );
  1045. BOOLEAN MappingVarNameAlloc (
  1046. PREGISTRY_MAPPING_NAME FileNameMapping,
  1047. PREGISTRY_MAPPING_APPNAME AppNameMapping,
  1048. PUNICODE_STRING VariableName,
  1049. LPCWSTR RegistryPath,
  1050. PREGISTRY_MAPPING_VARNAME *ReturnedVarNameMapping
  1051. )
  1052. {
  1053. PREGISTRY_MAPPING_TARGET MappingTarget = NULL;;
  1054. PREGISTRY_MAPPING_VARNAME VarNameMapping = NULL;
  1055. PREGISTRY_MAPPING_VARNAME *pp;
  1056. ULONG MappingFlags = 0L;
  1057. BOOLEAN Result = FALSE;
  1058. BOOLEAN Continue = TRUE;
  1059. if ( VariableName->Length != 0 )
  1060. {
  1061. pp = reinterpret_cast < PREGISTRY_MAPPING_VARNAME* > ( &AppNameMapping->VariableNames );
  1062. while ( VarNameMapping = *pp )
  1063. {
  1064. try
  1065. {
  1066. if ( VarNameMapping->Name )
  1067. {
  1068. if ( ! _wcsnicmp ( VariableName->Buffer, VarNameMapping->Name, VariableName->Length ) )
  1069. {
  1070. break;
  1071. }
  1072. }
  1073. }
  1074. catch ( ... )
  1075. {
  1076. Continue = FALSE;
  1077. break;
  1078. }
  1079. pp = reinterpret_cast < PREGISTRY_MAPPING_VARNAME* > ( &VarNameMapping->Next );
  1080. }
  1081. }
  1082. else
  1083. {
  1084. pp = reinterpret_cast < PREGISTRY_MAPPING_VARNAME* > ( &AppNameMapping->DefaultVarNameMapping );
  1085. VarNameMapping = *pp;
  1086. }
  1087. if ( Continue && VarNameMapping == NULL )
  1088. {
  1089. MappingTarget = MappingTargetAlloc ( RegistryPath, &MappingFlags );
  1090. if (MappingTarget != NULL)
  1091. {
  1092. VarNameMapping = reinterpret_cast < PREGISTRY_MAPPING_VARNAME > ( RtlAllocateHeap( RtlProcessHeap (), HEAP_ZERO_MEMORY, sizeof( REGISTRY_MAPPING_VARNAME ) ) );
  1093. if (VarNameMapping != NULL)
  1094. {
  1095. VarNameMapping->MappingFlags = MappingFlags;
  1096. VarNameMapping->MappingTarget = reinterpret_cast < ULONG_PTR > ( MappingTarget );
  1097. if ( VariableName->Length != 0 )
  1098. {
  1099. try
  1100. {
  1101. if ( ( VarNameMapping->Name = new WCHAR [ VariableName->Length / sizeof ( WCHAR ) + 1 ] ) != NULL )
  1102. {
  1103. wcsncpy ( VarNameMapping->Name, VariableName->Buffer, VariableName->Length / sizeof ( WCHAR ) );
  1104. VarNameMapping->Name [VariableName->Length / sizeof ( WCHAR )] = L'\0';
  1105. Result = TRUE;
  1106. }
  1107. }
  1108. catch ( ... )
  1109. {
  1110. if ( VarNameMapping->Name )
  1111. {
  1112. delete [] VarNameMapping->Name;
  1113. VarNameMapping->Name = NULL;
  1114. }
  1115. MappingVarNameFree ( VarNameMapping );
  1116. throw;
  1117. }
  1118. }
  1119. else
  1120. {
  1121. Result = TRUE;
  1122. }
  1123. *pp = VarNameMapping;
  1124. // return value
  1125. *ReturnedVarNameMapping = VarNameMapping;
  1126. }
  1127. }
  1128. }
  1129. return Result;
  1130. }
  1131. DWORD MappingVarNameFree ( IN PREGISTRY_MAPPING_VARNAME VarNameMapping )
  1132. {
  1133. DWORD Status = ERROR_INVALID_PARAMETER;
  1134. if ( VarNameMapping )
  1135. {
  1136. PREGISTRY_MAPPING_VARNAME VarNameMappingNext = NULL;
  1137. VarNameMappingNext = reinterpret_cast < PREGISTRY_MAPPING_VARNAME > ( VarNameMapping->Next );
  1138. if ( VarNameMappingNext )
  1139. {
  1140. MappingVarNameFree ( VarNameMappingNext );
  1141. }
  1142. // return status from helper ?
  1143. Status = MappingTargetFree ( reinterpret_cast < PREGISTRY_MAPPING_TARGET > ( VarNameMapping->MappingTarget ) );
  1144. if ( VarNameMapping->Name )
  1145. {
  1146. delete [] VarNameMapping->Name;
  1147. VarNameMapping->Name = NULL;
  1148. }
  1149. RtlFreeHeap( RtlProcessHeap(), 0, VarNameMapping );
  1150. VarNameMapping = NULL;
  1151. // success
  1152. Status = ERROR_SUCCESS;
  1153. }
  1154. return Status;
  1155. }
  1156. DWORD MappingAppNameFree ( IN PREGISTRY_MAPPING_APPNAME AppNameMapping );
  1157. BOOLEAN MappingAppNameAlloc (
  1158. PREGISTRY_MAPPING_NAME FileNameMapping,
  1159. PUNICODE_STRING ApplicationName,
  1160. PREGISTRY_MAPPING_APPNAME *ReturnedAppNameMapping
  1161. )
  1162. {
  1163. PREGISTRY_MAPPING_APPNAME AppNameMapping = NULL;
  1164. PREGISTRY_MAPPING_APPNAME *pp;
  1165. BOOLEAN Result = FALSE;
  1166. BOOLEAN Continue = TRUE;
  1167. if ( ApplicationName->Length != 0 )
  1168. {
  1169. pp = reinterpret_cast < PREGISTRY_MAPPING_APPNAME* > ( &FileNameMapping->ApplicationNames );
  1170. while ( AppNameMapping = *pp )
  1171. {
  1172. try
  1173. {
  1174. if ( AppNameMapping->Name )
  1175. {
  1176. if ( ! _wcsnicmp ( ApplicationName->Buffer, AppNameMapping->Name, ApplicationName->Length ) )
  1177. {
  1178. break;
  1179. }
  1180. }
  1181. }
  1182. catch ( ... )
  1183. {
  1184. Continue = FALSE;
  1185. break;
  1186. }
  1187. pp = reinterpret_cast < PREGISTRY_MAPPING_APPNAME* > ( &AppNameMapping->Next );
  1188. }
  1189. }
  1190. else
  1191. {
  1192. pp = reinterpret_cast < PREGISTRY_MAPPING_APPNAME* > ( &FileNameMapping->DefaultAppNameMapping );
  1193. AppNameMapping = *pp;
  1194. }
  1195. if ( Continue && AppNameMapping == NULL)
  1196. {
  1197. AppNameMapping = reinterpret_cast < PREGISTRY_MAPPING_APPNAME > ( RtlAllocateHeap( RtlProcessHeap(), HEAP_ZERO_MEMORY, sizeof( REGISTRY_MAPPING_APPNAME ) ) );
  1198. if (AppNameMapping != NULL)
  1199. {
  1200. if (ApplicationName->Length != 0)
  1201. {
  1202. try
  1203. {
  1204. if ( ( AppNameMapping->Name = new WCHAR [ ApplicationName->Length / sizeof ( WCHAR ) + 1 ] ) != NULL )
  1205. {
  1206. wcsncpy ( AppNameMapping->Name, ApplicationName->Buffer, ApplicationName->Length / sizeof ( WCHAR ) );
  1207. AppNameMapping->Name [ApplicationName->Length / sizeof ( WCHAR )] = L'\0';
  1208. Result = TRUE;
  1209. }
  1210. }
  1211. catch ( ... )
  1212. {
  1213. if ( AppNameMapping->Name )
  1214. {
  1215. delete [] AppNameMapping->Name;
  1216. AppNameMapping->Name = NULL;
  1217. }
  1218. MappingAppNameFree ( AppNameMapping );
  1219. throw;
  1220. }
  1221. }
  1222. else
  1223. {
  1224. Result = TRUE;
  1225. }
  1226. *pp = AppNameMapping;
  1227. // return value
  1228. *ReturnedAppNameMapping = AppNameMapping;
  1229. }
  1230. }
  1231. return Result;
  1232. }
  1233. DWORD MappingAppNameFree ( IN PREGISTRY_MAPPING_APPNAME AppNameMapping )
  1234. {
  1235. DWORD Status = ERROR_INVALID_PARAMETER;
  1236. if ( AppNameMapping )
  1237. {
  1238. PREGISTRY_MAPPING_APPNAME AppNameMappingNext = NULL;
  1239. AppNameMappingNext = reinterpret_cast < PREGISTRY_MAPPING_APPNAME > ( AppNameMapping->Next );
  1240. if ( AppNameMappingNext )
  1241. {
  1242. MappingAppNameFree ( AppNameMappingNext );
  1243. }
  1244. MappingVarNameFree( reinterpret_cast < PREGISTRY_MAPPING_VARNAME > ( AppNameMapping->VariableNames ) );
  1245. MappingVarNameFree( reinterpret_cast < PREGISTRY_MAPPING_VARNAME > ( AppNameMapping->DefaultVarNameMapping ) );
  1246. if ( AppNameMapping->Name )
  1247. {
  1248. delete [] AppNameMapping->Name;
  1249. AppNameMapping->Name = NULL;
  1250. }
  1251. RtlFreeHeap( RtlProcessHeap(), 0, AppNameMapping );
  1252. AppNameMapping = NULL;
  1253. // success
  1254. Status = ERROR_SUCCESS;
  1255. }
  1256. return Status;
  1257. }
  1258. BOOLEAN MappingNameAlloc (
  1259. IN PUNICODE_STRING FileName,
  1260. OUT PREGISTRY_MAPPING_NAME *ReturnedFileNameMapping
  1261. )
  1262. {
  1263. PREGISTRY_MAPPING_NAME FileNameMapping = NULL;
  1264. BOOLEAN Result = FALSE;
  1265. FileNameMapping = reinterpret_cast < PREGISTRY_MAPPING_NAME > ( RtlAllocateHeap( RtlProcessHeap (), HEAP_ZERO_MEMORY, sizeof( REGISTRY_MAPPING_NAME ) ) );
  1266. if ( FileNameMapping != NULL)
  1267. {
  1268. if (FileName->Length != 0)
  1269. {
  1270. try
  1271. {
  1272. if ( ( FileNameMapping->Name = new WCHAR [ FileName->Length / sizeof ( WCHAR ) + 1 ] ) != NULL )
  1273. {
  1274. wcsncpy ( FileNameMapping->Name, FileName->Buffer, FileName->Length / sizeof ( WCHAR ) );
  1275. FileNameMapping->Name [FileName->Length / sizeof ( WCHAR )] = L'\0';
  1276. Result = TRUE;
  1277. }
  1278. }
  1279. catch ( ... )
  1280. {
  1281. if ( FileNameMapping->Name )
  1282. {
  1283. delete [] FileNameMapping->Name;
  1284. FileNameMapping->Name = NULL;
  1285. }
  1286. }
  1287. }
  1288. else
  1289. {
  1290. Result = TRUE;
  1291. }
  1292. // return value
  1293. *ReturnedFileNameMapping = FileNameMapping;
  1294. }
  1295. return Result;
  1296. }
  1297. DWORD MappingNameFree ( IN PREGISTRY_MAPPING_NAME FileNameMapping )
  1298. {
  1299. DWORD Status = ERROR_INVALID_PARAMETER;
  1300. if ( FileNameMapping )
  1301. {
  1302. PREGISTRY_MAPPING_NAME FileNameMappingNext = NULL;
  1303. FileNameMappingNext = reinterpret_cast < PREGISTRY_MAPPING_NAME > ( FileNameMapping->Next );
  1304. if ( FileNameMappingNext )
  1305. {
  1306. MappingNameFree ( FileNameMappingNext );
  1307. }
  1308. MappingAppNameFree( reinterpret_cast < PREGISTRY_MAPPING_APPNAME > ( FileNameMapping->ApplicationNames ) );
  1309. MappingAppNameFree( reinterpret_cast < PREGISTRY_MAPPING_APPNAME > ( FileNameMapping->DefaultAppNameMapping ) );
  1310. if ( FileNameMapping->Name )
  1311. {
  1312. delete [] FileNameMapping->Name;
  1313. FileNameMapping->Name = NULL;
  1314. }
  1315. RtlFreeHeap( RtlProcessHeap(), 0, FileNameMapping );
  1316. FileNameMapping = NULL;
  1317. // success
  1318. Status = ERROR_SUCCESS;
  1319. }
  1320. return Status;
  1321. }
  1322. NTSTATUS IniFileMapping (
  1323. IN PREGISTRY_MAPPING_NAME FileNameMapping,
  1324. IN HANDLE Key,
  1325. IN LPCWSTR MyApplicationName,
  1326. IN LPCWSTR MyVariableName
  1327. )
  1328. {
  1329. NTSTATUS Status = STATUS_SUCCESS;
  1330. WCHAR Buffer[ 512 ];
  1331. PKEY_BASIC_INFORMATION KeyInformation = NULL;
  1332. PKEY_VALUE_FULL_INFORMATION KeyValueInformation = NULL;
  1333. OBJECT_ATTRIBUTES ObjectAttributes;
  1334. PREGISTRY_MAPPING_APPNAME AppNameMapping = NULL;
  1335. PREGISTRY_MAPPING_VARNAME VarNameMapping = NULL;
  1336. HANDLE SubKeyHandle = INVALID_HANDLE_VALUE;
  1337. ULONG SubKeyIndex;
  1338. UNICODE_STRING ValueName;
  1339. UNICODE_STRING SubKeyName;
  1340. UNICODE_STRING NullString;
  1341. RtlInitUnicodeString( &NullString, NULL );
  1342. //
  1343. // Enumerate node
  1344. //
  1345. KeyValueInformation = (PKEY_VALUE_FULL_INFORMATION)Buffer;
  1346. for ( ULONG ValueIndex = 0; TRUE; ValueIndex++ )
  1347. {
  1348. ULONG ResultLength = 0L;
  1349. Status = NtEnumerateValueKey ( Key,
  1350. ValueIndex,
  1351. KeyValueFullInformation,
  1352. KeyValueInformation,
  1353. sizeof( Buffer ),
  1354. &ResultLength
  1355. );
  1356. if ( Status == STATUS_NO_MORE_ENTRIES )
  1357. {
  1358. Status = STATUS_SUCCESS;
  1359. break;
  1360. }
  1361. else
  1362. if ( !NT_SUCCESS( Status ) )
  1363. {
  1364. break;
  1365. }
  1366. ValueName.Buffer = (PWSTR)&(KeyValueInformation->Name[0]);
  1367. ValueName.Length = (USHORT)KeyValueInformation->NameLength;
  1368. ValueName.MaximumLength = (USHORT)KeyValueInformation->NameLength;
  1369. if ( KeyValueInformation->Type == REG_SZ )
  1370. {
  1371. BOOL Continue = TRUE;
  1372. if ( MyApplicationName && MyVariableName )
  1373. {
  1374. if ( _wcsnicmp ( ValueName.Buffer, MyVariableName, ValueName.Length / sizeof ( WCHAR ) ) )
  1375. {
  1376. Continue = FALSE;
  1377. }
  1378. }
  1379. if ( Continue )
  1380. {
  1381. if ( MappingAppNameAlloc ( FileNameMapping, &ValueName, &AppNameMapping ) )
  1382. {
  1383. if ( MappingVarNameAlloc ( FileNameMapping,
  1384. AppNameMapping,
  1385. &NullString,
  1386. (PWSTR)((PCHAR)KeyValueInformation + KeyValueInformation->DataOffset),
  1387. &VarNameMapping
  1388. )
  1389. )
  1390. {
  1391. if (ValueName.Length == 0)
  1392. {
  1393. VarNameMapping->MappingFlags |= REGISTRY_MAPPING_APPEND_APPLICATION_NAME;
  1394. }
  1395. }
  1396. }
  1397. }
  1398. }
  1399. }
  1400. //
  1401. // Enumerate node's children and apply ourselves to each one
  1402. //
  1403. KeyInformation = (PKEY_BASIC_INFORMATION)Buffer;
  1404. for ( ULONG SubKeyIndex = 0; TRUE; SubKeyIndex++ )
  1405. {
  1406. ULONG ResultLength = 0L;
  1407. Status = NtEnumerateKey ( Key,
  1408. SubKeyIndex,
  1409. KeyBasicInformation,
  1410. KeyInformation,
  1411. sizeof( Buffer ),
  1412. &ResultLength
  1413. );
  1414. if ( Status == STATUS_NO_MORE_ENTRIES)
  1415. {
  1416. Status = STATUS_SUCCESS;
  1417. break;
  1418. }
  1419. else
  1420. if ( !NT_SUCCESS ( Status ) )
  1421. {
  1422. break;
  1423. }
  1424. SubKeyName.Buffer = (PWSTR)&(KeyInformation->Name[0]);
  1425. SubKeyName.Length = (USHORT)KeyInformation->NameLength;
  1426. SubKeyName.MaximumLength = (USHORT)KeyInformation->NameLength;
  1427. InitializeObjectAttributes ( &ObjectAttributes,
  1428. &SubKeyName,
  1429. OBJ_CASE_INSENSITIVE,
  1430. Key,
  1431. NULL
  1432. );
  1433. BOOL Continue = TRUE;
  1434. if ( MyApplicationName )
  1435. {
  1436. if ( _wcsnicmp ( SubKeyName.Buffer, MyApplicationName, SubKeyName.Length / sizeof ( WCHAR ) ) )
  1437. {
  1438. Continue = FALSE;
  1439. }
  1440. }
  1441. if ( Continue )
  1442. {
  1443. Status = NtOpenKey( &SubKeyHandle, GENERIC_READ, &ObjectAttributes );
  1444. try
  1445. {
  1446. if ( NT_SUCCESS( Status ) && SubKeyHandle != INVALID_HANDLE_VALUE && MappingAppNameAlloc( FileNameMapping, &SubKeyName, &AppNameMapping ) )
  1447. {
  1448. KeyValueInformation = (PKEY_VALUE_FULL_INFORMATION)Buffer;
  1449. for ( ULONG ValueIndex = 0; AppNameMapping != NULL; ValueIndex++ )
  1450. {
  1451. Status = NtEnumerateValueKey ( SubKeyHandle,
  1452. ValueIndex,
  1453. KeyValueFullInformation,
  1454. KeyValueInformation,
  1455. sizeof( Buffer ),
  1456. &ResultLength
  1457. );
  1458. if ( Status == STATUS_NO_MORE_ENTRIES )
  1459. {
  1460. Status = STATUS_SUCCESS;
  1461. break;
  1462. }
  1463. else
  1464. if ( !NT_SUCCESS ( Status ) )
  1465. {
  1466. break;
  1467. }
  1468. ValueName.Buffer = (PWSTR)&(KeyValueInformation->Name[0]);
  1469. ValueName.Length = (USHORT)KeyValueInformation->NameLength;
  1470. ValueName.MaximumLength = (USHORT)KeyValueInformation->NameLength;
  1471. BOOL ContinueValue = TRUE;
  1472. if ( MyApplicationName && MyVariableName )
  1473. {
  1474. if ( _wcsnicmp ( ValueName.Buffer, MyVariableName, ValueName.Length / sizeof ( WCHAR ) ) )
  1475. {
  1476. ContinueValue = FALSE;
  1477. }
  1478. }
  1479. if ( ContinueValue )
  1480. {
  1481. if ( KeyValueInformation->Type == REG_SZ )
  1482. {
  1483. MappingVarNameAlloc ( FileNameMapping,
  1484. AppNameMapping,
  1485. &ValueName,
  1486. (PWSTR)((PCHAR)KeyValueInformation + KeyValueInformation->DataOffset),
  1487. &VarNameMapping
  1488. );
  1489. }
  1490. }
  1491. }
  1492. NtClose( SubKeyHandle );
  1493. SubKeyHandle = INVALID_HANDLE_VALUE;
  1494. }
  1495. }
  1496. catch ( ... )
  1497. {
  1498. if ( SubKeyHandle && SubKeyHandle != INVALID_HANDLE_VALUE )
  1499. {
  1500. NtClose( SubKeyHandle );
  1501. SubKeyHandle = INVALID_HANDLE_VALUE;
  1502. }
  1503. throw;
  1504. }
  1505. }
  1506. }
  1507. return Status;
  1508. }
  1509. DWORD WMIRegistry_InitMapping ( PREGISTRY_PARAMETERS a )
  1510. {
  1511. DWORD Status = ERROR_INVALID_PARAMETER;
  1512. PREGISTRY_MAPPING_NAME RegistryMapping = NULL;
  1513. if ( a )
  1514. {
  1515. // prepare mapping
  1516. a->Mapping = NULL;
  1517. NTSTATUS NtStatus = STATUS_SUCCESS;
  1518. PREGISTRY_MAPPING_NAME DefaultFileNameMapping = NULL;
  1519. PREGISTRY_MAPPING_NAME FileNames = NULL;
  1520. PREGISTRY_MAPPING_APPNAME AppNameMapping = NULL;
  1521. PREGISTRY_MAPPING_VARNAME VarNameMapping = NULL;
  1522. OBJECT_ATTRIBUTES ObjectAttributes;
  1523. HANDLE IniFileMappingRoot = INVALID_HANDLE_VALUE;
  1524. PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation = NULL;
  1525. PKEY_BASIC_INFORMATION KeyInformation = NULL;
  1526. WCHAR Buffer[ 512 ];
  1527. LPWSTR BaseFileName = NULL;
  1528. Status = WMIREG_GetBaseFileName ( a->FileName, &BaseFileName );
  1529. if ( Status == ERROR_SUCCESS && BaseFileName )
  1530. {
  1531. UNICODE_STRING FullKeyName;
  1532. FullKeyName.Length = 0;
  1533. FullKeyName.MaximumLength = ( wcslen ( L"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\IniFileMapping\\" ) + wcslen ( BaseFileName ) + 1 ) * sizeof ( WCHAR );
  1534. FullKeyName.Buffer = reinterpret_cast < PWSTR > ( RtlAllocateHeap( RtlProcessHeap(), 0, FullKeyName.MaximumLength ) );
  1535. if ( FullKeyName.Buffer != NULL )
  1536. {
  1537. RtlAppendUnicodeToString ( &FullKeyName, L"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\IniFileMapping\\" );
  1538. RtlAppendUnicodeToString ( &FullKeyName, BaseFileName );
  1539. InitializeObjectAttributes ( &ObjectAttributes,
  1540. &FullKeyName,
  1541. OBJ_CASE_INSENSITIVE,
  1542. NULL,
  1543. NULL
  1544. );
  1545. NtStatus = NtOpenKey ( &IniFileMappingRoot,
  1546. GENERIC_READ,
  1547. &ObjectAttributes
  1548. );
  1549. if ( NT_SUCCESS ( NtStatus ) && IniFileMappingRoot != INVALID_HANDLE_VALUE )
  1550. {
  1551. UNICODE_STRING BaseFile;
  1552. RtlInitUnicodeString ( &BaseFile, BaseFileName );
  1553. if ( ! MappingNameAlloc( &BaseFile, &FileNames ) )
  1554. {
  1555. NtStatus = STATUS_NO_MEMORY;
  1556. }
  1557. else
  1558. {
  1559. try
  1560. {
  1561. NtStatus = IniFileMapping( FileNames, IniFileMappingRoot, a->ApplicationName, a->VariableName );
  1562. }
  1563. catch ( ... )
  1564. {
  1565. MappingNameFree ( FileNames );
  1566. FileNames = NULL;
  1567. NtStatus = STATUS_NO_MEMORY;
  1568. }
  1569. if ( ! NT_SUCCESS ( NtStatus ) )
  1570. {
  1571. if ( FileNames )
  1572. {
  1573. RtlFreeHeap( RtlProcessHeap(), 0, FileNames );
  1574. FileNames = NULL;
  1575. }
  1576. }
  1577. }
  1578. if ( NT_SUCCESS ( NtStatus ) )
  1579. {
  1580. a->Mapping = FileNames;
  1581. }
  1582. // close main root
  1583. if ( IniFileMappingRoot && IniFileMappingRoot != INVALID_HANDLE_VALUE )
  1584. {
  1585. NtClose ( IniFileMappingRoot );
  1586. IniFileMappingRoot = NULL;
  1587. }
  1588. }
  1589. // clear buffer
  1590. RtlFreeHeap ( RtlProcessHeap (), 0, FullKeyName.Buffer );
  1591. }
  1592. else
  1593. {
  1594. NtStatus = STATUS_NO_MEMORY;
  1595. }
  1596. // we are done with looking for
  1597. delete [] BaseFileName;
  1598. BaseFileName = NULL;
  1599. }
  1600. // name has not found ( get ready for default )
  1601. if ( NT_SUCCESS ( NtStatus ) && a->Mapping == NULL )
  1602. {
  1603. UNICODE_STRING KeyName;
  1604. RtlInitUnicodeString ( &KeyName,
  1605. L"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\IniFileMapping"
  1606. );
  1607. InitializeObjectAttributes ( &ObjectAttributes,
  1608. &KeyName,
  1609. OBJ_CASE_INSENSITIVE,
  1610. NULL,
  1611. NULL
  1612. );
  1613. NtStatus = NtOpenKey ( &IniFileMappingRoot,
  1614. GENERIC_READ,
  1615. &ObjectAttributes
  1616. );
  1617. if ( NT_SUCCESS ( NtStatus ) && IniFileMappingRoot != INVALID_HANDLE_VALUE )
  1618. {
  1619. ULONG ResultLength = 0L;
  1620. UNICODE_STRING NullString;
  1621. RtlInitUnicodeString( &NullString, NULL );
  1622. UNICODE_STRING ValueName;
  1623. RtlInitUnicodeString( &ValueName, NULL );
  1624. NtStatus = NtQueryValueKey ( IniFileMappingRoot,
  1625. &ValueName,
  1626. KeyValuePartialInformation,
  1627. KeyValueInformation,
  1628. sizeof( Buffer ),
  1629. &ResultLength
  1630. );
  1631. try
  1632. {
  1633. if ( NT_SUCCESS ( NtStatus ) )
  1634. {
  1635. if ( MappingNameAlloc( &NullString, &DefaultFileNameMapping ) )
  1636. {
  1637. if ( MappingAppNameAlloc ( DefaultFileNameMapping, &NullString, &AppNameMapping ) )
  1638. {
  1639. if ( MappingVarNameAlloc ( DefaultFileNameMapping, AppNameMapping, &NullString, (PWSTR)(KeyValueInformation->Data), &VarNameMapping ) )
  1640. {
  1641. VarNameMapping->MappingFlags |= REGISTRY_MAPPING_APPEND_BASE_NAME | REGISTRY_MAPPING_APPEND_APPLICATION_NAME;
  1642. // assign proper mapping
  1643. a->Mapping = DefaultFileNameMapping;
  1644. }
  1645. }
  1646. }
  1647. }
  1648. }
  1649. catch ( ... )
  1650. {
  1651. MappingNameFree ( DefaultFileNameMapping );
  1652. DefaultFileNameMapping = NULL;
  1653. a->Mapping = NULL;
  1654. NtStatus = STATUS_NO_MEMORY;
  1655. }
  1656. // close main root
  1657. if ( IniFileMappingRoot && IniFileMappingRoot != INVALID_HANDLE_VALUE )
  1658. {
  1659. NtClose ( IniFileMappingRoot );
  1660. IniFileMappingRoot = NULL;
  1661. }
  1662. }
  1663. }
  1664. if ( a->Mapping )
  1665. {
  1666. // return success
  1667. Status = ERROR_SUCCESS;
  1668. }
  1669. else
  1670. {
  1671. if ( NT_SUCCESS ( NtStatus ) )
  1672. {
  1673. // we do not have mapping
  1674. Status = STATUS_MORE_PROCESSING_REQUIRED;
  1675. }
  1676. else
  1677. {
  1678. Status = NtStatus;
  1679. }
  1680. }
  1681. }
  1682. return Status;
  1683. }
  1684. DWORD WMIRegistry_ParametersInit (
  1685. #ifdef WRITE_OPERATION
  1686. BOOLEAN WriteOperation,
  1687. #endif WRITE_OPERATION
  1688. REGISTRY_OPERATION Operation,
  1689. BOOLEAN MultiValueStrings,
  1690. LPCWSTR FileName,
  1691. LPCWSTR ApplicationName,
  1692. LPCWSTR VariableName,
  1693. LPWSTR VariableValue,
  1694. PULONG ResultMaxChars,
  1695. PREGISTRY_PARAMETERS *ReturnedParameterBlock
  1696. )
  1697. {
  1698. DWORD Status = ERROR_SUCCESS;
  1699. PREGISTRY_PARAMETERS a = NULL;
  1700. if ( ! ReturnedParameterBlock )
  1701. {
  1702. Status = ERROR_INVALID_PARAMETER;
  1703. }
  1704. if ( Status == ERROR_SUCCESS )
  1705. {
  1706. try
  1707. {
  1708. a = new REGISTRY_PARAMETERS();
  1709. if ( a== NULL )
  1710. {
  1711. Status = ERROR_NOT_ENOUGH_MEMORY;
  1712. }
  1713. }
  1714. catch ( ... )
  1715. {
  1716. if ( a )
  1717. {
  1718. delete a;
  1719. a = NULL;
  1720. }
  1721. Status = ERROR_NOT_ENOUGH_MEMORY;
  1722. }
  1723. }
  1724. if ( Status == ERROR_SUCCESS )
  1725. {
  1726. #ifdef WRITE_OPERATION
  1727. a->WriteOperation = WriteOperation;
  1728. #endif WRITE_OPERATION
  1729. a->ValueBufferAllocated = FALSE;
  1730. a->Operation = Operation;
  1731. a->MultiValueStrings = MultiValueStrings;
  1732. if ( FileName )
  1733. {
  1734. a->FileName = FileName;
  1735. }
  1736. else
  1737. {
  1738. a->FileName = L"win.ini";
  1739. }
  1740. // section name
  1741. if ( ApplicationName )
  1742. {
  1743. a->ApplicationName = ApplicationName;
  1744. }
  1745. else
  1746. {
  1747. a->ApplicationName = NULL;
  1748. }
  1749. // key name
  1750. if ( VariableName )
  1751. {
  1752. a->VariableName= VariableName;
  1753. }
  1754. else
  1755. {
  1756. a->VariableName= NULL;
  1757. }
  1758. Status = WMIRegistry_InitMapping ( a );
  1759. if ( Status != ERROR_SUCCESS )
  1760. {
  1761. delete a;
  1762. a = NULL;
  1763. }
  1764. else
  1765. {
  1766. // key value
  1767. if ( VariableValue )
  1768. {
  1769. #ifdef WRITE_OPERATION
  1770. if (a->WriteOperation)
  1771. {
  1772. a->ValueBuffer = VariableValue;
  1773. a->ValueLength = wcslen ( VariableValue );
  1774. }
  1775. else
  1776. #endif WRITE_OPERATION
  1777. {
  1778. if ( ResultMaxChars )
  1779. {
  1780. a->ResultMaxChars = *ResultMaxChars;
  1781. }
  1782. else
  1783. {
  1784. a->ResultMaxChars = 0;
  1785. }
  1786. a->ResultChars = 0;
  1787. a->ResultBuffer = VariableValue;
  1788. }
  1789. }
  1790. else
  1791. {
  1792. #ifdef WRITE_OPERATION
  1793. if ( a->WriteOperation )
  1794. {
  1795. a->ValueBuffer = NULL;
  1796. a->ValueLength = 0;
  1797. }
  1798. else
  1799. #endif WRITE_OPERATION
  1800. {
  1801. a->ResultMaxChars = 0;
  1802. a->ResultChars = 0;
  1803. a->ResultBuffer = NULL;
  1804. }
  1805. }
  1806. }
  1807. }
  1808. if ( ReturnedParameterBlock )
  1809. {
  1810. *ReturnedParameterBlock = a;
  1811. }
  1812. return Status;
  1813. }
  1814. DWORD WMIRegistry_ParametersClear (
  1815. PREGISTRY_PARAMETERS ParameterBlock
  1816. )
  1817. {
  1818. DWORD Status = ERROR_SUCCESS;
  1819. if ( ! ParameterBlock )
  1820. {
  1821. Status = ERROR_INVALID_PARAMETER;
  1822. }
  1823. if ( Status == ERROR_SUCCESS )
  1824. {
  1825. if ( ParameterBlock->Mapping )
  1826. {
  1827. MappingNameFree ( ParameterBlock->Mapping );
  1828. ParameterBlock->Mapping = NULL;
  1829. }
  1830. delete ParameterBlock;
  1831. ParameterBlock = NULL;
  1832. }
  1833. return Status;
  1834. }
  1835. ///////////////////////////////////////////////////////////////////////////////
  1836. // read function
  1837. ///////////////////////////////////////////////////////////////////////////////
  1838. DWORD WMIRegistry (
  1839. #ifdef WRITE_OPERATION
  1840. IN BOOLEAN WriteOperation,
  1841. #endif WRITE_OPERATION
  1842. IN BOOLEAN SectionOperation,
  1843. IN LPCWSTR FileName,
  1844. IN LPCWSTR ApplicationName,
  1845. IN LPCWSTR VariableName,
  1846. IN OUT LPWSTR VariableValue,
  1847. IN OUT PULONG VariableValueLength
  1848. )
  1849. {
  1850. // variables
  1851. DWORD Status = ERROR_INVALID_PARAMETER;
  1852. REGISTRY_OPERATION Operation = Registry_None;
  1853. BOOLEAN MultiValueStrings = FALSE;
  1854. if ( SectionOperation )
  1855. {
  1856. VariableName = NULL;
  1857. }
  1858. if ( ApplicationName )
  1859. {
  1860. if ( VariableValue )
  1861. {
  1862. if ( VariableName )
  1863. {
  1864. Operation = Registry_ReadKeyValue;
  1865. }
  1866. else
  1867. {
  1868. if ( SectionOperation )
  1869. {
  1870. Operation = Registry_ReadSectionValue;
  1871. MultiValueStrings = TRUE;
  1872. }
  1873. else
  1874. {
  1875. Operation = Registry_ReadKeyName;
  1876. MultiValueStrings = TRUE;
  1877. }
  1878. }
  1879. }
  1880. }
  1881. else
  1882. {
  1883. if ( ! ( SectionOperation || ! VariableValue ) )
  1884. {
  1885. Operation = Registry_ReadSectionName;
  1886. MultiValueStrings = TRUE;
  1887. }
  1888. }
  1889. // real operation
  1890. if ( Operation != Registry_None )
  1891. {
  1892. PREGISTRY_PARAMETERS a = NULL;
  1893. Status = WMIRegistry_ParametersInit (
  1894. #ifdef WRITE_OPERATION
  1895. WriteOperation,
  1896. #endif WRITE_OPERATION
  1897. Operation,
  1898. MultiValueStrings,
  1899. FileName,
  1900. ApplicationName,
  1901. VariableName,
  1902. VariableValue,
  1903. VariableValueLength,
  1904. &a
  1905. );
  1906. if ( Status == ERROR_SUCCESS )
  1907. {
  1908. if ( a->Mapping != NULL )
  1909. {
  1910. Status = WMIRegistry_Mapping( a );
  1911. if ( Status == ERROR_SUCCESS || Status == ERROR_MORE_DATA )
  1912. {
  1913. if ( a->Operation == Registry_ReadKeyName ||
  1914. a->Operation == Registry_ReadSectionName ||
  1915. a->Operation == Registry_ReadSectionValue
  1916. )
  1917. {
  1918. REGISTRY_AppendNULLToResultBuffer ( a );
  1919. }
  1920. if ( VariableValueLength )
  1921. {
  1922. *VariableValueLength = a->ResultChars;
  1923. }
  1924. }
  1925. }
  1926. else
  1927. {
  1928. Status = ERROR_INVALID_PARAMETER;
  1929. if ( VariableValueLength )
  1930. {
  1931. *VariableValueLength = 0;
  1932. }
  1933. }
  1934. }
  1935. WMIRegistry_ParametersClear ( a );
  1936. }
  1937. ::SetLastError ( Status );
  1938. return Status;
  1939. }
  1940. ///////////////////////////////////////////////////////////////////////////////
  1941. // get profile string
  1942. ///////////////////////////////////////////////////////////////////////////////
  1943. DWORD APIENTRY WMIRegistry_PrivateProfileString (
  1944. LPCWSTR lpAppName,
  1945. LPCWSTR lpKeyName,
  1946. LPCWSTR lpDefault,
  1947. LPWSTR lpReturnedString,
  1948. DWORD nSize,
  1949. LPCWSTR lpFileName
  1950. )
  1951. {
  1952. DWORD Status = ERROR_SUCCESS;
  1953. ULONG n = nSize;
  1954. if ( lpDefault == NULL )
  1955. {
  1956. lpDefault = L"";
  1957. }
  1958. Status = WMIRegistry (
  1959. #ifdef WRITE_OPERATION
  1960. FALSE, // Write operation
  1961. #endif WRITE_OPERATION
  1962. FALSE, // SectionOperation
  1963. lpFileName,
  1964. lpAppName,
  1965. lpKeyName,
  1966. lpReturnedString,
  1967. &n
  1968. );
  1969. if ( n && ( Status == ERROR_SUCCESS || Status == STATUS_BUFFER_OVERFLOW ) )
  1970. {
  1971. if ( Status == ERROR_SUCCESS )
  1972. {
  1973. n--;
  1974. }
  1975. else
  1976. {
  1977. if ( !lpAppName || !lpKeyName )
  1978. {
  1979. if ( nSize >= 2 )
  1980. {
  1981. n = nSize - 2;
  1982. lpReturnedString[ n+1 ] = L'\0';
  1983. }
  1984. else
  1985. {
  1986. n = 0;
  1987. }
  1988. }
  1989. else
  1990. {
  1991. if ( nSize >= 1 )
  1992. {
  1993. n = nSize - 1;
  1994. }
  1995. else
  1996. {
  1997. n = 0;
  1998. }
  1999. }
  2000. }
  2001. }
  2002. else
  2003. {
  2004. n = wcslen( lpDefault );
  2005. while ( n > 0 && lpDefault[n-1] == L' ')
  2006. {
  2007. n -= 1;
  2008. }
  2009. if (n >= nSize)
  2010. {
  2011. n = nSize;
  2012. }
  2013. wcsncpy ( lpReturnedString, lpDefault, n );
  2014. }
  2015. if ( n < nSize )
  2016. {
  2017. lpReturnedString[ n ] = L'\0';
  2018. }
  2019. else
  2020. {
  2021. if ( nSize > 0 )
  2022. {
  2023. lpReturnedString[ nSize-1 ] = L'\0';
  2024. }
  2025. }
  2026. return n;
  2027. }
  2028. ///////////////////////////////////////////////////////////////////////////////
  2029. // get profile section
  2030. ///////////////////////////////////////////////////////////////////////////////
  2031. DWORD APIENTRY WMIRegistry_PrivateProfileSection (
  2032. LPCWSTR lpAppName,
  2033. LPWSTR lpReturnedString,
  2034. DWORD nSize,
  2035. LPCWSTR lpFileName
  2036. )
  2037. {
  2038. NTSTATUS Status;
  2039. ULONG n;
  2040. n = nSize;
  2041. Status = WMIRegistry (
  2042. #ifdef WRITE_OPERATION
  2043. FALSE, // Write operation
  2044. #endif WRITE_OPERATION
  2045. TRUE, // SectionOperation
  2046. lpFileName,
  2047. lpAppName,
  2048. NULL,
  2049. lpReturnedString,
  2050. &n
  2051. );
  2052. if ( Status == ERROR_SUCCESS || Status == STATUS_BUFFER_OVERFLOW )
  2053. {
  2054. if ( Status == ERROR_SUCCESS )
  2055. {
  2056. n--;
  2057. }
  2058. else
  2059. {
  2060. if ( nSize >= 2 )
  2061. {
  2062. n = nSize - 2;
  2063. lpReturnedString[ n+1 ] = L'\0';
  2064. }
  2065. else
  2066. {
  2067. n = 0;
  2068. }
  2069. }
  2070. }
  2071. else
  2072. {
  2073. n = 0;
  2074. }
  2075. if ( n < nSize )
  2076. {
  2077. lpReturnedString[ n ] = L'\0';
  2078. }
  2079. else
  2080. {
  2081. if ( nSize > 0 )
  2082. {
  2083. lpReturnedString[ nSize-1 ] = L'\0';
  2084. }
  2085. }
  2086. return n;
  2087. }
  2088. ///////////////////////////////////////////////////////////////////////////////
  2089. // get profile integer
  2090. ///////////////////////////////////////////////////////////////////////////////
  2091. UINT APIENTRY WMIRegistry_PrivateProfileInt (
  2092. LPCWSTR lpAppName,
  2093. LPCWSTR lpKeyName,
  2094. INT nDefault
  2095. )
  2096. {
  2097. WCHAR ValueBuffer[ 256 ];
  2098. ULONG ReturnValue = nDefault;
  2099. ULONG cb = 0;
  2100. cb = WMIRegistry_PrivateProfileString ( lpAppName,
  2101. lpKeyName,
  2102. NULL,
  2103. ValueBuffer,
  2104. sizeof( ValueBuffer ) / sizeof( WCHAR ),
  2105. NULL
  2106. );
  2107. if ( cb )
  2108. {
  2109. // convert value to integer
  2110. _wtoi ( ValueBuffer );
  2111. }
  2112. return ReturnValue;
  2113. }
  2114. ///////////////////////////////////////////////////////////////////////////////
  2115. // get profile integer caller
  2116. ///////////////////////////////////////////////////////////////////////////////
  2117. UINT APIENTRY WMIRegistry_ProfileInt (
  2118. LPCWSTR lpAppName,
  2119. LPCWSTR lpKeyName,
  2120. INT nDefault
  2121. )
  2122. {
  2123. return( WMIRegistry_PrivateProfileInt ( lpAppName,
  2124. lpKeyName,
  2125. nDefault
  2126. )
  2127. );
  2128. }
  2129. ///////////////////////////////////////////////////////////////////////////////
  2130. // get profile section caller
  2131. ///////////////////////////////////////////////////////////////////////////////
  2132. DWORD APIENTRY WMIRegistry_ProfileSection (
  2133. LPCWSTR lpAppName,
  2134. LPWSTR lpReturnedString,
  2135. DWORD nSize
  2136. )
  2137. {
  2138. return( WMIRegistry_PrivateProfileSection ( lpAppName,
  2139. lpReturnedString,
  2140. nSize,
  2141. NULL
  2142. )
  2143. );
  2144. }
  2145. ///////////////////////////////////////////////////////////////////////////////
  2146. // get profile string caller
  2147. ///////////////////////////////////////////////////////////////////////////////
  2148. DWORD APIENTRY WMIRegistry_ProfileString (
  2149. LPCWSTR lpAppName,
  2150. LPCWSTR lpKeyName,
  2151. LPCWSTR lpDefault,
  2152. LPWSTR lpReturnedString,
  2153. DWORD nSize
  2154. )
  2155. {
  2156. return( WMIRegistry_PrivateProfileString ( lpAppName,
  2157. lpKeyName,
  2158. lpDefault,
  2159. lpReturnedString,
  2160. nSize,
  2161. NULL
  2162. )
  2163. );
  2164. }