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.

1248 lines
32 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Copyright (c) 1999 Microsoft Corporation
  4. // All rights reserved.
  5. //
  6. // File Name:
  7. // makebt32.c
  8. //
  9. // Description:
  10. // This program copies the images of the 4 Windows NT setup disks to
  11. // floppy disk so the user can boot their system with them.
  12. //
  13. // All characters and strings are wide (UNICODE). This file needs to be
  14. // compiled with UNICODE and _UNICODE defined.
  15. //
  16. // Assumptions:
  17. // This program will only run on NT 3.51 or later. This is a result of
  18. // the CreateFile function call. It is not available on DOS, Windows 3.1
  19. // or Windows 9x.
  20. //
  21. // The floppy disk images are in the current dir and named CDBOOT1.IMG,
  22. // CDBOOT2.IMG, CDBOOT3.IMG and CDBOOT4.IMG.
  23. //
  24. // Please note that there are a lot of places where I call exit() without
  25. // freeing memory for strings I have allocated. This version of the
  26. // program only runs on NT so when the process exits it frees all its
  27. // memory so it is not a concern that I may not call free() on some memory.
  28. //
  29. //----------------------------------------------------------------------------
  30. #include <windows.h>
  31. #include <setupapi.h>
  32. #include <winioctl.h>
  33. #include <conio.h>
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. #include "resource.h"
  37. //
  38. // Constants
  39. //
  40. #define MAKEBOOT_MAX_STRING_LEN 1024
  41. #define BYTES_PER_SECTOR 512
  42. #define SECTORS_PER_TRACK 18
  43. #define TRACK_SIZE SECTORS_PER_TRACK * BYTES_PER_SECTOR
  44. #define TRACKS_ON_DISK 80 * 2 // * 2 because it is double-sided
  45. #define MAX_DISK_LABEL_LENGTH 256
  46. #define MAX_INILINE_LENGTH 1023
  47. #define ENTER_KEY 13
  48. #define ESC_KEY 27
  49. #define NT_IMAGE_1_NAME L"CDBOOT1.IMG"
  50. #define NT_IMAGE_2_NAME L"CDBOOT2.IMG"
  51. #define NT_IMAGE_3_NAME L"CDBOOT3.IMG"
  52. #define NT_IMAGE_4_NAME L"CDBOOT4.IMG"
  53. #define NT_IMAGE_5_NAME L"CDBOOT5.IMG"
  54. #define NT_IMAGE_6_NAME L"CDBOOT6.IMG"
  55. #define NT_IMAGE_7_NAME L"CDBOOT7.IMG"
  56. #define NUMBER_OF_ASCII_WHEEL_SYMBOLS 4
  57. const WCHAR rgAsciiWheel[NUMBER_OF_ASCII_WHEEL_SYMBOLS] = { '|', '/', '-', '\\' };
  58. //
  59. // Function prototypes
  60. //
  61. BOOL WriteImageToFloppy( WCHAR *szFileName, WCHAR *DrivePath );
  62. VOID PrintErrorMessage( VOID );
  63. VOID PrintErrorWrongDriveType( UINT iDriveType );
  64. BOOL IsDriveLargeEnough( WCHAR *DrivePath );
  65. VOID FreeStrings( VOID );
  66. VOID LoadStrings( VOID );
  67. INT DoImageFilesExist( VOID ) ;
  68. VOID CleanUp( HANDLE *hFloppyDrive, HANDLE *hFloppyImage );
  69. BOOL DoesUserWantToTryCopyAgain( VOID );
  70. LPWSTR MyLoadString( UINT StringId );
  71. VOID print( WCHAR *szFirstString, ... );
  72. BOOL DoesFileExist( LPWSTR lpFileName );
  73. VOID PressAnyKeyToContinue( VOID );
  74. void SetFarEastThread();
  75. void ConsolePrint( WCHAR *szFirstString, ... );
  76. //
  77. // Global Strings
  78. //
  79. WCHAR *StrOutOfMemory = NULL;
  80. WCHAR *StrComplete = NULL;
  81. WCHAR *StrNtVersionName = NULL;
  82. WCHAR *StrCanNotFindFile = NULL;
  83. WCHAR *StrDiskLabel1 = NULL;
  84. WCHAR *StrDiskLabel2 = NULL;
  85. WCHAR *StrDiskLabel3 = NULL;
  86. WCHAR *StrDiskLabel4 = NULL;
  87. WCHAR *StrDiskLabel5 = NULL;
  88. WCHAR *StrDiskLabel6 = NULL;
  89. WCHAR *StrDiskLabel7 = NULL;
  90. WCHAR *StrStars = NULL;
  91. WCHAR *StrExplanationLine1 = NULL;
  92. WCHAR *StrExplanationLine2 = NULL;
  93. WCHAR *StrExplanationLine3 = NULL;
  94. WCHAR *StrExplanationLine4 = NULL;
  95. WCHAR *StrInsertFirstDiskLine1 = NULL;
  96. WCHAR *StrInsertFirstDiskLine2 = NULL;
  97. WCHAR *StrInsertAnotherDiskLine1 = NULL;
  98. WCHAR *StrInsertAnotherDiskLine2 = NULL;
  99. WCHAR *StrPressAnyKeyWhenReady = NULL;
  100. WCHAR *StrCompletedSuccessfully = NULL;
  101. //----------------------------------------------------------------------------
  102. //
  103. // Function: wmain
  104. //
  105. // Purpose: Instructs user to insert floppy disks to be copied and performs
  106. // the copy.
  107. //
  108. // Arguments: int argc - standard program argument, count of the command line args
  109. // char *argv[] - standard program argument, the 2nd argument is the
  110. // floppy drive to copy the images to.
  111. //
  112. // Returns: INT - zero on successful program completion
  113. // - non-zero on unsuccessful program completion, program
  114. // terminated because of an error
  115. //
  116. //----------------------------------------------------------------------------
  117. INT __cdecl
  118. wmain( INT argc, WCHAR *argv[] )
  119. {
  120. WCHAR *szOsName;
  121. WCHAR DriveLetter;
  122. WCHAR Drive[10];
  123. WCHAR DrivePath[10];
  124. UINT iDriveType;
  125. BOOL bTryAgain;
  126. szOsName = _wgetenv( L"OS" );
  127. //
  128. // Make sure we are on NT.
  129. //
  130. if( ( szOsName == NULL ) || ( _wcsicmp( szOsName, L"Windows_NT" ) != 0 ) )
  131. {
  132. // ******
  133. // This string cannot be localized because if we are not on NT then
  134. // we don't have wide chars.
  135. //
  136. printf( "This program only runs on Windows NT, Windows 2000 and Windows XP.\n" );
  137. exit( 1 );
  138. }
  139. SetFarEastThread();
  140. //
  141. // Load all of the strings from the resource file
  142. //
  143. LoadStrings();
  144. //
  145. // Don't allow the system to do any pop-ups. We will handle all
  146. // error messages
  147. //
  148. SetErrorMode( SEM_FAILCRITICALERRORS );
  149. print( L"" );
  150. print( StrStars );
  151. print( StrExplanationLine1 );
  152. print( StrExplanationLine2, StrNtVersionName );
  153. print( StrExplanationLine3 );
  154. print( StrExplanationLine4 );
  155. print( L"" );
  156. //
  157. // If they didn't specified the floppy drive on the command line then
  158. // prompt them for it.
  159. //
  160. if( argc == 1 )
  161. {
  162. WCHAR *StrSpecifyFloppyDrive = MyLoadString( IDS_SPECIFY_FLOPPY_DRIVE );
  163. ConsolePrint( L"%s", StrSpecifyFloppyDrive );
  164. DriveLetter = (WCHAR)_getche();
  165. ConsolePrint( L"\n\n" );
  166. free( StrSpecifyFloppyDrive );
  167. }
  168. else
  169. {
  170. DriveLetter = argv[1][0];
  171. }
  172. //
  173. // Make sure the character they entered is a possible drive letter
  174. //
  175. if( ! isalpha( DriveLetter ) )
  176. {
  177. WCHAR *StrInvalidDriveLetter = MyLoadString( IDS_INVALID_DRIVE_LETTER );
  178. ConsolePrint( L"%s\n", StrInvalidDriveLetter );
  179. free( StrInvalidDriveLetter );
  180. exit( 1 );
  181. }
  182. //
  183. // Make sure all the image files are in the current directory.
  184. //
  185. if( ! DoImageFilesExist() )
  186. {
  187. exit( 1 );
  188. }
  189. //
  190. // Make the char DriveLetter into a string
  191. //
  192. Drive[0] = DriveLetter;
  193. Drive[1] = L'\0';
  194. //
  195. // Build the drive path. For example the a: drive looks like \\.\a:
  196. //
  197. swprintf( DrivePath, L"\\\\.\\%c:", DriveLetter );
  198. //
  199. // Make sure the drive is a floppy drive
  200. //
  201. iDriveType = GetDriveType( wcscat( Drive, L":\\" ) );
  202. if( iDriveType != DRIVE_REMOVABLE )
  203. {
  204. PrintErrorWrongDriveType( iDriveType );
  205. exit( 1 );
  206. }
  207. //
  208. // Make sure the drive can hold at least 1.44 MB
  209. //
  210. if( ! IsDriveLargeEnough( DrivePath ) )
  211. {
  212. WCHAR *Str144NotSupported = MyLoadString( IDS_144_NOT_SUPPORTED );
  213. ConsolePrint( L"%s\n", Str144NotSupported );
  214. free( Str144NotSupported );
  215. exit( 1 );
  216. }
  217. print( StrInsertFirstDiskLine1, DriveLetter );
  218. print( StrInsertFirstDiskLine2, StrDiskLabel1 );
  219. PressAnyKeyToContinue();
  220. while( ! WriteImageToFloppy( NT_IMAGE_1_NAME, DrivePath ) )
  221. {
  222. bTryAgain = DoesUserWantToTryCopyAgain();
  223. if( ! bTryAgain )
  224. {
  225. exit( 1 );
  226. }
  227. }
  228. print( L"" );
  229. print( StrInsertAnotherDiskLine1, DriveLetter );
  230. print( StrInsertAnotherDiskLine2, StrDiskLabel2 );
  231. PressAnyKeyToContinue();
  232. while( ! WriteImageToFloppy( NT_IMAGE_2_NAME, DrivePath ) )
  233. {
  234. bTryAgain = DoesUserWantToTryCopyAgain();
  235. if( ! bTryAgain )
  236. {
  237. exit( 1 );
  238. }
  239. }
  240. print( L"" );
  241. print( StrInsertAnotherDiskLine1, DriveLetter );
  242. print( StrInsertAnotherDiskLine2, StrDiskLabel3 );
  243. PressAnyKeyToContinue();
  244. while( ! WriteImageToFloppy( NT_IMAGE_3_NAME, DrivePath ) )
  245. {
  246. bTryAgain = DoesUserWantToTryCopyAgain();
  247. if( ! bTryAgain )
  248. {
  249. exit( 1 );
  250. }
  251. }
  252. print( L"" );
  253. print( StrInsertAnotherDiskLine1, DriveLetter );
  254. print( StrInsertAnotherDiskLine2, StrDiskLabel4 );
  255. PressAnyKeyToContinue();
  256. while( ! WriteImageToFloppy( NT_IMAGE_4_NAME, DrivePath ) )
  257. {
  258. bTryAgain = DoesUserWantToTryCopyAgain();
  259. if( ! bTryAgain )
  260. {
  261. exit( 1 );
  262. }
  263. }
  264. print( L"" );
  265. print( StrInsertAnotherDiskLine1, DriveLetter );
  266. print( StrInsertAnotherDiskLine2, StrDiskLabel5 );
  267. PressAnyKeyToContinue();
  268. while( ! WriteImageToFloppy( NT_IMAGE_5_NAME, DrivePath ) )
  269. {
  270. bTryAgain = DoesUserWantToTryCopyAgain();
  271. if( ! bTryAgain )
  272. {
  273. exit( 1 );
  274. }
  275. }
  276. print( L"" );
  277. print( StrInsertAnotherDiskLine1, DriveLetter );
  278. print( StrInsertAnotherDiskLine2, StrDiskLabel6 );
  279. PressAnyKeyToContinue();
  280. while( ! WriteImageToFloppy( NT_IMAGE_6_NAME, DrivePath ) )
  281. {
  282. bTryAgain = DoesUserWantToTryCopyAgain();
  283. if( ! bTryAgain )
  284. {
  285. exit( 1 );
  286. }
  287. }
  288. print( L"" );
  289. print( StrInsertAnotherDiskLine1, DriveLetter );
  290. print( StrInsertAnotherDiskLine2, StrDiskLabel7 );
  291. PressAnyKeyToContinue();
  292. while( ! WriteImageToFloppy( NT_IMAGE_7_NAME, DrivePath ) )
  293. {
  294. bTryAgain = DoesUserWantToTryCopyAgain();
  295. if( ! bTryAgain )
  296. {
  297. exit( 1 );
  298. }
  299. }
  300. print( L"" );
  301. print( StrCompletedSuccessfully );
  302. print( StrStars );
  303. FreeStrings();
  304. return( 0 );
  305. }
  306. //----------------------------------------------------------------------------
  307. //
  308. // Function: WriteImageToFloppy
  309. //
  310. // Purpose: Writes an image file to a floppy disk. Handles all error
  311. // reporting to the user.
  312. //
  313. // Arguments: char *szFileName - filename to write to the floppy
  314. // char *DrivePath - drive path of the floppy to write to, it is of
  315. // the form \\.\x where x is the drive letter
  316. //
  317. // Returns: BOOL - TRUE if image written to floppy properly
  318. // FALSE if there were errors
  319. //
  320. //----------------------------------------------------------------------------
  321. BOOL
  322. WriteImageToFloppy( WCHAR *szFileName, WCHAR *DrivePath )
  323. {
  324. INT iCurrentTrack;
  325. INT cBytesRead = 0;
  326. INT cBytesWritten = 0;
  327. INT iPercentComplete = 0;
  328. INT iWheelPosition = 0;
  329. HANDLE hFloppyImage = NULL;
  330. HANDLE hFloppyDrive = NULL;
  331. char TrackBuffer[TRACK_SIZE];
  332. hFloppyImage = CreateFile( szFileName,
  333. GENERIC_READ,
  334. FILE_SHARE_READ | FILE_SHARE_WRITE,
  335. NULL,
  336. OPEN_EXISTING,
  337. FILE_FLAG_SEQUENTIAL_SCAN,
  338. NULL );
  339. if( hFloppyImage == INVALID_HANDLE_VALUE )
  340. {
  341. PrintErrorMessage();
  342. return( FALSE );
  343. }
  344. hFloppyDrive = CreateFile( DrivePath,
  345. GENERIC_WRITE,
  346. 0,
  347. NULL,
  348. OPEN_EXISTING,
  349. FILE_FLAG_SEQUENTIAL_SCAN,
  350. NULL );
  351. if( hFloppyDrive == INVALID_HANDLE_VALUE )
  352. {
  353. PrintErrorMessage();
  354. CleanUp( &hFloppyDrive, &hFloppyImage );
  355. return( FALSE );
  356. }
  357. for( iCurrentTrack = 0; iCurrentTrack < TRACKS_ON_DISK; iCurrentTrack++ )
  358. {
  359. if( ! ReadFile( hFloppyImage, TrackBuffer, TRACK_SIZE, &cBytesRead, NULL ) )
  360. {
  361. PrintErrorMessage();
  362. CleanUp( &hFloppyDrive, &hFloppyImage );
  363. return( FALSE );
  364. }
  365. if( ! WriteFile( hFloppyDrive, TrackBuffer, TRACK_SIZE, &cBytesWritten, NULL ) )
  366. {
  367. PrintErrorMessage();
  368. CleanUp( &hFloppyDrive, &hFloppyImage );
  369. return( FALSE );
  370. }
  371. iPercentComplete = (int) ( ( (double) (iCurrentTrack) / (double) (TRACKS_ON_DISK) ) * 100.0 );
  372. ConsolePrint( L"%c %3d%% %s.\r",
  373. rgAsciiWheel[iWheelPosition],
  374. iPercentComplete,
  375. StrComplete );
  376. //
  377. // Advance the ASCII wheel
  378. //
  379. iWheelPosition++;
  380. if( iWheelPosition >= NUMBER_OF_ASCII_WHEEL_SYMBOLS )
  381. {
  382. iWheelPosition = 0;
  383. }
  384. }
  385. //
  386. // We are done copying the disk so force it to read 100% and get rid of
  387. // the ascii wheel symbol.
  388. //
  389. ConsolePrint( L" 100%% %s. \n", StrComplete );
  390. //
  391. // Free allocated resources
  392. //
  393. CleanUp( &hFloppyDrive, &hFloppyImage );
  394. return TRUE;
  395. }
  396. //----------------------------------------------------------------------------
  397. //
  398. // Function: PrintErrorMessage
  399. //
  400. // Purpose: To get the last system error, look up what it is and print it out
  401. // to the user.
  402. //
  403. // Arguments: VOID
  404. //
  405. // Returns: VOID
  406. //
  407. //----------------------------------------------------------------------------
  408. VOID
  409. PrintErrorMessage( VOID )
  410. {
  411. LPVOID lpMsgBuf = NULL;
  412. if(!FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
  413. FORMAT_MESSAGE_FROM_SYSTEM |
  414. FORMAT_MESSAGE_IGNORE_INSERTS,
  415. NULL,
  416. GetLastError(),
  417. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  418. (LPWSTR) &lpMsgBuf,
  419. 0,
  420. NULL )) {
  421. // Great. Not enough memory to format an error message.
  422. ConsolePrint( L"\nNot enough memory to format error message.\n" );
  423. if( lpMsgBuf )
  424. LocalFree( lpMsgBuf );
  425. }
  426. else {
  427. ConsolePrint( L"\n%s\n", (LPCWSTR)lpMsgBuf );
  428. LocalFree( lpMsgBuf );
  429. }
  430. }
  431. //----------------------------------------------------------------------------
  432. //
  433. // Function: PrintErrorWrongDriveType
  434. //
  435. // Purpose: To translate a drive type error code into a message and print it
  436. //
  437. // Arguments: UINT iDriveType - drive type error code to look-up
  438. //
  439. // Returns: VOID
  440. //
  441. //----------------------------------------------------------------------------
  442. VOID
  443. PrintErrorWrongDriveType( UINT iDriveType )
  444. {
  445. if( iDriveType == DRIVE_NO_ROOT_DIR )
  446. {
  447. WCHAR *StrNoRootDir = MyLoadString( IDS_NO_ROOT_DIR );
  448. ConsolePrint( L"\n%s\n", StrNoRootDir );
  449. free( StrNoRootDir );
  450. }
  451. else
  452. {
  453. WCHAR *StrDriveNotFloppy = MyLoadString( IDS_DRIVE_NOT_FL0PPY );
  454. ConsolePrint( L"\n%s\n", StrDriveNotFloppy );
  455. free( StrDriveNotFloppy );
  456. }
  457. }
  458. //----------------------------------------------------------------------------
  459. //
  460. // Function: IsDriveLargeEnough
  461. //
  462. // Purpose: To determine if the floppy drive supports 1.44 MB or larger disks
  463. //
  464. // Arguments: char* DrivePath - drive path of the floppy to write to, it is of
  465. // the form \\.\x where x is the drive letter
  466. //
  467. // Returns: BOOL - TRUE if the drive supports 1.44 MB or greater, FALSE if not
  468. //
  469. //----------------------------------------------------------------------------
  470. BOOL
  471. IsDriveLargeEnough( WCHAR *DrivePath )
  472. {
  473. UINT i;
  474. HANDLE hFloppyDrive;
  475. DISK_GEOMETRY SupportedGeometry[20];
  476. DWORD SupportedGeometryCount;
  477. DWORD ReturnedByteCount;
  478. hFloppyDrive = CreateFile( DrivePath,
  479. 0,
  480. FILE_SHARE_READ,
  481. NULL,
  482. OPEN_ALWAYS,
  483. 0,
  484. NULL );
  485. if( hFloppyDrive == INVALID_HANDLE_VALUE )
  486. {
  487. PrintErrorMessage();
  488. exit( 1 );
  489. }
  490. if( DeviceIoControl( hFloppyDrive,
  491. IOCTL_DISK_GET_MEDIA_TYPES,
  492. NULL,
  493. 0,
  494. SupportedGeometry,
  495. sizeof( SupportedGeometry ),
  496. &ReturnedByteCount,
  497. NULL ) )
  498. {
  499. SupportedGeometryCount = ( ReturnedByteCount / sizeof( DISK_GEOMETRY ) );
  500. }
  501. else
  502. {
  503. SupportedGeometryCount = 0;
  504. }
  505. CloseHandle( hFloppyDrive );
  506. for( i = 0; i < SupportedGeometryCount; i++ )
  507. {
  508. if( SupportedGeometry[i].MediaType == F3_1Pt44_512 )
  509. {
  510. //
  511. // This drive supports 3.5, 1.44MB, 512 bytes/sector.
  512. //
  513. return( TRUE );
  514. }
  515. }
  516. return( FALSE );
  517. }
  518. //----------------------------------------------------------------------------
  519. //
  520. // Function: DoImageFilesExist
  521. //
  522. // Purpose: Determines if all the image files are in the current directory or
  523. // not. If an image file is missing, an error message is printed
  524. // to the user.
  525. //
  526. // Note: it detemines if a file exists by seeing if it can open it
  527. // for reading.
  528. //
  529. // Arguments: VOID
  530. //
  531. // Returns: INT -- non-zero on success, all images files exist in current dir
  532. // zero on failure, 1 or more image files do not exist
  533. //
  534. //----------------------------------------------------------------------------
  535. INT
  536. DoImageFilesExist( VOID )
  537. {
  538. BOOL bAllFilesExist = TRUE;
  539. if( ! DoesFileExist( NT_IMAGE_1_NAME ) )
  540. {
  541. print( StrCanNotFindFile, NT_IMAGE_1_NAME );
  542. bAllFilesExist = FALSE;
  543. }
  544. if( ! DoesFileExist( NT_IMAGE_2_NAME ) )
  545. {
  546. print( StrCanNotFindFile, NT_IMAGE_2_NAME );
  547. bAllFilesExist = FALSE;
  548. }
  549. if( ! DoesFileExist( NT_IMAGE_3_NAME ) )
  550. {
  551. print( StrCanNotFindFile, NT_IMAGE_3_NAME );
  552. bAllFilesExist = FALSE;
  553. }
  554. if( ! DoesFileExist( NT_IMAGE_4_NAME ) )
  555. {
  556. print( StrCanNotFindFile, NT_IMAGE_4_NAME );
  557. bAllFilesExist = FALSE;
  558. }
  559. if( ! DoesFileExist( NT_IMAGE_5_NAME ) )
  560. {
  561. print( StrCanNotFindFile, NT_IMAGE_5_NAME );
  562. bAllFilesExist = FALSE;
  563. }
  564. if( ! DoesFileExist( NT_IMAGE_6_NAME ) )
  565. {
  566. print( StrCanNotFindFile, NT_IMAGE_6_NAME );
  567. bAllFilesExist = FALSE;
  568. }
  569. if( ! DoesFileExist( NT_IMAGE_7_NAME ) )
  570. {
  571. print( StrCanNotFindFile, NT_IMAGE_7_NAME );
  572. bAllFilesExist = FALSE;
  573. }
  574. if( bAllFilesExist )
  575. {
  576. return( 1 );
  577. }
  578. else
  579. {
  580. return( 0 );
  581. }
  582. }
  583. //----------------------------------------------------------------------------
  584. //
  585. // Function: CleanUp
  586. //
  587. // Purpose: Closes open handles. This function should be called just before
  588. // exiting the program.
  589. //
  590. // Arguments: HANDLE *hFloppyDrive - the floppy disk handle to be closed
  591. // HANDLE *hFloppyImage - the floppy image file handle to be closed
  592. //
  593. // Returns: VOID
  594. //
  595. //----------------------------------------------------------------------------
  596. VOID
  597. CleanUp( HANDLE *hFloppyDrive, HANDLE *hFloppyImage )
  598. {
  599. if( *hFloppyDrive )
  600. {
  601. CloseHandle( *hFloppyDrive );
  602. *hFloppyDrive = NULL;
  603. }
  604. if( *hFloppyImage )
  605. {
  606. CloseHandle( *hFloppyImage );
  607. *hFloppyImage = NULL;
  608. }
  609. }
  610. //----------------------------------------------------------------------------
  611. //
  612. // Function: FreeStrings
  613. //
  614. // Purpose: Deallocate the memory for all the strings.
  615. //
  616. // Arguments: VOID
  617. //
  618. // Returns: VOID
  619. //
  620. //----------------------------------------------------------------------------
  621. VOID
  622. FreeStrings( VOID )
  623. {
  624. free( StrNtVersionName );
  625. free( StrDiskLabel1 );
  626. free( StrDiskLabel2 );
  627. free( StrDiskLabel3 );
  628. free( StrDiskLabel4 );
  629. free( StrDiskLabel5 );
  630. free( StrDiskLabel6 );
  631. free( StrDiskLabel7 );
  632. free( StrStars );
  633. free( StrExplanationLine1 );
  634. free( StrExplanationLine2 );
  635. free( StrExplanationLine3 );
  636. free( StrExplanationLine4 );
  637. free( StrInsertFirstDiskLine1 );
  638. free( StrInsertFirstDiskLine2 );
  639. free( StrInsertAnotherDiskLine1 );
  640. free( StrInsertAnotherDiskLine2 );
  641. free( StrPressAnyKeyWhenReady );
  642. free( StrCompletedSuccessfully );
  643. free( StrComplete );
  644. free( StrCanNotFindFile );
  645. free( StrOutOfMemory );
  646. }
  647. //----------------------------------------------------------------------------
  648. //
  649. // Function: LoadStrings
  650. //
  651. // Purpose: Load the string constants from the string table.
  652. //
  653. // Arguments: VOID
  654. //
  655. // Returns: VOID
  656. //
  657. //----------------------------------------------------------------------------
  658. VOID
  659. LoadStrings( VOID )
  660. {
  661. INT Length;
  662. //
  663. // Loading the Out of Memory string is a little tricky because of the
  664. // error that can occur while loading it.
  665. //
  666. // For the other strings, just call the MyLoadString function to do
  667. // the work
  668. //
  669. StrOutOfMemory = (WCHAR *) malloc( MAKEBOOT_MAX_STRING_LEN * sizeof(WCHAR) + 1 );
  670. if( StrOutOfMemory == NULL )
  671. {
  672. //
  673. // Can't localize this string
  674. //
  675. ConsolePrint( L"\nOut of memory. Please free more memory and run this program again.\n" );
  676. exit( 1 );
  677. }
  678. Length = LoadString( NULL,
  679. IDS_OUT_OF_MEMORY,
  680. StrOutOfMemory,
  681. MAKEBOOT_MAX_STRING_LEN );
  682. if( ! Length )
  683. {
  684. //
  685. // Can't localize this string
  686. //
  687. ConsolePrint( L"Unable to load resources.\n" );
  688. exit( 1 ) ;
  689. }
  690. StrStars = MyLoadString( IDS_STARS );
  691. StrExplanationLine1 = MyLoadString( IDS_PROGRAM_EXPLANATION_LINE_1 );
  692. StrExplanationLine2 = MyLoadString( IDS_PROGRAM_EXPLANATION_LINE_2 );
  693. StrExplanationLine3 = MyLoadString( IDS_PROGRAM_EXPLANATION_LINE_3 );
  694. StrExplanationLine4 = MyLoadString( IDS_PROGRAM_EXPLANATION_LINE_4 );
  695. StrInsertFirstDiskLine1 = MyLoadString( IDS_INSERT_FIRST_DISK_LINE_1 );
  696. StrInsertFirstDiskLine2 = MyLoadString( IDS_INSERT_FIRST_DISK_LINE_2 );
  697. StrInsertAnotherDiskLine1 = MyLoadString( IDS_INSERT_ANOTHER_DISK_LINE_1 );
  698. StrInsertAnotherDiskLine2 = MyLoadString( IDS_INSERT_ANOTHER_DISK_LINE_2 );
  699. StrPressAnyKeyWhenReady = MyLoadString( IDS_PRESS_ANY_KEY_WHEN_READY );
  700. StrCompletedSuccessfully = MyLoadString( IDS_COMPLETED_SUCCESSFULLY );
  701. StrComplete = MyLoadString( IDS_COMPLETE );
  702. StrCanNotFindFile = MyLoadString( IDS_CANNOT_FIND_FILE );
  703. StrNtVersionName = MyLoadString( IDS_NT_VERSION_NAME_DEFAULT );
  704. StrDiskLabel1 = MyLoadString( IDS_DISK_LABEL_1_DEFAULT );
  705. StrDiskLabel2 = MyLoadString( IDS_DISK_LABEL_2_DEFAULT );
  706. StrDiskLabel3 = MyLoadString( IDS_DISK_LABEL_3_DEFAULT );
  707. StrDiskLabel4 = MyLoadString( IDS_DISK_LABEL_4_DEFAULT );
  708. StrDiskLabel5 = MyLoadString( IDS_DISK_LABEL_5_DEFAULT );
  709. StrDiskLabel6 = MyLoadString( IDS_DISK_LABEL_6_DEFAULT );
  710. StrDiskLabel7 = MyLoadString( IDS_DISK_LABEL_7_DEFAULT );
  711. }
  712. //----------------------------------------------------------------------------
  713. //
  714. // Function: DoesUserWantToTryCopyAgain
  715. //
  716. // Purpose: Ask the user if they want to retry to copy the image to floppy.
  717. // Get the user input and return whether to copy again or not.
  718. //
  719. // Arguments: VOID
  720. //
  721. // Returns: BOOL - TRUE if user wants to attempt to copy again
  722. // - FALSE if user does not want to attempt to copy again
  723. //
  724. //----------------------------------------------------------------------------
  725. BOOL
  726. DoesUserWantToTryCopyAgain( VOID )
  727. {
  728. INT ch;
  729. WCHAR *StrAttemptToCreateFloppyAgain = MyLoadString( IDS_ATTEMPT_TO_CREATE_FLOPPY_AGAIN );
  730. WCHAR *StrPressEnterOrEsc = MyLoadString( IDS_PRESS_ENTER_OR_ESC );
  731. //
  732. // Clear the input stream by eating all the chars until there are none
  733. // left. Print the message and then wait for a key press.
  734. //
  735. while( _kbhit() )
  736. {
  737. _getch();
  738. }
  739. do
  740. {
  741. ConsolePrint( L"%s\n", StrAttemptToCreateFloppyAgain );
  742. ConsolePrint( L"%s\n", StrPressEnterOrEsc );
  743. ch = _getch();
  744. } while( ch != ENTER_KEY && ch != ESC_KEY );
  745. if( ch == ENTER_KEY )
  746. {
  747. return( TRUE );
  748. }
  749. else
  750. {
  751. return( FALSE );
  752. }
  753. free( StrAttemptToCreateFloppyAgain );
  754. free( StrPressEnterOrEsc );
  755. }
  756. //----------------------------------------------------------------------------
  757. //
  758. // Function: PressAnyKeyToContinue
  759. //
  760. // Purpose: Print the "Press any key when ready" message and wait until the
  761. // user presses a key.
  762. //
  763. // Arguments: VOID
  764. //
  765. // Returns: VOID
  766. //
  767. //----------------------------------------------------------------------------
  768. VOID
  769. PressAnyKeyToContinue( VOID )
  770. {
  771. //
  772. // Clear the input stream by eating all the chars until there are none
  773. // left. Print the message and then wait for a key press.
  774. //
  775. while( _kbhit() )
  776. {
  777. _getch();
  778. }
  779. print( StrPressAnyKeyWhenReady );
  780. //
  781. // Spin until the keyboard is pressed
  782. //
  783. while( ! _kbhit() )
  784. {
  785. ;
  786. }
  787. }
  788. //----------------------------------------------------------------------------
  789. //
  790. // Function: MyLoadString
  791. //
  792. // Purpose: Loads a string resource given it's IDS_* and returns
  793. // a malloc'ed buffer with its contents.
  794. //
  795. // The malloc()'ed buffer must be freed with free()
  796. //
  797. // This function will either return the string or exit. It will
  798. // never return NULL or a bad pointer.
  799. //
  800. // Arguments: UINT StringId - the string ID to load
  801. //
  802. // Returns:
  803. // Pointer to buffer. An empty string is returned if the StringId
  804. // does not exist. Null is returned if out of memory.
  805. //
  806. //----------------------------------------------------------------------------
  807. LPWSTR
  808. MyLoadString( UINT StringId )
  809. {
  810. WCHAR Buffer[ MAKEBOOT_MAX_STRING_LEN ];
  811. WCHAR *String = NULL;
  812. UINT Length;
  813. Length = LoadString( NULL,
  814. StringId,
  815. Buffer,
  816. MAKEBOOT_MAX_STRING_LEN );
  817. if( Length )
  818. {
  819. String = (WCHAR *) malloc( Length * sizeof(WCHAR) + 1 );
  820. if( String == NULL )
  821. {
  822. ConsolePrint( L"%s\n", StrOutOfMemory );
  823. exit( 1 );
  824. }
  825. else
  826. {
  827. wcscpy( String, Buffer );
  828. String[Length] = L'\0';
  829. return( String );
  830. }
  831. }
  832. else
  833. {
  834. //
  835. // Can't load the string so exit
  836. // NOTE: this string will not be localized
  837. //
  838. ConsolePrint( L"Unable to load resources.\n" );
  839. exit( 1 );
  840. }
  841. }
  842. //----------------------------------------------------------------------------
  843. //
  844. // Function: print
  845. //
  846. // Purpose: To print out strings to the user. Useful when there is
  847. // embedded formatting characters in a string that was loaded from
  848. // a string table.
  849. //
  850. // Arguments: szFirstString - the string that contains the embedded formatting
  851. // characters (such as %s, %c, etc.)
  852. // ... - variable number of arguments that correspond to each
  853. // formatting character
  854. //
  855. // Returns: VOID
  856. //
  857. //----------------------------------------------------------------------------
  858. VOID
  859. print( WCHAR *szFirstString, ... )
  860. {
  861. WCHAR OutputBuffer[MAKEBOOT_MAX_STRING_LEN];
  862. va_list arglist;
  863. va_start( arglist, szFirstString );
  864. wvsprintf( OutputBuffer, szFirstString, arglist );
  865. ConsolePrint( L"%s\n", OutputBuffer );
  866. va_end( arglist );
  867. }
  868. //----------------------------------------------------------------------------
  869. //
  870. // Function: DoesFileExist
  871. //
  872. // Purpose: To determine whether a file exists or not
  873. //
  874. // Arguments: LPWSTR lpFileName - filename to see if it exists or not
  875. //
  876. // Returns: BOOL - TRUE if the file exists
  877. // - FALSE if the file does not exist
  878. //
  879. //----------------------------------------------------------------------------
  880. BOOL
  881. DoesFileExist( LPWSTR lpFileName )
  882. {
  883. DWORD dwAttribs = GetFileAttributes( lpFileName );
  884. if( dwAttribs == (DWORD) -1 )
  885. {
  886. return( FALSE );
  887. }
  888. if( dwAttribs & FILE_ATTRIBUTE_DIRECTORY )
  889. {
  890. return( FALSE );
  891. }
  892. return( TRUE );
  893. }
  894. //----------------------------------------------------------------------------
  895. //
  896. // Function: IsDBCSConsole
  897. //
  898. // Purpose: To determine whether a DBC console or not
  899. //
  900. // Arguments: None
  901. //
  902. // Returns: BOOL - TRUE if FE console codepage
  903. // - FALSE if not FE console codepage
  904. //
  905. //----------------------------------------------------------------------------
  906. BOOL
  907. IsDBCSCodePage(UINT CodePage)
  908. {
  909. switch(CodePage) {
  910. case 932:
  911. case 936:
  912. case 949:
  913. case 950:
  914. return TRUE;
  915. }
  916. return FALSE;
  917. }
  918. //----------------------------------------------------------------------------
  919. //
  920. // Function: SetFarEastThread
  921. //
  922. // Purpose: FarEast version wants to display bi-lingual string according console OCP
  923. //
  924. // Arguments: None
  925. //
  926. // Returns: None
  927. //----------------------------------------------------------------------------
  928. void SetFarEastThread()
  929. {
  930. LANGID LangId = 0;
  931. switch(GetConsoleOutputCP()) {
  932. case 932:
  933. LangId = MAKELANGID( LANG_JAPANESE, SUBLANG_DEFAULT );
  934. break;
  935. case 949:
  936. LangId = MAKELANGID( LANG_KOREAN, SUBLANG_KOREAN );
  937. break;
  938. case 936:
  939. LangId = MAKELANGID( LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED );
  940. break;
  941. case 950:
  942. LangId = MAKELANGID( LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL );
  943. break;
  944. default:
  945. {
  946. LANGID TmpLangId = PRIMARYLANGID(LANGIDFROMLCID( GetUserDefaultLCID() ));
  947. if (TmpLangId == LANG_JAPANESE ||
  948. TmpLangId == LANG_KOREAN ||
  949. TmpLangId == LANG_CHINESE ) {
  950. LangId = MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US );
  951. }
  952. }
  953. break;
  954. }
  955. if (LangId) {
  956. SetThreadLocale( MAKELCID(LangId, SORT_DEFAULT) );
  957. }
  958. }
  959. //----------------------------------------------------------------------------
  960. //
  961. // Function: ConsolePrint
  962. //
  963. // Purpose: There is a bug in CRT library that unicode FE characters can't
  964. // convert correctly, so we output characters directly.
  965. //
  966. // Arguments: None
  967. //
  968. // Returns: None
  969. //----------------------------------------------------------------------------
  970. void ConsolePrint( WCHAR *szFirstString, ... )
  971. {
  972. HANDLE StdOut;
  973. DWORD WrittenCount;
  974. WCHAR OutputBuffer[MAKEBOOT_MAX_STRING_LEN];
  975. va_list arglist;
  976. if((StdOut = GetStdHandle(STD_OUTPUT_HANDLE)) == INVALID_HANDLE_VALUE) {
  977. return;
  978. }
  979. va_start( arglist, szFirstString );
  980. wvsprintf( OutputBuffer, szFirstString, arglist );
  981. WriteConsoleW(
  982. StdOut,
  983. OutputBuffer,
  984. lstrlenW(OutputBuffer),
  985. &WrittenCount,
  986. NULL
  987. );
  988. va_end( arglist );
  989. }