Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1892 lines
45 KiB

  1. #include "precomp.h"
  2. #pragma hdrstop
  3. //
  4. // Uncomment the next #define line to get debug trace info about
  5. // Registry keys opened, created or closed.
  6. //
  7. // #define DBG_REG_HANDLES
  8. //
  9. extern HWND hwndFrame;
  10. //
  11. // Updated by DavidHov on 6/1/92:
  12. //
  13. // Centralized error handling;
  14. // Eliminated "title" parameter from APIs; it's
  15. // reserved now, so using it gives "invalid parameter"
  16. //
  17. //
  18. // Updated by DavidHov on 1/6/93
  19. //
  20. // Chnaged FCreateRegKey and FOpenRegKey to always update
  21. // the desired value; a null (empty) string is used if the
  22. // operation has failed.
  23. //
  24. //
  25. // Local Prototypes
  26. //
  27. BOOL FDeleteTree( HKEY KeyHandle );
  28. BOOL FSetRegValueSz( HKEY hKey, SZ szValueName, UINT TitleIndex, SZ szValueData );
  29. BOOL FSetRegValueExpandSz( HKEY hKey, SZ szValueName, UINT TitleIndex, SZ szValueData );
  30. BOOL FSetRegValueMultiSz( HKEY hKey, SZ szValueName, UINT TitleIndex, UINT ValueType, SZ szValueData );
  31. BOOL FSetRegValueDword( HKEY hKey, SZ szValueName, UINT TitleIndex, SZ szValueData );
  32. BOOL FSetRegValueBin( HKEY hKey, SZ szValueName, UINT TitleIndex, UINT ValueType, SZ szValueData );
  33. PVOID SzToMultiSz( SZ sz, PDWORD cbData );
  34. SZ MultiSzToSz( PVOID Data, DWORD cbData );
  35. PVOID SzToBin( SZ sz, PDWORD cbData );
  36. SZ BinToSz( PVOID Data, DWORD cbData );
  37. SZ ValueDataToSz( DWORD ValueType, PVOID ValueData, DWORD cbData );
  38. //
  39. // Central error handling for all Registry processing errors.
  40. //
  41. void FUpdateRegLastError ( LONG Status, SZ szOp, SZ szName )
  42. {
  43. char RegLastError[25];
  44. _ltoa( Status, RegLastError, 10 );
  45. FAddSymbolValueToSymTab( REGLASTERROR, RegLastError );
  46. /* Uncomment to display all registry errors and their origin */
  47. #if defined(DBG_REG_HANDLES)
  48. OutputDebugString( "SETUP: Reg Error in " );
  49. OutputDebugString( szOp );
  50. OutputDebugString( " = " );
  51. OutputDebugString( RegLastError ) ;
  52. if ( szName )
  53. {
  54. OutputDebugString( "; " );
  55. OutputDebugString( szName ) ;
  56. }
  57. OutputDebugString( "\n" );
  58. #endif
  59. }
  60. // Debugging helper routing for finding lost Registry handles.
  61. void FDebugRegKey ( SZ szHandle, SZ szAction, SZ szName )
  62. {
  63. OutputDebugString( "SETUP: REGKEYTRACE: " );
  64. OutputDebugString( szHandle );
  65. OutputDebugString( " : " );
  66. OutputDebugString( szAction );
  67. OutputDebugString( " : " );
  68. if ( szName )
  69. {
  70. OutputDebugString( szName ) ;
  71. }
  72. OutputDebugString( "\n" );
  73. }
  74. #if defined(DBG_REG_HANDLES)
  75. #define DEBUGREGKEY(a,b,c) FDebugRegKey(a,b,c)
  76. #else
  77. #define DEBUGREGKEY(a,b,c)
  78. #endif
  79. /*
  80. * FCreateRegKey
  81. *
  82. * Crates a key in the registry
  83. *
  84. * Arguments:
  85. *
  86. */
  87. BOOL FCreateRegKey( SZ szHandle, SZ szKeyName, UINT TitleIndex, SZ szClass,
  88. SZ Security, UINT Access, UINT Options, SZ szNewHandle,
  89. CMO cmo )
  90. {
  91. BOOL fOkay;
  92. HKEY hKey;
  93. HKEY hSubKey;
  94. DWORD Disposition;
  95. LONG Status;
  96. char LibraryHandleSTR[25];
  97. LPSECURITY_ATTRIBUTES SecurityAttributes;
  98. hKey = (HKEY)LongToHandle(atol( szHandle + 1 ));
  99. //
  100. // If the Security parameter is specified, it must contain the
  101. // string "&<Address>" where <Address> is the decimal numeric
  102. // representation of the memory address of a SECURITY_ATTRIBUTES
  103. // structure.
  104. //
  105. if ( !Security || Security[0] != '\0' ) {
  106. if ( Security[0] != '&' ) {
  107. return fFalse;
  108. }
  109. SecurityAttributes = (LPSECURITY_ATTRIBUTES)LongToHandle(atol( Security + 1 ));
  110. if ( !SecurityAttributes ||
  111. !IsValidSecurityDescriptor( SecurityAttributes->lpSecurityDescriptor )
  112. ) {
  113. return fFalse;
  114. }
  115. } else {
  116. SecurityAttributes = NULL;
  117. }
  118. //
  119. // Create the key
  120. //
  121. fOkay = !( Status = RegCreateKeyEx( hKey,
  122. szKeyName,
  123. 0,
  124. szClass,
  125. Options,
  126. Access,
  127. SecurityAttributes,
  128. &hSubKey,
  129. &Disposition ));
  130. // Prepare an initial null result
  131. LibraryHandleSTR[0] = '\0' ;
  132. if ( !fOkay ) {
  133. FUpdateRegLastError( Status, "CreateRegKey", szKeyName );
  134. } else {
  135. //
  136. // If the key already existed, we error out.
  137. //
  138. if ( Disposition == REG_OPENED_EXISTING_KEY ) {
  139. RegCloseKey( hSubKey );
  140. FUpdateRegLastError( ERROR_CANTOPEN, "CreateRegKey", szKeyName );
  141. fOkay = fFalse;
  142. } else {
  143. //
  144. // Put the handle in the specified variable
  145. //
  146. LibraryHandleSTR[0] = '|';
  147. #if defined(_WIN64)
  148. _ui64toa( (DWORD_PTR)hSubKey, LibraryHandleSTR+1, 20 );
  149. #else
  150. _ultoa( (DWORD)hSubKey, LibraryHandleSTR+1, 10 );
  151. #endif
  152. DEBUGREGKEY( LibraryHandleSTR+1, "created", szKeyName ) ;
  153. }
  154. }
  155. // Always add the value to the symbol table, even if null (empty).
  156. while ( !FAddSymbolValueToSymTab( szNewHandle, LibraryHandleSTR ) )
  157. {
  158. if ( !FHandleOOM( hwndFrame ) )
  159. {
  160. if ( fOkay )
  161. {
  162. RegCloseKey( hSubKey );
  163. RegDeleteKey( hKey, szKeyName );
  164. fOkay = fFalse;
  165. }
  166. break;
  167. }
  168. }
  169. return (cmo & cmoVital) ? fOkay : fTrue;
  170. }
  171. /*
  172. * FOpenRegKey
  173. *
  174. * Opens a key in the registry
  175. *
  176. * Arguments:
  177. *
  178. */
  179. BOOL FOpenRegKey( SZ szHandle, SZ szMachineName, SZ szKeyName, UINT Access, SZ szNewHandle, CMO cmo )
  180. {
  181. BOOL fOkay = fTrue;
  182. HKEY hKey;
  183. HKEY hSubKey;
  184. LONG Status;
  185. char LibraryHandleSTR[25];
  186. hKey = (HKEY)LongToHandle(atol( szHandle + 1 ));
  187. //
  188. // If a remote machine is specified, we connect to the remote
  189. // machine and use the new handle.
  190. //
  191. if ( szMachineName[0] != '\0' ) {
  192. // BUGBUG ramonsa - Until RegConnectRegistry is operational
  193. //
  194. Status = ERROR_INVALID_PARAMETER;
  195. fOkay = fFalse;
  196. //
  197. //fOkay = !(Status = RegConnectRegistry( szMachineName,
  198. // hKey,
  199. // &hKey
  200. // );
  201. } else if ( szKeyName[0] == '\0' ) {
  202. //
  203. // If no machine name was given then a subkey name must
  204. // be given!
  205. //
  206. Status = ERROR_INVALID_PARAMETER;
  207. fOkay = fFalse;
  208. }
  209. // Prepare an initial null result
  210. LibraryHandleSTR[0] = '\0' ;
  211. if ( fOkay ) {
  212. //
  213. // If no subkey is given, we just want a root handle of the
  214. // remote machine. Otherwise we must open the subkey (and
  215. // close the handle if remote).
  216. //
  217. if ( szKeyName[0] == '\0' ) {
  218. //
  219. // The remote handle is what we want.
  220. //
  221. hSubKey = hKey;
  222. } else {
  223. //
  224. // We want a subkey.
  225. //
  226. fOkay = !( Status = RegOpenKeyEx( hKey,
  227. szKeyName,
  228. 0,
  229. Access,
  230. &hSubKey ));
  231. //
  232. // If a remote machine is specified, then hkey has
  233. // a remote handle and we must close it.
  234. //
  235. if ( szMachineName[0] != '\0' ) {
  236. RegCloseKey( hKey );
  237. }
  238. }
  239. if ( fOkay ) {
  240. //
  241. // Put the handle in the specified variable
  242. //
  243. LibraryHandleSTR[0] = '|';
  244. #if defined(_WIN64)
  245. _ui64toa( (DWORD_PTR)hSubKey, LibraryHandleSTR+1, 20 );
  246. #else
  247. _ultoa( (DWORD)hSubKey, LibraryHandleSTR+1, 10 );
  248. #endif
  249. DEBUGREGKEY( LibraryHandleSTR+1, "opened ", szKeyName ) ;
  250. }
  251. }
  252. if ( !fOkay ) {
  253. FUpdateRegLastError( Status, "OpenRegKey", szKeyName );
  254. }
  255. while ( !FAddSymbolValueToSymTab( szNewHandle, LibraryHandleSTR ) )
  256. {
  257. if ( !FHandleOOM( hwndFrame ) )
  258. {
  259. if ( fOkay )
  260. {
  261. RegCloseKey( hSubKey );
  262. Status = 0;
  263. fOkay = fFalse;
  264. }
  265. break ;
  266. }
  267. }
  268. return (cmo & cmoVital) ? fOkay : fTrue;
  269. }
  270. /*
  271. * FFlushRegKey
  272. *
  273. * Flushes a key in the registry
  274. *
  275. * Arguments:
  276. *
  277. */
  278. BOOL FFlushRegKey( SZ szHandle, CMO cmo )
  279. {
  280. BOOL fOkay;
  281. HKEY hKey;
  282. hKey = (HKEY)LongToHandle(atol( szHandle + 1 ));
  283. fOkay = !RegFlushKey( hKey );
  284. return (cmo & cmoVital) ? fOkay : fTrue;
  285. }
  286. /*
  287. * FCloseRegKey
  288. *
  289. * Close a key in the registry
  290. *
  291. * Arguments:
  292. *
  293. */
  294. BOOL FCloseRegKey( SZ szHandle, CMO cmo )
  295. {
  296. BOOL fOkay;
  297. HKEY hKey;
  298. LONG Status;
  299. if ( szHandle[0] != '|' )
  300. return fTrue;
  301. hKey = (HKEY)LongToHandle(atol( szHandle + 1 ));
  302. if ( hKey == NULL )
  303. return fTrue ;
  304. DEBUGREGKEY( szHandle+1, "closed ", NULL ) ;
  305. fOkay = !( Status = RegCloseKey( hKey ) );
  306. if ( !fOkay ) {
  307. FUpdateRegLastError( Status, "CloseRegKey", NULL );
  308. }
  309. return (cmo & cmoVital) ? fOkay : fTrue;
  310. }
  311. /*
  312. * FDeleteRegKey
  313. *
  314. * Deletes a key from the registry
  315. *
  316. * Arguments:
  317. *
  318. */
  319. BOOL FDeleteRegKey( SZ szHandle, SZ szKeyName, CMO cmo )
  320. {
  321. BOOL fOkay;
  322. HKEY hKey;
  323. LONG Status;
  324. hKey = (HKEY)LongToHandle(atol( szHandle + 1 ));
  325. fOkay = !( Status = RegDeleteKey( hKey, szKeyName ) );
  326. if ( !fOkay ) {
  327. FUpdateRegLastError( Status, "DeleteRegKey", NULL );
  328. }
  329. return (cmo & cmoVital) ? fOkay : fTrue;
  330. }
  331. /*
  332. * FDeleteRegTree
  333. *
  334. * Deletes a key and all its descentants from the registry
  335. *
  336. * Arguments:
  337. *
  338. */
  339. BOOL FDeleteRegTree( SZ szHandle, SZ szKeyName, CMO cmo )
  340. {
  341. BOOL fOkay;
  342. HKEY hKey;
  343. HKEY hSubKey;
  344. LONG Status;
  345. hKey = (HKEY)LongToHandle(atol( szHandle + 1 ));
  346. //
  347. // Open the key
  348. //
  349. fOkay = !( Status = RegOpenKeyEx( hKey,
  350. szKeyName,
  351. 0,
  352. KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
  353. &hSubKey ) );
  354. if ( !fOkay ) {
  355. FUpdateRegLastError( Status, "DeleteRegTree", szKeyName );
  356. } else {
  357. fOkay = FDeleteTree( hSubKey );
  358. }
  359. //
  360. // Now delete the key
  361. //
  362. if ( fOkay ) {
  363. fOkay = !( Status = RegCloseKey( hSubKey ) );
  364. if ( !fOkay ) {
  365. FUpdateRegLastError( Status, "DeleteRegTree", szKeyName );
  366. } else {
  367. fOkay = !RegDeleteKey( hKey, szKeyName );
  368. }
  369. }
  370. return (cmo & cmoVital) ? fOkay : fTrue;
  371. }
  372. /*
  373. * FDeleteTree
  374. *
  375. * Recursively deletes all the descendants of a key
  376. *
  377. * Arguments:
  378. *
  379. */
  380. BOOL FDeleteTree( HKEY KeyHandle )
  381. {
  382. BOOL fOkay;
  383. DWORD Index;
  384. HKEY ChildHandle;
  385. CHAR KeyName[ cchlFullPathMax ];
  386. DWORD KeyNameLength;
  387. CHAR ClassName[ cchlFullPathMax ];
  388. DWORD ClassNameLength;
  389. DWORD TitleIndex = 0 ;
  390. DWORD NumberOfSubKeys;
  391. DWORD MaxSubKeyLength;
  392. DWORD MaxClassLength;
  393. DWORD NumberOfValues;
  394. DWORD MaxValueNameLength;
  395. DWORD MaxValueDataLength;
  396. DWORD SizeSecurityDescriptor;
  397. FILETIME LastWriteTime;
  398. LONG Status;
  399. ClassNameLength = cchlFullPathMax;
  400. if ( Status = RegQueryInfoKey( KeyHandle,
  401. ClassName,
  402. &ClassNameLength,
  403. NULL,
  404. &NumberOfSubKeys,
  405. &MaxSubKeyLength,
  406. &MaxClassLength,
  407. &NumberOfValues,
  408. &MaxValueNameLength,
  409. &MaxValueDataLength,
  410. &SizeSecurityDescriptor,
  411. &LastWriteTime
  412. ) ) {
  413. FUpdateRegLastError( Status, "DeleteTree", NULL );
  414. return fFalse;
  415. }
  416. for ( Index = 0; Index < NumberOfSubKeys; Index++ ) {
  417. KeyNameLength = cchlFullPathMax;
  418. if ( Status = RegEnumKey( KeyHandle,
  419. 0,
  420. KeyName,
  421. KeyNameLength
  422. ) ) {
  423. FUpdateRegLastError( Status, "DeleteTree", NULL );
  424. return fFalse;
  425. }
  426. #ifdef BUGBUG
  427. // BUGBUG This should work when MAXIMUM_ALLOWED access works.
  428. if ( Status = RegOpenKey( KeyHandle,
  429. KeyName,
  430. &ChildHandle
  431. ) ) {
  432. FUpdateRegLastError( Status, "DeleteTree", NULL );
  433. return fFalse;
  434. }
  435. #else
  436. if ( Status = RegOpenKeyEx( KeyHandle,
  437. KeyName,
  438. 0,
  439. KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
  440. &ChildHandle
  441. ) ) {
  442. FUpdateRegLastError( Status, "DeleteTree", NULL );
  443. return fFalse;
  444. }
  445. #endif // ROBERTRE
  446. fOkay = FDeleteTree( ChildHandle );
  447. //
  448. // Whether DeleteTree of the ChildHandle succeeded or not, we'll
  449. // try to close it.
  450. //
  451. RegCloseKey( ChildHandle );
  452. if ( fOkay ) {
  453. if ( fOkay = !(Status = RegDeleteKey( KeyHandle, KeyName ) )) {
  454. FUpdateRegLastError( Status, "DeleteTree", NULL );
  455. }
  456. }
  457. if ( !fOkay ) {
  458. return fFalse;
  459. }
  460. }
  461. return fTrue;
  462. }
  463. /*
  464. * FEnumRegKey
  465. *
  466. * Obtains subkey enumeration
  467. *
  468. * Arguments:
  469. *
  470. */
  471. BOOL FEnumRegKey( SZ szHandle, SZ szInfVar, CMO cmo )
  472. {
  473. BOOL fOkay = fTrue;
  474. HKEY hKey;
  475. CHAR KeyName[ cbFullPathMax ];
  476. CHAR Class[ cbFullPathMax ];
  477. DWORD cbKeyName;
  478. DWORD cbClass;
  479. DWORD TitleIndex = 0 ;
  480. FILETIME FileTime;
  481. RGSZ rgszEnum;
  482. UINT EnumSize;
  483. RGSZ rgszKey;
  484. SZ szInfo;
  485. char szTitle[25];
  486. UINT Index;
  487. LONG Status;
  488. DWORD NumberOfSubKeys;
  489. DWORD MaxSubKeyLength;
  490. DWORD MaxClassLength;
  491. DWORD NumberOfValues;
  492. DWORD MaxValueNameLength;
  493. DWORD MaxValueDataLength;
  494. DWORD SizeSecurityDescriptor;
  495. FILETIME LastWriteTime;
  496. hKey = (HKEY)LongToHandle(atol( szHandle + 1 ));
  497. while ( (rgszEnum = (RGSZ)SAlloc( (CB)( 1 * sizeof(SZ)))) == NULL ) {
  498. if ( !FHandleOOM( hwndFrame ) ) {
  499. fOkay = fFalse;
  500. break;
  501. }
  502. }
  503. if ( fOkay ) {
  504. rgszEnum[0] = NULL;
  505. EnumSize = 0;
  506. cbClass = cbFullPathMax;
  507. if ( Status = RegQueryInfoKey( hKey,
  508. Class,
  509. &cbClass,
  510. NULL,
  511. &NumberOfSubKeys,
  512. &MaxSubKeyLength,
  513. &MaxClassLength,
  514. &NumberOfValues,
  515. &MaxValueNameLength,
  516. &MaxValueDataLength,
  517. &SizeSecurityDescriptor,
  518. &LastWriteTime
  519. ) ) {
  520. FUpdateRegLastError( Status, "EnumRegKey", NULL );
  521. return fFalse;
  522. }
  523. for ( Index = 0 ; Index < NumberOfSubKeys; Index++ ) {
  524. cbKeyName = cbFullPathMax;
  525. cbClass = cbFullPathMax;
  526. if ( Status = RegEnumKeyEx( hKey,
  527. Index,
  528. KeyName,
  529. &cbKeyName,
  530. NULL,
  531. (LPSTR)&Class,
  532. &cbClass,
  533. &FileTime ) ) {
  534. FUpdateRegLastError( Status, "EnumRegKey", NULL );
  535. break;
  536. }
  537. //
  538. // Get a list in which to put the key information.
  539. //
  540. while ( (rgszKey = (RGSZ)SAlloc( (CB)( 4 * sizeof(SZ)))) == NULL ) {
  541. if ( !FHandleOOM( hwndFrame ) ) {
  542. fOkay = fFalse;
  543. break;
  544. }
  545. }
  546. if ( fOkay ) {
  547. //
  548. // Put the information in the list
  549. //
  550. _ultoa( TitleIndex, szTitle, 10 );
  551. rgszKey[0] = KeyName;
  552. rgszKey[1] = szTitle;
  553. rgszKey[2] = Class;
  554. rgszKey[3] = NULL;
  555. //
  556. // Transform the list into a string so that it can be added to the
  557. // symbol table.
  558. //
  559. while ( (szInfo = SzListValueFromRgsz( rgszKey )) == (SZ)NULL ) {
  560. if ( !FHandleOOM( hwndFrame ) ) {
  561. fOkay = fFalse;
  562. break;
  563. }
  564. }
  565. if ( fOkay ) {
  566. while ( (rgszEnum = (RGSZ)SRealloc( rgszEnum,
  567. (CB)( (EnumSize+2) * sizeof(SZ)))
  568. ) == NULL ) {
  569. if ( !FHandleOOM( hwndFrame ) ) {
  570. fOkay = fFalse;
  571. break;
  572. }
  573. }
  574. if ( fOkay ) {
  575. rgszEnum[EnumSize] = szInfo;
  576. EnumSize++;
  577. rgszEnum[EnumSize] = NULL;
  578. }
  579. }
  580. SFree(rgszKey);
  581. }
  582. }
  583. //
  584. // Convert to SZ
  585. //
  586. while ( (szInfo = SzListValueFromRgsz( rgszEnum )) == (SZ)NULL ) {
  587. if ( !FHandleOOM( hwndFrame ) ) {
  588. fOkay = fFalse;
  589. break;
  590. }
  591. }
  592. if ( fOkay ) {
  593. //
  594. // Add it to the symbol table.
  595. //
  596. while ( !FAddSymbolValueToSymTab( szInfVar, szInfo ) ) {
  597. if ( !FHandleOOM( hwndFrame ) ) {
  598. fOkay = fFalse;
  599. break;
  600. }
  601. }
  602. SFree(szInfo);
  603. }
  604. FFreeRgsz( rgszEnum );
  605. }
  606. return (cmo & cmoVital) ? fOkay : fTrue;
  607. }
  608. /*
  609. * FSetRegValue
  610. *
  611. * Sets a value under the given key
  612. *
  613. * Arguments:
  614. *
  615. */
  616. BOOL FSetRegValue( SZ szHandle, SZ szValueName, UINT TitleIndex,
  617. UINT ValueType, SZ szValueData, CMO cmo )
  618. {
  619. BOOL fOkay;
  620. HKEY hKey;
  621. hKey = (HKEY)LongToHandle(atol( szHandle + 1 ));
  622. switch ( ValueType ) {
  623. case REG_MULTI_SZ:
  624. fOkay = FSetRegValueMultiSz( hKey, szValueName, TitleIndex, REG_MULTI_SZ, szValueData );
  625. break;
  626. case REG_SZ:
  627. fOkay = FSetRegValueSz( hKey, szValueName, TitleIndex, szValueData );
  628. break;
  629. case REG_EXPAND_SZ:
  630. fOkay = FSetRegValueExpandSz( hKey, szValueName, TitleIndex, szValueData );
  631. break;
  632. case REG_DWORD:
  633. fOkay = FSetRegValueDword( hKey, szValueName, TitleIndex, szValueData );
  634. break;
  635. case REG_BINARY:
  636. fOkay = FSetRegValueBin( hKey, szValueName, TitleIndex, REG_BINARY, szValueData );
  637. break;
  638. case REG_RESOURCE_LIST:
  639. fOkay = FSetRegValueBin( hKey, szValueName, TitleIndex, REG_RESOURCE_LIST, szValueData );
  640. break;
  641. case REG_FULL_RESOURCE_DESCRIPTOR:
  642. fOkay = FSetRegValueBin( hKey, szValueName, TitleIndex, REG_FULL_RESOURCE_DESCRIPTOR, szValueData );
  643. break;
  644. case REG_RESOURCE_REQUIREMENTS_LIST:
  645. fOkay = FSetRegValueBin( hKey, szValueName, TitleIndex, REG_RESOURCE_REQUIREMENTS_LIST, szValueData );
  646. break;
  647. default:
  648. fOkay = FSetRegValueBin( hKey, szValueName, TitleIndex, ValueType, szValueData );
  649. break;
  650. }
  651. return (cmo & cmoVital) ? fOkay : fTrue;
  652. }
  653. /*
  654. * FGetRegValue
  655. *
  656. * Gets the specified value under the given key
  657. *
  658. * Arguments:
  659. *
  660. */
  661. BOOL FGetRegValue( SZ szHandle, SZ szValueName, SZ szInfVar, CMO cmo )
  662. {
  663. BOOL fOkay;
  664. HKEY hKey;
  665. DWORD cbData;
  666. DWORD TitleIndex = 0 ;
  667. DWORD ValueType;
  668. PVOID ValueData;
  669. SZ szValueData;
  670. RGSZ rgszValue;
  671. SZ szInfo;
  672. LONG Status;
  673. char szTitle[25];
  674. char szValueType[25];
  675. char szKClass[ MAX_PATH ];
  676. DWORD cbKClass;
  677. DWORD KTitleIndex = 0 ;
  678. DWORD KSubKeys;
  679. DWORD cbKMaxSubKeyLen;
  680. DWORD cbKMaxClassLen;
  681. DWORD KValues;
  682. DWORD cbKMaxValueNameLen;
  683. DWORD SizeSecurityDescriptor;
  684. FILETIME KLastWriteTime;
  685. hKey = (HKEY)LongToHandle(atol( szHandle + 1 ));
  686. //
  687. // Get the size of the buffer needed
  688. //
  689. cbKClass = MAX_PATH;
  690. fOkay = !( Status = RegQueryInfoKey ( hKey,
  691. szKClass,
  692. &cbKClass,
  693. NULL,
  694. &KSubKeys,
  695. &cbKMaxSubKeyLen,
  696. &cbKMaxClassLen,
  697. &KValues,
  698. &cbKMaxValueNameLen,
  699. &cbData,
  700. &SizeSecurityDescriptor,
  701. &KLastWriteTime ) );
  702. //cbData = 0;
  703. //fOkay = !RegQueryValueEx( hKey,
  704. // szValueName,
  705. // NULL,
  706. // NULL,
  707. // NULL,
  708. // &cbData );
  709. if ( !fOkay ) {
  710. FUpdateRegLastError( Status, "GetRegValue", szValueName );
  711. } else {
  712. //
  713. // Allocate the buffer and get the data
  714. //
  715. while ( (ValueData = (PVOID)SAlloc( (CB)( cbData ))) == NULL ) {
  716. if ( !FHandleOOM( hwndFrame ) ) {
  717. fOkay = fFalse;
  718. break;
  719. }
  720. }
  721. if ( fOkay ) {
  722. fOkay = !( Status = RegQueryValueEx( hKey,
  723. szValueName,
  724. NULL,
  725. &ValueType,
  726. ValueData,
  727. &cbData ) );
  728. if ( !fOkay ) {
  729. FUpdateRegLastError( Status, "GetRegValue", szValueName );
  730. } else {
  731. //
  732. // Get a list in which to put the key information.
  733. //
  734. while ( (rgszValue = (RGSZ)SAlloc( (CB)( 5 * sizeof(SZ)))) == NULL ) {
  735. if ( !FHandleOOM( hwndFrame ) ) {
  736. fOkay = fFalse;
  737. break;
  738. }
  739. }
  740. if ( fOkay ) {
  741. //
  742. // Put the information in the list
  743. //
  744. if ( (fOkay = (szValueData = ValueDataToSz( ValueType, ValueData, cbData)) != NULL) ) {
  745. _ultoa( TitleIndex, szTitle, 10 );
  746. _ultoa( ValueType, szValueType, 10 );
  747. rgszValue[0] = szValueName;
  748. rgszValue[1] = szTitle;
  749. rgszValue[2] = szValueType;
  750. rgszValue[3] = szValueData;
  751. rgszValue[4] = NULL;
  752. //
  753. // Transform the list into a string so that it can be added to the
  754. // symbol table.
  755. //
  756. while ( (szInfo = SzListValueFromRgsz( rgszValue )) == (SZ)NULL ) {
  757. if ( !FHandleOOM( hwndFrame ) ) {
  758. fOkay = fFalse;
  759. break;
  760. }
  761. }
  762. if ( fOkay ) {
  763. //
  764. // Add it to the symbol table.
  765. //
  766. while ( !FAddSymbolValueToSymTab( szInfVar, szInfo ) ) {
  767. if ( !FHandleOOM( hwndFrame ) ) {
  768. fOkay = fFalse;
  769. break;
  770. }
  771. }
  772. SFree(szInfo);
  773. }
  774. SFree( szValueData );
  775. }
  776. SFree( rgszValue );
  777. }
  778. }
  779. SFree( ValueData );
  780. }
  781. }
  782. return (cmo & cmoVital) ? fOkay : fTrue;
  783. }
  784. /*
  785. * FDeleteRegValue
  786. *
  787. * Deletes a value under the given key
  788. *
  789. * Arguments:
  790. *
  791. */
  792. BOOL FDeleteRegValue( SZ szHandle, SZ szValueName, CMO cmo )
  793. {
  794. BOOL fOkay;
  795. HKEY hKey;
  796. LONG Status;
  797. hKey = (HKEY)LongToHandle(atol( szHandle + 1 ));
  798. fOkay = !( Status = RegDeleteValue( hKey, szValueName ) );
  799. if ( !fOkay ) {
  800. FUpdateRegLastError( Status, "DeleteRegValue", szValueName );
  801. }
  802. return (cmo & cmoVital) ? fOkay : fTrue;
  803. }
  804. /*
  805. * FEnumRegValue
  806. *
  807. * Obtains information for a value with a certain index.
  808. *
  809. * Arguments:
  810. *
  811. */
  812. BOOL FEnumRegValue( SZ szHandle, SZ szInfVar, CMO cmo )
  813. {
  814. BOOL fOkay;
  815. HKEY hKey;
  816. DWORD cbData;
  817. DWORD cbName;
  818. DWORD TitleIndex = 0 ;
  819. DWORD ValueType;
  820. PVOID ValueData;
  821. SZ szValueData;
  822. DWORD cbValueData;
  823. RGSZ rgszValue;
  824. RGSZ rgszEnum;
  825. UINT EnumSize;
  826. SZ szInfo;
  827. SZ szValueName;
  828. DWORD cbValueName;
  829. UINT Index;
  830. LONG Status;
  831. char szTitle[25];
  832. char szValueType[25];
  833. char szKClass[ cchlFullPathMax ];
  834. DWORD cbKClass;
  835. DWORD KTitleIndex = 0 ;
  836. DWORD KSubKeys;
  837. DWORD cbKMaxSubKeyLen;
  838. DWORD cbKMaxClassLen;
  839. DWORD SizeSecurityDescriptor;
  840. DWORD KValues;
  841. FILETIME KLastWriteTime;
  842. hKey = (HKEY)LongToHandle(atol( szHandle + 1 ));
  843. //
  844. // Get the size of the buffer needed
  845. //
  846. cbKClass = MAX_PATH;
  847. fOkay = !( Status = RegQueryInfoKey ( hKey,
  848. szKClass,
  849. &cbKClass,
  850. NULL,
  851. &KSubKeys,
  852. &cbKMaxSubKeyLen,
  853. &cbKMaxClassLen,
  854. &KValues,
  855. &cbName,
  856. &cbData,
  857. &SizeSecurityDescriptor,
  858. &KLastWriteTime ) );
  859. if ( !fOkay ) {
  860. FUpdateRegLastError( Status, "EnumRegValue", NULL );
  861. } else {
  862. //
  863. // Allocate the buffer to get the data.
  864. //
  865. while ( (ValueData = (PVOID)SAlloc( (CB)( cbData ))) == NULL ) {
  866. if ( !FHandleOOM( hwndFrame ) ) {
  867. fOkay = fFalse;
  868. break;
  869. }
  870. }
  871. if ( fOkay ) {
  872. //
  873. // Allocate a buffer to get the name. Allow for the string terminator.
  874. //
  875. while ( (szValueName = (SZ)SAlloc( (CB)( ( ++cbName ) * sizeof( TCHAR ) ))) == NULL ) {
  876. if ( !FHandleOOM( hwndFrame ) ) {
  877. fOkay = fFalse;
  878. break;
  879. }
  880. }
  881. if ( fOkay ) {
  882. //
  883. // Allocate empty enum list.
  884. //
  885. while ( (rgszEnum = (RGSZ)SAlloc( (CB)( 1 * sizeof(SZ)))) == NULL ) {
  886. if ( !FHandleOOM( hwndFrame ) ) {
  887. fOkay = fFalse;
  888. break;
  889. }
  890. }
  891. if ( fOkay ) {
  892. rgszEnum[0] = NULL;
  893. EnumSize = 0;
  894. for ( Index = 0 ; ; Index++ ) {
  895. cbValueName = cbName;
  896. cbValueData = cbData;
  897. if ( Status = RegEnumValue( hKey,
  898. Index,
  899. szValueName,
  900. &cbValueName,
  901. NULL,
  902. &ValueType,
  903. ValueData,
  904. &cbValueData ) ) {
  905. FUpdateRegLastError( Status, "EnumRegValue", NULL );
  906. break;
  907. }
  908. //
  909. // Get a list in which to put the key information.
  910. //
  911. while ( (rgszValue = (RGSZ)SAlloc( (CB)( 5 * sizeof(SZ)))) == NULL ) {
  912. if ( !FHandleOOM( hwndFrame ) ) {
  913. fOkay = fFalse;
  914. break;
  915. }
  916. }
  917. if ( fOkay ) {
  918. //
  919. // Put the information in the list
  920. //
  921. if ( (fOkay = (szValueData = ValueDataToSz( ValueType, ValueData, cbValueData)) != NULL) ) {
  922. _ultoa( TitleIndex, szTitle, 10 );
  923. _ultoa( ValueType, szValueType, 10 );
  924. rgszValue[0] = szValueName;
  925. rgszValue[1] = szTitle;
  926. rgszValue[2] = szValueType;
  927. rgszValue[3] = szValueData;
  928. rgszValue[4] = NULL;
  929. //
  930. // Transform the list into a string so that it can be added to the
  931. // symbol table.
  932. //
  933. while ( (szInfo = SzListValueFromRgsz( rgszValue )) == (SZ)NULL ) {
  934. if ( !FHandleOOM( hwndFrame ) ) {
  935. fOkay = fFalse;
  936. break;
  937. }
  938. }
  939. if ( fOkay ) {
  940. while ( (rgszEnum = (RGSZ)SRealloc( rgszEnum,
  941. (CB)( (EnumSize+2) * sizeof(SZ)))
  942. ) == NULL ) {
  943. if ( !FHandleOOM( hwndFrame ) ) {
  944. fOkay = fFalse;
  945. break;
  946. }
  947. }
  948. if ( fOkay ) {
  949. rgszEnum[EnumSize] = szInfo;
  950. EnumSize++;
  951. rgszEnum[EnumSize] = NULL;
  952. }
  953. }
  954. SFree( szValueData );
  955. }
  956. SFree( rgszValue );
  957. }
  958. }
  959. //
  960. // Convert to SZ
  961. //
  962. while ( (szInfo = SzListValueFromRgsz( rgszEnum )) == (SZ)NULL ) {
  963. if ( !FHandleOOM( hwndFrame ) ) {
  964. fOkay = fFalse;
  965. break;
  966. }
  967. }
  968. if ( fOkay ) {
  969. //
  970. // Add it to the symbol table.
  971. //
  972. while ( !FAddSymbolValueToSymTab( szInfVar, szInfo ) ) {
  973. if ( !FHandleOOM( hwndFrame ) ) {
  974. fOkay = fFalse;
  975. break;
  976. }
  977. }
  978. SFree( szInfo );
  979. }
  980. FFreeRgsz( rgszEnum );
  981. }
  982. SFree( szValueName );
  983. }
  984. SFree( ValueData );
  985. }
  986. }
  987. return (cmo & cmoVital) ? fOkay : fTrue;
  988. }
  989. /*
  990. * FSetRegValueSz
  991. *
  992. * Sets a value under the given key for SZ type
  993. *
  994. * Arguments:
  995. *
  996. */
  997. BOOL FSetRegValueSz( HKEY hKey, SZ szValueName, UINT TitleIndex, SZ szValueData )
  998. {
  999. LONG Status;
  1000. Status = RegSetValueEx( hKey,
  1001. szValueName,
  1002. 0,
  1003. REG_SZ,
  1004. szValueData,
  1005. lstrlen( szValueData ) + 1 );
  1006. if ( Status ) {
  1007. FUpdateRegLastError( Status,"SetRegValueSz", szValueName );
  1008. }
  1009. return !Status;
  1010. }
  1011. /*
  1012. * FSetRegValueExpandSz
  1013. *
  1014. * Sets a value under the given key for expand SZ type
  1015. *
  1016. * Arguments:
  1017. *
  1018. */
  1019. BOOL
  1020. FSetRegValueExpandSz(
  1021. HKEY hKey,
  1022. SZ szValueName,
  1023. UINT TitleIndex,
  1024. SZ szValueData
  1025. )
  1026. {
  1027. LONG Status;
  1028. Status = RegSetValueEx( hKey,
  1029. szValueName,
  1030. 0,
  1031. REG_EXPAND_SZ,
  1032. szValueData,
  1033. lstrlen( szValueData ) + 1 );
  1034. if ( Status ) {
  1035. FUpdateRegLastError( Status,"SetRegValueExpandSz", szValueName );
  1036. }
  1037. return !Status;
  1038. }
  1039. /*
  1040. * FSetRegValueMultiSz
  1041. *
  1042. * Sets a value under the given key for REG_MULTI_SZ type
  1043. *
  1044. * Arguments:
  1045. *
  1046. */
  1047. BOOL
  1048. FSetRegValueMultiSz(
  1049. HKEY hKey,
  1050. SZ szValueName,
  1051. UINT TitleIndex,
  1052. UINT ValueType,
  1053. SZ szValueData
  1054. )
  1055. {
  1056. BOOL fOkay = fFalse;
  1057. PVOID Data;
  1058. DWORD cbData;
  1059. LONG Status;
  1060. Data = SzToMultiSz( szValueData, &cbData );
  1061. fOkay = !( Status = RegSetValueEx( hKey,
  1062. szValueName,
  1063. 0,
  1064. ValueType,
  1065. Data,
  1066. cbData ) );
  1067. if ( !fOkay ) {
  1068. FUpdateRegLastError( Status,"SetRegValueMultiSz", szValueName );
  1069. }
  1070. if ( Data ) {
  1071. SFree( Data );
  1072. }
  1073. return fOkay;
  1074. }
  1075. /*
  1076. * FSetRegValueDword
  1077. *
  1078. * Sets a value under the given key for DWORD type
  1079. *
  1080. * Arguments:
  1081. *
  1082. */
  1083. BOOL FSetRegValueDword( HKEY hKey, SZ szValueName, UINT TitleIndex, SZ szValueData )
  1084. {
  1085. DWORD Data;
  1086. LONG Status;
  1087. Data = (DWORD)atol(szValueData );
  1088. Status = RegSetValueEx( hKey,
  1089. szValueName,
  1090. 0,
  1091. REG_DWORD,
  1092. (LPBYTE)&Data,
  1093. sizeof( DWORD ) );
  1094. if ( Status ) {
  1095. FUpdateRegLastError( Status,"SetRegValueDword", szValueName );
  1096. }
  1097. return !Status;
  1098. }
  1099. /*
  1100. * FSetRegValueBin
  1101. *
  1102. * Sets a value under the given key for BINARY and unknown types
  1103. *
  1104. * Arguments:
  1105. *
  1106. */
  1107. BOOL FSetRegValueBin( HKEY hKey, SZ szValueName, UINT TitleIndex,
  1108. UINT ValueType, SZ szValueData )
  1109. {
  1110. BOOL fOkay = fFalse;
  1111. PVOID Data;
  1112. DWORD cbData;
  1113. LONG Status;
  1114. Data = SzToBin( szValueData, &cbData );
  1115. fOkay = !( Status = RegSetValueEx( hKey,
  1116. szValueName,
  1117. 0,
  1118. ValueType,
  1119. Data,
  1120. cbData ) );
  1121. if ( !fOkay ) {
  1122. switch( ValueType ) {
  1123. case REG_BINARY:
  1124. FUpdateRegLastError( Status,"SetRegValueBin", szValueName );
  1125. break;
  1126. case REG_RESOURCE_LIST:
  1127. FUpdateRegLastError( Status,"SetRegValueResourceList", szValueName );
  1128. break;
  1129. case REG_FULL_RESOURCE_DESCRIPTOR:
  1130. FUpdateRegLastError( Status,"SetRegValueFullResourceDescriptor", szValueName );
  1131. break;
  1132. case REG_RESOURCE_REQUIREMENTS_LIST:
  1133. FUpdateRegLastError( Status,"SetRegValueResourceRequirementsList", szValueName );
  1134. break;
  1135. default:
  1136. FUpdateRegLastError( Status,"SetRegValueUnknownType", szValueName );
  1137. break;
  1138. }
  1139. }
  1140. if ( Data ) {
  1141. SFree( Data );
  1142. }
  1143. return fOkay;
  1144. }
  1145. /*
  1146. * SzToMultiSz
  1147. *
  1148. * Converts a list of sz strings to a single multi sz string
  1149. *
  1150. * Arguments:
  1151. *
  1152. */
  1153. PVOID SzToMultiSz( SZ sz, PDWORD cbData )
  1154. {
  1155. RGSZ rgsz;
  1156. SZ p = NULL, q;
  1157. int i, j;
  1158. *cbData = 0;
  1159. if ( FListValue( sz )) {
  1160. if ( rgsz = RgszFromSzListValue( sz )) {
  1161. //
  1162. // Get size of required buffer
  1163. //
  1164. for (i = 0, j = 0; rgsz[i] != NULL; i++ ) {
  1165. j = j + strlen( rgsz[i] ) + 1;
  1166. }
  1167. j = j + 1; // for the last null
  1168. //
  1169. // Allocate buffer
  1170. //
  1171. while ( (p = q = (SZ)SAlloc( (CB)( j * sizeof( CHAR )))) == NULL ) {
  1172. if ( !FHandleOOM( hwndFrame ) ) {
  1173. break;
  1174. }
  1175. }
  1176. if ( p ) {
  1177. for ( i=0; rgsz[i] != NULL; i++ ) {
  1178. lstrcpy( q, rgsz[ i ] );
  1179. q = q + lstrlen( rgsz[ i ] ) + 1;
  1180. }
  1181. *q = '\0';
  1182. *cbData = j * sizeof( CHAR );
  1183. }
  1184. FFreeRgsz( rgsz );
  1185. }
  1186. }
  1187. return (PVOID)p;
  1188. }
  1189. /*
  1190. * MultiSzToSz
  1191. *
  1192. * Converts a block of memory to a list containing hex digits
  1193. *
  1194. * Arguments:
  1195. *
  1196. */
  1197. SZ MultiSzToSz( PVOID Data, DWORD cbData )
  1198. {
  1199. RGSZ rgsz;
  1200. SZ sz = NULL, szData, szEnd;
  1201. DWORD i, cbList = 0;
  1202. //
  1203. // Count the number of list elements in the multi sz list. We do this
  1204. // by counting the number of '0's in the string and subtracting 1 from
  1205. // this
  1206. //
  1207. szData = (SZ)( Data );
  1208. szEnd = (SZ)( (PBYTE)Data + cbData );
  1209. while( szData < szEnd ) {
  1210. if (*szData++ == '\0') {
  1211. cbList++;
  1212. }
  1213. }
  1214. if( cbList > 0 ) {
  1215. cbList--; // remove the terminating null
  1216. //
  1217. // Allocate a rgsz list with cbList elements;
  1218. //
  1219. while ( (rgsz = (RGSZ)SAlloc( (CB)( (cbList + 1) * sizeof(SZ)))) == NULL ) {
  1220. if ( !FHandleOOM( hwndFrame ) ) {
  1221. break;
  1222. }
  1223. }
  1224. if( rgsz ) {
  1225. //
  1226. // Go through the szList and fill the rgsz structure
  1227. //
  1228. szData = (SZ)( Data );
  1229. for ( i = 0; i < cbList; i++ ) {
  1230. rgsz[i] = SzDupl( szData );
  1231. szData = szData + lstrlen( szData ) + 1;
  1232. }
  1233. rgsz[cbList] = NULL;
  1234. //
  1235. // Transform the list into a string.
  1236. //
  1237. while ( (sz = SzListValueFromRgsz( rgsz )) == (SZ)NULL ) {
  1238. if ( !FHandleOOM( hwndFrame ) ) {
  1239. break;
  1240. }
  1241. }
  1242. EvalAssert( FFreeRgsz( rgsz ) );
  1243. }
  1244. }
  1245. return( sz );
  1246. }
  1247. /*
  1248. * SzToBin
  1249. *
  1250. * Converts a list of hex digits to binary
  1251. *
  1252. * Arguments:
  1253. *
  1254. */
  1255. PVOID SzToBin( SZ sz, PDWORD cbData )
  1256. {
  1257. RGSZ rgsz;
  1258. PBYTE p, q = NULL;
  1259. int i;
  1260. *cbData = 0;
  1261. if ( FListValue( sz )) {
  1262. if ( rgsz = RgszFromSzListValue( sz )) {
  1263. //
  1264. // Get size of required buffer
  1265. //
  1266. for (i=0; rgsz[i] != NULL; i++ );
  1267. //
  1268. // Allocate buffer
  1269. //
  1270. while ( (p = q = (PBYTE)SAlloc( (CB)( i ))) == NULL ) {
  1271. if ( !FHandleOOM( hwndFrame ) ) {
  1272. break;
  1273. }
  1274. }
  1275. if ( p ) {
  1276. for ( i=0; rgsz[i] != NULL; i++ ) {
  1277. *p++ = (BYTE)atoi( rgsz[i] );
  1278. }
  1279. *cbData = i;
  1280. }
  1281. FFreeRgsz( rgsz );
  1282. }
  1283. }
  1284. return q;
  1285. }
  1286. /*
  1287. * BinToSz
  1288. *
  1289. * Converts a block of memory to a list containing hex digits
  1290. *
  1291. * Arguments:
  1292. *
  1293. */
  1294. SZ BinToSz( PVOID Data, DWORD cbData )
  1295. {
  1296. RGSZ rgsz;
  1297. SZ sz = NULL;
  1298. SZ szElement;
  1299. DWORD i;
  1300. PBYTE pbData;
  1301. //
  1302. // The list will contain cbData elements
  1303. //
  1304. while ( (rgsz = (RGSZ)SAlloc( (CB)( (cbData+1) * sizeof(SZ)))) == NULL ) {
  1305. if ( !FHandleOOM( hwndFrame ) ) {
  1306. break;
  1307. }
  1308. }
  1309. if ( rgsz ) {
  1310. //
  1311. // For each element of the list, allocate a buffer and convert it
  1312. // to a string
  1313. //
  1314. pbData = (PBYTE)Data;
  1315. for (i=0; i<cbData; i++ ) {
  1316. while ( (szElement = (SZ)SAlloc( (CB)( 25 ))) == NULL ) {
  1317. if ( !FHandleOOM( hwndFrame ) ) {
  1318. break;
  1319. }
  1320. }
  1321. if ( szElement ) {
  1322. _ultoa( *(pbData + i), szElement, 10 );
  1323. rgsz[i] = szElement;
  1324. } else {
  1325. rgsz[i] = NULL;
  1326. break;
  1327. }
  1328. }
  1329. if ( i == cbData ) {
  1330. rgsz[i] = NULL;
  1331. //
  1332. // Transform the list into a string.
  1333. //
  1334. while ( (sz = SzListValueFromRgsz( rgsz )) == (SZ)NULL ) {
  1335. if ( !FHandleOOM( hwndFrame ) ) {
  1336. break;
  1337. }
  1338. }
  1339. }
  1340. FFreeRgsz( rgsz );
  1341. }
  1342. return sz;
  1343. }
  1344. /*
  1345. * ValueDataToSz
  1346. *
  1347. * Converts a value data to its string form
  1348. *
  1349. * Arguments:
  1350. *
  1351. */
  1352. SZ ValueDataToSz( DWORD ValueType, PVOID ValueData, DWORD cbData )
  1353. {
  1354. SZ sz = NULL;
  1355. switch ( ValueType ) {
  1356. case REG_SZ:
  1357. sz = SzDupl((SZ)ValueData);
  1358. break;
  1359. case REG_EXPAND_SZ:
  1360. sz = SzDupl((SZ)ValueData);
  1361. break;
  1362. case REG_DWORD:
  1363. while ( (sz = (SZ)SAlloc( (CB)( 25 ))) == NULL ) {
  1364. if ( !FHandleOOM( hwndFrame ) ) {
  1365. break;
  1366. }
  1367. }
  1368. if ( sz ) {
  1369. _ultoa( *(PDWORD)ValueData, sz, 10 );
  1370. }
  1371. break;
  1372. case REG_MULTI_SZ:
  1373. sz = MultiSzToSz( ValueData, cbData );
  1374. break;
  1375. case REG_BINARY:
  1376. default:
  1377. sz = BinToSz( ValueData, cbData );
  1378. break;
  1379. }
  1380. return sz;
  1381. }
  1382. RGSZ
  1383. MultiSzToRgsz(
  1384. IN PVOID MultiSz
  1385. )
  1386. {
  1387. PCHAR p;
  1388. ULONG Count;
  1389. RGSZ rgsz;
  1390. //
  1391. // First count the number of strings in the the multisz.
  1392. //
  1393. Count = 0;
  1394. p = MultiSz;
  1395. while(*p) {
  1396. Count++;
  1397. p = strchr(p,'\0') + 1;
  1398. }
  1399. //
  1400. // Allocate the rgsz.
  1401. //
  1402. rgsz = (RGSZ)SAlloc((Count + 1) * sizeof(PCHAR));
  1403. if(rgsz == NULL) {
  1404. return(NULL);
  1405. }
  1406. memset(rgsz,0,(Count + 1) * sizeof(PCHAR));
  1407. //
  1408. // Now place the strings in the rgsz.
  1409. //
  1410. p = MultiSz;
  1411. Count = 0;
  1412. while(*p) {
  1413. if(rgsz[Count++] = SzDupl((SZ)p)) {
  1414. p = strchr(p,'\0') + 1;
  1415. } else {
  1416. FFreeRgsz(rgsz);
  1417. return(NULL);
  1418. }
  1419. }
  1420. return(rgsz);
  1421. }
  1422. PCHAR
  1423. RgszToMultiSz(
  1424. IN RGSZ rgsz
  1425. )
  1426. {
  1427. ULONG Size;
  1428. ULONG Str;
  1429. PCHAR MultiSz;
  1430. //
  1431. // First determine the size of the block to hold the multisz.
  1432. //
  1433. Size = 0;
  1434. Str = 0;
  1435. while(rgsz[Str]) {
  1436. Size += strlen(rgsz[Str++]) + 1;
  1437. }
  1438. Size++; // for extra NUL to terminate the multisz.
  1439. MultiSz = SAlloc(Size);
  1440. if(MultiSz == NULL) {
  1441. return(NULL);
  1442. }
  1443. Str = 0;
  1444. Size = 0;
  1445. while(rgsz[Str]) {
  1446. lstrcpy(MultiSz + Size, rgsz[Str]);
  1447. Size += lstrlen(rgsz[Str++]) + 1;
  1448. }
  1449. MultiSz[Size] = 0;
  1450. return(MultiSz);
  1451. }