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.

2598 lines
76 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. regvalue.cpp
  5. Abstract:
  6. Routines to read/write/configure registry value settings
  7. The following modules have links to registry values
  8. scejet.c <SceJetAddSection>
  9. inftojet.c <SceConvertpInfKeyValue>
  10. pfget.c <ScepGetRegistryValues>
  11. config.c <ScepConfigureRegistryValues>
  12. analyze.c <ScepAnalyzeRegistryValues>
  13. Author:
  14. Jin Huang (jinhuang) 07-Jan-1998
  15. Revision History:
  16. --*/
  17. #include "headers.h"
  18. #include "serverp.h"
  19. #include "regvalue.h"
  20. #include "pfp.h"
  21. DWORD
  22. ScepUnescapeAndAddCRLF(
  23. IN PWSTR pszSource,
  24. IN OUT PWSTR pszDest
  25. );
  26. DWORD
  27. ScepEscapeAndRemoveCRLF(
  28. IN const PWSTR pszSource,
  29. IN const DWORD dwSourceSize,
  30. IN OUT PWSTR pszDest
  31. );
  32. SCESTATUS
  33. ScepSaveRegistryValueToBuffer(
  34. IN DWORD RegType,
  35. IN PWSTR Value,
  36. IN DWORD dwBytes,
  37. IN OUT PSCE_REGISTRY_VALUE_INFO pRegValues
  38. );
  39. SCESTATUS
  40. ScepEnumAllRegValues(
  41. IN OUT PDWORD pCount,
  42. IN OUT PSCE_REGISTRY_VALUE_INFO *paRegValues
  43. );
  44. DWORD
  45. ScepAnalyzeOneRegistryValueNoValidate(
  46. IN HKEY hKey,
  47. IN PWSTR ValueName,
  48. IN PSCESECTION hSection OPTIONAL,
  49. IN DWORD dwAnalFlag,
  50. IN OUT PSCE_REGISTRY_VALUE_INFO pOneRegValue
  51. );
  52. extern "C" {
  53. VOID
  54. pSetupGetRealSystemTime(
  55. OUT LPSYSTEMTIME RealSystemTime
  56. );
  57. }
  58. SCESTATUS
  59. ScepGetRegistryValues(
  60. IN PSCECONTEXT hProfile,
  61. IN SCETYPE ProfileType,
  62. OUT PSCE_REGISTRY_VALUE_INFO * ppRegValues,
  63. OUT LPDWORD pValueCount,
  64. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  65. )
  66. /*++
  67. Routine Description:
  68. This routine retrieves registry values to secure from the Jet database
  69. and stores in the output buffer ppRegValues
  70. Arguments:
  71. hProfile - The profile handle context
  72. ppRegValues - the output array of registry values.
  73. pValueCount - the buffer to hold number of elements in the array
  74. Errlog - A buffer to hold all error codes/text encountered when
  75. parsing the INF file. If Errlog is NULL, no further error
  76. information is returned except the return DWORD
  77. Return value:
  78. SCESTATUS - SCESTATUS_SUCCESS
  79. SCESTATUS_NOT_ENOUGH_RESOURCE
  80. SCESTATUS_INVALID_PARAMETER
  81. SCESTATUS_BAD_FORMAT
  82. SCESTATUS_INVALID_DATA
  83. --*/
  84. {
  85. if ( !hProfile || !ppRegValues || !pValueCount ) {
  86. return(SCESTATUS_INVALID_PARAMETER);
  87. }
  88. SCESTATUS rc;
  89. PSCESECTION hSection=NULL;
  90. LPTSTR KeyName=NULL;
  91. DWORD KeyLen;
  92. DWORD i,j;
  93. LPTSTR ValueStr=NULL;
  94. LPTSTR Value=NULL;
  95. DWORD ValueLen;
  96. LONG dType;
  97. DWORD Status;
  98. DWORD dCount;
  99. rc = ScepOpenSectionForName(
  100. hProfile,
  101. (ProfileType==SCE_ENGINE_GPO) ? SCE_ENGINE_SCP : ProfileType,
  102. szRegistryValues,
  103. &hSection
  104. );
  105. if ( SCESTATUS_SUCCESS != rc ) {
  106. ScepBuildErrorLogInfo( ERROR_INVALID_DATA,
  107. Errlog, SCEERR_OPEN,
  108. szRegistryValues
  109. );
  110. return(rc);
  111. }
  112. //
  113. // get total number of values in this section
  114. //
  115. *ppRegValues = NULL;
  116. rc = SceJetGetLineCount(
  117. hSection,
  118. NULL,
  119. FALSE,
  120. pValueCount
  121. );
  122. if ( SCESTATUS_SUCCESS == rc && *pValueCount > 0 ) {
  123. //
  124. // allocate memory for all objects
  125. //
  126. *ppRegValues = (PSCE_REGISTRY_VALUE_INFO)ScepAlloc( LMEM_ZEROINIT,
  127. *pValueCount*sizeof(SCE_REGISTRY_VALUE_INFO) );
  128. if ( *ppRegValues ) {
  129. //
  130. // goto the first line of this section
  131. //
  132. rc = SceJetGetValue(
  133. hSection,
  134. SCEJET_PREFIX_MATCH,
  135. NULL,
  136. NULL,
  137. 0,
  138. &KeyLen,
  139. NULL,
  140. 0,
  141. &ValueLen
  142. );
  143. i=0;
  144. JET_COLUMNID ColGpoID = 0;
  145. JET_ERR JetErr;
  146. LONG GpoID=0;
  147. DWORD Actual;
  148. if ( ProfileType == SCE_ENGINE_GPO ) {
  149. JET_COLUMNDEF ColumnGpoIDDef;
  150. JetErr = JetGetTableColumnInfo(
  151. hSection->JetSessionID,
  152. hSection->JetTableID,
  153. "GpoID",
  154. (VOID *)&ColumnGpoIDDef,
  155. sizeof(JET_COLUMNDEF),
  156. JET_ColInfo
  157. );
  158. if ( JET_errSuccess == JetErr ) {
  159. ColGpoID = ColumnGpoIDDef.columnid;
  160. }
  161. }
  162. //
  163. // this count is for SCE_ENGINE_GPO type
  164. //
  165. dCount=0;
  166. while ( rc == SCESTATUS_SUCCESS ||
  167. rc == SCESTATUS_BUFFER_TOO_SMALL ) {
  168. //
  169. // Get string key and a int value.
  170. //
  171. if ( i >= *pValueCount ) {
  172. //
  173. // more lines than allocated
  174. //
  175. rc = SCESTATUS_INVALID_DATA;
  176. ScepBuildErrorLogInfo(ERROR_INVALID_DATA,
  177. Errlog,
  178. SCEERR_MORE_OBJECTS,
  179. *pValueCount
  180. );
  181. break;
  182. }
  183. GpoID = 1;
  184. if ( ProfileType == SCE_ENGINE_GPO ) {
  185. GpoID = 0;
  186. if ( ColGpoID > 0 ) {
  187. //
  188. // query if the setting comes from a GPO
  189. // get GPO ID field from the current line
  190. //
  191. JetErr = JetRetrieveColumn(
  192. hSection->JetSessionID,
  193. hSection->JetTableID,
  194. ColGpoID,
  195. (void *)&GpoID,
  196. 4,
  197. &Actual,
  198. 0,
  199. NULL
  200. );
  201. }
  202. }
  203. if ( GpoID <= 0 ) {
  204. //
  205. // read next line
  206. //
  207. rc = SceJetGetValue(
  208. hSection,
  209. SCEJET_NEXT_LINE,
  210. NULL,
  211. NULL,
  212. 0,
  213. &KeyLen,
  214. NULL,
  215. 0,
  216. &ValueLen
  217. );
  218. continue;
  219. }
  220. dCount++;
  221. //
  222. // allocate memory for the group name and value string
  223. //
  224. KeyName = (PWSTR)ScepAlloc( LMEM_ZEROINIT, KeyLen+2);
  225. if ( KeyName ) {
  226. Value = (PWSTR)ScepAlloc(LMEM_ZEROINIT, ValueLen+2);
  227. if ( Value ) {
  228. rc = SceJetGetValue(
  229. hSection,
  230. SCEJET_CURRENT,
  231. NULL,
  232. KeyName,
  233. KeyLen,
  234. &KeyLen,
  235. Value,
  236. ValueLen,
  237. &ValueLen
  238. );
  239. if ( rc == SCESTATUS_SUCCESS ||
  240. rc == SCESTATUS_BUFFER_TOO_SMALL ) {
  241. rc = SCESTATUS_SUCCESS;
  242. if ( ValueLen > 0 )
  243. Value[ValueLen/2] = L'\0';
  244. KeyName[KeyLen/2] = L'\0';
  245. if ( ValueLen > 0 && Value[0] != L'\0' ) {
  246. //
  247. // the first ansi character is the value type,
  248. // second ansi character is the status (if in SAP)
  249. // should be terminated by L'\0'
  250. //
  251. //dType = _wtol(Value);
  252. dType = *((CHAR *)Value) - '0';
  253. if ( *((CHAR *)Value+1) >= '0' ) {
  254. Status = *((CHAR *)Value+1) - '0';
  255. } else {
  256. Status = 0;
  257. }
  258. // if ( *(Value+2) ) { // a char and a null delimiter
  259. if ( ValueLen > 4 ) { // a char and a null delimiter
  260. //
  261. // the second field and after is the registry value
  262. // convert the multi-sz delimeter to ,
  263. //
  264. if ( dType == REG_MULTI_SZ &&
  265. (0 == _wcsicmp( KeyName, szLegalNoticeTextKeyName) ) ) {
  266. //
  267. // check for commas and escape them with "," so the UI etc.
  268. // understands this, since, at this point for lines such as
  269. // k=7,a",",b,c
  270. // pValueStr will be a,\0b\0c\0\0 which we should make
  271. // a","\0b\0c\0\0
  272. //
  273. DWORD dwCommaCount = 0;
  274. j = 0;
  275. for ( j=2; j< ValueLen/2 ; j++) {
  276. if ( Value[j] == L',' )
  277. dwCommaCount++;
  278. }
  279. if ( dwCommaCount > 0 ) {
  280. //
  281. // in this case we have to escape commas
  282. //
  283. PWSTR pszValueEscaped;
  284. DWORD dwBytes = (ValueLen/2 + 1 + dwCommaCount*2) * sizeof(WCHAR);
  285. pszValueEscaped = (PWSTR)ScepAlloc(LMEM_ZEROINIT, dwBytes);
  286. if (pszValueEscaped) {
  287. memset(pszValueEscaped, '\0', dwBytes);
  288. ValueLen = 2 * ScepEscapeString(Value,
  289. ValueLen/2,
  290. L',',
  291. L'"',
  292. pszValueEscaped
  293. );
  294. ScepFree(Value);
  295. Value = pszValueEscaped;
  296. } else {
  297. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  298. }
  299. }
  300. }
  301. ScepConvertMultiSzToDelim(Value+2, ValueLen/2-2, L'\0', L',');
  302. ValueStr = (PWSTR)ScepAlloc(0, (ValueLen/2-1)*sizeof(WCHAR));
  303. if ( ValueStr ) {
  304. wcscpy(ValueStr, Value+2);
  305. ValueStr[ValueLen/2-2] = L'\0';
  306. } else {
  307. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  308. }
  309. } // else no value available
  310. //
  311. // assign name to the output buffer
  312. //
  313. (*ppRegValues)[i].FullValueName = KeyName;
  314. KeyName = NULL;
  315. (*ppRegValues)[i].ValueType = dType;
  316. (*ppRegValues)[i].Value = ValueStr;
  317. (*ppRegValues)[i].Status = Status;
  318. ValueStr = NULL;
  319. //
  320. // increment the count
  321. //
  322. i++;
  323. } else {
  324. // shouldn't be possible to get into this loop
  325. // if it does, ignore this one
  326. rc = SCESTATUS_INVALID_DATA;
  327. }
  328. } else if ( rc != SCESTATUS_RECORD_NOT_FOUND ){
  329. ScepBuildErrorLogInfo( ERROR_READ_FAULT,
  330. Errlog,
  331. SCEERR_QUERY_VALUE,
  332. szRegistryValues
  333. );
  334. }
  335. if ( Value ) {
  336. ScepFree(Value);
  337. Value = NULL;
  338. }
  339. if ( ValueStr ) {
  340. ScepFree(ValueStr);
  341. ValueStr = NULL;
  342. }
  343. } else {
  344. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  345. }
  346. //
  347. // remember to free the KeyName
  348. //
  349. if ( KeyName ) {
  350. ScepFree(KeyName);
  351. KeyName = NULL;
  352. }
  353. if ( rc != SCESTATUS_SUCCESS ) {
  354. break;
  355. }
  356. //
  357. // read next line
  358. //
  359. rc = SceJetGetValue(
  360. hSection,
  361. SCEJET_NEXT_LINE,
  362. NULL,
  363. NULL,
  364. 0,
  365. &KeyLen,
  366. NULL,
  367. 0,
  368. &ValueLen
  369. );
  370. } else {
  371. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  372. }
  373. }
  374. } else {
  375. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  376. }
  377. }
  378. if ( rc == SCESTATUS_RECORD_NOT_FOUND ||
  379. rc == SCESTATUS_BUFFER_TOO_SMALL ) {
  380. rc = SCESTATUS_SUCCESS;
  381. }
  382. if ( rc != SCESTATUS_SUCCESS ) {
  383. //
  384. // free memory
  385. //
  386. ScepFreeRegistryValues( ppRegValues, *pValueCount );
  387. *ppRegValues = NULL;
  388. } else if ( ProfileType == SCE_ENGINE_GPO &&
  389. *pValueCount > dCount ) {
  390. //
  391. // reallocate the output buffer
  392. //
  393. if ( dCount > 0 ) {
  394. PSCE_REGISTRY_VALUE_INFO pTempRegValues = *ppRegValues;
  395. //
  396. // allocate memory for all objects
  397. //
  398. *ppRegValues = (PSCE_REGISTRY_VALUE_INFO)ScepAlloc( LMEM_ZEROINIT,
  399. dCount*sizeof(SCE_REGISTRY_VALUE_INFO) );
  400. if ( *ppRegValues ) {
  401. for ( i=0,j=0; i<*pValueCount; i++ ) {
  402. if ( pTempRegValues[i].Value ) {
  403. (*ppRegValues)[j].FullValueName = pTempRegValues[i].FullValueName;
  404. (*ppRegValues)[j].Value = pTempRegValues[i].Value;
  405. (*ppRegValues)[j].ValueType = pTempRegValues[i].ValueType;
  406. (*ppRegValues)[j].Status = pTempRegValues[i].Status;
  407. j++;
  408. } else if ( pTempRegValues[i].FullValueName ) {
  409. ScepFree( pTempRegValues[i].FullValueName );
  410. }
  411. }
  412. ScepFree( pTempRegValues );
  413. *pValueCount = dCount;
  414. } else {
  415. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  416. *pValueCount = 0;
  417. }
  418. } else {
  419. //
  420. // no registry value from the GPO settings are found
  421. //
  422. ScepFreeRegistryValues( ppRegValues, *pValueCount );
  423. *ppRegValues = NULL;
  424. *pValueCount = 0;
  425. }
  426. }
  427. //
  428. // close the section
  429. //
  430. SceJetCloseSection(&hSection, TRUE);
  431. return(rc);
  432. }
  433. DWORD
  434. ScepSetDriverSigningPolicy(
  435. BYTE Policy)
  436. /* ++
  437. Routine Description:
  438. This routine configures driver signing policy through a private API
  439. that ensures the value is not being reset by the code signing
  440. "anti-tampering" feature.
  441. Arguments:
  442. bPolicy - new policy to set
  443. Return value:
  444. win32 error
  445. -- */
  446. {
  447. DWORD Err;
  448. HKEY hKey;
  449. DWORD dwData = 0, dwSize, dwType;
  450. BYTE NewPolicy;
  451. SYSTEMTIME RealSystemTime;
  452. Err = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  453. TEXT("System\\WPA\\PnP"),
  454. 0,
  455. KEY_READ,
  456. &hKey
  457. );
  458. if(Err != ERROR_SUCCESS) {
  459. return Err;
  460. }
  461. dwSize = sizeof(dwData);
  462. Err = RegQueryValueEx(hKey,
  463. TEXT("seed"),
  464. NULL,
  465. &dwType,
  466. (PBYTE)&dwData,
  467. &dwSize
  468. );
  469. if(Err == ERROR_SUCCESS) {
  470. if(dwType != REG_DWORD) {
  471. Err = ERROR_DATATYPE_MISMATCH;
  472. } else if(dwSize != sizeof(dwData)) {
  473. Err = ERROR_INVALID_DATA;
  474. } else {
  475. RealSystemTime.wDayOfWeek = LOWORD(&hKey) | 4;
  476. RealSystemTime.wMinute = LOWORD(dwData);
  477. RealSystemTime.wYear = HIWORD(dwData);
  478. RealSystemTime.wMilliseconds = (LOWORD(&dwType)&~3072)|(((WORD)(Policy&3))<<10);
  479. pSetupGetRealSystemTime(&RealSystemTime);
  480. RealSystemTime.wDayOfWeek = LOWORD(&hKey) | 4;
  481. pSetupGetRealSystemTime(&RealSystemTime);
  482. NewPolicy = (BYTE)(((RealSystemTime.wMilliseconds+2)&15)^8)/4;
  483. if(Policy != NewPolicy) {
  484. Err = ERROR_FUNCTION_FAILED;
  485. }
  486. }
  487. }
  488. RegCloseKey(hKey);
  489. return Err;
  490. }
  491. SCESTATUS
  492. ScepConfigureRegistryValues(
  493. IN PSCECONTEXT hProfile OPTIONAL,
  494. IN PSCE_REGISTRY_VALUE_INFO pRegValues,
  495. IN DWORD ValueCount,
  496. IN PSCE_ERROR_LOG_INFO *pErrLog,
  497. IN DWORD ConfigOptions,
  498. OUT PBOOL pAnythingSet
  499. )
  500. /* ++
  501. Routine Description:
  502. This routine configure registry values in the area of security
  503. policy.
  504. Arguments:
  505. pRegValues - The array of registry values to configure
  506. ValueCount - the number of values to configure
  507. Return value:
  508. SCESTATUS_SUCCESS
  509. SCESTATUS_NOT_ENOUGH_RESOURCE
  510. SCESTATUS_INVALID_PARAMETER
  511. SCESTATUS_OTHER_ERROR
  512. -- */
  513. {
  514. if ( !pRegValues || ValueCount == 0 ) {
  515. //
  516. // if no info to configure
  517. //
  518. return SCESTATUS_SUCCESS;
  519. }
  520. DWORD rc;
  521. SCESTATUS Saverc=SCESTATUS_SUCCESS;
  522. PWSTR pStart, pTemp, pValue;
  523. HKEY hKey=NULL;
  524. HKEY hKeyRoot;
  525. PSCESECTION hSectionDomain=NULL;
  526. PSCESECTION hSectionTattoo=NULL;
  527. SCE_REGISTRY_VALUE_INFO OneRegValue;
  528. if ( pAnythingSet )
  529. *pAnythingSet = FALSE;
  530. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) && hProfile ) {
  531. ScepTattooOpenPolicySections(
  532. hProfile,
  533. szRegistryValues,
  534. &hSectionDomain,
  535. &hSectionTattoo
  536. );
  537. }
  538. for ( DWORD i=0; i<ValueCount; i++ ) {
  539. if ( !pRegValues[i].FullValueName ||
  540. !pRegValues[i].Value ) {
  541. //
  542. // no value to configure
  543. //
  544. continue;
  545. }
  546. ScepLogOutput3(2, 0, SCEDLL_SCP_CONFIGURE, pRegValues[i].FullValueName);
  547. //
  548. // look for the first \\
  549. //
  550. pStart = wcschr(pRegValues[i].FullValueName, L'\\') ;
  551. if ( !pStart ) {
  552. Saverc = SCESTATUS_INVALID_DATA;
  553. if ( pErrLog ) {
  554. ScepBuildErrorLogInfo(Saverc,pErrLog, SCEDLL_SCP_ERROR_CONFIGURE,
  555. pRegValues[i].FullValueName);
  556. } else {
  557. ScepLogOutput3(1, Saverc, SCEDLL_SCP_ERROR_CONFIGURE, pRegValues[i].FullValueName);
  558. }
  559. if ( ConfigOptions & SCE_RSOP_CALLBACK )
  560. ScepRsopLog(SCE_RSOP_REGISTRY_VALUE_INFO, Saverc, pRegValues[i].FullValueName, 0, 0);
  561. continue;
  562. }
  563. //
  564. // find the root key
  565. //
  566. if ( (7 == pStart-pRegValues[i].FullValueName) &&
  567. (0 == _wcsnicmp(L"MACHINE", pRegValues[i].FullValueName, 7)) ) {
  568. hKeyRoot = HKEY_LOCAL_MACHINE;
  569. } else if ( (5 == pStart-pRegValues[i].FullValueName) &&
  570. (0 == _wcsnicmp(L"USERS", pRegValues[i].FullValueName, 5)) ) {
  571. hKeyRoot = HKEY_USERS;
  572. } else if ( (12 == pStart-pRegValues[i].FullValueName) &&
  573. (0 == _wcsnicmp(L"CLASSES_ROOT", pRegValues[i].FullValueName, 12)) ) {
  574. hKeyRoot = HKEY_CLASSES_ROOT;
  575. } else {
  576. Saverc = SCESTATUS_INVALID_DATA;
  577. if ( pErrLog ) {
  578. ScepBuildErrorLogInfo(Saverc,pErrLog, SCEDLL_SCP_ERROR_CONFIGURE,
  579. pRegValues[i].FullValueName);
  580. } else {
  581. ScepLogOutput3(1, Saverc, SCEDLL_SCP_ERROR_CONFIGURE, pRegValues[i].FullValueName);
  582. }
  583. if ( ConfigOptions & SCE_RSOP_CALLBACK )
  584. ScepRsopLog(SCE_RSOP_REGISTRY_VALUE_INFO, Saverc, pRegValues[i].FullValueName, 0, 0);
  585. continue;
  586. }
  587. //
  588. // find the value name
  589. //
  590. pValue = pStart+1;
  591. do {
  592. pTemp = wcschr(pValue, L'\\');
  593. if ( pTemp ) {
  594. pValue = pTemp+1;
  595. }
  596. } while ( pTemp );
  597. if ( pValue == pStart+1 ) {
  598. Saverc = SCESTATUS_INVALID_DATA;
  599. if ( pErrLog ) {
  600. ScepBuildErrorLogInfo(Saverc,pErrLog, SCEDLL_SCP_ERROR_CONFIGURE,
  601. pRegValues[i].FullValueName);
  602. } else {
  603. ScepLogOutput3(1, Saverc, SCEDLL_SCP_ERROR_CONFIGURE, pRegValues[i].FullValueName);
  604. }
  605. if ( ConfigOptions & SCE_RSOP_CALLBACK )
  606. ScepRsopLog(SCE_RSOP_REGISTRY_VALUE_INFO, Saverc, pRegValues[i].FullValueName, 0, 0);
  607. continue;
  608. }
  609. //
  610. // terminate the subkey for now
  611. //
  612. *(pValue-1) = L'\0';
  613. //
  614. // set the value
  615. // always create the key if it does not exist.
  616. //
  617. rc = RegCreateKeyEx(hKeyRoot,
  618. pStart+1,
  619. 0,
  620. NULL,
  621. 0,
  622. KEY_READ | KEY_SET_VALUE,
  623. NULL,
  624. &hKey,
  625. NULL
  626. );
  627. if ( rc == ERROR_SUCCESS ||
  628. rc == ERROR_ALREADY_EXISTS ) {
  629. /*
  630. if(( rc = RegOpenKeyEx(hKeyRoot,
  631. pStart+1,
  632. 0,
  633. KEY_SET_VALUE,
  634. &hKey
  635. )) == ERROR_SUCCESS ) {
  636. */
  637. //
  638. // restore the char
  639. //
  640. *(pValue-1) = L'\\';
  641. OneRegValue.FullValueName = NULL;
  642. OneRegValue.Value = NULL;
  643. BOOL bLMSetting = FALSE;
  644. if ( (REG_DWORD == pRegValues[i].ValueType) &&
  645. _wcsicmp(SCEP_LMC_SETTING, pRegValues[i].FullValueName) == 0 ) {
  646. //
  647. // check if dcpromo upgrade in progress
  648. //
  649. DWORD dwInSetup=0;
  650. DWORD dwUpgraded=0;
  651. ScepRegQueryIntValue(HKEY_LOCAL_MACHINE,
  652. SCE_ROOT_PATH,
  653. TEXT("PromoteUpgradeInProgress"),
  654. &dwUpgraded
  655. );
  656. if ( dwUpgraded ) {
  657. //
  658. // in dcpromo upgrade, we need to do special check about
  659. // this setting
  660. //
  661. bLMSetting = TRUE;
  662. } else {
  663. //
  664. // check if in setup upgrade
  665. //
  666. dwUpgraded=0;
  667. ScepRegQueryIntValue(HKEY_LOCAL_MACHINE,
  668. TEXT("System\\Setup"),
  669. TEXT("SystemSetupInProgress"),
  670. &dwInSetup
  671. );
  672. if ( dwInSetup ) {
  673. //
  674. // if system is upgraded, the state is stored in registry
  675. // by SCE client at very beginning of GUI setup
  676. //
  677. ScepRegQueryIntValue(
  678. HKEY_LOCAL_MACHINE,
  679. SCE_ROOT_PATH,
  680. TEXT("SetupUpgraded"),
  681. (DWORD *)&dwUpgraded
  682. );
  683. if ( dwUpgraded ) {
  684. //
  685. // in setup upgrade, we need to do special check about
  686. // this setting
  687. //
  688. bLMSetting = TRUE;
  689. }
  690. }
  691. }
  692. }
  693. //
  694. // if in policy propagation, query the existing value
  695. //
  696. if ( ( (ConfigOptions & SCE_POLICY_TEMPLATE) && hProfile ) ||
  697. bLMSetting ) {
  698. OneRegValue.FullValueName = pRegValues[i].FullValueName;
  699. OneRegValue.ValueType = pRegValues[i].ValueType;
  700. OneRegValue.Status = 0;
  701. DWORD rc2 = ScepAnalyzeOneRegistryValueNoValidate(
  702. hKey,
  703. pValue,
  704. NULL,
  705. SCEREG_VALUE_SYSTEM,
  706. &OneRegValue
  707. );
  708. if ( ERROR_SUCCESS != rc2 ) {
  709. if ( !bLMSetting ) {
  710. ScepLogOutput3(1, 0, SCESRV_POLICY_TATTOO_ERROR_QUERY, rc2, pRegValues[i].FullValueName);
  711. } else if ( ERROR_FILE_NOT_FOUND != rc2 ) {
  712. ScepLogOutput3(1, 0, SCESRV_SETUPUPD_ERROR_LMCOMPAT, rc2, pRegValues[i].FullValueName);
  713. }
  714. }
  715. }
  716. if ( REG_DWORD == pRegValues[i].ValueType ) {
  717. //
  718. // REG_DWORD type, value is a dword
  719. //
  720. LONG RegValue = _wtol(pRegValues[i].Value);
  721. if ( !bLMSetting || OneRegValue.Value == NULL ||
  722. _wtol(OneRegValue.Value) <= RegValue ) {
  723. rc = RegSetValueEx( hKey,
  724. pValue,
  725. 0,
  726. REG_DWORD,
  727. (BYTE *)&RegValue,
  728. sizeof(DWORD)
  729. );
  730. } else {
  731. //
  732. // for LMCompatibility level, if in setup, set this value only if
  733. // current system setting is less than configuration, or not defined
  734. //
  735. ScepLogOutput3(2, 0, SCESRV_SETUPUPD_IGNORE_LMCOMPAT, pRegValues[i].FullValueName);
  736. }
  737. } else if ( -1 == pRegValues[i].ValueType ) {
  738. //
  739. // delete the registry value
  740. //
  741. rc = RegDeleteValue(hKey, pValue);
  742. //
  743. // if the value doesn't exist, ignore the error
  744. //
  745. if ( ERROR_FILE_NOT_FOUND == rc )
  746. rc = ERROR_SUCCESS;
  747. } else {
  748. PBYTE pRegBytes=NULL;
  749. DWORD nLen;
  750. nLen = wcslen(pRegValues[i].Value);
  751. if ( REG_MULTI_SZ == pRegValues[i].ValueType || REG_QWORD == pRegValues[i].ValueType) {
  752. //
  753. // translate the comma delimited string to multi-sz string
  754. //
  755. //
  756. // LegalNoticeText is special cased i.e. \0 should be converted to \r\n
  757. // and commas should be unescaped before writing this value into the registry
  758. //
  759. BOOL bIsLegalNoticeText = FALSE;
  760. if ( !(REG_MULTI_SZ == pRegValues[i].ValueType &&
  761. (0 == _wcsicmp(szLegalNoticeTextKeyName, pRegValues[i].FullValueName ) ) ) ) {
  762. pRegBytes = (PBYTE)ScepAlloc(0, (nLen+2)*sizeof(WCHAR));
  763. if ( pRegBytes ) {
  764. wcscpy((PWSTR)pRegBytes, pRegValues[i].Value);
  765. ((PWSTR)pRegBytes)[nLen] = L'\0';
  766. ((PWSTR)pRegBytes)[nLen+1] = L'\0';
  767. ScepConvertMultiSzToDelim((PWSTR)pRegBytes,
  768. nLen+1,
  769. L',',
  770. L'\0'
  771. );
  772. } else {
  773. rc = ERROR_NOT_ENOUGH_MEMORY;
  774. }
  775. }
  776. else {
  777. DWORD dwCommaCount = 0;
  778. DWORD dwBytes;
  779. bIsLegalNoticeText = TRUE;
  780. for ( DWORD dwIndex = 0; dwIndex <= nLen; dwIndex++) {
  781. if ( pRegValues[i].Value[dwIndex] == L',' )
  782. dwCommaCount++;
  783. }
  784. dwBytes = (nLen + dwCommaCount + 2)*sizeof(WCHAR);
  785. pRegBytes = (PBYTE)ScepAlloc(0, dwBytes);
  786. if ( pRegBytes ) {
  787. memset(pRegBytes, '\0', dwBytes);
  788. //
  789. // unescape the "," and add \r\n wherever there is a ,
  790. //
  791. nLen = ScepUnescapeAndAddCRLF( pRegValues[i].Value, (PWSTR) pRegBytes);
  792. } else {
  793. rc = ERROR_NOT_ENOUGH_MEMORY;
  794. }
  795. }
  796. if ( rc == NO_ERROR ) {
  797. //
  798. // engine/UI treat LegalNoticeText as REG_MULTI_SZ but
  799. // we force it to be REG_SZ for compatibility sake
  800. //
  801. rc = RegSetValueEx( hKey,
  802. pValue,
  803. 0,
  804. bIsLegalNoticeText ? REG_SZ : pRegValues[i].ValueType,
  805. pRegBytes,
  806. (nLen+2)*sizeof(WCHAR)
  807. );
  808. ScepFree(pRegBytes);
  809. }
  810. } else if ( REG_BINARY == pRegValues[i].ValueType ) {
  811. if ( nLen > 0 ) {
  812. //
  813. // binary type, translate the unicode string to binary data
  814. // 4 bytes (2 wchars) to 1 byte
  815. //
  816. DWORD newLen;
  817. newLen = nLen/2;
  818. if ( nLen % 2 ) {
  819. newLen++; // pad a leading 0
  820. }
  821. pRegBytes = (PBYTE)ScepAlloc(0, newLen);
  822. if ( pRegBytes ) {
  823. BYTE dByte;
  824. for ( INT j=newLen-1; j>=0; j-- ) {
  825. if ( nLen % 2 ) {
  826. // odd number of chars
  827. dByte = (pRegValues[i].Value[j*2]-L'0') % 16;
  828. if ( j*2 >= 1 ) {
  829. dByte += ((pRegValues[i].Value[j*2-1]-L'0') % 16) * 16;
  830. }
  831. } else {
  832. // even number of chars
  833. dByte = (pRegValues[i].Value[j*2+1]-L'0') % 16;
  834. dByte += ((pRegValues[i].Value[j*2]-L'0') % 16) * 16;
  835. }
  836. pRegBytes[j] = dByte;
  837. }
  838. // Special case for code signing policy, this value is protected from
  839. // "tampering" so we need to set it through their API to avoid being
  840. // overwritten.
  841. if (_wcsicmp(
  842. SCEP_DRIVER_SIGNING_SETTING,
  843. pRegValues[i].FullValueName) == 0 ) {
  844. rc = ScepSetDriverSigningPolicy(*pRegBytes);
  845. } else {
  846. rc = RegSetValueEx( hKey,
  847. pValue,
  848. 0,
  849. REG_BINARY,
  850. pRegBytes,
  851. newLen
  852. );
  853. }
  854. ScepFree(pRegBytes);
  855. } else {
  856. rc = ERROR_NOT_ENOUGH_MEMORY;
  857. }
  858. }
  859. } else {
  860. //
  861. // sz type, expand_sz
  862. //
  863. rc = RegSetValueEx( hKey,
  864. pValue,
  865. 0,
  866. pRegValues[i].ValueType,
  867. (BYTE *)(pRegValues[i].Value),
  868. (nLen)*sizeof(WCHAR)
  869. );
  870. }
  871. }
  872. //
  873. // manage the tattoo value
  874. //
  875. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) && hProfile ) {
  876. //
  877. // if can't query system setting (OneRegValue.Value == NULL)
  878. // (may be because they are deleted e.g. demotion)
  879. // we still need to delete the tattoo values
  880. //
  881. ScepTattooManageOneRegistryValue(hSectionDomain,
  882. hSectionTattoo,
  883. pRegValues[i].FullValueName,
  884. 0,
  885. &OneRegValue,
  886. rc
  887. );
  888. }
  889. if ( OneRegValue.Value ) ScepFree(OneRegValue.Value);
  890. RegCloseKey( hKey );
  891. }
  892. if ( NO_ERROR != rc ) {
  893. if ( pErrLog ) {
  894. ScepBuildErrorLogInfo(rc,pErrLog, SCEDLL_ERROR_SET_INFO,
  895. pRegValues[i].FullValueName);
  896. }
  897. if ( ERROR_FILE_NOT_FOUND != rc &&
  898. ERROR_PATH_NOT_FOUND != rc ) {
  899. ScepLogOutput3(1, rc, SCEDLL_ERROR_SET_INFO, pRegValues[i].FullValueName);
  900. Saverc = ScepDosErrorToSceStatus(rc);
  901. }
  902. }
  903. if ( ConfigOptions & SCE_RSOP_CALLBACK )
  904. ScepRsopLog(SCE_RSOP_REGISTRY_VALUE_INFO, rc, pRegValues[i].FullValueName, 0, 0);
  905. if ( pAnythingSet ) {
  906. *pAnythingSet = TRUE;
  907. }
  908. }
  909. if ( hSectionDomain ) SceJetCloseSection(&hSectionDomain, TRUE);
  910. if ( hSectionTattoo ) SceJetCloseSection(&hSectionTattoo, TRUE);
  911. return(Saverc);
  912. }
  913. DWORD
  914. ScepUnescapeAndAddCRLF(
  915. IN PWSTR pszSource,
  916. IN OUT PWSTR pszDest
  917. )
  918. /* ++
  919. Routine Description:
  920. Primarily used just before configuration
  921. Unescapes commas i.e. a","\0b\0c\0\0 -> a,\0b\0c\0\0
  922. Also replaces , with \r\n
  923. Arguments:
  924. pszSource - The source string
  925. dwSourceChars - The number of chars in pszSource
  926. pszDest - The destination string
  927. Return value:
  928. Number of characters copied to the destination
  929. -- */
  930. {
  931. DWORD dwCharsCopied = 0;
  932. while (pszSource[0] != L'\0') {
  933. if (0 == wcsncmp(pszSource, L"\",\"", 3)) {
  934. pszDest[0] = L',';
  935. ++dwCharsCopied;
  936. ++pszDest;
  937. pszSource +=3;
  938. }
  939. else if (pszSource[0] == L',') {
  940. pszDest[0] = L'\r';
  941. pszDest[1] = L'\n';
  942. dwCharsCopied +=2;
  943. pszDest +=2 ;
  944. ++pszSource;
  945. }
  946. else {
  947. pszDest[0] = pszSource[0];
  948. ++dwCharsCopied;
  949. ++pszDest;
  950. ++pszSource;
  951. }
  952. }
  953. pszDest = L'\0';
  954. ++dwCharsCopied;
  955. return dwCharsCopied;
  956. }
  957. DWORD
  958. ScepEscapeAndRemoveCRLF(
  959. IN const PWSTR pszSource,
  960. IN const DWORD dwSourceSize,
  961. IN OUT PWSTR pszDest
  962. )
  963. /* ++
  964. Routine Description:
  965. Primarily used before analysis
  966. Escapes commas i.e. a,\0b\0c\0\0 -> a","\0b\0c\0\0
  967. Also replaces \r\n with ,
  968. This routine is the inverse of ScepUnescapeAndAddCRLF
  969. Arguments:
  970. pszSource - The source string
  971. dwSourceChars - The number of chars in pszSource
  972. pszDest - The destination string
  973. Return value:
  974. Number of characters copied to the destination
  975. -- */
  976. {
  977. DWORD dwSourceIndex = 0;
  978. DWORD dwCopiedChars = 0;
  979. while (dwSourceIndex < dwSourceSize) {
  980. if (0 == wcsncmp(pszSource + dwSourceIndex, L"\r\n", 2)) {
  981. pszDest[0] = L',';
  982. ++pszDest;
  983. ++dwCopiedChars;
  984. dwSourceIndex +=2;
  985. }
  986. else if (pszSource[dwSourceIndex] == L',') {
  987. pszDest[0] = L'"';
  988. pszDest[1] = L',';
  989. pszDest[2] = L'"';
  990. pszDest +=3 ;
  991. dwCopiedChars +=3 ;
  992. ++dwSourceIndex;
  993. }
  994. else {
  995. pszDest[0] = pszSource[dwSourceIndex];
  996. ++pszDest;
  997. ++dwCopiedChars;
  998. ++dwSourceIndex;
  999. }
  1000. }
  1001. pszDest = L'\0';
  1002. return dwCopiedChars;
  1003. }
  1004. SCESTATUS
  1005. ScepAnalyzeRegistryValues(
  1006. IN PSCECONTEXT hProfile,
  1007. IN DWORD dwAnalFlag,
  1008. IN PSCE_PROFILE_INFO pSmpInfo
  1009. )
  1010. /* ++
  1011. Routine Description:
  1012. This routine analyze registry values in the area of security
  1013. policy.
  1014. Arguments:
  1015. Return value:
  1016. SCESTATUS_SUCCESS
  1017. SCESTATUS_NOT_ENOUGH_RESOURCE
  1018. SCESTATUS_INVALID_PARAMETER
  1019. SCESTATUS_OTHER_ERROR
  1020. -- */
  1021. {
  1022. if ( !pSmpInfo ) {
  1023. return SCESTATUS_INVALID_PARAMETER;
  1024. }
  1025. if ( (dwAnalFlag != SCEREG_VALUE_SYSTEM) && !hProfile ) {
  1026. return SCESTATUS_INVALID_PARAMETER;
  1027. }
  1028. SCESTATUS Saverc=SCESTATUS_SUCCESS;
  1029. if ( dwAnalFlag != SCEREG_VALUE_ROLLBACK ) {
  1030. Saverc = ScepEnumAllRegValues(
  1031. &(pSmpInfo->RegValueCount),
  1032. &(pSmpInfo->aRegValues)
  1033. );
  1034. }
  1035. if ( Saverc != SCESTATUS_SUCCESS ) {
  1036. return(Saverc);
  1037. }
  1038. if ( pSmpInfo->RegValueCount == 0 ||
  1039. pSmpInfo->aRegValues == NULL ) {
  1040. //
  1041. // if no info to configure
  1042. //
  1043. return SCESTATUS_SUCCESS;
  1044. }
  1045. DWORD rc;
  1046. DWORD i;
  1047. PSCESECTION hSection=NULL;
  1048. SCEJET_TABLE_TYPE tblType;
  1049. if ( dwAnalFlag != SCEREG_VALUE_SYSTEM ) {
  1050. //
  1051. // query value from system doesn't require accessing the database
  1052. //
  1053. switch ( dwAnalFlag ) {
  1054. case SCEREG_VALUE_SNAPSHOT:
  1055. case SCEREG_VALUE_FILTER:
  1056. case SCEREG_VALUE_ROLLBACK:
  1057. tblType = SCEJET_TABLE_SMP;
  1058. break;
  1059. default:
  1060. tblType = SCEJET_TABLE_SAP;
  1061. break;
  1062. }
  1063. //
  1064. // Prepare a new section
  1065. // for delay filter mode, data is written to the SMP (local) table
  1066. // when the setting is different from the effective setting (changed outside GPO)
  1067. //
  1068. Saverc = ScepStartANewSection(
  1069. hProfile,
  1070. &hSection,
  1071. tblType,
  1072. szRegistryValues
  1073. );
  1074. if ( Saverc != SCESTATUS_SUCCESS ) {
  1075. ScepLogOutput3(1, ScepSceStatusToDosError(Saverc),
  1076. SCEDLL_SAP_START_SECTION, (PWSTR)szRegistryValues);
  1077. return(Saverc);
  1078. }
  1079. }
  1080. for ( i=0; i<pSmpInfo->RegValueCount; i++ ) {
  1081. if ( dwAnalFlag == SCEREG_VALUE_SYSTEM ) {
  1082. //
  1083. // mark the status field
  1084. //
  1085. (pSmpInfo->aRegValues)[i].Status = SCE_STATUS_ERROR_NOT_AVAILABLE;
  1086. }
  1087. if ( !((pSmpInfo->aRegValues)[i].FullValueName) ) {
  1088. continue;
  1089. }
  1090. ScepLogOutput3(2, 0, SCEDLL_SAP_ANALYZE, (pSmpInfo->aRegValues)[i].FullValueName);
  1091. rc = ScepAnalyzeOneRegistryValue(
  1092. hSection,
  1093. dwAnalFlag,
  1094. &((pSmpInfo->aRegValues)[i])
  1095. );
  1096. if ( SCESTATUS_INVALID_PARAMETER == rc ||
  1097. SCESTATUS_INVALID_DATA == rc ) {
  1098. continue;
  1099. }
  1100. if ( SCESTATUS_SUCCESS != rc ) {
  1101. Saverc = rc;
  1102. break;
  1103. }
  1104. }
  1105. //
  1106. // close the section
  1107. //
  1108. SceJetCloseSection( &hSection, TRUE);
  1109. return(Saverc);
  1110. }
  1111. SCESTATUS
  1112. ScepAnalyzeOneRegistryValue(
  1113. IN PSCESECTION hSection OPTIONAL,
  1114. IN DWORD dwAnalFlag,
  1115. IN OUT PSCE_REGISTRY_VALUE_INFO pOneRegValue
  1116. )
  1117. {
  1118. SCESTATUS Saverc=SCESTATUS_SUCCESS;
  1119. PWSTR pStart, pTemp, pValue;
  1120. HKEY hKey=NULL, hKeyRoot;
  1121. DWORD rc=0;
  1122. if ( pOneRegValue == NULL ||
  1123. pOneRegValue->FullValueName == NULL ) {
  1124. return(SCESTATUS_INVALID_DATA);
  1125. }
  1126. if ( hSection == NULL &&
  1127. (SCEREG_VALUE_ANALYZE == dwAnalFlag ||
  1128. SCEREG_VALUE_ROLLBACK == dwAnalFlag) ) {
  1129. return(SCESTATUS_INVALID_PARAMETER);
  1130. }
  1131. //
  1132. // look for the first \\
  1133. //
  1134. pStart = wcschr(pOneRegValue->FullValueName, L'\\') ;
  1135. if ( !pStart ) {
  1136. //
  1137. // if it's in snapshot mode, ignore bogus reg value names
  1138. //
  1139. Saverc = SCESTATUS_INVALID_DATA;
  1140. if ( SCEREG_VALUE_ANALYZE == dwAnalFlag ) {
  1141. //
  1142. // error analyzing the value, save it
  1143. //
  1144. ScepSaveRegistryValue(
  1145. hSection,
  1146. pOneRegValue->FullValueName,
  1147. pOneRegValue->ValueType,
  1148. NULL,
  1149. 0,
  1150. SCE_STATUS_ERROR_NOT_AVAILABLE
  1151. );
  1152. }
  1153. return(Saverc);
  1154. }
  1155. //
  1156. // find the root key
  1157. //
  1158. if ( (7 == pStart-pOneRegValue->FullValueName) &&
  1159. (0 == _wcsnicmp(L"MACHINE", pOneRegValue->FullValueName, 7)) ) {
  1160. hKeyRoot = HKEY_LOCAL_MACHINE;
  1161. } else if ( (5 == pStart-pOneRegValue->FullValueName) &&
  1162. (0 == _wcsnicmp(L"USERS", pOneRegValue->FullValueName, 5)) ) {
  1163. hKeyRoot = HKEY_USERS;
  1164. } else if ( (12 == pStart-pOneRegValue->FullValueName) &&
  1165. (0 == _wcsnicmp(L"CLASSES_ROOT", pOneRegValue->FullValueName, 12)) ) {
  1166. hKeyRoot = HKEY_CLASSES_ROOT;
  1167. } else {
  1168. //
  1169. // if it's in snapshot mode, ignore bogus reg value names
  1170. //
  1171. Saverc = SCESTATUS_INVALID_DATA;
  1172. if ( SCEREG_VALUE_ANALYZE == dwAnalFlag ) {
  1173. //
  1174. // error analyzing the value, save it
  1175. //
  1176. ScepSaveRegistryValue(
  1177. hSection,
  1178. pOneRegValue->FullValueName,
  1179. pOneRegValue->ValueType,
  1180. NULL,
  1181. 0,
  1182. SCE_STATUS_ERROR_NOT_AVAILABLE
  1183. );
  1184. }
  1185. return(Saverc);
  1186. }
  1187. //
  1188. // find the value name
  1189. //
  1190. pValue = pStart+1;
  1191. do {
  1192. pTemp = wcschr(pValue, L'\\');
  1193. if ( pTemp ) {
  1194. pValue = pTemp+1;
  1195. }
  1196. } while ( pTemp );
  1197. if ( pValue == pStart+1 ) {
  1198. //
  1199. // if it's in snapshot mode, ignore bogus reg value names
  1200. //
  1201. Saverc = SCESTATUS_INVALID_DATA;
  1202. if ( SCEREG_VALUE_ANALYZE == dwAnalFlag ) {
  1203. //
  1204. // error analyzing the value, save it
  1205. //
  1206. ScepSaveRegistryValue(
  1207. hSection,
  1208. pOneRegValue->FullValueName,
  1209. pOneRegValue->ValueType,
  1210. NULL,
  1211. 0,
  1212. SCE_STATUS_ERROR_NOT_AVAILABLE
  1213. );
  1214. }
  1215. return(Saverc);
  1216. }
  1217. //
  1218. // terminate the subkey for now
  1219. //
  1220. *(pValue-1) = L'\0';
  1221. if(( rc = RegOpenKeyEx(hKeyRoot,
  1222. pStart+1,
  1223. 0,
  1224. KEY_READ,
  1225. &hKey
  1226. )) == ERROR_SUCCESS ) {
  1227. //
  1228. // resotre the char
  1229. //
  1230. *(pValue-1) = L'\\';
  1231. rc = ScepAnalyzeOneRegistryValueNoValidate(hKey,
  1232. pValue,
  1233. hSection,
  1234. dwAnalFlag,
  1235. pOneRegValue
  1236. );
  1237. //
  1238. // close the key
  1239. //
  1240. RegCloseKey(hKey);
  1241. } else {
  1242. //
  1243. // restore the char
  1244. //
  1245. *(pValue-1) = L'\\';
  1246. //
  1247. // error analyzing the value, or it doesn't exist, save it
  1248. //
  1249. if ( (SCEREG_VALUE_ANALYZE == dwAnalFlag) ||
  1250. (SCEREG_VALUE_ROLLBACK == dwAnalFlag) ) {
  1251. ScepSaveRegistryValue(
  1252. hSection,
  1253. pOneRegValue->FullValueName,
  1254. (SCEREG_VALUE_ANALYZE == dwAnalFlag) ? pOneRegValue->ValueType : -1,
  1255. NULL,
  1256. 0,
  1257. (SCEREG_VALUE_ANALYZE == dwAnalFlag) ? SCE_STATUS_ERROR_NOT_AVAILABLE : 0
  1258. );
  1259. }
  1260. if ( rc == ERROR_FILE_NOT_FOUND ||
  1261. rc == ERROR_PATH_NOT_FOUND ||
  1262. rc == ERROR_INVALID_HANDLE ||
  1263. rc == ERROR_ACCESS_DENIED ) {
  1264. rc = ERROR_SUCCESS;
  1265. }
  1266. }
  1267. if ( rc != NO_ERROR ) {
  1268. ScepLogOutput3(1, rc, SCEDLL_SAP_ERROR_ANALYZE, pOneRegValue->FullValueName);
  1269. Saverc = ScepDosErrorToSceStatus(rc);
  1270. }
  1271. return(Saverc);
  1272. }
  1273. DWORD
  1274. ScepAnalyzeOneRegistryValueNoValidate(
  1275. IN HKEY hKey,
  1276. IN PWSTR ValueName,
  1277. IN PSCESECTION hSection OPTIONAL,
  1278. IN DWORD dwAnalFlag,
  1279. IN OUT PSCE_REGISTRY_VALUE_INFO pOneRegValue
  1280. )
  1281. /*
  1282. Query and/or compare one registry value without validating the value name, etc.
  1283. The validation should be done outside of this routine.
  1284. This routine is primarily defined for sharing in both configuration and analysis.
  1285. */
  1286. {
  1287. if ( hKey == NULL || ValueName == NULL || pOneRegValue == NULL )
  1288. return(ERROR_INVALID_PARAMETER);
  1289. DWORD rc;
  1290. DWORD dSize=0;
  1291. DWORD RegType=pOneRegValue->ValueType;
  1292. DWORD RegData=0;
  1293. PWSTR strValue=NULL;
  1294. BOOL bIsLegalNoticeText = FALSE;
  1295. if ( SCEREG_VALUE_SYSTEM == dwAnalFlag ) {
  1296. //
  1297. // reset the status field, it's not error'ed
  1298. //
  1299. pOneRegValue->Status = 0;
  1300. }
  1301. if(( rc = RegQueryValueEx(hKey,
  1302. ValueName,
  1303. 0,
  1304. &RegType,
  1305. NULL,
  1306. &dSize
  1307. )) == ERROR_SUCCESS ) {
  1308. //
  1309. // we treat REG_DWORD_BIG_ENDIAN the same as REG_DWORD
  1310. //
  1311. if ( RegType == REG_DWORD_BIG_ENDIAN ) {
  1312. RegType = REG_DWORD;
  1313. }
  1314. if ( 0 == _wcsicmp( pOneRegValue->FullValueName, szLegalNoticeTextKeyName)) {
  1315. bIsLegalNoticeText = TRUE;
  1316. RegType = REG_MULTI_SZ;
  1317. } else if ( RegType != pOneRegValue->ValueType ) {
  1318. //
  1319. // if it's a wrong type, we assure it's not the value we found
  1320. //
  1321. rc = ERROR_FILE_NOT_FOUND;
  1322. }
  1323. if ( ERROR_SUCCESS == rc ) {
  1324. switch (RegType) {
  1325. case REG_DWORD:
  1326. dSize = sizeof(DWORD);
  1327. rc = RegQueryValueEx(hKey,
  1328. ValueName,
  1329. 0,
  1330. &RegType,
  1331. (BYTE *)&RegData,
  1332. &dSize
  1333. );
  1334. break;
  1335. default:
  1336. //
  1337. // can be REG_BINARY, REG_MULTI_SZ, REG_SZ, and REG_EXPAND_SZ
  1338. // everything else is treated as REG_SZ
  1339. //
  1340. strValue = (PWSTR)ScepAlloc(0, dSize + 4);
  1341. dSize += 2;
  1342. if ( strValue ) {
  1343. memset(strValue, 0, dSize + 4 - 2);
  1344. rc = RegQueryValueEx(hKey,
  1345. ValueName,
  1346. 0,
  1347. &RegType,
  1348. (BYTE *)strValue,
  1349. &dSize
  1350. );
  1351. if (bIsLegalNoticeText) {
  1352. RegType = REG_MULTI_SZ;
  1353. }
  1354. } else {
  1355. rc = ERROR_NOT_ENOUGH_MEMORY;
  1356. }
  1357. break;
  1358. }
  1359. }
  1360. }
  1361. if ( rc == NO_ERROR ) {
  1362. DWORD dwStatus = SCE_STATUS_NOT_CONFIGURED;
  1363. if ( SCEREG_VALUE_SNAPSHOT == dwAnalFlag ||
  1364. SCEREG_VALUE_ROLLBACK == dwAnalFlag )
  1365. dwStatus = 0;
  1366. switch ( RegType ) {
  1367. case REG_DWORD:
  1368. case REG_DWORD_BIG_ENDIAN:
  1369. if ( pOneRegValue->Value == NULL ||
  1370. (SCEREG_VALUE_SNAPSHOT == dwAnalFlag) ) {
  1371. if ( SCEREG_VALUE_SYSTEM == dwAnalFlag ) {
  1372. //
  1373. // add the value to OneRegValue buffer
  1374. //
  1375. rc = ScepSaveRegistryValueToBuffer(
  1376. REG_DWORD,
  1377. (PWSTR)&RegData,
  1378. sizeof(DWORD),
  1379. pOneRegValue
  1380. );
  1381. } else if ( SCEREG_VALUE_FILTER != dwAnalFlag ) {
  1382. //
  1383. // not configured, or snapshot the current value
  1384. //
  1385. rc = ScepSaveRegistryValue(
  1386. hSection,
  1387. pOneRegValue->FullValueName,
  1388. REG_DWORD,
  1389. (PWSTR)&RegData,
  1390. sizeof(DWORD),
  1391. dwStatus
  1392. );
  1393. } // else for the delay filter, only query the reg values configured
  1394. } else if ( (LONG)RegData != _wtol(pOneRegValue->Value) ) {
  1395. rc = ScepSaveRegistryValue(
  1396. hSection,
  1397. pOneRegValue->FullValueName,
  1398. REG_DWORD,
  1399. (PWSTR)&RegData,
  1400. sizeof(DWORD),
  1401. 0
  1402. );
  1403. }
  1404. break;
  1405. case REG_BINARY:
  1406. DWORD nLen;
  1407. if ( pOneRegValue->Value ) {
  1408. nLen = wcslen(pOneRegValue->Value);
  1409. } else {
  1410. nLen = 0;
  1411. }
  1412. if ( pOneRegValue->Value == NULL ||
  1413. (SCEREG_VALUE_SNAPSHOT == dwAnalFlag) ||
  1414. nLen == 0 ) {
  1415. if ( SCEREG_VALUE_SYSTEM == dwAnalFlag ) {
  1416. //
  1417. // add the value to OneRegValue buffer
  1418. //
  1419. rc = ScepSaveRegistryValueToBuffer(
  1420. RegType,
  1421. strValue,
  1422. dSize,
  1423. pOneRegValue
  1424. );
  1425. } else if ( SCEREG_VALUE_FILTER != dwAnalFlag ) {
  1426. //
  1427. // not configured, or snapshot the current value
  1428. //
  1429. rc = ScepSaveRegistryValue(
  1430. hSection,
  1431. pOneRegValue->FullValueName,
  1432. RegType,
  1433. strValue,
  1434. dSize,
  1435. dwStatus
  1436. );
  1437. }
  1438. } else if ( strValue ) {
  1439. DWORD newLen;
  1440. newLen = nLen/2;
  1441. if ( nLen % 2 ) {
  1442. newLen++; // pad a leading 0
  1443. }
  1444. PBYTE pRegBytes = (PBYTE)ScepAlloc(0, newLen);
  1445. if ( pRegBytes ) {
  1446. BYTE dByte;
  1447. for ( INT j=newLen-1; j>=0; j-- ) {
  1448. if ( nLen % 2 ) {
  1449. // odd number of chars
  1450. dByte = (pOneRegValue->Value[j*2]-L'0') % 16;
  1451. if ( j*2 >= 1 ) {
  1452. dByte += ((pOneRegValue->Value[j*2-1]-L'0') % 16) * 16;
  1453. }
  1454. } else {
  1455. // even number of chars
  1456. dByte = (pOneRegValue->Value[j*2+1]-L'0') % 16;
  1457. dByte += ((pOneRegValue->Value[j*2]-L'0') % 16) * 16;
  1458. }
  1459. pRegBytes[j] = dByte;
  1460. }
  1461. if ( memcmp(strValue, pRegBytes, dSize) == 0 ) {
  1462. //
  1463. // matched, do not do anything
  1464. //
  1465. } else {
  1466. //
  1467. // mismatched, save the binary data
  1468. //
  1469. rc = ScepSaveRegistryValue(
  1470. hSection,
  1471. pOneRegValue->FullValueName,
  1472. RegType,
  1473. strValue,
  1474. dSize,
  1475. 0
  1476. );
  1477. }
  1478. ScepFree(pRegBytes);
  1479. } else {
  1480. //
  1481. // out of memory
  1482. //
  1483. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  1484. }
  1485. } else {
  1486. //
  1487. // mismatched, save the binary data
  1488. //
  1489. rc = ScepSaveRegistryValue(
  1490. hSection,
  1491. pOneRegValue->FullValueName,
  1492. RegType,
  1493. strValue,
  1494. dSize,
  1495. 0
  1496. );
  1497. }
  1498. break;
  1499. case REG_MULTI_SZ:
  1500. case REG_QWORD:
  1501. if ( strValue ) {
  1502. if ( !(RegType == REG_MULTI_SZ &&
  1503. (0 == _wcsicmp( pOneRegValue->FullValueName, szLegalNoticeTextKeyName) ) ) ) {
  1504. ScepConvertMultiSzToDelim(strValue, dSize/2, L'\0', L',');
  1505. }
  1506. else {
  1507. DWORD dwCommaCount = 0;
  1508. PWSTR strValueNew;
  1509. DWORD dwBytes;
  1510. for (DWORD dwIndex=0; dwIndex < dSize/2; dwIndex++) {
  1511. if ( strValue[dwIndex] == L',' )
  1512. dwCommaCount++;
  1513. }
  1514. dwBytes = (dSize/2+dwCommaCount * 2 + 1) * sizeof(WCHAR);
  1515. strValueNew = (PWSTR)ScepAlloc(0, dwBytes);
  1516. if (strValueNew) {
  1517. memset(strValueNew, '\0', dwBytes);
  1518. dSize = 2 + 2 * ScepEscapeAndRemoveCRLF( strValue, dSize/2, strValueNew);
  1519. ScepFree(strValue);
  1520. strValue = strValueNew;
  1521. }
  1522. else {
  1523. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  1524. break;
  1525. }
  1526. }
  1527. }
  1528. // fall through
  1529. default:
  1530. if ( pOneRegValue->Value == NULL ||
  1531. (SCEREG_VALUE_SNAPSHOT == dwAnalFlag) ) {
  1532. if ( SCEREG_VALUE_SYSTEM == dwAnalFlag ) {
  1533. //
  1534. // add the value to OneRegValue buffer
  1535. //
  1536. rc = ScepSaveRegistryValueToBuffer(
  1537. RegType,
  1538. strValue,
  1539. dSize,
  1540. pOneRegValue
  1541. );
  1542. } else if ( SCEREG_VALUE_FILTER != dwAnalFlag ) {
  1543. rc = ScepSaveRegistryValue(
  1544. hSection,
  1545. pOneRegValue->FullValueName,
  1546. RegType,
  1547. strValue,
  1548. dSize,
  1549. dwStatus
  1550. );
  1551. }
  1552. } else if ( strValue && bIsLegalNoticeText &&
  1553. (pOneRegValue->ValueType != RegType)) {
  1554. //
  1555. // legalnotice text special case
  1556. // must be old template is used
  1557. // each comma is escaped with two quotes
  1558. //
  1559. DWORD Len = wcslen(pOneRegValue->Value);
  1560. PWSTR NewValue = (PWSTR)ScepAlloc(LPTR, Len*3*sizeof(WCHAR));
  1561. if ( NewValue ) {
  1562. ScepEscapeAndRemoveCRLF(pOneRegValue->Value, Len, NewValue);
  1563. if ( _wcsicmp(NewValue, strValue) != 0 ) {
  1564. //
  1565. // mismatched, save the item to the database
  1566. //
  1567. rc = ScepSaveRegistryValue(
  1568. hSection,
  1569. pOneRegValue->FullValueName,
  1570. RegType,
  1571. strValue,
  1572. dSize,
  1573. 0
  1574. );
  1575. }
  1576. ScepFree(NewValue);
  1577. } else {
  1578. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  1579. }
  1580. } else if ( strValue &&
  1581. _wcsicmp(pOneRegValue->Value, strValue) == 0 ) {
  1582. //
  1583. // matched, do not do anything
  1584. //
  1585. } else {
  1586. //
  1587. // mismatched, save the item to the database
  1588. //
  1589. rc = ScepSaveRegistryValue(
  1590. hSection,
  1591. pOneRegValue->FullValueName,
  1592. RegType,
  1593. strValue,
  1594. dSize,
  1595. 0
  1596. );
  1597. }
  1598. break;
  1599. }
  1600. rc = ScepSceStatusToDosError(rc);
  1601. } else {
  1602. //
  1603. // error analyzing the value, or it doesn't exist, save it
  1604. // if the registry value doesn't exist, doesn't mean it's 0
  1605. // just log an "not available" status in this case
  1606. //
  1607. if ( (SCEREG_VALUE_ANALYZE == dwAnalFlag) ||
  1608. (SCEREG_VALUE_ROLLBACK == dwAnalFlag) ) {
  1609. ScepSaveRegistryValue(
  1610. hSection,
  1611. pOneRegValue->FullValueName,
  1612. (SCEREG_VALUE_ANALYZE == dwAnalFlag) ? pOneRegValue->ValueType : -1,
  1613. NULL,
  1614. 0,
  1615. (SCEREG_VALUE_ANALYZE == dwAnalFlag) ? SCE_STATUS_ERROR_NOT_AVAILABLE : 0
  1616. );
  1617. }
  1618. if ( rc == ERROR_FILE_NOT_FOUND ||
  1619. rc == ERROR_PATH_NOT_FOUND ||
  1620. rc == ERROR_INVALID_HANDLE ||
  1621. rc == ERROR_ACCESS_DENIED ) {
  1622. rc = ERROR_SUCCESS;
  1623. }
  1624. }
  1625. //
  1626. // free buffer
  1627. //
  1628. if ( strValue ) {
  1629. ScepFree(strValue);
  1630. strValue = NULL;
  1631. }
  1632. return(rc);
  1633. }
  1634. SCESTATUS
  1635. ScepSaveRegistryValue(
  1636. IN PSCESECTION hSection,
  1637. IN PWSTR Name,
  1638. IN DWORD RegType,
  1639. IN PWSTR CurrentValue,
  1640. IN DWORD CurrentBytes,
  1641. IN DWORD Status
  1642. )
  1643. /* ++
  1644. Routine Description:
  1645. This routine compares system settings in string with the baseline profile
  1646. settings. If there is mismatch or unknown, the entry is saved in the SAP
  1647. profile.
  1648. Arguments:
  1649. hSection - The section handle
  1650. Name - The entry name
  1651. RegType - the registry value type
  1652. CurrentValue - The current system setting
  1653. CurrentBytes - The length of the current setting
  1654. Status - the status of this registry vlue analyzed
  1655. Return Value:
  1656. SCESTATUS_SUCCESS
  1657. SCESTATUS_INVALID_PARAMETER
  1658. SCESTATUS returned from SceJetSetLine
  1659. -- */
  1660. {
  1661. SCESTATUS rc;
  1662. if ( Name == NULL )
  1663. return(SCESTATUS_INVALID_PARAMETER);
  1664. if ( CurrentValue == NULL &&
  1665. REG_DWORD == RegType &&
  1666. Status == 0 ) {
  1667. //
  1668. // only return if it's a DWORD type and saving for mismatch status
  1669. // for other types, NULL should be treated as ""
  1670. return(SCESTATUS_SUCCESS);
  1671. }
  1672. //
  1673. // build a buffer containing type and value
  1674. // note MULTI_SZ must be converted to null delimited
  1675. //
  1676. if ( REG_DWORD == RegType ) {
  1677. TCHAR StrValue[20];
  1678. memset(StrValue, '\0', 40);
  1679. *((CHAR *)StrValue) = (BYTE)RegType + '0';
  1680. if ( Status == 0) {
  1681. *((CHAR *)StrValue+1) = SCE_STATUS_MISMATCH + '0';
  1682. } else {
  1683. *((CHAR *)StrValue+1) = (BYTE)Status + '0';
  1684. }
  1685. StrValue[1] = L'\0';
  1686. if ( CurrentValue ) {
  1687. swprintf(StrValue+2, L"%d", *CurrentValue);
  1688. }
  1689. rc = SceJetSetLine( hSection, Name, FALSE, StrValue, (2+wcslen(StrValue+2))*2, 0);
  1690. } else {
  1691. PWSTR StrValue;
  1692. if ( (CurrentBytes % 2) && REG_BINARY == RegType ) {
  1693. StrValue = (PWSTR)ScepAlloc(0, CurrentBytes+9);
  1694. }
  1695. else {
  1696. StrValue = (PWSTR)ScepAlloc(0, CurrentBytes+8); // 4 wide chars: one for type, one delim, and two NULL
  1697. }
  1698. if ( StrValue ) {
  1699. memset(StrValue, 0, sizeof(StrValue));
  1700. *((CHAR *)StrValue) = (BYTE)RegType + '0';
  1701. if ( Status == 0) {
  1702. *((CHAR *)StrValue+1) = SCE_STATUS_MISMATCH + '0';
  1703. } else {
  1704. *((CHAR *)StrValue+1) = (BYTE)Status + '0';
  1705. }
  1706. StrValue[1] = L'\0';
  1707. if ( CurrentValue ) {
  1708. if (REG_BINARY == RegType && CurrentBytes == 1) {
  1709. swprintf(StrValue+2, L"%d", *CurrentValue);
  1710. }
  1711. else {
  1712. memcpy(StrValue+2, (PBYTE)CurrentValue, CurrentBytes);
  1713. }
  1714. }
  1715. if ( (CurrentBytes % 2) && REG_BINARY == RegType ) {
  1716. StrValue[CurrentBytes/2+3] = L'\0';
  1717. StrValue[CurrentBytes/2+4] = L'\0';
  1718. }
  1719. else {
  1720. StrValue[CurrentBytes/2+2] = L'\0';
  1721. StrValue[CurrentBytes/2+3] = L'\0';
  1722. }
  1723. if ( REG_MULTI_SZ == RegType || REG_QWORD == RegType ) {
  1724. //
  1725. // convert the , to null
  1726. //
  1727. ScepConvertMultiSzToDelim(StrValue+2, CurrentBytes/2, L',', L'\0');
  1728. }
  1729. if ( (CurrentBytes % 2) && REG_BINARY == RegType ) {
  1730. rc = SceJetSetLine( hSection, Name, FALSE, StrValue, CurrentBytes+7, 0);
  1731. }
  1732. else {
  1733. rc = SceJetSetLine( hSection, Name, FALSE, StrValue, CurrentBytes+6, 0);
  1734. }
  1735. ScepFree(StrValue);
  1736. } else {
  1737. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  1738. }
  1739. }
  1740. switch (Status) {
  1741. case SCE_STATUS_ERROR_NOT_AVAILABLE:
  1742. ScepLogOutput3(2, 0, SCEDLL_STATUS_ERROR, Name);
  1743. break;
  1744. case SCE_STATUS_NOT_CONFIGURED:
  1745. ScepLogOutput3(2, 0, SCEDLL_STATUS_NC, Name);
  1746. break;
  1747. default:
  1748. ScepLogOutput3(2, 0, SCEDLL_STATUS_MISMATCH, Name);
  1749. break;
  1750. }
  1751. return(rc);
  1752. }
  1753. SCESTATUS
  1754. ScepSaveRegistryValueToBuffer(
  1755. IN DWORD RegType,
  1756. IN PWSTR Value,
  1757. IN DWORD dwBytes,
  1758. IN OUT PSCE_REGISTRY_VALUE_INFO pRegValues
  1759. )
  1760. /* ++
  1761. Routine Description:
  1762. This routine saves the registry value to the buffer
  1763. Arguments:
  1764. RegType - the registry value type
  1765. Value - The current system setting
  1766. dwBytes - The length of the current setting
  1767. pRegValues - the buffer for this registry value to save to
  1768. -- */
  1769. {
  1770. SCESTATUS rc=SCESTATUS_SUCCESS;
  1771. if ( pRegValues == NULL ) {
  1772. return(SCESTATUS_INVALID_PARAMETER);
  1773. }
  1774. if ( Value == NULL || dwBytes == 0 ) {
  1775. // nothing to save
  1776. return(SCESTATUS_SUCCESS);
  1777. }
  1778. //
  1779. // build a buffer containing type and value
  1780. // note MULTI_SZ must be converted to null delimited
  1781. //
  1782. if ( REG_DWORD == RegType ) {
  1783. TCHAR StrValue[20];
  1784. DWORD *pdwValue = (DWORD *)Value;
  1785. memset(StrValue, '\0', 40);
  1786. _ultow(*pdwValue, StrValue, 10);
  1787. PWSTR pValue = (PWSTR)ScepAlloc(0, (wcslen(StrValue)+1)*2);
  1788. if ( pValue ) {
  1789. wcscpy(pValue, StrValue);
  1790. pRegValues->Value = pValue;
  1791. pRegValues->ValueType = RegType;
  1792. } else {
  1793. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  1794. }
  1795. } else {
  1796. PWSTR StrValue;
  1797. if ( (dwBytes % 2) && REG_BINARY == RegType ) {
  1798. StrValue = (PWSTR)ScepAlloc(LPTR, dwBytes+5);
  1799. } else {
  1800. StrValue = (PWSTR)ScepAlloc(LPTR, dwBytes+4); // 2 wide chars: two NULL
  1801. }
  1802. if ( StrValue ) {
  1803. if (REG_BINARY == RegType && dwBytes == 1) {
  1804. swprintf(StrValue, L"%d", *Value);
  1805. } else {
  1806. memcpy(StrValue, (PBYTE)Value, dwBytes);
  1807. }
  1808. if ( (dwBytes % 2) && REG_BINARY == RegType ) {
  1809. StrValue[dwBytes/2+1] = L'\0';
  1810. StrValue[dwBytes/2+2] = L'\0';
  1811. }
  1812. else {
  1813. StrValue[dwBytes/2+0] = L'\0';
  1814. StrValue[dwBytes/2+1] = L'\0';
  1815. }
  1816. pRegValues->Value = StrValue;
  1817. pRegValues->ValueType = RegType;
  1818. } else {
  1819. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  1820. }
  1821. }
  1822. return(rc);
  1823. }
  1824. SCESTATUS
  1825. ScepEnumAllRegValues(
  1826. IN OUT PDWORD pCount,
  1827. IN OUT PSCE_REGISTRY_VALUE_INFO *paRegValues
  1828. )
  1829. /*
  1830. Routine Description:
  1831. Enumerate all registry values supported by SCE from registry.
  1832. Arguments:
  1833. pCount - the number of reg values to output
  1834. paRegValues - the array of registry values to output
  1835. Return Value:
  1836. */
  1837. {
  1838. DWORD Win32Rc;
  1839. HKEY hKey=NULL;
  1840. PSCE_NAME_STATUS_LIST pnsList=NULL;
  1841. DWORD nAdded=0;
  1842. Win32Rc = RegOpenKeyEx(
  1843. HKEY_LOCAL_MACHINE,
  1844. SCE_ROOT_REGVALUE_PATH,
  1845. 0,
  1846. KEY_READ,
  1847. &hKey
  1848. );
  1849. DWORD cSubKeys = 0;
  1850. DWORD nMaxLen;
  1851. if ( Win32Rc == ERROR_SUCCESS ) {
  1852. //
  1853. // enumerate all subkeys of the key
  1854. //
  1855. Win32Rc = RegQueryInfoKey (
  1856. hKey,
  1857. NULL,
  1858. NULL,
  1859. NULL,
  1860. &cSubKeys,
  1861. &nMaxLen,
  1862. NULL,
  1863. NULL,
  1864. NULL,
  1865. NULL,
  1866. NULL,
  1867. NULL
  1868. );
  1869. }
  1870. if ( Win32Rc == ERROR_SUCCESS && cSubKeys > 0 ) {
  1871. PWSTR szName = (PWSTR)ScepAlloc(0, (nMaxLen+2)*sizeof(WCHAR));
  1872. if ( !szName ) {
  1873. Win32Rc = ERROR_NOT_ENOUGH_MEMORY;
  1874. } else {
  1875. DWORD BufSize;
  1876. DWORD index = 0;
  1877. do {
  1878. BufSize = nMaxLen+1;
  1879. Win32Rc = RegEnumKeyEx(
  1880. hKey,
  1881. index,
  1882. szName,
  1883. &BufSize,
  1884. NULL,
  1885. NULL,
  1886. NULL,
  1887. NULL);
  1888. if ( ERROR_SUCCESS == Win32Rc ) {
  1889. index++;
  1890. //
  1891. // get the full registry key name and Valuetype
  1892. //
  1893. cSubKeys = REG_SZ;
  1894. //
  1895. // query ValueType, if error, default REG_SZ
  1896. //
  1897. ScepRegQueryIntValue( hKey,
  1898. szName,
  1899. SCE_REG_VALUE_TYPE,
  1900. &cSubKeys
  1901. );
  1902. if ( cSubKeys < REG_SZ || cSubKeys > REG_MULTI_SZ ) {
  1903. cSubKeys = REG_SZ;
  1904. }
  1905. //
  1906. // convert the path name
  1907. //
  1908. ScepConvertMultiSzToDelim(szName, BufSize, L'/', L'\\');
  1909. //
  1910. // compare with the input array, if not exist,
  1911. // add it
  1912. //
  1913. for ( DWORD i=0; i<*pCount; i++ ) {
  1914. if ( (*paRegValues)[i].FullValueName &&
  1915. _wcsicmp(szName, (*paRegValues)[i].FullValueName) == 0 ) {
  1916. break;
  1917. }
  1918. }
  1919. if ( i >= *pCount ) {
  1920. //
  1921. // did not find a match, add it
  1922. //
  1923. if ( SCESTATUS_SUCCESS != ScepAddToNameStatusList(&pnsList,
  1924. szName,
  1925. BufSize,
  1926. cSubKeys) ) {
  1927. Win32Rc = ERROR_NOT_ENOUGH_MEMORY;
  1928. break;
  1929. }
  1930. nAdded++;
  1931. }
  1932. } else if ( ERROR_NO_MORE_ITEMS != Win32Rc ) {
  1933. break;
  1934. }
  1935. } while ( Win32Rc != ERROR_NO_MORE_ITEMS );
  1936. if ( Win32Rc == ERROR_NO_MORE_ITEMS ) {
  1937. Win32Rc = ERROR_SUCCESS;
  1938. }
  1939. //
  1940. // free the enumeration buffer
  1941. //
  1942. ScepFree(szName);
  1943. }
  1944. }
  1945. if ( hKey ) {
  1946. RegCloseKey(hKey);
  1947. }
  1948. if ( ERROR_SUCCESS == Win32Rc ) {
  1949. //
  1950. // add the name list to the output arrays
  1951. //
  1952. DWORD nNewCount = *pCount + nAdded;
  1953. PSCE_REGISTRY_VALUE_INFO aNewArray;
  1954. if ( nNewCount ) {
  1955. aNewArray = (PSCE_REGISTRY_VALUE_INFO)ScepAlloc(0, nNewCount*sizeof(SCE_REGISTRY_VALUE_INFO));
  1956. if ( aNewArray ) {
  1957. DWORD i;
  1958. for ( i=0; i<*pCount; i++ ) {
  1959. aNewArray[i].FullValueName = (*paRegValues)[i].FullValueName;
  1960. aNewArray[i].Value = (*paRegValues)[i].Value;
  1961. aNewArray[i].ValueType = (*paRegValues)[i].ValueType;
  1962. }
  1963. i=0;
  1964. for ( PSCE_NAME_STATUS_LIST pns=pnsList;
  1965. pns; pns=pns->Next ) {
  1966. if ( pns->Name && i < nAdded ) {
  1967. aNewArray[*pCount+i].FullValueName = pns->Name;
  1968. pns->Name = NULL;
  1969. aNewArray[*pCount+i].Value = NULL;
  1970. aNewArray[*pCount+i].ValueType = pns->Status;
  1971. i++;
  1972. }
  1973. }
  1974. //
  1975. // free the original array
  1976. // all components in the array are already transferred to the new array
  1977. //
  1978. ScepFree(*paRegValues);
  1979. *pCount = nNewCount;
  1980. *paRegValues = aNewArray;
  1981. } else {
  1982. Win32Rc = ERROR_NOT_ENOUGH_MEMORY;
  1983. }
  1984. }
  1985. }
  1986. if ( ERROR_FILE_NOT_FOUND == Win32Rc ||
  1987. ERROR_PATH_NOT_FOUND == Win32Rc ) {
  1988. //
  1989. // no value has been registered
  1990. //
  1991. Win32Rc = ERROR_SUCCESS;
  1992. }
  1993. //
  1994. // free the name status list
  1995. //
  1996. SceFreeMemory(pnsList, SCE_STRUCT_NAME_STATUS_LIST);
  1997. return( ScepDosErrorToSceStatus(Win32Rc) );
  1998. }