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

902 lines
22 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Copyright (c) 1999 Microsoft Corporation
  4. // All rights reserved.
  5. //
  6. // File Name:
  7. // makeboot.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. // Assumptions:
  14. // The sector size is 512 and the sectors per track is 18
  15. //
  16. // The floppy disk images are in the current dir and named CDBOOT1.IMG,
  17. // CDBOOT2.IMG, CDBOOT3.IMG and CDBOOT4.IMG.
  18. //
  19. // The txtsetup.sif resides in ..\i386 or ..\alpha from where the
  20. // program is being run.
  21. //
  22. //----------------------------------------------------------------------------
  23. #include <bios.h>
  24. #include <string.h>
  25. #include <malloc.h>
  26. #include <io.h>
  27. #include <fcntl.h>
  28. #include <process.h>
  29. #include <errno.h>
  30. #include <conio.h>
  31. #include <ctype.h>
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #include <stdarg.h>
  35. #include "makeboot.h"
  36. //
  37. // Constants
  38. //
  39. //
  40. // To support disks other than 1.44 MB High-Density floppies, then these
  41. // numbers will have to be changed or determined at run-time.
  42. //
  43. #define SECTORS_PER_TRACK 18
  44. #define SECTOR_SIZE 512
  45. #define TRACK_SIZE SECTORS_PER_TRACK * SECTOR_SIZE
  46. #define NUMBER_OF_TRACKS 80
  47. #define SECTORS_TO_COPY_AT_A_TIME 18
  48. // we multiply by 2 because the disk is double-sided
  49. #define NUMBER_OF_SECTORS_ON_DISK NUMBER_OF_TRACKS * SECTORS_PER_TRACK * 2
  50. #define NT_NAME_OF_MAKEBOOT "makebt32.exe"
  51. #define NT_IMAGE_1_NAME "CDBOOT1.IMG"
  52. #define NT_IMAGE_2_NAME "CDBOOT2.IMG"
  53. #define NT_IMAGE_3_NAME "CDBOOT3.IMG"
  54. #define NT_IMAGE_4_NAME "CDBOOT4.IMG"
  55. #define NT_IMAGE_5_NAME "CDBOOT5.IMG"
  56. #define NT_IMAGE_6_NAME "CDBOOT6.IMG"
  57. #define MAX_INILINE_LENGTH 1023
  58. #define ENTER_KEY 13
  59. #define ESC_KEY 27
  60. #define NUMBER_OF_ASCII_WHEEL_SYMBOLS 4
  61. const char rgAsciiWheel[NUMBER_OF_ASCII_WHEEL_SYMBOLS] = { '|', '/', '-', '\\' };
  62. //
  63. // Function prototypes
  64. //
  65. int WriteImageToFloppy( char *szFileName, int drive );
  66. int DoesUserWantToTryCopyAgain( void );
  67. void ReportBiosError( unsigned int iBiosErrorCode );
  68. int DoImageFilesExist( void );
  69. unsigned int IsFloppyDrive( int DriveLetter );
  70. void PressAnyKeyToContinue( void );
  71. unsigned int AbsoluteDiskWrite( unsigned int *iErrorCode,
  72. unsigned int iDrive,
  73. unsigned int iStartingSector,
  74. unsigned int iNumberOfSectorsToWrite,
  75. void far *Buffer_to_be_written );
  76. unsigned DnGetCodepage(void);
  77. //
  78. // Variables that are allocated in strings.c that are used to determine what
  79. // string table to use.
  80. //
  81. extern unsigned int CODEPAGE;
  82. extern const char *EngStrings[];
  83. extern const char *LocStrings[];
  84. //
  85. // This var holds a pointer to the array of strings to be used
  86. //
  87. const char **StringTable;
  88. //----------------------------------------------------------------------------
  89. //
  90. // Function: main
  91. //
  92. // Purpose: Instructs user to insert floppy disks to be copied and performs
  93. // the copy.
  94. //
  95. // Arguments: int argc - standard program argument, count of the command line args
  96. // char *argv[] - standard program argument, the 2nd argument is the
  97. // floppy drive to copy the images to.
  98. // Returns: int - zero on success, non-zero on error
  99. //
  100. //----------------------------------------------------------------------------
  101. int
  102. main( int argc, char *argv[] )
  103. {
  104. char *szOsName;
  105. char Drive;
  106. char DriveLetter;
  107. int bTryAgain;
  108. //
  109. // Set the string table to the appropriate language depending on
  110. // the code page.
  111. //
  112. if( *LocStrings[0] == '\0' )
  113. {
  114. StringTable = EngStrings;
  115. }
  116. else {
  117. if( DnGetCodepage() != CODEPAGE )
  118. {
  119. StringTable = EngStrings;
  120. }
  121. else
  122. {
  123. StringTable = LocStrings;
  124. }
  125. }
  126. szOsName = getenv( "OS" );
  127. //
  128. // See if we are on NT. If we are, call the NT version and exit.
  129. // If we aren't then just continue executing this program.
  130. //
  131. if( szOsName && ( stricmp( szOsName, "Windows_NT" ) == 0 ) )
  132. {
  133. int iRetVal;
  134. iRetVal = spawnl( P_WAIT, NT_NAME_OF_MAKEBOOT, NT_NAME_OF_MAKEBOOT, argv[1], NULL );
  135. if( iRetVal == -1 )
  136. {
  137. if( errno == ENOENT )
  138. {
  139. printf( StringTable[ CANNOT_FIND_FILE ], NT_NAME_OF_MAKEBOOT );
  140. exit( 1 );
  141. }
  142. else if( errno == ENOMEM )
  143. {
  144. printf( StringTable[ NOT_ENOUGH_MEMORY ] );
  145. exit( 1 );
  146. }
  147. else if( errno == ENOEXEC )
  148. {
  149. printf( StringTable[ NOT_EXEC_FORMAT ], NT_NAME_OF_MAKEBOOT );
  150. exit( 1 );
  151. }
  152. else
  153. {
  154. printf( StringTable[ UNKNOWN_SPAWN_ERROR ], NT_NAME_OF_MAKEBOOT );
  155. exit( 1 );
  156. }
  157. }
  158. // successful completion
  159. exit( 0 );
  160. }
  161. printf( "\n%s\n", StringTable[ STARS ] );
  162. printf( "%s\n", StringTable[ EXPLANATION_LINE_1 ] );
  163. printf( StringTable[ EXPLANATION_LINE_2 ], StringTable[ NT_VERSION_NAME ] );
  164. printf( "\n\n" );
  165. printf( "%s\n", StringTable[ EXPLANATION_LINE_3 ] );
  166. printf( "%s\n\n", StringTable[ EXPLANATION_LINE_4 ] );
  167. //
  168. // If they didn't specified the floppy drive on the command line then
  169. // prompt them for it.
  170. //
  171. if( argc == 1 )
  172. {
  173. printf( StringTable[ SPECIFY_DRIVE ] );
  174. DriveLetter = (char) getche();
  175. printf( "\n\n" );
  176. }
  177. else
  178. {
  179. DriveLetter = argv[1][0];
  180. }
  181. //
  182. // Make sure the character they entered is a possible drive letter
  183. //
  184. if( ! isalpha( DriveLetter ) )
  185. {
  186. printf( StringTable[ INVALID_DRIVE_LETTER ] );
  187. exit( 1 );
  188. }
  189. //
  190. // Make sure the drive specified is actually a floppy drive
  191. //
  192. if( ! IsFloppyDrive( DriveLetter ) )
  193. {
  194. printf( StringTable[ NOT_A_FLOPPY ], DriveLetter );
  195. exit( 1 );
  196. }
  197. //
  198. // map the drive letter a or A to 0, b or B to 1, etc.
  199. //
  200. Drive = (char) ( toupper( DriveLetter ) - (int)'A' );
  201. //
  202. // Make sure all the images files exist in the current directory
  203. //
  204. if( ! DoImageFilesExist() )
  205. {
  206. exit( 1 );
  207. }
  208. printf( StringTable[ INSERT_FIRST_DISK_LINE_1 ], DriveLetter );
  209. printf( "\n" );
  210. printf( StringTable[ INSERT_FIRST_DISK_LINE_2 ], StringTable[ DISK_LABEL_1 ] );
  211. printf( "\n\n" );
  212. PressAnyKeyToContinue();
  213. while( ! WriteImageToFloppy( NT_IMAGE_1_NAME, Drive ) )
  214. {
  215. bTryAgain = DoesUserWantToTryCopyAgain();
  216. if( ! bTryAgain )
  217. {
  218. exit( 1 );
  219. }
  220. }
  221. printf( "\n" );
  222. printf( StringTable[ INSERT_ANOTHER_DISK_LINE_1 ], DriveLetter );
  223. printf( "\n" );
  224. printf( StringTable[ INSERT_ANOTHER_DISK_LINE_2 ], StringTable[ DISK_LABEL_2 ] );
  225. printf( "\n\n" );
  226. PressAnyKeyToContinue();
  227. while( ! WriteImageToFloppy( NT_IMAGE_2_NAME, Drive ) )
  228. {
  229. bTryAgain = DoesUserWantToTryCopyAgain();
  230. if( ! bTryAgain )
  231. {
  232. exit( 1 );
  233. }
  234. }
  235. printf( "\n" );
  236. printf( StringTable[ INSERT_ANOTHER_DISK_LINE_1 ], DriveLetter );
  237. printf( "\n" );
  238. printf( StringTable[ INSERT_ANOTHER_DISK_LINE_2 ], StringTable[ DISK_LABEL_3 ] );
  239. printf( "\n\n" );
  240. PressAnyKeyToContinue();
  241. while( ! WriteImageToFloppy( NT_IMAGE_3_NAME, Drive ) )
  242. {
  243. bTryAgain = DoesUserWantToTryCopyAgain();
  244. if( ! bTryAgain )
  245. {
  246. exit( 1 );
  247. }
  248. }
  249. printf( "\n" );
  250. printf( StringTable[ INSERT_ANOTHER_DISK_LINE_1 ], DriveLetter );
  251. printf( "\n" );
  252. printf( StringTable[ INSERT_ANOTHER_DISK_LINE_2 ], StringTable[ DISK_LABEL_4 ] );
  253. printf( "\n\n" );
  254. PressAnyKeyToContinue();
  255. while( ! WriteImageToFloppy( NT_IMAGE_4_NAME, Drive ) )
  256. {
  257. bTryAgain = DoesUserWantToTryCopyAgain();
  258. if( ! bTryAgain )
  259. {
  260. exit( 1 );
  261. }
  262. }
  263. printf( "\n" );
  264. printf( StringTable[ INSERT_ANOTHER_DISK_LINE_1 ], DriveLetter );
  265. printf( "\n" );
  266. printf( StringTable[ INSERT_ANOTHER_DISK_LINE_2 ], StringTable[ DISK_LABEL_5 ] );
  267. printf( "\n\n" );
  268. PressAnyKeyToContinue();
  269. while( ! WriteImageToFloppy( NT_IMAGE_5_NAME, Drive ) )
  270. {
  271. bTryAgain = DoesUserWantToTryCopyAgain();
  272. if( ! bTryAgain )
  273. {
  274. exit( 1 );
  275. }
  276. }
  277. printf( "\n" );
  278. printf( StringTable[ INSERT_ANOTHER_DISK_LINE_1 ], DriveLetter );
  279. printf( "\n" );
  280. printf( StringTable[ INSERT_ANOTHER_DISK_LINE_2 ], StringTable[ DISK_LABEL_6 ] );
  281. printf( "\n\n" );
  282. PressAnyKeyToContinue();
  283. while( ! WriteImageToFloppy( NT_IMAGE_6_NAME, Drive ) )
  284. {
  285. bTryAgain = DoesUserWantToTryCopyAgain();
  286. if( ! bTryAgain )
  287. {
  288. exit( 1 );
  289. }
  290. }
  291. printf( "\n\n%s\n\n", StringTable[ COMPLETED_SUCCESSFULLY ] );
  292. printf( "%s\n", StringTable[ STARS ] );
  293. return( 0 );
  294. }
  295. //----------------------------------------------------------------------------
  296. //
  297. // Function: WriteImageToFloppy
  298. //
  299. // Purpose: Writes an image file to a floppy disk. Handles all error
  300. // reporting to the user.
  301. //
  302. // Arguments: char *szFileName - filename to write to the floppy
  303. // int drive - drive letter of the floppy to write to
  304. //
  305. // Returns: int - non-zero on success
  306. // - zero on error
  307. //
  308. //----------------------------------------------------------------------------
  309. int
  310. WriteImageToFloppy( char *szFileName, int drive )
  311. {
  312. char *pTrack;
  313. int hImageFile;
  314. unsigned int iSuccess;
  315. unsigned int iErrorCode;
  316. unsigned int iBytesRead;
  317. unsigned int iTotalSectorsWritten;
  318. unsigned int iPercentComplete;
  319. unsigned int iWheelPosition;
  320. char TrackBuffer[ TRACK_SIZE ];
  321. _fmode = O_BINARY;
  322. //
  323. // Open the image file
  324. //
  325. hImageFile = open( szFileName, O_RDONLY );
  326. if( hImageFile == -1 )
  327. {
  328. perror( szFileName );
  329. return( 0 );
  330. }
  331. iWheelPosition = 0;
  332. iTotalSectorsWritten = 0;
  333. //
  334. // Loop reading a track and then writing SECTORS_TO_COPY_AT_A_TIME sectors
  335. // out at a time until we reach the end of the file
  336. //
  337. while( ( iBytesRead = read( hImageFile, TrackBuffer, TRACK_SIZE ) ) > 0 )
  338. {
  339. pTrack = TrackBuffer;
  340. for( ;
  341. iBytesRead > 0;
  342. iTotalSectorsWritten += SECTORS_TO_COPY_AT_A_TIME )
  343. {
  344. iSuccess = AbsoluteDiskWrite( &iErrorCode,
  345. drive,
  346. iTotalSectorsWritten,
  347. SECTORS_TO_COPY_AT_A_TIME,
  348. (void far *) pTrack );
  349. if( ! iSuccess )
  350. {
  351. ReportBiosError( iErrorCode );
  352. close( hImageFile );
  353. return( 0 );
  354. }
  355. iBytesRead = iBytesRead - ( SECTOR_SIZE * SECTORS_TO_COPY_AT_A_TIME );
  356. pTrack = pTrack + ( SECTOR_SIZE * SECTORS_TO_COPY_AT_A_TIME );
  357. }
  358. iPercentComplete = (int) ( ( (double) (iTotalSectorsWritten) / (double) (NUMBER_OF_SECTORS_ON_DISK) ) * 100.0 );
  359. printf( "%c %3d%% %s\r",
  360. rgAsciiWheel[iWheelPosition],
  361. iPercentComplete,
  362. StringTable[ COMPLETE ] );
  363. //
  364. // Advance the ASCII wheel
  365. //
  366. iWheelPosition++;
  367. if( iWheelPosition >= NUMBER_OF_ASCII_WHEEL_SYMBOLS )
  368. {
  369. iWheelPosition = 0;
  370. }
  371. }
  372. //
  373. // We are done copying the disk so force it to read 100% and get rid of
  374. // the ascii wheel symbol.
  375. //
  376. printf( " 100%% %s \n", StringTable[ COMPLETE ] );
  377. close( hImageFile );
  378. return( 1 );
  379. }
  380. //----------------------------------------------------------------------------
  381. //
  382. // Function: DoesUserWantToTryCopyAgain
  383. //
  384. // Purpose: Ask the user if they want to retry to copy the image to floppy.
  385. // Get the user input and return whether to copy again or not.
  386. //
  387. // Arguments: void
  388. //
  389. // Returns: int - non-zero if user wants to attempt to copy again
  390. // - zero if user does not want to attempt to copy again
  391. //
  392. //----------------------------------------------------------------------------
  393. int
  394. DoesUserWantToTryCopyAgain( void )
  395. {
  396. int ch;
  397. //
  398. // Clear the input stream by eating all the chars until there are none
  399. // left. Print the message and then wait for a key press.
  400. //
  401. while( kbhit() )
  402. {
  403. getch();
  404. }
  405. do
  406. {
  407. printf( "%s\n", StringTable[ ATTEMPT_TO_CREATE_FLOPPY_AGAIN ] );
  408. printf( "%s\n", StringTable[ PRESS_ENTER_OR_ESC ] );
  409. ch = getch();
  410. } while( ch != ENTER_KEY && ch != ESC_KEY );
  411. if( ch == ENTER_KEY )
  412. {
  413. return( 1 );
  414. }
  415. else
  416. {
  417. return( 0 );
  418. }
  419. }
  420. //----------------------------------------------------------------------------
  421. //
  422. // Function: PressAnyKeyToContinue
  423. //
  424. // Purpose: Print the "Press any key when ready" message and wait until the
  425. // user presses a key.
  426. //
  427. // Arguments: void
  428. //
  429. // Returns: void
  430. //
  431. //----------------------------------------------------------------------------
  432. void
  433. PressAnyKeyToContinue( void )
  434. {
  435. //
  436. // Clear the input stream by eating all the chars until there are none
  437. // left. Print the message and then wait for a key press.
  438. //
  439. while( kbhit() )
  440. {
  441. getch();
  442. }
  443. printf( "%s\n", StringTable[ PRESS_ANY_KEY_TO_CONTINUE ] );
  444. //
  445. // Spin until the keyboard is pressed
  446. //
  447. while( ! kbhit() )
  448. {
  449. ;
  450. }
  451. }
  452. //----------------------------------------------------------------------------
  453. //
  454. // Function: DoImageFilesExist
  455. //
  456. // Purpose: Determines if all the image files are in the current directory or
  457. // not. If an image file is missing, an error message is printed
  458. // to the user.
  459. //
  460. // Note: it detemines if a file exists by seeing if it can open it
  461. // for reading.
  462. //
  463. // Arguments: void
  464. //
  465. // Returns: int -- non-zero on success, all images files exist in current dir
  466. // zero on failure, 1 or more image files do not exist
  467. //
  468. //----------------------------------------------------------------------------
  469. int
  470. DoImageFilesExist( void )
  471. {
  472. FILE *FileStream;
  473. int iSuccess = 1; // assume success
  474. if( ( FileStream = fopen( NT_IMAGE_1_NAME, "r" ) ) == NULL )
  475. {
  476. printf( StringTable[ CANNOT_FIND_FILE ], NT_IMAGE_1_NAME );
  477. printf( "\n" );
  478. iSuccess = 0;
  479. }
  480. else
  481. {
  482. fclose( FileStream );
  483. }
  484. if( ( FileStream = fopen( NT_IMAGE_2_NAME, "r" ) ) == NULL )
  485. {
  486. printf( StringTable[ CANNOT_FIND_FILE ], NT_IMAGE_2_NAME );
  487. printf( "\n" );
  488. iSuccess = 0;
  489. }
  490. else
  491. {
  492. fclose( FileStream );
  493. }
  494. if( ( FileStream = fopen( NT_IMAGE_3_NAME, "r" ) ) == NULL )
  495. {
  496. printf( StringTable[ CANNOT_FIND_FILE ], NT_IMAGE_3_NAME );
  497. printf( "\n" );
  498. iSuccess = 0;
  499. }
  500. else
  501. {
  502. fclose( FileStream );
  503. }
  504. if( ( FileStream = fopen( NT_IMAGE_4_NAME, "r" ) ) == NULL )
  505. {
  506. printf( StringTable[ CANNOT_FIND_FILE ], NT_IMAGE_4_NAME );
  507. printf( "\n" );
  508. iSuccess = 0;
  509. }
  510. else
  511. {
  512. fclose( FileStream );
  513. }
  514. if( ( FileStream = fopen( NT_IMAGE_5_NAME, "r" ) ) == NULL )
  515. {
  516. printf( StringTable[ CANNOT_FIND_FILE ], NT_IMAGE_5_NAME );
  517. printf( "\n" );
  518. iSuccess = 0;
  519. }
  520. else
  521. {
  522. fclose( FileStream );
  523. }
  524. if( ( FileStream = fopen( NT_IMAGE_6_NAME, "r" ) ) == NULL )
  525. {
  526. printf( StringTable[ CANNOT_FIND_FILE ], NT_IMAGE_6_NAME );
  527. printf( "\n" );
  528. iSuccess = 0;
  529. }
  530. else
  531. {
  532. fclose( FileStream );
  533. }
  534. return( iSuccess );
  535. }
  536. //----------------------------------------------------------------------------
  537. //
  538. // Function: IsFloppyDrive
  539. //
  540. // Purpose: To determine if a particular drive is a floppy drive.
  541. //
  542. // Arguments: int DriveLetter - the drive letter to test whether it is a
  543. // floppy or not
  544. //
  545. // Returns: unsigned int -- non-zero if the specified drive is a floppy drive
  546. // zero if the specified drive is not a floppy drive
  547. //
  548. //----------------------------------------------------------------------------
  549. unsigned int
  550. IsFloppyDrive( int DriveLetter )
  551. {
  552. unsigned int drive;
  553. unsigned int iIsFloppy;
  554. //
  555. // Convert the drive letter to a number. 1 = A, 2 = B, 3 = C, ...
  556. //
  557. drive = ( toupper( DriveLetter ) - (int)'A' ) + 1;
  558. //
  559. // Assume it is not a floppy
  560. //
  561. iIsFloppy = 0;
  562. _asm {
  563. push ds
  564. push es
  565. push bp
  566. mov ah, 1Ch // going to call function 1Ch
  567. mov dl, BYTE PTR [drive]
  568. int 21h // call Int 21h function 1Ch
  569. cmp BYTE PTR ds:[bx], 0F8h // test for fixed drive
  570. je done
  571. mov iIsFloppy, 1 // it is a floppy
  572. done:
  573. pop bp
  574. pop es
  575. pop ds
  576. }
  577. return( iIsFloppy );
  578. }
  579. //----------------------------------------------------------------------------
  580. //
  581. // Function: ReportBiosError
  582. //
  583. // Purpose: To convert a BIOS error code to a error message and print it out
  584. // for the user to see.
  585. //
  586. // Arguments: unsigned int iBiosErrorCode - the BIOS error code to be looked up
  587. //
  588. // Returns: void
  589. //
  590. //----------------------------------------------------------------------------
  591. void
  592. ReportBiosError( unsigned int iBiosErrorCode )
  593. {
  594. //
  595. // Print out the error code for the lower byte
  596. //
  597. switch( iBiosErrorCode & 0x00FF )
  598. {
  599. case 0x0000: printf( StringTable[ ERROR_DISK_WRITE_PROTECTED ] ); break;
  600. case 0x0001: printf( StringTable[ ERROR_UNKNOWN_DISK_UNIT ] ); break;
  601. case 0x0002: printf( StringTable[ ERROR_DRIVE_NOT_READY ] ); break;
  602. case 0x0003: printf( StringTable[ ERROR_UNKNOWN_COMMAND ] ); break;
  603. case 0x0004: printf( StringTable[ ERROR_DATA_ERROR ] ); break;
  604. case 0x0005: printf( StringTable[ ERROR_BAD_REQUEST ] ); break;
  605. case 0x0006: printf( StringTable[ ERROR_SEEK_ERROR ] ); break;
  606. case 0x0007: printf( StringTable[ ERROR_MEDIA_TYPE_NOT_FOUND ] ); break;
  607. case 0x0008: printf( StringTable[ ERROR_SECTOR_NOT_FOUND ] ); break;
  608. case 0x000A: printf( StringTable[ ERROR_WRITE_FAULT ] ); break;
  609. case 0x000C: printf( StringTable[ ERROR_GENERAL_FAILURE ] ); break;
  610. }
  611. //
  612. // Print out the error code for the upper byte
  613. //
  614. switch( iBiosErrorCode & 0xFF00 )
  615. {
  616. case 0x0100: printf( StringTable[ ERROR_INVALID_REQUEST ] ); break;
  617. case 0x0200: printf( StringTable[ ERROR_ADDRESS_MARK_NOT_FOUND ] ); break;
  618. case 0x0300: printf( StringTable[ ERROR_DISK_WRITE_FAULT ] ); break;
  619. case 0x0400: printf( StringTable[ ERROR_SECTOR_NOT_FOUND ] ); break;
  620. case 0x0800: printf( StringTable[ ERROR_DMA_OVERRUN ] ); break;
  621. case 0x1000: printf( StringTable[ ERROR_CRC_ERROR ] ); break;
  622. case 0x2000: printf( StringTable[ ERROR_CONTROLLER_FAILURE ] ); break;
  623. case 0x4000: printf( StringTable[ ERROR_SEEK_ERROR ] ); break;
  624. case 0x8000: printf( StringTable[ ERROR_DISK_TIMED_OUT ] ); break;
  625. }
  626. }
  627. //----------------------------------------------------------------------------
  628. //
  629. // Function: AbsoluteDiskWrite
  630. //
  631. // Purpose: To write a buffer in memory to a specific portion of a disk.
  632. //
  633. // Arguments: unsigned int *iErrorCode - if an error occurs, the error code
  634. // is returned in this OUT variable
  635. // unsigned int iDrive - drive to write the buffer to
  636. // unsigned int iStartingSector - sector where the write is to begin
  637. // unsigned int iNumberOfSectorsToWrite - the number of sectors
  638. // to write
  639. //
  640. // Returns: returns 1 on success, 0 on failure
  641. // If it fails, then the error code is returned in the argument
  642. // iErrorCode.
  643. // If it succeeds, iErrorCode is undefined.
  644. //
  645. //----------------------------------------------------------------------------
  646. unsigned int
  647. AbsoluteDiskWrite( unsigned int *iErrorCode,
  648. unsigned int iDrive,
  649. unsigned int iStartingSector,
  650. unsigned int iNumberOfSectorsToWrite,
  651. void far *Buffer_to_be_written )
  652. {
  653. //
  654. // used to temporarily store the error code
  655. //
  656. unsigned int iTempErrorCode;
  657. unsigned int iRetVal;
  658. _asm
  659. {
  660. push ds
  661. push es
  662. push bp
  663. mov ax, WORD PTR [Buffer_to_be_written + 2]
  664. mov ds, ax
  665. mov bx, WORD PTR [Buffer_to_be_written]
  666. mov dx, iStartingSector
  667. mov cx, iNumberOfSectorsToWrite
  668. mov al, BYTE PTR [iDrive]
  669. int 26h // do the absolute disk write
  670. lahf
  671. popf
  672. sahf
  673. pop bp
  674. pop es
  675. pop ds
  676. mov iRetVal, 1 // assume success
  677. jnc done // see if an error occured
  678. mov iRetVal, 0
  679. mov iTempErrorCode, ax
  680. done:
  681. }
  682. *iErrorCode = iTempErrorCode;
  683. return( iRetVal );
  684. }
  685. unsigned
  686. DnGetCodepage(void)
  687. /*++
  688. Routine Description:
  689. Determine the currently active codepage.
  690. Arguments:
  691. None.
  692. Return Value:
  693. Currently active codepage. 0 if we can't determine it.
  694. --*/
  695. {
  696. unsigned int iRetVal;
  697. _asm {
  698. mov ax,06601h
  699. int 21h
  700. jnc ok
  701. xor bx,bx
  702. ok: mov iRetVal,bx
  703. }
  704. return( iRetVal );
  705. }