1165 lines
33 KiB
C
1165 lines
33 KiB
C
/*++
|
||
|
||
Routine Description:
|
||
|
||
contains functions to format a floppy disk
|
||
|
||
Arguments:
|
||
|
||
|
||
|
||
Return Value:
|
||
|
||
|
||
|
||
--*/
|
||
#include <windows.h> // required for all Windows applications
|
||
#include <tchar.h> // 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);
|
||
}
|
||
|