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.

8418 lines
254 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. spconfig.c
  5. Abstract:
  6. Registry manipulation routines
  7. Author:
  8. Vijay Jayaseelan (vijayj@microsoft.com) 16 May 2001
  9. Revision History:
  10. None.
  11. --*/
  12. #include "spprecmp.h"
  13. #pragma hdrstop
  14. #include <initguid.h>
  15. #include <devguid.h>
  16. //
  17. // The following two are defined in winlogon\setup.h, but we
  18. // cannot include setup.h so we are putting these two values here
  19. //
  20. #define SETUPTYPE_FULL 1
  21. #define SETUPTYPE_UPGRADE 4
  22. PWSTR LOCAL_MACHINE_KEY_NAME = L"\\registry\\machine";
  23. PWSTR SETUP_KEY_NAME = L"setup";
  24. PWSTR ATDISK_NAME = L"atdisk";
  25. PWSTR ABIOSDISK_NAME = L"abiosdsk";
  26. PWSTR PRIMARY_DISK_GROUP = L"Primary disk";
  27. PWSTR VIDEO_GROUP = L"Video";
  28. PWSTR KEYBOARD_PORT_GROUP = L"Keyboard Port";
  29. PWSTR POINTER_PORT_GROUP = L"Pointer Port";
  30. PWSTR DEFAULT_EVENT_LOG = L"%SystemRoot%\\System32\\IoLogMsg.dll";
  31. PWSTR CODEPAGE_NAME = L"CodePage";
  32. PWSTR UPGRADE_IN_PROGRESS = L"UpgradeInProgress";
  33. PWSTR VIDEO_DEVICE0 = L"Device0";
  34. PWSTR SESSION_MANAGER_KEY = L"Control\\Session Manager";
  35. PWSTR BOOT_EXECUTE = L"BootExecute";
  36. PWSTR RESTART_SETUP = L"RestartSetup";
  37. PWSTR PRODUCT_OPTIONS_KEY_NAME = L"ProductOptions";
  38. PWSTR PRODUCT_SUITE_VALUE_NAME = L"ProductSuite";
  39. PWSTR SP_SERVICES_TO_DISABLE = L"ServicesToDisable";
  40. PWSTR SP_UPPER_FILTERS = L"UpperFilters";
  41. PWSTR SP_LOWER_FILTERS = L"LowerFilters";
  42. PWSTR SP_MATCHING_DEVICE_ID = L"MatchingDeviceId";
  43. PWSTR SP_CONTROL_CLASS_KEY = L"Control\\Class";
  44. PWSTR SP_CLASS_GUID_VALUE_NAME = L"ClassGUID";
  45. PWSTR ProductSuiteNames[] =
  46. {
  47. L"Small Business",
  48. L"Enterprise",
  49. L"BackOffice",
  50. L"CommunicationServer",
  51. L"Terminal Server",
  52. L"Small Business(Restricted)",
  53. L"EmbeddedNT",
  54. L"DataCenter",
  55. NULL, // This is a placeholder for Single User TS - not actually a suite but the bit position is defined in ntdef.h
  56. L"Personal",
  57. L"Blade"
  58. };
  59. #define CountProductSuiteNames (sizeof(ProductSuiteNames)/sizeof(PWSTR))
  60. #define MAX_PRODUCT_SUITE_BYTES 1024
  61. extern BOOLEAN DriveAssignFromA; //NEC98
  62. NTSTATUS
  63. SpSavePreinstallList(
  64. IN PVOID SifHandle,
  65. IN PWSTR SystemRoot,
  66. IN HANDLE hKeySystemHive
  67. );
  68. NTSTATUS
  69. SpDoRegistryInitialization(
  70. IN PVOID SifHandle,
  71. IN PDISK_REGION TargetRegion,
  72. IN PWSTR PartitionPath,
  73. IN PWSTR SystemRoot,
  74. IN HANDLE *HiveRootKeys,
  75. IN PWSTR SetupSourceDevicePath,
  76. IN PWSTR DirectoryOnSourceDevice,
  77. IN PWSTR SpecialDevicePath, OPTIONAL
  78. IN HANDLE ControlSet
  79. );
  80. NTSTATUS
  81. SpFormSetupCommandLine(
  82. IN PVOID SifHandle,
  83. IN HANDLE hKeySystemHive,
  84. IN PWSTR SetupSourceDevicePath,
  85. IN PWSTR DirectoryOnSourceDevice,
  86. IN PWSTR FullTargetPath,
  87. IN PWSTR SpecialDevicePath OPTIONAL
  88. );
  89. NTSTATUS
  90. SpDriverLoadList(
  91. IN PVOID SifHandle,
  92. IN PWSTR SystemRoot,
  93. IN HANDLE hKeySystemHive,
  94. IN HANDLE hKeyControlSet
  95. );
  96. NTSTATUS
  97. SpSaveSKUStuff(
  98. IN HANDLE hKeySystemHive
  99. );
  100. NTSTATUS
  101. SpWriteVideoParameters(
  102. IN PVOID SifHandle,
  103. IN HANDLE hKeyControlSetServices
  104. );
  105. NTSTATUS
  106. SpConfigureNlsParameters(
  107. IN PVOID SifHandle,
  108. IN HANDLE hKeyDefaultHive,
  109. IN HANDLE hKeyControlSetControl
  110. );
  111. NTSTATUS
  112. SpCreateCodepageEntry(
  113. IN PVOID SifHandle,
  114. IN HANDLE hKeyNls,
  115. IN PWSTR SubkeyName,
  116. IN PWSTR SifNlsSectionKeyName,
  117. IN PWSTR EntryName
  118. );
  119. NTSTATUS
  120. SpConfigureFonts(
  121. IN PVOID SifHandle,
  122. IN HANDLE hKeySoftwareHive
  123. );
  124. NTSTATUS
  125. SpStoreHwInfoForSetup(
  126. IN HANDLE hKeyControlSetControl
  127. );
  128. NTSTATUS
  129. SpConfigureMouseKeyboardDrivers(
  130. IN PVOID SifHandle,
  131. IN ULONG HwComponent,
  132. IN PWSTR ClassServiceName,
  133. IN HANDLE hKeyControlSetServices,
  134. IN PWSTR ServiceGroup
  135. );
  136. NTSTATUS
  137. SpCreateServiceEntryIndirect(
  138. IN HANDLE hKeyControlSetServices,
  139. IN PVOID SifHandle, OPTIONAL
  140. IN PWSTR SifSectionName, OPTIONAL
  141. IN PWSTR KeyName,
  142. IN ULONG ServiceType,
  143. IN ULONG ServiceStart,
  144. IN PWSTR ServiceGroup, OPTIONAL
  145. IN ULONG ServiceError,
  146. IN PWSTR FileName, OPTIONAL
  147. OUT PHANDLE SubkeyHandle OPTIONAL
  148. );
  149. NTSTATUS
  150. SpThirdPartyRegistry(
  151. IN PVOID hKeyControlSetServices
  152. );
  153. NTSTATUS
  154. SpGetCurrentControlSetNumber(
  155. IN HANDLE SystemHiveRoot,
  156. OUT PULONG Number
  157. );
  158. NTSTATUS
  159. SpCreateControlSetSymbolicLink(
  160. IN HANDLE SystemHiveRoot,
  161. OUT HANDLE *CurrentControlSetRoot
  162. );
  163. NTSTATUS
  164. SpAppendStringToMultiSz(
  165. IN HANDLE hKey,
  166. IN PWSTR Subkey,
  167. IN PWSTR ValueName,
  168. IN PWSTR StringToAdd
  169. );
  170. NTSTATUS
  171. SpGetValueKey(
  172. IN HANDLE hKeyRoot,
  173. IN PWSTR KeyName,
  174. IN PWSTR ValueName,
  175. IN ULONG BufferLength,
  176. OUT PUCHAR Buffer,
  177. OUT PULONG ResultLength
  178. );
  179. NTSTATUS
  180. SpPostprocessHives(
  181. IN PWSTR PartitionPath,
  182. IN PWSTR Sysroot,
  183. IN PCWSTR *HiveNames,
  184. IN HANDLE *HiveRootKeys,
  185. IN unsigned HiveCount,
  186. IN HANDLE hkeyCCS
  187. );
  188. NTSTATUS
  189. SpSaveSetupPidList(
  190. IN HANDLE hKeySystemHive
  191. );
  192. NTSTATUS
  193. SpSavePageFileInfo(
  194. IN HANDLE hKeyCCSetControl,
  195. IN HANDLE hKeySystemHive
  196. );
  197. NTSTATUS
  198. SpSetPageFileInfo(
  199. IN PVOID SifHandle,
  200. IN HANDLE hKeyCCSetControl,
  201. IN HANDLE hKeySystemHive
  202. );
  203. NTSTATUS
  204. SpGetProductSuiteMask(
  205. IN HANDLE hKeyControlSetControl,
  206. OUT PULONG SuiteMask
  207. );
  208. NTSTATUS
  209. SpSetProductSuite(
  210. IN HANDLE hKeyControlSetControl,
  211. IN ULONG SuiteMask
  212. );
  213. NTSTATUS
  214. SppMigrateFtKeys(
  215. IN HANDLE hDestSystemHive
  216. );
  217. NTSTATUS
  218. SpMigrateSetupKeys(
  219. IN PWSTR PartitionPath,
  220. IN PWSTR SystemRoot,
  221. IN HANDLE hDestLocalMachine,
  222. IN PVOID SifHandle
  223. );
  224. NTSTATUS
  225. SppDisableDynamicVolumes(
  226. IN HANDLE hCCSet
  227. );
  228. NTSTATUS
  229. SppCleanupKeysFromRemoteInstall(
  230. VOID
  231. );
  232. NTSTATUS
  233. SpDisableUnsupportedScsiDrivers(
  234. IN HANDLE hKeyControlSet
  235. );
  236. NTSTATUS
  237. SpAppendPathToDevicePath(
  238. IN HANDLE hKeySoftwareHive,
  239. IN PWSTR OemPnpDriversDirPath
  240. );
  241. NTSTATUS
  242. SpAppendFullPathListToDevicePath (
  243. IN HANDLE hKeySoftwareHive,
  244. IN PWSTR PnpDriverFullPathList
  245. );
  246. NTSTATUS
  247. SpUpdateDeviceInstanceData(
  248. IN HANDLE ControlSet
  249. );
  250. NTSTATUS
  251. SpCleanUpHive(
  252. VOID
  253. );
  254. NTSTATUS
  255. SpProcessServicesToDisable(
  256. IN PVOID WinntSifHandle,
  257. IN PWSTR SectionName,
  258. IN HANDLE SystemKey
  259. );
  260. NTSTATUS
  261. SpDeleteRequiredDeviceInstanceFilters(
  262. IN HANDLE CCSHandle
  263. );
  264. #if defined(REMOTE_BOOT)
  265. NTSTATUS
  266. SpCopyRemoteBootKeyword(
  267. IN PVOID SifHandle,
  268. IN PWSTR KeywordName,
  269. IN HANDLE hKeyCCSetControl
  270. );
  271. #endif // defined(REMOTE_BOOT)
  272. #define STRING_VALUE(s) REG_SZ,(s),(wcslen((s))+1)*sizeof(WCHAR)
  273. #define ULONG_VALUE(u) REG_DWORD,&(u),sizeof(ULONG)
  274. //
  275. // List of oem inf files installed as part of the installation of third party drivers
  276. //
  277. extern POEM_INF_FILE OemInfFileList;
  278. //
  279. // Name of the directory where OEM files need to be copied, if a catalog file (.cat) is part of
  280. // the third party driver package that the user provide using the F6 or F5 key.
  281. //
  282. extern PWSTR OemDirName;
  283. VOID
  284. SpInitializeRegistry(
  285. IN PVOID SifHandle,
  286. IN PDISK_REGION TargetRegion,
  287. IN PWSTR SystemRoot,
  288. IN PWSTR SetupSourceDevicePath,
  289. IN PWSTR DirectoryOnSourceDevice,
  290. IN PWSTR SpecialDevicePath OPTIONAL,
  291. IN PDISK_REGION SystemPartitionRegion
  292. )
  293. {
  294. OBJECT_ATTRIBUTES ObjectAttributes;
  295. UNICODE_STRING UnicodeString;
  296. NTSTATUS Status;
  297. PWSTR pwstrTemp1,pwstrTemp2;
  298. int h;
  299. ULONG Disposition;
  300. LPCWSTR HiveNames[SetupHiveMax] = { L"system",L"software",L"default",L"userdiff" };
  301. HANDLE HiveRootKeys[SetupHiveMax] = { NULL ,NULL ,NULL ,NULL };
  302. PWSTR PartitionPath;
  303. HANDLE FileHandle;
  304. HANDLE KeyHandle;
  305. IO_STATUS_BLOCK IoStatusBlock;
  306. //
  307. // Put up a screen telling the user what we are doing.
  308. //
  309. SpStartScreen(
  310. SP_SCRN_DOING_REG_CONFIG,
  311. 0,
  312. 8,
  313. TRUE,
  314. FALSE,
  315. DEFAULT_ATTRIBUTE
  316. );
  317. SpDisplayStatusText(SP_STAT_REG_LOADING_HIVES,DEFAULT_STATUS_ATTRIBUTE);
  318. //
  319. // Get the name of the target patition.
  320. //
  321. SpNtNameFromRegion(
  322. TargetRegion,
  323. TemporaryBuffer,
  324. sizeof(TemporaryBuffer),
  325. PartitionOrdinalCurrent
  326. );
  327. PartitionPath = SpDupStringW(TemporaryBuffer);
  328. // pwstrTemp2 points half way through the buffer.
  329. pwstrTemp1 = TemporaryBuffer;
  330. pwstrTemp2 = TemporaryBuffer + (sizeof(TemporaryBuffer) / sizeof(WCHAR) / 2);
  331. //
  332. // In the fresh install case, there are no hive files in the target tree.
  333. // We create a key in a known place (\Registry\Machine\System\$$$PROTO.HIV,
  334. // which is 4 levels deep because \Registry\Machine\$$$PROTO.HIV would
  335. // imply a hive called $$$PROTO.HIV and we don't want to get tripped up
  336. // by those semantics). Then we save off that empty key 3 times into
  337. // system32\config to form 3 empty hives.
  338. //
  339. // In the upgrade case this there are actual hives in the target tree
  340. // which we do NOT want to overwrite!
  341. //
  342. // If this is the ASR quick test, we don't want to recreate any of the hives
  343. //
  344. // We also want to create an empty userdiff hive in both the fresh and
  345. // upgrade cases.
  346. //
  347. //
  348. INIT_OBJA(
  349. &ObjectAttributes,
  350. &UnicodeString,
  351. L"\\Registry\\Machine\\System\\$$$PROTO.HIV"
  352. );
  353. Status = ZwCreateKey(
  354. &KeyHandle,
  355. KEY_ALL_ACCESS,
  356. &ObjectAttributes,
  357. 0,
  358. NULL,
  359. REG_OPTION_NON_VOLATILE,
  360. &Disposition
  361. );
  362. if(!NT_SUCCESS(Status)) {
  363. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: unable to create root key for protohive (%lx)\n",Status));
  364. } else {
  365. ASSERT(SetupHiveUserdiff == SetupHiveMax-1);
  366. if (ASRMODE_QUICKTEST_FULL != SpAsrGetAsrMode()) {
  367. for(h = ((NTUpgrade == UpgradeFull) ? SetupHiveUserdiff : 0);
  368. NT_SUCCESS(Status) && (h < SetupHiveMax);
  369. h++) {
  370. //
  371. // Form full pathname to the hive we want to create.
  372. // Then create the file.
  373. //
  374. wcscpy(pwstrTemp1,PartitionPath);
  375. SpConcatenatePaths(pwstrTemp1,SystemRoot);
  376. SpConcatenatePaths(pwstrTemp1,L"SYSTEM32\\CONFIG");
  377. SpConcatenatePaths(pwstrTemp1,HiveNames[h]);
  378. SpDeleteFile(pwstrTemp1,NULL,NULL); // Make sure that we get rid of the file if it has attributes.
  379. INIT_OBJA(&ObjectAttributes,&UnicodeString,pwstrTemp1);
  380. Status = ZwCreateFile(
  381. &FileHandle,
  382. FILE_GENERIC_WRITE,
  383. &ObjectAttributes,
  384. &IoStatusBlock,
  385. NULL,
  386. FILE_ATTRIBUTE_NORMAL,
  387. 0, // no sharing
  388. FILE_OVERWRITE_IF,
  389. FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
  390. NULL,
  391. 0
  392. );
  393. if(!NT_SUCCESS(Status)) {
  394. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: unable to create file %ws for protohive (%lx)\n",pwstrTemp1,Status));
  395. } else {
  396. //
  397. // Save the empty key we created above into the file
  398. // we just created. This creates an empty hive.
  399. // Call the Ex version to make sure the hive is in the latest format
  400. //
  401. Status = ZwSaveKeyEx(KeyHandle,FileHandle,REG_LATEST_FORMAT);
  402. if(!NT_SUCCESS(Status)) {
  403. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: unable to save empty key to protohive %ws (%lx)\n",pwstrTemp1,Status));
  404. }
  405. ZwClose(FileHandle);
  406. }
  407. }
  408. }
  409. ZwDeleteKey(KeyHandle);
  410. ZwClose(KeyHandle);
  411. }
  412. //
  413. // Now we have hives in both the upgrade and fresh install cases.
  414. // Load them up. We use the convention that a hive is loaded into
  415. // \Registry\Machine\x<hivename>.
  416. //
  417. for(h=0; NT_SUCCESS(Status) && (h<SetupHiveMax); h++) {
  418. swprintf(pwstrTemp1,L"%ws\\x%ws",LOCAL_MACHINE_KEY_NAME,HiveNames[h]);
  419. wcscpy(pwstrTemp2,PartitionPath);
  420. SpConcatenatePaths(pwstrTemp2,SystemRoot);
  421. SpConcatenatePaths(pwstrTemp2,L"SYSTEM32\\CONFIG");
  422. SpConcatenatePaths(pwstrTemp2,HiveNames[h]);
  423. Status = SpLoadUnloadKey(NULL,NULL,pwstrTemp1,pwstrTemp2);
  424. if(!NT_SUCCESS(Status)) {
  425. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: load hive %ws into %ws failed (%lx)\n",pwstrTemp2,pwstrTemp1,Status));
  426. } else {
  427. INIT_OBJA(&ObjectAttributes,&UnicodeString,pwstrTemp1);
  428. Status = ZwOpenKey(&HiveRootKeys[h],KEY_ALL_ACCESS,&ObjectAttributes);
  429. if(!NT_SUCCESS(Status)) {
  430. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: open root key %ws failed (%lx)\n",pwstrTemp1,Status));
  431. }
  432. }
  433. }
  434. //
  435. // Make a symbolic link such that CurrentControlSet is valid.
  436. // This allows references in infs to work in either the fresh install case,
  437. // where we're always dealing with ControlSet001, or in the upgrade case,
  438. // where the control set we're dealing with is dictated by the state of
  439. // the existing registry.
  440. //
  441. if(NT_SUCCESS(Status)) {
  442. Status = SpCreateControlSetSymbolicLink(HiveRootKeys[SetupHiveSystem],&KeyHandle);
  443. if(!NT_SUCCESS(Status)) {
  444. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to create ccs symbolic link (%lx)\n",Status));
  445. }
  446. }
  447. //
  448. // Go do registry initialization.
  449. //
  450. if(NT_SUCCESS(Status)) {
  451. SpDisplayStatusText(SP_STAT_REG_DOING_HIVES,DEFAULT_STATUS_ATTRIBUTE);
  452. Status = SpDoRegistryInitialization(
  453. SifHandle,
  454. TargetRegion,
  455. PartitionPath,
  456. SystemRoot,
  457. HiveRootKeys,
  458. SetupSourceDevicePath,
  459. DirectoryOnSourceDevice,
  460. SpecialDevicePath,
  461. KeyHandle
  462. );
  463. SpDisplayStatusText(SP_STAT_REG_SAVING_HIVES,DEFAULT_STATUS_ATTRIBUTE);
  464. if(NT_SUCCESS(Status)) {
  465. #ifdef _X86_
  466. if (WinUpgradeType == UpgradeWin95) {
  467. //
  468. // NOTE: -- Clean this up.
  469. //
  470. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Migrating disk registry of win9x information.\n"));
  471. Status = SpMigrateDiskRegistry( HiveRootKeys[SetupHiveSystem]);
  472. if (!NT_SUCCESS(Status)) {
  473. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to migrate disk registry.\n"));
  474. }
  475. }
  476. //
  477. // We've set the \\Registry\\Machine\\System\\Setup\\SystemPartition
  478. // value when we did the partitioning code. Now we need to migrate
  479. // that value into the proto hives so they'll be there for
  480. // the reboot.
  481. //
  482. {
  483. #if 0
  484. HANDLE Key;
  485. DWORD ResultLength;
  486. PWSTR SystemPartitionString = 0;
  487. INIT_OBJA(&ObjectAttributes,&UnicodeString,LOCAL_MACHINE_KEY_NAME);
  488. Status = ZwOpenKey(&Key,KEY_READ,&ObjectAttributes);
  489. if(NT_SUCCESS(Status)) {
  490. Status = SpGetValueKey(
  491. Key,
  492. L"System\\Setup",
  493. L"SystemPartition",
  494. sizeof(TemporaryBuffer),
  495. (PCHAR)TemporaryBuffer,
  496. &ResultLength
  497. );
  498. ZwClose(Key);
  499. if(NT_SUCCESS(Status)) {
  500. SystemPartitionString = SpDupStringW( TemporaryBuffer );
  501. if( SystemPartitionString ) {
  502. Status = SpOpenSetValueAndClose( HiveRootKeys[SetupHiveSystem],
  503. SETUP_KEY_NAME,
  504. L"SystemPartition",
  505. STRING_VALUE(SystemPartitionString) );
  506. if(!NT_SUCCESS(Status)) {
  507. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Failed to set SystemPartitionString. (%lx)\n", Status));
  508. }
  509. SpMemFree(SystemPartitionString);
  510. } else {
  511. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Failed to duplicate SystemPartitionString.\n"));
  512. }
  513. } else {
  514. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Failed to query SystemPartition Value.\n"));
  515. }
  516. } else {
  517. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Failed to Open HKLM while trying to query the SytemPartition Value.\n"));
  518. }
  519. #else
  520. PWSTR SystemPartitionString = 0;
  521. SpNtNameFromRegion( SystemPartitionRegion,
  522. TemporaryBuffer,
  523. sizeof(TemporaryBuffer),
  524. PartitionOrdinalCurrent );
  525. SystemPartitionString = SpDupStringW( TemporaryBuffer );
  526. if( SystemPartitionString ) {
  527. Status = SpOpenSetValueAndClose( HiveRootKeys[SetupHiveSystem],
  528. SETUP_KEY_NAME,
  529. L"SystemPartition",
  530. STRING_VALUE(SystemPartitionString) );
  531. if(!NT_SUCCESS(Status)) {
  532. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Failed to set SystemPartitionString. (%lx)\n", Status));
  533. }
  534. SpMemFree(SystemPartitionString);
  535. } else {
  536. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Failed to duplicate SystemPartitionString.\n"));
  537. }
  538. #endif
  539. }
  540. #endif
  541. //
  542. // If we're headless, we'd like to supress any eventlog entries
  543. // that may occur if the machine has an i8042, but no one has
  544. // connected a physical keyboard to the machine. We can do that
  545. // by adding a regkey here.
  546. //
  547. if( HeadlessTerminalConnected ) {
  548. ULONG One = 1;
  549. Status = SpOpenSetValueAndClose( KeyHandle,
  550. L"Services\\i8042prt\\Parameters",
  551. L"Headless",
  552. ULONG_VALUE(One) );
  553. if( !NT_SUCCESS(Status) ) {
  554. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Failed to set Headless parameter for i8042. (%lx)\n", Status));
  555. }
  556. }
  557. //
  558. // Note that SpPostprocessHives() will always close KeyHandle
  559. //
  560. Status = SpPostprocessHives(
  561. PartitionPath,
  562. SystemRoot,
  563. HiveNames,
  564. HiveRootKeys,
  565. 3,
  566. KeyHandle
  567. );
  568. } else {
  569. //
  570. // If SpDoRegistryInitialization() fails, then we need to close KeyHandle here,
  571. // before we start unloading the hives.
  572. //
  573. NtClose(KeyHandle);
  574. }
  575. }
  576. SpDisplayStatusText(SP_STAT_REG_SAVING_HIVES,DEFAULT_STATUS_ATTRIBUTE);
  577. //
  578. // From now on, do not disturb the value of Status.
  579. //
  580. // NOTE: DO NOT WRITE ANYTHING INTO HIVES BEYOND THIS POINT!!!
  581. //
  582. // In the upgrade case we have performed a little swictheroo in
  583. // SpPostprocessHives() such that anything written to the system hive
  584. // ends up in system.sav instead of system!
  585. //
  586. for(h=0; h<SetupHiveMax; h++) {
  587. if(HiveRootKeys[h]) {
  588. ZwClose(HiveRootKeys[h]);
  589. }
  590. swprintf(pwstrTemp1,L"%ws\\x%ws",LOCAL_MACHINE_KEY_NAME,HiveNames[h]);
  591. SpLoadUnloadKey(NULL,NULL,pwstrTemp1,NULL);
  592. }
  593. SpMemFree(PartitionPath);
  594. if(!NT_SUCCESS(Status)) {
  595. SpDisplayScreen(SP_SCRN_REGISTRY_CONFIG_FAILED,3,HEADER_HEIGHT+1);
  596. SpDisplayStatusOptions(DEFAULT_STATUS_ATTRIBUTE,SP_STAT_F3_EQUALS_EXIT,0);
  597. SpInputDrain();
  598. while(SpInputGetKeypress() != KEY_F3) ;
  599. SpDone(0,FALSE,TRUE);
  600. }
  601. }
  602. NTSTATUS
  603. SpDoRegistryInitialization(
  604. IN PVOID SifHandle,
  605. IN PDISK_REGION TargetRegion,
  606. IN PWSTR PartitionPath,
  607. IN PWSTR SystemRoot,
  608. IN HANDLE *HiveRootKeys,
  609. IN PWSTR SetupSourceDevicePath,
  610. IN PWSTR DirectoryOnSourceDevice,
  611. IN PWSTR SpecialDevicePath, OPTIONAL
  612. IN HANDLE ControlSet
  613. )
  614. /*++
  615. Routine Description:
  616. Initialize a registry based on user selection for hardware types,
  617. software options, and user preferences.
  618. - Create a command line for GUI setup, to be used by winlogon.
  619. - Create/munge service list entries for device drivers being installed.
  620. - Initialize the keyboard layout.
  621. - Initialize a core set of fonts for use with Windows.
  622. - Store information about selected ahrdware components for use by GUI setup.
  623. Arguments:
  624. SifHandle - supplies handle to loaded setup information file.
  625. TargetRegion - supplies region descriptor for region to which the system
  626. is to be installed.
  627. PartitionPath - supplies the NT name for the drive of windows nt.
  628. SystemRoot - supplies nt path of the windows nt directory.
  629. HiveRootKeys - supplies the handles to the root key of the system, software
  630. and default hives
  631. HiveRootPaths - supplies the paths to the root keys of the system, software
  632. and default hives.
  633. SetupSourceDevicePath - supplies nt path to the device setup is using for
  634. source media (\device\floppy0, \device\cdrom0, etc).
  635. DirectoryOnSourceDevice - supplies the directory on the source device
  636. where setup files are kept.
  637. Return Value:
  638. Status value indicating outcome of operation.
  639. --*/
  640. {
  641. NTSTATUS Status;
  642. OBJECT_ATTRIBUTES Obja;
  643. UNICODE_STRING UnicodeString;
  644. HANDLE hKeyControlSetControl;
  645. PWSTR FullTargetPath;
  646. LPWSTR p;
  647. BOOLEAN b;
  648. ULONG SuiteMask = 0;
  649. PWSTR AdditionalGuiPnpDrivers;
  650. if(NTUpgrade != UpgradeFull) {
  651. b = SpHivesFromInfs(
  652. SifHandle,
  653. L"HiveInfs.Fresh",
  654. SetupSourceDevicePath,
  655. DirectoryOnSourceDevice,
  656. HiveRootKeys[SetupHiveSystem],
  657. HiveRootKeys[SetupHiveSoftware],
  658. HiveRootKeys[SetupHiveDefault],
  659. HiveRootKeys[SetupHiveUserdiff]
  660. );
  661. #if defined(REMOTE_BOOT)
  662. //
  663. // If this is a remote boot setup, process the AddReg.RemoteBoot
  664. // section in hivesys.inf and the AddReg section in winnt.sif.
  665. //
  666. if (b && RemoteBootSetup) {
  667. (VOID)SpHivesFromInfs(
  668. SifHandle,
  669. L"HiveInfs.Fresh.RemoteBoot",
  670. SetupSourceDevicePath,
  671. DirectoryOnSourceDevice,
  672. HiveRootKeys[SetupHiveSystem],
  673. HiveRootKeys[SetupHiveSoftware],
  674. HiveRootKeys[SetupHiveDefault],
  675. NULL
  676. );
  677. ASSERT(WinntSifHandle != NULL);
  678. (VOID)SpProcessAddRegSection(
  679. WinntSifHandle,
  680. L"AddReg",
  681. HiveRootKeys[SetupHiveSystem],
  682. HiveRootKeys[SetupHiveSoftware],
  683. HiveRootKeys[SetupHiveDefault],
  684. NULL
  685. );
  686. }
  687. #endif // defined(REMOTE_BOOT)
  688. if(!b) {
  689. Status = STATUS_UNSUCCESSFUL;
  690. goto sdoinitreg1;
  691. }
  692. }
  693. //
  694. // Open ControlSet\Control.
  695. //
  696. INIT_OBJA(&Obja,&UnicodeString,L"Control");
  697. Obja.RootDirectory = ControlSet;
  698. Status = ZwOpenKey(&hKeyControlSetControl,KEY_ALL_ACCESS,&Obja);
  699. if(!NT_SUCCESS(Status)) {
  700. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to open CurrentControlSet\\Control (%lx)\n",Status));
  701. goto sdoinitreg1;
  702. }
  703. //
  704. // Save the Pid list
  705. //
  706. SpSaveSetupPidList( HiveRootKeys[SetupHiveSystem] );
  707. //
  708. // Form the setup command line.
  709. //
  710. wcscpy(TemporaryBuffer, PartitionPath);
  711. SpConcatenatePaths(TemporaryBuffer, SystemRoot);
  712. FullTargetPath = SpDupStringW(TemporaryBuffer);
  713. Status = SpFormSetupCommandLine(
  714. SifHandle,
  715. HiveRootKeys[SetupHiveSystem],
  716. SetupSourceDevicePath,
  717. DirectoryOnSourceDevice,
  718. FullTargetPath,
  719. SpecialDevicePath
  720. );
  721. SpMemFree(FullTargetPath);
  722. if(!NT_SUCCESS(Status)) {
  723. goto sdoinitreg3;
  724. }
  725. //
  726. // Save evalution time
  727. //
  728. Status = SpSaveSKUStuff(HiveRootKeys[SetupHiveSystem]);
  729. if(!NT_SUCCESS(Status)) {
  730. goto sdoinitreg3;
  731. }
  732. //
  733. // Set the product suite
  734. //
  735. SpGetProductSuiteMask(hKeyControlSetControl,&SuiteMask);
  736. //
  737. // Account for multiple suite bits being set in SuiteType.
  738. //
  739. // SuiteMask |= (1 << (SuiteType-1));
  740. //
  741. // there's one more problem: PERSONAL sku is identified by VER_SUITE_PERSONAL flag set
  742. // we want to be able to upgrade from PER to PRO, but PRO doesn't have any flag set
  743. // we also want to be able to upgrade from PER to PER, but in this case this bit will be set
  744. // in SuiteType; therefore it's safe to always clear this bit before applying the new mask
  745. //
  746. SuiteMask &= ~VER_SUITE_PERSONAL;
  747. SuiteMask |= SuiteType;
  748. SpSetProductSuite(hKeyControlSetControl,SuiteMask);
  749. //
  750. // Language/locale-specific registry initialization.
  751. //
  752. Status = SplangSetRegistryData(
  753. SifHandle,
  754. ControlSet,
  755. (NTUpgrade == UpgradeFull) ? NULL : HardwareComponents,
  756. (BOOLEAN)(NTUpgrade == UpgradeFull)
  757. );
  758. if(!NT_SUCCESS(Status)) {
  759. goto sdoinitreg3;
  760. }
  761. //
  762. // If we need to convert to ntfs, set that up here.
  763. // We can't use the PartitionPath since that is based on
  764. // *current* disk ordinal -- we need a name based on the *on-disk*
  765. // ordinal, since the convert occurs after a reboot. Moved it here
  766. // so that this is done for upgrades too.
  767. //
  768. if(ConvertNtVolumeToNtfs) {
  769. WCHAR GuidVolumeName[MAX_PATH] = {0};
  770. PWSTR VolumeName;
  771. wcscpy(TemporaryBuffer,L"autoconv ");
  772. VolumeName = TemporaryBuffer + wcslen(TemporaryBuffer);
  773. SpNtNameFromRegion(
  774. TargetRegion,
  775. VolumeName, // append to the "autoconv " we put there
  776. 512, // just need any reasonable size
  777. PartitionOrdinalCurrent
  778. );
  779. //
  780. // NOTE: Don't use volume GUIDs for file system conversion
  781. // for 9x upgrades.
  782. //
  783. if (WinUpgradeType == NoWinUpgrade) {
  784. //
  785. // Try to get hold of the \\??\Volume{a-b-c-d} format
  786. // volume name for the partition
  787. //
  788. Status = SpPtnGetGuidNameForPartition(VolumeName,
  789. GuidVolumeName);
  790. //
  791. // If GuidVolumeName is available then use that rather
  792. // than \device\harddiskX\partitionY since disk ids can
  793. // change across reboots
  794. //
  795. if (NT_SUCCESS(Status) && GuidVolumeName[0]) {
  796. wcscpy(VolumeName, GuidVolumeName);
  797. }
  798. }
  799. wcscat(TemporaryBuffer, L" /fs:NTFS");
  800. FullTargetPath = SpDupStringW(TemporaryBuffer);
  801. Status = SpAppendStringToMultiSz(
  802. ControlSet,
  803. SESSION_MANAGER_KEY,
  804. BOOT_EXECUTE,
  805. FullTargetPath
  806. );
  807. SpMemFree(FullTargetPath);
  808. }
  809. if(NTUpgrade == UpgradeFull) {
  810. SpSavePageFileInfo( hKeyControlSetControl,
  811. HiveRootKeys[SetupHiveSystem] );
  812. Status = SpUpgradeNTRegistry(
  813. SifHandle,
  814. HiveRootKeys,
  815. SetupSourceDevicePath,
  816. DirectoryOnSourceDevice,
  817. ControlSet
  818. );
  819. if(!NT_SUCCESS(Status)) {
  820. goto sdoinitreg3;
  821. }
  822. Status = SpProcessAddRegSection(
  823. WinntSifHandle,
  824. L"compatibility",
  825. HiveRootKeys[SetupHiveSystem],
  826. NULL,
  827. NULL,
  828. NULL
  829. );
  830. if (!NT_SUCCESS(Status)) {
  831. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to process compatibility settings.\n"));
  832. }
  833. //
  834. // Disable all upper and lower level class filters for the services which were
  835. // disabled
  836. //
  837. Status = SpProcessServicesToDisable(WinntSifHandle,
  838. SP_SERVICES_TO_DISABLE,
  839. hKeyControlSetControl);
  840. if (!NT_SUCCESS(Status)) {
  841. KdPrintEx((DPFLTR_SETUP_ID,
  842. DPFLTR_ERROR_LEVEL,
  843. "SETUP: Unable to process ServicesToDisable section (%lx).\n",
  844. Status));
  845. }
  846. //
  847. // Remove all the upper and lower device instance filter drivers for keyboard and
  848. // mouse class drivers
  849. //
  850. Status = SpDeleteRequiredDeviceInstanceFilters(ControlSet);
  851. if (!NT_SUCCESS(Status)) {
  852. KdPrintEx((DPFLTR_SETUP_ID,
  853. DPFLTR_ERROR_LEVEL,
  854. "SETUP: Unable to unable to delete keyboard & mouse device filter drivers (%lx).\n",
  855. Status));
  856. }
  857. //
  858. // Set up font entries.
  859. //
  860. Status = SpConfigureFonts(SifHandle,HiveRootKeys[SetupHiveSoftware]);
  861. if(!NT_SUCCESS(Status)) {
  862. goto sdoinitreg3;
  863. }
  864. //
  865. // Enable detected scsi miniports, atdisk and abios disk, if necessary
  866. //
  867. Status = SpDriverLoadList(SifHandle,SystemRoot,HiveRootKeys[SetupHiveSystem],ControlSet);
  868. if(!NT_SUCCESS(Status)) {
  869. goto sdoinitreg3;
  870. }
  871. //
  872. // Disable the unsupported scsi drivers that need to be disabled
  873. //
  874. if( UnsupportedScsiHardwareToDisable != NULL ) {
  875. SpDisableUnsupportedScsiDrivers( ControlSet );
  876. }
  877. } else {
  878. if (IsNEC_98) { //NEC98
  879. //
  880. // NEC98 default drive assign for hard drive is start from A:,
  881. // so if it need to start from C: we should set "DriveLetter" KEY into hive.
  882. //
  883. if( !DriveAssignFromA ) {
  884. Status = SpOpenSetValueAndClose(HiveRootKeys[SetupHiveSystem],
  885. SETUP_KEY_NAME,
  886. L"DriveLetter",
  887. STRING_VALUE(L"C"));
  888. }
  889. if(!NT_SUCCESS(Status)) {
  890. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to set system\\setup\\drive letter (%lx)\n",Status));
  891. return(Status);
  892. }
  893. } //NEC98
  894. //
  895. // Create service entries for drivers being installed
  896. // (ie, munge the driver load list).
  897. //
  898. Status = SpDriverLoadList(SifHandle,SystemRoot,HiveRootKeys[SetupHiveSystem],ControlSet);
  899. if(!NT_SUCCESS(Status)) {
  900. goto sdoinitreg3;
  901. }
  902. if (SpDrEnabled()) {
  903. Status = SpDrSetEnvironmentVariables(HiveRootKeys);
  904. if(!NT_SUCCESS(Status)) {
  905. goto sdoinitreg3;
  906. }
  907. }
  908. //
  909. // Set up the keyboard layout and nls-related stuff.
  910. //
  911. Status = SpConfigureNlsParameters(SifHandle,HiveRootKeys[SetupHiveDefault],hKeyControlSetControl);
  912. if(!NT_SUCCESS(Status)) {
  913. goto sdoinitreg3;
  914. }
  915. //
  916. // Set up font entries.
  917. //
  918. Status = SpConfigureFonts(SifHandle,HiveRootKeys[SetupHiveSoftware]);
  919. if(!NT_SUCCESS(Status)) {
  920. goto sdoinitreg3;
  921. }
  922. //
  923. // Store information used by gui setup, describing the hardware
  924. // selections made by the user.
  925. //
  926. Status = SpStoreHwInfoForSetup(hKeyControlSetControl);
  927. if(!NT_SUCCESS(Status)) {
  928. goto sdoinitreg3;
  929. }
  930. if( PreInstall ) {
  931. ULONG u;
  932. PWSTR OemPnpDriversDirPath;
  933. u = 1;
  934. SpSavePreinstallList( SifHandle,
  935. SystemRoot,
  936. HiveRootKeys[SetupHiveSystem] );
  937. Status = SpOpenSetValueAndClose( hKeyControlSetControl,
  938. L"Windows",
  939. L"NoPopupsOnBoot",
  940. ULONG_VALUE(u) );
  941. if(!NT_SUCCESS(Status)) {
  942. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to set NoPopupOnBoot. Status = %lx \n",Status));
  943. }
  944. //
  945. // Add autolfn.exe to bootexecute list.
  946. //
  947. Status = SpAppendStringToMultiSz(
  948. ControlSet,
  949. SESSION_MANAGER_KEY,
  950. BOOT_EXECUTE,
  951. L"autolfn"
  952. );
  953. if(!NT_SUCCESS(Status)) {
  954. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to add autolfn to BootExecute. Status = %lx \n",Status));
  955. goto sdoinitreg3;
  956. }
  957. //
  958. // If unattended file specifies path to OEM drivers directory, then append path
  959. // to HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion, DevicePath
  960. //
  961. OemPnpDriversDirPath = SpGetSectionKeyIndex(UnattendedSifHandle,
  962. SIF_UNATTENDED,
  963. WINNT_OEM_PNP_DRIVERS_PATH_W,
  964. 0);
  965. if( OemPnpDriversDirPath != NULL ) {
  966. Status = SpAppendPathToDevicePath( HiveRootKeys[SetupHiveSoftware], OemPnpDriversDirPath );
  967. if(!NT_SUCCESS(Status)) {
  968. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to append %ls to DevicePath. Status = %lx \n",OemPnpDriversDirPath,Status));
  969. goto sdoinitreg3;
  970. }
  971. }
  972. }
  973. }
  974. SpSetPageFileInfo( SifHandle, hKeyControlSetControl, HiveRootKeys[SetupHiveSystem] );
  975. //
  976. // Skip migration of FTKeys in the win95 upgrade case. This is important in order to ensure that
  977. // drive letters are preserved. At the beginning of GUI mode, the mounted devices key will
  978. // be rebuilt using the data stored by win9xupg in the HKLM\System\DISK.
  979. //
  980. #ifdef _X86_
  981. if (WinUpgradeType != UpgradeWin95) {
  982. #endif
  983. //
  984. // Do the migration of HKEY_LOCAL_MACHINE\SYSTEM\DISK and HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices
  985. // from the setup hive to the target hive (if these keys exist).
  986. //
  987. Status = SppMigrateFtKeys(HiveRootKeys[SetupHiveSystem]);
  988. if(!NT_SUCCESS(Status)) {
  989. goto sdoinitreg3;
  990. }
  991. #ifdef _X86_
  992. }
  993. #endif
  994. //
  995. // On a remote install, we do some registry cleanup before migrating
  996. // keys.
  997. //
  998. if (RemoteInstallSetup) {
  999. SppCleanupKeysFromRemoteInstall();
  1000. }
  1001. //
  1002. // Do any cleanup on the system hive before we migrate it to the target
  1003. // system hive.
  1004. //
  1005. SpCleanUpHive();
  1006. //
  1007. // Migrate some keys from the setup hive to the target system hive.
  1008. //
  1009. Status = SpMigrateSetupKeys( PartitionPath, SystemRoot, ControlSet, SifHandle );
  1010. if( !NT_SUCCESS(Status) ) {
  1011. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to migrate registry keys from the setup hive to the target system hive. Status = %lx\n", Status));
  1012. goto sdoinitreg3;
  1013. }
  1014. //
  1015. // Disable Dynamic Volumes on portables and
  1016. // Whistler Personal
  1017. //
  1018. if( DockableMachine || SpIsProductSuite(VER_SUITE_PERSONAL)) {
  1019. NTSTATUS Status1;
  1020. Status1 = SppDisableDynamicVolumes(ControlSet);
  1021. if( !NT_SUCCESS( Status1 ) ) {
  1022. KdPrintEx((DPFLTR_SETUP_ID,
  1023. DPFLTR_ERROR_LEVEL,
  1024. "SETUP: Unable to disable dynamic volumes on laptop/personal builds. Status = %lx \n",
  1025. Status1));
  1026. }
  1027. }
  1028. //
  1029. // A side-effect of loading setupdd.sys is that Plug&Play generates a device instance
  1030. // key for it called "Root\LEGACY_SETUPDD\0000". Clean that up now. (No need to check
  1031. // the return status--if this fails it's no big deal.)
  1032. //
  1033. SppDeleteKeyRecursive(ControlSet,
  1034. L"Enum\\Root\\LEGACY_SETUPDD",
  1035. TRUE
  1036. );
  1037. //
  1038. // Delete the virtual RAM devices and driver keys
  1039. //
  1040. if (VirtualOemSourceDevices) {
  1041. //
  1042. // delete the root devnodes
  1043. //
  1044. SpDeleteRootDevnodeKeys(SifHandle,
  1045. ControlSet,
  1046. L"RootDevicesToDelete.clean",
  1047. NULL);
  1048. //
  1049. // Remove the service
  1050. //
  1051. SppDeleteKeyRecursive(ControlSet,
  1052. L"Services\\" RAMDISK_DRIVER_NAME,
  1053. TRUE);
  1054. }
  1055. #if defined(REMOTE_BOOT)
  1056. //
  1057. // Copy information that remote boot needs from the .sif to the
  1058. // registry.
  1059. //
  1060. if (RemoteBootSetup) {
  1061. (VOID)SpCopyRemoteBootKeyword(WinntSifHandle,
  1062. SIF_ENABLEIPSECURITY,
  1063. hKeyControlSetControl);
  1064. (VOID)SpCopyRemoteBootKeyword(WinntSifHandle,
  1065. SIF_REPARTITION,
  1066. hKeyControlSetControl);
  1067. }
  1068. #endif // defined(REMOTE_BOOT)
  1069. //
  1070. // Finally, if the answer file specifies a path list to additional GUI drivers,
  1071. // then append this path to the DevicePath value
  1072. //
  1073. AdditionalGuiPnpDrivers = SpGetSectionKeyIndex (
  1074. WinntSifHandle,
  1075. SIF_SETUPPARAMS,
  1076. WINNT_SP_DYNUPDTADDITIONALGUIDRIVERS_W,
  1077. 0
  1078. );
  1079. if (AdditionalGuiPnpDrivers) {
  1080. Status = SpAppendFullPathListToDevicePath (HiveRootKeys[SetupHiveSoftware], AdditionalGuiPnpDrivers);
  1081. if (!NT_SUCCESS(Status)) {
  1082. KdPrintEx ((
  1083. DPFLTR_SETUP_ID,
  1084. DPFLTR_ERROR_LEVEL,
  1085. "SETUP: Unable to append %ls to DevicePath. Status = %lx \n",
  1086. AdditionalGuiPnpDrivers,
  1087. Status
  1088. ));
  1089. goto sdoinitreg3;
  1090. }
  1091. }
  1092. sdoinitreg3:
  1093. ZwClose(hKeyControlSetControl);
  1094. sdoinitreg1:
  1095. return(Status);
  1096. }
  1097. NTSTATUS
  1098. SpFormSetupCommandLine(
  1099. IN PVOID SifHandle,
  1100. IN HANDLE hKeySystemHive,
  1101. IN PWSTR SetupSourceDevicePath,
  1102. IN PWSTR DirectoryOnSourceDevice,
  1103. IN PWSTR FullTargetPath,
  1104. IN PWSTR SpecialDevicePath OPTIONAL
  1105. )
  1106. /*++
  1107. Routine Description:
  1108. Create the command line to invoke GUI setup and store it in
  1109. HKEY_LOCAL_MACHINE\system\<ControlSet>\Setup:CmdLine.
  1110. The command line for the command to be launched depends
  1111. on whether NT Setup is executing within a disaster recovery
  1112. context, or a normal context. For the normal case, the
  1113. command line is is as follows:
  1114. setup -newsetup
  1115. For Automated System Recovery (ASR), the command line is
  1116. setup -newsetup -asr
  1117. For the automated ASR quick test, the command line is
  1118. setup - newsetup -asrquicktest
  1119. Arguments:
  1120. SifHandle - handle to the master sif (txtsetup.sif)
  1121. hKeySystemHive - supplies handle to root of the system hive
  1122. (ie, HKEY_LOCAL_MACHINE\System).
  1123. SetupSourceDevicePath - supplies the nt device path of the source media
  1124. to be used during setup (\device\floppy0, \device\cdrom0, etc).
  1125. DirectoryOnSourceDevice - supplies the directory on the source device
  1126. where setup files are kept.
  1127. FullTargetPath - supplies the NtPartitionName+SystemRoot path on the target device.
  1128. SpecialDevicePath - if specified, will be passed to setup as the value for
  1129. STF_SPECIAL_PATH. If not specified, STF_SPECIAL_PATH will be "NO"
  1130. Return Value:
  1131. Status value indicating outcome of operation.
  1132. --*/
  1133. {
  1134. PWSTR OptionalDirSpec = NULL;
  1135. PWSTR UserExecuteCmd = NULL;
  1136. PWSTR szLanManNt = WINNT_A_LANMANNT_W;
  1137. PWSTR szWinNt = WINNT_A_WINNT_W;
  1138. PWSTR szYes = WINNT_A_YES_W;
  1139. PWSTR szNo = WINNT_A_NO_W;
  1140. PWSTR SourcePathBuffer;
  1141. PWSTR CmdLine;
  1142. DWORD SetupType,SetupInProgress;
  1143. NTSTATUS Status;
  1144. PWSTR TargetFile;
  1145. PWSTR p;
  1146. WCHAR *Data[1];
  1147. //
  1148. // Can't use TemporaryBuffer because we make subroutine calls
  1149. // below that trash its contents.
  1150. //
  1151. CmdLine = SpMemAlloc(256);
  1152. CmdLine[0] = 0;
  1153. //
  1154. // Construct the setup command line. Start with the basic part.
  1155. // We first look in winnt.sif for this data, and if it isn't there, then
  1156. // we look in the sif handle which was input to us.
  1157. //
  1158. if(p = SpGetSectionKeyIndex(WinntSifHandle,SIF_SETUPDATA,SIF_SETUPCMDPREPEND,0)) {
  1159. wcscpy(CmdLine,p);
  1160. } else if(p = SpGetSectionKeyIndex(SifHandle,SIF_SETUPDATA,SIF_SETUPCMDPREPEND,0)) {
  1161. wcscpy(CmdLine,p);
  1162. }
  1163. // If we did get some parameter read in from unattend file, add separator.
  1164. //
  1165. if (*CmdLine)
  1166. wcscat(CmdLine,L" ");
  1167. //
  1168. // If this is ASR, append the appropriate cmd line options to GUI-mode Setup
  1169. //
  1170. if (SpDrEnabled()) {
  1171. if (ASRMODE_NORMAL == SpAsrGetAsrMode()) {
  1172. //
  1173. // This is normal ASR mode
  1174. //
  1175. wcscat(CmdLine, L"setup -newsetup -asr");
  1176. }
  1177. else {
  1178. //
  1179. // This is the Full Asr QuickTest
  1180. //
  1181. wcscat(CmdLine, L"setup -newsetup -asrquicktest");
  1182. }
  1183. } else {
  1184. wcscat( CmdLine,L"setup -newsetup" );
  1185. }
  1186. //
  1187. // Put the setup source in the command line.
  1188. // Note that the source is an NT-style name. GUI Setup handles this properly.
  1189. //
  1190. SourcePathBuffer = SpMemAlloc( (wcslen(SetupSourceDevicePath) +
  1191. wcslen(DirectoryOnSourceDevice) + 2) * sizeof(WCHAR) );
  1192. wcscpy(SourcePathBuffer,SetupSourceDevicePath);
  1193. if (!NoLs) {
  1194. SpConcatenatePaths(SourcePathBuffer,DirectoryOnSourceDevice);
  1195. }
  1196. //
  1197. // if we were given an administrator password via a remote install,
  1198. // we need to put this in the unattend file if appropriate.
  1199. //
  1200. if (NetBootAdministratorPassword) {
  1201. SpAddLineToSection(
  1202. WinntSifHandle,
  1203. SIF_GUI_UNATTENDED,
  1204. WINNT_US_ADMINPASS_W,
  1205. &NetBootAdministratorPassword,
  1206. 1);
  1207. }
  1208. SpAddLineToSection(WinntSifHandle,SIF_DATA,WINNT_D_SOURCEPATH_W,
  1209. &SourcePathBuffer,1);
  1210. //
  1211. // Put a flag indicating whether this is a win3.1 upgrade.
  1212. //
  1213. SpAddLineToSection(WinntSifHandle,SIF_DATA,WINNT_D_WIN31UPGRADE_W,
  1214. ( (WinUpgradeType == UpgradeWin31) ? &szYes : &szNo),1);
  1215. //
  1216. // Put a flag indicating whether this is a win95 upgrade.
  1217. //
  1218. SpAddLineToSection(WinntSifHandle,SIF_DATA,WINNT_D_WIN95UPGRADE_W,
  1219. ( (WinUpgradeType == UpgradeWin95) ? &szYes : &szNo),1);
  1220. //
  1221. // Put a flag indicating whether this is an NT upgrade.
  1222. //
  1223. SpAddLineToSection(WinntSifHandle,SIF_DATA,WINNT_D_NTUPGRADE_W,
  1224. ((NTUpgrade == UpgradeFull) ? &szYes : &szNo), 1);
  1225. //
  1226. // Put a flag indicating whether to upgrade a standard server
  1227. // (an existing standard server, or an existing workstation to
  1228. // a standard server)
  1229. //
  1230. SpAddLineToSection(WinntSifHandle,SIF_DATA,WINNT_D_SERVERUPGRADE_W,
  1231. (StandardServerUpgrade ? &szYes : &szNo),1);
  1232. //
  1233. // Tell gui mode whether this is server or workstation.
  1234. //
  1235. SpAddLineToSection(WinntSifHandle,SIF_DATA,WINNT_D_PRODUCT_W,
  1236. (AdvancedServer ? &szLanManNt : &szWinNt),1);
  1237. //
  1238. // Special path spec.
  1239. //
  1240. SpAddLineToSection(WinntSifHandle,SIF_DATA,WINNT_D_BOOTPATH_W,
  1241. (SpecialDevicePath ? &SpecialDevicePath : &szNo), 1);
  1242. //
  1243. // Go Fetch the Optional Dir Specs...
  1244. //
  1245. OptionalDirSpec = SpGetSectionKeyIndex(WinntSifHandle,SIF_SETUPPARAMS,
  1246. L"OptionalDirs",0);
  1247. //
  1248. // Check for commad line to execute at end of gui setup
  1249. //
  1250. UserExecuteCmd = SpGetSectionKeyIndex(WinntSifHandle,SIF_SETUPPARAMS,
  1251. L"UserExecute",0);
  1252. //
  1253. // Unattended mode flag | script filename
  1254. //
  1255. SpAddLineToSection(WinntSifHandle,SIF_DATA,WINNT_D_INSTALL_W,
  1256. ((UnattendedOperation || UnattendedGuiOperation || SpDrEnabled()) ? &szYes : &szNo), 1);
  1257. //
  1258. // If this is ASR, write out the Networking sections to allow
  1259. // GUI-mode to be unattended
  1260. //
  1261. if (SpDrEnabled()) {
  1262. SpAddLineToSection(WinntSifHandle,L"Networking",L"InstallDefaultComponents",&szYes,1);
  1263. Data[0]=L"WORKGROUP";
  1264. SpAddLineToSection(WinntSifHandle,L"Identification",L"JoinWorkgroup",Data,1);
  1265. }
  1266. //
  1267. // Write the name of OEM inf files, if any.
  1268. //
  1269. if( OemInfFileList != NULL ) {
  1270. PWSTR OemDriversKeyName = WINNT_OEMDRIVERS_W; // L"OemDrivers";
  1271. PWSTR OemDriverPathName = WINNT_OEMDRIVERS_PATHNAME_W; // L"OemDriverPathName";
  1272. PWSTR OemInfName = WINNT_OEMDRIVERS_INFNAME_W; // L"OemInfName";
  1273. PWSTR OemDriverFlags = WINNT_OEMDRIVERS_FLAGS_W;
  1274. PWSTR OemInfSectionName = L"OemInfFiles";
  1275. PWSTR szOne = L"1";
  1276. PWSTR p;
  1277. PWSTR *r;
  1278. ULONG NumberOfInfFiles;
  1279. POEM_INF_FILE q;
  1280. ULONG i;
  1281. SpAddLineToSection(WinntSifHandle, SIF_DATA, OemDriversKeyName, &OemInfSectionName, 1);
  1282. wcscpy( TemporaryBuffer, L"%SystemRoot%" );
  1283. SpConcatenatePaths( TemporaryBuffer, OemDirName );
  1284. p = SpDupStringW( TemporaryBuffer );
  1285. SpAddLineToSection(WinntSifHandle, OemInfSectionName, OemDriverPathName, &p, 1);
  1286. SpMemFree( p );
  1287. SpAddLineToSection(WinntSifHandle, OemInfSectionName, OemDriverFlags, &szOne, 1);
  1288. for( q = OemInfFileList, NumberOfInfFiles = 0;
  1289. q != NULL;
  1290. q = q->Next, NumberOfInfFiles++ );
  1291. r = SpMemAlloc( NumberOfInfFiles * sizeof( PWSTR ) );
  1292. for( q = OemInfFileList, i = 0;
  1293. q != NULL;
  1294. r[i] = q->InfName, q = q->Next, i++ );
  1295. SpAddLineToSection(WinntSifHandle,OemInfSectionName, OemInfName, r, NumberOfInfFiles);
  1296. SpMemFree( r );
  1297. }
  1298. //
  1299. // Before we write the answer to this, we need to know if we successfully
  1300. // have written Winnt.sif into system32\$winnt$.inf
  1301. //
  1302. wcscpy(TemporaryBuffer, FullTargetPath);
  1303. SpConcatenatePaths(TemporaryBuffer, L"system32");
  1304. SpConcatenatePaths(TemporaryBuffer, SIF_UNATTENDED_INF_FILE);
  1305. TargetFile = SpDupStringW(TemporaryBuffer);
  1306. Status = SpWriteSetupTextFile(WinntSifHandle,TargetFile,NULL,NULL);
  1307. if(NT_SUCCESS(Status)) {
  1308. Status = SpOpenSetValueAndClose(
  1309. hKeySystemHive,
  1310. SETUP_KEY_NAME,
  1311. L"CmdLine",
  1312. STRING_VALUE(CmdLine)
  1313. );
  1314. }
  1315. //
  1316. // Free up whatever memory we have allocated
  1317. //
  1318. SpMemFree(TargetFile);
  1319. SpMemFree(CmdLine);
  1320. SpMemFree(SourcePathBuffer);
  1321. if(!NT_SUCCESS(Status)) {
  1322. return(Status);
  1323. }
  1324. //
  1325. // Set the SetupType value to the right value SETUPTYPE_FULL in the
  1326. // case of initial install and SETUPTYPE_UPGRADE in the case of upgrade.
  1327. //
  1328. SetupType = (NTUpgrade == UpgradeFull) ? SETUPTYPE_UPGRADE : SETUPTYPE_FULL;
  1329. Status = SpOpenSetValueAndClose(
  1330. hKeySystemHive,
  1331. SETUP_KEY_NAME,
  1332. L"SetupType",
  1333. ULONG_VALUE(SetupType)
  1334. );
  1335. if(!NT_SUCCESS(Status)) {
  1336. return(Status);
  1337. }
  1338. //
  1339. // Set the SystemSetupInProgress value. Don't rely on the default hives
  1340. // having this set
  1341. //
  1342. SetupInProgress = 1;
  1343. Status = SpOpenSetValueAndClose(
  1344. hKeySystemHive,
  1345. SETUP_KEY_NAME,
  1346. L"SystemSetupInProgress",
  1347. ULONG_VALUE(SetupInProgress)
  1348. );
  1349. return(Status);
  1350. }
  1351. NTSTATUS
  1352. SpDriverLoadList(
  1353. IN PVOID SifHandle,
  1354. IN PWSTR SystemRoot,
  1355. IN HANDLE hKeySystemHive,
  1356. IN HANDLE hKeyControlSet
  1357. )
  1358. {
  1359. NTSTATUS Status;
  1360. OBJECT_ATTRIBUTES Obja;
  1361. UNICODE_STRING UnicodeString;
  1362. HANDLE hKeyControlSetServices;
  1363. PHARDWARE_COMPONENT ScsiHwComponent;
  1364. // PHARDWARE_COMPONENT TempExtender;
  1365. ULONG u;
  1366. ULONG i;
  1367. PHARDWARE_COMPONENT TempHw;
  1368. PHARDWARE_COMPONENT DeviceLists[] = {
  1369. BootBusExtenders,
  1370. BusExtenders,
  1371. InputDevicesSupport
  1372. };
  1373. PWSTR SectionNames[] = {
  1374. SIF_BOOTBUSEXTENDERS,
  1375. SIF_BUSEXTENDERS,
  1376. SIF_INPUTDEVICESSUPPORT
  1377. };
  1378. PWSTR ServiceGroupNames[] = {
  1379. L"Boot Bus Extender",
  1380. L"System Bus Extender",
  1381. NULL
  1382. };
  1383. ULONG StartValues[] = {
  1384. SERVICE_BOOT_START,
  1385. SERVICE_BOOT_START,
  1386. SERVICE_DEMAND_START
  1387. };
  1388. //
  1389. // Open controlset\services.
  1390. //
  1391. INIT_OBJA(&Obja,&UnicodeString,L"services");
  1392. Obja.RootDirectory = hKeyControlSet;
  1393. Status = ZwCreateKey(
  1394. &hKeyControlSetServices,
  1395. KEY_ALL_ACCESS,
  1396. &Obja,
  1397. 0,
  1398. NULL,
  1399. REG_OPTION_NON_VOLATILE,
  1400. NULL
  1401. );
  1402. if(!NT_SUCCESS(Status)) {
  1403. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: unable to open services key (%lx)\n",Status));
  1404. return(Status);
  1405. }
  1406. //
  1407. // For each non-third-party miniport driver that loaded,
  1408. // go create a services entry for it.
  1409. //
  1410. if( !PreInstall ||
  1411. ( PreinstallScsiHardware == NULL ) ) {
  1412. ScsiHwComponent = ScsiHardware;
  1413. } else {
  1414. ScsiHwComponent = PreinstallScsiHardware;
  1415. }
  1416. for( ; ScsiHwComponent; ScsiHwComponent=ScsiHwComponent->Next) {
  1417. if(!ScsiHwComponent->ThirdPartyOptionSelected) {
  1418. //
  1419. // For scsi, the shortname (idstring) is used as
  1420. // the name of the service node key in the registry --
  1421. // we don't look up the service entry in the [SCSI] section
  1422. // of the setup info file.
  1423. //
  1424. Status = SpCreateServiceEntryIndirect(
  1425. hKeyControlSetServices,
  1426. NULL,
  1427. NULL,
  1428. ScsiHwComponent->IdString,
  1429. SERVICE_KERNEL_DRIVER,
  1430. SERVICE_BOOT_START,
  1431. L"SCSI miniport",
  1432. SERVICE_ERROR_NORMAL,
  1433. NULL,
  1434. NULL
  1435. );
  1436. if(!NT_SUCCESS(Status)) {
  1437. goto spdrvlist1;
  1438. }
  1439. }
  1440. }
  1441. //
  1442. // If there are any atdisks out there, enable atdisk.
  1443. // We have to enable AtDisk if Pcmcia was loaded, even
  1444. // if atdisk doesn't exist. This will allow the user to
  1445. // insert a pcmcia atdisk device, and have it work when
  1446. // they boot. In this case, however, we turn off error
  1447. // logging, so that they won't get an annoying popup
  1448. // when there is no atdisk device in the card slot.
  1449. //
  1450. // Note that atdisk.sys is always copied to the system.
  1451. //
  1452. Status = SpCreateServiceEntryIndirect(
  1453. hKeyControlSetServices,
  1454. NULL,
  1455. NULL,
  1456. ATDISK_NAME,
  1457. SERVICE_KERNEL_DRIVER,
  1458. ( AtDisksExist )? SERVICE_BOOT_START : SERVICE_DISABLED,
  1459. PRIMARY_DISK_GROUP,
  1460. ( AtDisksExist && !AtapiLoaded )? SERVICE_ERROR_NORMAL : SERVICE_ERROR_IGNORE,
  1461. NULL,
  1462. NULL
  1463. );
  1464. if(!NT_SUCCESS(Status)) {
  1465. goto spdrvlist1;
  1466. }
  1467. //
  1468. // If there are any abios disks out there, enable abiosdsk.
  1469. //
  1470. if(AbiosDisksExist) {
  1471. Status = SpCreateServiceEntryIndirect(
  1472. hKeyControlSetServices,
  1473. NULL,
  1474. NULL,
  1475. ABIOSDISK_NAME,
  1476. SERVICE_KERNEL_DRIVER,
  1477. SERVICE_BOOT_START,
  1478. PRIMARY_DISK_GROUP,
  1479. SERVICE_ERROR_NORMAL,
  1480. NULL,
  1481. NULL
  1482. );
  1483. if(!NT_SUCCESS(Status)) {
  1484. goto spdrvlist1;
  1485. }
  1486. }
  1487. //
  1488. // For each bus enumerator driver that loaded,
  1489. // go create a services entry for it.
  1490. //
  1491. for( i = 0; i < sizeof(DeviceLists) / sizeof(PDETECTED_DEVICE); i++ ) {
  1492. for( TempHw = DeviceLists[i]; TempHw; TempHw=TempHw->Next) {
  1493. //
  1494. // For bus extenders and input devices, the shortname (idstring) is used as
  1495. // the name of the service node key in the registry --
  1496. // we don't look up the service entry in the [BusExtenders] or [InputDevicesSupport] section
  1497. // of the setup info file.
  1498. //
  1499. Status = SpCreateServiceEntryIndirect(
  1500. hKeyControlSetServices,
  1501. SifHandle,
  1502. SectionNames[i],
  1503. TempHw->IdString,
  1504. SERVICE_KERNEL_DRIVER,
  1505. StartValues[i],
  1506. ServiceGroupNames[i],
  1507. SERVICE_ERROR_NORMAL,
  1508. NULL,
  1509. NULL
  1510. );
  1511. if(!NT_SUCCESS(Status)) {
  1512. goto spdrvlist1;
  1513. }
  1514. }
  1515. }
  1516. if( NTUpgrade != UpgradeFull ) {
  1517. //
  1518. // Set up video parameters.
  1519. //
  1520. Status = SpWriteVideoParameters(SifHandle,hKeyControlSetServices);
  1521. if(!NT_SUCCESS(Status)) {
  1522. goto spdrvlist1;
  1523. }
  1524. //
  1525. // Enable the relevent keyboard and mouse drivers. If the class drivers
  1526. // are being replaced by third-party ones, then disable the built-in ones.
  1527. //
  1528. Status = SpConfigureMouseKeyboardDrivers(
  1529. SifHandle,
  1530. HwComponentKeyboard,
  1531. L"kbdclass",
  1532. hKeyControlSetServices,
  1533. KEYBOARD_PORT_GROUP
  1534. );
  1535. if(!NT_SUCCESS(Status)) {
  1536. goto spdrvlist1;
  1537. }
  1538. Status = SpConfigureMouseKeyboardDrivers(
  1539. SifHandle,
  1540. HwComponentMouse,
  1541. L"mouclass",
  1542. hKeyControlSetServices,
  1543. POINTER_PORT_GROUP
  1544. );
  1545. if(!NT_SUCCESS(Status)) {
  1546. goto spdrvlist1;
  1547. }
  1548. }
  1549. Status = SpThirdPartyRegistry(hKeyControlSetServices);
  1550. spdrvlist1:
  1551. ZwClose(hKeyControlSetServices);
  1552. return(Status);
  1553. }
  1554. NTSTATUS
  1555. SpSaveSKUStuff(
  1556. IN HANDLE hKeySystemHive
  1557. )
  1558. {
  1559. LARGE_INTEGER l;
  1560. NTSTATUS Status;
  1561. ULONG NumberOfProcessors;
  1562. BOOLEAN OldStyleRegisteredProcessorMode;
  1563. ULONG Index = 0;
  1564. //
  1565. // Do not change any of this algorithm without changing
  1566. // SetUpEvaluationSKUStuff() in syssetup.dll (registry.c).
  1567. //
  1568. // Embed the evaluation time and a bool indicating whether
  1569. // this is a server or workstation inside a random large integer.
  1570. //
  1571. // Evaluation time: bits 13-44
  1572. // Product type : bit 58
  1573. //
  1574. // Bit 10 == 1 : Setup works as it does before the 4.0 restriction logic
  1575. // == 0 : GUI Setup writes registered processors based on the
  1576. // contents of bits 5-9
  1577. //
  1578. // Bits 5 - 9 : The maximum number of processors that the system is licensed
  1579. // to use. The value stored is actually ~(MaxProcessors-1)
  1580. //
  1581. //
  1582. // RestrictCpu is used to build protucts this place a very hard
  1583. // limit on the number of processors
  1584. //
  1585. // - a value of 0 means for NTW, the hard limit is 2, and for NTS,
  1586. // the hard limit is 4
  1587. //
  1588. // - a value of 1-32 means that the hard limit is the number
  1589. // specified
  1590. //
  1591. // - a value > 32 means that the hard limit is 32 processors and GUI
  1592. // setup operates on registered processors as it does today
  1593. //
  1594. l.LowPart = SpComputeSerialNumber();
  1595. l.HighPart = SpComputeSerialNumber();
  1596. l.QuadPart &= 0xfbffe0000000181f;
  1597. l.QuadPart |= ((ULONGLONG)EvaluationTime) << 13;
  1598. if ( RestrictCpu == 0 ) {
  1599. //
  1600. // NTW and NTS will take this path using setupreg.hiv/setupret.hiv
  1601. //
  1602. OldStyleRegisteredProcessorMode = FALSE;
  1603. //
  1604. // new licensing model says that whistler is a 2 cpu system, not 4
  1605. //
  1606. NumberOfProcessors = 2;
  1607. //NumberOfProcessors = (AdvancedServer ? 4 : 2);
  1608. } else if ( RestrictCpu <= MAXIMUM_PROCESSORS ) {
  1609. //
  1610. // NTS/EE/DTC will take this path using a hive targetted at 8/16 CPU.
  1611. //
  1612. OldStyleRegisteredProcessorMode = FALSE;
  1613. NumberOfProcessors = RestrictCpu;
  1614. } else {
  1615. OldStyleRegisteredProcessorMode = TRUE;
  1616. NumberOfProcessors = MAXIMUM_PROCESSORS;
  1617. }
  1618. //
  1619. // Logic of getting the log(NumberOfProcessor) and verification.
  1620. // 2
  1621. // Here we encode the number of processors as the power of 2.
  1622. // Where NumberOfProcessors is the maximum number of processors that
  1623. // the system is licensed to use.
  1624. //
  1625. //
  1626. // If exact power of two only then it is a good value.
  1627. //
  1628. if (NumberOfProcessors & (NumberOfProcessors-1)){
  1629. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Invalid NumberOfProcessors (%u)\n",NumberOfProcessors));
  1630. return(STATUS_INVALID_PARAMETER);
  1631. }
  1632. //
  1633. // Count the number of times we need to divide NumberOfProcessors
  1634. // by 2 to reduce it to 1.
  1635. // 8 = 1000 in binary and (2^3 = 8) and we store 3 in the registry.
  1636. //
  1637. Index = 0;
  1638. while(NumberOfProcessors > 1){
  1639. NumberOfProcessors = NumberOfProcessors >> 1;
  1640. ++Index;
  1641. }
  1642. NumberOfProcessors = Index;
  1643. //
  1644. // Now NumberOfProcessors is correct. Convert it to the in registry format
  1645. //
  1646. NumberOfProcessors = NumberOfProcessors << 5;
  1647. NumberOfProcessors &= 0x000003e0;
  1648. //
  1649. // Store NumberOfProcessors into the registry
  1650. //
  1651. l.LowPart |= NumberOfProcessors;
  1652. //
  1653. // Tell Gui Mode to do old style registered processors
  1654. //
  1655. if ( OldStyleRegisteredProcessorMode ) {
  1656. l.LowPart |= 0x00000400;
  1657. }
  1658. if(AdvancedServer) {
  1659. l.HighPart |= 0x04000000;
  1660. }
  1661. //
  1662. // Save in registry.
  1663. //
  1664. Status = SpOpenSetValueAndClose(
  1665. hKeySystemHive,
  1666. SETUP_KEY_NAME,
  1667. L"SystemPrefix",
  1668. REG_BINARY,
  1669. &l.QuadPart,
  1670. sizeof(ULONGLONG)
  1671. );
  1672. if(!NT_SUCCESS(Status)) {
  1673. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to set SystemPrefix (%lx)\n",Status));
  1674. }
  1675. return(Status);
  1676. }
  1677. NTSTATUS
  1678. SpSetUlongValueFromSif(
  1679. IN PVOID SifHandle,
  1680. IN PWSTR SifSection,
  1681. IN PWSTR SifKey,
  1682. IN ULONG SifIndex,
  1683. IN HANDLE hKey,
  1684. IN PWSTR ValueName
  1685. )
  1686. {
  1687. UNICODE_STRING UnicodeString;
  1688. PWSTR ValueString;
  1689. LONG Value;
  1690. NTSTATUS Status;
  1691. //
  1692. // Look up the value.
  1693. //
  1694. ValueString = SpGetSectionKeyIndex(SifHandle,SifSection,SifKey,SifIndex);
  1695. if(!ValueString) {
  1696. SpFatalSifError(SifHandle,SifSection,SifKey,0,SifIndex);
  1697. }
  1698. Value = SpStringToLong(ValueString,NULL,10);
  1699. if(Value == -1) {
  1700. Status = STATUS_SUCCESS;
  1701. } else {
  1702. RtlInitUnicodeString(&UnicodeString,ValueName);
  1703. Status = ZwSetValueKey(hKey,&UnicodeString,0,ULONG_VALUE((ULONG)Value));
  1704. if(!NT_SUCCESS(Status)) {
  1705. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to set value %ws (%lx)\n",ValueName,Status));
  1706. }
  1707. }
  1708. return(Status);
  1709. }
  1710. NTSTATUS
  1711. SpConfigureMouseKeyboardDrivers(
  1712. IN PVOID SifHandle,
  1713. IN ULONG HwComponent,
  1714. IN PWSTR ClassServiceName,
  1715. IN HANDLE hKeyControlSetServices,
  1716. IN PWSTR ServiceGroup
  1717. )
  1718. {
  1719. PHARDWARE_COMPONENT hw;
  1720. NTSTATUS Status;
  1721. ULONG val = SERVICE_DISABLED;
  1722. Status = STATUS_SUCCESS;
  1723. if( !PreInstall ||
  1724. ( PreinstallHardwareComponents[HwComponent] == NULL ) ) {
  1725. hw = HardwareComponents[HwComponent];
  1726. } else {
  1727. hw = PreinstallHardwareComponents[HwComponent];
  1728. }
  1729. for(;hw && NT_SUCCESS( Status ); hw=hw->Next) {
  1730. if(hw->ThirdPartyOptionSelected) {
  1731. if(IS_FILETYPE_PRESENT(hw->FileTypeBits,HwFileClass)) {
  1732. if( !PreInstall ) {
  1733. //
  1734. // Disable the built-in class driver.
  1735. //
  1736. Status = SpOpenSetValueAndClose(
  1737. hKeyControlSetServices,
  1738. ClassServiceName,
  1739. L"Start",
  1740. ULONG_VALUE(val)
  1741. );
  1742. }
  1743. }
  1744. } else {
  1745. Status = SpCreateServiceEntryIndirect(
  1746. hKeyControlSetServices,
  1747. SifHandle,
  1748. NonlocalizedComponentNames[HwComponent],
  1749. hw->IdString,
  1750. SERVICE_KERNEL_DRIVER,
  1751. SERVICE_SYSTEM_START,
  1752. ServiceGroup,
  1753. SERVICE_ERROR_IGNORE,
  1754. NULL,
  1755. NULL
  1756. );
  1757. }
  1758. }
  1759. return(Status);
  1760. }
  1761. NTSTATUS
  1762. SpWriteVideoParameters(
  1763. IN PVOID SifHandle,
  1764. IN HANDLE hKeyControlSetServices
  1765. )
  1766. {
  1767. NTSTATUS Status;
  1768. PWSTR KeyName;
  1769. HANDLE hKeyDisplayService;
  1770. OBJECT_ATTRIBUTES Obja;
  1771. UNICODE_STRING UnicodeString;
  1772. ULONG x,y,b,v,i;
  1773. PHARDWARE_COMPONENT pHw;
  1774. if( !PreInstall ||
  1775. ( PreinstallHardwareComponents[HwComponentDisplay] == NULL ) ) {
  1776. pHw = HardwareComponents[HwComponentDisplay];
  1777. } else {
  1778. pHw = PreinstallHardwareComponents[HwComponentDisplay];
  1779. }
  1780. Status = STATUS_SUCCESS;
  1781. for(;pHw && NT_SUCCESS(Status);pHw=pHw->Next) {
  1782. //
  1783. // Third party drivers will have values written into the miniport
  1784. // Device0 key at the discretion of the txtsetup.oem author.
  1785. //
  1786. if(pHw->ThirdPartyOptionSelected) {
  1787. continue;
  1788. // return(STATUS_SUCCESS);
  1789. }
  1790. KeyName = SpGetSectionKeyIndex(
  1791. SifHandle,
  1792. NonlocalizedComponentNames[HwComponentDisplay],
  1793. pHw->IdString,
  1794. INDEX_INFKEYNAME
  1795. );
  1796. //
  1797. // If no key name is specified for this display then there's nothing to do.
  1798. // The setup display subsystem can tell us that the mode parameters are
  1799. // not relevent. If so there's nothing to do.
  1800. //
  1801. if(!KeyName || !SpvidGetModeParams(&x,&y,&b,&v,&i)) {
  1802. continue;
  1803. // return(STATUS_SUCCESS);
  1804. }
  1805. //
  1806. // We want to write the parameters for the display mode setup
  1807. // is using into the relevent key in the service list. This will force
  1808. // the right mode for, say, a fixed-frequency monitor attached to
  1809. // a vxl (which might default to a mode not supported by the monitor).
  1810. //
  1811. INIT_OBJA(&Obja,&UnicodeString,KeyName);
  1812. Obja.RootDirectory = hKeyControlSetServices;
  1813. Status = ZwCreateKey(
  1814. &hKeyDisplayService,
  1815. KEY_ALL_ACCESS,
  1816. &Obja,
  1817. 0,
  1818. NULL,
  1819. REG_OPTION_NON_VOLATILE,
  1820. NULL
  1821. );
  1822. if(!NT_SUCCESS(Status)) {
  1823. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: unable to open/create key %ws (%lx)\n",KeyName,Status));
  1824. return(Status);
  1825. }
  1826. //
  1827. // Set the x resolution.
  1828. //
  1829. Status = SpOpenSetValueAndClose(
  1830. hKeyDisplayService,
  1831. VIDEO_DEVICE0,
  1832. L"DefaultSettings.XResolution",
  1833. ULONG_VALUE(x)
  1834. );
  1835. if(NT_SUCCESS(Status)) {
  1836. //
  1837. // Set the y resolution.
  1838. //
  1839. Status = SpOpenSetValueAndClose(
  1840. hKeyDisplayService,
  1841. VIDEO_DEVICE0,
  1842. L"DefaultSettings.YResolution",
  1843. ULONG_VALUE(y)
  1844. );
  1845. if(NT_SUCCESS(Status)) {
  1846. //
  1847. // Set the bits per pixel.
  1848. //
  1849. Status = SpOpenSetValueAndClose(
  1850. hKeyDisplayService,
  1851. VIDEO_DEVICE0,
  1852. L"DefaultSettings.BitsPerPel",
  1853. ULONG_VALUE(b)
  1854. );
  1855. if(NT_SUCCESS(Status)) {
  1856. //
  1857. // Set the vertical refresh.
  1858. //
  1859. Status = SpOpenSetValueAndClose(
  1860. hKeyDisplayService,
  1861. VIDEO_DEVICE0,
  1862. L"DefaultSettings.VRefresh",
  1863. ULONG_VALUE(v)
  1864. );
  1865. if(NT_SUCCESS(Status)) {
  1866. //
  1867. // Set the interlaced flag.
  1868. //
  1869. Status = SpOpenSetValueAndClose(
  1870. hKeyDisplayService,
  1871. VIDEO_DEVICE0,
  1872. L"DefaultSettings.Interlaced",
  1873. ULONG_VALUE(i)
  1874. );
  1875. }
  1876. }
  1877. }
  1878. }
  1879. ZwClose(hKeyDisplayService);
  1880. }
  1881. return(Status);
  1882. }
  1883. NTSTATUS
  1884. SpConfigureNlsParameters(
  1885. IN PVOID SifHandle,
  1886. IN HANDLE hKeyDefaultHive,
  1887. IN HANDLE hKeyControlSetControl
  1888. )
  1889. /*++
  1890. Routine Description:
  1891. This routine configures NLS-related stuff in the registry:
  1892. - a keyboard layout
  1893. - the primary ansi, oem, and mac codepages
  1894. - the language casetable
  1895. - the oem hal font
  1896. Arguments:
  1897. SifHandle - supplies handle to open setup information file.
  1898. hKeyDefaultHive - supplies handle to root of default user hive.
  1899. hKeyControlSetControl - supplies handle to the Control subkey of
  1900. the control set being operated on.
  1901. Return Value:
  1902. Status value indicating outcome of operation.
  1903. --*/
  1904. {
  1905. PHARDWARE_COMPONENT_FILE HwFile;
  1906. PWSTR LayoutId;
  1907. NTSTATUS Status;
  1908. HANDLE hKeyNls;
  1909. PWSTR OemHalFont;
  1910. OBJECT_ATTRIBUTES Obja;
  1911. UNICODE_STRING UnicodeString;
  1912. PWSTR IntlLayoutId, LayoutText, LayoutFile, SubKey;
  1913. //
  1914. // We don't allow third-party keyboard layouts.
  1915. //
  1916. ASSERT(!HardwareComponents[HwComponentLayout]->ThirdPartyOptionSelected);
  1917. //
  1918. // Make an entry in the keyboard layout section in the default user hive.
  1919. // This will match an entry in HKLM\CCS\Control\Nls\Keyboard Layouts,
  1920. // which is 'preloaded' with all the possible layouts.
  1921. //
  1922. if( !PreInstall ||
  1923. (PreinstallHardwareComponents[HwComponentLayout] == NULL) ) {
  1924. LayoutId = HardwareComponents[HwComponentLayout]->IdString;
  1925. } else {
  1926. LayoutId = PreinstallHardwareComponents[HwComponentLayout]->IdString;
  1927. }
  1928. Status = SpOpenSetValueAndClose(
  1929. hKeyDefaultHive,
  1930. L"Keyboard Layout\\Preload",
  1931. L"1",
  1932. STRING_VALUE(LayoutId)
  1933. );
  1934. if(!NT_SUCCESS(Status)) {
  1935. return(Status);
  1936. }
  1937. //
  1938. // Add 3 entries into the registry here. our entries will be:
  1939. // 1. HKLM\System\CurrentControlSet\Control\Keyboard Layouts\LayoutId\Layout File
  1940. // 2. HKLM\System\CurrentControlSet\Control\Keyboard Layouts\LayoutId\Layout Id
  1941. // 3. HKLM\System\CurrentControlSet\Control\Keyboard Layouts\LayoutId\Layout Text
  1942. //
  1943. wcscpy( TemporaryBuffer, L"Keyboard Layouts" );
  1944. SpConcatenatePaths( TemporaryBuffer, LayoutId );
  1945. SubKey = SpDupStringW(TemporaryBuffer);
  1946. //
  1947. // First, do the "Layout File" key.
  1948. //
  1949. LayoutFile = SpGetSectionKeyIndex(
  1950. SifHandle, // txtsetup.sif
  1951. SIF_KEYBOARDLAYOUTFILES,// Files.KeyboardLayout
  1952. LayoutId, // IdString
  1953. 0 // 0
  1954. );
  1955. if(!LayoutFile) {
  1956. SpFatalSifError(
  1957. SifHandle,
  1958. SIF_KEYBOARDLAYOUTFILES,
  1959. LayoutId,
  1960. 0,
  1961. INDEX_DESCRIPTION
  1962. );
  1963. //
  1964. // Should not come here, but lets make prefix happy
  1965. //
  1966. return STATUS_NO_SUCH_FILE;
  1967. }
  1968. Status = SpOpenSetValueAndClose(
  1969. hKeyControlSetControl, // Handle to ControlSet\Control
  1970. SubKey, // \Keyboard Layouts\LayoutId
  1971. L"Layout File", // ValueName
  1972. REG_SZ, // ValueType
  1973. LayoutFile, // Value
  1974. (wcslen(LayoutFile)+1)*sizeof(WCHAR) // ValueSize
  1975. );
  1976. if(!NT_SUCCESS(Status)) {
  1977. return(Status);
  1978. }
  1979. //
  1980. // Next, do the "\Keyboard layouts\Layout Text" key.
  1981. //
  1982. LayoutText = SpGetSectionKeyIndex(
  1983. SifHandle, // txtsetup.sif
  1984. SIF_KEYBOARDLAYOUT, // Keyboard Layout
  1985. LayoutId, // IdString
  1986. 0 // 0
  1987. );
  1988. if(!LayoutText) {
  1989. SpFatalSifError(
  1990. SifHandle,
  1991. SIF_KEYBOARDLAYOUT,
  1992. LayoutId,
  1993. 0,
  1994. INDEX_DESCRIPTION
  1995. );
  1996. }
  1997. Status = SpOpenSetValueAndClose(
  1998. hKeyControlSetControl, // Handle to ControlSet\Control
  1999. SubKey, // \Keyboard Layouts\LayoutId
  2000. L"Layout Text", // ValueName
  2001. REG_SZ, // ValueType
  2002. LayoutText, // Value
  2003. (wcslen(LayoutText)+1)*sizeof(WCHAR) // ValueSize
  2004. );
  2005. if(!NT_SUCCESS(Status)) {
  2006. return(Status);
  2007. }
  2008. //
  2009. // Lastly, do the "\Keyboard layouts\Layout Id" key.
  2010. //
  2011. IntlLayoutId = SpGetSectionKeyIndex(
  2012. SifHandle, // txtsetup.sif
  2013. L"KeyboardLayoutId", // KeyboardLayoutId
  2014. LayoutId, // IdString
  2015. 0 // 0
  2016. );
  2017. //
  2018. // There may legitimatley not be one...
  2019. //
  2020. if(IntlLayoutId) {
  2021. Status = SpOpenSetValueAndClose(
  2022. hKeyControlSetControl, // Handle to ControlSet\Control
  2023. SubKey, // \Keyboard Layouts\LayoutId
  2024. L"Layout Id", // ValueName
  2025. REG_SZ, // ValueType
  2026. IntlLayoutId, // Value
  2027. (wcslen(IntlLayoutId)+1)*sizeof(WCHAR) // ValueSize
  2028. );
  2029. if(!NT_SUCCESS(Status)) {
  2030. return(Status);
  2031. }
  2032. }
  2033. SpMemFree(SubKey);
  2034. //
  2035. // Open controlset\Control\Nls.
  2036. //
  2037. INIT_OBJA(&Obja,&UnicodeString,L"Nls");
  2038. Obja.RootDirectory = hKeyControlSetControl;
  2039. Status = ZwCreateKey(
  2040. &hKeyNls,
  2041. KEY_ALL_ACCESS,
  2042. &Obja,
  2043. 0,
  2044. NULL,
  2045. REG_OPTION_NON_VOLATILE,
  2046. NULL
  2047. );
  2048. if(!NT_SUCCESS(Status)) {
  2049. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to open controlset\\Control\\Nls key (%lx)\n",Status));
  2050. return(Status);
  2051. }
  2052. //
  2053. // Create an entry for the ansi codepage.
  2054. //
  2055. Status = SpCreateCodepageEntry(
  2056. SifHandle,
  2057. hKeyNls,
  2058. CODEPAGE_NAME,
  2059. SIF_ANSICODEPAGE,
  2060. L"ACP"
  2061. );
  2062. if(NT_SUCCESS(Status)) {
  2063. //
  2064. // Create entries for the oem codepage(s).
  2065. //
  2066. Status = SpCreateCodepageEntry(
  2067. SifHandle,
  2068. hKeyNls,
  2069. CODEPAGE_NAME,
  2070. SIF_OEMCODEPAGE,
  2071. L"OEMCP"
  2072. );
  2073. if(NT_SUCCESS(Status)) {
  2074. //
  2075. // Create an entry for the mac codepage.
  2076. //
  2077. Status = SpCreateCodepageEntry(
  2078. SifHandle,
  2079. hKeyNls,
  2080. CODEPAGE_NAME,
  2081. SIF_MACCODEPAGE,
  2082. L"MACCP"
  2083. );
  2084. }
  2085. }
  2086. if(NT_SUCCESS(Status)) {
  2087. //
  2088. // Create an entry for the oem hal font.
  2089. //
  2090. OemHalFont = SpGetSectionKeyIndex(SifHandle,SIF_NLS,SIF_OEMHALFONT,0);
  2091. if(!OemHalFont) {
  2092. SpFatalSifError(SifHandle,SIF_NLS,SIF_OEMHALFONT,0,0);
  2093. }
  2094. Status = SpOpenSetValueAndClose(
  2095. hKeyNls,
  2096. CODEPAGE_NAME,
  2097. L"OEMHAL",
  2098. STRING_VALUE(OemHalFont)
  2099. );
  2100. }
  2101. //
  2102. // Create an entry for the language case table.
  2103. //
  2104. if(NT_SUCCESS(Status)) {
  2105. Status = SpCreateCodepageEntry(
  2106. SifHandle,
  2107. hKeyNls,
  2108. L"Language",
  2109. SIF_UNICODECASETABLE,
  2110. L"Default"
  2111. );
  2112. }
  2113. #ifdef _X86_
  2114. //
  2115. // If necessary, let the win9x upgrade override the code page for GUI mode.
  2116. //
  2117. if (WinUpgradeType == UpgradeWin95) {
  2118. SpWin9xOverrideGuiModeCodePage (hKeyNls);
  2119. }
  2120. #endif
  2121. ZwClose(hKeyNls);
  2122. return(Status);
  2123. }
  2124. NTSTATUS
  2125. SpCreateCodepageEntry(
  2126. IN PVOID SifHandle,
  2127. IN HANDLE hKeyNls,
  2128. IN PWSTR SubkeyName,
  2129. IN PWSTR SifNlsSectionKeyName,
  2130. IN PWSTR EntryName
  2131. )
  2132. {
  2133. PWSTR Filename,Identifier;
  2134. NTSTATUS Status;
  2135. ULONG value = 0;
  2136. PWSTR DefaultIdentifier = NULL;
  2137. while(Filename = SpGetSectionKeyIndex(SifHandle,SIF_NLS,SifNlsSectionKeyName,value)) {
  2138. value++;
  2139. Identifier = SpGetSectionKeyIndex(SifHandle,SIF_NLS,SifNlsSectionKeyName,value);
  2140. if(!Identifier) {
  2141. SpFatalSifError(SifHandle,SIF_NLS,SifNlsSectionKeyName,0,value);
  2142. }
  2143. //
  2144. // Remember first identifier.
  2145. //
  2146. if(DefaultIdentifier == NULL) {
  2147. DefaultIdentifier = Identifier;
  2148. }
  2149. value++;
  2150. Status = SpOpenSetValueAndClose(
  2151. hKeyNls,
  2152. SubkeyName,
  2153. Identifier,
  2154. STRING_VALUE(Filename)
  2155. );
  2156. if(!NT_SUCCESS(Status)) {
  2157. return(Status);
  2158. }
  2159. }
  2160. if(!value) {
  2161. SpFatalSifError(SifHandle,SIF_NLS,SifNlsSectionKeyName,0,0);
  2162. }
  2163. Status = SpOpenSetValueAndClose(
  2164. hKeyNls,
  2165. SubkeyName,
  2166. EntryName,
  2167. STRING_VALUE(DefaultIdentifier)
  2168. );
  2169. return(Status);
  2170. }
  2171. NTSTATUS
  2172. SpConfigureFonts(
  2173. IN PVOID SifHandle,
  2174. IN HANDLE hKeySoftwareHive
  2175. )
  2176. /*++
  2177. Routine Description:
  2178. Prepare a list of fonts for use with Windows.
  2179. This routine runs down a list of fonts stored in the setup information
  2180. file and adds each one to the registry, in the area that shadows the
  2181. [Fonts] section of win.ini (HKEY_LOCAL_MACHINE\Software\Microsoft\
  2182. Windows NT\CurrentVersion\Fonts). If a particular font value entry
  2183. already exists (e.g., if we're doing an upgrade), then it is left alone.
  2184. Eventually it will add the correct resolution (96 or 120 dpi)
  2185. fonts but for now it only deals with the 96 dpi fonts.
  2186. Arguments:
  2187. SifHandle - supplies a handle to the open text setup information file.
  2188. hKeySoftwareHive - supplies handle to root of software registry hive.
  2189. Return Value:
  2190. Status value indicating outcome of operation.
  2191. --*/
  2192. {
  2193. OBJECT_ATTRIBUTES Obja;
  2194. UNICODE_STRING UnicodeString;
  2195. NTSTATUS Status;
  2196. HANDLE hKey;
  2197. PWSTR FontList;
  2198. PWSTR FontName;
  2199. PWSTR FontDescription;
  2200. ULONG FontCount,font;
  2201. ULONG KeyValueLength;
  2202. //
  2203. // Open HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Fonts.
  2204. //
  2205. INIT_OBJA(
  2206. &Obja,
  2207. &UnicodeString,
  2208. L"Microsoft\\Windows NT\\CurrentVersion\\Fonts"
  2209. );
  2210. Obja.RootDirectory = hKeySoftwareHive;
  2211. Status = ZwCreateKey(
  2212. &hKey,
  2213. KEY_ALL_ACCESS,
  2214. &Obja,
  2215. 0,
  2216. NULL,
  2217. REG_OPTION_NON_VOLATILE,
  2218. NULL
  2219. );
  2220. if(!NT_SUCCESS(Status)) {
  2221. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to open Fonts key (%lx)\n",Status));
  2222. return(Status);
  2223. }
  2224. //
  2225. // For now always use the 96 dpi fonts.
  2226. //
  2227. FontList = L"FontListE";
  2228. //
  2229. // Process each line in the text setup information file section
  2230. // for the selected font list.
  2231. //
  2232. FontCount = SpCountLinesInSection(SifHandle,FontList);
  2233. if(!FontCount) {
  2234. SpFatalSifError(SifHandle,FontList,NULL,0,0);
  2235. }
  2236. for(font=0; font<FontCount; font++) {
  2237. //
  2238. // Fetch the font description.
  2239. //
  2240. FontDescription = SpGetKeyName(SifHandle,FontList,font);
  2241. if(!FontDescription) {
  2242. SpFatalSifError(SifHandle,FontList,NULL,font,(ULONG)(-1));
  2243. }
  2244. //
  2245. // Check to see if a value entry for this font already exists. If so,
  2246. // we want to leave it alone.
  2247. //
  2248. RtlInitUnicodeString(&UnicodeString,FontDescription);
  2249. Status = ZwQueryValueKey(hKey,
  2250. &UnicodeString,
  2251. KeyValueFullInformation,
  2252. (PVOID)NULL,
  2253. 0,
  2254. &KeyValueLength
  2255. );
  2256. if((Status == STATUS_BUFFER_OVERFLOW) || (Status == STATUS_BUFFER_TOO_SMALL)) {
  2257. Status = STATUS_SUCCESS;
  2258. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: Font %ws already exists--entry will not be modified\n", FontDescription));
  2259. continue;
  2260. }
  2261. //
  2262. // Fetch the font filename.
  2263. //
  2264. FontName = SpGetSectionLineIndex(SifHandle,FontList,font,0);
  2265. if(!FontName) {
  2266. SpFatalSifError(SifHandle,FontList,NULL,font,0);
  2267. }
  2268. //
  2269. // Set the entry.
  2270. //
  2271. Status = ZwSetValueKey(hKey,&UnicodeString,0,STRING_VALUE(FontName));
  2272. if(!NT_SUCCESS(Status)) {
  2273. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to set %ws to %ws (%lx)\n",FontDescription,FontName,Status));
  2274. break;
  2275. }
  2276. }
  2277. ZwClose(hKey);
  2278. return(Status);
  2279. }
  2280. NTSTATUS
  2281. SpStoreHwInfoForSetup(
  2282. IN HANDLE hKeyControlSetControl
  2283. )
  2284. /*++
  2285. Routine Description:
  2286. This routine stored information in the registry which will be used by
  2287. GUI setup to determine which options for mouse, display, and keyboard
  2288. are currently selected.
  2289. The data is stored in HKEY_LOCAL_MACHINE\System\<control set>\Control\Setup
  2290. in values pointer, video, and keyboard.
  2291. Arguments:
  2292. hKeyControlSetControl - supplies handle to open key
  2293. HKEY_LOCAL_MACHINE\System\<Control Set>\Control.
  2294. Return Value:
  2295. Status value indicating outcome of operation.
  2296. --*/
  2297. {
  2298. NTSTATUS Status;
  2299. ASSERT(HardwareComponents[HwComponentMouse]->IdString);
  2300. ASSERT(HardwareComponents[HwComponentDisplay]->IdString);
  2301. ASSERT(HardwareComponents[HwComponentKeyboard]->IdString);
  2302. Status = SpOpenSetValueAndClose(
  2303. hKeyControlSetControl,
  2304. SETUP_KEY_NAME,
  2305. L"pointer",
  2306. STRING_VALUE(HardwareComponents[HwComponentMouse]->IdString)
  2307. );
  2308. if(!NT_SUCCESS(Status)) {
  2309. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to set control\\setup\\pointer value (%lx)\n",Status));
  2310. return(Status);
  2311. }
  2312. Status = SpOpenSetValueAndClose(
  2313. hKeyControlSetControl,
  2314. SETUP_KEY_NAME,
  2315. L"video",
  2316. STRING_VALUE(HardwareComponents[HwComponentDisplay]->IdString)
  2317. );
  2318. if(!NT_SUCCESS(Status)) {
  2319. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to set control\\setup\\video value (%lx)\n",Status));
  2320. return(Status);
  2321. }
  2322. Status = SpOpenSetValueAndClose(
  2323. hKeyControlSetControl,
  2324. SETUP_KEY_NAME,
  2325. L"keyboard",
  2326. STRING_VALUE(HardwareComponents[HwComponentKeyboard]->IdString)
  2327. );
  2328. if(!NT_SUCCESS(Status)) {
  2329. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to set control\\setup\\keyboard value (%lx)\n",Status));
  2330. return(Status);
  2331. }
  2332. return(STATUS_SUCCESS);
  2333. }
  2334. NTSTATUS
  2335. SpOpenSetValueAndClose(
  2336. IN HANDLE hKeyRoot,
  2337. IN PWSTR SubKeyName, OPTIONAL
  2338. IN PWSTR ValueName,
  2339. IN ULONG ValueType,
  2340. IN PVOID Value,
  2341. IN ULONG ValueSize
  2342. )
  2343. /*++
  2344. Routine Description:
  2345. Open a subkey, set a value in it, and close the subkey.
  2346. The subkey will be created if it does not exist.
  2347. Arguments:
  2348. hKeyRoot - supplies handle to an open registry key.
  2349. SubKeyName - supplies path relative to hKeyRoot for key in which
  2350. the value is to be set. If this is not specified, then the value
  2351. is set in hKeyRoot.
  2352. ValueName - supplies the name of the value to be set.
  2353. ValueType - supplies the data type for the value to be set.
  2354. Value - supplies a buffer containing the value data.
  2355. ValueSize - supplies the size of the buffer pointed to by Value.
  2356. Return Value:
  2357. Status value indicating outcome of operation.
  2358. --*/
  2359. {
  2360. OBJECT_ATTRIBUTES Obja;
  2361. HANDLE hSubKey;
  2362. UNICODE_STRING UnicodeString;
  2363. NTSTATUS Status;
  2364. //
  2365. // Open or create the subkey in which we want to set the value.
  2366. //
  2367. hSubKey = hKeyRoot;
  2368. if(SubKeyName) {
  2369. //
  2370. // If SubKeyName is a path to the key, then we need to create
  2371. // the subkeys in the path, because they may not exist yet.
  2372. //
  2373. PWSTR p;
  2374. PWSTR q;
  2375. PWSTR r;
  2376. //
  2377. // Since this function may temporarily write to the key path (which may be a constant string,
  2378. // and the system will bug check if we write to it), we need to duplicate the string so that
  2379. // we can write to memory that we own.
  2380. //
  2381. p = SpDupStringW( SubKeyName );
  2382. r = p;
  2383. do {
  2384. //
  2385. // p points to the next subkey to be created.
  2386. // q points to NUL character at the end of the
  2387. // name.
  2388. // r points to the beginning of the duplicated string. It will be used at the end of this
  2389. // routine, when we no longer need the string, so that we can free the alocated memory.
  2390. //
  2391. q = wcschr(p, (WCHAR)'\\');
  2392. if( q != NULL ) {
  2393. //
  2394. // Temporarily replace the '\' with the
  2395. // NUL character
  2396. //
  2397. *q = (WCHAR)'\0';
  2398. }
  2399. INIT_OBJA(&Obja,&UnicodeString,p);
  2400. Obja.RootDirectory = hSubKey;
  2401. Status = ZwCreateKey(
  2402. &hSubKey,
  2403. KEY_ALL_ACCESS,
  2404. &Obja,
  2405. 0,
  2406. NULL,
  2407. REG_OPTION_NON_VOLATILE,
  2408. NULL
  2409. );
  2410. if( q != NULL ) {
  2411. //
  2412. // Restore the '\' in the subkey name, and make
  2413. // p and q point to the remainder of the path
  2414. // that was not processed yet.
  2415. //
  2416. *q = (WCHAR)'\\';
  2417. q++;
  2418. p = q;
  2419. }
  2420. //
  2421. // The parent of the key that we just attempted to open/create
  2422. // is no longer needed.
  2423. //
  2424. if( Obja.RootDirectory != hKeyRoot ) {
  2425. ZwClose( Obja.RootDirectory );
  2426. }
  2427. if(!NT_SUCCESS(Status)) {
  2428. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to open subkey %ws (%lx)\n",SubKeyName,Status));
  2429. return(Status);
  2430. }
  2431. } while( q != NULL );
  2432. SpMemFree( r );
  2433. }
  2434. //
  2435. // Set the value.
  2436. //
  2437. RtlInitUnicodeString(&UnicodeString,ValueName);
  2438. Status = ZwSetValueKey(
  2439. hSubKey,
  2440. &UnicodeString,
  2441. 0,
  2442. ValueType,
  2443. Value,
  2444. ValueSize
  2445. );
  2446. if(!NT_SUCCESS(Status)) {
  2447. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to set value %ws:%ws (%lx)\n",SubKeyName,ValueName,Status));
  2448. }
  2449. if(SubKeyName) {
  2450. ZwClose(hSubKey);
  2451. }
  2452. return(Status);
  2453. }
  2454. NTSTATUS
  2455. SpGetProductSuiteMask(
  2456. IN HANDLE hKeyControlSetControl,
  2457. OUT PULONG SuiteMask
  2458. )
  2459. {
  2460. OBJECT_ATTRIBUTES Obja;
  2461. HANDLE hSubKey;
  2462. UNICODE_STRING UnicodeString;
  2463. NTSTATUS Status;
  2464. UCHAR Buffer[MAX_PRODUCT_SUITE_BYTES];
  2465. ULONG BufferLength;
  2466. ULONG ResultLength = 0;
  2467. PWSTR p;
  2468. PUCHAR Data;
  2469. ULONG DataLength;
  2470. BOOLEAN SuiteFound = FALSE;
  2471. ULONG i,j;
  2472. *SuiteMask = 0;
  2473. //
  2474. // Open or create the subkey in which we want to set the value.
  2475. //
  2476. INIT_OBJA(&Obja,&UnicodeString,PRODUCT_OPTIONS_KEY_NAME);
  2477. Obja.RootDirectory = hKeyControlSetControl;
  2478. Status = ZwCreateKey(
  2479. &hSubKey,
  2480. KEY_ALL_ACCESS,
  2481. &Obja,
  2482. 0,
  2483. NULL,
  2484. REG_OPTION_NON_VOLATILE,
  2485. NULL
  2486. );
  2487. if(!NT_SUCCESS(Status)) {
  2488. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to open subkey (%lx)\n",Status));
  2489. return(Status);
  2490. }
  2491. //
  2492. // query the current value
  2493. //
  2494. INIT_OBJA(&Obja,&UnicodeString,PRODUCT_SUITE_VALUE_NAME);
  2495. BufferLength = sizeof(Buffer);
  2496. RtlZeroMemory( Buffer, BufferLength );
  2497. Status = ZwQueryValueKey(
  2498. hSubKey,
  2499. &UnicodeString,
  2500. KeyValuePartialInformation,
  2501. Buffer,
  2502. BufferLength,
  2503. &ResultLength
  2504. );
  2505. if((!NT_SUCCESS(Status)) && (Status != STATUS_OBJECT_NAME_NOT_FOUND)) {
  2506. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to query subkey (%lx)\n",Status));
  2507. return(Status);
  2508. }
  2509. if (ResultLength == BufferLength) {
  2510. //
  2511. // the buffer is too small, this should not happen
  2512. // unless we have too many suites
  2513. //
  2514. ZwClose(hSubKey);
  2515. return STATUS_BUFFER_OVERFLOW;
  2516. }
  2517. if (ResultLength) {
  2518. Data = (PUCHAR)(((PKEY_VALUE_PARTIAL_INFORMATION)Buffer)->Data);
  2519. if (((PWSTR)Data)[0] == 0) {
  2520. ((PKEY_VALUE_PARTIAL_INFORMATION)Buffer)->DataLength -= sizeof(WCHAR);
  2521. }
  2522. DataLength = ((PKEY_VALUE_PARTIAL_INFORMATION)Buffer)->DataLength;
  2523. p = (PWSTR)Data;
  2524. i = 0;
  2525. while (i<DataLength) {
  2526. for (j=0; j<CountProductSuiteNames; j++) {
  2527. if (ProductSuiteNames[j] != NULL && wcscmp(p,ProductSuiteNames[j]) == 0) {
  2528. *SuiteMask |= (1 << j);
  2529. }
  2530. }
  2531. if (*p < L'A' || *p > L'z') {
  2532. i += 1;
  2533. p += 1;
  2534. } else {
  2535. i += (wcslen( p ) + 1);
  2536. p += (wcslen( p ) + 1);
  2537. }
  2538. }
  2539. }
  2540. ZwClose(hSubKey);
  2541. return(Status);
  2542. }
  2543. NTSTATUS
  2544. SpSetProductSuite(
  2545. IN HANDLE hKeyControlSetControl,
  2546. IN ULONG SuiteMask
  2547. )
  2548. {
  2549. OBJECT_ATTRIBUTES Obja;
  2550. HANDLE hSubKey;
  2551. UNICODE_STRING UnicodeString;
  2552. NTSTATUS Status;
  2553. UCHAR Buffer[MAX_PRODUCT_SUITE_BYTES];
  2554. ULONG BufferLength;
  2555. ULONG ResultLength = 0;
  2556. PWSTR p;
  2557. PUCHAR Data;
  2558. ULONG DataLength;
  2559. BOOLEAN SuiteFound = FALSE;
  2560. ULONG i;
  2561. ULONG tmp;
  2562. //
  2563. // Open or create the subkey in which we want to set the value.
  2564. //
  2565. INIT_OBJA(&Obja,&UnicodeString,PRODUCT_OPTIONS_KEY_NAME);
  2566. Obja.RootDirectory = hKeyControlSetControl;
  2567. Status = ZwCreateKey(
  2568. &hSubKey,
  2569. KEY_ALL_ACCESS,
  2570. &Obja,
  2571. 0,
  2572. NULL,
  2573. REG_OPTION_NON_VOLATILE,
  2574. NULL
  2575. );
  2576. if(!NT_SUCCESS(Status)) {
  2577. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to open subkey (%lx)\n",Status));
  2578. return(Status);
  2579. }
  2580. RtlZeroMemory( Buffer, sizeof(Buffer) );
  2581. tmp = SuiteMask;
  2582. p = (PWSTR)Buffer;
  2583. i = 0;
  2584. while (tmp && i<CountProductSuiteNames) {
  2585. if ((tmp&1) && ProductSuiteNames[i] != NULL) {
  2586. wcscpy(p,ProductSuiteNames[i]);
  2587. p += (wcslen(p) + 1);
  2588. }
  2589. i += 1;
  2590. tmp >>= 1;
  2591. }
  2592. BufferLength = (ULONG)((ULONG_PTR)p - (ULONG_PTR)Buffer) + sizeof(WCHAR);
  2593. //
  2594. // Set the value.
  2595. //
  2596. INIT_OBJA(&Obja,&UnicodeString,PRODUCT_SUITE_VALUE_NAME);
  2597. Status = ZwSetValueKey(
  2598. hSubKey,
  2599. &UnicodeString,
  2600. 0,
  2601. REG_MULTI_SZ,
  2602. Buffer,
  2603. BufferLength
  2604. );
  2605. if(!NT_SUCCESS(Status)) {
  2606. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to set value (%lx)\n",Status));
  2607. }
  2608. ZwClose(hSubKey);
  2609. return Status;
  2610. }
  2611. NTSTATUS
  2612. SpCreateServiceEntryIndirect(
  2613. IN HANDLE hKeyControlSetServices,
  2614. IN PVOID SifHandle, OPTIONAL
  2615. IN PWSTR SifSectionName, OPTIONAL
  2616. IN PWSTR KeyName,
  2617. IN ULONG ServiceType,
  2618. IN ULONG ServiceStart,
  2619. IN PWSTR ServiceGroup, OPTIONAL
  2620. IN ULONG ServiceError,
  2621. IN PWSTR FileName, OPTIONAL
  2622. OUT PHANDLE SubkeyHandle OPTIONAL
  2623. )
  2624. {
  2625. HANDLE hKeyService;
  2626. OBJECT_ATTRIBUTES Obja;
  2627. NTSTATUS Status;
  2628. UNICODE_STRING UnicodeString;
  2629. PWSTR pwstr;
  2630. //
  2631. // Look in the sif file to get the subkey name within the
  2632. // services list, unless the key name specified by the caller
  2633. // is the actual key name.
  2634. //
  2635. if(SifHandle) {
  2636. pwstr = SpGetSectionKeyIndex(SifHandle,SifSectionName,KeyName,INDEX_INFKEYNAME);
  2637. if(!pwstr) {
  2638. SpFatalSifError(SifHandle,SifSectionName,KeyName,0,INDEX_INFKEYNAME);
  2639. }
  2640. KeyName = pwstr;
  2641. }
  2642. //
  2643. // Create the subkey in the services key.
  2644. //
  2645. INIT_OBJA(&Obja,&UnicodeString,KeyName);
  2646. Obja.RootDirectory = hKeyControlSetServices;
  2647. Status = ZwCreateKey(
  2648. &hKeyService,
  2649. KEY_ALL_ACCESS,
  2650. &Obja,
  2651. 0,
  2652. NULL,
  2653. REG_OPTION_NON_VOLATILE,
  2654. NULL
  2655. );
  2656. if(!NT_SUCCESS(Status)) {
  2657. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to open/create key for %ws service (%lx)\n",KeyName,Status));
  2658. return (Status) ;
  2659. }
  2660. //
  2661. // Set the service type.
  2662. //
  2663. RtlInitUnicodeString(&UnicodeString, REGSTR_VALUE_TYPE);
  2664. Status = ZwSetValueKey(
  2665. hKeyService,
  2666. &UnicodeString,
  2667. 0,
  2668. ULONG_VALUE(ServiceType)
  2669. );
  2670. if(!NT_SUCCESS(Status)) {
  2671. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to set service %ws Type (%lx)\n",KeyName,Status));
  2672. goto spcsie1;
  2673. }
  2674. //
  2675. // Set the service start type.
  2676. //
  2677. RtlInitUnicodeString(&UnicodeString,L"Start");
  2678. Status = ZwSetValueKey(
  2679. hKeyService,
  2680. &UnicodeString,
  2681. 0,
  2682. ULONG_VALUE(ServiceStart)
  2683. );
  2684. if(!NT_SUCCESS(Status)) {
  2685. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to set service %ws Start (%lx)\n",KeyName,Status));
  2686. goto spcsie1;
  2687. }
  2688. if( ServiceGroup != NULL ) {
  2689. //
  2690. // Set the service group name.
  2691. //
  2692. RtlInitUnicodeString(&UnicodeString,L"Group");
  2693. Status = ZwSetValueKey(
  2694. hKeyService,
  2695. &UnicodeString,
  2696. 0,
  2697. STRING_VALUE(ServiceGroup)
  2698. );
  2699. if(!NT_SUCCESS(Status)) {
  2700. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to set service %ws Group (%lx)\n",KeyName,Status));
  2701. goto spcsie1;
  2702. }
  2703. }
  2704. //
  2705. // Set the service error type.
  2706. //
  2707. RtlInitUnicodeString(&UnicodeString,L"ErrorControl");
  2708. Status = ZwSetValueKey(
  2709. hKeyService,
  2710. &UnicodeString,
  2711. 0,
  2712. ULONG_VALUE(ServiceError)
  2713. );
  2714. if(!NT_SUCCESS(Status)) {
  2715. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to set service %ws ErrorControl (%lx)\n",KeyName,Status));
  2716. goto spcsie1;
  2717. }
  2718. //
  2719. // If asked to do so, set the service image path.
  2720. //
  2721. if(FileName) {
  2722. pwstr = TemporaryBuffer;
  2723. wcscpy(pwstr,L"system32\\drivers");
  2724. SpConcatenatePaths(pwstr,FileName);
  2725. RtlInitUnicodeString(&UnicodeString,L"ImagePath");
  2726. Status = ZwSetValueKey(hKeyService,&UnicodeString,0,STRING_VALUE(pwstr));
  2727. if(!NT_SUCCESS(Status)) {
  2728. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to set service %w image path (%lx)\n",KeyName,Status));
  2729. goto spcsie1;
  2730. }
  2731. } else {
  2732. if(NTUpgrade == UpgradeFull) {
  2733. //
  2734. // Delete imagepath on upgrade. This makes sure we are getting
  2735. // our driver, and from the right place. Fixes Compaq's SSD stuff,
  2736. // for example. Do something similar for PlugPlayServiceType, in case
  2737. // we are renabling a device that the user disabled (in which case
  2738. // the PlugPlayServiceType could cause us to fail to make up a
  2739. // device instance for a legacy device, and cause the driver to fail
  2740. // to load/initialize.
  2741. //
  2742. RtlInitUnicodeString(&UnicodeString,L"ImagePath");
  2743. Status = ZwDeleteValueKey(hKeyService,&UnicodeString);
  2744. if(!NT_SUCCESS(Status)) {
  2745. if (Status != STATUS_OBJECT_NAME_NOT_FOUND) {
  2746. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to remove imagepath from service %ws (%lx)\n",KeyName,Status));
  2747. }
  2748. Status = STATUS_SUCCESS;
  2749. }
  2750. RtlInitUnicodeString(&UnicodeString,L"PlugPlayServiceType");
  2751. Status = ZwDeleteValueKey(hKeyService,&UnicodeString);
  2752. if(!NT_SUCCESS(Status)) {
  2753. if (Status != STATUS_OBJECT_NAME_NOT_FOUND) {
  2754. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to remove plugplayservicetype from service %ws (%lx)\n",KeyName,Status));
  2755. }
  2756. Status = STATUS_SUCCESS;
  2757. }
  2758. }
  2759. }
  2760. //
  2761. // If the caller doesn't want the handle to the service subkey
  2762. // we just created, close the handle. If we are returning an
  2763. // error, always close it.
  2764. //
  2765. spcsie1:
  2766. if(NT_SUCCESS(Status) && SubkeyHandle) {
  2767. *SubkeyHandle = hKeyService;
  2768. } else {
  2769. ZwClose(hKeyService);
  2770. }
  2771. //
  2772. // Done.
  2773. //
  2774. return(Status);
  2775. }
  2776. NTSTATUS
  2777. SpThirdPartyRegistry(
  2778. IN PVOID hKeyControlSetServices
  2779. )
  2780. {
  2781. OBJECT_ATTRIBUTES Obja;
  2782. UNICODE_STRING UnicodeString;
  2783. NTSTATUS Status;
  2784. HANDLE hKeyEventLogSystem;
  2785. HwComponentType Component;
  2786. PHARDWARE_COMPONENT Dev;
  2787. PHARDWARE_COMPONENT_REGISTRY Reg;
  2788. PHARDWARE_COMPONENT_FILE File;
  2789. WCHAR NodeName[9];
  2790. ULONG DriverType;
  2791. ULONG DriverStart;
  2792. ULONG DriverErrorControl;
  2793. PWSTR DriverGroup;
  2794. HANDLE hKeyService;
  2795. //
  2796. // Open HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\EventLog\System
  2797. //
  2798. INIT_OBJA(&Obja,&UnicodeString,L"EventLog\\System");
  2799. Obja.RootDirectory = hKeyControlSetServices;
  2800. Status = ZwCreateKey(
  2801. &hKeyEventLogSystem,
  2802. KEY_ALL_ACCESS,
  2803. &Obja,
  2804. 0,
  2805. NULL,
  2806. REG_OPTION_NON_VOLATILE,
  2807. NULL
  2808. );
  2809. if(!NT_SUCCESS(Status)) {
  2810. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: SpThirdPartyRegistry: couldn't open eventlog\\system (%lx)",Status));
  2811. return(Status);
  2812. }
  2813. for(Component=0; Component<=HwComponentMax; Component++) {
  2814. // no registry stuff applicable to keyboard layout
  2815. if(Component == HwComponentLayout) {
  2816. continue;
  2817. }
  2818. Dev = (Component == HwComponentMax)
  2819. ? ((!PreInstall ||
  2820. (PreinstallScsiHardware==NULL))? ScsiHardware :
  2821. PreinstallScsiHardware)
  2822. : ((!PreInstall ||
  2823. (PreinstallHardwareComponents[Component]==NULL))? HardwareComponents[Component] :
  2824. PreinstallHardwareComponents[Component]);
  2825. for( ; Dev; Dev = Dev->Next) {
  2826. //
  2827. // If there is no third-party option selected here, then skip
  2828. // the component.
  2829. //
  2830. if(!Dev->ThirdPartyOptionSelected) {
  2831. continue;
  2832. }
  2833. //
  2834. // Iterate through the files for this device. If a file has
  2835. // a ServiceKeyName, create the key and add values in it
  2836. // as appropriate.
  2837. //
  2838. for(File=Dev->Files; File; File=File->Next) {
  2839. HwFileType filetype = File->FileType;
  2840. PWSTR p;
  2841. ULONG dw;
  2842. //
  2843. // If there is to be no node for this file, skip it.
  2844. //
  2845. if(!File->ConfigName) {
  2846. continue;
  2847. }
  2848. //
  2849. // Calculate the node name. This is the name of the driver
  2850. // without the extension.
  2851. //
  2852. wcsncpy(NodeName,File->Filename,8);
  2853. NodeName[8] = 0;
  2854. if(p = wcschr(NodeName,L'.')) {
  2855. *p = 0;
  2856. }
  2857. //
  2858. // The driver type and error control are always the same.
  2859. //
  2860. DriverType = SERVICE_KERNEL_DRIVER;
  2861. DriverErrorControl = SERVICE_ERROR_NORMAL;
  2862. //
  2863. // The start type depends on the component.
  2864. // For scsi, it's boot loader start. For others, it's
  2865. // system start.
  2866. //
  2867. DriverStart = (Component == HwComponentMax)
  2868. ? SERVICE_BOOT_START
  2869. : SERVICE_SYSTEM_START;
  2870. //
  2871. // The group depends on the component.
  2872. //
  2873. switch(Component) {
  2874. case HwComponentDisplay:
  2875. DriverGroup = L"Video";
  2876. break;
  2877. case HwComponentMouse:
  2878. if(filetype == HwFileClass) {
  2879. DriverGroup = L"Pointer Class";
  2880. } else {
  2881. DriverGroup = L"Pointer Port";
  2882. }
  2883. break;
  2884. case HwComponentKeyboard:
  2885. if(filetype == HwFileClass) {
  2886. DriverGroup = L"Keyboard Class";
  2887. } else {
  2888. DriverGroup = L"Keyboard Port";
  2889. }
  2890. break;
  2891. case HwComponentMax:
  2892. DriverGroup = L"SCSI miniport";
  2893. break;
  2894. default:
  2895. DriverGroup = L"Base";
  2896. break;
  2897. }
  2898. //
  2899. // Attempt to create the service entry.
  2900. //
  2901. Status = SpCreateServiceEntryIndirect(
  2902. hKeyControlSetServices,
  2903. NULL,
  2904. NULL,
  2905. NodeName,
  2906. DriverType,
  2907. DriverStart,
  2908. DriverGroup,
  2909. DriverErrorControl,
  2910. File->Filename,
  2911. &hKeyService
  2912. );
  2913. if(!NT_SUCCESS(Status)) {
  2914. goto sp3reg1;
  2915. }
  2916. //
  2917. // Create a default eventlog configuration.
  2918. //
  2919. Status = SpOpenSetValueAndClose(
  2920. hKeyEventLogSystem,
  2921. NodeName,
  2922. L"EventMessageFile",
  2923. REG_EXPAND_SZ,
  2924. DEFAULT_EVENT_LOG,
  2925. (wcslen(DEFAULT_EVENT_LOG)+1)*sizeof(WCHAR)
  2926. );
  2927. if(!NT_SUCCESS(Status)) {
  2928. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: SpThirdPartyRegistry: unable to set eventlog %ws EventMessageFile",NodeName));
  2929. ZwClose(hKeyService);
  2930. goto sp3reg1;
  2931. }
  2932. dw = 7;
  2933. Status = SpOpenSetValueAndClose(
  2934. hKeyEventLogSystem,
  2935. NodeName,
  2936. L"TypesSupported",
  2937. ULONG_VALUE(dw)
  2938. );
  2939. if(!NT_SUCCESS(Status)) {
  2940. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: SpThirdPartyRegistry: unable to set eventlog %ws TypesSupported",NodeName));
  2941. ZwClose(hKeyService);
  2942. goto sp3reg1;
  2943. }
  2944. for(Reg=File->RegistryValueList; Reg; Reg=Reg->Next) {
  2945. //
  2946. // If the key name is null or empty, there is no key to create;
  2947. // use the load list node itself in this case. Otherwise create
  2948. // the subkey in the load list node.
  2949. //
  2950. Status = SpOpenSetValueAndClose(
  2951. hKeyService,
  2952. (Reg->KeyName && *Reg->KeyName) ? Reg->KeyName : NULL,
  2953. Reg->ValueName,
  2954. Reg->ValueType,
  2955. Reg->Buffer,
  2956. Reg->BufferSize
  2957. );
  2958. if(!NT_SUCCESS(Status)) {
  2959. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  2960. "SETUP: SpThirdPartyRegistry: unable to set value %ws (%lx)\n",
  2961. Reg->ValueName,
  2962. Status
  2963. ));
  2964. ZwClose(hKeyService);
  2965. goto sp3reg1;
  2966. }
  2967. }
  2968. ZwClose(hKeyService);
  2969. }
  2970. }
  2971. }
  2972. sp3reg1:
  2973. ZwClose(hKeyEventLogSystem);
  2974. return(Status);
  2975. }
  2976. NTSTATUS
  2977. SpDetermineProduct(
  2978. IN PDISK_REGION TargetRegion,
  2979. IN PWSTR SystemRoot,
  2980. OUT PNT_PRODUCT_TYPE ProductType,
  2981. OUT ULONG *MajorVersion,
  2982. OUT ULONG *MinorVersion,
  2983. OUT ULONG *BuildNumber, OPTIONAL
  2984. OUT ULONG *ProductSuiteMask,
  2985. OUT UPG_PROGRESS_TYPE *UpgradeProgressValue,
  2986. OUT PWSTR *UniqueIdFromReg, OPTIONAL
  2987. OUT PWSTR *Pid, OPTIONAL
  2988. OUT PBOOLEAN pIsEvalVariation OPTIONAL,
  2989. OUT PLCID LangId,
  2990. OUT ULONG *ServicePack OPTIONAL
  2991. )
  2992. {
  2993. OBJECT_ATTRIBUTES Obja;
  2994. UNICODE_STRING UnicodeString;
  2995. NTSTATUS Status, TempStatus;
  2996. PWSTR Hive,HiveKey;
  2997. PUCHAR buffer;
  2998. #define BUFFERSIZE (sizeof(KEY_VALUE_PARTIAL_INFORMATION)+256)
  2999. BOOLEAN HiveLoaded = FALSE;
  3000. PWSTR PartitionPath = NULL;
  3001. PWSTR p;
  3002. HANDLE hKeyRoot = NULL, hKeyCCSet = NULL;
  3003. ULONG ResultLength;
  3004. ULONG Number;
  3005. ULONG i;
  3006. //
  3007. // Allocate buffers.
  3008. //
  3009. Hive = SpMemAlloc(MAX_PATH * sizeof(WCHAR));
  3010. HiveKey = SpMemAlloc(MAX_PATH * sizeof(WCHAR));
  3011. buffer = SpMemAlloc(BUFFERSIZE);
  3012. //
  3013. // Get the name of the target partition.
  3014. //
  3015. SpNtNameFromRegion(
  3016. TargetRegion,
  3017. TemporaryBuffer,
  3018. sizeof(TemporaryBuffer),
  3019. PartitionOrdinalCurrent
  3020. );
  3021. PartitionPath = SpDupStringW(TemporaryBuffer);
  3022. //
  3023. // Load the system hive
  3024. //
  3025. wcscpy(Hive,PartitionPath);
  3026. SpConcatenatePaths(Hive,SystemRoot);
  3027. SpConcatenatePaths(Hive,L"system32\\config");
  3028. SpConcatenatePaths(Hive,L"system");
  3029. //
  3030. // Form the path of the key into which we will
  3031. // load the hive. We'll use the convention that
  3032. // a hive will be loaded into \registry\machine\x<hivename>.
  3033. //
  3034. wcscpy(HiveKey,LOCAL_MACHINE_KEY_NAME);
  3035. SpConcatenatePaths(HiveKey,L"xSystem");
  3036. //
  3037. // Attempt to load the key.
  3038. //
  3039. Status = SpLoadUnloadKey(NULL,NULL,HiveKey,Hive);
  3040. if(!NT_SUCCESS(Status)) {
  3041. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to load hive %ws to key %ws (%lx)\n",Hive,HiveKey,Status));
  3042. goto spdp_1;
  3043. }
  3044. HiveLoaded = TRUE;
  3045. //
  3046. // Now get a key to the root of the hive we just loaded.
  3047. //
  3048. INIT_OBJA(&Obja,&UnicodeString,HiveKey);
  3049. Status = ZwOpenKey(&hKeyRoot,KEY_ALL_ACCESS,&Obja);
  3050. if(!NT_SUCCESS(Status)) {
  3051. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to open %ws (%lx)\n",HiveKey,Status));
  3052. goto spdp_2;
  3053. }
  3054. //
  3055. // Get the unique identifier if needed.
  3056. // This value is not always present.
  3057. //
  3058. if(UniqueIdFromReg) {
  3059. *UniqueIdFromReg = NULL;
  3060. Status = SpGetValueKey(
  3061. hKeyRoot,
  3062. SETUP_KEY_NAME,
  3063. SIF_UNIQUEID,
  3064. BUFFERSIZE,
  3065. buffer,
  3066. &ResultLength
  3067. );
  3068. if(NT_SUCCESS(Status)) {
  3069. *UniqueIdFromReg = SpDupStringW((PWSTR)(((PKEY_VALUE_PARTIAL_INFORMATION)buffer)->Data));
  3070. }
  3071. // no error if not found.
  3072. }
  3073. //
  3074. // See if this is a failed upgrade
  3075. //
  3076. *UpgradeProgressValue = UpgradeNotInProgress;
  3077. Status = SpGetValueKey(
  3078. hKeyRoot,
  3079. SETUP_KEY_NAME,
  3080. UPGRADE_IN_PROGRESS,
  3081. BUFFERSIZE,
  3082. buffer,
  3083. &ResultLength
  3084. );
  3085. if(NT_SUCCESS(Status)) {
  3086. DWORD dw;
  3087. if( (dw = *(DWORD *)(((PKEY_VALUE_PARTIAL_INFORMATION)buffer)->Data)) < UpgradeMaxValue ) {
  3088. *UpgradeProgressValue = (UPG_PROGRESS_TYPE)dw;
  3089. }
  3090. }
  3091. //
  3092. // Get the key to the current control set
  3093. //
  3094. Status = SpGetCurrentControlSetNumber(hKeyRoot,&Number);
  3095. if(!NT_SUCCESS(Status)) {
  3096. goto spdp_3;
  3097. }
  3098. swprintf((PVOID)buffer,L"ControlSet%03d",Number);
  3099. INIT_OBJA(&Obja,&UnicodeString,(PVOID)buffer);
  3100. Obja.RootDirectory = hKeyRoot;
  3101. Status = ZwOpenKey(&hKeyCCSet,KEY_READ,&Obja);
  3102. if(!NT_SUCCESS(Status)) {
  3103. goto spdp_3;
  3104. }
  3105. //
  3106. // Get the Product type field
  3107. //
  3108. Status = SpGetValueKey(
  3109. hKeyCCSet,
  3110. L"Control\\ProductOptions",
  3111. L"ProductType",
  3112. BUFFERSIZE,
  3113. buffer,
  3114. &ResultLength
  3115. );
  3116. if(!NT_SUCCESS(Status)) {
  3117. goto spdp_3;
  3118. }
  3119. if( _wcsicmp( (PWSTR)(((PKEY_VALUE_PARTIAL_INFORMATION)buffer)->Data), L"WinNT" ) == 0 ) {
  3120. *ProductType = NtProductWinNt;
  3121. } else if( _wcsicmp( (PWSTR)(((PKEY_VALUE_PARTIAL_INFORMATION)buffer)->Data), L"LanmanNt" ) == 0 ) {
  3122. *ProductType = NtProductLanManNt;
  3123. } else if( _wcsicmp( (PWSTR)(((PKEY_VALUE_PARTIAL_INFORMATION)buffer)->Data), L"ServerNt" ) == 0 ) {
  3124. *ProductType = NtProductServer;
  3125. } else {
  3126. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Error, unknown ProductType = %ls. Assuming WinNt \n",
  3127. (PWSTR)(((PKEY_VALUE_PARTIAL_INFORMATION)buffer)->Data) ));
  3128. *ProductType = NtProductWinNt;
  3129. }
  3130. *ProductSuiteMask = 0;
  3131. Status = SpGetValueKey(
  3132. hKeyCCSet,
  3133. L"Control\\ProductOptions",
  3134. L"ProductSuite",
  3135. BUFFERSIZE,
  3136. buffer,
  3137. &ResultLength
  3138. );
  3139. if(NT_SUCCESS(Status)) {
  3140. p = (PWSTR)(((PKEY_VALUE_PARTIAL_INFORMATION)buffer)->Data);
  3141. while (p && *p) {
  3142. for (i = 0; i < CountProductSuiteNames; i++) {
  3143. if (ProductSuiteNames[i] != NULL && _wcsicmp( p, ProductSuiteNames[i]) == 0) {
  3144. *ProductSuiteMask |= (1 << i);
  3145. break;
  3146. }
  3147. }
  3148. p = p + wcslen(p) + 1;
  3149. }
  3150. } else {
  3151. Status = SpGetValueKey(
  3152. hKeyCCSet,
  3153. L"Control\\Citrix",
  3154. L"OemId",
  3155. BUFFERSIZE,
  3156. buffer,
  3157. &ResultLength
  3158. );
  3159. if (NT_SUCCESS(Status)) {
  3160. PWSTR wbuff = (PWSTR)(((PKEY_VALUE_PARTIAL_INFORMATION)buffer)->Data);
  3161. if (*wbuff != L'\0') {
  3162. *ProductSuiteMask |= VER_SUITE_TERMINAL;
  3163. }
  3164. }
  3165. }
  3166. if (LangId) {
  3167. PWSTR EndChar;
  3168. PWSTR Value = 0;
  3169. //
  3170. // Get the install language ID
  3171. //
  3172. Status = SpGetValueKey(
  3173. hKeyCCSet,
  3174. L"Control\\Nls\\Language",
  3175. L"InstallLanguage",
  3176. BUFFERSIZE,
  3177. buffer,
  3178. &ResultLength
  3179. );
  3180. if (!NT_SUCCESS(Status) || !buffer || !ResultLength) {
  3181. //
  3182. // Try to get default Language ID if we can't get install
  3183. // language ID
  3184. //
  3185. Status = SpGetValueKey(
  3186. hKeyCCSet,
  3187. L"Control\\Nls\\Language",
  3188. L"Default",
  3189. BUFFERSIZE,
  3190. buffer,
  3191. &ResultLength
  3192. );
  3193. if (!NT_SUCCESS(Status) || !buffer || !ResultLength)
  3194. goto spdp_3;
  3195. }
  3196. Value = (PWSTR)(((PKEY_VALUE_PARTIAL_INFORMATION)buffer)->Data);
  3197. *LangId = (LANGID)SpStringToLong(Value, &EndChar, 16); // hex base
  3198. }
  3199. //
  3200. // Get the Eval variation flag
  3201. //
  3202. if (pIsEvalVariation) {
  3203. *pIsEvalVariation = FALSE;
  3204. Status = SpGetValueKey(
  3205. hKeyCCSet,
  3206. L"Control\\Session Manager\\Executive",
  3207. L"PriorityQuantumMatrix",
  3208. BUFFERSIZE,
  3209. buffer,
  3210. &ResultLength);
  3211. if (NT_SUCCESS(Status)) {
  3212. PKEY_VALUE_PARTIAL_INFORMATION pValInfo =
  3213. (PKEY_VALUE_PARTIAL_INFORMATION)buffer;
  3214. PBYTE pData = (PBYTE)(((PKEY_VALUE_PARTIAL_INFORMATION)buffer)->Data);
  3215. //
  3216. // Note : PriorityQantumMatix Value is made up of 3 ULONGS
  3217. // Low Install Date&Time ULONG, Eval Duration (ULONG),
  3218. // High Install Date&Time ULONG
  3219. //
  3220. if (pData && pValInfo && (pValInfo->Type == REG_BINARY) &&
  3221. (ResultLength >= 8) && *(((ULONG *)pData) + 1)) {
  3222. *pIsEvalVariation = TRUE;
  3223. }
  3224. } else {
  3225. // discard the error (NT 3.51 and below version does not have this key)
  3226. Status = STATUS_SUCCESS;
  3227. }
  3228. }
  3229. //
  3230. // Get the ServicePack Number
  3231. //
  3232. if(ServicePack) {
  3233. *ServicePack = 0;
  3234. Status = SpGetValueKey(
  3235. hKeyCCSet,
  3236. L"Control\\Windows",
  3237. L"CSDVersion",
  3238. BUFFERSIZE,
  3239. buffer,
  3240. &ResultLength
  3241. );
  3242. if (NT_SUCCESS(Status)) {
  3243. PKEY_VALUE_PARTIAL_INFORMATION pValInfo =
  3244. (PKEY_VALUE_PARTIAL_INFORMATION)buffer;
  3245. if (pValInfo && pValInfo->Data && (pValInfo->Type == REG_DWORD)) {
  3246. *ServicePack = ((*(PULONG)(pValInfo->Data)) >> 8 & (0xff)) * 100
  3247. + ((*(PULONG)(pValInfo->Data)) & 0xff);
  3248. }
  3249. } else {
  3250. // discard the error
  3251. Status = STATUS_SUCCESS;
  3252. }
  3253. }
  3254. //
  3255. // Close the hive key
  3256. //
  3257. ZwClose( hKeyCCSet );
  3258. ZwClose( hKeyRoot );
  3259. hKeyRoot = NULL;
  3260. hKeyCCSet = NULL;
  3261. //
  3262. // Unload the system hive
  3263. //
  3264. TempStatus = SpLoadUnloadKey(NULL,NULL,HiveKey,NULL);
  3265. if(!NT_SUCCESS(TempStatus)) {
  3266. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: warning: unable to unload key %ws (%lx)\n",HiveKey,TempStatus));
  3267. }
  3268. HiveLoaded = FALSE;
  3269. //
  3270. // Load the software hive
  3271. //
  3272. wcscpy(Hive,PartitionPath);
  3273. SpConcatenatePaths(Hive,SystemRoot);
  3274. SpConcatenatePaths(Hive,L"system32\\config");
  3275. SpConcatenatePaths(Hive,L"software");
  3276. //
  3277. // Form the path of the key into which we will
  3278. // load the hive. We'll use the convention that
  3279. // a hive will be loaded into \registry\machine\x<hivename>.
  3280. //
  3281. wcscpy(HiveKey,LOCAL_MACHINE_KEY_NAME);
  3282. SpConcatenatePaths(HiveKey,L"x");
  3283. wcscat(HiveKey,L"software");
  3284. //
  3285. // Attempt to load the key.
  3286. //
  3287. Status = SpLoadUnloadKey(NULL,NULL,HiveKey,Hive);
  3288. if(!NT_SUCCESS(Status)) {
  3289. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to load hive %ws to key %ws (%lx)\n",Hive,HiveKey,Status));
  3290. goto spdp_1;
  3291. }
  3292. HiveLoaded = TRUE;
  3293. //
  3294. // Now get a key to the root of the hive we just loaded.
  3295. //
  3296. INIT_OBJA(&Obja,&UnicodeString,HiveKey);
  3297. Status = ZwOpenKey(&hKeyRoot,KEY_ALL_ACCESS,&Obja);
  3298. if(!NT_SUCCESS(Status)) {
  3299. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to open %ws (%lx)\n",HiveKey,Status));
  3300. goto spdp_2;
  3301. }
  3302. //
  3303. // Query the version of the NT
  3304. //
  3305. Status = SpGetValueKey(
  3306. hKeyRoot,
  3307. L"Microsoft\\Windows NT\\CurrentVersion",
  3308. L"CurrentVersion",
  3309. BUFFERSIZE,
  3310. buffer,
  3311. &ResultLength
  3312. );
  3313. //
  3314. // Convert the version into a dword
  3315. //
  3316. {
  3317. WCHAR wcsMajorVersion[] = L"0";
  3318. WCHAR wcsMinorVersion[] = L"00";
  3319. PWSTR Version = (PWSTR)(((PKEY_VALUE_PARTIAL_INFORMATION)buffer)->Data);
  3320. if( Version[0] && Version[1] && Version[2] ) {
  3321. wcsMajorVersion[0] = Version[0];
  3322. wcsMinorVersion[0] = Version[2];
  3323. if( Version[3] ) {
  3324. wcsMinorVersion[1] = Version[3];
  3325. }
  3326. }
  3327. *MajorVersion = (ULONG)SpStringToLong( wcsMajorVersion, NULL, 10 );
  3328. *MinorVersion = (ULONG)SpStringToLong( wcsMinorVersion, NULL, 10 );
  3329. }
  3330. //
  3331. // EVAL variations on NT 5.0 are detected using MPC code
  3332. // (This is to allow pre 5.0 RTM builds with timebomb to
  3333. // upgrade properly
  3334. //
  3335. if (pIsEvalVariation && (*MajorVersion >= 5))
  3336. *pIsEvalVariation = FALSE;
  3337. //
  3338. // Get build number
  3339. //
  3340. if(BuildNumber) {
  3341. Status = SpGetValueKey(
  3342. hKeyRoot,
  3343. L"Microsoft\\Windows NT\\CurrentVersion",
  3344. L"CurrentBuildNumber",
  3345. BUFFERSIZE,
  3346. buffer,
  3347. &ResultLength
  3348. );
  3349. *BuildNumber = NT_SUCCESS(Status)
  3350. ? (ULONG)SpStringToLong((PWSTR)(((PKEY_VALUE_PARTIAL_INFORMATION)buffer)->Data),NULL,10)
  3351. : 0;
  3352. }
  3353. //
  3354. // Query the PID, if requested
  3355. //
  3356. if( Pid != NULL ) {
  3357. TempStatus = SpGetValueKey(
  3358. hKeyRoot,
  3359. L"Microsoft\\Windows NT\\CurrentVersion",
  3360. L"ProductId",
  3361. BUFFERSIZE,
  3362. buffer,
  3363. &ResultLength
  3364. );
  3365. if(!NT_SUCCESS(TempStatus)) {
  3366. //
  3367. // If unable to read PID, assume empty string
  3368. //
  3369. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to query PID from hive %ws. Status = (%lx)\n",Hive,TempStatus));
  3370. *Pid = SpDupStringW( L"" );
  3371. } else {
  3372. *Pid = SpDupStringW( (PWSTR)(((PKEY_VALUE_PARTIAL_INFORMATION)buffer)->Data) );
  3373. }
  3374. }
  3375. //
  3376. // Let the following do the cleaning up
  3377. spdp_3:
  3378. if( hKeyCCSet ) {
  3379. ZwClose( hKeyCCSet );
  3380. }
  3381. if( hKeyRoot ) {
  3382. ZwClose(hKeyRoot);
  3383. }
  3384. spdp_2:
  3385. //
  3386. // Unload the currently loaded hive.
  3387. //
  3388. if( HiveLoaded ) {
  3389. TempStatus = SpLoadUnloadKey(NULL,NULL,HiveKey,NULL);
  3390. if(!NT_SUCCESS(TempStatus)) {
  3391. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: warning: unable to unload key %ws (%lx)\n",HiveKey,TempStatus));
  3392. }
  3393. }
  3394. spdp_1:
  3395. SpMemFree(PartitionPath);
  3396. SpMemFree(Hive);
  3397. SpMemFree(HiveKey);
  3398. SpMemFree(buffer);
  3399. return( Status );
  3400. #undef BUFFERSIZE
  3401. }
  3402. NTSTATUS
  3403. SpSetUpgradeStatus(
  3404. IN PDISK_REGION TargetRegion,
  3405. IN PWSTR SystemRoot,
  3406. IN UPG_PROGRESS_TYPE UpgradeProgressValue
  3407. )
  3408. {
  3409. OBJECT_ATTRIBUTES Obja;
  3410. UNICODE_STRING UnicodeString;
  3411. NTSTATUS Status, TempStatus;
  3412. WCHAR Hive[MAX_PATH], HiveKey[MAX_PATH];
  3413. BOOLEAN HiveLoaded = FALSE;
  3414. PWSTR PartitionPath = NULL;
  3415. HANDLE hKeySystemHive;
  3416. DWORD dw;
  3417. //
  3418. // Get the name of the target patition.
  3419. //
  3420. SpNtNameFromRegion(
  3421. TargetRegion,
  3422. TemporaryBuffer,
  3423. sizeof(TemporaryBuffer),
  3424. PartitionOrdinalCurrent
  3425. );
  3426. PartitionPath = SpDupStringW(TemporaryBuffer);
  3427. //
  3428. // Load the system hive
  3429. //
  3430. wcscpy(Hive,PartitionPath);
  3431. SpConcatenatePaths(Hive,SystemRoot);
  3432. SpConcatenatePaths(Hive,L"system32\\config");
  3433. SpConcatenatePaths(Hive,L"system");
  3434. //
  3435. // Form the path of the key into which we will
  3436. // load the hive. We'll use the convention that
  3437. // a hive will be loaded into \registry\machine\x<hivename>.
  3438. //
  3439. wcscpy(HiveKey,LOCAL_MACHINE_KEY_NAME);
  3440. SpConcatenatePaths(HiveKey,L"x");
  3441. wcscat(HiveKey,L"system");
  3442. //
  3443. // Attempt to load the key.
  3444. //
  3445. Status = SpLoadUnloadKey(NULL,NULL,HiveKey,Hive);
  3446. if(!NT_SUCCESS(Status)) {
  3447. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to load hive %ws to key %ws (%lx)\n",Hive,HiveKey,Status));
  3448. goto spus_1;
  3449. }
  3450. HiveLoaded = TRUE;
  3451. //
  3452. // Now get a key to the root of the hive we just loaded.
  3453. //
  3454. INIT_OBJA(&Obja,&UnicodeString,HiveKey);
  3455. Status = ZwOpenKey(&hKeySystemHive,KEY_ALL_ACCESS,&Obja);
  3456. if(!NT_SUCCESS(Status)) {
  3457. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to open %ws (%lx)\n",HiveKey,Status));
  3458. goto spus_2;
  3459. }
  3460. //
  3461. // Set the upgrade status under the setup key.
  3462. //
  3463. dw = UpgradeProgressValue;
  3464. Status = SpOpenSetValueAndClose(
  3465. hKeySystemHive,
  3466. SETUP_KEY_NAME,
  3467. UPGRADE_IN_PROGRESS,
  3468. ULONG_VALUE(dw)
  3469. );
  3470. //
  3471. // Flush the key. Ignore the error
  3472. //
  3473. TempStatus = ZwFlushKey(hKeySystemHive);
  3474. if(!NT_SUCCESS(TempStatus)) {
  3475. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: ZwFlushKey %ws failed (%lx)\n",HiveKey,Status));
  3476. }
  3477. //
  3478. // Close the hive key
  3479. //
  3480. ZwClose( hKeySystemHive );
  3481. hKeySystemHive = NULL;
  3482. //
  3483. // Unload the system hive
  3484. //
  3485. TempStatus = SpLoadUnloadKey(NULL,NULL,HiveKey,NULL);
  3486. if(!NT_SUCCESS(TempStatus)) {
  3487. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: warning: unable to unload key %ws (%lx)\n",HiveKey,TempStatus));
  3488. }
  3489. HiveLoaded = FALSE;
  3490. spus_2:
  3491. //
  3492. // Unload the currently loaded hive.
  3493. //
  3494. if( HiveLoaded ) {
  3495. TempStatus = SpLoadUnloadKey(NULL,NULL,HiveKey,NULL);
  3496. if(!NT_SUCCESS(TempStatus)) {
  3497. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: warning: unable to unload key %ws (%lx)\n",HiveKey,TempStatus));
  3498. }
  3499. }
  3500. spus_1:
  3501. SpMemFree(PartitionPath);
  3502. return( Status );
  3503. }
  3504. NTSTATUS
  3505. SpGetCurrentControlSetNumber(
  3506. IN HANDLE SystemHiveRoot,
  3507. OUT PULONG Number
  3508. )
  3509. /*++
  3510. Routine Description:
  3511. This routine determines the ordinal number of the "current" control set
  3512. as indicated by the values in a SELECT key at the root of a system hive.
  3513. Arguments:
  3514. SystemHiveRoot - supplies an open key to the a key which is to be
  3515. considered the root of a system hive.
  3516. Number - If the routine is successful, recieves the ordinal number of
  3517. the "current" control set in that system hive.
  3518. Return Value:
  3519. NT Status value indicating outcome.
  3520. --*/
  3521. {
  3522. NTSTATUS Status;
  3523. UCHAR buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION)+256];
  3524. ULONG ResultLength;
  3525. Status = SpGetValueKey(
  3526. SystemHiveRoot,
  3527. L"Select",
  3528. L"Current",
  3529. sizeof(buffer),
  3530. buffer,
  3531. &ResultLength
  3532. );
  3533. if(NT_SUCCESS(Status)) {
  3534. *Number = *(DWORD *)(((PKEY_VALUE_PARTIAL_INFORMATION)buffer)->Data);
  3535. }
  3536. return(Status);
  3537. }
  3538. NTSTATUS
  3539. SpCreateControlSetSymbolicLink(
  3540. IN HANDLE SystemHiveRoot,
  3541. OUT HANDLE *CurrentControlSetRoot
  3542. )
  3543. /*++
  3544. Routine Description:
  3545. This routine creates a CurrentControlSet symbolic link, whose target
  3546. is the appropriate ControlSetxxx key within a given system hive.
  3547. The symbolic link is created volatile.
  3548. Arguments:
  3549. SystemHiveRoot - supplies a handle to a key that is to be considered
  3550. the root key of a system hive.
  3551. CurrentControlSetRoot - if this routine is successful then this receives
  3552. a handle to the open root key of the current control set, with
  3553. KEY_ALL_ACCESS.
  3554. Return Value:
  3555. NT status code indicating outcome.
  3556. --*/
  3557. {
  3558. NTSTATUS Status;
  3559. ULONG Number;
  3560. HANDLE KeyHandle;
  3561. OBJECT_ATTRIBUTES Obja;
  3562. UNICODE_STRING UnicodeString;
  3563. WCHAR name[50];
  3564. //
  3565. // First we need to figure out which control set is the "current" one.
  3566. // In the upgrade case we need to get it from looking at the existing
  3567. // hive; in the fresh install case it's always 1.
  3568. //
  3569. if(NTUpgrade == UpgradeFull) {
  3570. Status = SpGetCurrentControlSetNumber(SystemHiveRoot,&Number);
  3571. if(!NT_SUCCESS(Status)) {
  3572. return(Status);
  3573. }
  3574. } else {
  3575. Number = 1;
  3576. //
  3577. // HACK: In the fresh install case we need to make sure that there is
  3578. // a ControlSet001 value to link to! There won't be one when we get here
  3579. // because we didn't run any infs yet.
  3580. //
  3581. RtlInitUnicodeString(&UnicodeString,L"ControlSet001");
  3582. InitializeObjectAttributes(
  3583. &Obja,
  3584. &UnicodeString,
  3585. OBJ_CASE_INSENSITIVE,
  3586. SystemHiveRoot,
  3587. NULL
  3588. );
  3589. Status = ZwCreateKey(
  3590. &KeyHandle,
  3591. KEY_QUERY_VALUE,
  3592. &Obja,
  3593. 0,
  3594. NULL,
  3595. REG_OPTION_NON_VOLATILE,
  3596. NULL
  3597. );
  3598. if(!NT_SUCCESS(Status)) {
  3599. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: can't create ControlSet001 key (%lx)\n",Status));
  3600. return(Status);
  3601. }
  3602. ZwClose(KeyHandle);
  3603. }
  3604. //
  3605. // Create CurrentControlSet for create-link access.
  3606. //
  3607. RtlInitUnicodeString(&UnicodeString,L"CurrentControlSet");
  3608. InitializeObjectAttributes(
  3609. &Obja,
  3610. &UnicodeString,
  3611. OBJ_CASE_INSENSITIVE,
  3612. SystemHiveRoot,
  3613. NULL
  3614. );
  3615. Status = ZwCreateKey(
  3616. &KeyHandle,
  3617. KEY_CREATE_LINK,
  3618. &Obja,
  3619. 0,
  3620. NULL,
  3621. REG_OPTION_VOLATILE | REG_OPTION_CREATE_LINK,
  3622. NULL
  3623. );
  3624. if(!NT_SUCCESS(Status)) {
  3625. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: can't create CurrentControlSet symbolic key (%lx)\n",Status));
  3626. return(Status);
  3627. }
  3628. //
  3629. // Now set the value value in there. If the swprintf changes, make sure
  3630. // the name buffer is large enough!
  3631. //
  3632. swprintf(name,L"\\Registry\\Machine\\xSystem\\ControlSet%03d",Number);
  3633. RtlInitUnicodeString(&UnicodeString,L"SymbolicLinkValue");
  3634. Status = ZwSetValueKey(KeyHandle,&UnicodeString,0,REG_LINK,name,wcslen(name)*sizeof(WCHAR));
  3635. ZwClose(KeyHandle);
  3636. if(!NT_SUCCESS(Status)) {
  3637. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to set SymbolicLinkValue for CurrentControlSet to %ws (%lx)\n",name,Status));
  3638. } else {
  3639. //
  3640. // Finally, open a handle to the key.
  3641. //
  3642. INIT_OBJA(&Obja,&UnicodeString,name);
  3643. Status = ZwOpenKey(CurrentControlSetRoot,KEY_ALL_ACCESS,&Obja);
  3644. if(!NT_SUCCESS(Status)) {
  3645. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to open control set root %ws (%lx)\n",name,Status));
  3646. }
  3647. }
  3648. return(Status);
  3649. }
  3650. NTSTATUS
  3651. SpAppendStringToMultiSz(
  3652. IN HANDLE hKey,
  3653. IN PWSTR Subkey,
  3654. IN PWSTR ValueName,
  3655. IN PWSTR StringToAdd
  3656. )
  3657. {
  3658. NTSTATUS Status;
  3659. ULONG Length;
  3660. PUCHAR Data;
  3661. Status = SpGetValueKey(
  3662. hKey,
  3663. Subkey,
  3664. ValueName,
  3665. sizeof(TemporaryBuffer),
  3666. (PCHAR)TemporaryBuffer,
  3667. &Length
  3668. );
  3669. if(!NT_SUCCESS(Status)) {
  3670. return(Status);
  3671. }
  3672. Data = ((PKEY_VALUE_PARTIAL_INFORMATION)TemporaryBuffer)->Data;
  3673. Length = ((PKEY_VALUE_PARTIAL_INFORMATION)TemporaryBuffer)->DataLength;
  3674. //
  3675. // Stick on end. For a multi_sz there has to be at least
  3676. // the terminating nul, but just to be safe we'll be robust.
  3677. //
  3678. ASSERT(Length);
  3679. if(!Length) {
  3680. *(PWCHAR)Data = 0;
  3681. Length = sizeof(WCHAR);
  3682. }
  3683. //
  3684. // Append new string to end and add new terminating 0.
  3685. //
  3686. wcscpy((PWSTR)(Data+Length-sizeof(WCHAR)),StringToAdd);
  3687. Length += (wcslen(StringToAdd)+1)*sizeof(WCHAR);
  3688. *(PWCHAR)(Data+Length-sizeof(WCHAR)) = 0;
  3689. //
  3690. // Write back out to registry.
  3691. //
  3692. Status = SpOpenSetValueAndClose(
  3693. hKey,
  3694. Subkey,
  3695. ValueName,
  3696. REG_MULTI_SZ,
  3697. Data,
  3698. Length
  3699. );
  3700. return(Status);
  3701. }
  3702. NTSTATUS
  3703. SpRemoveStringFromMultiSz(
  3704. IN HANDLE KeyHandle,
  3705. IN PWSTR SubKey OPTIONAL,
  3706. IN PWSTR ValueName,
  3707. IN PWSTR StringToRemove
  3708. )
  3709. /*++
  3710. Routine Description:
  3711. Removes the specified string from the given multi_sz value.
  3712. Arguments:
  3713. KeyHandle - The handle to the key which contains the value or
  3714. the SubKey.
  3715. SubKey - The subkey name which contains the value.
  3716. ValueName - The value name which is under the SubKey or the
  3717. Key reachable by KeyHandle.
  3718. StringToRemove - The string that needs to be removed from
  3719. from the multi_sz strings.
  3720. Return Value:
  3721. Appropriate NT status error code.
  3722. --*/
  3723. {
  3724. NTSTATUS Status = STATUS_INVALID_PARAMETER;
  3725. //
  3726. // Validate parameters
  3727. //
  3728. if (KeyHandle && ValueName && StringToRemove) {
  3729. HANDLE NewKeyHandle = KeyHandle;
  3730. HANDLE SubKeyHandle = NULL;
  3731. Status = STATUS_SUCCESS;
  3732. //
  3733. // Open the subkey if needed
  3734. //
  3735. if (SubKey) {
  3736. UNICODE_STRING SubKeyName;
  3737. OBJECT_ATTRIBUTES ObjAttrs;
  3738. INIT_OBJA(&ObjAttrs, &SubKeyName, SubKey);
  3739. ObjAttrs.RootDirectory = KeyHandle;
  3740. Status = ZwOpenKey(&SubKeyHandle,
  3741. KEY_ALL_ACCESS,
  3742. &ObjAttrs);
  3743. if (NT_SUCCESS(Status)) {
  3744. NewKeyHandle = SubKeyHandle;
  3745. }
  3746. }
  3747. if (NT_SUCCESS(Status)) {
  3748. ULONG ResultLength = 0;
  3749. PWSTR Buffer = NULL;
  3750. ULONG BufferLength = 0;
  3751. UNICODE_STRING ValueNameStr;
  3752. RtlInitUnicodeString(&ValueNameStr, ValueName);
  3753. Status = ZwQueryValueKey(NewKeyHandle,
  3754. &ValueNameStr,
  3755. KeyValueFullInformation,
  3756. NULL,
  3757. 0,
  3758. &ResultLength);
  3759. //
  3760. // Is there something to process ?
  3761. //
  3762. if (ResultLength &&
  3763. (Status == STATUS_BUFFER_OVERFLOW) || (Status == STATUS_BUFFER_TOO_SMALL)) {
  3764. //
  3765. // Allocate adequate buffer
  3766. //
  3767. BufferLength = ResultLength + (2 * sizeof(WCHAR));
  3768. Buffer = (PWSTR)SpMemAlloc(BufferLength);
  3769. if (Buffer) {
  3770. PKEY_VALUE_FULL_INFORMATION ValueInfo;
  3771. //
  3772. // Get the current value
  3773. //
  3774. ValueInfo = (PKEY_VALUE_FULL_INFORMATION)Buffer;
  3775. Status = ZwQueryValueKey(NewKeyHandle,
  3776. &ValueNameStr,
  3777. KeyValueFullInformation,
  3778. ValueInfo,
  3779. BufferLength,
  3780. &ResultLength);
  3781. if (NT_SUCCESS(Status)) {
  3782. //
  3783. // Verify that its REG_MULTI_SZ or REG_SZ type
  3784. // NOTE : We allow REG_SZ also since in some W2K installations
  3785. // the string type is REG_SZ for class upperfilters & lowerfilters
  3786. //
  3787. if ((ValueInfo->Type == REG_MULTI_SZ) ||
  3788. (ValueInfo->Type == REG_SZ)){
  3789. PWSTR CurrString = (PWSTR)(((PUCHAR)ValueInfo + ValueInfo->DataOffset));
  3790. BOOLEAN Found = FALSE;
  3791. ULONG BytesToProcess = ValueInfo->DataLength;
  3792. ULONG BytesProcessed;
  3793. ULONG Length;
  3794. //
  3795. // null terminate the string (we allocated enough buffer space above)
  3796. //
  3797. CurrString[ValueInfo->DataLength/sizeof(WCHAR)] = UNICODE_NULL;
  3798. CurrString[(ValueInfo->DataLength/sizeof(WCHAR))+1] = UNICODE_NULL;
  3799. //
  3800. // Search for an occurrence of the string to replace
  3801. //
  3802. for (BytesProcessed = 0;
  3803. (!Found && (BytesProcessed < BytesToProcess));
  3804. CurrString += (Length + 1), BytesProcessed += ((Length + 1) * sizeof(WCHAR)))
  3805. {
  3806. Length = wcslen(CurrString);
  3807. if (Length && !_wcsicmp(CurrString, StringToRemove)) {
  3808. Found = TRUE;
  3809. }
  3810. }
  3811. if (Found) {
  3812. //
  3813. // We found an occurrence -- allocate new buffer to selectively
  3814. // copy the required information from the old string
  3815. //
  3816. PWSTR NewString = (PWSTR)(SpMemAlloc(ValueInfo->DataLength));
  3817. if (NewString) {
  3818. PWSTR CurrDestString = NewString;
  3819. RtlZeroMemory(NewString, ValueInfo->DataLength);
  3820. CurrString = (PWSTR)(((PUCHAR)ValueInfo + ValueInfo->DataOffset));
  3821. CurrString[ValueInfo->DataLength/sizeof(WCHAR)] = UNICODE_NULL;
  3822. CurrString[(ValueInfo->DataLength/sizeof(WCHAR))+1] = UNICODE_NULL;
  3823. //
  3824. // Copy all the strings except the one's to skip
  3825. //
  3826. for (BytesProcessed = 0;
  3827. (BytesProcessed < BytesToProcess);
  3828. CurrString += (Length + 1), BytesProcessed += ((Length + 1) * sizeof(WCHAR)))
  3829. {
  3830. Length = wcslen(CurrString);
  3831. //
  3832. // copy the unmatched non-empty source string to destination
  3833. //
  3834. if (Length && (_wcsicmp(CurrString, StringToRemove))) {
  3835. wcscpy(CurrDestString, CurrString);
  3836. CurrDestString += (Length + 1);
  3837. }
  3838. }
  3839. //
  3840. // Set the string back if its not empty
  3841. //
  3842. if (CurrDestString != NewString) {
  3843. *CurrDestString++ = UNICODE_NULL;
  3844. //
  3845. // Set the new value back
  3846. //
  3847. Status = ZwSetValueKey(NewKeyHandle,
  3848. &ValueNameStr,
  3849. 0,
  3850. REG_MULTI_SZ,
  3851. NewString,
  3852. ((CurrDestString - NewString) * sizeof(WCHAR)));
  3853. } else {
  3854. //
  3855. // Remove the empty value
  3856. //
  3857. Status = ZwDeleteValueKey(NewKeyHandle,
  3858. &ValueNameStr);
  3859. }
  3860. //
  3861. // done with the buffer
  3862. //
  3863. SpMemFree(NewString);
  3864. } else {
  3865. Status = STATUS_NO_MEMORY;
  3866. }
  3867. } else {
  3868. Status = STATUS_OBJECT_NAME_NOT_FOUND;
  3869. }
  3870. } else {
  3871. Status = STATUS_INVALID_PARAMETER;
  3872. }
  3873. }
  3874. SpMemFree(Buffer);
  3875. } else {
  3876. Status = STATUS_NO_MEMORY;
  3877. }
  3878. }
  3879. }
  3880. if (SubKeyHandle) {
  3881. ZwClose(SubKeyHandle);
  3882. }
  3883. }
  3884. return Status;
  3885. }
  3886. NTSTATUS
  3887. SpGetValueKey(
  3888. IN HANDLE hKeyRoot,
  3889. IN PWSTR KeyName,
  3890. IN PWSTR ValueName,
  3891. IN ULONG BufferLength,
  3892. OUT PUCHAR Buffer,
  3893. OUT PULONG ResultLength
  3894. )
  3895. {
  3896. UNICODE_STRING UnicodeString;
  3897. OBJECT_ATTRIBUTES Obja;
  3898. NTSTATUS Status;
  3899. HANDLE hKey = NULL;
  3900. //
  3901. // Open the key for read access
  3902. //
  3903. INIT_OBJA(&Obja,&UnicodeString,KeyName);
  3904. Obja.RootDirectory = hKeyRoot;
  3905. #if 0
  3906. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "+ [spconfig.c:%lu] KeyName %ws\n", __LINE__, KeyName ));
  3907. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "+ [spconfig.c:%lu] ValueName %ws\n", __LINE__, UnicodeString ));
  3908. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "+ [spconfig.c:%lu] UnicodeString %ws\n", __LINE__, UnicodeString ));
  3909. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "+ [spconfig.c:%lu] UnicodeString %S\n", __LINE__, UnicodeString ));
  3910. #endif
  3911. Status = ZwOpenKey(&hKey,KEY_READ,&Obja);
  3912. if(!NT_SUCCESS(Status)) {
  3913. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: SpGetValueKey: couldn't open key %ws for read access (%lx)\n",KeyName, Status));
  3914. }
  3915. else {
  3916. //
  3917. // Find out the value of the Current value
  3918. //
  3919. RtlInitUnicodeString(&UnicodeString,ValueName);
  3920. Status = ZwQueryValueKey(
  3921. hKey,
  3922. &UnicodeString,
  3923. KeyValuePartialInformation,
  3924. Buffer,
  3925. BufferLength,
  3926. ResultLength
  3927. );
  3928. if(!NT_SUCCESS(Status)) {
  3929. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: SpGetValueKey: couldn't query value %ws in key %ws (%lx)\n",ValueName,KeyName,Status));
  3930. }
  3931. }
  3932. if( hKey ) {
  3933. ZwClose( hKey );
  3934. }
  3935. return( Status );
  3936. }
  3937. NTSTATUS
  3938. SpDeleteValueKey(
  3939. IN HANDLE hKeyRoot,
  3940. IN PWSTR KeyName,
  3941. IN PWSTR ValueName
  3942. )
  3943. {
  3944. UNICODE_STRING UnicodeString;
  3945. OBJECT_ATTRIBUTES Obja;
  3946. NTSTATUS Status;
  3947. HANDLE hKey = NULL;
  3948. //
  3949. // Open the key for read access
  3950. //
  3951. INIT_OBJA(&Obja,&UnicodeString,KeyName);
  3952. Obja.RootDirectory = hKeyRoot;
  3953. Status = ZwOpenKey(&hKey,KEY_SET_VALUE,&Obja);
  3954. if(!NT_SUCCESS(Status)) {
  3955. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: SpDeleteValueKey: couldn't open key %ws for write access (%lx)\n",KeyName, Status));
  3956. }
  3957. else {
  3958. //
  3959. // Find out the value of the Current value
  3960. //
  3961. RtlInitUnicodeString(&UnicodeString,ValueName);
  3962. Status = ZwDeleteValueKey(
  3963. hKey,
  3964. &UnicodeString
  3965. );
  3966. if(!NT_SUCCESS(Status)) {
  3967. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: SpDeleteValueKey: couldn't delete value %ws in key %ws (%lx)\n",ValueName,KeyName,Status));
  3968. }
  3969. }
  3970. if( hKey ) {
  3971. ZwClose( hKey );
  3972. }
  3973. return( Status );
  3974. }
  3975. BOOLEAN
  3976. SpReadSKUStuff(
  3977. VOID
  3978. )
  3979. /*++
  3980. Routine Description:
  3981. Read SKU differentiation data from the setup hive we are currently
  3982. running on.
  3983. In the unnamed key of our driver node, there is a REG_BINARY that
  3984. tells us whether this is stepup mode, and/or whether this is an
  3985. evaluation unit (gives us the time in minutes).
  3986. Arguments:
  3987. None.
  3988. Return Value:
  3989. Boolean value indicating outcome.
  3990. If TRUE, StepUpMode and EvaluationTime globals are filled in.
  3991. If FALSE, product may have been tampered with.
  3992. --*/
  3993. {
  3994. NTSTATUS Status;
  3995. PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
  3996. PULONG Values;
  3997. ULONG ResultLength;
  3998. OBJECT_ATTRIBUTES Obja;
  3999. UNICODE_STRING UnicodeString;
  4000. HKEY Key;
  4001. INIT_OBJA(&Obja,&UnicodeString,LOCAL_MACHINE_KEY_NAME);
  4002. Status = ZwOpenKey(&Key,KEY_READ,&Obja);
  4003. if(!NT_SUCCESS(Status)) {
  4004. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Failed to open %ws (Status = %lx)\n",LOCAL_MACHINE_KEY_NAME,Status));
  4005. return(FALSE);
  4006. }
  4007. Status = SpGetValueKey(
  4008. Key,
  4009. L"System\\ControlSet001\\Services\\setupdd",
  4010. L"",
  4011. sizeof(TemporaryBuffer),
  4012. (PCHAR)TemporaryBuffer,
  4013. &ResultLength
  4014. );
  4015. ZwClose(Key);
  4016. ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)TemporaryBuffer;
  4017. //
  4018. // This line of code depends on the setup hive setupreg.hiv
  4019. // (see oak\bin\setupreg.ini).
  4020. //
  4021. if(NT_SUCCESS(Status) && (ValueInfo->Type == REG_BINARY) && (ValueInfo->DataLength == 16)) {
  4022. Values = (PULONG)ValueInfo->Data;
  4023. //
  4024. // First DWORD is eval time, second is stepup boolean, third is restric cpu val, fourth is suite
  4025. //
  4026. EvaluationTime = Values[0];
  4027. StepUpMode = (BOOLEAN)Values[1];
  4028. RestrictCpu = Values[2];
  4029. SuiteType = Values[3];
  4030. return(TRUE);
  4031. }
  4032. return(FALSE);
  4033. }
  4034. VOID
  4035. SpSetDirtyShutdownFlag(
  4036. IN PDISK_REGION TargetRegion,
  4037. IN PWSTR SystemRoot
  4038. )
  4039. {
  4040. NTSTATUS Status;
  4041. PWSTR HiveRootPath;
  4042. PWSTR HiveFilePath;
  4043. BOOLEAN HiveLoaded;
  4044. OBJECT_ATTRIBUTES Obja;
  4045. UNICODE_STRING UnicodeString;
  4046. HANDLE HiveRootKey;
  4047. UCHAR buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION)+sizeof(DISK_CONFIG_HEADER)];
  4048. ULONG ResultLength;
  4049. PDISK_CONFIG_HEADER DiskHeader;
  4050. //
  4051. // Get the name of the target patition.
  4052. //
  4053. SpNtNameFromRegion(
  4054. TargetRegion,
  4055. TemporaryBuffer,
  4056. sizeof(TemporaryBuffer),
  4057. PartitionOrdinalCurrent
  4058. );
  4059. //
  4060. // Form the name of the hive file.
  4061. // This is partitionpath + sysroot + system32\config + the hive name.
  4062. //
  4063. SpConcatenatePaths(TemporaryBuffer, SystemRoot);
  4064. SpConcatenatePaths(TemporaryBuffer,L"system32\\config\\system");
  4065. HiveFilePath = SpDupStringW(TemporaryBuffer);
  4066. //
  4067. // Form the path of the key into which we will
  4068. // load the hive. We'll use the convention that
  4069. // a hive will be loaded into \registry\machine\x<hivename>.
  4070. //
  4071. wcscpy(TemporaryBuffer,LOCAL_MACHINE_KEY_NAME);
  4072. SpConcatenatePaths(TemporaryBuffer,L"x");
  4073. wcscat(TemporaryBuffer,L"system");
  4074. HiveRootPath = SpDupStringW(TemporaryBuffer);
  4075. ASSERT(HiveRootPath);
  4076. //
  4077. // Attempt to load the key.
  4078. //
  4079. HiveLoaded = FALSE;
  4080. Status = SpLoadUnloadKey(NULL,NULL,HiveRootPath,HiveFilePath);
  4081. if(!NT_SUCCESS(Status)) {
  4082. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to load hive %ws to key %ws (%lx)\n",HiveFilePath,HiveRootPath,Status));
  4083. goto setdirty1;
  4084. }
  4085. HiveLoaded = TRUE;
  4086. //
  4087. // Now get a key to the root of the hive we just loaded.
  4088. //
  4089. INIT_OBJA(&Obja,&UnicodeString,HiveRootPath);
  4090. Status = ZwOpenKey(&HiveRootKey,KEY_ALL_ACCESS,&Obja);
  4091. if(!NT_SUCCESS(Status)) {
  4092. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to open %ws (%lx)\n",HiveRootPath,Status));
  4093. goto setdirty1;
  4094. }
  4095. //
  4096. // Make the appropriate change
  4097. //
  4098. Status = SpGetValueKey(
  4099. HiveRootKey,
  4100. L"DISK",
  4101. L"Information",
  4102. sizeof(TemporaryBuffer),
  4103. (PCHAR)TemporaryBuffer,
  4104. &ResultLength
  4105. );
  4106. //
  4107. // TemporaryBuffer is 32kb long, and it should be big enough
  4108. // for the data.
  4109. //
  4110. ASSERT( Status != STATUS_BUFFER_OVERFLOW );
  4111. if(!NT_SUCCESS(Status)) {
  4112. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to read value from registry. KeyName = Disk, ValueName = Information, Status = (%lx)\n",Status));
  4113. goto setdirty1;
  4114. }
  4115. DiskHeader = ( PDISK_CONFIG_HEADER )(((PKEY_VALUE_PARTIAL_INFORMATION)TemporaryBuffer)->Data);
  4116. DiskHeader->DirtyShutdown = TRUE;
  4117. Status = SpOpenSetValueAndClose( HiveRootKey,
  4118. L"DISK",
  4119. L"Information",
  4120. REG_BINARY,
  4121. DiskHeader,
  4122. ((PKEY_VALUE_PARTIAL_INFORMATION)TemporaryBuffer)->DataLength
  4123. );
  4124. if(!NT_SUCCESS(Status)) {
  4125. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to write value to registry. KeyName = Disk, ValueName = Information, Status = (%lx)\n",Status));
  4126. goto setdirty1;
  4127. }
  4128. setdirty1:
  4129. //
  4130. // Flush the hive.
  4131. //
  4132. if(HiveLoaded && HiveRootKey) {
  4133. NTSTATUS stat;
  4134. stat = ZwFlushKey(HiveRootKey);
  4135. if(!NT_SUCCESS(stat)) {
  4136. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: ZwFlushKey x%ws failed (%lx)\n", HiveRootPath, Status));
  4137. }
  4138. }
  4139. if(HiveLoaded) {
  4140. //
  4141. // We don't want to disturb the value of Status
  4142. // so use a we'll different variable below.
  4143. //
  4144. NTSTATUS stat;
  4145. if(HiveRootKey!=NULL) {
  4146. ZwClose(HiveRootKey);
  4147. HiveRootKey = NULL;
  4148. }
  4149. //
  4150. // Unload the hive.
  4151. //
  4152. stat = SpLoadUnloadKey(NULL,NULL,HiveRootPath,NULL);
  4153. if(!NT_SUCCESS(stat)) {
  4154. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: warning: unable to unload key %ws (%lx)\n",HiveRootPath,stat));
  4155. }
  4156. HiveLoaded = FALSE;
  4157. }
  4158. SpMemFree(HiveRootPath);
  4159. SpMemFree(HiveFilePath);
  4160. //
  4161. // If we fail to set the DirtyShutdown flag, then we silently fail
  4162. // because there is nothing that the user can do about, and the system
  4163. // is unlikely to boot anyway.
  4164. // This will occur if setup fails to:
  4165. //
  4166. // - Load the system hive
  4167. // - Open System\Disk key
  4168. // - Read the value entry
  4169. // - Write the value entry
  4170. // - Unload the system hive
  4171. //
  4172. if(!NT_SUCCESS(Status)) {
  4173. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: setup was unable to set DirtyShutdown flag. Status = (%lx)\n", Status));
  4174. }
  4175. }
  4176. NTSTATUS
  4177. SpPostprocessHives(
  4178. IN PWSTR PartitionPath,
  4179. IN PWSTR Sysroot,
  4180. IN PCWSTR *HiveNames,
  4181. IN HANDLE *HiveRootKeys,
  4182. IN unsigned HiveCount,
  4183. IN HANDLE hKeyCCS
  4184. )
  4185. {
  4186. NTSTATUS Status;
  4187. ULONG u;
  4188. unsigned h;
  4189. PWSTR SaveHiveName;
  4190. PWSTR HiveName;
  4191. HANDLE SaveHiveHandle;
  4192. IO_STATUS_BLOCK IoStatusBlock;
  4193. OBJECT_ATTRIBUTES ObjectAttributes;
  4194. OBJECT_ATTRIBUTES ObjectAttributes2;
  4195. UNICODE_STRING UnicodeString;
  4196. UNICODE_STRING UnicodeString2;
  4197. DWORD MangledVersion;
  4198. PWSTR Value;
  4199. PWSTR SecurityHives[] = {
  4200. L"sam",
  4201. L"security"
  4202. };
  4203. //
  4204. // Flush all hives.
  4205. //
  4206. for(h=0; h<HiveCount; h++) {
  4207. Status = ZwFlushKey(HiveRootKeys[h]);
  4208. if(!NT_SUCCESS(Status)) {
  4209. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Warning: ZwFlushKey %ws failed (%lx)\n",HiveNames[h],Status));
  4210. }
  4211. SendSetupProgressEvent(SavingSettingsEvent, SaveHiveEvent, NULL);
  4212. }
  4213. //
  4214. // If GUI setup is supposed to be restartable, we need to add an entry
  4215. // to the BootExecute list, to cause sprestrt.exe to run.
  4216. // Also, we want system.sav to have a RestartSetup=TRUE value in it,
  4217. // but we want the actual system hive to have RestartSetup=FALSE.
  4218. //
  4219. if(RestartableGuiSetup) {
  4220. Status = SpAppendStringToMultiSz(
  4221. hKeyCCS,
  4222. SESSION_MANAGER_KEY,
  4223. BOOT_EXECUTE,
  4224. L"sprestrt"
  4225. );
  4226. if(NT_SUCCESS(Status)) {
  4227. //
  4228. // Add a RestartSetup value, set to TRUE.
  4229. // To understand why we use a different value here in upgrade
  4230. // and non-upgrade case, see discussion below.
  4231. //
  4232. u = (NTUpgrade == UpgradeFull) ? 0 : 1;
  4233. Status = SpOpenSetValueAndClose(
  4234. HiveRootKeys[SetupHiveSystem],
  4235. SETUP_KEY_NAME,
  4236. RESTART_SETUP,
  4237. ULONG_VALUE(u)
  4238. );
  4239. }
  4240. } else {
  4241. Status = STATUS_SUCCESS;
  4242. }
  4243. //
  4244. // Do the final update of device instance data.
  4245. //
  4246. if((NTUpgrade == UpgradeFull)) {
  4247. //
  4248. // SANTOSHJ: This whole code needs to go away for BLACKCOMB.
  4249. //
  4250. Value = SpGetSectionKeyIndex(WinntSifHandle,
  4251. SIF_DATA, WINNT_D_WIN32_VER_W, 0);
  4252. if(Value) {
  4253. //
  4254. // version is bbbbllhh - build/low/high
  4255. //
  4256. MangledVersion = (DWORD)SpStringToLong( Value, NULL, 16 );
  4257. if (LOWORD(MangledVersion) == 0x0105) {
  4258. Status = SpUpdateDeviceInstanceData(hKeyCCS);
  4259. if (!NT_SUCCESS(Status)) {
  4260. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Could not update device instance data. Status = (%lx)\n",Status));
  4261. return(Status);
  4262. }
  4263. }
  4264. }
  4265. }
  4266. //
  4267. // At this point, we no longer need hKeyCCS, so we close the key.
  4268. // Note that key needs to be closed before we call ZwReplaceKey, otherwise
  4269. // this API will fail.
  4270. //
  4271. // Note also, that the caller of this function expects this function to close this handle
  4272. // before it returns.
  4273. //
  4274. NtClose(hKeyCCS);
  4275. if(NT_SUCCESS(Status)) {
  4276. //
  4277. // Save out the hives to *.sav in the initial install case,
  4278. // or *.tmp in the upgrade case.
  4279. //
  4280. for(h=0; NT_SUCCESS(Status) && (h<HiveCount); h++) {
  4281. //
  4282. // Form full pathname of hive file.
  4283. //
  4284. wcscpy(TemporaryBuffer,PartitionPath);
  4285. SpConcatenatePaths(TemporaryBuffer,Sysroot);
  4286. SpConcatenatePaths(TemporaryBuffer,L"system32\\config");
  4287. SpConcatenatePaths(TemporaryBuffer,HiveNames[h]);
  4288. wcscat(TemporaryBuffer,(NTUpgrade == UpgradeFull) ? L".tmp" : L".sav");
  4289. SaveHiveName = SpDupStringW(TemporaryBuffer);
  4290. SpDeleteFile( SaveHiveName, NULL, NULL ); // Make sure that we get rid of the file if it has attributes.
  4291. INIT_OBJA(&ObjectAttributes,&UnicodeString,SaveHiveName);
  4292. Status = ZwCreateFile(
  4293. &SaveHiveHandle,
  4294. FILE_GENERIC_WRITE,
  4295. &ObjectAttributes,
  4296. &IoStatusBlock,
  4297. NULL,
  4298. FILE_ATTRIBUTE_NORMAL,
  4299. 0, // no sharing
  4300. FILE_OVERWRITE_IF,
  4301. FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
  4302. NULL,
  4303. 0
  4304. );
  4305. if(NT_SUCCESS(Status)) {
  4306. //
  4307. // call the Ex version to make sure the hive is saved in the lates format
  4308. //
  4309. Status = ZwSaveKeyEx(HiveRootKeys[h],SaveHiveHandle,REG_LATEST_FORMAT);
  4310. if(!NT_SUCCESS(Status)) {
  4311. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: save key into %ws failed (%lx)\n",SaveHiveName,Status));
  4312. }
  4313. ZwClose(SaveHiveHandle);
  4314. } else {
  4315. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: unable to create file %ws to save hive (%lx)\n",SaveHiveName,Status));
  4316. }
  4317. //
  4318. // In the upgrade case, there is significant benefit to ensuring that
  4319. // the hives are in the latest format. A hive that has been created
  4320. // via NtSaveKeyEx(...,...,REG_LATEST_FORMAT) is guaranteed to be in the latest format.
  4321. // Since we just did a SaveKey, xxx.tmp is in the latest format,
  4322. // and we should use that as the xxx hive from now on. The existing
  4323. // (old-format) hive can be retained as xxx.sav.
  4324. //
  4325. // NtReplaceKey does exactly what we want, but we have to make sure
  4326. // that there is no .sav file already there, because that causes
  4327. // NtReplaceKey to fail with STATUS_OBJECT_NAME_COLLISION.
  4328. //
  4329. // After NtReplaceKey is done, the hive root keys refer to the .sav
  4330. // on-disk file but the extensionless on-disk file will be used at next
  4331. // boot. Thus we need to be careful about how we write the restart values
  4332. // into the hives.
  4333. //
  4334. if(NT_SUCCESS(Status) && (NTUpgrade == UpgradeFull)) {
  4335. HiveName = SpDupStringW(SaveHiveName);
  4336. wcscpy(HiveName+wcslen(HiveName)-3,L"sav");
  4337. SpDeleteFile(HiveName,NULL,NULL);
  4338. INIT_OBJA(&ObjectAttributes,&UnicodeString,SaveHiveName);
  4339. INIT_OBJA(&ObjectAttributes2,&UnicodeString2,HiveName);
  4340. Status = ZwReplaceKey(&ObjectAttributes,HiveRootKeys[h],&ObjectAttributes2);
  4341. }
  4342. SpMemFree(SaveHiveName);
  4343. }
  4344. }
  4345. if(NT_SUCCESS(Status) && (NTUpgrade == UpgradeFull)) {
  4346. //
  4347. // In the upgarde case, make a backup of the security
  4348. // hives. They need to be restored if the system is restartable.
  4349. //
  4350. //
  4351. // Initialize the diamond decompression engine.
  4352. // This needs to be done, because SpCopyFileUsingNames() uses
  4353. // the decompression engine.
  4354. //
  4355. SpdInitialize();
  4356. for( h = 0; h < sizeof(SecurityHives)/sizeof(PWSTR); h++ ) {
  4357. PWSTR p, q;
  4358. wcscpy(TemporaryBuffer,PartitionPath);
  4359. SpConcatenatePaths(TemporaryBuffer,Sysroot);
  4360. SpConcatenatePaths(TemporaryBuffer,L"system32\\config");
  4361. SpConcatenatePaths(TemporaryBuffer,SecurityHives[h]);
  4362. p = SpDupStringW(TemporaryBuffer);
  4363. wcscat(TemporaryBuffer, L".sav");
  4364. q = SpDupStringW(TemporaryBuffer);
  4365. Status = SpCopyFileUsingNames( p, q, 0, 0 );
  4366. if( !NT_SUCCESS(Status) ) {
  4367. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: unable to create backup file %ws. Status = %lx\n", q, Status));
  4368. }
  4369. SpMemFree(p);
  4370. SpMemFree(q);
  4371. if( !NT_SUCCESS(Status) ) {
  4372. break;
  4373. }
  4374. }
  4375. //
  4376. // Terminate diamond.
  4377. //
  4378. SpdTerminate();
  4379. }
  4380. if(NT_SUCCESS(Status) && RestartableGuiSetup) {
  4381. //
  4382. // Set RestartSetup to FALSE in mainline hive.
  4383. // To understand why we use a different value here in upgrade
  4384. // and non-upgrade case, see discussion above.
  4385. //
  4386. u = (NTUpgrade == UpgradeFull) ? 1 : 0;
  4387. Status = SpOpenSetValueAndClose(
  4388. HiveRootKeys[SetupHiveSystem],
  4389. SETUP_KEY_NAME,
  4390. RESTART_SETUP,
  4391. ULONG_VALUE(u)
  4392. );
  4393. }
  4394. return(Status);
  4395. }
  4396. NTSTATUS
  4397. SpSaveSetupPidList(
  4398. IN HANDLE hKeySystemHive
  4399. )
  4400. /*++
  4401. Routine Description:
  4402. Save the Product Id read from setup.ini on HKEY_LOCAL_MACHINE\SYSTEM\Setup\\Pid.
  4403. Also create the key HKEY_LOCAL_MACHINE\SYSTEM\Setup\PidList, and create
  4404. value entries under this key that contain various Pid20 found in the other
  4405. systems installed on this machine (the contents Pid20Array).
  4406. Arguments:
  4407. hKeySystemHive - supplies handle to root of the system hive
  4408. (ie, HKEY_LOCAL_MACHINE\System).
  4409. Return Value:
  4410. Status value indicating outcome of operation.
  4411. --*/
  4412. {
  4413. PWSTR ValueName;
  4414. NTSTATUS Status;
  4415. ULONG i;
  4416. //
  4417. // First save the Pid read from setup.ini
  4418. //
  4419. if( PidString != NULL ) {
  4420. Status = SpOpenSetValueAndClose( hKeySystemHive,
  4421. L"Setup\\Pid",
  4422. L"Pid",
  4423. STRING_VALUE(PidString)
  4424. );
  4425. if(!NT_SUCCESS(Status)) {
  4426. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to save Pid on SYSTEM\\Setup\\Pid. Status = %lx\n", Status ));
  4427. }
  4428. }
  4429. //
  4430. // If Pid20Array is empty, then don't bother to create the Pid key
  4431. //
  4432. if( Pid20Array == NULL || Pid20Array[0] == NULL ) {
  4433. return( STATUS_SUCCESS );
  4434. }
  4435. //
  4436. // Can't use TemporaryBuffer because we make subroutine calls
  4437. // below that trash its contents.
  4438. // Note that a buffer of size MAX_PATH for a value name is more than enough.
  4439. //
  4440. ValueName = SpMemAlloc((MAX_PATH+1)*sizeof(WCHAR));
  4441. for( i = 0; Pid20Array[i] != NULL; i++ ) {
  4442. swprintf( ValueName, L"Pid_%d", i );
  4443. Status = SpOpenSetValueAndClose( hKeySystemHive,
  4444. L"Setup\\PidList",
  4445. ValueName,
  4446. STRING_VALUE(Pid20Array[i])
  4447. );
  4448. if(!NT_SUCCESS(Status)) {
  4449. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to open or create SYSTEM\\Setup\\PidList. ValueName = %ws, ValueData = %ws, Status = %lx\n",
  4450. ValueName, Pid20Array[i] ));
  4451. }
  4452. }
  4453. SpMemFree(ValueName);
  4454. return( STATUS_SUCCESS );
  4455. }
  4456. NTSTATUS
  4457. SpSavePreinstallHwInfo(
  4458. IN PVOID SifHandle,
  4459. IN PWSTR SystemRoot,
  4460. IN HANDLE hKeyPreinstall,
  4461. IN ULONG ComponentIndex,
  4462. IN PHARDWARE_COMPONENT pHwList
  4463. )
  4464. {
  4465. NTSTATUS Status;
  4466. NTSTATUS SaveStatus;
  4467. PHARDWARE_COMPONENT TmpHw;
  4468. PHARDWARE_COMPONENT_FILE File;
  4469. PWSTR OemTag = L"OemComponent";
  4470. PWSTR RetailClass = L"RetailClassToDisable";
  4471. PWSTR ClassName;
  4472. ULONG u;
  4473. WCHAR NodeName[9];
  4474. PWSTR ServiceName;
  4475. SaveStatus = STATUS_SUCCESS;
  4476. for( TmpHw = pHwList; TmpHw != NULL; TmpHw = TmpHw->Next ) {
  4477. if( !TmpHw->ThirdPartyOptionSelected ) {
  4478. u = 0;
  4479. if( ( ComponentIndex == HwComponentKeyboard ) ||
  4480. ( ComponentIndex == HwComponentMouse ) ) {
  4481. ServiceName = SpGetSectionKeyIndex(SifHandle,
  4482. NonlocalizedComponentNames[ComponentIndex],
  4483. TmpHw->IdString,
  4484. INDEX_INFKEYNAME);
  4485. } else {
  4486. ServiceName = TmpHw->IdString;
  4487. }
  4488. Status = SpOpenSetValueAndClose( hKeyPreinstall,
  4489. ServiceName,
  4490. OemTag,
  4491. ULONG_VALUE(u)
  4492. );
  4493. if( !NT_SUCCESS( Status ) ) {
  4494. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Failed to save information for preinstalled retail driver %ls. Status = %lx \n", TmpHw->IdString, Status ));
  4495. if( SaveStatus == STATUS_SUCCESS ) {
  4496. SaveStatus = Status;
  4497. }
  4498. }
  4499. } else {
  4500. //
  4501. // Find the name of the service, save it, and indicate if there is
  4502. // a retail class driver that needs to be disabled if the service
  4503. // initializes successfully.
  4504. //
  4505. if( IS_FILETYPE_PRESENT(TmpHw->FileTypeBits, HwFileClass) ) {
  4506. if( ComponentIndex == HwComponentKeyboard ) {
  4507. ClassName = L"kbdclass";
  4508. } else if( ComponentIndex == HwComponentMouse ) {
  4509. ClassName = L"mouclass";
  4510. } else {
  4511. ClassName = NULL;
  4512. }
  4513. } else {
  4514. ClassName = NULL;
  4515. }
  4516. for(File=TmpHw->Files; File; File=File->Next) {
  4517. PWSTR p;
  4518. //
  4519. // If there is to be no node for this file, skip it.
  4520. //
  4521. if(!File->ConfigName) {
  4522. continue;
  4523. }
  4524. //
  4525. // Calculate the node name. This is the name of the driver
  4526. // without the extension.
  4527. //
  4528. wcsncpy(NodeName,File->Filename,8);
  4529. NodeName[8] = L'\0';
  4530. if(p = wcschr(NodeName,L'.')) {
  4531. *p = L'\0';
  4532. }
  4533. u = 1;
  4534. Status = SpOpenSetValueAndClose( hKeyPreinstall,
  4535. NodeName,
  4536. OemTag,
  4537. ULONG_VALUE(u)
  4538. );
  4539. if( !NT_SUCCESS( Status ) ) {
  4540. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Failed to save information for preinstalled OEM driver %ls. Status = %lx \n", NodeName, Status ));
  4541. if( SaveStatus == STATUS_SUCCESS ) {
  4542. SaveStatus = Status;
  4543. }
  4544. }
  4545. if( ClassName != NULL ) {
  4546. Status = SpOpenSetValueAndClose( hKeyPreinstall,
  4547. NodeName,
  4548. RetailClass,
  4549. STRING_VALUE(ClassName)
  4550. );
  4551. if( !NT_SUCCESS( Status ) ) {
  4552. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Failed to save information for preinstalled OEM driver %ls. Status = %lx \n", NodeName, Status ));
  4553. if( SaveStatus == STATUS_SUCCESS ) {
  4554. SaveStatus = Status;
  4555. }
  4556. }
  4557. }
  4558. }
  4559. }
  4560. }
  4561. return( SaveStatus );
  4562. }
  4563. NTSTATUS
  4564. SpSavePreinstallList(
  4565. IN PVOID SifHandle,
  4566. IN PWSTR SystemRoot,
  4567. IN HANDLE hKeySystemHive
  4568. )
  4569. {
  4570. NTSTATUS Status;
  4571. NTSTATUS SaveStatus;
  4572. OBJECT_ATTRIBUTES Obja;
  4573. UNICODE_STRING UnicodeString;
  4574. HANDLE hKeyPreinstall;
  4575. ULONG i;
  4576. //
  4577. // Create setup\preinstall
  4578. //
  4579. INIT_OBJA(&Obja,&UnicodeString,L"Setup\\Preinstall");
  4580. Obja.RootDirectory = hKeySystemHive;
  4581. Status = ZwCreateKey(
  4582. &hKeyPreinstall,
  4583. KEY_ALL_ACCESS,
  4584. &Obja,
  4585. 0,
  4586. NULL,
  4587. REG_OPTION_NON_VOLATILE,
  4588. NULL
  4589. );
  4590. if(!NT_SUCCESS(Status)) {
  4591. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: unable to create Preinstall key. Status = %lx\n",Status));
  4592. return( Status );
  4593. }
  4594. SaveStatus = STATUS_SUCCESS;
  4595. for( i = 0; i < HwComponentMax; i++ ) {
  4596. if( ( i == HwComponentComputer ) ||
  4597. ( i == HwComponentDisplay ) ||
  4598. ( i == HwComponentLayout ) ||
  4599. ( PreinstallHardwareComponents[i] == NULL ) ) {
  4600. continue;
  4601. }
  4602. Status = SpSavePreinstallHwInfo( SifHandle,
  4603. SystemRoot,
  4604. hKeyPreinstall,
  4605. i,
  4606. PreinstallHardwareComponents[i] );
  4607. if( !NT_SUCCESS( Status ) ) {
  4608. if( SaveStatus == STATUS_SUCCESS ) {
  4609. SaveStatus = Status;
  4610. }
  4611. }
  4612. }
  4613. if( PreinstallScsiHardware != NULL ) {
  4614. Status = SpSavePreinstallHwInfo( SifHandle,
  4615. SystemRoot,
  4616. hKeyPreinstall,
  4617. HwComponentMax,
  4618. PreinstallScsiHardware );
  4619. if( !NT_SUCCESS( Status ) ) {
  4620. if( SaveStatus == STATUS_SUCCESS ) {
  4621. SaveStatus = Status;
  4622. }
  4623. }
  4624. }
  4625. ZwClose(hKeyPreinstall);
  4626. return( SaveStatus );
  4627. }
  4628. NTSTATUS
  4629. SpSetPageFileInfo(
  4630. IN PVOID SifHandle,
  4631. IN HANDLE hKeyCCSetControl,
  4632. IN HANDLE hKeySystemHive
  4633. )
  4634. /*++
  4635. Routine Description:
  4636. This function replaces the original data of 'PagingFile'
  4637. CurrentControlSet\Session Manager\Memory Management with values from txtsetup.sif if the values don't measure up.
  4638. The original value will have already been saved on HKEY_LOCAL_MACHINE\SYSTEM\Setup\\PageFile,
  4639. and it will be restored at the end of GUI setup.
  4640. Arguments:
  4641. SifHandle - handle to txtsetup.sif
  4642. hKeyCCSetControl - supplies handle to SYSTEM\CurrentControlSet\Control
  4643. hKeySystemHive - supplies handle to root of the system hive
  4644. (ie, HKEY_LOCAL_MACHINE\System).
  4645. Return Value:
  4646. Status value indicating outcome of operation.
  4647. --*/
  4648. {
  4649. NTSTATUS Status;
  4650. PUCHAR Data;
  4651. ULONG Length;
  4652. PWSTR SrcKeyPath = L"Session Manager\\Memory Management";
  4653. PWSTR ValueName = L"PagingFiles";
  4654. PWSTR Buffer;
  4655. PWSTR NextDstSubstring;
  4656. ULONG AuxLength;
  4657. ULONG StartPagefile,MaxPagefile;
  4658. ULONG OldStartPagefile,OldMaxPagefile;
  4659. PWSTR p;
  4660. //
  4661. // Read recommended pagefile size for gui-mode.
  4662. //
  4663. if(p = SpGetSectionKeyIndex(SifHandle,SIF_SETUPDATA,SIF_PAGEFILE,0)) {
  4664. StartPagefile = SpStringToLong( p, NULL, 10 );
  4665. }
  4666. else {
  4667. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to retrieve initial pagefile size from txtsetup.sif\n"));
  4668. return( STATUS_UNSUCCESSFUL );
  4669. }
  4670. if(p = SpGetSectionKeyIndex(SifHandle,SIF_SETUPDATA,SIF_PAGEFILE,1)) {
  4671. MaxPagefile = SpStringToLong( p, NULL, 10 );
  4672. }
  4673. else {
  4674. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to retrieve max pagefile size from txtsetup.sif\n"));
  4675. return( STATUS_UNSUCCESSFUL );
  4676. }
  4677. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Read pagefile from txtsetup %lx %lx\n", StartPagefile, MaxPagefile ));
  4678. //
  4679. // Retrieve the original value of 'PagingFiles'
  4680. //
  4681. Status = SpGetValueKey( hKeyCCSetControl,
  4682. SrcKeyPath,
  4683. ValueName,
  4684. sizeof(TemporaryBuffer),
  4685. (PCHAR)TemporaryBuffer,
  4686. &Length );
  4687. OldStartPagefile = 0;
  4688. OldMaxPagefile = 0;
  4689. NextDstSubstring = TemporaryBuffer;
  4690. if(NT_SUCCESS(Status) && ((PKEY_VALUE_PARTIAL_INFORMATION)TemporaryBuffer)->Type == REG_MULTI_SZ) {
  4691. PWSTR r;
  4692. WCHAR SaveChar;
  4693. PWSTR s=NULL;
  4694. Data = ((PKEY_VALUE_PARTIAL_INFORMATION)TemporaryBuffer)->Data;
  4695. Length = ((PKEY_VALUE_PARTIAL_INFORMATION)TemporaryBuffer)->DataLength;
  4696. Buffer = SpMemAlloc( Length );
  4697. RtlMoveMemory( Buffer, Data, Length );
  4698. AuxLength = wcslen( Buffer);
  4699. // If it's not one string, then we won't change the pagefile
  4700. if( AuxLength == 0 || *(Buffer+AuxLength+1) != (WCHAR)'\0') {
  4701. SpMemFree( Buffer );
  4702. return( STATUS_SUCCESS );
  4703. }
  4704. //
  4705. // Form a new value entry that contains the information regarding the
  4706. // paging files to be created. The paths to the paging files will be the
  4707. // same ones used in the system before the upgrade.
  4708. //
  4709. // Make a copy of the original value entry, and form the data for the new
  4710. // value entry in the TemporaryBuffer.
  4711. //
  4712. SpStringToLower( Buffer );
  4713. r = wcsstr( Buffer, L"\\pagefile.sys" );
  4714. if( r != NULL ) {
  4715. r += wcslen( L"\\pagefile.sys" );
  4716. SaveChar = *r;
  4717. *r = (WCHAR)'\0';
  4718. wcscpy( NextDstSubstring, Buffer );
  4719. *r = SaveChar;
  4720. OldStartPagefile = SpStringToLong( r, &s, 10 );
  4721. if( (s != NULL) && (*s != (WCHAR)'\0') ) {
  4722. OldMaxPagefile = max( OldStartPagefile, (ULONG)SpStringToLong( s, NULL, 10 ));
  4723. } else {
  4724. OldMaxPagefile = OldStartPagefile;
  4725. }
  4726. } else {
  4727. wcscpy( NextDstSubstring, L"?:\\pagefile.sys" );
  4728. }
  4729. SpMemFree( Buffer );
  4730. // NextDstSubstring should now point just after pagefile.sys at the null
  4731. } else {
  4732. wcscpy( NextDstSubstring, L"?:\\pagefile.sys" );
  4733. }
  4734. NextDstSubstring += wcslen( NextDstSubstring );
  4735. //
  4736. // Overwrite the original value of PagingFiles
  4737. //
  4738. swprintf( NextDstSubstring, L" %d %d", max( OldStartPagefile, StartPagefile), max( OldMaxPagefile, MaxPagefile));
  4739. Length = wcslen( TemporaryBuffer );
  4740. Length++;
  4741. (TemporaryBuffer)[ Length++ ] = UNICODE_NULL;
  4742. Status = SpOpenSetValueAndClose( hKeyCCSetControl,
  4743. SrcKeyPath,
  4744. ValueName,
  4745. REG_MULTI_SZ,
  4746. TemporaryBuffer,
  4747. Length*sizeof(WCHAR) );
  4748. if(!NT_SUCCESS(Status)) {
  4749. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to save pagefile. Status = %lx\n", Status ));
  4750. }
  4751. return( Status );
  4752. }
  4753. NTSTATUS
  4754. SpSavePageFileInfo(
  4755. IN HANDLE hKeyCCSetControl,
  4756. IN HANDLE hKeySystemHive
  4757. )
  4758. /*++
  4759. Routine Description:
  4760. This function is only called on the upgrade case.
  4761. The original value will be saved on HKEY_LOCAL_MACHINE\SYSTEM\Setup\\PageFile,
  4762. and it will be restored at the end of GUI setup.
  4763. Arguments:
  4764. hKeyCCSetControl - supplies handle to SYSTEM\CurrentControlSet\Control
  4765. hKeySystemHive - supplies handle to root of the system hive
  4766. (ie, HKEY_LOCAL_MACHINE\System).
  4767. Return Value:
  4768. Status value indicating outcome of operation.
  4769. --*/
  4770. {
  4771. NTSTATUS Status;
  4772. PUCHAR Data;
  4773. ULONG Length;
  4774. PWSTR SrcKeyPath = L"Session Manager\\Memory Management";
  4775. PWSTR ValueName = L"PagingFiles";
  4776. //
  4777. // Retrieve the original value of 'PagingFiles'
  4778. //
  4779. Status = SpGetValueKey( hKeyCCSetControl,
  4780. SrcKeyPath,
  4781. ValueName,
  4782. sizeof(TemporaryBuffer),
  4783. (PCHAR)TemporaryBuffer,
  4784. &Length );
  4785. if(!NT_SUCCESS(Status)) {
  4786. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to retrieve %ls on %ls. Status = %lx \n", ValueName, SrcKeyPath, Status ));
  4787. return( Status );
  4788. }
  4789. Data = ((PKEY_VALUE_PARTIAL_INFORMATION)TemporaryBuffer)->Data;
  4790. Length = ((PKEY_VALUE_PARTIAL_INFORMATION)TemporaryBuffer)->DataLength;
  4791. //
  4792. // Save the data in SYSTEM\Setup\PageFile
  4793. //
  4794. Status = SpOpenSetValueAndClose(
  4795. hKeySystemHive,
  4796. L"Setup\\PageFile",
  4797. ValueName,
  4798. REG_MULTI_SZ,
  4799. Data,
  4800. Length
  4801. );
  4802. if(!NT_SUCCESS(Status)) {
  4803. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to save %ls on SYSTEM\\Setup\\PageFile. ValueName, Status = %lx\n", Status ));
  4804. }
  4805. return( Status );
  4806. }
  4807. NTSTATUS
  4808. SppMigrateSetupRegNonVolatileKeys(
  4809. IN PWSTR PartitionPath,
  4810. IN PWSTR SystemRoot,
  4811. IN HANDLE hDestControlSet,
  4812. IN PWSTR KeyPath,
  4813. IN BOOLEAN OverwriteValues,
  4814. IN BOOLEAN OverwriteACLs
  4815. )
  4816. /*++
  4817. Routine Description:
  4818. This routine migrates keys of the setup hive to the target hive.
  4819. These keys are subkeys of \Registry\Machine\System\CurrentControlSet,
  4820. and are listed on the section [SetupKeysToMigrate] on txtsetup.sif.
  4821. Arguments:
  4822. PartitionPath - supplies the NT name for the drive of windows nt.
  4823. SystemRoot - supplies nt path of the windows nt directory.
  4824. hDestLocalMachine - Handle to HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet on the target hive.
  4825. KeyPath - Path to the key to be migrated, relative to \Registry\Machine\System\CurrentControlSet.
  4826. SifHandle - Handle to txtsetup.sif
  4827. Return Value:
  4828. Status value indicating outcome of operation.
  4829. --*/
  4830. {
  4831. NTSTATUS Status;
  4832. OBJECT_ATTRIBUTES Obja;
  4833. UNICODE_STRING UnicodeString;
  4834. HANDLE hSrcKey;
  4835. HANDLE hTempSrcKey;
  4836. HANDLE SaveHiveHandle;
  4837. HANDLE hDestKey;
  4838. PWSTR TempKeyPath = L"\\registry\\machine\\TempKey";
  4839. PWSTR SaveHiveName;
  4840. IO_STATUS_BLOCK IoStatusBlock;
  4841. PSECURITY_DESCRIPTOR Security = NULL;
  4842. ULONG ResultLength;
  4843. //
  4844. // Open the key the key that needs to be saved
  4845. //
  4846. wcscpy(TemporaryBuffer,L"\\registry\\machine\\system\\currentcontrolset");
  4847. SpConcatenatePaths(TemporaryBuffer,KeyPath);
  4848. INIT_OBJA(&Obja,&UnicodeString,TemporaryBuffer);
  4849. Obja.RootDirectory = NULL;
  4850. Status = ZwOpenKey(&hSrcKey,KEY_ALL_ACCESS,&Obja);
  4851. if( !NT_SUCCESS( Status ) ) {
  4852. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to open %ls on the setup hive (%lx)\n", TemporaryBuffer, Status));
  4853. return( Status ) ;
  4854. }
  4855. //
  4856. // Create the hive file
  4857. //
  4858. wcscpy(TemporaryBuffer,PartitionPath);
  4859. SpConcatenatePaths(TemporaryBuffer,SystemRoot);
  4860. SpConcatenatePaths(TemporaryBuffer,L"system32\\config");
  4861. SpConcatenatePaths(TemporaryBuffer,L"TempKey");
  4862. SaveHiveName = SpDupStringW(TemporaryBuffer);
  4863. SpDeleteFile( SaveHiveName, NULL, NULL );
  4864. INIT_OBJA(&Obja,&UnicodeString,SaveHiveName);
  4865. Status = ZwCreateFile(
  4866. &SaveHiveHandle,
  4867. FILE_GENERIC_WRITE,
  4868. &Obja,
  4869. &IoStatusBlock,
  4870. NULL,
  4871. FILE_ATTRIBUTE_NORMAL,
  4872. 0, // no sharing
  4873. FILE_OVERWRITE_IF,
  4874. FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
  4875. NULL,
  4876. 0
  4877. );
  4878. if( !NT_SUCCESS( Status ) ) {
  4879. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to create the hive file %ls. Status = %lx\n", SaveHiveName, Status));
  4880. goto TempMigr_2;
  4881. }
  4882. Status = ZwSaveKey( hSrcKey, SaveHiveHandle );
  4883. ZwClose( SaveHiveHandle );
  4884. if( !NT_SUCCESS( Status ) ) {
  4885. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to save %ls key to the hive file %ls. Status = %lx\n", KeyPath, SaveHiveName, Status));
  4886. goto TempMigr_3;
  4887. }
  4888. Status = SpLoadUnloadKey( NULL,
  4889. NULL,
  4890. TempKeyPath,
  4891. SaveHiveName );
  4892. if( !NT_SUCCESS( Status ) ) {
  4893. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to load %ls key to the setup hive. Status = %lx\n", SaveHiveName, Status));
  4894. goto TempMigr_3;
  4895. }
  4896. //
  4897. // Open TempKey
  4898. //
  4899. INIT_OBJA(&Obja,&UnicodeString,TempKeyPath);
  4900. Obja.RootDirectory = NULL;
  4901. Status = ZwOpenKey(&hTempSrcKey,KEY_ALL_ACCESS,&Obja);
  4902. if( !NT_SUCCESS( Status ) ) {
  4903. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to open TempSrc key on the setup hive. Status = %lx\n", Status));
  4904. goto TempMigr_4;
  4905. }
  4906. //
  4907. // First, get the security descriptor from the source key so we can create
  4908. // the destination key with the correct ACL.
  4909. //
  4910. Status = ZwQuerySecurityObject(hTempSrcKey,
  4911. DACL_SECURITY_INFORMATION,
  4912. NULL,
  4913. 0,
  4914. &ResultLength
  4915. );
  4916. if(Status==STATUS_BUFFER_TOO_SMALL) {
  4917. Security=SpMemAlloc(ResultLength);
  4918. Status = ZwQuerySecurityObject(hTempSrcKey,
  4919. DACL_SECURITY_INFORMATION,
  4920. Security,
  4921. ResultLength,
  4922. &ResultLength);
  4923. if(!NT_SUCCESS(Status)) {
  4924. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: unable to query security for key %ws in the source hive (%lx)\n",
  4925. TempKeyPath,
  4926. Status)
  4927. );
  4928. SpMemFree(Security);
  4929. Security=NULL;
  4930. }
  4931. } else {
  4932. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: unable to query security size for key %ws in the source hive (%lx)\n",
  4933. TempKeyPath,
  4934. Status)
  4935. );
  4936. Security=NULL;
  4937. }
  4938. //
  4939. // Open the key on the target hive
  4940. //
  4941. INIT_OBJA(&Obja,&UnicodeString,KeyPath);
  4942. Obja.RootDirectory = hDestControlSet;
  4943. Status = ZwOpenKey(&hDestKey,KEY_ALL_ACCESS,&Obja);
  4944. if(!NT_SUCCESS(Status)) {
  4945. //
  4946. // Assume that failure was because the key didn't exist. Now try creating
  4947. // the key.
  4948. Obja.SecurityDescriptor = Security;
  4949. Status = ZwCreateKey(
  4950. &hDestKey,
  4951. KEY_ALL_ACCESS,
  4952. &Obja,
  4953. 0,
  4954. NULL,
  4955. REG_OPTION_NON_VOLATILE,
  4956. NULL
  4957. );
  4958. if(!NT_SUCCESS(Status)) {
  4959. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: unable to open or create key %ws(%lx)\n",KeyPath, Status));
  4960. if(Security) {
  4961. SpMemFree(Security);
  4962. }
  4963. goto TempMigr_5;
  4964. }
  4965. } else if (OverwriteACLs) {
  4966. Status = ZwSetSecurityObject(
  4967. hDestKey,
  4968. DACL_SECURITY_INFORMATION,
  4969. Security );
  4970. if(!NT_SUCCESS(Status)) {
  4971. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: unable to copy ACL to existing key %ws(%lx)\n",KeyPath, Status));
  4972. }
  4973. }
  4974. if(Security) {
  4975. SpMemFree(Security);
  4976. }
  4977. Status = SppCopyKeyRecursive(
  4978. hTempSrcKey,
  4979. hDestKey,
  4980. NULL,
  4981. NULL,
  4982. OverwriteValues,
  4983. OverwriteACLs
  4984. );
  4985. if( !NT_SUCCESS( Status ) ) {
  4986. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to migrate %ls to the target hive. KeyPath, Status = %lx\n", Status));
  4987. }
  4988. ZwClose( hDestKey );
  4989. TempMigr_5:
  4990. ZwClose( hTempSrcKey );
  4991. TempMigr_4:
  4992. //
  4993. // Unload hive
  4994. //
  4995. SpLoadUnloadKey( NULL,
  4996. NULL,
  4997. TempKeyPath,
  4998. NULL );
  4999. TempMigr_3:
  5000. SpDeleteFile( SaveHiveName, NULL, NULL );
  5001. TempMigr_2:
  5002. SpMemFree( SaveHiveName );
  5003. return( Status );
  5004. }
  5005. BOOLEAN
  5006. SpHivesFromInfs(
  5007. IN PVOID SifHandle,
  5008. IN LPCWSTR SectionName,
  5009. IN LPCWSTR SourcePath1,
  5010. IN LPCWSTR SourcePath2, OPTIONAL
  5011. IN HANDLE SystemHiveRoot,
  5012. IN HANDLE SoftwareHiveRoot,
  5013. IN HANDLE DefaultUserHiveRoot,
  5014. IN HANDLE HKR
  5015. )
  5016. /*++
  5017. Routine Description:
  5018. This routine runs addreg and delreg sections as listed in txtsetup.sif,
  5019. in order to create or perform the basic upgrade on the registry hives.
  5020. Each line in the given section is expected to be in the following form:
  5021. addreg = <filename>,<section>
  5022. or
  5023. delreg = <filename>,<section>
  5024. Multiple addreg and delreg lines can be supplied, and the sections are
  5025. processed in order listed.
  5026. The filename specs are filename only; the files are expected to be
  5027. in the source directory.
  5028. Arguments:
  5029. SifHandle - supplies the handle to txtsetup.sif.
  5030. SectionName - supplies the name of the section in txtsetuyp.sif that
  5031. lists infs/sections to be processed.
  5032. SourcePath - supplies NT-style path to the source files for installation.
  5033. SystemHiveRoot - supplies handle to root key of system hive under
  5034. construction.
  5035. SoftwareHiveRoot - supplies handle to root key of software hive under
  5036. construction.
  5037. DefaultUserHiveRoot - supplies handle to root key of default hive under
  5038. construction.
  5039. HKR - supplies key to be used for HKR.
  5040. Return Value:
  5041. Boolean value indicating outcome.
  5042. --*/
  5043. {
  5044. LPCWSTR PreviousInf;
  5045. LPCWSTR CurrentInf;
  5046. ULONG LineNumber;
  5047. LPCWSTR TypeSpec;
  5048. LPCWSTR SectionSpec;
  5049. PVOID InfHandle;
  5050. ULONG ErrorLine;
  5051. NTSTATUS Status;
  5052. LPWSTR name;
  5053. LPWSTR MediaShortname;
  5054. LPWSTR MediaDirectory;
  5055. //
  5056. // Allocate a buffer for names.
  5057. //
  5058. name = SpMemAlloc(1000);
  5059. LineNumber = 0;
  5060. PreviousInf = L"";
  5061. InfHandle = NULL;
  5062. while((TypeSpec = SpGetKeyName(SifHandle,SectionName,LineNumber))
  5063. && (CurrentInf = SpGetSectionLineIndex(SifHandle,SectionName,LineNumber,0))
  5064. && (SectionSpec = SpGetSectionLineIndex(SifHandle,SectionName,LineNumber,1))) {
  5065. //
  5066. // Only load the inf if it's different than the previous one,
  5067. // as a time optimization.
  5068. //
  5069. if(_wcsicmp(CurrentInf,PreviousInf)) {
  5070. if(InfHandle) {
  5071. SpFreeTextFile(InfHandle);
  5072. InfHandle = NULL;
  5073. }
  5074. MediaShortname = SpLookUpValueForFile(SifHandle,(LPWSTR)CurrentInf,INDEX_WHICHMEDIA,TRUE);
  5075. SpGetSourceMediaInfo(SifHandle,MediaShortname,NULL,NULL,&MediaDirectory);
  5076. wcscpy(name,SourcePath1);
  5077. if(SourcePath2) {
  5078. SpConcatenatePaths(name,SourcePath2);
  5079. }
  5080. SpConcatenatePaths(name,MediaDirectory);
  5081. SpConcatenatePaths(name,CurrentInf);
  5082. Status = SpLoadSetupTextFile(name,NULL,0,&InfHandle,&ErrorLine,FALSE,FALSE);
  5083. if(!NT_SUCCESS(Status)) {
  5084. SpStartScreen(
  5085. SP_SCRN_INF_LINE_CORRUPT,
  5086. 3,
  5087. HEADER_HEIGHT+1,
  5088. FALSE,
  5089. FALSE,
  5090. DEFAULT_ATTRIBUTE,
  5091. ErrorLine,
  5092. CurrentInf
  5093. );
  5094. SpDisplayStatusOptions(DEFAULT_STATUS_ATTRIBUTE,SP_STAT_F3_EQUALS_EXIT,0);
  5095. SpInputDrain();
  5096. while(SpInputGetKeypress() != KEY_F3) ;
  5097. SpDone(0,FALSE,TRUE);
  5098. }
  5099. PreviousInf = CurrentInf;
  5100. }
  5101. if(!_wcsicmp(TypeSpec,L"addreg")) {
  5102. Status = SpProcessAddRegSection(
  5103. InfHandle,
  5104. SectionSpec,
  5105. SystemHiveRoot,
  5106. SoftwareHiveRoot,
  5107. DefaultUserHiveRoot,
  5108. HKR
  5109. );
  5110. SendSetupProgressEvent(SavingSettingsEvent, InitializeHiveEvent, NULL);
  5111. } else {
  5112. if(!_wcsicmp(TypeSpec,L"delreg")) {
  5113. Status = SpProcessDelRegSection(
  5114. InfHandle,
  5115. SectionSpec,
  5116. SystemHiveRoot,
  5117. SoftwareHiveRoot,
  5118. DefaultUserHiveRoot,
  5119. HKR
  5120. );
  5121. SendSetupProgressEvent(SavingSettingsEvent, InitializeHiveEvent, NULL);
  5122. } else {
  5123. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: unknown hive section type spec %ws\n",TypeSpec));
  5124. SpFreeTextFile(InfHandle);
  5125. SpMemFree(name);
  5126. return(FALSE);
  5127. }
  5128. }
  5129. if(!NT_SUCCESS(Status)) {
  5130. SpFreeTextFile(InfHandle);
  5131. SpMemFree(name);
  5132. return(FALSE);
  5133. }
  5134. LineNumber++;
  5135. }
  5136. if(InfHandle) {
  5137. SpFreeTextFile(InfHandle);
  5138. }
  5139. SpMemFree(name);
  5140. return(TRUE);
  5141. }
  5142. NTSTATUS
  5143. SpMigrateSetupKeys(
  5144. IN PWSTR PartitionPath,
  5145. IN PWSTR SystemRoot,
  5146. IN HANDLE hDestControlSet,
  5147. IN PVOID SifHandle
  5148. )
  5149. /*++
  5150. Routine Description:
  5151. This routine migrates keys of the setup hive to the target hive.
  5152. These keys are subkeys of \Registry\Machine\System\CurrentControlSet,
  5153. and are listed on the section [SetupKeysToMigrate] on txtsetup.sif.
  5154. Arguments:
  5155. PartitionPath - supplies the NT name for the drive of windows nt.
  5156. SystemRoot - supplies nt path of the windows nt directory.
  5157. hDestLocalMachine - Handle to HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet
  5158. on the target hive.
  5159. SifHandle - Handle to txtsetup.sif
  5160. Return Value:
  5161. Status value indicating outcome of operation.
  5162. --*/
  5163. {
  5164. NTSTATUS Status;
  5165. NTSTATUS SavedStatus;
  5166. OBJECT_ATTRIBUTES Obja;
  5167. UNICODE_STRING UnicodeString;
  5168. HANDLE hSrcKey;
  5169. ULONG LineIndex;
  5170. PWSTR KeyName;
  5171. PWSTR SectionName = L"SetupKeysToMigrate";
  5172. BOOLEAN MigrateVolatileKeys;
  5173. BOOLEAN OverwriteValues;
  5174. BOOLEAN OverwriteACLs;
  5175. BOOLEAN MigrateOnCleanInstall;
  5176. BOOLEAN MigrateOnUpgrade;
  5177. ULONG InstType;
  5178. PWSTR p;
  5179. SavedStatus = STATUS_SUCCESS;
  5180. for( LineIndex = 0;
  5181. ( KeyName = SpGetKeyName( SifHandle,
  5182. SectionName,
  5183. LineIndex ) ) != NULL;
  5184. LineIndex++ ) {
  5185. p = SpGetSectionKeyIndex ( SifHandle,
  5186. SectionName,
  5187. KeyName,
  5188. 0 );
  5189. MigrateVolatileKeys = ( ( p != NULL ) && ( SpStringToLong( p, NULL, 10 ) == 0 ) )? FALSE : TRUE;
  5190. p = SpGetSectionKeyIndex ( SifHandle,
  5191. SectionName,
  5192. KeyName,
  5193. 1 );
  5194. if( p != NULL ) {
  5195. InstType = SpStringToLong( p, NULL, 10 );
  5196. if( InstType > 2 ) {
  5197. InstType = 2;
  5198. }
  5199. } else {
  5200. InstType = 2;
  5201. }
  5202. MigrateOnCleanInstall = ( InstType != 1 );
  5203. MigrateOnUpgrade = ( InstType != 0 );
  5204. p = SpGetSectionKeyIndex ( SifHandle,
  5205. SectionName,
  5206. KeyName,
  5207. 2 );
  5208. OverwriteValues = ( ( p != NULL ) && ( SpStringToLong( p, NULL, 10 ) == 0 ) )? FALSE : TRUE;
  5209. p = SpGetSectionKeyIndex ( SifHandle,
  5210. SectionName,
  5211. KeyName,
  5212. 3 );
  5213. OverwriteACLs = ( ( p != NULL ) && ( SpStringToLong( p, NULL, 10 ) != 0 ) );
  5214. if( ( ( NTUpgrade == DontUpgrade ) && MigrateOnCleanInstall ) ||
  5215. ( ( NTUpgrade != DontUpgrade ) && MigrateOnUpgrade ) ) {
  5216. if( MigrateVolatileKeys ) {
  5217. wcscpy( TemporaryBuffer, L"\\registry\\machine\\system\\currentcontrolset\\" );
  5218. SpConcatenatePaths(TemporaryBuffer, KeyName);
  5219. //
  5220. // Open the source key
  5221. //
  5222. INIT_OBJA(&Obja,&UnicodeString,TemporaryBuffer);
  5223. Obja.RootDirectory = NULL;
  5224. Status = ZwOpenKey(&hSrcKey,KEY_ALL_ACCESS,&Obja);
  5225. if( !NT_SUCCESS( Status ) ) {
  5226. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to open %ls on the setup hive (%lx)\n", TemporaryBuffer, Status));
  5227. if( SavedStatus != STATUS_SUCCESS ) {
  5228. SavedStatus = Status;
  5229. }
  5230. continue;
  5231. }
  5232. Status = SppCopyKeyRecursive(
  5233. hSrcKey,
  5234. hDestControlSet,
  5235. NULL,
  5236. KeyName,
  5237. OverwriteValues,
  5238. OverwriteACLs
  5239. );
  5240. if( !NT_SUCCESS( Status ) ) {
  5241. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to migrate %ls. Status = %lx\n", KeyName, Status));
  5242. if( SavedStatus != STATUS_SUCCESS ) {
  5243. SavedStatus = Status;
  5244. }
  5245. }
  5246. } else {
  5247. Status = SppMigrateSetupRegNonVolatileKeys( PartitionPath,
  5248. SystemRoot,
  5249. hDestControlSet,
  5250. KeyName,
  5251. OverwriteValues,
  5252. OverwriteACLs );
  5253. if( !NT_SUCCESS( Status ) ) {
  5254. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to migrate %ls. Status = %lx\n", KeyName, Status));
  5255. if( SavedStatus != STATUS_SUCCESS ) {
  5256. SavedStatus = Status;
  5257. }
  5258. }
  5259. }
  5260. }
  5261. }
  5262. return( SavedStatus );
  5263. }
  5264. NTSTATUS
  5265. SppMigrateFtKeys(
  5266. IN HANDLE hDestSystemHive
  5267. )
  5268. /*++
  5269. Routine Description:
  5270. This routine migrates the ftdisk related keys on the setup hive to the
  5271. target hive.
  5272. Arguments:
  5273. hDestSystemHive - Handle to the root of the system hive on the system
  5274. being upgraded.
  5275. Return Value:
  5276. Status value indicating outcome of operation.
  5277. --*/
  5278. {
  5279. NTSTATUS Status;
  5280. NTSTATUS SavedStatus;
  5281. OBJECT_ATTRIBUTES Obja;
  5282. UNICODE_STRING UnicodeString;
  5283. PWSTR FtDiskKeys[] = {
  5284. L"Disk",
  5285. L"MountedDevices"
  5286. };
  5287. WCHAR KeyPath[MAX_PATH];
  5288. HANDLE SrcKey;
  5289. ULONG i;
  5290. SavedStatus = STATUS_SUCCESS;
  5291. for( i = 0; i < sizeof(FtDiskKeys)/sizeof(PWSTR); i++ ) {
  5292. //
  5293. // Open the source key
  5294. //
  5295. swprintf( KeyPath, L"\\registry\\machine\\system\\%ls", FtDiskKeys[i] );
  5296. INIT_OBJA(&Obja,&UnicodeString,KeyPath);
  5297. Obja.RootDirectory = NULL;
  5298. Status = ZwOpenKey(&SrcKey,KEY_ALL_ACCESS,&Obja);
  5299. if( !NT_SUCCESS( Status ) ) {
  5300. //
  5301. // If the key doesn't exist, just assume success
  5302. //
  5303. if( Status != STATUS_OBJECT_NAME_NOT_FOUND ) {
  5304. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to open %ls on the setup hive. Status = %lx \n", KeyPath, Status));
  5305. if( SavedStatus == STATUS_SUCCESS ) {
  5306. SavedStatus = Status;
  5307. }
  5308. }
  5309. continue;
  5310. }
  5311. Status = SppCopyKeyRecursive( SrcKey,
  5312. hDestSystemHive,
  5313. NULL,
  5314. FtDiskKeys[i],
  5315. (((NTUpgrade == UpgradeFull) && !_wcsicmp( FtDiskKeys[i], L"MountedDevices"))? FALSE : TRUE),
  5316. FALSE
  5317. );
  5318. if( !NT_SUCCESS( Status ) ) {
  5319. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to migrate %ls to SYSTEM\\%ls. Status = %lx\n", KeyPath, FtDiskKeys[i], Status));
  5320. if( SavedStatus == STATUS_SUCCESS ) {
  5321. SavedStatus = Status;
  5322. }
  5323. }
  5324. ZwClose( SrcKey );
  5325. }
  5326. return( SavedStatus );
  5327. }
  5328. NTSTATUS
  5329. SppCleanupKeysFromRemoteInstall(
  5330. VOID
  5331. )
  5332. /*++
  5333. Routine Description:
  5334. This routine cleans up some keys that remote install modified to get
  5335. the network card working. This is so that PnP setup during GUI-mode is
  5336. not confused by the card already being setup.
  5337. Arguments:
  5338. None.
  5339. Return Value:
  5340. Status value indicating outcome of operation.
  5341. --*/
  5342. {
  5343. OBJECT_ATTRIBUTES Obja;
  5344. UNICODE_STRING UnicodeString;
  5345. NTSTATUS Status;
  5346. ULONG ResultLength;
  5347. HANDLE hKey;
  5348. PWSTR DeviceInstance;
  5349. //
  5350. // Open the remote boot key.
  5351. //
  5352. wcscpy( TemporaryBuffer, L"\\registry\\machine\\system\\currentcontrolset\\control\\remoteboot" );
  5353. INIT_OBJA(&Obja,&UnicodeString,TemporaryBuffer);
  5354. Obja.RootDirectory = NULL;
  5355. Status = ZwOpenKey(&hKey,KEY_READ,&Obja);
  5356. if( !NT_SUCCESS( Status ) ) {
  5357. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: SppCleanupKeysFromRemoteInstall unable to open %ls on the setup hive (%lx)\n", TemporaryBuffer, Status));
  5358. return Status;
  5359. }
  5360. //
  5361. // Read the netboot card's device instance out.
  5362. //
  5363. RtlInitUnicodeString(&UnicodeString, REGSTR_VAL_DEVICE_INSTANCE);
  5364. Status = ZwQueryValueKey(
  5365. hKey,
  5366. &UnicodeString,
  5367. KeyValuePartialInformation,
  5368. TemporaryBuffer,
  5369. sizeof(TemporaryBuffer),
  5370. &ResultLength
  5371. );
  5372. ZwClose(hKey);
  5373. if( !NT_SUCCESS( Status ) ) {
  5374. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: SppCleanupKeysFromRemoteInstall unable to read RemoteBoot\\DeviceInstance value (%lx)\n", Status));
  5375. return Status;
  5376. }
  5377. DeviceInstance = SpDupStringW((PWSTR)(((PKEY_VALUE_PARTIAL_INFORMATION)TemporaryBuffer)->Data));
  5378. //
  5379. // Now open the device instance key under control\enum.
  5380. //
  5381. wcscpy( TemporaryBuffer, L"\\registry\\machine\\system\\currentcontrolset\\enum\\" );
  5382. SpConcatenatePaths(TemporaryBuffer, DeviceInstance);
  5383. SpMemFree(DeviceInstance);
  5384. INIT_OBJA(&Obja,&UnicodeString,TemporaryBuffer);
  5385. Obja.RootDirectory = NULL;
  5386. Status = ZwOpenKey(&hKey,KEY_ALL_ACCESS,&Obja);
  5387. if( !NT_SUCCESS( Status ) ) {
  5388. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: SppCleanupKeysFromRemoteInstall unable to open %ls on the setup hive (%lx)\n", TemporaryBuffer, Status));
  5389. return Status;
  5390. }
  5391. //
  5392. // Now delete the keys we added to get the card up -- Service,
  5393. // ClassGUID, and Driver.
  5394. //
  5395. RtlInitUnicodeString(&UnicodeString, REGSTR_VAL_SERVICE);
  5396. Status = ZwDeleteValueKey(hKey,&UnicodeString);
  5397. if( !NT_SUCCESS( Status ) ) {
  5398. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: SppCleanupKeysFromRemoteInstall unable to delete Service (%lx)\n", Status));
  5399. ZwClose(hKey);
  5400. return Status;
  5401. }
  5402. RtlInitUnicodeString(&UnicodeString, REGSTR_VAL_CLASSGUID);
  5403. Status = ZwDeleteValueKey(hKey,&UnicodeString);
  5404. if( !NT_SUCCESS( Status ) ) {
  5405. RtlInitUnicodeString(&UnicodeString, REGSTR_VALUE_GUID);
  5406. Status = ZwDeleteValueKey(hKey,&UnicodeString);
  5407. if( !NT_SUCCESS( Status ) ) {
  5408. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: SppCleanupKeysFromRemoteInstall unable to delete ClassGUID (%lx)\n", Status));
  5409. ZwClose(hKey);
  5410. return Status;
  5411. }
  5412. }
  5413. RtlInitUnicodeString(&UnicodeString, REGSTR_VAL_DRIVER);
  5414. Status = ZwDeleteValueKey(hKey,&UnicodeString);
  5415. if( !NT_SUCCESS( Status ) ) {
  5416. RtlInitUnicodeString(&UnicodeString, REGSTR_VALUE_DRVINST);
  5417. Status = ZwDeleteValueKey(hKey,&UnicodeString);
  5418. ZwClose(hKey);
  5419. if( !NT_SUCCESS( Status ) ) {
  5420. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: SppCleanupKeysFromRemoteInstall unable to delete Driver (%lx)\n", Status));
  5421. return Status;
  5422. }
  5423. }
  5424. return STATUS_SUCCESS;
  5425. }
  5426. NTSTATUS
  5427. SpDisableUnsupportedScsiDrivers(
  5428. IN HANDLE hKeyControlSet
  5429. )
  5430. {
  5431. NTSTATUS Status;
  5432. NTSTATUS SavedStatus;
  5433. PHARDWARE_COMPONENT TmpHw;
  5434. ULONG u;
  5435. OBJECT_ATTRIBUTES Obja;
  5436. UNICODE_STRING UnicodeString;
  5437. HANDLE hKeyControlSetServices;
  5438. ULONG val = SERVICE_DISABLED;
  5439. //
  5440. // Open controlset\services.
  5441. //
  5442. INIT_OBJA(&Obja,&UnicodeString,L"services");
  5443. Obja.RootDirectory = hKeyControlSet;
  5444. Status = ZwCreateKey(
  5445. &hKeyControlSetServices,
  5446. KEY_ALL_ACCESS,
  5447. &Obja,
  5448. 0,
  5449. NULL,
  5450. REG_OPTION_NON_VOLATILE,
  5451. NULL
  5452. );
  5453. if(!NT_SUCCESS(Status)) {
  5454. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: unable to open services key (%lx)\n",Status));
  5455. return(Status);
  5456. }
  5457. SavedStatus = STATUS_SUCCESS;
  5458. for( TmpHw = UnsupportedScsiHardwareToDisable;
  5459. TmpHw != NULL;
  5460. TmpHw = TmpHw->Next ) {
  5461. Status = SpOpenSetValueAndClose(
  5462. hKeyControlSetServices,
  5463. TmpHw->IdString,
  5464. L"Start",
  5465. ULONG_VALUE(val)
  5466. );
  5467. if(!NT_SUCCESS(Status)) {
  5468. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: unable to disable unsupported driver %ls. Status = %lx \n", TmpHw->IdString, Status));
  5469. if( SavedStatus == STATUS_SUCCESS ) {
  5470. SavedStatus = Status;
  5471. }
  5472. } else {
  5473. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: unsupported driver %ls successfully disabled. \n", TmpHw->IdString));
  5474. }
  5475. }
  5476. ZwClose( hKeyControlSetServices );
  5477. return( SavedStatus );
  5478. }
  5479. NTSTATUS
  5480. SpAppendPathToDevicePath(
  5481. IN HANDLE hKeySoftwareHive,
  5482. IN PWSTR OemPnpDriversDirPath
  5483. )
  5484. /*++
  5485. Routine Description:
  5486. This routine should be called only on OEM preinstall.
  5487. It appends the path to the directory that cntains the OEM drivers to be installed during GUI
  5488. setup to HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion!DevicePath.
  5489. Arguments:
  5490. hKeySoftwareKey - Handle to the root of the software hive.
  5491. OemPnpDriversDirPath - Path to the directory that contains the OEM pnp drivers (eg. \Dell).
  5492. Return Value:
  5493. Status value indicating outcome of operation.
  5494. --*/
  5495. {
  5496. NTSTATUS Status;
  5497. ULONG Length;
  5498. PWSTR szCurrentVersionKey = L"Microsoft\\Windows\\CurrentVersion";
  5499. PWSTR szDevicePath = L"DevicePath";
  5500. Status = SpGetValueKey( hKeySoftwareHive,
  5501. szCurrentVersionKey,
  5502. szDevicePath,
  5503. sizeof(TemporaryBuffer),
  5504. (PCHAR)TemporaryBuffer,
  5505. &Length );
  5506. if( NT_SUCCESS(Status) ) {
  5507. if( wcslen( (PWSTR)(((PKEY_VALUE_PARTIAL_INFORMATION)TemporaryBuffer)->Data) ) != 0 ) {
  5508. PWSTR BeginStrPtr;
  5509. PWSTR EndStrPtr;
  5510. BOOL Done = FALSE;
  5511. //
  5512. // OemPnpDriversDirPath can have several entries, separated by
  5513. // a semicolon. For each entry, we need to:
  5514. // 1. append a semicolon.
  5515. // 2. append %SystemDrive%
  5516. // 3. concatenate the entry.
  5517. //
  5518. BeginStrPtr = OemPnpDriversDirPath;
  5519. do {
  5520. //
  5521. // Mark the end of this entry.
  5522. //
  5523. EndStrPtr = BeginStrPtr;
  5524. while( (*EndStrPtr) && (*EndStrPtr != L';') ) {
  5525. EndStrPtr++;
  5526. }
  5527. //
  5528. // Is this the last entry?
  5529. //
  5530. if( *EndStrPtr == 0 ) {
  5531. Done = TRUE;
  5532. }
  5533. *EndStrPtr = 0;
  5534. wcscat( (PWSTR)(((PKEY_VALUE_PARTIAL_INFORMATION)TemporaryBuffer)->Data), L";" );
  5535. wcscat( (PWSTR)(((PKEY_VALUE_PARTIAL_INFORMATION)TemporaryBuffer)->Data), L"%SystemDrive%" );
  5536. SpConcatenatePaths((PWSTR)(((PKEY_VALUE_PARTIAL_INFORMATION)TemporaryBuffer)->Data), BeginStrPtr);
  5537. BeginStrPtr = EndStrPtr + 1;
  5538. //
  5539. // Take care of the case where the user ended the
  5540. // OemPnpDriversPath entry with a semicolon.
  5541. //
  5542. if( *BeginStrPtr == 0 ) {
  5543. Done = TRUE;
  5544. }
  5545. } while( !Done );
  5546. //
  5547. // Now put the entry back into the registry.
  5548. //
  5549. Status = SpOpenSetValueAndClose( hKeySoftwareHive,
  5550. szCurrentVersionKey,
  5551. szDevicePath,
  5552. ((PKEY_VALUE_PARTIAL_INFORMATION)TemporaryBuffer)->Type,
  5553. ((PKEY_VALUE_PARTIAL_INFORMATION)TemporaryBuffer)->Data,
  5554. (wcslen( (PWSTR)(((PKEY_VALUE_PARTIAL_INFORMATION)TemporaryBuffer)->Data) ) +1 ) * sizeof(WCHAR) );
  5555. }
  5556. }
  5557. return( Status );
  5558. }
  5559. NTSTATUS
  5560. SpAppendFullPathListToDevicePath (
  5561. IN HANDLE hKeySoftwareHive,
  5562. IN PWSTR PnpDriverFullPathList
  5563. )
  5564. /*++
  5565. Routine Description:
  5566. This routine appends the given full path list to the directory that cntains the OEM drivers to be installed during GUI
  5567. setup to HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion!DevicePath.
  5568. Arguments:
  5569. hKeySoftwareKey - Handle to the root of the software hive.
  5570. PnpDriverFullPathList - List of full paths to the directories that contain additional pnp drivers
  5571. Return Value:
  5572. Status value indicating outcome of operation.
  5573. --*/
  5574. {
  5575. NTSTATUS Status;
  5576. ULONG Length;
  5577. PWSTR szCurrentVersionKey = L"Microsoft\\Windows\\CurrentVersion";
  5578. PWSTR szDevicePath = L"DevicePath";
  5579. Status = SpGetValueKey (
  5580. hKeySoftwareHive,
  5581. szCurrentVersionKey,
  5582. szDevicePath,
  5583. sizeof(TemporaryBuffer),
  5584. (PCHAR)TemporaryBuffer,
  5585. &Length
  5586. );
  5587. if (NT_SUCCESS (Status)) {
  5588. if (*(WCHAR*)((PKEY_VALUE_PARTIAL_INFORMATION)TemporaryBuffer)->Data) {
  5589. wcscat ((PWSTR)(((PKEY_VALUE_PARTIAL_INFORMATION)TemporaryBuffer)->Data), L";");
  5590. }
  5591. wcscat ((PWSTR)(((PKEY_VALUE_PARTIAL_INFORMATION)TemporaryBuffer)->Data), PnpDriverFullPathList);
  5592. //
  5593. // Now put the entry back into the registry.
  5594. //
  5595. Status = SpOpenSetValueAndClose (
  5596. hKeySoftwareHive,
  5597. szCurrentVersionKey,
  5598. szDevicePath,
  5599. ((PKEY_VALUE_PARTIAL_INFORMATION)TemporaryBuffer)->Type,
  5600. ((PKEY_VALUE_PARTIAL_INFORMATION)TemporaryBuffer)->Data,
  5601. (wcslen ((PWSTR)((PKEY_VALUE_PARTIAL_INFORMATION)TemporaryBuffer)->Data) + 1) * sizeof(WCHAR)
  5602. );
  5603. }
  5604. return( Status );
  5605. }
  5606. #if defined(REMOTE_BOOT)
  5607. NTSTATUS
  5608. SpCopyRemoteBootKeyword(
  5609. IN PVOID SifHandle,
  5610. IN PWSTR KeywordName,
  5611. IN HANDLE hKeyCCSetControl
  5612. )
  5613. /*++
  5614. Routine Description:
  5615. This routine looks in a .sif file for the specified keyword
  5616. in the [RemoteBoot] section. If it finds it, it creates a registry
  5617. DWORD value with same name under System\CurrentControlSet\Control\
  5618. RemoteBoot. The value will be set to 1 if the sif keyword was
  5619. "Yes" and 0 if it was "No" (or anything else).
  5620. Arguments:
  5621. SifHandle - The handle to the open SIF file.
  5622. KeywordName - The name of the keyword.
  5623. hKeyCCSetControl - The handle to CurrentControlSet\Control.
  5624. Return Value:
  5625. Status value indicating outcome of operation.
  5626. --*/
  5627. {
  5628. PWSTR KeywordSifValue;
  5629. DWORD KeywordRegistryValue;
  5630. NTSTATUS Status;
  5631. //
  5632. // First see if the value exists in the SIF.
  5633. //
  5634. KeywordSifValue = SpGetSectionKeyIndex(SifHandle,
  5635. SIF_REMOTEBOOT,
  5636. KeywordName,
  5637. 0);
  5638. if (KeywordSifValue == NULL) {
  5639. return STATUS_SUCCESS;
  5640. }
  5641. //
  5642. // This is the value we write to the registry.
  5643. //
  5644. if ((KeywordSifValue[0] == 'Y') || (KeywordSifValue[0] == 'y')) {
  5645. KeywordRegistryValue = 1;
  5646. } else {
  5647. KeywordRegistryValue = 0;
  5648. }
  5649. //
  5650. // Set the value.
  5651. //
  5652. Status = SpOpenSetValueAndClose(
  5653. hKeyCCSetControl,
  5654. SIF_REMOTEBOOT,
  5655. KeywordName,
  5656. ULONG_VALUE(KeywordRegistryValue)
  5657. );
  5658. return Status;
  5659. }
  5660. #endif // defined(REMOTE_BOOT)
  5661. NTSTATUS
  5662. SppDisableDynamicVolumes(
  5663. IN HANDLE hCCSet
  5664. )
  5665. /*++
  5666. Routine Description:
  5667. This routine disable dynamic volumes by disabling the appropriate services in the
  5668. target hive.
  5669. In addition, DmServer is reset to MANUAL start, so that it will only run when
  5670. the LDM UI is open.
  5671. Arguments:
  5672. hCCSet - Handle to CurrentControlSet of the target system hive.
  5673. Return Value:
  5674. Status value indicating outcome of operation.
  5675. --*/
  5676. {
  5677. OBJECT_ATTRIBUTES Obja;
  5678. UNICODE_STRING UnicodeString;
  5679. NTSTATUS Status;
  5680. NTSTATUS SavedStatus;
  5681. DWORD u;
  5682. ULONG i;
  5683. HANDLE hServices;
  5684. WCHAR KeyPath[MAX_PATH];
  5685. PWSTR LDMServices[] = {
  5686. L"dmboot",
  5687. L"dmio",
  5688. L"dmload"
  5689. };
  5690. PWSTR LDMDmServer = L"dmserver";
  5691. //
  5692. // Open ControlSet\Services.
  5693. //
  5694. INIT_OBJA(&Obja,&UnicodeString,L"Services");
  5695. Obja.RootDirectory = hCCSet;
  5696. Status = ZwOpenKey(&hServices,KEY_ALL_ACCESS,&Obja);
  5697. if(!NT_SUCCESS(Status)) {
  5698. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to open CurrentControlSet\\Services. Status = %lx \n",Status));
  5699. return(Status);
  5700. }
  5701. SavedStatus = STATUS_SUCCESS;
  5702. u = 0x4;
  5703. for( i = 0; i < sizeof(LDMServices)/sizeof(PWSTR); i++ ) {
  5704. Status = SpOpenSetValueAndClose( hServices,
  5705. LDMServices[i],
  5706. L"Start",
  5707. ULONG_VALUE(u)
  5708. );
  5709. if( !NT_SUCCESS( Status ) ) {
  5710. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to disable HKLM\\SYSTEM\\CurrentControlSet\\Services\\%ls. Status = %lx\n", LDMServices[i], Status));
  5711. if( SavedStatus == STATUS_SUCCESS ) {
  5712. SavedStatus = Status;
  5713. }
  5714. }
  5715. }
  5716. u = 0x3;
  5717. Status = SpOpenSetValueAndClose( hServices,
  5718. LDMDmServer,
  5719. L"Start",
  5720. ULONG_VALUE(u)
  5721. );
  5722. if( !NT_SUCCESS( Status ) ) {
  5723. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to set HKLM\\SYSTEM\\CurrentControlSet\\Services\\%ls to MANUAL start. Status = %lx\n", LDMDmServer, Status));
  5724. if( SavedStatus == STATUS_SUCCESS ) {
  5725. SavedStatus = Status;
  5726. }
  5727. }
  5728. ZwClose( hServices );
  5729. return( SavedStatus );
  5730. }
  5731. NTSTATUS
  5732. SpGetRegistryValue(
  5733. IN HANDLE KeyHandle,
  5734. IN PWSTR ValueName,
  5735. OUT PKEY_VALUE_FULL_INFORMATION *Information
  5736. )
  5737. /*++
  5738. Routine Description:
  5739. This routine is invoked to retrieve the data for a registry key's value.
  5740. This is done by querying the value of the key with a zero-length buffer
  5741. to determine the size of the value, and then allocating a buffer and
  5742. actually querying the value into the buffer.
  5743. It is the responsibility of the caller to free the buffer.
  5744. Arguments:
  5745. KeyHandle - Supplies the key handle whose value is to be queried
  5746. ValueName - Supplies the null-terminated Unicode name of the value.
  5747. Information - Returns a pointer to the allocated data buffer.
  5748. Return Value:
  5749. The function value is the final status of the query operation.
  5750. --*/
  5751. {
  5752. UNICODE_STRING unicodeString;
  5753. NTSTATUS status;
  5754. PKEY_VALUE_FULL_INFORMATION infoBuffer;
  5755. ULONG keyValueLength;
  5756. PAGED_CODE();
  5757. RtlInitUnicodeString( &unicodeString, ValueName );
  5758. //
  5759. // Figure out how big the data value is so that a buffer of the
  5760. // appropriate size can be allocated.
  5761. //
  5762. status = ZwQueryValueKey( KeyHandle,
  5763. &unicodeString,
  5764. KeyValueFullInformation,
  5765. (PVOID) NULL,
  5766. 0,
  5767. &keyValueLength );
  5768. if (status != STATUS_BUFFER_OVERFLOW &&
  5769. status != STATUS_BUFFER_TOO_SMALL) {
  5770. ASSERT(!NT_SUCCESS(status));
  5771. return status;
  5772. }
  5773. //
  5774. // Allocate a buffer large enough to contain the entire key data value.
  5775. //
  5776. infoBuffer = SpMemAlloc(keyValueLength);
  5777. if (!infoBuffer) {
  5778. return STATUS_INSUFFICIENT_RESOURCES;
  5779. }
  5780. //
  5781. // Query the data for the key value.
  5782. //
  5783. status = ZwQueryValueKey( KeyHandle,
  5784. &unicodeString,
  5785. KeyValueFullInformation,
  5786. infoBuffer,
  5787. keyValueLength,
  5788. &keyValueLength );
  5789. if (!NT_SUCCESS( status )) {
  5790. SpMemFree(infoBuffer);
  5791. return status;
  5792. }
  5793. //
  5794. // Everything worked, so simply return the address of the allocated
  5795. // buffer to the caller, who is now responsible for freeing it.
  5796. //
  5797. *Information = infoBuffer;
  5798. return STATUS_SUCCESS;
  5799. }
  5800. VOID
  5801. SpUpdateDeviceInstanceKeyData(
  5802. IN HANDLE InstanceKey,
  5803. IN HANDLE ClassBranchKey,
  5804. IN PUNICODE_STRING EnumName,
  5805. IN PUNICODE_STRING DeviceName,
  5806. IN PUNICODE_STRING InstanceName
  5807. )
  5808. /*++
  5809. Routine Description:
  5810. This routine updates (removes\changes type\names) the various values under
  5811. the device instance key on an upgrade.
  5812. Arguments:
  5813. InstanceKey - Handle to the device instance key.
  5814. ClassBranchKey - Handle to the classes branch.
  5815. EnumName - Enumerator name.
  5816. DeviceName - Device name.
  5817. InstanceName - Instance name.
  5818. Return Value:
  5819. None.
  5820. --*/
  5821. {
  5822. NTSTATUS status;
  5823. UNICODE_STRING valueName, guidString, drvInstString;
  5824. DWORD length;
  5825. GUID guid;
  5826. PKEY_VALUE_FULL_INFORMATION info, guidInfo;
  5827. PWCHAR ids, className;
  5828. ULONG drvInst;
  5829. WCHAR driver[GUID_STRING_LEN + 5];
  5830. OBJECT_ATTRIBUTES obja;
  5831. HANDLE hClassKey;
  5832. BOOLEAN guidAllocatedViaRtl = FALSE;
  5833. //
  5834. // Preinit
  5835. //
  5836. RtlInitUnicodeString(&guidString, NULL);
  5837. info = NULL;
  5838. guidInfo = NULL;
  5839. //
  5840. // Look at the instance key to see if we are dealing with a WinXP Beta2
  5841. // machine. If so, we need to convert it's compressed PnP data format back
  5842. // to the original Win2K format (app compat):
  5843. //
  5844. // <Normal, Win2K/WinXP> <Compressed, XP Beta2>
  5845. // "ClassGUID" (REG_SZ) "GUID" (REG_BINARY)
  5846. // "Driver" (REG_SZ, ClassGUID\DrvInst) "DrvInst" (REG_DWORD, DrvInst)
  5847. // "HardwareID" (UNICODE, MultiSz) "HwIDs" (ANSI-REG_BINARY, MultiSz)
  5848. // "CompatibleIDs" (UNICODE, MultiSz) "CIDs" (ANSI-REG_BINARY, MultiSz)
  5849. // "Class" (UNICODE) none, retrieved using ClassGUID
  5850. //
  5851. //
  5852. // Do we have the XP-Beta2 style "GUID" key?
  5853. //
  5854. status = SpGetRegistryValue(InstanceKey, REGSTR_VALUE_GUID, &info);
  5855. if (NT_SUCCESS(status) && !info) {
  5856. status = STATUS_UNSUCCESSFUL;
  5857. }
  5858. if (NT_SUCCESS(status)) {
  5859. //
  5860. // Change "GUID" (REG_BINARY) to "ClassGUID" (REG_SZ).
  5861. //
  5862. status = RtlStringFromGUID((GUID *)((PUCHAR)info + info->DataOffset), &guidString);
  5863. SpMemFree(info);
  5864. if (NT_SUCCESS(status)) {
  5865. guidAllocatedViaRtl = TRUE;
  5866. RtlInitUnicodeString(&valueName, REGSTR_VAL_CLASSGUID);
  5867. ZwSetValueKey(
  5868. InstanceKey,
  5869. &valueName,
  5870. 0,
  5871. REG_SZ,
  5872. guidString.Buffer,
  5873. guidString.Length + sizeof(UNICODE_NULL));
  5874. //
  5875. // Delete old "GUID" value
  5876. //
  5877. RtlInitUnicodeString(&valueName, REGSTR_VALUE_GUID);
  5878. ZwDeleteValueKey(InstanceKey, &valueName);
  5879. }
  5880. } else {
  5881. //
  5882. // This might be a rare Lab1 build where we've already done the
  5883. // conversion but we forgot to restore the class name.
  5884. //
  5885. status = SpGetRegistryValue(InstanceKey, REGSTR_VAL_CLASS, &info);
  5886. if (NT_SUCCESS(status) && info) {
  5887. //
  5888. // We successfully retrieved the class name from the device
  5889. // instance key--no need to attempt further migration.
  5890. //
  5891. SpMemFree(info);
  5892. status = STATUS_UNSUCCESSFUL;
  5893. } else {
  5894. status = SpGetRegistryValue(InstanceKey, REGSTR_VAL_CLASSGUID, &guidInfo);
  5895. if (NT_SUCCESS(status) && !guidInfo) {
  5896. status = STATUS_UNSUCCESSFUL;
  5897. }
  5898. if (NT_SUCCESS(status)) {
  5899. //
  5900. // The ClassGUID value exists. Initialize our string with this
  5901. // GUID so we can go to the corresponding key under the Class
  5902. // Branch to lookup the Class name.
  5903. //
  5904. guidAllocatedViaRtl = FALSE;
  5905. RtlInitUnicodeString(&guidString,
  5906. (PWCHAR)((PUCHAR)guidInfo + guidInfo->DataOffset)
  5907. );
  5908. }
  5909. }
  5910. }
  5911. if (NT_SUCCESS(status)) {
  5912. //
  5913. // While we are here we need to restore the class name as well.
  5914. // Start by getting the class name from the class's branch itself.
  5915. //
  5916. InitializeObjectAttributes(
  5917. &obja,
  5918. &guidString,
  5919. OBJ_CASE_INSENSITIVE,
  5920. ClassBranchKey,
  5921. NULL
  5922. );
  5923. status = ZwOpenKey(&hClassKey, KEY_ALL_ACCESS, &obja);
  5924. ASSERT(NT_SUCCESS(status));
  5925. if (NT_SUCCESS(status)) {
  5926. status = SpGetRegistryValue(hClassKey, REGSTR_VAL_CLASS, &info);
  5927. if (NT_SUCCESS(status) && !info) {
  5928. status = STATUS_UNSUCCESSFUL;
  5929. }
  5930. if (NT_SUCCESS(status)) {
  5931. //
  5932. // Copy the class name stored in the class branch to the
  5933. // instance key.
  5934. //
  5935. className = (PWCHAR)((PUCHAR)info + info->DataOffset);
  5936. RtlInitUnicodeString(&valueName, REGSTR_VAL_CLASS);
  5937. ZwSetValueKey(
  5938. InstanceKey,
  5939. &valueName,
  5940. 0,
  5941. REG_SZ,
  5942. className,
  5943. (wcslen(className)+1)*sizeof(WCHAR)
  5944. );
  5945. SpMemFree(info);
  5946. }
  5947. ZwClose(hClassKey);
  5948. }
  5949. }
  5950. //
  5951. // At this point, if status is successful, that means we migrated Class/
  5952. // ClassGUID values, so there may be more to do...
  5953. //
  5954. if (NT_SUCCESS(status)) {
  5955. //
  5956. // Do we have the XP-Beta2 style "DrvInst" key?
  5957. //
  5958. status = SpGetRegistryValue(InstanceKey, REGSTR_VALUE_DRVINST, &info);
  5959. if (NT_SUCCESS(status) && !info) {
  5960. status = STATUS_UNSUCCESSFUL;
  5961. }
  5962. if (NT_SUCCESS(status)) {
  5963. //
  5964. // Change DrvInst (REG_DWORD) to Driver (REG_SZ) from "ClassGuid\DrvInst"
  5965. //
  5966. ASSERT(guidString.Length != 0);
  5967. drvInst = *(PULONG)((PUCHAR)info + info->DataOffset);
  5968. swprintf(driver,
  5969. TEXT("%wZ\\%04u"),
  5970. &guidString,
  5971. drvInst);
  5972. SpMemFree(info);
  5973. RtlInitUnicodeString(&valueName, REGSTR_VAL_DRIVER);
  5974. ZwSetValueKey(
  5975. InstanceKey,
  5976. &valueName,
  5977. 0,
  5978. REG_SZ,
  5979. driver,
  5980. sizeof(driver)
  5981. );
  5982. //
  5983. // Delete DrvInst value
  5984. //
  5985. RtlInitUnicodeString(&valueName, REGSTR_VALUE_DRVINST);
  5986. ZwDeleteValueKey(InstanceKey, &valueName);
  5987. }
  5988. }
  5989. //
  5990. // We don't need the class guid anymore.
  5991. //
  5992. if (guidString.Buffer) {
  5993. if (guidAllocatedViaRtl) {
  5994. RtlFreeUnicodeString(&guidString);
  5995. } else {
  5996. SpMemFree(guidInfo);
  5997. }
  5998. }
  5999. //
  6000. // Do we have the XP-Beta2 "HwIDs" key?
  6001. //
  6002. status = SpGetRegistryValue(InstanceKey, REGSTR_VALUE_HWIDS, &info);
  6003. if (NT_SUCCESS(status) && !info) {
  6004. status = STATUS_UNSUCCESSFUL;
  6005. }
  6006. if (NT_SUCCESS(status)) {
  6007. //
  6008. // Change HW IDs from ANSI to UNICODE.
  6009. //
  6010. ids = SpConvertMultiSzStrToWstr(((PUCHAR)info + info->DataOffset), info->DataLength);
  6011. if (ids) {
  6012. RtlInitUnicodeString(&valueName, REGSTR_VAL_HARDWAREID);
  6013. ZwSetValueKey(
  6014. InstanceKey,
  6015. &valueName,
  6016. 0,
  6017. REG_MULTI_SZ,
  6018. ids,
  6019. info->DataLength * sizeof(WCHAR)
  6020. );
  6021. //
  6022. // Delete HwIDs value
  6023. //
  6024. RtlInitUnicodeString(&valueName, REGSTR_VALUE_HWIDS);
  6025. ZwDeleteValueKey(InstanceKey, &valueName);
  6026. SpMemFree(ids);
  6027. }
  6028. SpMemFree(info);
  6029. }
  6030. //
  6031. // Do we have the XP-Beta2 "CIDs" key?
  6032. //
  6033. status = SpGetRegistryValue(InstanceKey, REGSTR_VALUE_CIDS, &info);
  6034. if (NT_SUCCESS(status) && !info) {
  6035. status = STATUS_UNSUCCESSFUL;
  6036. }
  6037. if (NT_SUCCESS(status)) {
  6038. //
  6039. // Change Compatible IDs from ANSI to UNICODE.
  6040. //
  6041. ids = SpConvertMultiSzStrToWstr(((PUCHAR)info + info->DataOffset), info->DataLength);
  6042. if (ids) {
  6043. RtlInitUnicodeString(&valueName, REGSTR_VAL_COMPATIBLEIDS);
  6044. ZwSetValueKey(
  6045. InstanceKey,
  6046. &valueName,
  6047. 0,
  6048. REG_MULTI_SZ,
  6049. ids,
  6050. info->DataLength * sizeof(WCHAR)
  6051. );
  6052. //
  6053. // Delete CIDs value
  6054. //
  6055. RtlInitUnicodeString(&valueName, REGSTR_VALUE_CIDS);
  6056. ZwDeleteValueKey(InstanceKey, &valueName);
  6057. SpMemFree(ids);
  6058. }
  6059. SpMemFree(info);
  6060. }
  6061. }
  6062. NTSTATUS
  6063. SpUpdateDeviceInstanceData(
  6064. IN HANDLE ControlSet
  6065. )
  6066. /*++
  6067. Routine Description:
  6068. This routine enumerates all the keys under HKLM\System\CCS\Enum and call
  6069. SpUpdateDeviceInstanceKeyData for each device instance key.
  6070. Arguments:
  6071. ControlSet - Handle to the control set to update.
  6072. Return Value:
  6073. Status value indicating outcome of operation.
  6074. --*/
  6075. {
  6076. NTSTATUS status;
  6077. OBJECT_ATTRIBUTES obja;
  6078. HANDLE hEnumBranchKey, hClassBranchKey;
  6079. UNICODE_STRING enumBranch, classBranch;
  6080. HANDLE hEnumeratorKey, hDeviceKey, hInstanceKey;
  6081. UNICODE_STRING enumeratorName, deviceName, instanceName;
  6082. PKEY_BASIC_INFORMATION enumBasicInfo, deviceBasicInfo, instBasicInfo;
  6083. ULONG ulEnumerator, ulDevice, ulInstance, ulLength, ulBasicInfoSize;
  6084. //
  6085. // Preinit for error
  6086. //
  6087. hEnumBranchKey = NULL;
  6088. hClassBranchKey = NULL;
  6089. enumBasicInfo = NULL;
  6090. //
  6091. // First open the enum branch for this control set
  6092. //
  6093. RtlInitUnicodeString(&enumBranch, REGSTR_KEY_ENUM);
  6094. InitializeObjectAttributes(
  6095. &obja,
  6096. &enumBranch,
  6097. OBJ_CASE_INSENSITIVE,
  6098. ControlSet,
  6099. NULL
  6100. );
  6101. status = ZwOpenKey(&hEnumBranchKey, KEY_ALL_ACCESS, &obja);
  6102. if (!NT_SUCCESS(status)) {
  6103. ASSERT(NT_SUCCESS(status));
  6104. goto Exit;
  6105. }
  6106. //
  6107. // Now open the class key for this control set.
  6108. //
  6109. RtlInitUnicodeString(&classBranch, REGSTR_KEY_CONTROL L"\\" REGSTR_KEY_CLASS);
  6110. InitializeObjectAttributes(
  6111. &obja,
  6112. &classBranch,
  6113. OBJ_CASE_INSENSITIVE,
  6114. ControlSet,
  6115. NULL
  6116. );
  6117. status = ZwOpenKey(&hClassBranchKey, KEY_ALL_ACCESS, &obja);
  6118. if (!NT_SUCCESS(status)) {
  6119. ASSERT(NT_SUCCESS(status));
  6120. goto Exit;
  6121. }
  6122. //
  6123. // Allocate memory for enumeration
  6124. //
  6125. ulBasicInfoSize = sizeof(KEY_BASIC_INFORMATION) + REG_MAX_KEY_NAME_LENGTH;
  6126. enumBasicInfo = SpMemAlloc(ulBasicInfoSize * 3);
  6127. if (enumBasicInfo == NULL) {
  6128. status = STATUS_INSUFFICIENT_RESOURCES;
  6129. goto Exit;
  6130. }
  6131. //
  6132. // Cast two pointers for future buffer usage.
  6133. //
  6134. deviceBasicInfo = (PKEY_BASIC_INFORMATION)((PUCHAR)enumBasicInfo + ulBasicInfoSize);
  6135. instBasicInfo = (PKEY_BASIC_INFORMATION)((PUCHAR)deviceBasicInfo + ulBasicInfoSize);
  6136. //
  6137. // Walk each enumerator and then each device instance
  6138. //
  6139. status = STATUS_SUCCESS;
  6140. for (ulEnumerator = 0; ; ulEnumerator++) {
  6141. status = ZwEnumerateKey(
  6142. hEnumBranchKey,
  6143. ulEnumerator,
  6144. KeyBasicInformation,
  6145. enumBasicInfo,
  6146. ulBasicInfoSize,
  6147. &ulLength
  6148. );
  6149. if (!NT_SUCCESS(status)) {
  6150. break;
  6151. }
  6152. //
  6153. // Open the enumerator
  6154. //
  6155. enumeratorName.Length = enumeratorName.MaximumLength = (USHORT)enumBasicInfo->NameLength;
  6156. enumeratorName.Buffer = &enumBasicInfo->Name[0];
  6157. InitializeObjectAttributes(
  6158. &obja,
  6159. &enumeratorName,
  6160. OBJ_CASE_INSENSITIVE,
  6161. hEnumBranchKey,
  6162. NULL
  6163. );
  6164. status = ZwOpenKey(&hEnumeratorKey, KEY_ALL_ACCESS, &obja);
  6165. if (!NT_SUCCESS(status)) {
  6166. break;
  6167. }
  6168. //
  6169. // Walk each device
  6170. //
  6171. for (ulDevice = 0; ; ulDevice++) {
  6172. status = ZwEnumerateKey(
  6173. hEnumeratorKey,
  6174. ulDevice,
  6175. KeyBasicInformation,
  6176. deviceBasicInfo,
  6177. ulBasicInfoSize,
  6178. &ulLength
  6179. );
  6180. if (!NT_SUCCESS(status)) {
  6181. break;
  6182. }
  6183. deviceName.Length = deviceName.MaximumLength = (USHORT)deviceBasicInfo->NameLength;
  6184. deviceName.Buffer = &deviceBasicInfo->Name[0];
  6185. InitializeObjectAttributes(
  6186. &obja,
  6187. &deviceName,
  6188. OBJ_CASE_INSENSITIVE,
  6189. hEnumeratorKey,
  6190. NULL
  6191. );
  6192. status = ZwOpenKey(&hDeviceKey, KEY_ALL_ACCESS, &obja);
  6193. if (!NT_SUCCESS(status)) {
  6194. break;
  6195. }
  6196. //
  6197. // Now walk each instance
  6198. //
  6199. for (ulInstance = 0; ; ulInstance++) {
  6200. status = ZwEnumerateKey(
  6201. hDeviceKey,
  6202. ulInstance,
  6203. KeyBasicInformation,
  6204. instBasicInfo,
  6205. ulBasicInfoSize,
  6206. &ulLength
  6207. );
  6208. if (!NT_SUCCESS(status)) {
  6209. break;
  6210. }
  6211. instanceName.Length = instanceName.MaximumLength = (USHORT)instBasicInfo->NameLength;
  6212. instanceName.Buffer = &instBasicInfo->Name[0];
  6213. InitializeObjectAttributes(
  6214. &obja,
  6215. &instanceName,
  6216. OBJ_CASE_INSENSITIVE,
  6217. hDeviceKey,
  6218. NULL
  6219. );
  6220. status = ZwOpenKey(&hInstanceKey, KEY_ALL_ACCESS, &obja);
  6221. if (!NT_SUCCESS(status)) {
  6222. break;
  6223. }
  6224. SpUpdateDeviceInstanceKeyData(
  6225. hInstanceKey,
  6226. hClassBranchKey,
  6227. &enumeratorName,
  6228. &deviceName,
  6229. &instanceName
  6230. );
  6231. ZwClose(hInstanceKey);
  6232. }
  6233. ZwClose(hDeviceKey);
  6234. if (status != STATUS_NO_MORE_ENTRIES) {
  6235. break;
  6236. }
  6237. }
  6238. ZwClose(hEnumeratorKey);
  6239. if (status != STATUS_NO_MORE_ENTRIES) {
  6240. break;
  6241. }
  6242. }
  6243. //
  6244. // STATUS_NO_MORE_ENTRIES isn't a failure, it just means we've exhausted
  6245. // the number of enumerators.
  6246. //
  6247. if (status == STATUS_NO_MORE_ENTRIES) {
  6248. status = STATUS_SUCCESS;
  6249. }
  6250. Exit:
  6251. if (enumBasicInfo) {
  6252. SpMemFree(enumBasicInfo);
  6253. }
  6254. if (hEnumBranchKey) {
  6255. ZwClose(hEnumBranchKey);
  6256. }
  6257. if (hClassBranchKey) {
  6258. ZwClose(hClassBranchKey);
  6259. }
  6260. ASSERT(NT_SUCCESS(status));
  6261. return status;
  6262. }
  6263. NTSTATUS
  6264. SppDeleteRegistryValueRecursive(
  6265. HANDLE hKeyRoot,
  6266. PWSTR KeyPath, OPTIONAL
  6267. PWSTR ValueToDelete
  6268. )
  6269. /*++
  6270. Routine Description:
  6271. This routine will recursively enumerate the specified hKeyRoot and KeyPath
  6272. and delete any ValueToDelete registry values in those keys.
  6273. Arguments:
  6274. hKeyRoot: Handle to root key
  6275. KeyPath: root key relative path to the subkey which needs to be
  6276. recursively copied. if this is null hKeyRoot is the key
  6277. from which the recursive copy is to be done.
  6278. ValueToDelete name of the value that needs to be deleted.
  6279. Return Value:
  6280. Status is returned.
  6281. --*/
  6282. {
  6283. NTSTATUS Status = STATUS_SUCCESS;
  6284. OBJECT_ATTRIBUTES ObjaSrc;
  6285. UNICODE_STRING UnicodeStringSrc, UnicodeStringValue;
  6286. HANDLE hKey=NULL;
  6287. ULONG ResultLength, Index;
  6288. PWSTR SubkeyName;
  6289. PKEY_BASIC_INFORMATION KeyInfo;
  6290. //
  6291. // Get a handle to the source key
  6292. //
  6293. if(KeyPath == NULL) {
  6294. hKey = hKeyRoot;
  6295. }
  6296. else {
  6297. //
  6298. // Open the Src key
  6299. //
  6300. INIT_OBJA(&ObjaSrc,&UnicodeStringSrc,KeyPath);
  6301. ObjaSrc.RootDirectory = hKeyRoot;
  6302. Status = ZwOpenKey(&hKey,KEY_READ,&ObjaSrc);
  6303. if(!NT_SUCCESS(Status)) {
  6304. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: unable to open key %ws in the source hive (%lx)\n",KeyPath,Status));
  6305. return(Status);
  6306. }
  6307. }
  6308. //
  6309. // Enumerate all keys in the source key and recursively create
  6310. // all the subkeys
  6311. //
  6312. KeyInfo = (PKEY_BASIC_INFORMATION)TemporaryBuffer;
  6313. for( Index=0;;Index++ ) {
  6314. Status = ZwEnumerateKey(
  6315. hKey,
  6316. Index,
  6317. KeyBasicInformation,
  6318. TemporaryBuffer,
  6319. sizeof(TemporaryBuffer),
  6320. &ResultLength
  6321. );
  6322. if(!NT_SUCCESS(Status)) {
  6323. if(Status == STATUS_NO_MORE_ENTRIES) {
  6324. Status = STATUS_SUCCESS;
  6325. }
  6326. else {
  6327. if(KeyPath!=NULL) {
  6328. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: unable to enumerate subkeys in key %ws(%lx)\n",KeyPath, Status));
  6329. }
  6330. else {
  6331. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: unable to enumerate subkeys in root key(%lx)\n", Status));
  6332. }
  6333. }
  6334. break;
  6335. }
  6336. //
  6337. // Zero-terminate the subkey name just in case.
  6338. //
  6339. KeyInfo->Name[KeyInfo->NameLength/sizeof(WCHAR)] = 0;
  6340. //
  6341. // Make a duplicate of the subkey name because the name is
  6342. // in TemporaryBuffer, which might get clobbered by recursive
  6343. // calls to this routine.
  6344. //
  6345. SubkeyName = SpDupStringW(KeyInfo->Name);
  6346. if (SubkeyName) {
  6347. Status = SppDeleteRegistryValueRecursive(
  6348. hKey,
  6349. SubkeyName,
  6350. ValueToDelete
  6351. );
  6352. SpMemFree(SubkeyName);
  6353. }
  6354. }
  6355. //
  6356. // Process any errors if found
  6357. //
  6358. if(!NT_SUCCESS(Status)) {
  6359. if(KeyPath != NULL) {
  6360. ZwClose(hKey);
  6361. }
  6362. return(Status);
  6363. }
  6364. //
  6365. // Delete the ValueToDelete value in this key. We won't check the status
  6366. // since it doesn't matter if this succeeds or not.
  6367. //
  6368. RtlInitUnicodeString(&UnicodeStringValue, ValueToDelete);
  6369. ZwDeleteValueKey(hKey,&UnicodeStringValue);
  6370. //
  6371. // cleanup
  6372. //
  6373. if(KeyPath != NULL) {
  6374. ZwClose(hKey);
  6375. }
  6376. return(Status);
  6377. }
  6378. NTSTATUS
  6379. SpCleanUpHive(
  6380. VOID
  6381. )
  6382. /*++
  6383. Routine Description:
  6384. This routine will cleanup the system hive before it is migrated to the
  6385. target system hive.
  6386. Arguments:
  6387. none
  6388. Return Value:
  6389. Status value indicating outcome of operation.
  6390. --*/
  6391. {
  6392. NTSTATUS Status;
  6393. OBJECT_ATTRIBUTES Obja;
  6394. UNICODE_STRING UnicodeString;
  6395. HANDLE hKey;
  6396. INIT_OBJA(&Obja,&UnicodeString,L"\\registry\\machine\\system\\currentcontrolset");
  6397. Obja.RootDirectory = NULL;
  6398. Status = ZwOpenKey(&hKey,KEY_ALL_ACCESS,&Obja);
  6399. if( !NT_SUCCESS( Status ) ) {
  6400. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to open %ls on the setup hive (%lx)\n", L"\\registry\\machine\\system\\currentcontrolset", Status));
  6401. return( Status ) ;
  6402. }
  6403. //
  6404. // Delete the DeviceDesc values from under the enum key.
  6405. // The reason for this is that if we replace the DeviceDesc values on an
  6406. // upgrade then GUI mode setup won't be able to backup any 3rd party drivers
  6407. // that we are replaceing with our in-box drivers. This is because the
  6408. // DeviceDesc is one of three values that setupapi uses to create a
  6409. // unique driver node.
  6410. //
  6411. if (NTUpgrade == UpgradeFull) {
  6412. Status = SppDeleteRegistryValueRecursive(
  6413. hKey,
  6414. REGSTR_KEY_ENUM,
  6415. REGSTR_VAL_DEVDESC
  6416. );
  6417. if( !NT_SUCCESS( Status ) ) {
  6418. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to migrate %ls to the target hive. KeyPath, Status = %lx\n", Status));
  6419. }
  6420. }
  6421. ZwClose( hKey );
  6422. return( Status );
  6423. }
  6424. NTSTATUS
  6425. SpIterateRegistryKeyForKeys(
  6426. IN HANDLE RootKeyHandle,
  6427. IN PWSTR KeyToIterate,
  6428. IN SP_REGISTRYKEY_ITERATION_CALLBACK Callback,
  6429. IN PVOID Context
  6430. )
  6431. /*++
  6432. Routine Description:
  6433. Iterates the registry key looking for registry keys which are
  6434. immediately below the current key.
  6435. NOTE : To stop the iteration the callback function should return
  6436. FALSE.
  6437. Arguments:
  6438. RootKeyHandle - The root key which contains the key to iterate
  6439. KeyToIterate - The relative path for the key to iterate w.r.t to
  6440. root key.
  6441. Callback - The call function which will be called for each subkey
  6442. found under the requested key.
  6443. Context - Opaque context data that the caller needs and will be
  6444. passed on by the iteration routine for each invocation of
  6445. the callback function.
  6446. Return Value:
  6447. Appropriate NT status error code.
  6448. --*/
  6449. {
  6450. NTSTATUS Status = STATUS_INVALID_PARAMETER;
  6451. //
  6452. // Validate the arguments
  6453. //
  6454. if (RootKeyHandle && KeyToIterate && Callback) {
  6455. HANDLE KeyHandle = NULL;
  6456. UNICODE_STRING KeyName;
  6457. OBJECT_ATTRIBUTES ObjAttrs;
  6458. //
  6459. // Open the key which needs to be iterated
  6460. //
  6461. INIT_OBJA(&ObjAttrs, &KeyName, KeyToIterate);
  6462. ObjAttrs.RootDirectory = RootKeyHandle;
  6463. Status = ZwOpenKey(&KeyHandle,
  6464. KEY_ALL_ACCESS,
  6465. &ObjAttrs);
  6466. if (NT_SUCCESS(Status)) {
  6467. ULONG BufferLength = 4096;
  6468. PKEY_FULL_INFORMATION FullInfo = (PKEY_FULL_INFORMATION)SpMemAlloc(BufferLength);
  6469. ULONG ResultLength = 0;
  6470. if (FullInfo) {
  6471. //
  6472. // Find out how many subkeys the current key has
  6473. //
  6474. Status = ZwQueryKey(KeyHandle,
  6475. KeyFullInformation,
  6476. FullInfo,
  6477. BufferLength,
  6478. &ResultLength);
  6479. if (NT_SUCCESS(Status)) {
  6480. ULONG NumSubKeys = FullInfo->SubKeys;
  6481. ULONG Index;
  6482. BOOLEAN Done;
  6483. NTSTATUS LastError = STATUS_SUCCESS;
  6484. //
  6485. // Iterate each subkey of the current key and callback
  6486. // the subscriber function
  6487. //
  6488. for (Index = 0, Done = FALSE;
  6489. NT_SUCCESS(Status) && !Done && (Index < NumSubKeys);
  6490. Index++) {
  6491. PKEY_BASIC_INFORMATION BasicInfo = (PKEY_BASIC_INFORMATION)FullInfo;
  6492. Status = ZwEnumerateKey(KeyHandle,
  6493. Index,
  6494. KeyBasicInformation,
  6495. BasicInfo,
  6496. BufferLength,
  6497. &ResultLength);
  6498. if (NT_SUCCESS(Status)) {
  6499. NTSTATUS CallbackStatus = STATUS_SUCCESS;
  6500. SP_REGISTRYKEY_ITERATION_CALLBACK_DATA CallbackData;
  6501. CallbackData.InformationType = KeyBasicInformation;
  6502. CallbackData.Information = (PVOID)BasicInfo;
  6503. CallbackData.ParentKeyHandle = KeyHandle;
  6504. //
  6505. // Callback
  6506. //
  6507. Done = (Callback(Context, &CallbackData, &CallbackStatus) == FALSE);
  6508. //
  6509. // register any error and continue on
  6510. //
  6511. if (!NT_SUCCESS(CallbackStatus)) {
  6512. LastError = CallbackStatus;
  6513. }
  6514. } else if (Status == STATUS_NO_MORE_ENTRIES) {
  6515. //
  6516. // Done with iteration
  6517. //
  6518. Done = TRUE;
  6519. Status = STATUS_SUCCESS;
  6520. }
  6521. }
  6522. if (!NT_SUCCESS(LastError)) {
  6523. Status = LastError;
  6524. }
  6525. }
  6526. SpMemFree(FullInfo);
  6527. } else {
  6528. Status = STATUS_NO_MEMORY;
  6529. }
  6530. }
  6531. }
  6532. return Status;
  6533. }
  6534. //
  6535. // Context data structure for class filter deletion
  6536. //
  6537. typedef struct _SP_CLASS_FILTER_DELETE_CONTEXT {
  6538. PVOID Buffer;
  6539. ULONG BufferLength;
  6540. PWSTR DriverName;
  6541. } SP_CLASS_FILTER_DELETE_CONTEXT, *PSP_CLASS_FILTER_DELETE_CONTEXT;
  6542. static
  6543. BOOLEAN
  6544. SppFixUpperAndLowerFilterEntries(
  6545. IN PVOID Context,
  6546. IN PSP_REGISTRYKEY_ITERATION_CALLBACK_DATA Data,
  6547. OUT NTSTATUS *Status
  6548. )
  6549. /*++
  6550. Routine Description:
  6551. Arguments:
  6552. Context - The SP_CLASS_FILTER_DELETE_CONTEXT disguised as
  6553. a void pointer.
  6554. Data - The data the iterator passed to us, containing information
  6555. about the current subkey.
  6556. Status - Place holder for receiving the error status code which
  6557. this function returns.
  6558. Return Value:
  6559. TRUE if the iteration needs to be continued otherwise FALSE.
  6560. --*/
  6561. {
  6562. BOOLEAN Result = FALSE;
  6563. *Status = STATUS_INVALID_PARAMETER;
  6564. if (Context && Data && (Data->InformationType == KeyBasicInformation)) {
  6565. NTSTATUS UpperStatus, LowerStatus;
  6566. PKEY_BASIC_INFORMATION BasicInfo = (PKEY_BASIC_INFORMATION)(Data->Information);
  6567. PSP_CLASS_FILTER_DELETE_CONTEXT DelContext = (PSP_CLASS_FILTER_DELETE_CONTEXT)Context;
  6568. PWSTR KeyName = (PWSTR)(DelContext->Buffer);
  6569. if (KeyName && (BasicInfo->NameLength < DelContext->BufferLength)) {
  6570. wcsncpy(KeyName, BasicInfo->Name, BasicInfo->NameLength/sizeof(WCHAR));
  6571. KeyName[BasicInfo->NameLength/sizeof(WCHAR)] = UNICODE_NULL;
  6572. //
  6573. // Delete the string from upperfilters
  6574. //
  6575. UpperStatus = SpRemoveStringFromMultiSz(Data->ParentKeyHandle,
  6576. KeyName,
  6577. SP_UPPER_FILTERS,
  6578. DelContext->DriverName);
  6579. //
  6580. // Delete the string from lowerfilters
  6581. //
  6582. LowerStatus = SpRemoveStringFromMultiSz(Data->ParentKeyHandle,
  6583. KeyName,
  6584. SP_LOWER_FILTERS,
  6585. DelContext->DriverName);
  6586. if (NT_SUCCESS(UpperStatus) || NT_SUCCESS(LowerStatus)) {
  6587. *Status = STATUS_SUCCESS;
  6588. } else if (((UpperStatus == STATUS_OBJECT_NAME_NOT_FOUND) ||
  6589. (UpperStatus == STATUS_OBJECT_NAME_INVALID)) &&
  6590. ((LowerStatus == STATUS_OBJECT_NAME_NOT_FOUND) ||
  6591. (LowerStatus == STATUS_OBJECT_NAME_INVALID))) {
  6592. //
  6593. // If the value was not found then continue on
  6594. //
  6595. *Status = STATUS_SUCCESS;
  6596. }
  6597. //
  6598. // we want to continue iterating irrespective of the results
  6599. //
  6600. Result = TRUE;
  6601. }
  6602. }
  6603. return Result;
  6604. }
  6605. NTSTATUS
  6606. SpProcessServicesToDisable(
  6607. IN PVOID WinntSifHandle,
  6608. IN PWSTR SectionName,
  6609. IN HANDLE CurrentControlSetKey
  6610. )
  6611. /*++
  6612. Routine Description:
  6613. Processess the winnt.sif's [ServiceToDisable] section to
  6614. remove the service entries from upper and lower filters.
  6615. Arguments:
  6616. WinntSifHandle - Handle to winnt.sif file.
  6617. SectionName - The name of section in winnt.sif which contains
  6618. a list of service name which need to be removed from
  6619. the filter list.
  6620. CurrentControlKey - The handle to CurrentControlSet root key.
  6621. Return Value:
  6622. Appropriate NTSTATUS error code.
  6623. --*/
  6624. {
  6625. NTSTATUS Status = STATUS_INVALID_PARAMETER;
  6626. //
  6627. // Validate arguments
  6628. //
  6629. if (WinntSifHandle && SectionName && CurrentControlSetKey) {
  6630. ULONG EntriesToProcess = SpCountLinesInSection(WinntSifHandle,
  6631. SP_SERVICES_TO_DISABLE);
  6632. //
  6633. // If there are any entries to process -- then process them
  6634. //
  6635. if (EntriesToProcess) {
  6636. ULONG BufferLength = 16 * 1024;
  6637. PVOID Buffer = SpMemAlloc(BufferLength);
  6638. if (Buffer) {
  6639. ULONG Index;
  6640. PWSTR CurrentEntry;
  6641. SP_CLASS_FILTER_DELETE_CONTEXT DeleteContext = {0};
  6642. NTSTATUS LastErrorStatus = STATUS_SUCCESS;
  6643. //
  6644. // Process each entry
  6645. //
  6646. DeleteContext.Buffer = Buffer;
  6647. DeleteContext.BufferLength = BufferLength;
  6648. for(Index = 0; Index < EntriesToProcess; Index++) {
  6649. CurrentEntry = SpGetSectionLineIndex(WinntSifHandle,
  6650. SP_SERVICES_TO_DISABLE,
  6651. Index,
  6652. 0);
  6653. if (CurrentEntry) {
  6654. DeleteContext.DriverName = CurrentEntry;
  6655. Status = SpIterateRegistryKeyForKeys(CurrentControlSetKey,
  6656. L"Class",
  6657. SppFixUpperAndLowerFilterEntries,
  6658. &DeleteContext);
  6659. //
  6660. // save away the error code and continue on
  6661. //
  6662. if (!NT_SUCCESS(Status)) {
  6663. LastErrorStatus = Status;
  6664. }
  6665. }
  6666. }
  6667. //
  6668. // Even one of the entries failed to delete correctly
  6669. // then flag it as a failure
  6670. //
  6671. if (!NT_SUCCESS(LastErrorStatus)) {
  6672. Status = LastErrorStatus;
  6673. }
  6674. SpMemFree(Buffer);
  6675. }
  6676. } else {
  6677. Status = STATUS_SUCCESS; // nothing to process
  6678. }
  6679. }
  6680. return Status;
  6681. }
  6682. //
  6683. // Context data structure for device instance filter deletion
  6684. //
  6685. typedef struct _SP_DEVINSTANCE_FILTER_DELETE_CONTEXT {
  6686. PVOID Buffer;
  6687. ULONG BufferLength;
  6688. PUNICODE_STRING *ClassGuids;
  6689. } SP_DEVINSTANCE_FILTER_DELETE_CONTEXT, *PSP_DEVINSTANCE_FILTER_DELETE_CONTEXT;
  6690. static
  6691. VOID
  6692. SppRemoveFilterDriversForClassDeviceInstances(
  6693. IN HANDLE SetupInstanceKeyHandle,
  6694. IN HANDLE UpgradeInstanceKeyHandle,
  6695. IN BOOLEAN RootEnumerated,
  6696. IN PVOID Context
  6697. )
  6698. /*++
  6699. Routine Description:
  6700. Callback which removes the filter drivers for the
  6701. specified device instance
  6702. Arguments:
  6703. SetupInstanceKeyHandle - Handle to device instance key in setupreg.hiv.
  6704. UpgradeInstanceKeyHandle - Handle to device instance key in the
  6705. system hive of the installation being upgraded.
  6706. RootEnumerated - Whether this is root enumerated key or not.
  6707. Context - SP_DEVINSTANCE_FILTER_DELETE_CONTEXT instance disguised
  6708. as PVOID context.
  6709. Return Value:
  6710. None.
  6711. --*/
  6712. {
  6713. //
  6714. // Validate arguments
  6715. //
  6716. if (Context && SetupInstanceKeyHandle) {
  6717. PSP_DEVINSTANCE_FILTER_DELETE_CONTEXT DelContext;
  6718. //
  6719. // get device instance filter deletion context
  6720. //
  6721. DelContext = (PSP_DEVINSTANCE_FILTER_DELETE_CONTEXT)Context;
  6722. //
  6723. // Validate the context
  6724. //
  6725. if (DelContext->Buffer && DelContext->BufferLength &&
  6726. DelContext->ClassGuids && DelContext->ClassGuids[0]) {
  6727. PKEY_VALUE_FULL_INFORMATION ValueInfo;
  6728. UNICODE_STRING GuidValueName;
  6729. ULONG BufferLength;
  6730. NTSTATUS Status;
  6731. BOOLEAN DeleteFilterValueKeys = FALSE;
  6732. //
  6733. // reuse the buffer allocated by the iterator caller
  6734. //
  6735. ValueInfo = (PKEY_VALUE_FULL_INFORMATION)(DelContext->Buffer);
  6736. RtlInitUnicodeString(&GuidValueName, SP_CLASS_GUID_VALUE_NAME);
  6737. //
  6738. // Get the class GUID for the current device instance
  6739. //
  6740. Status = ZwQueryValueKey(SetupInstanceKeyHandle,
  6741. &GuidValueName,
  6742. KeyValueFullInformation,
  6743. ValueInfo,
  6744. DelContext->BufferLength - sizeof(WCHAR),
  6745. &BufferLength);
  6746. if (NT_SUCCESS(Status)) {
  6747. PWSTR CurrentGuid = (PWSTR)(((PUCHAR)ValueInfo + ValueInfo->DataOffset));
  6748. ULONG Index;
  6749. //
  6750. // null terminate the string (NOTE:we assume buffer has space)
  6751. //
  6752. CurrentGuid[ValueInfo->DataLength/sizeof(WCHAR)] = UNICODE_NULL;
  6753. //
  6754. // Is this the one of the class device instance we are looking for?
  6755. //
  6756. for (Index = 0; DelContext->ClassGuids[Index]; Index++) {
  6757. if (!_wcsicmp(CurrentGuid, DelContext->ClassGuids[Index]->Buffer)) {
  6758. DeleteFilterValueKeys = TRUE;
  6759. break;
  6760. }
  6761. }
  6762. }
  6763. //
  6764. // Delete the upper and lower filter value keys
  6765. //
  6766. if (DeleteFilterValueKeys) {
  6767. UNICODE_STRING UpperValueName, LowerValueName;
  6768. RtlInitUnicodeString(&UpperValueName, SP_UPPER_FILTERS);
  6769. RtlInitUnicodeString(&LowerValueName, SP_LOWER_FILTERS);
  6770. if (SetupInstanceKeyHandle) {
  6771. ZwDeleteValueKey(SetupInstanceKeyHandle, &UpperValueName);
  6772. ZwDeleteValueKey(SetupInstanceKeyHandle, &LowerValueName);
  6773. }
  6774. if (UpgradeInstanceKeyHandle) {
  6775. ZwDeleteValueKey(UpgradeInstanceKeyHandle, &UpperValueName);
  6776. ZwDeleteValueKey(UpgradeInstanceKeyHandle, &LowerValueName);
  6777. }
  6778. }
  6779. }
  6780. }
  6781. }
  6782. NTSTATUS
  6783. SpDeleteRequiredDeviceInstanceFilters(
  6784. IN HANDLE CCSKeyHandle
  6785. )
  6786. /*++
  6787. Routine Description:
  6788. Deletes filter entries from keyboard and mouse class device
  6789. instances in registry.
  6790. Arguments:
  6791. CCSHandle - Handle to CCS key.
  6792. Return Value:
  6793. Appropriate NT status code.
  6794. --*/
  6795. {
  6796. NTSTATUS Status = STATUS_INVALID_PARAMETER;
  6797. if (CCSKeyHandle) {
  6798. UNICODE_STRING MouseGuidStr = {0};
  6799. UNICODE_STRING KeyboardGuidStr = {0};
  6800. PUNICODE_STRING ClassGuids[16] = {0};
  6801. ULONG CurrentIndex = 0;
  6802. NTSTATUS LastErrorCode = STATUS_SUCCESS;
  6803. //
  6804. // Get hold of keyboard class GUID string
  6805. //
  6806. Status = RtlStringFromGUID(&GUID_DEVCLASS_KEYBOARD, &KeyboardGuidStr);
  6807. if (NT_SUCCESS(Status)) {
  6808. ClassGuids[CurrentIndex++] = &KeyboardGuidStr;
  6809. } else {
  6810. LastErrorCode = Status;
  6811. }
  6812. //
  6813. // Get hold of mouse class GUID string
  6814. //
  6815. Status = RtlStringFromGUID(&GUID_DEVCLASS_MOUSE, &MouseGuidStr);
  6816. if (NT_SUCCESS(Status)) {
  6817. ClassGuids[CurrentIndex++] = &MouseGuidStr;
  6818. } else {
  6819. LastErrorCode = Status;
  6820. }
  6821. //
  6822. // If we could form atleast one class guid string
  6823. //
  6824. if (CurrentIndex) {
  6825. SP_DEVINSTANCE_FILTER_DELETE_CONTEXT DelContext = {0};
  6826. ULONG BufferLength = 4096;
  6827. PVOID Buffer = SpMemAlloc(BufferLength);
  6828. if (Buffer) {
  6829. //
  6830. // null terminate the class GUID unicode string array
  6831. //
  6832. ClassGuids[CurrentIndex] = NULL;
  6833. DelContext.Buffer = Buffer;
  6834. DelContext.BufferLength = BufferLength;
  6835. DelContext.ClassGuids = ClassGuids;
  6836. //
  6837. // Iterate through all the device instances
  6838. //
  6839. SpApplyFunctionToDeviceInstanceKeys(CCSKeyHandle,
  6840. SppRemoveFilterDriversForClassDeviceInstances,
  6841. &DelContext);
  6842. SpMemFree(Buffer);
  6843. } else {
  6844. LastErrorCode = STATUS_NO_MEMORY;
  6845. }
  6846. //
  6847. // free the allocated strings
  6848. //
  6849. if (MouseGuidStr.Buffer) {
  6850. RtlFreeUnicodeString(&MouseGuidStr);
  6851. }
  6852. if (KeyboardGuidStr.Buffer) {
  6853. RtlFreeUnicodeString(&KeyboardGuidStr);
  6854. }
  6855. }
  6856. Status = LastErrorCode;
  6857. }
  6858. return Status;
  6859. }