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.

3134 lines
93 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. bootini.c
  5. Abstract:
  6. Code to lay boot blocks on x86, and to configure for boot loader,
  7. including munging/creating boot.ini and bootsect.dos.
  8. Author:
  9. Ted Miller (tedm) 12-November-1992
  10. Revision History:
  11. Sunil Pai ( sunilp ) 2-November-1993 rewrote for new text setup
  12. --*/
  13. #include "spprecmp.h"
  14. #pragma hdrstop
  15. #include "spboot.h"
  16. #include "bootvar.h"
  17. #include "spfile.h" //NEC98
  18. #include <hdlsblk.h>
  19. #include <hdlsterm.h>
  20. extern PDISK_REGION TargetRegion_Nec98; //NEC98
  21. SIGNATURED_PARTITIONS SignedBootVars;
  22. BOOLEAN
  23. SpHasMZHeader(
  24. IN PWSTR FileName
  25. );
  26. NTSTATUS
  27. Spx86WriteBootIni(
  28. IN PWCHAR BootIni,
  29. IN PWSTR **BootVars,
  30. IN ULONG Timeout,
  31. IN PWSTR Default,
  32. IN ULONG Count
  33. );
  34. //
  35. // DefSwitches support
  36. //
  37. UCHAR DefSwitches[128];
  38. UCHAR DefSwitchesNoRedirect[128];
  39. //
  40. // Routines
  41. //
  42. BOOLEAN
  43. Spx86InitBootVars(
  44. OUT PWSTR **BootVars,
  45. OUT PWSTR *Default,
  46. OUT PULONG Timeout
  47. )
  48. {
  49. WCHAR BootIni[512];
  50. HANDLE FileHandle;
  51. HANDLE SectionHandle;
  52. PVOID ViewBase;
  53. NTSTATUS Status;
  54. ULONG FileSize;
  55. PUCHAR BootIniBuf;
  56. PDISK_REGION CColonRegion;
  57. BOOTVAR i;
  58. PUCHAR p;
  59. ULONG index;
  60. //
  61. // Initialize the defaults
  62. //
  63. for(i = FIRSTBOOTVAR; i <= LASTBOOTVAR; i++) {
  64. BootVars[i] = (PWSTR *)SpMemAlloc( sizeof ( PWSTR * ) );
  65. ASSERT( BootVars[i] );
  66. *BootVars[i] = NULL;
  67. }
  68. *Default = NULL;
  69. *Timeout = DEFAULT_TIMEOUT;
  70. //
  71. // See if there is a valid C: already. If not, then silently fail.
  72. //
  73. if (!IsNEC_98 // NEC98
  74. #if defined(REMOTE_BOOT)
  75. || RemoteBootSetup
  76. #endif // defined(REMOTE_BOOT)
  77. ) {
  78. #if defined(REMOTE_BOOT)
  79. if (RemoteBootSetup && !RemoteInstallSetup) {
  80. ASSERT(RemoteBootTargetRegion != NULL);
  81. CColonRegion = RemoteBootTargetRegion;
  82. } else
  83. #endif // defined(REMOTE_BOOT)
  84. {
  85. CColonRegion = SpPtValidSystemPartition();
  86. if(!CColonRegion) {
  87. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: no C:, no boot.ini!\n"));
  88. return(TRUE);
  89. }
  90. }
  91. //
  92. // Form name of file. Boot.ini better not be on a doublespace drive.
  93. //
  94. ASSERT(CColonRegion->Filesystem != FilesystemDoubleSpace);
  95. SpNtNameFromRegion(CColonRegion,BootIni,sizeof(BootIni),PartitionOrdinalCurrent);
  96. SpConcatenatePaths(BootIni,WBOOT_INI);
  97. //
  98. // Open and map the file.
  99. //
  100. FileHandle = 0;
  101. Status = SpOpenAndMapFile(BootIni,&FileHandle,&SectionHandle,&ViewBase,&FileSize,FALSE);
  102. if(!NT_SUCCESS(Status)) {
  103. return TRUE;
  104. }
  105. //
  106. // Allocate a buffer for the file.
  107. //
  108. BootIniBuf = SpMemAlloc(FileSize+1);
  109. ASSERT(BootIniBuf);
  110. RtlZeroMemory(BootIniBuf, FileSize+1);
  111. //
  112. // Transfer boot.ini into the buffer. We do this because we also
  113. // want to place a 0 byte at the end of the buffer to terminate
  114. // the file.
  115. //
  116. // Guard the RtlMoveMemory because if we touch the memory backed by boot.ini
  117. // and get an i/o error, the memory manager will raise an exception.
  118. try {
  119. RtlMoveMemory(BootIniBuf,ViewBase,FileSize);
  120. }
  121. except( IN_PAGE_ERROR ) {
  122. //
  123. // Do nothing, boot ini processing can proceed with whatever has been
  124. // read
  125. //
  126. }
  127. //
  128. // Not needed since buffer has already been zeroed, however just do this
  129. // just the same
  130. //
  131. BootIniBuf[FileSize] = 0;
  132. //
  133. // Cleanup
  134. //
  135. SpUnmapFile(SectionHandle,ViewBase);
  136. ZwClose(FileHandle);
  137. } else { //NEC98
  138. //
  139. // Serch for all drive which include boot.ini file.
  140. //
  141. FileSize = 0;
  142. BootIniBuf = SpCreateBootiniImage(&FileSize);
  143. if(BootIniBuf == NULL){
  144. return(TRUE);
  145. }
  146. } //NEC98
  147. //
  148. // Do the actual processing of the file.
  149. //
  150. SppProcessBootIni(BootIniBuf, BootVars, Default, Timeout);
  151. //
  152. // Dump the boot vars
  153. //
  154. KdPrintEx( (DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "Spx86InitBootVars - Boot.ini entries:\n") );
  155. for( index = 0; BootVars[OSLOADPARTITION][index] ; index++ ) {
  156. KdPrintEx( (DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, " BootVar: %d\n =========\n", index) );
  157. KdPrintEx( (DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, " OsLoadpartition: %ws\n", BootVars[OSLOADPARTITION][index]) );
  158. KdPrintEx( (DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, " OsLoadFileName: %ws\n\n", BootVars[OSLOADFILENAME][index]) );
  159. }
  160. //
  161. // Dump the signatures too...
  162. //
  163. KdPrintEx( (DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "Spx86InitBootVars - Boot.ini signed entries:\n") );
  164. {
  165. SIGNATURED_PARTITIONS *my_ptr = &SignedBootVars;
  166. do{
  167. if( my_ptr->SignedString ) {
  168. KdPrintEx( (DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "Signature entry:\n================\n") );
  169. KdPrintEx( (DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, " %ws\n", my_ptr->SignedString) );
  170. KdPrintEx( (DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, " %ws\n", my_ptr->MultiString) );
  171. };
  172. my_ptr = my_ptr->Next;
  173. } while( my_ptr );
  174. }
  175. //
  176. // Scan the Buffer to see if there is a DefSwitches line,
  177. // to move into new boot.ini in the [boot loader] section.
  178. // If no DefSwitches, just point to a null string to be moved.
  179. //
  180. DefSwitches[0] = '\0';
  181. for(p=BootIniBuf; *p && (p < BootIniBuf+FileSize-(sizeof("DefSwitches")-1)); p++) {
  182. if(!_strnicmp(p,"DefSwitches",sizeof("DefSwitches")-1)) {
  183. index = 0;
  184. while ((*p != '\r') && (*p != '\n') && *p && (index < sizeof(DefSwitches)-4)) {
  185. DefSwitches[index++] = *p++;
  186. }
  187. DefSwitches[index++] = '\r';
  188. DefSwitches[index++] = '\n';
  189. DefSwitches[index] = '\0';
  190. break;
  191. }
  192. }
  193. //
  194. // get a copy of the defswitches without any redirection switches
  195. //
  196. strcpy(DefSwitchesNoRedirect, DefSwitches);
  197. //
  198. // Now add any headless parameters to the default switches.
  199. // Scan the Buffer to see if there's already a headless line.
  200. // If so, keep it.
  201. //
  202. for(p=BootIniBuf; *p && (p < BootIniBuf+FileSize-(sizeof("redirect=")-1)); p++) {
  203. if(!_strnicmp(p,"[Operat",sizeof("[Operat")-1)) {
  204. //
  205. // We're past the [Boot Loader] section. Stop looking.
  206. //
  207. break;
  208. }
  209. if(!_strnicmp(p,"redirect=",sizeof("redirect=")-1)) {
  210. PUCHAR q = p;
  211. UCHAR temp;
  212. while ((*p != '\r') && (*p != '\n') && *p) {
  213. p++;
  214. }
  215. temp = *p;
  216. *p = '\0';
  217. strcat(DefSwitches, q);
  218. strcat(DefSwitches, "\r\n");
  219. *p = temp;
  220. }
  221. }
  222. //
  223. // Now look for a 'redirectbaudrate' line.
  224. //
  225. for(p=BootIniBuf; *p && (p < BootIniBuf+FileSize-(sizeof("redirectbaudrate=")-1)); p++) {
  226. if(!_strnicmp(p,"[Operat",sizeof("[Operat")-1)) {
  227. //
  228. // We're past the [Boot Loader] section. Stop looking.
  229. //
  230. break;
  231. }
  232. if(!_strnicmp(p,"redirectbaudrate=",sizeof("redirectbaudrate=")-1)) {
  233. PUCHAR q = p;
  234. UCHAR temp;
  235. while ((*p != '\r') && (*p != '\n') && *p) {
  236. p++;
  237. }
  238. temp = *p;
  239. *p = '\0';
  240. strcat(DefSwitches, q);
  241. strcat(DefSwitches, "\r\n");
  242. *p = temp;
  243. }
  244. }
  245. SpMemFree(BootIniBuf);
  246. return( TRUE );
  247. }
  248. BOOLEAN
  249. Spx86FlushBootVars(
  250. IN PWSTR **BootVars,
  251. IN ULONG Timeout,
  252. IN PWSTR Default
  253. )
  254. {
  255. PDISK_REGION CColonRegion;
  256. WCHAR *BootIni;
  257. WCHAR *BootIniBak;
  258. BOOLEAN BootIniBackedUp = FALSE;
  259. NTSTATUS Status;
  260. //
  261. // See if there is a valid C: already. If not, then fail.
  262. //
  263. #if defined(REMOTE_BOOT)
  264. // On a remote boot machine, it's acceptable to have no local disk.
  265. //
  266. #endif // defined(REMOTE_BOOT)
  267. if (!IsNEC_98){ //NEC98
  268. CColonRegion = SpPtValidSystemPartition();
  269. if(!CColonRegion) {
  270. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: no C:, no boot.ini!\n"));
  271. #if defined(REMOTE_BOOT)
  272. if (RemoteBootSetup && !RemoteInstallSetup) {
  273. return(TRUE);
  274. }
  275. #endif // defined(REMOTE_BOOT)
  276. return(FALSE);
  277. }
  278. } else {
  279. //
  280. // CColonRegion equal TargetRegion on NEC98.
  281. //
  282. CColonRegion = TargetRegion_Nec98;
  283. } //NEC98
  284. //
  285. // Allocate the buffers to 2K worth of stack space.
  286. //
  287. BootIni = SpMemAlloc(512*sizeof(WCHAR));
  288. if (!BootIni) {
  289. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: No memory for boot.ini!\n"));
  290. return FALSE;
  291. }
  292. BootIniBak = SpMemAlloc(512*sizeof(WCHAR));
  293. if (!BootIniBak) {
  294. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: No memory for boot.ini.bak!\n"));
  295. SpMemFree(BootIni);
  296. return FALSE;
  297. }
  298. //
  299. // Form name of file. Boot.ini better not be on a doublespace drive.
  300. //
  301. ASSERT(CColonRegion->Filesystem != FilesystemDoubleSpace);
  302. SpNtNameFromRegion(CColonRegion,BootIni,512*sizeof(WCHAR),PartitionOrdinalCurrent);
  303. wcscpy(BootIniBak, BootIni);
  304. SpConcatenatePaths(BootIni,WBOOT_INI);
  305. SpConcatenatePaths(BootIniBak,WBOOT_INI_BAK);
  306. //
  307. // If Boot.ini already exists, delete any backup bootini
  308. // rename the existing bootini to the backup bootini, if unable
  309. // to rename, delete the file
  310. //
  311. if( SpFileExists( BootIni, FALSE ) ) {
  312. if( SpFileExists( BootIniBak, FALSE ) ) {
  313. SpDeleteFile( BootIniBak, NULL, NULL);
  314. }
  315. Status = SpRenameFile( BootIni, BootIniBak, FALSE );
  316. if (!(BootIniBackedUp = NT_SUCCESS( Status ))) {
  317. SpDeleteFile( BootIni, NULL, NULL );
  318. }
  319. }
  320. //
  321. // Write boot.ini.
  322. //
  323. Status = Spx86WriteBootIni(
  324. BootIni,
  325. BootVars,
  326. Timeout,
  327. Default,
  328. 0 // write all lines
  329. );
  330. if(!NT_SUCCESS( Status )) {
  331. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Error writing boot.ini!\n"));
  332. goto cleanup;
  333. }
  334. cleanup:
  335. //
  336. // If we were unsuccessful in writing out boot ini then try recovering
  337. // the old boot ini from the backed up file, else delete the backed up
  338. // file.
  339. //
  340. if( !NT_SUCCESS(Status) ) {
  341. //
  342. // If the backup copy of boot ini exists then delete incomplete boot
  343. // ini and rename the backup copy of boot into bootini
  344. //
  345. if ( BootIniBackedUp ) {
  346. SpDeleteFile( BootIni, NULL, NULL );
  347. SpRenameFile( BootIniBak, BootIni, FALSE );
  348. }
  349. }
  350. else {
  351. SpDeleteFile( BootIniBak, NULL, NULL );
  352. }
  353. SpMemFree(BootIni);
  354. SpMemFree(BootIniBak);
  355. return( NT_SUCCESS(Status) );
  356. }
  357. PCHAR
  358. Spx86ConvertToSignatureArcName(
  359. IN PWSTR ArcPathIn,
  360. IN ULONG Signature
  361. )
  362. {
  363. PWSTR s,p,b;
  364. PWSTR UseSignatures;
  365. SIGNATURED_PARTITIONS *SignedEntries = &SignedBootVars;
  366. KdPrintEx( (DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "Spx86ConvertToSignatureArcName - Incoming ArcPath: %ws\n\tIncoming Signature %lx\n", ArcPathIn, Signature ) );
  367. //
  368. // First, check for any boot.ini entries that already had a 'signature'
  369. // string.
  370. //
  371. do {
  372. if( (SignedEntries->MultiString) && (SignedEntries->SignedString) ) {
  373. if( !_wcsicmp( ArcPathIn, SignedEntries->MultiString ) ) {
  374. //
  375. // We hit. Convert the signatured string
  376. // to ASCII and return.
  377. //
  378. KdPrintEx( (DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "Spx86ConvertToSignatureArcName - Matched a multi-signed boot.ini entry:\n") );
  379. KdPrintEx( (DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "\t%ws\n\t%ws\n", SignedEntries->MultiString, SignedEntries->SignedString) );
  380. return SpToOem( SignedEntries->SignedString );
  381. }
  382. }
  383. SignedEntries = SignedEntries->Next;
  384. } while( SignedEntries );
  385. #if 0
  386. //
  387. // Don't do this because winnt.exe and CDROM-boot installs won't
  388. // have this entry set, so we won't use signature entries, which
  389. // is a mistake.
  390. //
  391. UseSignatures = SpGetSectionKeyIndex(WinntSifHandle,SIF_DATA,L"UseSignatures",0);
  392. if (UseSignatures == NULL || _wcsicmp(UseSignatures,WINNT_A_YES_W) != 0) {
  393. //
  394. // Just return the string we came in with.
  395. //
  396. return SpToOem(ArcPathIn);
  397. }
  398. #endif
  399. if (_wcsnicmp( ArcPathIn, L"scsi(", 5 ) != 0) {
  400. //
  401. // If he's anything but a "scsi(..." entry,
  402. // just return the string that was sent in.
  403. //
  404. return SpToOem(ArcPathIn);
  405. }
  406. if( Signature ) {
  407. b = (PWSTR)TemporaryBuffer;
  408. p = ArcPathIn;
  409. s = wcschr( p, L')' ) + 1;
  410. swprintf( b, L"signature(%x)%ws", Signature, s );
  411. return SpToOem( b );
  412. } else {
  413. //
  414. // Just return the string we came in with.
  415. //
  416. return SpToOem(ArcPathIn);
  417. }
  418. }
  419. NTSTATUS
  420. Spx86WriteBootIni(
  421. IN PWCHAR BootIni,
  422. IN PWSTR **BootVars,
  423. IN ULONG Timeout,
  424. IN PWSTR Default,
  425. IN ULONG Count
  426. )
  427. {
  428. IO_STATUS_BLOCK IoStatusBlock;
  429. UNICODE_STRING BootIni_U;
  430. HANDLE fh = NULL;
  431. PCHAR Default_O, Osloadpartition_O, Osloadfilename_O, Osloadoptions_O, Loadidentifier_O;
  432. FILE_BASIC_INFORMATION BasicInfo;
  433. OBJECT_ATTRIBUTES oa;
  434. ULONG i;
  435. NTSTATUS Status1;
  436. NTSTATUS Status;
  437. PWSTR s;
  438. PDISK_REGION Region;
  439. WCHAR _Default[MAX_PATH] = {0};
  440. extern ULONG DefaultSignature;
  441. //
  442. // Open Bootini file. Open if write through because we'll be shutting down
  443. // shortly (this is for safety).
  444. //
  445. RtlInitUnicodeString(&BootIni_U,BootIni);
  446. InitializeObjectAttributes(&oa,&BootIni_U,OBJ_CASE_INSENSITIVE,NULL,NULL);
  447. Status = ZwCreateFile(
  448. &fh,
  449. FILE_GENERIC_WRITE | DELETE,
  450. &oa,
  451. &IoStatusBlock,
  452. NULL,
  453. FILE_ATTRIBUTE_NORMAL,
  454. 0, // no sharing
  455. FILE_OVERWRITE_IF,
  456. FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_WRITE_THROUGH,
  457. NULL,
  458. 0
  459. );
  460. if( !NT_SUCCESS( Status ) ) {
  461. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to open %ws for writing!\n", BootIni));
  462. goto cleanup;
  463. }
  464. //
  465. // make sure there is a Default specified before we use it.
  466. //
  467. if (Default != NULL) {
  468. //
  469. // use the temporary buffer to form the FLEXBOOT section.
  470. // and then write it out
  471. //
  472. s = NULL;
  473. s = wcschr( Default, L'\\' );
  474. if( s ) {
  475. //
  476. // Save off the Default string, then terminate
  477. // the Default string where the directory path starts.
  478. //
  479. wcscpy( _Default, Default );
  480. *s = L'\0';
  481. s = wcschr( _Default, L'\\' );
  482. }
  483. if( ForceBIOSBoot ) {
  484. //
  485. // If ForceBIOSBoot is TRUE, then we want to
  486. // force a "multi(..." string. Don't even bother calling
  487. // Spx86ConvertToSignatureArcName on the off chance
  488. // that we may get erroneously converted.
  489. //
  490. if (_wcsnicmp( Default, L"scsi(", 5 ) == 0) {
  491. PWSTR MyStringPointer = NULL;
  492. //
  493. // Darn! We have a string that the old standard
  494. // thought should be converted into a signature(...
  495. // string, but we didn't write out a miniport driver.
  496. // That can happen if someone asked us not to via
  497. // an unattend switch.
  498. //
  499. // We need to change the "scsi(" to "multi("
  500. //
  501. // We must preserve Default because we use it later
  502. // for comparison.
  503. //
  504. MyStringPointer = SpScsiArcToMultiArc( Default );
  505. if( MyStringPointer ) {
  506. Default_O = SpToOem( MyStringPointer );
  507. } else {
  508. //
  509. // We're in trouble. Take a shot though. Just
  510. // change the "scsi(" part to "multi(".
  511. //
  512. wcscpy( TemporaryBuffer, L"multi" );
  513. wcscat( TemporaryBuffer, &Default[4] );
  514. Default_O = SpToOem( TemporaryBuffer );
  515. }
  516. } else {
  517. //
  518. // Just convert to ANSI.
  519. //
  520. Default_O = SpToOem( Default );
  521. }
  522. } else {
  523. Default_O = Spx86ConvertToSignatureArcName( Default, DefaultSignature );
  524. }
  525. if( s ) {
  526. //
  527. // We need to append our directory path back on.
  528. //
  529. strcpy( (PCHAR)TemporaryBuffer, Default_O );
  530. SpMemFree( Default_O );
  531. Default_O = SpToOem( s );
  532. strcat( (PCHAR)TemporaryBuffer, Default_O );
  533. SpMemFree( Default_O );
  534. Default_O = SpDupString( (PCHAR)TemporaryBuffer );
  535. }
  536. if (Default_O == NULL) {
  537. Default_O = SpToOem( Default );
  538. }
  539. } else {
  540. //
  541. // the Default was not set, so make a null Default_O
  542. //
  543. Default_O = SpDupString("");
  544. }
  545. ASSERT( Default_O );
  546. //
  547. // See if we should use the loaded redirect switches,
  548. // if there were any, or insert user defined swithes
  549. //
  550. if(RedirectSwitchesMode != UseDefaultSwitches) {
  551. //
  552. // get a copy of the switches up to the [operat region
  553. //
  554. strcpy(DefSwitches, DefSwitchesNoRedirect);
  555. //
  556. // insert our custom switch(s) if appropriate
  557. //
  558. switch(RedirectSwitchesMode){
  559. case DisableRedirect: {
  560. //
  561. // we don't have to do anything here
  562. //
  563. break;
  564. }
  565. case UseUserDefinedRedirect: {
  566. sprintf((PUCHAR)TemporaryBuffer,
  567. "redirect=%s\r\n",
  568. RedirectSwitches.port
  569. );
  570. (void)StringCchCatA(DefSwitches,
  571. sizeof(DefSwitches)/sizeof(DefSwitches[0]),
  572. (PUCHAR)TemporaryBuffer);
  573. break;
  574. }
  575. case UseUserDefinedRedirectAndBaudRate: {
  576. sprintf((PUCHAR)TemporaryBuffer,
  577. "redirect=%s\r\n",
  578. RedirectSwitches.port
  579. );
  580. (void)StringCchCatA(DefSwitches,
  581. sizeof(DefSwitches)/sizeof(DefSwitches[0]),
  582. (PUCHAR)TemporaryBuffer);
  583. sprintf((PUCHAR)TemporaryBuffer,
  584. "redirectbaudrate=%s\r\n",
  585. RedirectSwitches.baudrate
  586. );
  587. (void)StringCchCatA(DefSwitches,
  588. sizeof(DefSwitches)/sizeof(DefSwitches[0]),
  589. (PUCHAR)TemporaryBuffer);
  590. break;
  591. }
  592. default:{
  593. ASSERT(0);
  594. }
  595. }
  596. } else {
  597. //
  598. // Make sure the required headless settings are already in the DefSwitches string before
  599. // we write it out.
  600. //
  601. _strlwr( DefSwitches );
  602. if( !strstr(DefSwitches, "redirect") ) {
  603. PUCHAR p;
  604. HEADLESS_RSP_QUERY_INFO Response;
  605. SIZE_T Length;
  606. //
  607. // There are no headless settings. See if we need to add any.
  608. //
  609. Length = sizeof(HEADLESS_RSP_QUERY_INFO);
  610. Status = HeadlessDispatch(HeadlessCmdQueryInformation,
  611. NULL,
  612. 0,
  613. &Response,
  614. &Length
  615. );
  616. p=NULL;
  617. if (NT_SUCCESS(Status) &&
  618. (Response.PortType == HeadlessSerialPort) &&
  619. Response.Serial.TerminalAttached) {
  620. if (Response.Serial.UsedBiosSettings) {
  621. strcat(DefSwitches, "redirect=UseBiosSettings\r\n");
  622. } else {
  623. switch (Response.Serial.TerminalPort) {
  624. case ComPort1:
  625. p = "redirect=com1\r\n";
  626. break;
  627. case ComPort2:
  628. p = "redirect=com2\r\n";
  629. break;
  630. case ComPort3:
  631. p = "redirect=com3\r\n";
  632. break;
  633. case ComPort4:
  634. p = "redirect=com4\r\n";
  635. break;
  636. default:
  637. ASSERT(0);
  638. p = NULL;
  639. break;
  640. }
  641. if (p) {
  642. strcat(DefSwitches, p);
  643. }
  644. //
  645. // Now take care of the 'redirectbaudrate' entry.
  646. //
  647. switch (Response.Serial.TerminalBaudRate) {
  648. case 115200:
  649. p = "redirectbaudrate=115200\r\n";
  650. break;
  651. case 57600:
  652. p = "redirectbaudrate=57600\r\n";
  653. break;
  654. case 19200:
  655. p = "redirectbaudrate=19200\r\n";
  656. break;
  657. default:
  658. p = "redirectbaudrate=9600\r\n";
  659. break;
  660. }
  661. strcat(DefSwitches, p);
  662. }
  663. }
  664. }
  665. }
  666. sprintf(
  667. (PUCHAR)TemporaryBuffer,
  668. "%s%s%s%s%s%ld%s%s%s%s%s",
  669. FLEXBOOT_SECTION2,
  670. CRLF,
  671. DefSwitches,
  672. TIMEOUT,
  673. EQUALS,
  674. Timeout,
  675. CRLF,
  676. DEFAULT,
  677. EQUALS,
  678. Default_O,
  679. CRLF
  680. );
  681. SpMemFree( Default_O );
  682. Status = ZwWriteFile(
  683. fh,
  684. NULL,
  685. NULL,
  686. NULL,
  687. &IoStatusBlock,
  688. TemporaryBuffer,
  689. strlen((PUCHAR)TemporaryBuffer) * sizeof(UCHAR),
  690. NULL,
  691. NULL
  692. );
  693. if(!NT_SUCCESS( Status )) {
  694. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Error writing %s section to %ws!\n", FLEXBOOT_SECTION2, BootIni));
  695. goto cleanup;
  696. }
  697. //
  698. // Now write the BOOTINI_OS_SECTION label to boot.ini
  699. //
  700. sprintf(
  701. (PUCHAR)TemporaryBuffer,
  702. "%s%s",
  703. BOOTINI_OS_SECTION,
  704. CRLF
  705. );
  706. Status = ZwWriteFile(
  707. fh,
  708. NULL,
  709. NULL,
  710. NULL,
  711. &IoStatusBlock,
  712. TemporaryBuffer,
  713. strlen((PUCHAR)TemporaryBuffer) * sizeof(UCHAR),
  714. NULL,
  715. NULL
  716. );
  717. if(!NT_SUCCESS( Status )) {
  718. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Error writing %s section to %ws!\n", BOOTINI_OS_SECTION, BootIni));
  719. goto cleanup;
  720. }
  721. //
  722. // run through all the systems that we have and write them out
  723. //
  724. for( i = 0; BootVars[OSLOADPARTITION][i] ; i++ ) {
  725. //
  726. // If we were told to write a specified number of lines, exit
  727. // when we have done that.
  728. //
  729. if (Count && (i == Count)) {
  730. Status = STATUS_SUCCESS;
  731. goto cleanup;
  732. }
  733. ASSERT( BootVars[OSLOADFILENAME][i] );
  734. ASSERT( BootVars[OSLOADOPTIONS][i] );
  735. ASSERT( BootVars[LOADIDENTIFIER][i] );
  736. //
  737. // On some upgrades, if we're upgrading a "signature" entry,
  738. // then we may not have a DefaultSignature. I fixed that case over
  739. // in Spx86ConvertToSignatureArcName. The other case is where
  740. // we have a DefaultSignature, but there are also some "scsi(..."
  741. // entries in the boot.ini that don't pertain to the entry we're
  742. // upgrading. For that case, we need to send in a signature
  743. // of 0 here, which will force Spx86ConvertToSignatureArcName
  744. // to return us the correct item.
  745. //
  746. //
  747. // You thought the hack above was gross... This one's even
  748. // worse. Problem: we don't think we need a miniport to boot,
  749. // but there are some other boot.ini entries (that point to our
  750. // partition) that do. We always want to leave existing
  751. // boot.ini entries alone though, so we'll leave those broken.
  752. //
  753. // Solution: if the OSLOADPARTITION that we're translating ==
  754. // Default, && ForceBIOSBoot is TRUE && we're translating
  755. // the first OSLOADPARTITION (which is the one for our Default),
  756. // then just don't call Spx86ConvertToSignatureArcName.
  757. // This is bad because it assumes that our entry is the first,
  758. // which it is, but it's a shakey assumption.
  759. //
  760. if( !_wcsicmp( BootVars[OSLOADPARTITION][i], Default ) ) {
  761. //
  762. // This might be our Default entry. Make sure it
  763. // really is and if so, process it the same way.
  764. //
  765. if( i == 0 ) {
  766. //
  767. // It is.
  768. //
  769. if( ForceBIOSBoot ) {
  770. //
  771. // If ForceBIOSBoot is TRUE, then we want to
  772. // force a "multi(..." string. Don't even bother calling
  773. // Spx86ConvertToSignatureArcName on the off chance
  774. // that we may get erroneously converted.
  775. //
  776. if (_wcsnicmp( BootVars[OSLOADPARTITION][i], L"scsi(", 5 ) == 0) {
  777. PWSTR MyStringPointer = NULL;
  778. //
  779. // Darn! We have a string that the old standard
  780. // thought should be converted into a signature(...
  781. // string, but we didn't write out a miniport driver.
  782. // That can happen if someone asked us not to via
  783. // an unattend switch.
  784. //
  785. // We need to change the "scsi(" to "multi("
  786. //
  787. MyStringPointer = SpScsiArcToMultiArc( BootVars[OSLOADPARTITION][i] );
  788. if( MyStringPointer ) {
  789. Osloadpartition_O = SpToOem( MyStringPointer );
  790. } else {
  791. //
  792. // We're in trouble. Take a shot though. Just
  793. // change the "scsi(" part to "multi(".
  794. //
  795. wcscpy( TemporaryBuffer, L"multi" );
  796. wcscat( TemporaryBuffer, &BootVars[OSLOADPARTITION][i][4] );
  797. Osloadpartition_O = SpToOem( TemporaryBuffer );
  798. }
  799. } else {
  800. //
  801. // Just convert to ANSI.
  802. //
  803. Osloadpartition_O = SpToOem( BootVars[OSLOADPARTITION][i] );
  804. }
  805. } else {
  806. //
  807. // We may need to convert this entry.
  808. //
  809. Osloadpartition_O = Spx86ConvertToSignatureArcName( BootVars[OSLOADPARTITION][i], DefaultSignature );
  810. }
  811. } else {
  812. //
  813. // This entry looks just like our Default, but it's point
  814. // to a different installation. Just call Spx86ConvertToSignatureArcName
  815. //
  816. Osloadpartition_O = Spx86ConvertToSignatureArcName( BootVars[OSLOADPARTITION][i], DefaultSignature );
  817. }
  818. } else {
  819. //
  820. // This entry doesn't even look like our string. Send in a
  821. // 0x0 DefaultSignature so that it will only get translated if it
  822. // matches some entry that we know was signed in the original boot.ini.
  823. //
  824. Osloadpartition_O = Spx86ConvertToSignatureArcName( BootVars[OSLOADPARTITION][i], 0 );
  825. }
  826. //
  827. // Insurance...
  828. //
  829. if (Osloadpartition_O == NULL) {
  830. Osloadpartition_O = SpToOem( BootVars[OSLOADPARTITION][i] );
  831. }
  832. Osloadfilename_O = SpToOem( BootVars[OSLOADFILENAME][i] );
  833. Osloadoptions_O = SpToOem( BootVars[OSLOADOPTIONS][i] );
  834. Loadidentifier_O = SpToOem( BootVars[LOADIDENTIFIER][i] );
  835. sprintf(
  836. (PUCHAR)TemporaryBuffer,
  837. "%s%s%s%s %s%s",
  838. Osloadpartition_O,
  839. Osloadfilename_O,
  840. EQUALS,
  841. Loadidentifier_O,
  842. Osloadoptions_O,
  843. CRLF
  844. );
  845. SpMemFree( Osloadpartition_O );
  846. SpMemFree( Osloadfilename_O );
  847. SpMemFree( Osloadoptions_O );
  848. SpMemFree( Loadidentifier_O );
  849. Status = ZwWriteFile(
  850. fh,
  851. NULL,
  852. NULL,
  853. NULL,
  854. &IoStatusBlock,
  855. TemporaryBuffer,
  856. strlen((PUCHAR)TemporaryBuffer) * sizeof(UCHAR),
  857. NULL,
  858. NULL
  859. );
  860. if(!NT_SUCCESS( Status )) {
  861. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Error writing %s section entry to %ws!\n", BOOTINI_OS_SECTION, BootIni));
  862. goto cleanup;
  863. }
  864. }
  865. //
  866. // Finally write the old operating system line to boot.ini
  867. // (but only if not installing on top of Win9x) and if it was
  868. // not specifically disabled
  869. //
  870. if (!DiscardOldSystemLine && (WinUpgradeType != UpgradeWin95)) {
  871. Status = ZwWriteFile(
  872. fh,
  873. NULL,
  874. NULL,
  875. NULL,
  876. &IoStatusBlock,
  877. OldSystemLine,
  878. strlen(OldSystemLine) * sizeof(UCHAR),
  879. NULL,
  880. NULL
  881. );
  882. if (!NT_SUCCESS(Status)) {
  883. KdPrintEx((DPFLTR_SETUP_ID,
  884. DPFLTR_ERROR_LEVEL,
  885. "SETUP: Error writing %s section line to %ws!\n",
  886. BOOTINI_OS_SECTION,
  887. BootIni));
  888. goto cleanup;
  889. }
  890. }
  891. cleanup:
  892. if( !NT_SUCCESS(Status) ) {
  893. if( fh ) {
  894. ZwClose( fh );
  895. }
  896. }
  897. else {
  898. //
  899. // Set the hidden, system, readonly attributes on bootini. ignore
  900. // error
  901. //
  902. RtlZeroMemory( &BasicInfo, sizeof( FILE_BASIC_INFORMATION ) );
  903. BasicInfo.FileAttributes = FILE_ATTRIBUTE_READONLY |
  904. FILE_ATTRIBUTE_HIDDEN |
  905. FILE_ATTRIBUTE_SYSTEM |
  906. FILE_ATTRIBUTE_ARCHIVE
  907. ;
  908. Status1 = SpSetInformationFile(
  909. fh,
  910. FileBasicInformation,
  911. sizeof(BasicInfo),
  912. &BasicInfo
  913. );
  914. if(!NT_SUCCESS(Status1)) {
  915. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to change attribute of %ws. Status = (%lx). Ignoring error.\n",BootIni,Status1));
  916. }
  917. ZwClose( fh );
  918. }
  919. //
  920. // If we copied out the Default, then
  921. // put the original copy of Default back
  922. //
  923. if (Default != NULL) {
  924. wcscpy(Default, _Default);
  925. }
  926. return Status;
  927. }
  928. VOID
  929. SppProcessBootIni(
  930. IN PCHAR BootIni,
  931. OUT PWSTR **BootVars,
  932. OUT PWSTR *Default,
  933. OUT PULONG Timeout
  934. )
  935. /*++
  936. Routine Description:
  937. Look through the [operating systems] section and save all lines
  938. except the one for "C:\" (previous operating system) and one other
  939. optionally specified line.
  940. Filters out the local boot line (C:\$WIN_NT$.~BT) if present.
  941. Arguments:
  942. Return Value:
  943. --*/
  944. {
  945. PCHAR sect,s,p,n;
  946. PWSTR tmp;
  947. CHAR Key[MAX_PATH], Value[MAX_PATH], RestOfLine[MAX_PATH];
  948. ULONG NumComponents;
  949. BOOTVAR i;
  950. ULONG DiskSignature,digval;
  951. SIGNATURED_PARTITIONS *SignedBootIniVars = &SignedBootVars;;
  952. //
  953. // Process the flexboot section, extract timeout and default
  954. //
  955. sect = SppFindSectionInBootIni(BootIni, FLEXBOOT_SECTION1);
  956. if (!sect) {
  957. sect = SppFindSectionInBootIni(BootIni, FLEXBOOT_SECTION2);
  958. }
  959. if (!sect) {
  960. sect = SppFindSectionInBootIni(BootIni, FLEXBOOT_SECTION3);
  961. }
  962. if ( sect ) {
  963. while (sect = SppNextLineInSection(sect)) {
  964. if( SppProcessLine( sect, Key, Value, RestOfLine) ) {
  965. if ( !_stricmp( Key, TIMEOUT ) ) {
  966. *Timeout = atol( Value );
  967. }
  968. else if( !_stricmp( Key, DEFAULT ) ) {
  969. *Default = SpToUnicode( Value );
  970. }
  971. }
  972. }
  973. }
  974. //
  975. // Process the operating systems section
  976. //
  977. sect = SppFindSectionInBootIni(BootIni,BOOTINI_OS_SECTION);
  978. if(!sect) {
  979. return;
  980. }
  981. NumComponents = 0;
  982. while(sect = SppNextLineInSection(sect)) {
  983. if( SppProcessLine( sect, Key, Value, RestOfLine)) {
  984. PCHAR OsLoaddir;
  985. //
  986. // Check if the line is the old bootloader line in which case just
  987. // save it above, else add it to the BootVars structure
  988. //
  989. if (!IsNEC_98) { //NEC98
  990. if( !_stricmp( Key, "C:\\" ) ) {
  991. sprintf( OldSystemLine, "%s=%s %s\r\n", Key, Value, RestOfLine );
  992. } else {
  993. //
  994. // Ignore if local boot directory. This automatically
  995. // filters out that directory when boot.ini is later flushed.
  996. //
  997. if(_strnicmp(Key,"C:\\$WIN_NT$.~BT",15) && (OsLoaddir = strchr(Key,'\\'))) {
  998. //
  999. // Get the ARC name of the x86 system partition region.
  1000. //
  1001. PDISK_REGION SystemPartitionRegion;
  1002. WCHAR SystemPartitionPath[256];
  1003. NumComponents++;
  1004. for(i = FIRSTBOOTVAR; i <= LASTBOOTVAR; i++) {
  1005. BootVars[i] = SpMemRealloc( BootVars[i], (NumComponents + 1) * sizeof( PWSTR * ) );
  1006. ASSERT( BootVars[i] );
  1007. BootVars[i][NumComponents] = NULL;
  1008. }
  1009. SystemPartitionRegion = SpPtValidSystemPartition();
  1010. #if defined(REMOTE_BOOT)
  1011. ASSERT(SystemPartitionRegion ||
  1012. (RemoteBootSetup && !RemoteInstallSetup));
  1013. #else
  1014. ASSERT(SystemPartitionRegion);
  1015. #endif // defined(REMOTE_BOOT)
  1016. if (SystemPartitionRegion) {
  1017. SpArcNameFromRegion(
  1018. SystemPartitionRegion,
  1019. SystemPartitionPath,
  1020. sizeof(SystemPartitionPath),
  1021. PartitionOrdinalOriginal,
  1022. PrimaryArcPath
  1023. );
  1024. BootVars[OSLOADER][NumComponents - 1] = SpMemAlloc((wcslen(SystemPartitionPath)*sizeof(WCHAR))+sizeof(L"ntldr")+sizeof(WCHAR));
  1025. wcscpy(BootVars[OSLOADER][NumComponents - 1],SystemPartitionPath);
  1026. SpConcatenatePaths(BootVars[OSLOADER][NumComponents - 1],L"ntldr");
  1027. BootVars[SYSTEMPARTITION][NumComponents - 1] = SpDupStringW( SystemPartitionPath );
  1028. }
  1029. BootVars[LOADIDENTIFIER][NumComponents - 1] = SpToUnicode( Value );
  1030. BootVars[OSLOADOPTIONS][NumComponents - 1] = SpToUnicode( RestOfLine );
  1031. *OsLoaddir = '\0';
  1032. //
  1033. // Now convert the signature entry into a 'multi...' entry.
  1034. //
  1035. s = strstr( Key, "signature(" );
  1036. if (s) {
  1037. s += 10;
  1038. p = strchr( s, ')' );
  1039. if (p) {
  1040. //
  1041. // We've got a boot.ini entry with a 'signature' string.
  1042. // Let's save it off before we convert it into a 'multi'
  1043. // string so we can convert back easily when we're ready
  1044. // to write out the boot.ini.
  1045. //
  1046. if( SignedBootIniVars->SignedString != NULL ) {
  1047. //
  1048. // We've used this entry, get another...
  1049. //
  1050. SignedBootIniVars->Next = SpMemAlloc(sizeof(SIGNATURED_PARTITIONS));
  1051. SignedBootIniVars = SignedBootIniVars->Next;
  1052. //
  1053. // Make sure...
  1054. //
  1055. SignedBootIniVars->Next = NULL;
  1056. SignedBootIniVars->SignedString = NULL;
  1057. SignedBootIniVars->MultiString = NULL;
  1058. }
  1059. SignedBootIniVars->SignedString = SpToUnicode( Key );
  1060. *p = 0;
  1061. DiskSignature = 0;
  1062. for (n=s; *n; n++) {
  1063. if (isdigit((int)(unsigned char)*n)) {
  1064. digval = *n - '0';
  1065. } else if (isxdigit((int)(unsigned char)*n)) {
  1066. digval = toupper(*n) - 'A' + 10;
  1067. } else {
  1068. digval = 0;
  1069. }
  1070. DiskSignature = DiskSignature * 16 + digval;
  1071. }
  1072. *p = ')';
  1073. //
  1074. // !!! ISSUE : 4/27/01 : vijayj !!!
  1075. //
  1076. // Sometimes we might map a arcname to wrong region on
  1077. // disk.
  1078. //
  1079. // Although we compute a new multi(0)... style arcname
  1080. // from the nt device name, we don't have an entry in
  1081. // the map which actually maps the scsi(0)... style
  1082. // arcname to nt device name.
  1083. //
  1084. // In a multi installation scenario, if the current installation
  1085. // is on a disk which is not visible by firmware and the
  1086. // boot.ini has scsi(...) entry for this installation we
  1087. // would convert it into multi(0)... format which could be
  1088. // similar to the actual multi(0) disk. If this is the case
  1089. // and another installation exists on the first disk also
  1090. // with the same partition number and WINDOWS directory
  1091. // then we would end up using the first disk region as the
  1092. // region to upgrade and fail subsequently while trying
  1093. // to match unique IDs. User will end up with "unable to
  1094. // locate installation to upgrade message".
  1095. //
  1096. // Since the probability of all this conditions being replicated
  1097. // on different machines is very very less, currently
  1098. // I am not going to fix this.
  1099. //
  1100. //
  1101. // We've isolated the signature. Now go find a disk
  1102. // with that signature and get his ARC path.
  1103. //
  1104. for(i=0; (ULONG)i<HardDiskCount; i++) {
  1105. if (HardDisks[i].Signature == DiskSignature) {
  1106. tmp = SpNtToArc( HardDisks[i].DevicePath, PrimaryArcPath );
  1107. if( tmp ) {
  1108. wcscpy( (PWSTR)TemporaryBuffer, tmp );
  1109. SpMemFree(tmp);
  1110. p = strstr( Key, "partition(" );
  1111. if( p ) {
  1112. tmp = SpToUnicode(p);
  1113. if( tmp ) {
  1114. wcscat( (PWSTR)TemporaryBuffer, tmp );
  1115. SpMemFree(tmp);
  1116. BootVars[OSLOADPARTITION][NumComponents - 1] = SpDupStringW( (PWSTR)TemporaryBuffer );
  1117. break;
  1118. }
  1119. }
  1120. }
  1121. }
  1122. }
  1123. if ((ULONG)i == HardDiskCount) {
  1124. BootVars[OSLOADPARTITION][NumComponents - 1] = SpToUnicode( Key );
  1125. }
  1126. //
  1127. // Save off the 'multi' entry in our list of signatures.
  1128. //
  1129. SignedBootIniVars->MultiString = SpDupStringW( BootVars[OSLOADPARTITION][NumComponents - 1] );
  1130. }
  1131. } else {
  1132. BootVars[OSLOADPARTITION][NumComponents - 1] = SpToUnicode( Key );
  1133. }
  1134. *OsLoaddir = '\\';
  1135. #if defined(REMOTE_BOOT)
  1136. if (RemoteBootSetup && !RemoteInstallSetup) {
  1137. BootVars[OSLOADFILENAME][NumComponents - 1] = SpToUnicode( strrchr(OsLoaddir,'\\') );
  1138. } else
  1139. #endif // defined(REMOTE_BOOT)
  1140. {
  1141. BootVars[OSLOADFILENAME][NumComponents - 1] = SpToUnicode( OsLoaddir );
  1142. }
  1143. }
  1144. }
  1145. } else { //NEC98
  1146. if (_strnicmp(Key,"C:\\$WIN_NT$.~BT",15) && (OsLoaddir = strchr( Key, '\\' ))) {
  1147. NumComponents++;
  1148. for(i = FIRSTBOOTVAR; i <= LASTBOOTVAR; i++) {
  1149. BootVars[i] = SpMemRealloc( BootVars[i], (NumComponents + 1) * sizeof( PWSTR * ) );
  1150. ASSERT( BootVars[i] );
  1151. BootVars[i][NumComponents] = NULL;
  1152. }
  1153. BootVars[OSLOADER][NumComponents - 1] = SpMemAlloc(sizeof(L"ntldr")+sizeof(WCHAR));
  1154. wcscpy(BootVars[OSLOADER][NumComponents - 1],L"\\");
  1155. SpConcatenatePaths(BootVars[OSLOADER][NumComponents - 1],L"ntldr");
  1156. BootVars[SYSTEMPARTITION][NumComponents - 1] = SpToUnicode( Key );
  1157. BootVars[LOADIDENTIFIER][NumComponents - 1] = SpToUnicode( Value );
  1158. BootVars[OSLOADOPTIONS][NumComponents - 1] = SpToUnicode( RestOfLine );
  1159. *OsLoaddir = '\0';
  1160. BootVars[OSLOADPARTITION][NumComponents - 1] = SpToUnicode( Key );
  1161. *OsLoaddir = '\\';
  1162. BootVars[OSLOADFILENAME][NumComponents - 1] = SpToUnicode( OsLoaddir );
  1163. ASSERT( BootVars[OSLOADER][NumComponents - 1] );
  1164. ASSERT( BootVars[SYSTEMPARTITION][NumComponents - 1] );
  1165. ASSERT( BootVars[LOADIDENTIFIER][NumComponents - 1] );
  1166. ASSERT( BootVars[OSLOADOPTIONS][NumComponents - 1] );
  1167. ASSERT( BootVars[OSLOADPARTITION][NumComponents - 1] );
  1168. ASSERT( BootVars[OSLOADPARTITION][NumComponents - 1] );
  1169. }
  1170. } //NEC98
  1171. }
  1172. }
  1173. return;
  1174. }
  1175. PCHAR
  1176. SppNextLineInSection(
  1177. IN PCHAR p
  1178. )
  1179. {
  1180. //
  1181. // Find the next \n.
  1182. //
  1183. p = strchr(p,'\n');
  1184. if(!p) {
  1185. return(NULL);
  1186. }
  1187. //
  1188. // skip crs, lfs, spaces, and tabs.
  1189. //
  1190. while(*p && strchr("\r\n \t",*p)) {
  1191. p++;
  1192. }
  1193. // detect if at end of file or section
  1194. if(!(*p) || (*p == '[')) {
  1195. return(NULL);
  1196. }
  1197. return(p);
  1198. }
  1199. PCHAR
  1200. SppFindSectionInBootIni(
  1201. IN PCHAR p,
  1202. IN PCHAR Section
  1203. )
  1204. {
  1205. ULONG len = strlen(Section);
  1206. do {
  1207. //
  1208. // Skip space at front of line
  1209. //
  1210. while(*p && ((*p == ' ') || (*p == '\t'))) {
  1211. p++;
  1212. }
  1213. if(*p) {
  1214. //
  1215. // See if this line matches.
  1216. //
  1217. if(!_strnicmp(p,Section,len)) {
  1218. return(p);
  1219. }
  1220. //
  1221. // Advance to the start of the next line.
  1222. //
  1223. while(*p && (*p != '\n')) {
  1224. p++;
  1225. }
  1226. if(*p) { // skip nl if that terminated the loop.
  1227. p++;
  1228. }
  1229. }
  1230. } while(*p);
  1231. return(NULL);
  1232. }
  1233. BOOLEAN
  1234. SppProcessLine(
  1235. IN PCHAR Line,
  1236. IN OUT PCHAR Key,
  1237. IN OUT PCHAR Value,
  1238. IN OUT PCHAR RestOfLine
  1239. )
  1240. {
  1241. PCHAR p = Line, pLine = Line, pToken;
  1242. CHAR savec;
  1243. BOOLEAN Status = FALSE;
  1244. //
  1245. // Determine end of line
  1246. //
  1247. if(!p) {
  1248. return( Status );
  1249. }
  1250. while( *p && (*p != '\r') && (*p != '\n') ) {
  1251. p++;
  1252. }
  1253. //
  1254. // back up from this position to squeeze out any whitespaces at the
  1255. // end of the line
  1256. //
  1257. while( ((p - 1) >= Line) && strchr(" \t", *(p - 1)) ) {
  1258. p--;
  1259. }
  1260. //
  1261. // terminate the line with null temporarily
  1262. //
  1263. savec = *p;
  1264. *p = '\0';
  1265. //
  1266. // Start at beginning of line and pick out the key
  1267. //
  1268. if ( SppNextToken( pLine, &pToken, &pLine ) ) {
  1269. CHAR savec1 = *pLine;
  1270. *pLine = '\0';
  1271. strcpy( Key, pToken );
  1272. *pLine = savec1;
  1273. //
  1274. // Get next token, it should be a =
  1275. //
  1276. if ( SppNextToken( pLine, &pToken, &pLine ) && *pToken == '=') {
  1277. //
  1278. // Get next token, it will be the value
  1279. //
  1280. if( SppNextToken( pLine, &pToken, &pLine ) ) {
  1281. savec1 = *pLine;
  1282. *pLine = '\0';
  1283. strcpy( Value, pToken );
  1284. *pLine = savec1;
  1285. //
  1286. // if another token exists then take the whole remaining line
  1287. // and make it the RestOfLine token
  1288. //
  1289. if( SppNextToken( pLine, &pToken, &pLine ) ) {
  1290. strcpy( RestOfLine, pToken );
  1291. }
  1292. else {
  1293. *RestOfLine = '\0';
  1294. }
  1295. //
  1296. // We have a well formed line
  1297. //
  1298. Status = TRUE;
  1299. }
  1300. }
  1301. }
  1302. *p = savec;
  1303. return( Status );
  1304. }
  1305. BOOLEAN
  1306. SppNextToken(
  1307. PCHAR p,
  1308. PCHAR *pBegin,
  1309. PCHAR *pEnd
  1310. )
  1311. {
  1312. BOOLEAN Status = FALSE;
  1313. //
  1314. // Validate pointer
  1315. //
  1316. if( !p ) {
  1317. return( Status );
  1318. }
  1319. //
  1320. // Skip whitespace
  1321. //
  1322. while (*p && strchr( " \t", *p ) ) {
  1323. p++;
  1324. }
  1325. //
  1326. // Valid tokens are "=", space delimited strings, quoted strings
  1327. //
  1328. if (*p) {
  1329. *pBegin = p;
  1330. if ( *p == '=' ) {
  1331. *pEnd = p + 1;
  1332. Status = TRUE;
  1333. }
  1334. else if ( *p == '\"' ) {
  1335. if ( p = strchr( p + 1, '\"' ) ) {
  1336. *pEnd = p + 1;
  1337. Status = TRUE;
  1338. }
  1339. }
  1340. else {
  1341. while (*p && !strchr(" \t\"=", *p) ) {
  1342. p++;
  1343. }
  1344. *pEnd = p;
  1345. Status = TRUE;
  1346. }
  1347. }
  1348. return( Status );
  1349. }
  1350. //
  1351. // Boot code stuff.
  1352. //
  1353. NTSTATUS
  1354. pSpBootCodeIo(
  1355. IN PWSTR FilePath,
  1356. IN PWSTR AdditionalFilePath, OPTIONAL
  1357. IN ULONG BytesToRead,
  1358. IN OUT PUCHAR *Buffer,
  1359. IN ULONG OpenDisposition,
  1360. IN BOOLEAN Write,
  1361. IN ULONGLONG Offset,
  1362. IN ULONG BytesPerSector
  1363. )
  1364. {
  1365. PWSTR FullPath;
  1366. PUCHAR buffer = NULL;
  1367. NTSTATUS Status;
  1368. IO_STATUS_BLOCK IoStatusBlock;
  1369. UNICODE_STRING UnicodeString;
  1370. OBJECT_ATTRIBUTES Obja;
  1371. HANDLE Handle;
  1372. LARGE_INTEGER LargeZero;
  1373. PVOID UnalignedMem,AlignedBuffer;
  1374. LargeZero.QuadPart = Offset;
  1375. //
  1376. // Form the name of the file.
  1377. //
  1378. wcscpy((PWSTR)TemporaryBuffer,FilePath);
  1379. if(AdditionalFilePath) {
  1380. SpConcatenatePaths((PWSTR)TemporaryBuffer,AdditionalFilePath);
  1381. }
  1382. FullPath = SpDupStringW((PWSTR)TemporaryBuffer);
  1383. //
  1384. // Open the file.
  1385. //
  1386. INIT_OBJA(&Obja,&UnicodeString,FullPath);
  1387. Status = ZwCreateFile(
  1388. &Handle,
  1389. Write ? FILE_GENERIC_WRITE : FILE_GENERIC_READ,
  1390. &Obja,
  1391. &IoStatusBlock,
  1392. NULL,
  1393. FILE_ATTRIBUTE_NORMAL,
  1394. FILE_SHARE_READ | FILE_SHARE_WRITE,
  1395. OpenDisposition,
  1396. FILE_SYNCHRONOUS_IO_NONALERT | (Write ? FILE_WRITE_THROUGH : 0),
  1397. NULL,
  1398. 0
  1399. );
  1400. if(NT_SUCCESS(Status)) {
  1401. //
  1402. // Allocate a buffer if we are reading.
  1403. // Otherwise the caller passed us the buffer.
  1404. //
  1405. buffer = Write ? *Buffer : SpMemAlloc(BytesToRead);
  1406. //
  1407. // Read or write the disk -- properly aligned. Note that we force at least
  1408. // 512-byte alignment, since there's a hard-coded alignment requirement
  1409. // in the FT driver that must be satisfied.
  1410. //
  1411. if(BytesPerSector < 512) {
  1412. BytesPerSector = 512;
  1413. }
  1414. UnalignedMem = SpMemAlloc(BytesToRead + BytesPerSector);
  1415. AlignedBuffer = ALIGN(UnalignedMem,BytesPerSector);
  1416. if(Write) {
  1417. RtlMoveMemory(AlignedBuffer,buffer,BytesToRead);
  1418. }
  1419. Status = Write
  1420. ?
  1421. ZwWriteFile(
  1422. Handle,
  1423. NULL,
  1424. NULL,
  1425. NULL,
  1426. &IoStatusBlock,
  1427. AlignedBuffer,
  1428. BytesToRead,
  1429. &LargeZero,
  1430. NULL
  1431. )
  1432. :
  1433. ZwReadFile(
  1434. Handle,
  1435. NULL,
  1436. NULL,
  1437. NULL,
  1438. &IoStatusBlock,
  1439. AlignedBuffer,
  1440. BytesToRead,
  1441. &LargeZero,
  1442. NULL
  1443. );
  1444. if(NT_SUCCESS(Status)) {
  1445. if(!Write) {
  1446. RtlMoveMemory(buffer,AlignedBuffer,BytesToRead);
  1447. }
  1448. } else {
  1449. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  1450. "SETUP: Unable to %ws %u bytes from %ws (%lx)\n",
  1451. Write ? L"write" : L"read",
  1452. BytesToRead,
  1453. FullPath,
  1454. Status
  1455. ));
  1456. }
  1457. SpMemFree(UnalignedMem);
  1458. //
  1459. // Close the file.
  1460. //
  1461. ZwClose(Handle);
  1462. } else {
  1463. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: pSpBootCodeIo: Unable to open %ws (%lx)\n",FullPath,Status));
  1464. }
  1465. SpMemFree(FullPath);
  1466. if(!Write) {
  1467. if(NT_SUCCESS(Status)) {
  1468. *Buffer = buffer;
  1469. } else {
  1470. if(buffer) {
  1471. SpMemFree(buffer);
  1472. }
  1473. }
  1474. }
  1475. return(Status);
  1476. }
  1477. BOOLEAN
  1478. pSpScanBootcode(
  1479. IN PVOID Buffer,
  1480. IN PCHAR String
  1481. )
  1482. /*++
  1483. Routine Description:
  1484. Look in a boot sector to find an identifying string. The scan starts
  1485. at offset 128 and continues through byte 509 of the buffer.
  1486. The search is case-sensitive.
  1487. Arguments:
  1488. Buffer - buffer to scan
  1489. String - string to scan for
  1490. Return Value:
  1491. --*/
  1492. {
  1493. ULONG len = strlen(String);
  1494. ULONG LastFirstByte = 510 - len;
  1495. ULONG i;
  1496. PCHAR p = Buffer;
  1497. //
  1498. // Use the obvious brute force method.
  1499. //
  1500. for(i=128; i<LastFirstByte; i++) {
  1501. if(!strncmp(p+i,String,len)) {
  1502. return(TRUE);
  1503. }
  1504. }
  1505. return(FALSE);
  1506. }
  1507. VOID
  1508. SpDetermineOsTypeFromBootSector(
  1509. IN PWSTR CColonPath,
  1510. IN PUCHAR BootSector,
  1511. OUT PUCHAR *OsDescription,
  1512. OUT PBOOLEAN IsNtBootcode,
  1513. OUT PBOOLEAN IsOtherOsInstalled,
  1514. IN WCHAR DriveLetter
  1515. )
  1516. {
  1517. PWSTR description;
  1518. PWSTR *FilesToLookFor;
  1519. ULONG FileCount;
  1520. BOOLEAN PossiblyChicago = FALSE;
  1521. PWSTR MsDosFiles[2] = { L"MSDOS.SYS" , L"IO.SYS" };
  1522. //
  1523. // Some versions of PC-DOS have ibmio.com, others have ibmbio.com.
  1524. //
  1525. //PWSTR PcDosFiles[2] = { L"IBMDOS.COM", L"IBMIO.COM" };
  1526. PWSTR PcDosFiles[1] = { L"IBMDOS.COM" };
  1527. PWSTR Os2Files[2] = { L"OS2LDR" , L"OS2KRNL" };
  1528. //
  1529. // Check for nt boot code.
  1530. //
  1531. if(pSpScanBootcode(BootSector,"NTLDR")) {
  1532. *IsNtBootcode = TRUE;
  1533. *IsOtherOsInstalled = FALSE;
  1534. description = L"";
  1535. } else {
  1536. //
  1537. // It's not NT bootcode.
  1538. //
  1539. *IsNtBootcode = FALSE;
  1540. *IsOtherOsInstalled = TRUE;
  1541. //
  1542. // Check for MS-DOS.
  1543. //
  1544. if (pSpScanBootcode(BootSector,((!IsNEC_98) ? "MSDOS SYS" : "IO SYS"))) { //NEC98
  1545. FilesToLookFor = MsDosFiles;
  1546. FileCount = ELEMENT_COUNT(MsDosFiles);
  1547. description = L"MS-DOS";
  1548. PossiblyChicago = TRUE; // Chicago uses same signature files
  1549. } else {
  1550. //
  1551. // Check for PC-DOS.
  1552. //
  1553. if(pSpScanBootcode(BootSector,"IBMDOS COM")) {
  1554. FilesToLookFor = PcDosFiles;
  1555. FileCount = ELEMENT_COUNT(PcDosFiles);
  1556. description = L"PC-DOS";
  1557. } else {
  1558. //
  1559. // Check for OS/2.
  1560. //
  1561. if(pSpScanBootcode(BootSector,"OS2")) {
  1562. FilesToLookFor = Os2Files;
  1563. FileCount = ELEMENT_COUNT(Os2Files);
  1564. description = L"OS/2";
  1565. } else {
  1566. //
  1567. // Not NT, DOS, or OS/2.
  1568. // It's just plain old "previous operating system."
  1569. // Fetch the string from the resources.
  1570. //
  1571. WCHAR DriveLetterString[2];
  1572. DriveLetterString[0] = DriveLetter;
  1573. DriveLetterString[1] = L'\0';
  1574. SpStringToUpper(DriveLetterString);
  1575. FilesToLookFor = NULL;
  1576. FileCount = 0;
  1577. description = (PWSTR)TemporaryBuffer;
  1578. SpFormatMessage(description,sizeof(TemporaryBuffer),SP_TEXT_PREVIOUS_OS, DriveLetterString);
  1579. }
  1580. }
  1581. }
  1582. //
  1583. // If we think we have found an os, check to see whether
  1584. // its signature files are present.
  1585. // We could have, say, a disk where the user formats is using DOS
  1586. // and then installs NT immediately thereafter.
  1587. //
  1588. if(FilesToLookFor) {
  1589. //
  1590. // Copy CColonPath into a larger buffer, because
  1591. // SpNFilesExist wants to append a backslash onto it.
  1592. //
  1593. wcscpy((PWSTR)TemporaryBuffer,CColonPath);
  1594. if(!SpNFilesExist((PWSTR)TemporaryBuffer,FilesToLookFor,FileCount,FALSE)) {
  1595. //
  1596. // Ths os is not really there.
  1597. //
  1598. *IsOtherOsInstalled = FALSE;
  1599. description = L"";
  1600. } else if(PossiblyChicago) {
  1601. wcscpy((PWSTR)TemporaryBuffer, CColonPath);
  1602. SpConcatenatePaths((PWSTR)TemporaryBuffer, L"IO.SYS");
  1603. if(SpHasMZHeader((PWSTR)TemporaryBuffer)) {
  1604. description = L"Microsoft Windows";
  1605. }
  1606. }
  1607. }
  1608. }
  1609. //
  1610. // convert the description to oem text.
  1611. //
  1612. *OsDescription = SpToOem(description);
  1613. }
  1614. VOID
  1615. SpLayBootCode(
  1616. IN OUT PDISK_REGION CColonRegion
  1617. )
  1618. {
  1619. PUCHAR NewBootCode;
  1620. ULONG BootCodeSize;
  1621. PUCHAR ExistingBootCode;
  1622. NTSTATUS Status;
  1623. PUCHAR ExistingBootCodeOs;
  1624. PWSTR CColonPath;
  1625. HANDLE PartitionHandle;
  1626. PWSTR BootsectDosName = L"\\bootsect.dos";
  1627. PWSTR OldBootsectDosName = L"\\bootsect.bak";
  1628. PWSTR BootSectDosFullName, OldBootSectDosFullName, p;
  1629. BOOLEAN IsNtBootcode,OtherOsInstalled, FileExist;
  1630. UNICODE_STRING UnicodeString;
  1631. OBJECT_ATTRIBUTES Obja;
  1632. IO_STATUS_BLOCK IoStatusBlock;
  1633. BOOLEAN BootSectorCorrupt = FALSE;
  1634. ULONG MirrorSector;
  1635. ULONG BytesPerSector;
  1636. ULONGLONG ActualSectorCount, hidden_sectors, super_area_size;
  1637. UCHAR SysId;
  1638. ULONGLONG HiddenSectorCount,VolumeSectorCount; //NEC98
  1639. PUCHAR DiskArraySectorData,TmpBuffer; //NEC98
  1640. ExistingBootCode = NULL;
  1641. BytesPerSector = HardDisks[CColonRegion->DiskNumber].Geometry.BytesPerSector;
  1642. CLEAR_CLIENT_SCREEN();
  1643. SpDisplayStatusText(SP_STAT_INITING_FLEXBOOT,DEFAULT_STATUS_ATTRIBUTE);
  1644. switch(CColonRegion->Filesystem) {
  1645. case FilesystemNewlyCreated:
  1646. //
  1647. // If the filesystem is newly-created, then there is
  1648. // nothing to do, because there can be no previous
  1649. // operating system.
  1650. //
  1651. return;
  1652. case FilesystemNtfs:
  1653. NewBootCode = (!IsNEC_98) ? NtfsBootCode : PC98NtfsBootCode; //NEC98
  1654. BootCodeSize = (!IsNEC_98) ? sizeof(NtfsBootCode) : sizeof(PC98NtfsBootCode); //NEC98
  1655. ASSERT(BootCodeSize == 8192);
  1656. break;
  1657. case FilesystemFat:
  1658. NewBootCode = (!IsNEC_98) ? FatBootCode : PC98FatBootCode; //NEC98
  1659. BootCodeSize = (!IsNEC_98) ? sizeof(FatBootCode) : sizeof(PC98FatBootCode); //NEC98
  1660. ASSERT(BootCodeSize == 512);
  1661. break;
  1662. case FilesystemFat32:
  1663. //
  1664. // Special hackage required for Fat32 because its NT boot code
  1665. // is discontiguous.
  1666. //
  1667. ASSERT(sizeof(Fat32BootCode) == 1536);
  1668. NewBootCode = (!IsNEC_98) ? Fat32BootCode : PC98Fat32BootCode; //NEC98
  1669. BootCodeSize = 512;
  1670. break;
  1671. default:
  1672. if (RepairItems[RepairBootSect]) {
  1673. BootSectorCorrupt = TRUE;
  1674. } else {
  1675. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: bogus filesystem %u for C:!\n",CColonRegion->Filesystem));
  1676. ASSERT(0);
  1677. return;
  1678. }
  1679. }
  1680. //
  1681. // Form the device path to C: and open the partition.
  1682. //
  1683. SpNtNameFromRegion(CColonRegion,(PWSTR)TemporaryBuffer,sizeof(TemporaryBuffer),PartitionOrdinalCurrent);
  1684. CColonPath = SpDupStringW((PWSTR)TemporaryBuffer);
  1685. INIT_OBJA(&Obja,&UnicodeString,CColonPath);
  1686. Status = ZwCreateFile(
  1687. &PartitionHandle,
  1688. FILE_GENERIC_READ | FILE_GENERIC_WRITE,
  1689. &Obja,
  1690. &IoStatusBlock,
  1691. NULL,
  1692. FILE_ATTRIBUTE_NORMAL,
  1693. FILE_SHARE_READ | FILE_SHARE_WRITE,
  1694. FILE_OPEN,
  1695. FILE_SYNCHRONOUS_IO_NONALERT,
  1696. NULL,
  1697. 0
  1698. );
  1699. if (!NT_SUCCESS(Status)) {
  1700. KdPrintEx ((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: unable to open the partition for C:!\n"));
  1701. ASSERT(0);
  1702. return;
  1703. }
  1704. //
  1705. // Allocate a buffer and read in the boot sector(s) currently on the disk.
  1706. //
  1707. if (BootSectorCorrupt) {
  1708. //
  1709. // We can't determine the file system type from the boot sector, so
  1710. // we assume it's NTFS if we find a mirror sector, and FAT otherwise.
  1711. //
  1712. if (MirrorSector = NtfsMirrorBootSector (PartitionHandle,
  1713. BytesPerSector, &ExistingBootCode)) {
  1714. //
  1715. // It's NTFS - use the mirror boot sector
  1716. //
  1717. NewBootCode = (!IsNEC_98) ? NtfsBootCode : PC98NtfsBootCode; //NEC98
  1718. BootCodeSize = (!IsNEC_98) ? sizeof(NtfsBootCode) : sizeof(PC98NtfsBootCode); //NEC98
  1719. ASSERT(BootCodeSize == 8192);
  1720. CColonRegion->Filesystem = FilesystemNtfs;
  1721. IsNtBootcode = TRUE;
  1722. } else {
  1723. //
  1724. // It's FAT - create a new boot sector
  1725. //
  1726. NewBootCode = (!IsNEC_98) ? FatBootCode : PC98FatBootCode; //NEC98
  1727. BootCodeSize = (!IsNEC_98) ? sizeof(FatBootCode) : sizeof(PC98FatBootCode); //NEC98
  1728. ASSERT(BootCodeSize == 512);
  1729. CColonRegion->Filesystem = FilesystemFat;
  1730. IsNtBootcode = FALSE;
  1731. SpPtGetSectorLayoutInformation (CColonRegion, &hidden_sectors,
  1732. &ActualSectorCount);
  1733. //
  1734. // No alignment requirement here
  1735. //
  1736. ExistingBootCode = SpMemAlloc(BytesPerSector);
  1737. //
  1738. // This will actually fail with STATUS_BUFFER_TOO_SMALL but it will fill in
  1739. // the bpb, which is what we want
  1740. //
  1741. FmtFillFormatBuffer (
  1742. ActualSectorCount,
  1743. BytesPerSector,
  1744. HardDisks[CColonRegion->DiskNumber].Geometry.SectorsPerTrack,
  1745. HardDisks[CColonRegion->DiskNumber].Geometry.TracksPerCylinder,
  1746. hidden_sectors,
  1747. ExistingBootCode,
  1748. BytesPerSector,
  1749. &super_area_size,
  1750. NULL,
  1751. 0,
  1752. &SysId
  1753. );
  1754. }
  1755. Status = STATUS_SUCCESS;
  1756. } else if (
  1757. RepairItems[RepairBootSect] &&
  1758. CColonRegion->Filesystem == FilesystemNtfs &&
  1759. (MirrorSector = NtfsMirrorBootSector (PartitionHandle, BytesPerSector,
  1760. &ExistingBootCode))
  1761. ) {
  1762. //
  1763. // We use the mirror sector to repair a NTFS file system
  1764. //
  1765. } else {
  1766. //
  1767. // Just use the existing boot code.
  1768. //
  1769. Status = pSpBootCodeIo(
  1770. CColonPath,
  1771. NULL,
  1772. BootCodeSize,
  1773. &ExistingBootCode,
  1774. FILE_OPEN,
  1775. FALSE,
  1776. 0,
  1777. BytesPerSector
  1778. );
  1779. if(CColonRegion->Filesystem == FilesystemNtfs) {
  1780. MirrorSector = NtfsMirrorBootSector(PartitionHandle,BytesPerSector,NULL);
  1781. }
  1782. }
  1783. if(NT_SUCCESS(Status)) {
  1784. //
  1785. // Determine the type of operating system the existing boot sector(s) are for
  1786. // and whether that os is actually installed. Note that we don't need to call
  1787. // this for NTFS.
  1788. //
  1789. if (BootSectorCorrupt) {
  1790. OtherOsInstalled = FALSE;
  1791. ExistingBootCodeOs = NULL;
  1792. } else if(CColonRegion->Filesystem != FilesystemNtfs) {
  1793. SpDetermineOsTypeFromBootSector(
  1794. CColonPath,
  1795. ExistingBootCode,
  1796. &ExistingBootCodeOs,
  1797. &IsNtBootcode,
  1798. &OtherOsInstalled,
  1799. CColonRegion->DriveLetter
  1800. );
  1801. } else {
  1802. IsNtBootcode = TRUE;
  1803. OtherOsInstalled = FALSE;
  1804. ExistingBootCodeOs = NULL;
  1805. }
  1806. //
  1807. // lay down the new boot code
  1808. //
  1809. if(OtherOsInstalled) {
  1810. if(RepairItems[RepairBootSect]) {
  1811. p = (PWSTR)TemporaryBuffer;
  1812. wcscpy(p,CColonPath);
  1813. SpConcatenatePaths(p,OldBootsectDosName);
  1814. OldBootSectDosFullName = SpDupStringW(p);
  1815. p = (PWSTR)TemporaryBuffer;
  1816. wcscpy(p,CColonPath);
  1817. SpConcatenatePaths(p,BootsectDosName);
  1818. BootSectDosFullName = SpDupStringW(p);
  1819. //
  1820. // If bootsect.dos already exists, we need to delete
  1821. // bootsect.pre, which may or may not exist and
  1822. // rename the bootsect.dos to bootsect.pre.
  1823. //
  1824. FileExist = SpFileExists(BootSectDosFullName, FALSE);
  1825. if (SpFileExists(OldBootSectDosFullName, FALSE) && FileExist) {
  1826. SpDeleteFile(CColonPath,OldBootsectDosName,NULL);
  1827. }
  1828. if (FileExist) {
  1829. SpRenameFile(BootSectDosFullName, OldBootSectDosFullName, FALSE);
  1830. }
  1831. SpMemFree(BootSectDosFullName);
  1832. SpMemFree(OldBootSectDosFullName);
  1833. } else {
  1834. //
  1835. // Delete bootsect.dos in preparation for rewriting it below.
  1836. // Doing this leverages code to set its attributes in SpDeleteFile.
  1837. // (We need to remove read-only attribute before overwriting).
  1838. //
  1839. SpDeleteFile(CColonPath,BootsectDosName,NULL);
  1840. }
  1841. //
  1842. // Write out the existing (old) boot sector into c:\bootsect.dos.
  1843. //
  1844. Status = pSpBootCodeIo(
  1845. CColonPath,
  1846. BootsectDosName,
  1847. BootCodeSize,
  1848. &ExistingBootCode,
  1849. FILE_OVERWRITE_IF,
  1850. TRUE,
  1851. 0,
  1852. BytesPerSector
  1853. );
  1854. //
  1855. // Set the description text to the description calculated
  1856. // by SpDetermineOsTypeFromBootSector().
  1857. //
  1858. _snprintf(
  1859. OldSystemLine,
  1860. sizeof(OldSystemLine),
  1861. "C:\\ = \"%s\"\r\n",
  1862. ExistingBootCodeOs
  1863. );
  1864. } // end if(OtherOsInstalled)
  1865. if(NT_SUCCESS(Status)) {
  1866. //
  1867. // Transfer the bpb from the existing boot sector into the boot code buffer
  1868. // and make sure the physical drive field is set to hard disk (0x80).
  1869. //
  1870. // The first three bytes of the NT boot code are going to be something like
  1871. // EB 3C 90, which is intel jump instruction to an offset in the boot sector,
  1872. // past the BPB, to continue execution. We want to preserve everything in the
  1873. // current boot sector up to the start of that code. Instead of harcoding
  1874. // a value, we'll use the offset of the jump instruction to determine how many
  1875. // bytes must be preserved.
  1876. //
  1877. RtlMoveMemory(NewBootCode+3,ExistingBootCode+3,NewBootCode[1]-1);
  1878. if(CColonRegion->Filesystem != FilesystemFat32) {
  1879. //
  1880. // On fat32 this overwrites the BigNumFatSecs field,
  1881. // a very bad thing to do indeed!
  1882. //
  1883. NewBootCode[36] = 0x80;
  1884. }
  1885. //
  1886. // get Hidden sector informatin.
  1887. //
  1888. if (IsNEC_98) { //NEC98
  1889. SpPtGetSectorLayoutInformation(
  1890. CColonRegion,
  1891. &HiddenSectorCount,
  1892. &VolumeSectorCount // not used
  1893. );
  1894. //
  1895. // write Hidden sector informatin.
  1896. //
  1897. if (!RepairWinnt) { // for install a partition where before DOS 3.x
  1898. *((ULONG *)&(NewBootCode[0x1c])) = (ULONG)HiddenSectorCount;
  1899. if(*((USHORT *)&(NewBootCode[0x13])) != 0) {
  1900. *((ULONG *)&(NewBootCode[0x20])) = 0L;
  1901. }
  1902. }
  1903. } //NEC98
  1904. //
  1905. // Write out boot code buffer, which now contains the valid bpb,
  1906. // to the boot sector(s).
  1907. //
  1908. Status = pSpBootCodeIo(
  1909. CColonPath,
  1910. NULL,
  1911. BootCodeSize,
  1912. &NewBootCode,
  1913. FILE_OPEN,
  1914. TRUE,
  1915. 0,
  1916. BytesPerSector
  1917. );
  1918. //
  1919. // Special case for Fat32, which has a second sector of boot code
  1920. // at sector 12, discontiguous from the code on sector 0.
  1921. //
  1922. if(NT_SUCCESS(Status) && (CColonRegion->Filesystem == FilesystemFat32)) {
  1923. NewBootCode = (!IsNEC_98) ? Fat32BootCode + 1024
  1924. : PC98Fat32BootCode + 1024; //NEC98
  1925. Status = pSpBootCodeIo(
  1926. CColonPath,
  1927. NULL,
  1928. BootCodeSize,
  1929. &NewBootCode,
  1930. FILE_OPEN,
  1931. TRUE,
  1932. 12*512,
  1933. BytesPerSector
  1934. );
  1935. }
  1936. //
  1937. // Update the mirror boot sector.
  1938. //
  1939. if((CColonRegion->Filesystem == FilesystemNtfs) && MirrorSector) {
  1940. WriteNtfsBootSector(PartitionHandle,BytesPerSector,NewBootCode,MirrorSector);
  1941. }
  1942. }
  1943. if(ExistingBootCodeOs) {
  1944. SpMemFree(ExistingBootCodeOs);
  1945. }
  1946. }
  1947. if(ExistingBootCode) {
  1948. SpMemFree(ExistingBootCode);
  1949. }
  1950. SpMemFree(CColonPath);
  1951. ZwClose (PartitionHandle);
  1952. //
  1953. // Handle the error case.
  1954. //
  1955. if(!NT_SUCCESS(Status)) {
  1956. WCHAR DriveLetterString[2];
  1957. DriveLetterString[0] = CColonRegion->DriveLetter;
  1958. DriveLetterString[1] = L'\0';
  1959. SpStringToUpper(DriveLetterString);
  1960. SpStartScreen(SP_SCRN_CANT_INIT_FLEXBOOT,
  1961. 3,
  1962. HEADER_HEIGHT+1,
  1963. FALSE,
  1964. FALSE,
  1965. DEFAULT_ATTRIBUTE,
  1966. DriveLetterString,
  1967. DriveLetterString
  1968. );
  1969. SpDisplayStatusOptions(DEFAULT_STATUS_ATTRIBUTE,SP_STAT_F3_EQUALS_EXIT,0);
  1970. SpInputDrain();
  1971. while(SpInputGetKeypress() != KEY_F3) ;
  1972. SpDone(0,FALSE,TRUE);
  1973. }
  1974. }
  1975. #if defined(REMOTE_BOOT)
  1976. BOOLEAN
  1977. Spx86FlushRemoteBootVars(
  1978. IN PDISK_REGION TargetRegion,
  1979. IN PWSTR **BootVars,
  1980. IN PWSTR Default
  1981. )
  1982. {
  1983. WCHAR BootIni[512];
  1984. NTSTATUS Status;
  1985. //
  1986. // Form the path to boot.ini.
  1987. //
  1988. SpNtNameFromRegion(TargetRegion,BootIni,sizeof(BootIni),PartitionOrdinalCurrent);
  1989. SpConcatenatePaths(BootIni,WBOOT_INI);
  1990. //
  1991. // If Boot.ini already exists, delete it.
  1992. //
  1993. if( SpFileExists( BootIni, FALSE ) ) {
  1994. SpDeleteFile( BootIni, NULL, NULL );
  1995. }
  1996. Status = Spx86WriteBootIni(
  1997. BootIni,
  1998. BootVars,
  1999. 1, // timeout
  2000. Default,
  2001. 1 // only write one line
  2002. );
  2003. if(!NT_SUCCESS( Status )) {
  2004. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Error writing boot.ini!\n"));
  2005. goto cleanup;
  2006. }
  2007. cleanup:
  2008. return( NT_SUCCESS(Status) );
  2009. }
  2010. #endif // defined(REMOTE_BOOT)
  2011. BOOLEAN
  2012. SpHasMZHeader(
  2013. IN PWSTR FileName
  2014. )
  2015. {
  2016. HANDLE FileHandle;
  2017. HANDLE SectionHandle;
  2018. PVOID ViewBase;
  2019. ULONG FileSize;
  2020. NTSTATUS Status;
  2021. PUCHAR Header;
  2022. BOOLEAN Ret = FALSE;
  2023. //
  2024. // Open and map the file.
  2025. //
  2026. FileHandle = 0;
  2027. Status = SpOpenAndMapFile(FileName,
  2028. &FileHandle,
  2029. &SectionHandle,
  2030. &ViewBase,
  2031. &FileSize,
  2032. FALSE
  2033. );
  2034. if(!NT_SUCCESS(Status)) {
  2035. return FALSE;
  2036. }
  2037. Header = (PUCHAR)ViewBase;
  2038. //
  2039. // Guard with try/except in case we get an inpage error
  2040. //
  2041. try {
  2042. if((FileSize >= 2) && (Header[0] == 'M') && (Header[1] == 'Z')) {
  2043. Ret = TRUE;
  2044. }
  2045. } except(IN_PAGE_ERROR) {
  2046. //
  2047. // Do nothing, we simply want to return FALSE.
  2048. //
  2049. }
  2050. SpUnmapFile(SectionHandle, ViewBase);
  2051. ZwClose(FileHandle);
  2052. return Ret;
  2053. }
  2054. //
  2055. // NEC98
  2056. //
  2057. PUCHAR
  2058. SpCreateBootiniImage(
  2059. OUT PULONG FileSize
  2060. )
  2061. {
  2062. PUCHAR BootIniBuf,IniImageBuf,IniImageBufSave,IniCreateBuf,IniCreateBufSave;
  2063. PUCHAR FindSectPtr;
  2064. PUCHAR sect; // point to target section. if it is NULL,not existing target section.
  2065. PUCHAR pArcNameA;
  2066. WCHAR TempBuffer[256];
  2067. WCHAR TempArcPath[256];
  2068. ULONG NtDirLen,TotalNtDirlen,CreateBufCnt;
  2069. ULONG Timeout;
  2070. ULONG Disk;
  2071. ULONG BootiniSize;
  2072. ULONG ArcNameLen;
  2073. PDISK_REGION pRegion;
  2074. HANDLE fh;
  2075. HANDLE SectionHandle;
  2076. PVOID ViewBase;
  2077. #define Default_Dir "\\MOCHI"
  2078. if(!HardDiskCount){
  2079. return(NULL);
  2080. }
  2081. //
  2082. // Create basic style of boot.ini image and progress pointer end of line.
  2083. //
  2084. NtDirLen = TotalNtDirlen = CreateBufCnt = 0;
  2085. IniCreateBufSave = IniCreateBuf = SpMemAlloc(1024);
  2086. RtlZeroMemory(IniCreateBuf,1024);
  2087. Timeout = DEFAULT_TIMEOUT;
  2088. sprintf(
  2089. IniCreateBuf,
  2090. "%s%s%s%s%ld%s%s%s%s%s%s%s%s",
  2091. FLEXBOOT_SECTION2, // [boot loader]
  2092. CRLF,
  2093. TIMEOUT,
  2094. EQUALS,
  2095. Timeout,
  2096. CRLF,
  2097. DEFAULT,
  2098. EQUALS,
  2099. "c:",
  2100. Default_Dir,
  2101. CRLF,
  2102. BOOTINI_OS_SECTION, // [operating systems]
  2103. CRLF
  2104. );
  2105. sect = SppFindSectionInBootIni(IniCreateBuf,FLEXBOOT_SECTION2);
  2106. if(sect == NULL){
  2107. return(NULL);
  2108. }
  2109. for( IniCreateBuf = sect; *IniCreateBuf && (*IniCreateBuf != '\n'); IniCreateBuf++,CreateBufCnt++);
  2110. CreateBufCnt++;
  2111. sect = SppFindSectionInBootIni(IniCreateBuf,TIMEOUT);
  2112. if(sect == NULL){
  2113. return(NULL);
  2114. }
  2115. for( IniCreateBuf = sect; *IniCreateBuf && (*IniCreateBuf != '\n'); IniCreateBuf++,CreateBufCnt++);
  2116. CreateBufCnt++;
  2117. sect = SppFindSectionInBootIni(IniCreateBuf,DEFAULT);
  2118. if(sect == NULL){
  2119. return(NULL);
  2120. }
  2121. for( IniCreateBuf = sect; *IniCreateBuf && (*IniCreateBuf != '\n'); IniCreateBuf++,CreateBufCnt++);
  2122. CreateBufCnt++;
  2123. sect = SppFindSectionInBootIni(IniCreateBuf,BOOTINI_OS_SECTION);
  2124. if(sect == NULL){
  2125. return(NULL);
  2126. }
  2127. for( IniCreateBuf = sect; *IniCreateBuf && (*IniCreateBuf != '\n'); IniCreateBuf++,CreateBufCnt++);
  2128. IniCreateBuf++;
  2129. CreateBufCnt++;
  2130. //
  2131. // Read boot.ini files from all drives.(except sleep and non bootable drives.)
  2132. //
  2133. for(Disk=0; Disk < HardDiskCount; Disk++){
  2134. for(pRegion=PartitionedDisks[Disk].PrimaryDiskRegions; pRegion;pRegion=pRegion->Next){
  2135. if(!pRegion->PartitionedSpace) {
  2136. continue;
  2137. }
  2138. SpNtNameFromRegion(
  2139. pRegion,
  2140. TempBuffer,
  2141. sizeof(TempBuffer),
  2142. PartitionOrdinalCurrent
  2143. );
  2144. SpConcatenatePaths(TempBuffer,WBOOT_INI);
  2145. //
  2146. // Open and map the boot.ini file.
  2147. //
  2148. fh = 0;
  2149. if(!NT_SUCCESS(SpOpenAndMapFile(TempBuffer,&fh,&SectionHandle,&ViewBase,&BootiniSize,FALSE))) {
  2150. continue;
  2151. }
  2152. //
  2153. // Allocate a buffer for the file.
  2154. //
  2155. IniImageBuf = SpMemAlloc(BootiniSize+1);
  2156. IniImageBufSave = IniImageBuf;
  2157. ASSERT(IniImageBuf);
  2158. RtlZeroMemory(IniImageBuf, BootiniSize+1);
  2159. //
  2160. // Transfer boot.ini into the buffer. We do this because we also
  2161. // want to place a 0 byte at the end of the buffer to terminate
  2162. // the file.
  2163. //
  2164. // Guard the RtlMoveMemory because if we touch the memory backed by boot.ini
  2165. // and get an i/o error, the memory manager will raise an exception.
  2166. try {
  2167. RtlMoveMemory(IniImageBuf,ViewBase,BootiniSize);
  2168. }
  2169. except( IN_PAGE_ERROR ) {
  2170. //
  2171. // Do nothing, boot ini processing can proceed with whatever has been
  2172. // read
  2173. //
  2174. }
  2175. //
  2176. // check out existing target section in boot.ini
  2177. //
  2178. sect = SppFindSectionInBootIni(IniImageBuf,FLEXBOOT_SECTION2);
  2179. if(sect==NULL){
  2180. SpMemFree(IniImageBufSave);
  2181. SpUnmapFile(SectionHandle,ViewBase);
  2182. ZwClose(fh);
  2183. continue;
  2184. }
  2185. sect = SppFindSectionInBootIni(IniImageBuf,DEFAULT);
  2186. if(sect==NULL){
  2187. SpMemFree(IniImageBufSave);
  2188. SpUnmapFile(SectionHandle,ViewBase);
  2189. ZwClose(fh);
  2190. continue;
  2191. }
  2192. sect = SppFindSectionInBootIni(IniImageBuf,BOOTINI_OS_SECTION);
  2193. if(sect == NULL){
  2194. SpUnmapFile(SectionHandle,ViewBase);
  2195. ZwClose(fh);
  2196. continue;
  2197. }
  2198. //
  2199. // move pointer to end of line and skip the space.
  2200. //
  2201. for( IniImageBuf = sect; *IniImageBuf && (*IniImageBuf != '\n'); IniImageBuf++ );
  2202. for( ; *IniImageBuf && (( *IniImageBuf == ' ' ) || (*IniImageBuf == '\t')) ; IniImageBuf++ );
  2203. IniImageBuf++;
  2204. FindSectPtr = IniImageBuf;
  2205. //
  2206. // NOTE:
  2207. // override arc name when boot path written as "C:", not as arc name.
  2208. //
  2209. ArcNameLen = 0;
  2210. pArcNameA = (PUCHAR)NULL;
  2211. if( ( *(IniImageBuf+1) == L':' )&&( *(IniImageBuf+2) == L'\\' ) ) {
  2212. //
  2213. // This is NEC98 legacy style format, like "C:\WINNT=...",
  2214. // So translate to arc name for boot.ini in NT 5.0
  2215. //
  2216. SpArcNameFromRegion(pRegion,
  2217. TempArcPath,
  2218. sizeof(TempArcPath),
  2219. PartitionOrdinalOriginal,
  2220. PrimaryArcPath
  2221. );
  2222. pArcNameA = SpToOem(TempArcPath);
  2223. if( pArcNameA ) {
  2224. ArcNameLen = strlen(pArcNameA);
  2225. IniImageBuf += 2;
  2226. FindSectPtr = IniImageBuf;
  2227. }
  2228. }
  2229. for( NtDirLen = 0 ; *IniImageBuf && (*IniImageBuf != '\n');NtDirLen++,IniImageBuf++);
  2230. NtDirLen++;
  2231. if( ArcNameLen && pArcNameA ) { // Only case of override arc path.
  2232. RtlMoveMemory( IniCreateBuf+TotalNtDirlen, pArcNameA, ArcNameLen );
  2233. TotalNtDirlen += ArcNameLen;
  2234. SpMemFree(pArcNameA);
  2235. }
  2236. RtlMoveMemory(IniCreateBuf+TotalNtDirlen,FindSectPtr,NtDirLen);
  2237. TotalNtDirlen += NtDirLen;
  2238. SpMemFree(IniImageBufSave);
  2239. SpUnmapFile(SectionHandle,ViewBase);
  2240. ZwClose(fh);
  2241. }
  2242. }
  2243. if(TotalNtDirlen == 0){
  2244. SpMemFree(IniCreateBufSave);
  2245. return(NULL);
  2246. }
  2247. BootIniBuf = SpMemAlloc(CreateBufCnt + TotalNtDirlen + 1);
  2248. if(!(BootIniBuf)){
  2249. SpMemFree(IniCreateBufSave);
  2250. return(NULL);
  2251. }
  2252. if(FileSize) {
  2253. *FileSize = CreateBufCnt + TotalNtDirlen;
  2254. }
  2255. RtlZeroMemory(BootIniBuf,CreateBufCnt + TotalNtDirlen + 1);
  2256. RtlMoveMemory(BootIniBuf,IniCreateBufSave,CreateBufCnt + TotalNtDirlen);
  2257. BootIniBuf[CreateBufCnt + TotalNtDirlen] = 0;
  2258. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Create NT List\n%s\n",BootIniBuf));
  2259. SpMemFree(IniCreateBufSave);
  2260. return(BootIniBuf);
  2261. }
  2262. //
  2263. // NEC98
  2264. //
  2265. BOOLEAN
  2266. SppReInitializeBootVars_Nec98(
  2267. OUT PWSTR **BootVars,
  2268. OUT PWSTR *Default,
  2269. OUT PULONG Timeout
  2270. )
  2271. {
  2272. WCHAR BootIni[512];
  2273. HANDLE FileHandle;
  2274. HANDLE SectionHandle;
  2275. PVOID ViewBase;
  2276. NTSTATUS Status;
  2277. ULONG FileSize;
  2278. PUCHAR BootIniBuf;
  2279. PDISK_REGION CColonRegion;
  2280. BOOTVAR i;
  2281. PUCHAR p;
  2282. ULONG index;
  2283. PUCHAR TmpBootIniBuf;
  2284. PUCHAR pBuf;
  2285. PUCHAR pTmpBuf;
  2286. PUCHAR pArcNameA;
  2287. PUCHAR NtDir;
  2288. ULONG ArcNameLen;
  2289. ULONG NtDirLen;
  2290. WCHAR TempArcPath[256];
  2291. BOOLEAN IsChanged = FALSE;
  2292. SIZE_T Length;
  2293. HEADLESS_RSP_QUERY_INFO Response;
  2294. //
  2295. // Initialize the defaults
  2296. //
  2297. for(i = FIRSTBOOTVAR; i <= LASTBOOTVAR; i++) {
  2298. if(BootVars[i]){
  2299. SpMemFree(BootVars[i]);
  2300. }
  2301. }
  2302. for(i = FIRSTBOOTVAR; i <= LASTBOOTVAR; i++) {
  2303. BootVars[i] = (PWSTR *)SpMemAlloc( sizeof ( PWSTR * ) );
  2304. ASSERT( BootVars[i] );
  2305. *BootVars[i] = NULL;
  2306. }
  2307. *Default = NULL;
  2308. *Timeout = DEFAULT_TIMEOUT;
  2309. //
  2310. // Just clear BOOTVARS[] when fresh setup.
  2311. //
  2312. if(NTUpgrade != UpgradeFull)
  2313. return TRUE;
  2314. //
  2315. // See if there is a valid C: already. If not, then silently fail.
  2316. //
  2317. #if defined(REMOTE_BOOT)
  2318. if (RemoteBootSetup && !RemoteInstallSetup) {
  2319. ASSERT(RemoteBootTargetRegion != NULL);
  2320. CColonRegion = RemoteBootTargetRegion;
  2321. } else
  2322. #endif // defined(REMOTE_BOOT)
  2323. {
  2324. CColonRegion = TargetRegion_Nec98;
  2325. }
  2326. //
  2327. // Form name of file. Boot.ini better not be on a doublespace drive.
  2328. //
  2329. ASSERT(CColonRegion->Filesystem != FilesystemDoubleSpace);
  2330. SpNtNameFromRegion(CColonRegion,BootIni,sizeof(BootIni),PartitionOrdinalCurrent);
  2331. SpConcatenatePaths(BootIni,WBOOT_INI);
  2332. //
  2333. // Open and map the file.
  2334. //
  2335. FileHandle = 0;
  2336. Status = SpOpenAndMapFile(BootIni,&FileHandle,&SectionHandle,&ViewBase,&FileSize,FALSE);
  2337. if(!NT_SUCCESS(Status)) {
  2338. return TRUE;
  2339. }
  2340. //
  2341. // Allocate a buffer for the file.
  2342. //
  2343. BootIniBuf = SpMemAlloc(FileSize+1);
  2344. ASSERT(BootIniBuf);
  2345. RtlZeroMemory(BootIniBuf, FileSize+1);
  2346. //
  2347. // Transfer boot.ini into the buffer. We do this because we also
  2348. // want to place a 0 byte at the end of the buffer to terminate
  2349. // the file.
  2350. //
  2351. // Guard the RtlMoveMemory because if we touch the memory backed by boot.ini
  2352. // and get an i/o error, the memory manager will raise an exception.
  2353. try {
  2354. RtlMoveMemory(BootIniBuf,ViewBase,FileSize);
  2355. }
  2356. except( IN_PAGE_ERROR ) {
  2357. //
  2358. // Do nothing, boot ini processing can proceed with whatever has been
  2359. // read
  2360. //
  2361. }
  2362. //
  2363. // Not needed since buffer has already been zeroed, however just do this
  2364. // just the same
  2365. //
  2366. BootIniBuf[FileSize] = 0;
  2367. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Create NT List\n%s\n",BootIniBuf));
  2368. //***
  2369. TmpBootIniBuf = SpMemAlloc(FileSize+256);
  2370. RtlZeroMemory(TmpBootIniBuf,FileSize+256);
  2371. RtlMoveMemory(TmpBootIniBuf,BootIniBuf,FileSize);
  2372. pBuf = SppFindSectionInBootIni(BootIniBuf,BOOTINI_OS_SECTION);
  2373. pTmpBuf = SppFindSectionInBootIni(TmpBootIniBuf,BOOTINI_OS_SECTION);
  2374. if (pBuf && pTmpBuf) {
  2375. while( *pBuf && (pBuf < BootIniBuf+FileSize-(sizeof("C:\\")-1)) ) {
  2376. if((!_strnicmp(pBuf,"C:\\",sizeof("C:\\")-1))||
  2377. (!_strnicmp(pBuf,"c:\\",sizeof("c:\\")-1))) {
  2378. ArcNameLen = 0;
  2379. pArcNameA = NULL;
  2380. p = strchr(pBuf+3,'='); // *(pBuf+3) == '\\'
  2381. if((p != pBuf+3) && (*p == '=')) {
  2382. NtDirLen = (ULONG)(p - (pBuf+3));
  2383. NtDir = SpMemAlloc(NtDirLen+1);
  2384. RtlZeroMemory(NtDir,NtDirLen+1);
  2385. RtlMoveMemory(NtDir,pBuf+3,NtDirLen);
  2386. if(SpIsNtInDirectory(TargetRegion_Nec98,SpToUnicode(NtDir))){
  2387. SpArcNameFromRegion(TargetRegion_Nec98,
  2388. TempArcPath,
  2389. sizeof(TempArcPath),
  2390. PartitionOrdinalOriginal,
  2391. PrimaryArcPath
  2392. );
  2393. if(pArcNameA=SpToOem(TempArcPath)) {
  2394. ArcNameLen = strlen(pArcNameA);
  2395. RtlMoveMemory(pTmpBuf,pArcNameA,ArcNameLen);
  2396. pBuf += 2;
  2397. pTmpBuf += ArcNameLen;
  2398. if( !IsChanged)
  2399. IsChanged = TRUE;
  2400. SpMemFree(NtDir);
  2401. continue;
  2402. }
  2403. }
  2404. SpMemFree(NtDir);
  2405. }
  2406. }
  2407. *pTmpBuf = *pBuf;
  2408. pBuf++;
  2409. pTmpBuf++;
  2410. }
  2411. }
  2412. if (IsChanged) {
  2413. if (pTmpBuf) {
  2414. *pTmpBuf = 0;
  2415. }
  2416. SpMemFree(BootIniBuf);
  2417. BootIniBuf = TmpBootIniBuf;
  2418. TmpBootIniBuf = (PUCHAR)NULL;
  2419. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL,
  2420. "SETUP: Create New NT List\n%s\n",BootIniBuf));
  2421. } else {
  2422. SpMemFree(TmpBootIniBuf);
  2423. TmpBootIniBuf = (PUCHAR)NULL;
  2424. }
  2425. //
  2426. // Cleanup
  2427. //
  2428. SpUnmapFile(SectionHandle,ViewBase);
  2429. ZwClose(FileHandle);
  2430. //
  2431. // Do the actual processing of the file.
  2432. //
  2433. SppProcessBootIni(BootIniBuf, BootVars, Default, Timeout);
  2434. //
  2435. // Scan the Buffer to see if there is a DefSwitches line,
  2436. // to move into new boot.ini in the [boot loader] section.
  2437. // If no DefSwitches, just point to a null string to be moved.
  2438. //
  2439. DefSwitches[0] = '\0';
  2440. for(p=BootIniBuf; *p && (p < BootIniBuf+FileSize-(sizeof("DefSwitches")-1)); p++) {
  2441. if(!_strnicmp(p,"DefSwitches",sizeof("DefSwitches")-1)) {
  2442. index = 0;
  2443. while ((*p != '\r') && (*p != '\n') && *p && (index < sizeof(DefSwitches)-4)) {
  2444. DefSwitches[index++] = *p++;
  2445. }
  2446. DefSwitches[index++] = '\r';
  2447. DefSwitches[index++] = '\n';
  2448. DefSwitches[index] = '\0';
  2449. break;
  2450. }
  2451. }
  2452. //
  2453. // Now add any headless parameters to the default switches.
  2454. //
  2455. Length = sizeof(HEADLESS_RSP_QUERY_INFO);
  2456. Status = HeadlessDispatch(HeadlessCmdQueryInformation,
  2457. NULL,
  2458. 0,
  2459. &Response,
  2460. &Length
  2461. );
  2462. if (NT_SUCCESS(Status) &&
  2463. (Response.PortType == HeadlessSerialPort) &&
  2464. Response.Serial.TerminalAttached) {
  2465. if (Response.Serial.UsedBiosSettings) {
  2466. p = "redirect=UseBiosSettings\r\n";
  2467. } else {
  2468. switch (Response.Serial.TerminalPort) {
  2469. case ComPort1:
  2470. p = "redirect=com1\r\n";
  2471. break;
  2472. case ComPort2:
  2473. p = "redirect=com2\r\n";
  2474. break;
  2475. case ComPort3:
  2476. p = "redirect=com3\r\n";
  2477. break;
  2478. case ComPort4:
  2479. p = "redirect=com4\r\n";
  2480. break;
  2481. default:
  2482. ASSERT(0);
  2483. p = NULL;
  2484. break;
  2485. }
  2486. }
  2487. if (p != NULL) {
  2488. strcat(DefSwitches, p);
  2489. }
  2490. }
  2491. SpMemFree(BootIniBuf);
  2492. return( TRUE );
  2493. }
  2494. //
  2495. // NEC98
  2496. //
  2497. NTSTATUS
  2498. SppRestoreBootCode(
  2499. VOID
  2500. )
  2501. {
  2502. //
  2503. // Restore previous OS boot code to boot sector from bootsect.dos.
  2504. //
  2505. WCHAR p1[256] = {0};
  2506. PUCHAR BootSectBuf;
  2507. PUCHAR BootCodeBuf;
  2508. HANDLE FileHandle;
  2509. HANDLE SectionHandle;
  2510. PVOID ViewBase;
  2511. ULONG FileSize;
  2512. NTSTATUS Status;
  2513. PDISK_REGION SystemRegion;
  2514. //
  2515. // add some code to determine bytes per sector.
  2516. //
  2517. ULONG BytesPerSector;
  2518. // BytesPerSector = HardDisks[SystemPartitionRegion->DiskNumber].Geometry.BytesPerSector;
  2519. BytesPerSector = 512; //???
  2520. wcscpy(p1,NtBootDevicePath);
  2521. SpConcatenatePaths(p1,L"bootsect.dos");
  2522. FileHandle = 0;
  2523. Status = SpOpenAndMapFile(p1,&FileHandle,&SectionHandle,&ViewBase,&FileSize,FALSE);
  2524. if(!NT_SUCCESS(Status)) {
  2525. return(Status);
  2526. }
  2527. BootCodeBuf = SpMemAlloc(FileSize+1);
  2528. try {
  2529. RtlMoveMemory(BootCodeBuf,ViewBase,FileSize);
  2530. }
  2531. except( IN_PAGE_ERROR ) {
  2532. //
  2533. // Do nothing, boot ini processing can proceed with whatever has been
  2534. // read
  2535. //
  2536. }
  2537. Status = pSpBootCodeIo(
  2538. NtBootDevicePath,
  2539. NULL,
  2540. 2048,
  2541. &BootSectBuf,
  2542. FILE_OPEN,
  2543. FALSE,
  2544. 0,
  2545. BytesPerSector
  2546. );
  2547. if(!NT_SUCCESS(Status)) {
  2548. SpMemFree(BootCodeBuf);
  2549. SpUnmapFile(SectionHandle,ViewBase);
  2550. ZwClose(FileHandle);
  2551. return(Status);
  2552. }
  2553. //
  2554. // Keep dirty flag in FAT BPB, to avoid confusion in disk management.
  2555. //
  2556. SystemRegion = SpRegionFromNtName(NtBootDevicePath, PartitionOrdinalCurrent);
  2557. if(SystemRegion && (SystemRegion->Filesystem != FilesystemNtfs)) {
  2558. BootCodeBuf[0x25] = BootSectBuf[0x25]; // Dirty flag in BPB.
  2559. }
  2560. RtlMoveMemory(BootSectBuf,BootCodeBuf,512);
  2561. pSpBootCodeIo(
  2562. NtBootDevicePath,
  2563. NULL,
  2564. 2048,
  2565. &BootSectBuf,
  2566. FILE_OPEN,
  2567. TRUE,
  2568. 0,
  2569. BytesPerSector
  2570. );
  2571. SpMemFree(BootCodeBuf);
  2572. SpMemFree(BootSectBuf);
  2573. SpUnmapFile(SectionHandle,ViewBase);
  2574. ZwClose(FileHandle);
  2575. return(Status);
  2576. }