/*++ Routine Description: contains functions to format a floppy disk Arguments: Return Value: --*/ #include // required for all Windows applications #include // unicode definitions #include "otnboot.h" // application definitions #include "otnbtdlg.h" // dialog box constants #include "fmifs.h" // file manager IFS DLL functions // // local windows messages // #define FS_CANCELUPDATE (WM_USER+104) // // Disk format information structure // #define FF_ONLYONE 0x1000 #define FF_RETRY 0x4000 typedef struct _CANCEL_INFO { HWND hCancelDlg; BOOL bCancel; HANDLE hThread; BOOL fmifsSuccess; UINT dReason; UINT fuStyle; // Message box style INT nPercentDrawn; // percent drawn so FAR enum _CANCEL_TYPE { CANCEL_NULL=0, CANCEL_FORMAT, CANCEL_COPY, CANCEL_BACKUP, CANCEL_RESTORE, CANCEL_COMPRESS, CANCEL_UNCOMPRESS } eCancelType; BOOL bModal; struct _INFO { struct _FORMAT { INT iFormatDrive; FMIFS_MEDIA_TYPE fmMediaType; BOOL fQuick; DWORD fFlags; // FF_ONLYONE = 0x1000 TCHAR szLabel[MAXLABELLEN+1]; } Format; struct _COPY { INT iSourceDrive; INT iDestDrive; BOOL bFormatDest; } Copy; } Info; } CANCEL_INFO, *PCANCEL_INFO; static HANDLE hfmifsDll = NULL; // dll w/ file system utils static TCHAR szFmifsDll[] = {TEXT("fmifs.dll")}; // dll for FAT file system static TCHAR SZ_PERCENTFORMAT[] = {TEXT("%3d%%")}; // // pointers to DLL functions; // static PFMIFS_FORMAT_ROUTINE lpfnFormat = NULL; static PFMIFS_DISKCOPY_ROUTINE lpfnDiskCopy = NULL; static PFMIFS_SETLABEL_ROUTINE lpfnSetLabel = NULL; static PFMIFS_QSUPMEDIA_ROUTINE lpfnQuerySupportedMedia = NULL; // // Format dialog box information // static CANCEL_INFO CancelInfo; static BOOL bDataInitialized = FALSE; ULONG ulSpaceAvail = 0; ULONG ulTotalSpace = 0; static LONG GetFloppyDiskSize ( IN TCHAR cDrive ) /*++ Routine Description: Examines the specified floppy drive to determine if it supports 1.2M or 1.44M formats. Arguments: IN TCHAR cDrive drive letter of floppy drive to examine Return Value: 0 if unable to read drive or drive does not support a HD format 3 if the drive is a 3.5" drive that supports 1.44M-byte format 5 if the drive is a 5.25" drive that supports the 1.2M-byte format --*/ { #define DG_ELEMS 16 // accomodate up to 16 different formats TCHAR szDrivePath[8]; // local drive spec. string HANDLE hDrive; // handle to drive device driver DWORD dwError; // local error code DWORD dwBytesReturned; // size of buffer returned LONG lSize; // disk size returned to calling fn. DWORD dwCount; // number of DISK_GEOMETRY structures in buffer DWORD dwEntry; // structure being evaluated DISK_GEOMETRY dgArray[DG_ELEMS]; // buffer to put data in // check input argument switch (cDrive){ case TEXT('A'): case TEXT('a'): case TEXT('B'): case TEXT('b'): break; default: SetLastError (ERROR_INVALID_PARAMETER); return 0; } // make NT device path for drive szDrivePath[0] = cBackslash; szDrivePath[1] = cBackslash; szDrivePath[2] = cPeriod; szDrivePath[3] = cBackslash; szDrivePath[4] = cDrive; szDrivePath[5] = cColon; szDrivePath[6] = 0; szDrivePath[7] = 0; // open drive hDrive = CreateFile ( szDrivePath, // drive to open 0, // just talk to the driver, not the drive FILE_SHARE_READ | FILE_SHARE_WRITE, // allow sharing NULL, // default security OPEN_EXISTING, // open existing device FILE_ATTRIBUTE_NORMAL, // this is ignored NULL); // no template if (hDrive == INVALID_HANDLE_VALUE) { // unable to open drive so return error dwError = GetLastError (); return 0; } // get device information if (DeviceIoControl (hDrive, IOCTL_DISK_GET_MEDIA_TYPES, NULL, 0, // no input buffer &dgArray[0], sizeof(DISK_GEOMETRY)*DG_ELEMS,// output buffer info &dwBytesReturned, NULL)) { // return information // see if at least one entry was returned if (dwBytesReturned >= sizeof(DISK_GEOMETRY)) { dwCount = dwBytesReturned / sizeof(DISK_GEOMETRY); // go through array to see if there's a desired entry // i.e. a HD format in the list of supported formats for (lSize = 0, dwEntry = 0; (dwEntry < dwCount) && (lSize == 0); dwEntry++) { switch (dgArray[dwEntry].MediaType) { // only return a size if a supported // format is allowed by this drive case F5_1Pt2_512: lSize = 5; break; case F3_1Pt44_512: lSize = 3; break; case F5_360_512: case F5_320_512: case F5_320_1024: case F5_180_512: case F5_160_512: case F3_2Pt88_512: case F3_20Pt8_512: case F3_720_512: default: lSize = 0; break; } } } else { // no data returned so return error dwError = GetLastError (); SetLastError (ERROR_NO_DATA); lSize = 0; } } else { // unable to read device driver info dwError = GetLastError (); lSize = 0; } // close handle and return data found. CloseHandle (hDrive); return lSize; } static BOOL DriveLoaded ( IN TCHAR cDrive, IN BOOL bCheckFormat ) /*++ Routine Description: formats call to MediaPresent function for use with just a drive letter Arguments: IN TCHAR cDrive drive letter to detect. Return Value: TRUE if a disk (formatted or unformatted) is detected. FALSE if disk is not present in drive --*/ { TCHAR szPath[4]; szPath[0] = cDrive; szPath[1] = cColon; szPath[2] = cBackslash; szPath[3] = 0; return MediaPresent (szPath, bCheckFormat); } static VOID CancelDlgQuit( VOID ) ///////////////////////////////////////////////////////////////////// // // Name: CancelDlgQuit // // Synopsis: Quits the cancel modeless dialog (status for diskcopy/format) // // IN: VOID // // Return: VOID // // Assumes: Called from worker thread only; CancelInfo.hThread valid // // Effects: Kills calling thread // // // Notes: // ///////////////////////////////////////////////////////////////////// { // // Close thread if successful // if (CancelInfo.hThread) { CloseHandle(CancelInfo.hThread); CancelInfo.hThread = NULL; } else { // // BUGBUG // } // // At this point, when we call FS_CANCELEND, // the other thread thinks that this one has died since // CancelInfo.hThread is NULL. // This is exactly what we want, since we will very shortly // exit after the SendMessage. // EndDialog (CancelInfo.hCancelDlg, IDOK); ExitThread(0L); } static BOOL Callback_Function( IN FMIFS_PACKET_TYPE PacketType, IN DWORD PacketLength, IN PVOID PacketData ) /*++ Routine Description: Callback function used by IFS dll (stolen from Winfile code) Arguments: Return Value: --*/ { TCHAR szTemp[128]; // Quit if told to do so.. if (CancelInfo.bCancel) return FALSE; switch (PacketType) { case FmIfsPercentCompleted: // // If we are copying and we just finished a destination format, // then set the window text back to the original message // if (CANCEL_COPY == CancelInfo.eCancelType && CancelInfo.Info.Copy.bFormatDest) { CancelInfo.Info.Copy.bFormatDest = FALSE; lstrcpy (szTemp, GetStringResource (CancelInfo.Info.Copy.bFormatDest ? IDS_FORMATTINGDEST : IDS_COPYINGDISKTITLE)); SetWindowText(CancelInfo.hCancelDlg, szTemp); } CancelInfo.nPercentDrawn = ((PFMIFS_PERCENT_COMPLETE_INFORMATION)PacketData)->PercentCompleted; PostMessage(CancelInfo.hCancelDlg, FS_CANCELUPDATE, ((PFMIFS_PERCENT_COMPLETE_INFORMATION)PacketData)->PercentCompleted, 0L); break; case FmIfsFormatReport: ulTotalSpace = ((PFMIFS_FORMAT_REPORT_INFORMATION)PacketData)->KiloBytesTotalDiskSpace * 1024L; ulSpaceAvail = ((PFMIFS_FORMAT_REPORT_INFORMATION)PacketData)->KiloBytesAvailable * 1024L; break; case FmIfsInsertDisk: switch(((PFMIFS_INSERT_DISK_INFORMATION)PacketData)->DiskType) { case DISK_TYPE_GENERIC: CancelInfo.fuStyle = MB_OK_TASK_INFO; return DisplayMessageBox(CancelInfo.hCancelDlg, IDS_INSERTSRC, IDS_COPYDISK, CancelInfo.fuStyle); case DISK_TYPE_SOURCE: CancelInfo.fuStyle = MB_OK_TASK_INFO; return DisplayMessageBox(CancelInfo.hCancelDlg, IDS_INSERTSRC, IDS_COPYDISK, CancelInfo.fuStyle); case DISK_TYPE_TARGET: CancelInfo.fuStyle = MB_OK_TASK_INFO; return DisplayMessageBox(CancelInfo.hCancelDlg, IDS_INSERTDEST, IDS_COPYDISK, CancelInfo.fuStyle); case DISK_TYPE_SOURCE_AND_TARGET: CancelInfo.fuStyle = MB_OK_TASK_INFO; return DisplayMessageBox(CancelInfo.hCancelDlg, IDS_INSERTSRCDEST, IDS_COPYDISK, CancelInfo.fuStyle); } break; case FmIfsIncompatibleFileSystem: CancelInfo.dReason = IDS_FFERR_INCFS; break; case FmIfsFormattingDestination: CancelInfo.Info.Copy.bFormatDest = TRUE; lstrcpy (szTemp, GetStringResource ( (CancelInfo.Info.Copy.bFormatDest ? IDS_FORMATTINGDEST : IDS_COPYINGDISKTITLE))); SetWindowText(CancelInfo.hCancelDlg, szTemp); CancelInfo.nPercentDrawn = ((PFMIFS_PERCENT_COMPLETE_INFORMATION)PacketData)->PercentCompleted; PostMessage(CancelInfo.hCancelDlg, FS_CANCELUPDATE, ((PFMIFS_PERCENT_COMPLETE_INFORMATION)PacketData)->PercentCompleted, 0L); break; case FmIfsIncompatibleMedia: CancelInfo.fuStyle = MB_ICONHAND | MB_OK; return DisplayMessageBox(CancelInfo.hCancelDlg, IDS_COPYSRCDESTINCOMPAT, IDS_COPYDISK, CancelInfo.fuStyle); case FmIfsAccessDenied: CancelInfo.dReason = IDS_FFERR_ACCESSDENIED; break; case FmIfsMediaWriteProtected: CancelInfo.dReason = IDS_FFERR_DISKWP; break; case FmIfsCantLock: CancelInfo.dReason = IDS_FFERR_CANTLOCK; break; case FmIfsBadLabel: CancelInfo.fuStyle = MB_OK_TASK_EXCL; return DisplayMessageBox(CancelInfo.hCancelDlg, IDS_FFERR_BADLABEL, IDS_COPYERROR + FUNC_LABEL, CancelInfo.fuStyle); case FmIfsCantQuickFormat: // Can't quick format, ask if user wants to regular format: CancelInfo.fuStyle = MB_ICONEXCLAMATION | MB_YESNO; if (IDYES == DisplayMessageBox( CancelInfo.hCancelDlg, IDS_FORMATQUICKFAILURE, IDS_FORMATERR, CancelInfo.fuStyle)) { CancelInfo.Info.Format.fQuick = FALSE; CancelInfo.Info.Format.fFlags |= FF_RETRY; } else { // // Just fake a cancel // CancelInfo.fmifsSuccess = FALSE; CancelInfo.bCancel = TRUE; } break; case FmIfsIoError: switch(((PFMIFS_IO_ERROR_INFORMATION)PacketData)->DiskType) { case DISK_TYPE_GENERIC: CancelInfo.dReason = IDS_FFERR_GENIOERR; break; case DISK_TYPE_SOURCE: CancelInfo.dReason = IDS_FFERR_SRCIOERR; break; case DISK_TYPE_TARGET: CancelInfo.dReason = IDS_FFERR_DSTIOERR; break; case DISK_TYPE_SOURCE_AND_TARGET: CancelInfo.dReason = IDS_FFERR_SRCDSTIOERR; break; } break; case FmIfsFinished: CancelInfo.fmifsSuccess = ((PFMIFS_FINISHED_INFORMATION)PacketData)->Success; break; default: break; } return TRUE; } static VOID FormatDrive( IN PVOID ThreadParameter ) /*++ Routine Description: Thread routine to format the floppy diskette as described in the CancelInfo data structure. Arguments: Not used Return Value: None --*/ { WCHAR wszDrive[3]; WCHAR wszFileSystem[4] = L"FAT"; wszDrive[0] = (WCHAR)(CancelInfo.Info.Format.iFormatDrive + cA); wszDrive[1] = cColon; wszDrive[2] = 0; #define wszLabel CancelInfo.Info.Format.szLabel do { CancelInfo.Info.Format.fFlags &= ~FF_RETRY; (*lpfnFormat)(wszDrive, CancelInfo.Info.Format.fmMediaType, wszFileSystem, wszLabel, (BOOLEAN)CancelInfo.Info.Format.fQuick, (FMIFS_CALLBACK)&Callback_Function); } while (CancelInfo.Info.Format.fFlags & FF_RETRY); CancelDlgQuit(); } static FMIFS_MEDIA_TYPE GetDriveTypeFromDriveLetter ( IN TCHAR cDrive ) /*++ Routine Description: returns the drive type of the drive specified in the path argument Arguments: IN LPCTSTR szPath path on drive to examine Return Value: MEDIA_TYPE value identifying drive type in format compatible with IFS DLL --*/ { HANDLE hFloppy; DWORD dwRetSize; DISK_GEOMETRY dgFloppy; TCHAR szDevicePath[16]; UINT nDriveType; UINT nErrorMode; // make device name from drive letter szDevicePath[0] = cBackslash; szDevicePath[1] = cBackslash; szDevicePath[2] = cPeriod; szDevicePath[3] = cBackslash; szDevicePath[4] = cDrive; szDevicePath[5] = cColon; // colon szDevicePath[6] = cBackslash; // null terminator szDevicePath[7] = 0; // null terminator nDriveType = GetDriveType((LPTSTR)&szDevicePath[4]); // see if this is a remote disk and exit if it is. if (nDriveType == DRIVE_REMOTE) return FmMediaUnknown; if ((nDriveType == DRIVE_REMOVABLE) || (nDriveType == DRIVE_CDROM)) { // make device path into an NT device path szDevicePath[6] = 0; // null terminator // disable windows error message popup nErrorMode = SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX); // open device to get type hFloppy = CreateFile ( szDevicePath, GENERIC_READ, (FILE_SHARE_READ | FILE_SHARE_WRITE), NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFloppy != INVALID_HANDLE_VALUE) { // get drive information if (!DeviceIoControl (hFloppy, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &dgFloppy, sizeof(DISK_GEOMETRY), &dwRetSize, NULL) ){ // unable to get data so set to unknown dgFloppy.MediaType = Unknown; } // else return data from returned structure CloseHandle (hFloppy); } else { // unable to open handle to device dgFloppy.MediaType = Unknown; } SetErrorMode (nErrorMode); // reset error mode } // translate from MEDIA_TYPE to FMIFS_MEDIA_TYPE here switch (dgFloppy.MediaType) { case (F5_1Pt2_512): return FmMediaF5_1Pt2_512; case (F3_1Pt44_512): return FmMediaF3_1Pt44_512; case (F3_2Pt88_512): return FmMediaF3_2Pt88_512; case (F3_20Pt8_512): return FmMediaF3_20Pt8_512; case (F3_720_512): return FmMediaF3_720_512; case (F5_360_512): return FmMediaF5_360_512; case (F5_320_512): return FmMediaF5_320_512; case (F5_320_1024): return FmMediaF5_320_1024; case (F5_180_512): return FmMediaF5_180_512; case (F5_160_512): return FmMediaF5_160_512; case (FixedMedia): return FmMediaFixed; case (Unknown): return FmMediaUnknown; default: return FmMediaUnknown; } } static BOOL FmifsLoaded( IN HWND hWnd ) /*++ Routine Description: loads (if not already loaded) the File Manager IFS dll and initializes the pointers to it's functions Arguments: IN HWND hWnd window handle of parent, used for MessageBox calls Return Value: TRUE if file loaded FALSE if not --*/ { // Load the fmifs dll. if (hfmifsDll < (HANDLE)32) { hfmifsDll = LoadLibrary(szFmifsDll); if (hfmifsDll < (HANDLE)32) { /* FMIFS not available. */ DisplayMessageBox(hWnd, IDS_APP_NAME, IDS_FMIFSLOADERR, MB_OK | MB_ICONEXCLAMATION | MB_SYSTEMMODAL); hfmifsDll = NULL; return FALSE; } else { lpfnFormat = (PVOID)GetProcAddress(hfmifsDll, "Format"); lpfnQuerySupportedMedia = (PVOID)GetProcAddress(hfmifsDll, "QuerySupportedMedia"); lpfnSetLabel = (PVOID)GetProcAddress(hfmifsDll, "SetLabel"); lpfnDiskCopy = (PVOID)GetProcAddress(hfmifsDll, "DiskCopy"); if (!lpfnFormat || !lpfnQuerySupportedMedia || !lpfnSetLabel || !lpfnDiskCopy) { DisplayMessageBox(hWnd, IDS_APP_NAME, IDS_FMIFSLOADERR, MB_OK | MB_ICONEXCLAMATION | MB_SYSTEMMODAL); FreeLibrary(hfmifsDll); hfmifsDll = NULL; return FALSE; } } } return TRUE; } static VOID DestroyCancelWindow( VOID ) /*++ Routine Description: Destroys the CANCEL (i.e. Format) window. Arguments: None Return Value: None --*/ { if (!CancelInfo.hCancelDlg) return; if (CancelInfo.bModal) { EndDialog(CancelInfo.hCancelDlg,0); } else { DestroyWindow(CancelInfo.hCancelDlg); } CancelInfo.hCancelDlg = NULL; } static BOOL CancelDlgProc(HWND hDlg, IN UINT message, IN WPARAM wParam, IN LPARAM lParam ) /*------------------------- CancelDlgProc * * DESCRIPTION: * dialog procedure for the modeless dialog. two main purposes * here: * * 1. if the user chooses CANCEL we set bCancel to TRUE * which will end the PeekMessage background processing loop * * 2. handle the private FS_CANCELUPDATE message and draw * a "gas gauge" indication of how FAR the background job * has progressed * * ARGUMENTS: * stock dialog proc arguments * * RETURN VALUE: * stock dialog proc return value - BOOL * * GLOBALS READ: * none * * GLOBALS WRITTEN: * CancelInfo structure * * MESSAGES: * WM_COMMAND - handle IDCANCEL by setting bCancel to TRUE * and calling DestroyWindow to end the dialog * * WM_INITDIALOG - set control text, get coordinates of gas gauge, * disable main window so we look modal * * WM_PAINT - draw the "gas gauge" control * * FS_CANCELUPDATE - the percentage done has changed, so update * nPercentDrawn and force a repaint * * NOTES: * * The bCancel global variable is used to communicate * with the main window. If the user chooses to cancel * we set bCancel to TRUE. * * When we get the private message FS_CANCELUPDATE * we update the "gas gauge" control that indicates * what percentage of the rectangles have been drawn * so FAR. This shows that we can draw in the dialog * as the looping operation progresses. (FS_CANCELUPDATE is sent * first to hwndFrame, which sets %completed then sends message to us.) * */ { static RECT rectGG; // GasGauge rectangle DWORD Ignore; TCHAR szTemp[128]; static BOOL bLastQuick; switch (message) { case WM_COMMAND: switch (LOWORD(wParam)) { case IDCANCEL: DestroyCancelWindow(); CancelInfo.bCancel = TRUE; return TRUE; default: return FALSE; } case WM_INITDIALOG: { CancelInfo.hCancelDlg = hDlg; bLastQuick = TRUE; switch(CancelInfo.eCancelType) { case CANCEL_FORMAT: // // Formatting disk requires that we release any notification // requests on this drive. // // NotifyPause(CancelInfo.Info.Format.iFormatDrive, DRIVE_REMOVABLE); break; case CANCEL_COPY: // // Pause notifications on dest drive. // // NotifyPause(CancelInfo.Info.Copy.iDestDrive, DRIVE_REMOVABLE); lstrcpy (szTemp, GetStringResource( CancelInfo.Info.Copy.bFormatDest ? IDS_FORMATTINGDEST : IDS_COPYINGDISKTITLE)); SetWindowText(hDlg, szTemp); break; default: break; } if (!CancelInfo.hThread) { switch (CancelInfo.eCancelType) { case CANCEL_FORMAT: CancelInfo.hThread = CreateThread( NULL, // Security 0L, // Stack Size (LPTHREAD_START_ROUTINE)FormatDrive, NULL, 0L, &Ignore ); break; default: break; } } // Get the coordinates of the gas gauge static control rectangle, // and convert them to dialog client area coordinates GetClientRect(GetDlgItem(hDlg, IDD_GASGAUGE), &rectGG); ClientToScreen(GetDlgItem(hDlg, IDD_GASGAUGE), (LPPOINT)&rectGG.left); ClientToScreen(GetDlgItem(hDlg, IDD_GASGAUGE), (LPPOINT)&rectGG.right); ScreenToClient(hDlg, (LPPOINT)&rectGG.left); ScreenToClient(hDlg, (LPPOINT)&rectGG.right); return TRUE; } case WM_PAINT: { HDC hDC; PAINTSTRUCT ps; TCHAR buffer[48]; SIZE size; INT xText, yText; INT nDivideRects; RECT rectDone, rectLeftToDo; // The gas gauge is drawn by drawing a text string stating // what percentage of the job is done into the middle of // the gas gauge rectangle, and by separating that rectangle // into two parts: rectDone (the left part, filled in blue) // and rectLeftToDo(the right part, filled in white). // nDivideRects is the x coordinate that divides these two rects. // // The text in the blue rectangle is drawn white, and vice versa // This is easy to do with ExtTextOut()! hDC = BeginPaint(hDlg, &ps); // // If formatting quick, set this display // if (CancelInfo.Info.Format.fQuick && CANCEL_FORMAT == CancelInfo.eCancelType) { lstrcpy (buffer, GetStringResource (IDS_QUICKFORMATTINGTITLE)); SendDlgItemMessage(hDlg, IDD_TEXT, WM_SETTEXT, 0, (LPARAM)cszEmptyString); bLastQuick = TRUE; } else { if (bLastQuick) { lstrcpy (buffer, GetStringResource (IDS_PERCENTCOMPLETE)); SendDlgItemMessage(hDlg, IDD_TEXT, WM_SETTEXT, 0, (LPARAM)buffer); bLastQuick = FALSE; } wsprintf(buffer, SZ_PERCENTFORMAT, CancelInfo.nPercentDrawn); } GetTextExtentPoint32(hDC, buffer, lstrlen(buffer), &size); xText = rectGG.left + ((rectGG.right - rectGG.left) - size.cx) / 2; yText = rectGG.top + ((rectGG.bottom - rectGG.top) - size.cy) / 2; nDivideRects = ((rectGG.right - rectGG.left) * CancelInfo.nPercentDrawn) / 100; // Paint in the "done so FAR" rectangle of the gas // gauge with blue background and white text SetRect(&rectDone, rectGG.left, rectGG.top, rectGG.left + nDivideRects, rectGG.bottom); SetTextColor(hDC, RGB(255, 255, 255)); SetBkColor(hDC, RGB(0, 0, 255)); ExtTextOut(hDC, xText, yText, ETO_CLIPPED | ETO_OPAQUE, &rectDone, buffer, lstrlen(buffer), NULL); // Paint in the "still left to do" rectangle of the gas // gauge with white background and blue text SetRect(&rectLeftToDo, rectGG.left+nDivideRects, rectGG.top, rectGG.right, rectGG.bottom); SetTextColor(hDC, RGB(0, 0, 255)); SetBkColor(hDC, RGB(255, 255, 255)); ExtTextOut(hDC, xText, yText, ETO_CLIPPED | ETO_OPAQUE, &rectLeftToDo, buffer, lstrlen(buffer), NULL); EndPaint(hDlg, &ps); return TRUE; } case FS_CANCELUPDATE: InvalidateRect(hDlg, &rectGG, TRUE); UpdateWindow(hDlg); return TRUE; default: return FALSE; } } static BOOL InitUserData ( IN HWND hWnd ) /*++ Routine Description: initializes the CancelInfo data structure used to format the disk Arguments: Window handle of calling function Return Value: TRUE If library loaded and data initialized --*/ { CancelInfo.hCancelDlg = NULL; CancelInfo.bCancel = FALSE; CancelInfo.hThread = NULL; CancelInfo.fmifsSuccess = FmifsLoaded(hWnd); CancelInfo.dReason = 0; CancelInfo.fuStyle = 0; CancelInfo.nPercentDrawn = 0; CancelInfo.eCancelType = CANCEL_NULL; CancelInfo.bModal = TRUE; CancelInfo.Info.Format.iFormatDrive = 0; CancelInfo.Info.Format.fmMediaType = Unknown; CancelInfo.Info.Format.fQuick = FALSE; CancelInfo.Info.Format.fFlags = 0; CancelInfo.Info.Format.szLabel[0] = 0; CancelInfo.Info.Copy.iSourceDrive = 0; CancelInfo.Info.Copy.iDestDrive = 0; CancelInfo.Info.Copy.bFormatDest = FALSE; if (CancelInfo.fmifsSuccess) { bDataInitialized = TRUE; return TRUE; } else { return FALSE; } } BOOL FormatDiskInDrive ( IN HWND hWnd, // owner window IN TCHAR cDrive, // drive letter to format (only A or B) IN LPCTSTR szLabel, // label text IN BOOL bConfirmFormat // prompt with "r-u-sure?" dialog ) /*++ Routine Description: formats the floppy disk in the specified drive and labels it if desired. If the floppy has a valid format, then a Quick Format is performed. if there is no detectible format or a bad format, then a complete format is done. Arguments: IN HWND hWnd, // owner window IN TCHAR cDrive, // drive letter to format (only A or B) IN LPCTSTR szLabel, // label text IN BOOL bConfirmFormat // prompt with "r-u-sure?" dialog before formatting Return Value: TRUE if disk is formatted FALSE if not --*/ { UINT nDlgBox; // check input argument switch (cDrive){ case TEXT('A'): case TEXT('a'): case TEXT('B'): case TEXT('b'): break; default: SetLastError (ERROR_INVALID_PARAMETER); return FALSE; } if (lstrlen(szLabel) > MAXLABELLEN) { SetLastError (ERROR_INVALID_PARAMETER); return FALSE; } // make sure the DLL and data structures are initialized if (!bDataInitialized) { if (!InitUserData (hWnd)) { SetLastError (ERROR_FILE_NOT_FOUND); return FALSE; } } // set the remaining fields to format the diskette CancelInfo.hThread = NULL; CancelInfo.hCancelDlg = NULL; CancelInfo.eCancelType = CANCEL_FORMAT; CancelInfo.bCancel = FALSE; CancelInfo.dReason = 0; CancelInfo.nPercentDrawn = 0; CancelInfo.Info.Format.iFormatDrive = (cDrive - TEXT('A')); CancelInfo.Info.Format.fmMediaType = GetDriveTypeFromDriveLetter (cDrive); if (CancelInfo.Info.Format.fmMediaType == FmMediaUnknown) { switch (GetFloppyDiskSize(cDrive)) { case 3: CancelInfo.Info.Format.fmMediaType = FmMediaF3_1Pt44_512; break; case 5: CancelInfo.Info.Format.fmMediaType = FmMediaF5_1Pt2_512; break; default: return FALSE; } CancelInfo.Info.Format.fQuick = FALSE; } else { CancelInfo.Info.Format.fQuick = DriveLoaded(cDrive, TRUE); } CancelInfo.Info.Format.fFlags = FF_ONLYONE; lstrcpy (CancelInfo.Info.Format.szLabel, szLabel); if (bConfirmFormat) { if (DisplayMessageBox(hWnd, IDS_DISKCOPYCONFIRM, IDS_DISKCOPYCONFIRMTITLE, MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON1) != IDYES) // bail out here if they don't want to format the disk return FALSE; } // make sure disk is in drive and prompt if not while (!DriveLoaded (cDrive, FALSE)) { if (DisplayMessageBox (hWnd, IDS_INSERTDEST, FMT_INSERT_FLOPPY, MB_OKCANCEL_TASK_INFO) == IDCANCEL) { return FALSE; } } // display formatting... dialog box nDlgBox = DialogBox(GetModuleHandle(NULL), (LPTSTR) MAKEINTRESOURCE(CANCELDLG), hWnd, (DLGPROC) CancelDlgProc); if (nDlgBox == IDOK) { if (CancelInfo.dReason != 0) { // display reason for not being formatted if it didn't work DisplayMessageBox (hWnd, CancelInfo.dReason, IDS_APP_NAME, MB_OK_TASK_EXCL); return FALSE; } else { return TRUE; } } else { return FALSE; } } BOOL LabelDiskInDrive ( IN HWND hWnd, // owner window IN TCHAR cDrive, // drive letter to format (only A or B) IN LPCTSTR szLabel // label text ) /*++ Routine Description: labels the floppy disk in the specified drive. Arguments: IN HWND hWnd, // owner window IN TCHAR cDrive, // drive letter to label (only A or B) IN LPCTSTR szLabel, // label text Return Value: TRUE if disk is formatted FALSE if not --*/ { TCHAR szDrive[4]; // check input argument switch (cDrive){ case TEXT('A'): case TEXT('a'): case TEXT('B'): case TEXT('b'): break; default: SetLastError (ERROR_INVALID_PARAMETER); return FALSE; } if (lstrlen(szLabel) > MAXLABELLEN) { SetLastError (ERROR_INVALID_PARAMETER); return FALSE; } // make sure the DLL and data structures are initialized if (!bDataInitialized) { if (!InitUserData (hWnd)) { SetLastError (ERROR_FILE_NOT_FOUND); return FALSE; } } szDrive[0] = cDrive; szDrive[1] = cColon; szDrive[2] = 0; // make sure disk is in drive and prompt if not while (!DriveLoaded (cDrive, FALSE)) { if (DisplayMessageBox (hWnd, IDS_INSERTDEST, FMT_INSERT_FLOPPY, MB_OKCANCEL_TASK_INFO) == IDCANCEL) { return FALSE; } } return (*lpfnSetLabel)(szDrive, (PWSTR)szLabel); }