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

/*++
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
#ifdef JAPAN
// fixed kkntbug #11940
// Network client administrator can not make install disks on PC with C drive as FD
#define OEM_ID_PC98 0X0D00
//
// Japanese specific floppy format styles
//
#define F3_12 1 // 3.5" drive that supports 1.2M-byte format
#define F3_123 2 // 3.5" drive that supports 1.23M-byte format
#define F5_123 4 // 5.25" drive that supports 1.23M-byte format
#endif
//
// 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
// Japanese specific floppy format styles
F3_12 if the drive is a 3.5" drive that supports 1.2M-byte format
F3_123 if the drive is a 3.5" drive that supports 1.23M-byte format
F5_123 if the drive is a 5.25" drive that supports 1.23M-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
#ifndef JAPAN
// fixed kkntbug #11940
// Network client administrator can not make install disks on PC with C drive as FD
// 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;
}
#endif
// 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;
#ifdef JAPAN
// fixed kkntbug #11940
// Network client administrator can not make install disks on PC with C drive as FD
case F5_1Pt23_1024:
lSize = F5_123;
break;
case F3_1Pt2_512:
lSize = F3_12;
break;
case F3_1Pt23_1024:
lSize = F3_123;
break;
#endif
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;
}
//
// 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) {
#ifdef JAPAN
// fixed kkntbug #11940
// Network client administrator can not make install disks on PC with C drive as FD
case (F3_1Pt2_512): return FmMediaF3_1Pt2_512;
case (F3_1Pt23_1024): return FmMediaF3_1Pt23_1024;
case (F5_1Pt23_1024): return FmMediaF5_1Pt23_1024;
#endif
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
INT_PTR
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;
static HFONT hFont = NULL;
switch (message) {
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDCANCEL:
DestroyCancelWindow();
if (hFont != NULL) {
DeleteObject(hFont);
hFont = NULL;
}
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;
}
}
// a-jagram: bug fix 305171
// Create the font
if (hFont == NULL) { // it should be
LOGFONT lf;
HGDIOBJ hGObj;
hGObj = GetStockObject(SYSTEM_FONT);
if( hGObj != NULL ) {
if (GetObject(hGObj, sizeof(lf), (LPVOID) &lf)) {
lstrcpy(lf.lfFaceName, TEXT("MS Shell Dlg"));
hFont = CreateFontIndirect(&lf);
}
}
}
// 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;
HGDIOBJ hOldFont = NULL;
// 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 (hFont) {
hOldFont = SelectObject(hDC, hFont);
}
//
// 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);
if (hOldFont) {
SelectObject(hDC, hOldFont);
}
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.
Always use a complete format.
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;
#if defined(JAPAN) && defined(_X86_)
// fixed kkntbug #11940
// Network client administrator can not make install disks on PC with C drive as FD
LONG lFloppyDiskSize;
#endif
#ifndef JAPAN
// fixed kkntbug #11940
// Network client administrator can not make install disks on PC with C drive as FD
// 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;
}
#endif
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;
#ifdef JAPAN
// fixed kkntbug #11940
// Network client administrator can not make install disks on PC with C drive as FD
case F3_12:
CancelInfo.Info.Format.fmMediaType = FmMediaF3_1Pt2_512;
break;
case F3_123:
CancelInfo.Info.Format.fmMediaType = FmMediaF3_1Pt23_1024;
break;
case F5_123:
CancelInfo.Info.Format.fmMediaType = FmMediaF5_1Pt23_1024;
break;
#endif
default:
return FALSE;
}
CancelInfo.Info.Format.fQuick = FALSE;
} else {
#if defined(JAPAN) && defined(_X86_)
// fixed kkntbug #11940
// Network client administrator can not make install disks on PC with C drive as FD
lFloppyDiskSize = GetFloppyDiskSize(cDrive);
if ( ((GetKeyboardType(1)&0xff00) == OEM_ID_PC98) &&
((lFloppyDiskSize == 3) ||
(lFloppyDiskSize == F3_123) ||
(lFloppyDiskSize == F3_12)) ) {
if (CancelInfo.Info.Format.fmMediaType == FmMediaF5_1Pt23_1024) {
CancelInfo.Info.Format.fmMediaType = FmMediaF3_1Pt23_1024;
}
if (CancelInfo.Info.Format.fmMediaType == FmMediaF5_1Pt2_512) {
CancelInfo.Info.Format.fmMediaType = FmMediaF3_1Pt2_512;
}
}
#endif
//
// Always do a full format.
//
CancelInfo.Info.Format.fQuick = FALSE;
}
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 = (int)DialogBox(GetModuleHandle(NULL), (LPTSTR) MAKEINTRESOURCE(CANCELDLG), hWnd, 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];
#ifndef JAPAN
// 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;
}
#endif
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);
}