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.

1288 lines
37 KiB

  1. /*++
  2. Routine Description:
  3. contains functions to format a floppy disk
  4. Arguments:
  5. Return Value:
  6. --*/
  7. #include <windows.h> // required for all Windows applications
  8. #include <tchar.h> // unicode definitions
  9. #include "otnboot.h" // application definitions
  10. #include "otnbtdlg.h" // dialog box constants
  11. #include "fmifs.h" // file manager IFS DLL functions
  12. #ifdef JAPAN
  13. // fixed kkntbug #11940
  14. // Network client administrator can not make install disks on PC with C drive as FD
  15. #define OEM_ID_PC98 0X0D00
  16. //
  17. // Japanese specific floppy format styles
  18. //
  19. #define F3_12 1 // 3.5" drive that supports 1.2M-byte format
  20. #define F3_123 2 // 3.5" drive that supports 1.23M-byte format
  21. #define F5_123 4 // 5.25" drive that supports 1.23M-byte format
  22. #endif
  23. //
  24. // local windows messages
  25. //
  26. #define FS_CANCELUPDATE (WM_USER+104)
  27. //
  28. // Disk format information structure
  29. //
  30. #define FF_ONLYONE 0x1000
  31. #define FF_RETRY 0x4000
  32. typedef struct _CANCEL_INFO {
  33. HWND hCancelDlg;
  34. BOOL bCancel;
  35. HANDLE hThread;
  36. BOOL fmifsSuccess;
  37. UINT dReason;
  38. UINT fuStyle; // Message box style
  39. INT nPercentDrawn; // percent drawn so FAR
  40. enum _CANCEL_TYPE {
  41. CANCEL_NULL=0,
  42. CANCEL_FORMAT,
  43. CANCEL_COPY,
  44. CANCEL_BACKUP,
  45. CANCEL_RESTORE,
  46. CANCEL_COMPRESS,
  47. CANCEL_UNCOMPRESS
  48. } eCancelType;
  49. BOOL bModal;
  50. struct _INFO {
  51. struct _FORMAT {
  52. INT iFormatDrive;
  53. FMIFS_MEDIA_TYPE fmMediaType;
  54. BOOL fQuick;
  55. DWORD fFlags; // FF_ONLYONE = 0x1000
  56. TCHAR szLabel[MAXLABELLEN+1];
  57. } Format;
  58. struct _COPY {
  59. INT iSourceDrive;
  60. INT iDestDrive;
  61. BOOL bFormatDest;
  62. } Copy;
  63. } Info;
  64. } CANCEL_INFO, *PCANCEL_INFO;
  65. static HANDLE hfmifsDll = NULL; // dll w/ file system utils
  66. static TCHAR szFmifsDll[] = {TEXT("fmifs.dll")}; // dll for FAT file system
  67. static TCHAR SZ_PERCENTFORMAT[] = {TEXT("%3d%%")};
  68. //
  69. // pointers to DLL functions;
  70. //
  71. static PFMIFS_FORMAT_ROUTINE lpfnFormat = NULL;
  72. static PFMIFS_DISKCOPY_ROUTINE lpfnDiskCopy = NULL;
  73. static PFMIFS_SETLABEL_ROUTINE lpfnSetLabel = NULL;
  74. static PFMIFS_QSUPMEDIA_ROUTINE lpfnQuerySupportedMedia = NULL;
  75. //
  76. // Format dialog box information
  77. //
  78. static CANCEL_INFO CancelInfo;
  79. static BOOL bDataInitialized = FALSE;
  80. ULONG ulSpaceAvail = 0;
  81. ULONG ulTotalSpace = 0;
  82. static
  83. LONG
  84. GetFloppyDiskSize (
  85. IN TCHAR cDrive
  86. )
  87. /*++
  88. Routine Description:
  89. Examines the specified floppy drive to determine if it
  90. supports 1.2M or 1.44M formats.
  91. Arguments:
  92. IN TCHAR cDrive
  93. drive letter of floppy drive to examine
  94. Return Value:
  95. 0 if unable to read drive or drive does not support a HD format
  96. 3 if the drive is a 3.5" drive that supports 1.44M-byte format
  97. 5 if the drive is a 5.25" drive that supports the 1.2M-byte format
  98. // Japanese specific floppy format styles
  99. F3_12 if the drive is a 3.5" drive that supports 1.2M-byte format
  100. F3_123 if the drive is a 3.5" drive that supports 1.23M-byte format
  101. F5_123 if the drive is a 5.25" drive that supports 1.23M-byte format
  102. --*/
  103. {
  104. #define DG_ELEMS 16 // accomodate up to 16 different formats
  105. TCHAR szDrivePath[8]; // local drive spec. string
  106. HANDLE hDrive; // handle to drive device driver
  107. DWORD dwError; // local error code
  108. DWORD dwBytesReturned; // size of buffer returned
  109. LONG lSize; // disk size returned to calling fn.
  110. DWORD dwCount; // number of DISK_GEOMETRY structures in buffer
  111. DWORD dwEntry; // structure being evaluated
  112. DISK_GEOMETRY dgArray[DG_ELEMS]; // buffer to put data in
  113. #ifndef JAPAN
  114. // fixed kkntbug #11940
  115. // Network client administrator can not make install disks on PC with C drive as FD
  116. // check input argument
  117. switch (cDrive){
  118. case TEXT('A'):
  119. case TEXT('a'):
  120. case TEXT('B'):
  121. case TEXT('b'):
  122. break;
  123. default:
  124. SetLastError (ERROR_INVALID_PARAMETER);
  125. return 0;
  126. }
  127. #endif
  128. // make NT device path for drive
  129. szDrivePath[0] = cBackslash;
  130. szDrivePath[1] = cBackslash;
  131. szDrivePath[2] = cPeriod;
  132. szDrivePath[3] = cBackslash;
  133. szDrivePath[4] = cDrive;
  134. szDrivePath[5] = cColon;
  135. szDrivePath[6] = 0;
  136. szDrivePath[7] = 0;
  137. // open drive
  138. hDrive = CreateFile (
  139. szDrivePath, // drive to open
  140. 0, // just talk to the driver, not the drive
  141. FILE_SHARE_READ | FILE_SHARE_WRITE, // allow sharing
  142. NULL, // default security
  143. OPEN_EXISTING, // open existing device
  144. FILE_ATTRIBUTE_NORMAL, // this is ignored
  145. NULL); // no template
  146. if (hDrive == INVALID_HANDLE_VALUE) {
  147. // unable to open drive so return error
  148. dwError = GetLastError ();
  149. return 0;
  150. }
  151. // get device information
  152. if (DeviceIoControl (hDrive,
  153. IOCTL_DISK_GET_MEDIA_TYPES,
  154. NULL, 0, // no input buffer
  155. &dgArray[0], sizeof(DISK_GEOMETRY)*DG_ELEMS,// output buffer info
  156. &dwBytesReturned, NULL)) { // return information
  157. // see if at least one entry was returned
  158. if (dwBytesReturned >= sizeof(DISK_GEOMETRY)) {
  159. dwCount = dwBytesReturned / sizeof(DISK_GEOMETRY);
  160. // go through array to see if there's a desired entry
  161. // i.e. a HD format in the list of supported formats
  162. for (lSize = 0, dwEntry = 0;
  163. (dwEntry < dwCount) && (lSize == 0);
  164. dwEntry++) {
  165. switch (dgArray[dwEntry].MediaType) {
  166. // only return a size if a supported
  167. // format is allowed by this drive
  168. case F5_1Pt2_512:
  169. lSize = 5;
  170. break;
  171. case F3_1Pt44_512:
  172. lSize = 3;
  173. break;
  174. #ifdef JAPAN
  175. // fixed kkntbug #11940
  176. // Network client administrator can not make install disks on PC with C drive as FD
  177. case F5_1Pt23_1024:
  178. lSize = F5_123;
  179. break;
  180. case F3_1Pt2_512:
  181. lSize = F3_12;
  182. break;
  183. case F3_1Pt23_1024:
  184. lSize = F3_123;
  185. break;
  186. #endif
  187. case F5_360_512:
  188. case F5_320_512:
  189. case F5_320_1024:
  190. case F5_180_512:
  191. case F5_160_512:
  192. case F3_2Pt88_512:
  193. case F3_20Pt8_512:
  194. case F3_720_512:
  195. default:
  196. lSize = 0;
  197. break;
  198. }
  199. }
  200. } else {
  201. // no data returned so return error
  202. dwError = GetLastError ();
  203. SetLastError (ERROR_NO_DATA);
  204. lSize = 0;
  205. }
  206. } else {
  207. // unable to read device driver info
  208. dwError = GetLastError ();
  209. lSize = 0;
  210. }
  211. // close handle and return data found.
  212. CloseHandle (hDrive);
  213. return lSize;
  214. }
  215. static
  216. BOOL
  217. DriveLoaded (
  218. IN TCHAR cDrive,
  219. IN BOOL bCheckFormat
  220. )
  221. /*++
  222. Routine Description:
  223. formats call to MediaPresent function for use with just a drive letter
  224. Arguments:
  225. IN TCHAR cDrive
  226. drive letter to detect.
  227. Return Value:
  228. TRUE if a disk (formatted or unformatted) is detected.
  229. FALSE if disk is not present in drive
  230. --*/
  231. {
  232. TCHAR szPath[4];
  233. szPath[0] = cDrive;
  234. szPath[1] = cColon;
  235. szPath[2] = cBackslash;
  236. szPath[3] = 0;
  237. return MediaPresent (szPath, bCheckFormat);
  238. }
  239. static
  240. VOID
  241. CancelDlgQuit(
  242. VOID
  243. )
  244. /////////////////////////////////////////////////////////////////////
  245. //
  246. // Name: CancelDlgQuit
  247. //
  248. // Synopsis: Quits the cancel modeless dialog (status for diskcopy/format)
  249. //
  250. // IN: VOID
  251. //
  252. // Return: VOID
  253. //
  254. // Assumes: Called from worker thread only; CancelInfo.hThread valid
  255. //
  256. // Effects: Kills calling thread
  257. //
  258. //
  259. // Notes:
  260. //
  261. /////////////////////////////////////////////////////////////////////
  262. {
  263. //
  264. // Close thread if successful
  265. //
  266. if (CancelInfo.hThread) {
  267. CloseHandle(CancelInfo.hThread);
  268. CancelInfo.hThread = NULL;
  269. }
  270. //
  271. // At this point, when we call FS_CANCELEND,
  272. // the other thread thinks that this one has died since
  273. // CancelInfo.hThread is NULL.
  274. // This is exactly what we want, since we will very shortly
  275. // exit after the SendMessage.
  276. //
  277. EndDialog (CancelInfo.hCancelDlg, IDOK);
  278. ExitThread(0L);
  279. }
  280. static
  281. BOOL
  282. Callback_Function(
  283. IN FMIFS_PACKET_TYPE PacketType,
  284. IN DWORD PacketLength,
  285. IN PVOID PacketData
  286. )
  287. /*++
  288. Routine Description:
  289. Callback function used by IFS dll (stolen from Winfile code)
  290. Arguments:
  291. Return Value:
  292. --*/
  293. {
  294. TCHAR szTemp[128];
  295. // Quit if told to do so..
  296. if (CancelInfo.bCancel)
  297. return FALSE;
  298. switch (PacketType) {
  299. case FmIfsPercentCompleted:
  300. //
  301. // If we are copying and we just finished a destination format,
  302. // then set the window text back to the original message
  303. //
  304. if (CANCEL_COPY == CancelInfo.eCancelType &&
  305. CancelInfo.Info.Copy.bFormatDest) {
  306. CancelInfo.Info.Copy.bFormatDest = FALSE;
  307. lstrcpy (szTemp,
  308. GetStringResource (CancelInfo.Info.Copy.bFormatDest ?
  309. IDS_FORMATTINGDEST : IDS_COPYINGDISKTITLE));
  310. SetWindowText(CancelInfo.hCancelDlg, szTemp);
  311. }
  312. CancelInfo.nPercentDrawn = ((PFMIFS_PERCENT_COMPLETE_INFORMATION)PacketData)->PercentCompleted;
  313. PostMessage(CancelInfo.hCancelDlg, FS_CANCELUPDATE, ((PFMIFS_PERCENT_COMPLETE_INFORMATION)PacketData)->PercentCompleted, 0L);
  314. break;
  315. case FmIfsFormatReport:
  316. ulTotalSpace = ((PFMIFS_FORMAT_REPORT_INFORMATION)PacketData)->KiloBytesTotalDiskSpace * 1024L;
  317. ulSpaceAvail = ((PFMIFS_FORMAT_REPORT_INFORMATION)PacketData)->KiloBytesAvailable * 1024L;
  318. break;
  319. case FmIfsInsertDisk:
  320. switch(((PFMIFS_INSERT_DISK_INFORMATION)PacketData)->DiskType) {
  321. case DISK_TYPE_GENERIC:
  322. CancelInfo.fuStyle = MB_OK_TASK_INFO;
  323. return DisplayMessageBox(CancelInfo.hCancelDlg,
  324. IDS_INSERTSRC, IDS_COPYDISK, CancelInfo.fuStyle);
  325. case DISK_TYPE_SOURCE:
  326. CancelInfo.fuStyle = MB_OK_TASK_INFO;
  327. return DisplayMessageBox(CancelInfo.hCancelDlg,
  328. IDS_INSERTSRC, IDS_COPYDISK, CancelInfo.fuStyle);
  329. case DISK_TYPE_TARGET:
  330. CancelInfo.fuStyle = MB_OK_TASK_INFO;
  331. return DisplayMessageBox(CancelInfo.hCancelDlg,
  332. IDS_INSERTDEST, IDS_COPYDISK, CancelInfo.fuStyle);
  333. case DISK_TYPE_SOURCE_AND_TARGET:
  334. CancelInfo.fuStyle = MB_OK_TASK_INFO;
  335. return DisplayMessageBox(CancelInfo.hCancelDlg,
  336. IDS_INSERTSRCDEST, IDS_COPYDISK, CancelInfo.fuStyle);
  337. }
  338. break;
  339. case FmIfsIncompatibleFileSystem:
  340. CancelInfo.dReason = IDS_FFERR_INCFS;
  341. break;
  342. case FmIfsFormattingDestination:
  343. CancelInfo.Info.Copy.bFormatDest = TRUE;
  344. lstrcpy (szTemp, GetStringResource (
  345. (CancelInfo.Info.Copy.bFormatDest ?
  346. IDS_FORMATTINGDEST : IDS_COPYINGDISKTITLE)));
  347. SetWindowText(CancelInfo.hCancelDlg, szTemp);
  348. CancelInfo.nPercentDrawn = ((PFMIFS_PERCENT_COMPLETE_INFORMATION)PacketData)->PercentCompleted;
  349. PostMessage(CancelInfo.hCancelDlg, FS_CANCELUPDATE, ((PFMIFS_PERCENT_COMPLETE_INFORMATION)PacketData)->PercentCompleted, 0L);
  350. break;
  351. case FmIfsIncompatibleMedia:
  352. CancelInfo.fuStyle = MB_ICONHAND | MB_OK;
  353. return DisplayMessageBox(CancelInfo.hCancelDlg,
  354. IDS_COPYSRCDESTINCOMPAT, IDS_COPYDISK, CancelInfo.fuStyle);
  355. case FmIfsAccessDenied:
  356. CancelInfo.dReason = IDS_FFERR_ACCESSDENIED;
  357. break;
  358. case FmIfsMediaWriteProtected:
  359. CancelInfo.dReason = IDS_FFERR_DISKWP;
  360. break;
  361. case FmIfsCantLock:
  362. CancelInfo.dReason = IDS_FFERR_CANTLOCK;
  363. break;
  364. case FmIfsBadLabel:
  365. CancelInfo.fuStyle = MB_OK_TASK_EXCL;
  366. return DisplayMessageBox(CancelInfo.hCancelDlg,
  367. IDS_FFERR_BADLABEL, IDS_COPYERROR + FUNC_LABEL, CancelInfo.fuStyle);
  368. case FmIfsCantQuickFormat:
  369. // Can't quick format, ask if user wants to regular format:
  370. CancelInfo.fuStyle = MB_ICONEXCLAMATION | MB_YESNO;
  371. if (IDYES == DisplayMessageBox(
  372. CancelInfo.hCancelDlg,
  373. IDS_FORMATQUICKFAILURE,
  374. IDS_FORMATERR,
  375. CancelInfo.fuStyle)) {
  376. CancelInfo.Info.Format.fQuick = FALSE;
  377. CancelInfo.Info.Format.fFlags |= FF_RETRY;
  378. } else {
  379. //
  380. // Just fake a cancel
  381. //
  382. CancelInfo.fmifsSuccess = FALSE;
  383. CancelInfo.bCancel = TRUE;
  384. }
  385. break;
  386. case FmIfsIoError:
  387. switch(((PFMIFS_IO_ERROR_INFORMATION)PacketData)->DiskType) {
  388. case DISK_TYPE_GENERIC:
  389. CancelInfo.dReason = IDS_FFERR_GENIOERR;
  390. break;
  391. case DISK_TYPE_SOURCE:
  392. CancelInfo.dReason = IDS_FFERR_SRCIOERR;
  393. break;
  394. case DISK_TYPE_TARGET:
  395. CancelInfo.dReason = IDS_FFERR_DSTIOERR;
  396. break;
  397. case DISK_TYPE_SOURCE_AND_TARGET:
  398. CancelInfo.dReason = IDS_FFERR_SRCDSTIOERR;
  399. break;
  400. }
  401. break;
  402. case FmIfsFinished:
  403. CancelInfo.fmifsSuccess = ((PFMIFS_FINISHED_INFORMATION)PacketData)->Success;
  404. break;
  405. default:
  406. break;
  407. }
  408. return TRUE;
  409. }
  410. static
  411. VOID
  412. FormatDrive(
  413. IN PVOID ThreadParameter
  414. )
  415. /*++
  416. Routine Description:
  417. Thread routine to format the floppy diskette as described in the
  418. CancelInfo data structure.
  419. Arguments:
  420. Not used
  421. Return Value:
  422. None
  423. --*/
  424. {
  425. WCHAR wszDrive[3];
  426. WCHAR wszFileSystem[4] = L"FAT";
  427. wszDrive[0] = (WCHAR)(CancelInfo.Info.Format.iFormatDrive + cA);
  428. wszDrive[1] = cColon;
  429. wszDrive[2] = 0;
  430. #define wszLabel CancelInfo.Info.Format.szLabel
  431. do {
  432. CancelInfo.Info.Format.fFlags &= ~FF_RETRY;
  433. (*lpfnFormat)(wszDrive,
  434. CancelInfo.Info.Format.fmMediaType,
  435. wszFileSystem,
  436. wszLabel,
  437. (BOOLEAN)CancelInfo.Info.Format.fQuick,
  438. (FMIFS_CALLBACK)&Callback_Function);
  439. } while (CancelInfo.Info.Format.fFlags & FF_RETRY);
  440. CancelDlgQuit();
  441. }
  442. static
  443. FMIFS_MEDIA_TYPE
  444. GetDriveTypeFromDriveLetter (
  445. IN TCHAR cDrive
  446. )
  447. /*++
  448. Routine Description:
  449. returns the drive type of the drive specified in the path argument
  450. Arguments:
  451. IN LPCTSTR szPath
  452. path on drive to examine
  453. Return Value:
  454. MEDIA_TYPE value identifying drive type in format compatible with
  455. IFS DLL
  456. --*/
  457. {
  458. HANDLE hFloppy;
  459. DWORD dwRetSize;
  460. DISK_GEOMETRY dgFloppy;
  461. TCHAR szDevicePath[16];
  462. UINT nDriveType;
  463. UINT nErrorMode;
  464. // make device name from drive letter
  465. szDevicePath[0] = cBackslash;
  466. szDevicePath[1] = cBackslash;
  467. szDevicePath[2] = cPeriod;
  468. szDevicePath[3] = cBackslash;
  469. szDevicePath[4] = cDrive;
  470. szDevicePath[5] = cColon; // colon
  471. szDevicePath[6] = cBackslash; // null terminator
  472. szDevicePath[7] = 0; // null terminator
  473. nDriveType = GetDriveType((LPTSTR)&szDevicePath[4]);
  474. // see if this is a remote disk and exit if it is.
  475. if (nDriveType == DRIVE_REMOTE) return FmMediaUnknown;
  476. if ((nDriveType == DRIVE_REMOVABLE) || (nDriveType == DRIVE_CDROM)) {
  477. // make device path into an NT device path
  478. szDevicePath[6] = 0; // null terminator
  479. // disable windows error message popup
  480. nErrorMode = SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
  481. // open device to get type
  482. hFloppy = CreateFile (
  483. szDevicePath,
  484. GENERIC_READ,
  485. (FILE_SHARE_READ | FILE_SHARE_WRITE),
  486. NULL,
  487. OPEN_EXISTING,
  488. FILE_ATTRIBUTE_NORMAL,
  489. NULL);
  490. if (hFloppy != INVALID_HANDLE_VALUE) {
  491. // get drive information
  492. if (!DeviceIoControl (hFloppy,
  493. IOCTL_DISK_GET_DRIVE_GEOMETRY,
  494. NULL, 0,
  495. &dgFloppy,
  496. sizeof(DISK_GEOMETRY),
  497. &dwRetSize,
  498. NULL) ){
  499. // unable to get data so set to unknown
  500. dgFloppy.MediaType = Unknown;
  501. } // else return data from returned structure
  502. CloseHandle (hFloppy);
  503. } else {
  504. // unable to open handle to device
  505. dgFloppy.MediaType = Unknown;
  506. }
  507. SetErrorMode (nErrorMode); // reset error mode
  508. }
  509. // translate from MEDIA_TYPE to FMIFS_MEDIA_TYPE here
  510. switch (dgFloppy.MediaType) {
  511. #ifdef JAPAN
  512. // fixed kkntbug #11940
  513. // Network client administrator can not make install disks on PC with C drive as FD
  514. case (F3_1Pt2_512): return FmMediaF3_1Pt2_512;
  515. case (F3_1Pt23_1024): return FmMediaF3_1Pt23_1024;
  516. case (F5_1Pt23_1024): return FmMediaF5_1Pt23_1024;
  517. #endif
  518. case (F5_1Pt2_512): return FmMediaF5_1Pt2_512;
  519. case (F3_1Pt44_512): return FmMediaF3_1Pt44_512;
  520. case (F3_2Pt88_512): return FmMediaF3_2Pt88_512;
  521. case (F3_20Pt8_512): return FmMediaF3_20Pt8_512;
  522. case (F3_720_512): return FmMediaF3_720_512;
  523. case (F5_360_512): return FmMediaF5_360_512;
  524. case (F5_320_512): return FmMediaF5_320_512;
  525. case (F5_320_1024): return FmMediaF5_320_1024;
  526. case (F5_180_512): return FmMediaF5_180_512;
  527. case (F5_160_512): return FmMediaF5_160_512;
  528. case (FixedMedia): return FmMediaFixed;
  529. case (Unknown): return FmMediaUnknown;
  530. default: return FmMediaUnknown;
  531. }
  532. }
  533. static
  534. BOOL
  535. FmifsLoaded(
  536. IN HWND hWnd
  537. )
  538. /*++
  539. Routine Description:
  540. loads (if not already loaded) the File Manager IFS dll and initializes
  541. the pointers to it's functions
  542. Arguments:
  543. IN HWND hWnd
  544. window handle of parent, used for MessageBox calls
  545. Return Value:
  546. TRUE if file loaded
  547. FALSE if not
  548. --*/
  549. {
  550. // Load the fmifs dll.
  551. if (hfmifsDll < (HANDLE)32) {
  552. hfmifsDll = LoadLibrary(szFmifsDll);
  553. if (hfmifsDll < (HANDLE)32) {
  554. /* FMIFS not available. */
  555. DisplayMessageBox(hWnd,
  556. IDS_APP_NAME,
  557. IDS_FMIFSLOADERR,
  558. MB_OK | MB_ICONEXCLAMATION | MB_SYSTEMMODAL);
  559. hfmifsDll = NULL;
  560. return FALSE;
  561. }
  562. else {
  563. lpfnFormat = (PVOID)GetProcAddress(hfmifsDll, "Format");
  564. lpfnQuerySupportedMedia = (PVOID)GetProcAddress(hfmifsDll, "QuerySupportedMedia");
  565. lpfnSetLabel = (PVOID)GetProcAddress(hfmifsDll, "SetLabel");
  566. lpfnDiskCopy = (PVOID)GetProcAddress(hfmifsDll, "DiskCopy");
  567. if (!lpfnFormat || !lpfnQuerySupportedMedia ||
  568. !lpfnSetLabel || !lpfnDiskCopy) {
  569. DisplayMessageBox(hWnd,
  570. IDS_APP_NAME,
  571. IDS_FMIFSLOADERR,
  572. MB_OK | MB_ICONEXCLAMATION | MB_SYSTEMMODAL);
  573. FreeLibrary(hfmifsDll);
  574. hfmifsDll = NULL;
  575. return FALSE;
  576. }
  577. }
  578. }
  579. return TRUE;
  580. }
  581. static
  582. VOID
  583. DestroyCancelWindow(
  584. VOID
  585. )
  586. /*++
  587. Routine Description:
  588. Destroys the CANCEL (i.e. Format) window.
  589. Arguments:
  590. None
  591. Return Value:
  592. None
  593. --*/
  594. {
  595. if (!CancelInfo.hCancelDlg)
  596. return;
  597. if (CancelInfo.bModal) {
  598. EndDialog(CancelInfo.hCancelDlg,0);
  599. } else {
  600. DestroyWindow(CancelInfo.hCancelDlg);
  601. }
  602. CancelInfo.hCancelDlg = NULL;
  603. }
  604. static
  605. INT_PTR
  606. CancelDlgProc(HWND hDlg,
  607. IN UINT message,
  608. IN WPARAM wParam,
  609. IN LPARAM lParam
  610. )
  611. /*------------------------- CancelDlgProc
  612. *
  613. * DESCRIPTION:
  614. * dialog procedure for the modeless dialog. two main purposes
  615. * here:
  616. *
  617. * 1. if the user chooses CANCEL we set bCancel to TRUE
  618. * which will end the PeekMessage background processing loop
  619. *
  620. * 2. handle the private FS_CANCELUPDATE message and draw
  621. * a "gas gauge" indication of how FAR the background job
  622. * has progressed
  623. *
  624. * ARGUMENTS:
  625. * stock dialog proc arguments
  626. *
  627. * RETURN VALUE:
  628. * stock dialog proc return value - BOOL
  629. *
  630. * GLOBALS READ:
  631. * none
  632. *
  633. * GLOBALS WRITTEN:
  634. * CancelInfo structure
  635. *
  636. * MESSAGES:
  637. * WM_COMMAND - handle IDCANCEL by setting bCancel to TRUE
  638. * and calling DestroyWindow to end the dialog
  639. *
  640. * WM_INITDIALOG - set control text, get coordinates of gas gauge,
  641. * disable main window so we look modal
  642. *
  643. * WM_PAINT - draw the "gas gauge" control
  644. *
  645. * FS_CANCELUPDATE - the percentage done has changed, so update
  646. * nPercentDrawn and force a repaint
  647. *
  648. * NOTES:
  649. *
  650. * The bCancel global variable is used to communicate
  651. * with the main window. If the user chooses to cancel
  652. * we set bCancel to TRUE.
  653. *
  654. * When we get the private message FS_CANCELUPDATE
  655. * we update the "gas gauge" control that indicates
  656. * what percentage of the rectangles have been drawn
  657. * so FAR. This shows that we can draw in the dialog
  658. * as the looping operation progresses. (FS_CANCELUPDATE is sent
  659. * first to hwndFrame, which sets %completed then sends message to us.)
  660. *
  661. */
  662. {
  663. static RECT rectGG; // GasGauge rectangle
  664. DWORD Ignore;
  665. TCHAR szTemp[128];
  666. static BOOL bLastQuick;
  667. static HFONT hFont = NULL;
  668. switch (message) {
  669. case WM_COMMAND:
  670. switch (LOWORD(wParam)) {
  671. case IDCANCEL:
  672. DestroyCancelWindow();
  673. if (hFont != NULL) {
  674. DeleteObject(hFont);
  675. hFont = NULL;
  676. }
  677. CancelInfo.bCancel = TRUE;
  678. return TRUE;
  679. default:
  680. return FALSE;
  681. }
  682. case WM_INITDIALOG:
  683. {
  684. CancelInfo.hCancelDlg = hDlg;
  685. bLastQuick = TRUE;
  686. switch(CancelInfo.eCancelType) {
  687. case CANCEL_FORMAT:
  688. //
  689. // Formatting disk requires that we release any notification
  690. // requests on this drive.
  691. //
  692. // NotifyPause(CancelInfo.Info.Format.iFormatDrive, DRIVE_REMOVABLE);
  693. break;
  694. case CANCEL_COPY:
  695. //
  696. // Pause notifications on dest drive.
  697. //
  698. // NotifyPause(CancelInfo.Info.Copy.iDestDrive, DRIVE_REMOVABLE);
  699. lstrcpy (szTemp, GetStringResource(
  700. CancelInfo.Info.Copy.bFormatDest ?
  701. IDS_FORMATTINGDEST : IDS_COPYINGDISKTITLE));
  702. SetWindowText(hDlg, szTemp);
  703. break;
  704. default:
  705. break;
  706. }
  707. if (!CancelInfo.hThread) {
  708. switch (CancelInfo.eCancelType) {
  709. case CANCEL_FORMAT:
  710. CancelInfo.hThread = CreateThread( NULL, // Security
  711. 0L, // Stack Size
  712. (LPTHREAD_START_ROUTINE)FormatDrive,
  713. NULL,
  714. 0L,
  715. &Ignore );
  716. break;
  717. default:
  718. break;
  719. }
  720. }
  721. // a-jagram: bug fix 305171
  722. // Create the font
  723. if (hFont == NULL) { // it should be
  724. LOGFONT lf;
  725. HGDIOBJ hGObj;
  726. hGObj = GetStockObject(SYSTEM_FONT);
  727. if( hGObj != NULL ) {
  728. if (GetObject(hGObj, sizeof(lf), (LPVOID) &lf)) {
  729. lstrcpy(lf.lfFaceName, TEXT("MS Shell Dlg"));
  730. hFont = CreateFontIndirect(&lf);
  731. }
  732. }
  733. }
  734. // Get the coordinates of the gas gauge static control rectangle,
  735. // and convert them to dialog client area coordinates
  736. GetClientRect(GetDlgItem(hDlg, IDD_GASGAUGE), &rectGG);
  737. ClientToScreen(GetDlgItem(hDlg, IDD_GASGAUGE), (LPPOINT)&rectGG.left);
  738. ClientToScreen(GetDlgItem(hDlg, IDD_GASGAUGE), (LPPOINT)&rectGG.right);
  739. ScreenToClient(hDlg, (LPPOINT)&rectGG.left);
  740. ScreenToClient(hDlg, (LPPOINT)&rectGG.right);
  741. return TRUE;
  742. }
  743. case WM_PAINT:
  744. {
  745. HDC hDC;
  746. PAINTSTRUCT ps;
  747. TCHAR buffer[48];
  748. SIZE size;
  749. INT xText, yText;
  750. INT nDivideRects;
  751. RECT rectDone, rectLeftToDo;
  752. HGDIOBJ hOldFont = NULL;
  753. // The gas gauge is drawn by drawing a text string stating
  754. // what percentage of the job is done into the middle of
  755. // the gas gauge rectangle, and by separating that rectangle
  756. // into two parts: rectDone (the left part, filled in blue)
  757. // and rectLeftToDo(the right part, filled in white).
  758. // nDivideRects is the x coordinate that divides these two rects.
  759. //
  760. // The text in the blue rectangle is drawn white, and vice versa
  761. // This is easy to do with ExtTextOut()!
  762. hDC = BeginPaint(hDlg, &ps);
  763. if (hFont) {
  764. hOldFont = SelectObject(hDC, hFont);
  765. }
  766. //
  767. // If formatting quick, set this display
  768. //
  769. if (CancelInfo.Info.Format.fQuick &&
  770. CANCEL_FORMAT == CancelInfo.eCancelType) {
  771. lstrcpy (buffer, GetStringResource (IDS_QUICKFORMATTINGTITLE));
  772. SendDlgItemMessage(hDlg, IDD_TEXT, WM_SETTEXT, 0, (LPARAM)cszEmptyString);
  773. bLastQuick = TRUE;
  774. } else {
  775. if (bLastQuick) {
  776. lstrcpy (buffer, GetStringResource (IDS_PERCENTCOMPLETE));
  777. SendDlgItemMessage(hDlg, IDD_TEXT, WM_SETTEXT, 0, (LPARAM)buffer);
  778. bLastQuick = FALSE;
  779. }
  780. wsprintf(buffer, SZ_PERCENTFORMAT, CancelInfo.nPercentDrawn);
  781. }
  782. GetTextExtentPoint32(hDC, buffer, lstrlen(buffer), &size);
  783. xText = rectGG.left
  784. + ((rectGG.right - rectGG.left) - size.cx) / 2;
  785. yText = rectGG.top
  786. + ((rectGG.bottom - rectGG.top) - size.cy) / 2;
  787. nDivideRects = ((rectGG.right - rectGG.left) * CancelInfo.nPercentDrawn) / 100;
  788. // Paint in the "done so FAR" rectangle of the gas
  789. // gauge with blue background and white text
  790. SetRect(&rectDone, rectGG.left, rectGG.top,
  791. rectGG.left + nDivideRects, rectGG.bottom);
  792. SetTextColor(hDC, RGB(255, 255, 255));
  793. SetBkColor(hDC, RGB(0, 0, 255));
  794. ExtTextOut(hDC, xText, yText, ETO_CLIPPED | ETO_OPAQUE,
  795. &rectDone, buffer, lstrlen(buffer), NULL);
  796. // Paint in the "still left to do" rectangle of the gas
  797. // gauge with white background and blue text
  798. SetRect(&rectLeftToDo, rectGG.left+nDivideRects, rectGG.top,
  799. rectGG.right, rectGG.bottom);
  800. SetTextColor(hDC, RGB(0, 0, 255));
  801. SetBkColor(hDC, RGB(255, 255, 255));
  802. ExtTextOut(hDC, xText, yText, ETO_CLIPPED | ETO_OPAQUE,
  803. &rectLeftToDo, buffer, lstrlen(buffer), NULL);
  804. if (hOldFont) {
  805. SelectObject(hDC, hOldFont);
  806. }
  807. EndPaint(hDlg, &ps);
  808. return TRUE;
  809. }
  810. case FS_CANCELUPDATE:
  811. InvalidateRect(hDlg, &rectGG, TRUE);
  812. UpdateWindow(hDlg);
  813. return TRUE;
  814. default:
  815. return FALSE;
  816. }
  817. }
  818. static
  819. BOOL
  820. InitUserData (
  821. IN HWND hWnd
  822. )
  823. /*++
  824. Routine Description:
  825. initializes the CancelInfo data structure used to format the disk
  826. Arguments:
  827. Window handle of calling function
  828. Return Value:
  829. TRUE If library loaded and data initialized
  830. --*/
  831. {
  832. CancelInfo.hCancelDlg = NULL;
  833. CancelInfo.bCancel = FALSE;
  834. CancelInfo.hThread = NULL;
  835. CancelInfo.fmifsSuccess = FmifsLoaded(hWnd);
  836. CancelInfo.dReason = 0;
  837. CancelInfo.fuStyle = 0;
  838. CancelInfo.nPercentDrawn = 0;
  839. CancelInfo.eCancelType = CANCEL_NULL;
  840. CancelInfo.bModal = TRUE;
  841. CancelInfo.Info.Format.iFormatDrive = 0;
  842. CancelInfo.Info.Format.fmMediaType = Unknown;
  843. CancelInfo.Info.Format.fQuick = FALSE;
  844. CancelInfo.Info.Format.fFlags = 0;
  845. CancelInfo.Info.Format.szLabel[0] = 0;
  846. CancelInfo.Info.Copy.iSourceDrive = 0;
  847. CancelInfo.Info.Copy.iDestDrive = 0;
  848. CancelInfo.Info.Copy.bFormatDest = FALSE;
  849. if (CancelInfo.fmifsSuccess) {
  850. bDataInitialized = TRUE;
  851. return TRUE;
  852. } else {
  853. return FALSE;
  854. }
  855. }
  856. BOOL
  857. FormatDiskInDrive (
  858. IN HWND hWnd, // owner window
  859. IN TCHAR cDrive, // drive letter to format (only A or B)
  860. IN LPCTSTR szLabel, // label text
  861. IN BOOL bConfirmFormat // prompt with "r-u-sure?" dialog
  862. )
  863. /*++
  864. Routine Description:
  865. formats the floppy disk in the specified drive and labels it if desired.
  866. Always use a complete format.
  867. Arguments:
  868. IN HWND hWnd, // owner window
  869. IN TCHAR cDrive, // drive letter to format (only A or B)
  870. IN LPCTSTR szLabel, // label text
  871. IN BOOL bConfirmFormat // prompt with "r-u-sure?" dialog before formatting
  872. Return Value:
  873. TRUE if disk is formatted
  874. FALSE if not
  875. --*/
  876. {
  877. UINT nDlgBox;
  878. #if defined(JAPAN) && defined(_X86_)
  879. // fixed kkntbug #11940
  880. // Network client administrator can not make install disks on PC with C drive as FD
  881. LONG lFloppyDiskSize;
  882. #endif
  883. #ifndef JAPAN
  884. // fixed kkntbug #11940
  885. // Network client administrator can not make install disks on PC with C drive as FD
  886. // check input argument
  887. switch (cDrive){
  888. case TEXT('A'):
  889. case TEXT('a'):
  890. case TEXT('B'):
  891. case TEXT('b'):
  892. break;
  893. default:
  894. SetLastError (ERROR_INVALID_PARAMETER);
  895. return FALSE;
  896. }
  897. #endif
  898. if (lstrlen(szLabel) > MAXLABELLEN) {
  899. SetLastError (ERROR_INVALID_PARAMETER);
  900. return FALSE;
  901. }
  902. // make sure the DLL and data structures are initialized
  903. if (!bDataInitialized) {
  904. if (!InitUserData (hWnd)) {
  905. SetLastError (ERROR_FILE_NOT_FOUND);
  906. return FALSE;
  907. }
  908. }
  909. // set the remaining fields to format the diskette
  910. CancelInfo.hThread = NULL;
  911. CancelInfo.hCancelDlg = NULL;
  912. CancelInfo.eCancelType = CANCEL_FORMAT;
  913. CancelInfo.bCancel = FALSE;
  914. CancelInfo.dReason = 0;
  915. CancelInfo.nPercentDrawn = 0;
  916. CancelInfo.Info.Format.iFormatDrive = (cDrive - TEXT('A'));
  917. CancelInfo.Info.Format.fmMediaType = GetDriveTypeFromDriveLetter (cDrive);
  918. if (CancelInfo.Info.Format.fmMediaType == FmMediaUnknown) {
  919. switch (GetFloppyDiskSize(cDrive)) {
  920. case 3:
  921. CancelInfo.Info.Format.fmMediaType = FmMediaF3_1Pt44_512;
  922. break;
  923. case 5:
  924. CancelInfo.Info.Format.fmMediaType = FmMediaF5_1Pt2_512;
  925. break;
  926. #ifdef JAPAN
  927. // fixed kkntbug #11940
  928. // Network client administrator can not make install disks on PC with C drive as FD
  929. case F3_12:
  930. CancelInfo.Info.Format.fmMediaType = FmMediaF3_1Pt2_512;
  931. break;
  932. case F3_123:
  933. CancelInfo.Info.Format.fmMediaType = FmMediaF3_1Pt23_1024;
  934. break;
  935. case F5_123:
  936. CancelInfo.Info.Format.fmMediaType = FmMediaF5_1Pt23_1024;
  937. break;
  938. #endif
  939. default:
  940. return FALSE;
  941. }
  942. CancelInfo.Info.Format.fQuick = FALSE;
  943. } else {
  944. #if defined(JAPAN) && defined(_X86_)
  945. // fixed kkntbug #11940
  946. // Network client administrator can not make install disks on PC with C drive as FD
  947. lFloppyDiskSize = GetFloppyDiskSize(cDrive);
  948. if ( ((GetKeyboardType(1)&0xff00) == OEM_ID_PC98) &&
  949. ((lFloppyDiskSize == 3) ||
  950. (lFloppyDiskSize == F3_123) ||
  951. (lFloppyDiskSize == F3_12)) ) {
  952. if (CancelInfo.Info.Format.fmMediaType == FmMediaF5_1Pt23_1024) {
  953. CancelInfo.Info.Format.fmMediaType = FmMediaF3_1Pt23_1024;
  954. }
  955. if (CancelInfo.Info.Format.fmMediaType == FmMediaF5_1Pt2_512) {
  956. CancelInfo.Info.Format.fmMediaType = FmMediaF3_1Pt2_512;
  957. }
  958. }
  959. #endif
  960. //
  961. // Always do a full format.
  962. //
  963. CancelInfo.Info.Format.fQuick = FALSE;
  964. }
  965. CancelInfo.Info.Format.fFlags = FF_ONLYONE;
  966. lstrcpy (CancelInfo.Info.Format.szLabel, szLabel);
  967. if (bConfirmFormat) {
  968. if (DisplayMessageBox(hWnd,
  969. IDS_DISKCOPYCONFIRM,
  970. IDS_DISKCOPYCONFIRMTITLE,
  971. MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON1) != IDYES)
  972. // bail out here if they don't want to format the disk
  973. return FALSE;
  974. }
  975. // make sure disk is in drive and prompt if not
  976. while (!DriveLoaded (cDrive, FALSE)) {
  977. if (DisplayMessageBox (hWnd,
  978. IDS_INSERTDEST,
  979. FMT_INSERT_FLOPPY,
  980. MB_OKCANCEL_TASK_INFO) == IDCANCEL) {
  981. return FALSE;
  982. }
  983. }
  984. // display formatting... dialog box
  985. nDlgBox = (int)DialogBox(GetModuleHandle(NULL), (LPTSTR) MAKEINTRESOURCE(CANCELDLG), hWnd, CancelDlgProc);
  986. if (nDlgBox == IDOK) {
  987. if (CancelInfo.dReason != 0) {
  988. // display reason for not being formatted if it didn't work
  989. DisplayMessageBox (hWnd,
  990. CancelInfo.dReason,
  991. IDS_APP_NAME,
  992. MB_OK_TASK_EXCL);
  993. return FALSE;
  994. } else {
  995. return TRUE;
  996. }
  997. } else {
  998. return FALSE;
  999. }
  1000. }
  1001. BOOL
  1002. LabelDiskInDrive (
  1003. IN HWND hWnd, // owner window
  1004. IN TCHAR cDrive, // drive letter to format (only A or B)
  1005. IN LPCTSTR szLabel // label text
  1006. )
  1007. /*++
  1008. Routine Description:
  1009. labels the floppy disk in the specified drive.
  1010. Arguments:
  1011. IN HWND hWnd, // owner window
  1012. IN TCHAR cDrive, // drive letter to label (only A or B)
  1013. IN LPCTSTR szLabel, // label text
  1014. Return Value:
  1015. TRUE if disk is formatted
  1016. FALSE if not
  1017. --*/
  1018. {
  1019. TCHAR szDrive[4];
  1020. #ifndef JAPAN
  1021. // check input argument
  1022. switch (cDrive){
  1023. case TEXT('A'):
  1024. case TEXT('a'):
  1025. case TEXT('B'):
  1026. case TEXT('b'):
  1027. break;
  1028. default:
  1029. SetLastError (ERROR_INVALID_PARAMETER);
  1030. return FALSE;
  1031. }
  1032. #endif
  1033. if (lstrlen(szLabel) > MAXLABELLEN) {
  1034. SetLastError (ERROR_INVALID_PARAMETER);
  1035. return FALSE;
  1036. }
  1037. // make sure the DLL and data structures are initialized
  1038. if (!bDataInitialized) {
  1039. if (!InitUserData (hWnd)) {
  1040. SetLastError (ERROR_FILE_NOT_FOUND);
  1041. return FALSE;
  1042. }
  1043. }
  1044. szDrive[0] = cDrive;
  1045. szDrive[1] = cColon;
  1046. szDrive[2] = 0;
  1047. // make sure disk is in drive and prompt if not
  1048. while (!DriveLoaded (cDrive, FALSE)) {
  1049. if (DisplayMessageBox (hWnd,
  1050. IDS_INSERTDEST,
  1051. FMT_INSERT_FLOPPY,
  1052. MB_OKCANCEL_TASK_INFO) == IDCANCEL) {
  1053. return FALSE;
  1054. }
  1055. }
  1056. return (*lpfnSetLabel)(szDrive, (PWSTR)szLabel);
  1057. }