mirror of https://github.com/lianthony/NT4.0
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.
2175 lines
66 KiB
2175 lines
66 KiB
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1994 - 1995.
|
|
//
|
|
// File: format.c
|
|
//
|
|
// Contents: Implements disk formatting from a drive's context menu
|
|
//
|
|
// Functions: SHELL API SHFormatDrive
|
|
//
|
|
// file local BeginFormat
|
|
// file local DiableControls
|
|
// file local EnableControls
|
|
// file local StuffFormatInfoPtr
|
|
// file local UnstuffFormatInfoPtr
|
|
// file local GetFormatInfoPtr
|
|
// file local FileSysChange
|
|
// file local FormatCallback
|
|
// file local FormatDlgProc
|
|
// file local InitializeFormatDlg
|
|
// file local LoadFMIFS
|
|
//
|
|
// History: 2-13-95 davepl Created
|
|
// 10-15-95 brianau Added compression setting when fmifs not
|
|
// available.
|
|
// 10-23-95 brianau Enabled FMIFS support. Removed changes
|
|
// of 10-15-95.
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
#ifdef WINNT // Chicago has its own format code
|
|
|
|
#define WTEXT(quote) L##quote
|
|
|
|
#ifdef DEBUG
|
|
#define LOAD_STRING(id,buffer)\
|
|
{\
|
|
if (0==LoadStringW(HINST_THISDLL, id, buffer, ARRAYSIZE(buffer)))\
|
|
Assert(FALSE);\
|
|
}
|
|
#else
|
|
#define LOAD_STRING(id,buffer) LoadStringW(HINST_THISDLL, id, buffer, ARRAYSIZE(buffer))
|
|
#endif
|
|
|
|
const WCHAR cwsz_FAT[] = WTEXT("FAT");
|
|
const WCHAR cwsz_NTFS[] = WTEXT("NTFS");
|
|
const WCHAR cwsz_OFS[] = WTEXT("OFS");
|
|
|
|
static DWORD FmtaIds[]={IDOK, IDH_FORMATDLG_START,
|
|
IDCANCEL, IDH_CANCEL,
|
|
IDC_CAPCOMBO, IDH_FORMATDLG_CAPACITY,
|
|
IDC_FSCOMBO, IDH_FORMATDLG_FILESYS,
|
|
IDC_ASCOMBO, IDH_FORMATDLG_ALLOCSIZE,
|
|
IDC_VLABEL, IDH_FORMATDLG_LABEL,
|
|
IDC_GROUPBOX_1, IDH_COMM_GROUPBOX,
|
|
IDC_QFCHECK, IDH_FORMATDLG_QUICKFULL,
|
|
IDC_ECCHECK, IDH_FORMATDLG_COMPRESS,
|
|
IDC_FMTPROGRESS, IDH_FORMATDLG_PROGRESS,
|
|
0,0};
|
|
|
|
static DWORD ChkaIds[]={IDOK, IDH_CHKDSKDLG_START,
|
|
IDCANCEL, IDH_CHKDSKDLG_CANCEL,
|
|
IDC_GROUPBOX_1, IDH_COMM_GROUPBOX,
|
|
IDC_FIXERRORS, IDH_CHKDSKDLG_FIXERRORS,
|
|
IDC_RECOVERY, IDH_CHKDSKDLG_SCAN,
|
|
IDC_CHKDSKPROGRESS, IDH_CHKDSKDLG_PROGRESS,
|
|
0,0};
|
|
|
|
//
|
|
// The following structure encapsulates our calling into the FMIFS.DLL
|
|
//
|
|
#define HAVE_FMIFS_SUPPORT 1 // Yes, we have FMIFS support.
|
|
|
|
typedef struct tagFMIFSEntryPoints
|
|
{
|
|
HINSTANCE hFMIFS_DLL;
|
|
|
|
#ifdef HAVE_FMIFS_SUPPORT
|
|
PFMIFS_FORMATEX_ROUTINE FormatEx;
|
|
#else
|
|
PFMIFS_FORMAT_ROUTINE FormatEx;
|
|
#endif
|
|
|
|
PFMIFS_QSUPMEDIA_ROUTINE QuerySupportedMedia;
|
|
|
|
#ifdef HAVE_FMIFS_SUPPORT
|
|
PFMIFS_ENABLECOMP_ROUTINE EnableVolumeCompression;
|
|
#else
|
|
#endif
|
|
|
|
PFMIFS_CHKDSK_ROUTINE ChkDsk;
|
|
} FMIFS, * LPFMIFS;
|
|
|
|
//
|
|
// This structure described the current formatting session
|
|
//
|
|
|
|
typedef struct tagFormatInfo
|
|
{
|
|
UINT drive; // 0-based index of drive to format
|
|
UINT fmtID; // Last format ID
|
|
UINT options; // options passed to us via the API
|
|
LPFMIFS pFMIFS; // ptr to FMIFS structure, above
|
|
HWND hDlg; // handle to the format dialog
|
|
BOOL fIsFloppy; // TRUE -> its a floppy
|
|
BOOL fEnableComp; // Last "Enable Comp" choice from user
|
|
BOOL fCancelled; // User cancelled the last format
|
|
BOOL fShouldCancel; // User has clicked cancel; pending abort
|
|
BOOL fWasFAT; // Was it FAT originally?
|
|
BOOL fFinishedOK; // Did format complete sucessfully?
|
|
BOOL fErrorAlready; // Did we put up an error dialog already?
|
|
DWORD dwClusterSize; // Orig NT cluster size, or last choice
|
|
WCHAR wszVolName[MAX_PATH]; // Volume Label
|
|
WCHAR wszWinTitle[MAX_PATH]; // Format dialog window title
|
|
WCHAR wszDriveName[4]; // Root path to drive (eg: A:\)
|
|
HANDLE hThread; // Handle of format thread
|
|
|
|
// Array of media types supported by the device
|
|
FMIFS_MEDIA_TYPE rgMedia[IDS_FMT_MEDIA11-IDS_FMT_MEDIA0];
|
|
|
|
// Used to cache the enabled/disabled state of the dialog controls
|
|
BOOL fControlEnabled[DLG_FORMATDISK_NUMCONTROLS];
|
|
|
|
} FORMATINFO, * LPFORMATINFO;
|
|
|
|
//
|
|
// An enumeration to make the filesystem combo-box code more readble
|
|
//
|
|
|
|
typedef enum tagFILESYSENUM
|
|
{
|
|
e_FAT = 0,
|
|
e_NTFS,
|
|
e_OFS
|
|
} FILESYSENUM;
|
|
|
|
//
|
|
// Private WM_USER messages we will use. For some unknown reason, USER sends
|
|
// us a WM_USER during initialization, so I start my private messages at
|
|
// WM_USER + 0x0100
|
|
//
|
|
|
|
typedef enum tagPRIVMSGS
|
|
{
|
|
PWM_FORMATDONE = WM_USER + 0x0100,
|
|
PWM_CHKDSKDONE
|
|
} PRIVMSGS;
|
|
|
|
#define cdw_Kilobyte (1024)
|
|
#define cdw_Megabyte (1024 * 1024)
|
|
#define cdw_Gigabyte (1024 * 1024 * 1024)
|
|
|
|
#define cdwTHREADWAIT (10000) // Wait 10 seconds for fmt thread to exit
|
|
// before asking retry / killing it
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: LoadFMIFS
|
|
//
|
|
// Synopsis: Loads FMIFS.DLL and sets up the function entry points for
|
|
// the member functions we are interested in.
|
|
//
|
|
// Arguments: [pFEP] -- Pointer to a FMIFSEntryPoints struc
|
|
//
|
|
// Returns: HRESULT
|
|
//
|
|
// History: 2-15-95 davepl Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
HRESULT LoadFMIFS(LPFMIFS pFMIFS)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// Load the FMIFS DLL and query for the entry points we need
|
|
//
|
|
|
|
if (NULL == (pFMIFS->hFMIFS_DLL = LoadLibrary(WTEXT("FMIFS.DLL"))))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
|
|
#ifdef HAVE_FMIFS_SUPPORT
|
|
else if (NULL == (pFMIFS->FormatEx = (PFMIFS_FORMATEX_ROUTINE)
|
|
GetProcAddress(pFMIFS->hFMIFS_DLL, "FormatEx")))
|
|
#else
|
|
else if (NULL == (pFMIFS->FormatEx = (PFMIFS_FORMAT_ROUTINE)
|
|
GetProcAddress(pFMIFS->hFMIFS_DLL, "Format")))
|
|
#endif
|
|
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
else if (NULL == (pFMIFS->QuerySupportedMedia = (PFMIFS_QSUPMEDIA_ROUTINE)
|
|
GetProcAddress(pFMIFS->hFMIFS_DLL, "QuerySupportedMedia")))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
#ifdef HAVE_FMIFS_SUPPORT
|
|
else if (NULL == (pFMIFS->EnableVolumeCompression = (PFMIFS_ENABLECOMP_ROUTINE)
|
|
GetProcAddress(pFMIFS->hFMIFS_DLL, "EnableVolumeCompression")))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
#endif
|
|
else if (NULL == (pFMIFS->ChkDsk = (PFMIFS_CHKDSK_ROUTINE)
|
|
GetProcAddress(pFMIFS->hFMIFS_DLL, "Chkdsk")))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
|
|
//
|
|
// If anything failed, and we've got the DLL loaded, release the DLL
|
|
//
|
|
|
|
if (hr != S_OK && pFMIFS->hFMIFS_DLL)
|
|
{
|
|
FreeLibrary(pFMIFS->hFMIFS_DLL);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: StuffFormatInfoPtr()
|
|
//
|
|
// Synopsis: Allocates a thread-local index slot for this thread's
|
|
// FORMATINFO pointer, if the index doesn't already exist.
|
|
// In any event, stores the FORMATINFO pointer in the slot
|
|
// and increments the index's usage count.
|
|
//
|
|
// Arguments: [pFormatInfo] -- The pointer to store
|
|
//
|
|
// Returns: HRESULT
|
|
//
|
|
// History: 2-20-95 davepl Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
//
|
|
// Thread-Local Storage index for our FORMATINFO structure pointer
|
|
//
|
|
|
|
static DWORD g_iTLSFormatInfo = 0;
|
|
static LONG g_cTLSFormatInfo = 0; // Usage count
|
|
|
|
HRESULT StuffFormatInfoPtr(LPFORMATINFO pFormatInfo)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// Allocate an index slot for our thread-local FORMATINFO pointer, if one
|
|
// doesn't already exist, then stuff our FORMATINFO ptr at that index.
|
|
//
|
|
|
|
ENTERCRITICAL;
|
|
if (0 == g_iTLSFormatInfo)
|
|
{
|
|
if (0xFFFFFFFF == (g_iTLSFormatInfo = TlsAlloc()))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
g_cTLSFormatInfo = 0;
|
|
}
|
|
if (S_OK == hr)
|
|
{
|
|
if (TlsSetValue(g_iTLSFormatInfo, (LPVOID) pFormatInfo))
|
|
{
|
|
g_cTLSFormatInfo++;
|
|
}
|
|
else
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
}
|
|
LEAVECRITICAL;
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: UnstuffFormatInfoPtr()
|
|
//
|
|
// Synopsis: Decrements the usage count on our thread-local storage
|
|
// index, and if it goes to zero the index is free'd
|
|
//
|
|
// Arguments: [none]
|
|
//
|
|
// Returns: none
|
|
//
|
|
// History: 2-20-95 davepl Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
__inline void UnstuffFormatInfoPtr()
|
|
{
|
|
ENTERCRITICAL;
|
|
if (0 == --g_cTLSFormatInfo)
|
|
{
|
|
TlsFree(g_iTLSFormatInfo);
|
|
g_iTLSFormatInfo = 0;
|
|
}
|
|
LEAVECRITICAL;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: GetFormatInfoPtr()
|
|
//
|
|
// Synopsis: Retrieves this threads FORMATINFO ptr by grabbing the
|
|
// thread-local value previously stuff'd
|
|
//
|
|
// Arguments: [none]
|
|
//
|
|
// Returns: The pointer, of course
|
|
//
|
|
// History: 2-20-95 davepl Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
__inline LPFORMATINFO GetFormatInfoPtr()
|
|
{
|
|
return TlsGetValue(g_iTLSFormatInfo);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: DisableControls
|
|
//
|
|
// Synopsis: Ghosts all controls except "Cancel", saving their
|
|
// previous state in the FORMATINFO structure
|
|
//
|
|
// Arguments: [pFormatInfo] -- Describes a format dialog session
|
|
//
|
|
// History: 2-14-95 davepl Created
|
|
//
|
|
// Notes: Also changes "Close" button text to read "Cancel"
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
void DisableControls(LPFORMATINFO pFormatInfo)
|
|
{
|
|
WCHAR wszCancel[64];
|
|
int i;
|
|
|
|
for (i = 0; i < DLG_FORMATDISK_NUMCONTROLS; i++)
|
|
{
|
|
HWND hControl = GetDlgItem(pFormatInfo->hDlg, i + DLG_FORMATDISK_FIRSTCONTROL);
|
|
|
|
pFormatInfo->fControlEnabled[i] = IsWindowEnabled(hControl);
|
|
EnableWindow(hControl, FALSE);
|
|
}
|
|
|
|
EnableWindow(GetDlgItem(pFormatInfo->hDlg, IDOK), FALSE);
|
|
|
|
LOAD_STRING( IDS_FMT_CANCEL, wszCancel );
|
|
SetWindowText(GetDlgItem(pFormatInfo->hDlg, IDCANCEL), wszCancel );
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: EnableControls
|
|
//
|
|
// Synopsis: Restores controls to the enabled/disabled state they were
|
|
// before a previous call to DisableControls().
|
|
//
|
|
// Arguments: [pFormatInfo] -- Decribes a format dialog session
|
|
//
|
|
// History: 2-14-95 davepl Created
|
|
//
|
|
// Notes: Undefined behaviour if DisableControls has not been called
|
|
// Also changes "Cancel" button to say "Close"
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
void EnableControls(LPFORMATINFO pFormatInfo)
|
|
{
|
|
WCHAR wszClose[64];
|
|
int i;
|
|
|
|
for (i = 0; i < DLG_FORMATDISK_NUMCONTROLS; i++)
|
|
{
|
|
HWND hControl = GetDlgItem(pFormatInfo->hDlg, i + DLG_FORMATDISK_FIRSTCONTROL);
|
|
EnableWindow(hControl, pFormatInfo->fControlEnabled[i]);
|
|
}
|
|
EnableWindow(GetDlgItem(pFormatInfo->hDlg, IDOK), TRUE);
|
|
|
|
LOAD_STRING( IDS_FMT_CLOSE, wszClose );
|
|
SetWindowText(GetDlgItem(pFormatInfo->hDlg, IDCANCEL), wszClose);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: SetWindowTitle
|
|
//
|
|
// Synopsis: Sets the format dialog's title to "Format A:" or
|
|
// "Formatting A:" depending on the drive letter and the
|
|
// fInProgress flag.
|
|
//
|
|
// Arguments: [pFormatInfo] -- Carries the drive letter
|
|
// [fInProgress] -- TRUE => currently formatting
|
|
//
|
|
// History: 2-14-95 davepl Created
|
|
//
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
void SetWindowTitle(LPFORMATINFO pFormatInfo, BOOL fInProgress)
|
|
{
|
|
LOAD_STRING( fInProgress ? IDS_FMT_FORMATTING:IDS_FMT_FORMAT, pFormatInfo->wszWinTitle );
|
|
|
|
lstrcat(pFormatInfo->wszWinTitle, pFormatInfo->wszDriveName);
|
|
pFormatInfo->wszDriveName[lstrlen(pFormatInfo->wszDriveName)] = WTEXT('\0');
|
|
|
|
SetWindowText(pFormatInfo->hDlg, pFormatInfo->wszWinTitle);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: FileSysChange
|
|
//
|
|
// Synopsis: Called when a user picks a filesystem in the dialog, this
|
|
// sets the states of the other relevant controls, such as
|
|
// Enable Compression, Allocation Size, etc.
|
|
//
|
|
// Arguments: [n] -- One of e_FAT, e_NTFS, or e_OFS
|
|
// [pFormatInfo] -- Current format dialog session
|
|
//
|
|
// History: 2-14-95 davepl Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
void FileSysChange(FILESYSENUM n, LPFORMATINFO pFormatInfo)
|
|
{
|
|
WCHAR wszTmp[MAX_PATH];
|
|
int i;
|
|
|
|
switch(n)
|
|
{
|
|
case e_FAT:
|
|
|
|
// Clean & Diable the Enable Compression option
|
|
|
|
SendDlgItemMessage( pFormatInfo->hDlg, IDC_ECCHECK, BM_SETCHECK, FALSE, 0 );
|
|
EnableWindow(GetDlgItem(pFormatInfo->hDlg, IDC_ECCHECK), FALSE);
|
|
|
|
SendDlgItemMessage(pFormatInfo->hDlg, IDC_ASCOMBO, CB_RESETCONTENT, 0, 0);
|
|
|
|
LOAD_STRING(IDS_FMT_ALLOC0, wszTmp );
|
|
SendDlgItemMessage(pFormatInfo->hDlg, IDC_ASCOMBO, CB_ADDSTRING, 0, (LPARAM)wszTmp);
|
|
SendDlgItemMessage(pFormatInfo->hDlg, IDC_ASCOMBO, CB_SETCURSEL, 0, 0);
|
|
|
|
break;
|
|
|
|
case e_NTFS:
|
|
case e_OFS:
|
|
|
|
EnableWindow(GetDlgItem(pFormatInfo->hDlg, IDC_ECCHECK), TRUE);
|
|
SendDlgItemMessage(pFormatInfo->hDlg, IDC_ECCHECK, BM_SETCHECK, pFormatInfo->fEnableComp, 0);
|
|
|
|
// Set up the NTFS Allocation choices, and select the current choice
|
|
|
|
SendDlgItemMessage(pFormatInfo->hDlg, IDC_ASCOMBO, CB_RESETCONTENT, 0, 0);
|
|
|
|
for ( i = IDS_FMT_ALLOC0 ; i <= IDS_FMT_ALLOC4 ; i++ )
|
|
{
|
|
LOAD_STRING( i, wszTmp );
|
|
SendDlgItemMessage( pFormatInfo->hDlg, IDC_ASCOMBO, CB_ADDSTRING, 0, (LPARAM)wszTmp );
|
|
}
|
|
|
|
switch(pFormatInfo->dwClusterSize)
|
|
{
|
|
case 512:
|
|
SendDlgItemMessage(pFormatInfo->hDlg, IDC_ASCOMBO, CB_SETCURSEL, 1, 0);
|
|
break;
|
|
|
|
case 1024:
|
|
SendDlgItemMessage(pFormatInfo->hDlg, IDC_ASCOMBO, CB_SETCURSEL, 2, 0);
|
|
break;
|
|
|
|
case 2048:
|
|
SendDlgItemMessage(pFormatInfo->hDlg, IDC_ASCOMBO, CB_SETCURSEL, 3, 0);
|
|
break;
|
|
|
|
case 4096:
|
|
SendDlgItemMessage(pFormatInfo->hDlg, IDC_ASCOMBO, CB_SETCURSEL, 4, 0);
|
|
break;
|
|
|
|
default:
|
|
SendDlgItemMessage(pFormatInfo->hDlg, IDC_ASCOMBO, CB_SETCURSEL, 0, 0);
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
} // switch(n)
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: InitializeFormatDlg
|
|
//
|
|
// Synopsis: Initializes the format dialog to a default state. Examines
|
|
// the disk/partition to obtain default values.
|
|
//
|
|
// Arguments: [hDlg] -- Handle to the format dialog
|
|
// [pFormatInfo] -- Describes current format session
|
|
//
|
|
// Returns: HRESULT
|
|
//
|
|
// History: 2-14-95 davepl Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
HRESULT InitializeFormatDlg(LPFORMATINFO pFormatInfo)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
ULONG cMedia;
|
|
HWND hCapacityCombo;
|
|
HWND hFilesystemCombo;
|
|
HWND hDlg = pFormatInfo->hDlg;
|
|
WCHAR wszBuffer[256];
|
|
|
|
//
|
|
// Set up some typical default values
|
|
//
|
|
|
|
pFormatInfo->fEnableComp = FALSE;
|
|
pFormatInfo->dwClusterSize = 0;
|
|
pFormatInfo->fIsFloppy = TRUE;
|
|
pFormatInfo->fWasFAT = TRUE;
|
|
pFormatInfo->fFinishedOK = FALSE;
|
|
pFormatInfo->fErrorAlready = FALSE;
|
|
pFormatInfo->wszVolName[0] = WTEXT('\0');
|
|
|
|
//
|
|
// Initialize the Quick Format checkbox based on option passed to
|
|
// the SHFormatDrive() API
|
|
//
|
|
|
|
SendDlgItemMessage(hDlg, IDC_QFCHECK, BM_SETCHECK,
|
|
(pFormatInfo->options & SHFMT_OPT_FULL) ? TRUE : FALSE,
|
|
0);
|
|
//
|
|
// Set the dialog title to indicate which drive we are dealing with
|
|
//
|
|
|
|
lstrcpyW(pFormatInfo->wszDriveName, WTEXT("A:\\"));
|
|
ASSERT(pFormatInfo->drive < 26);
|
|
pFormatInfo->wszDriveName[0] += (WCHAR) pFormatInfo->drive;
|
|
|
|
SetWindowTitle(pFormatInfo, FALSE);
|
|
|
|
//
|
|
// Query the supported media types for the drive in question
|
|
//
|
|
|
|
if (FALSE == pFormatInfo->pFMIFS->QuerySupportedMedia(pFormatInfo->wszDriveName,
|
|
pFormatInfo->rgMedia,
|
|
ARRAYSIZE(pFormatInfo->rgMedia),
|
|
&cMedia))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
|
|
//
|
|
// For each of the formats that the drive can handle, add a selection
|
|
// to the capcity combobox.
|
|
//
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
ULONG i,j;
|
|
hCapacityCombo = GetDlgItem(hDlg, IDC_CAPCOMBO);
|
|
hFilesystemCombo = GetDlgItem(hDlg, IDC_FSCOMBO);
|
|
Assert(hCapacityCombo && hFilesystemCombo);
|
|
|
|
//
|
|
// Strip out weird media types
|
|
//
|
|
j = 0;
|
|
for ( i = 0; i < cMedia; i++)
|
|
{
|
|
if (pFormatInfo->rgMedia[i] != FmMediaF5_160_512 &&
|
|
pFormatInfo->rgMedia[i] != FmMediaF5_180_512 &&
|
|
pFormatInfo->rgMedia[i] != FmMediaF5_320_512 &&
|
|
pFormatInfo->rgMedia[i] != FmMediaF5_320_1024 )
|
|
{
|
|
// Ok, its not a weird one...
|
|
pFormatInfo->rgMedia[j] = pFormatInfo->rgMedia[i];
|
|
j++;
|
|
}
|
|
}
|
|
cMedia = j;
|
|
|
|
for (i = 0; i < cMedia; i++)
|
|
{
|
|
//
|
|
// If we find any non-floppy format, clear the fIsFloppy flag
|
|
//
|
|
|
|
if (FmMediaFixed == pFormatInfo->rgMedia[i] || FmMediaRemovable == pFormatInfo->rgMedia[i])
|
|
{
|
|
pFormatInfo->fIsFloppy = FALSE;
|
|
}
|
|
|
|
//
|
|
// For fixed media we query the size, for floppys we present
|
|
// a set of options supported by the drive
|
|
//
|
|
|
|
if (FmMediaFixed == pFormatInfo->rgMedia[i])
|
|
{
|
|
DWORD dwSectorsPerCluster,
|
|
dwBytesPerSector,
|
|
dwFreeClusters,
|
|
dwClusters;
|
|
|
|
if (GetDiskFreeSpace(pFormatInfo->wszDriveName,
|
|
&dwSectorsPerCluster,
|
|
&dwBytesPerSector,
|
|
&dwFreeClusters,
|
|
&dwClusters))
|
|
{
|
|
WCHAR wszBuf[100];
|
|
__int64 iCapacity = (__int64)dwSectorsPerCluster *
|
|
(__int64)dwBytesPerSector *
|
|
(__int64)dwClusters;
|
|
|
|
pFormatInfo->dwClusterSize = dwBytesPerSector * dwSectorsPerCluster;
|
|
|
|
ShortSizeFormat64(iCapacity, wszBuf);
|
|
|
|
|
|
// Add a capacity desciption to the combobox
|
|
|
|
SendMessage(hCapacityCombo,
|
|
CB_ADDSTRING,
|
|
0,
|
|
(LPARAM) wszBuf);
|
|
}
|
|
else
|
|
{
|
|
// Couldn't get the free space... prob. not fatal
|
|
|
|
LOAD_STRING( IDS_FMT_CAPUNKNOWN, wszBuffer );
|
|
SendMessage(hCapacityCombo,
|
|
CB_ADDSTRING,
|
|
0,
|
|
(LPARAM)wszBuffer);
|
|
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
// Add a capacity desciption to the combo
|
|
|
|
LOAD_STRING(IDS_FMT_MEDIA0+pFormatInfo->rgMedia[i], wszBuffer );
|
|
SendMessage(hCapacityCombo, CB_ADDSTRING, 0, (LPARAM)wszBuffer);
|
|
}
|
|
}
|
|
|
|
SendMessage(hCapacityCombo, CB_SETCURSEL, 0, 0);
|
|
}
|
|
|
|
//
|
|
// Add the appropriate filesystem selections to the combobox
|
|
//
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
SendMessage(hFilesystemCombo, CB_ADDSTRING, 0, (LPARAM)cwsz_FAT );
|
|
|
|
if (FALSE == pFormatInfo->fIsFloppy)
|
|
{
|
|
SendMessage(hFilesystemCombo, CB_ADDSTRING, 0, (LPARAM)cwsz_NTFS );
|
|
|
|
//#ifdef CAIRO // BUGBUG (DavePl) I mean _really_ CAIRO
|
|
//LOAD_STRING( IDS_FMT_OFS, wszBuffer );
|
|
//SendMessage(hFilesystemCombo, CB_ADDSTRING, 0, (LPARAM)szBuffer);
|
|
//#endif
|
|
}
|
|
|
|
// By default, pick FAT (entry 0 in the _nonsorted_ combobox)
|
|
|
|
SendMessage(hFilesystemCombo, CB_SETCURSEL, e_FAT, 0);
|
|
FileSysChange(e_FAT, pFormatInfo);
|
|
}
|
|
|
|
// If we can determine something other than FAT is being used,
|
|
// select it as the default in the combobox
|
|
|
|
if (S_OK == hr && !pFormatInfo->fIsFloppy)
|
|
{
|
|
WCHAR wszCurFileSys[MAX_PATH];
|
|
UINT olderror = SetErrorMode(SEM_FAILCRITICALERRORS);
|
|
|
|
if (GetVolumeInformation(pFormatInfo->wszDriveName,
|
|
pFormatInfo->wszVolName, ARRAYSIZE(pFormatInfo->wszVolName),
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
wszCurFileSys, ARRAYSIZE(wszCurFileSys)))
|
|
{
|
|
//
|
|
// If we got a current volume label, stuff it in the edit control
|
|
//
|
|
|
|
if (pFormatInfo->wszVolName[0] != WTEXT('\0'))
|
|
{
|
|
SetWindowText(GetDlgItem(pFormatInfo->hDlg, IDC_VLABEL), pFormatInfo->wszVolName);
|
|
}
|
|
|
|
if (0 == lstrcmpi(cwsz_NTFS, wszCurFileSys))
|
|
{
|
|
SendMessage(hFilesystemCombo, CB_SETCURSEL, e_NTFS, 0);
|
|
pFormatInfo->fWasFAT = FALSE;
|
|
FileSysChange(e_NTFS, pFormatInfo);
|
|
}
|
|
else // if (0 == lstrcmpi(cwsz_FAT, wszCurFileSys))
|
|
{
|
|
SendMessage(hFilesystemCombo, CB_SETCURSEL, e_FAT, 0);
|
|
pFormatInfo->fWasFAT = TRUE;
|
|
pFormatInfo->dwClusterSize = 0;
|
|
FileSysChange(e_FAT, pFormatInfo);
|
|
}
|
|
|
|
|
|
// BUGBUG - What about specialized file-systems? Don't care for now.
|
|
|
|
//#ifdef CAIRO // BUGBUG (DavePl) I mean _really_ CAIRO
|
|
//if (0 == lstrcmpi(cwsz_OFS, wszCurFileSys))
|
|
//{
|
|
// SendMessage(hFilesystemCombo, CB_SETCURSEL, e_OFS, 0);
|
|
// pFormatInfo->fWasFAT = FALSE;
|
|
// FileSysChange(e_OFS, pFormatInfo);
|
|
//}
|
|
//#endif
|
|
}
|
|
}
|
|
|
|
//
|
|
// If the above failed due to disk not in drive, notify the user
|
|
//
|
|
|
|
if (HRESULT_FROM_WIN32(ERROR_NOT_READY) == hr)
|
|
{
|
|
ShellMessageBox(HINST_THISDLL,
|
|
hDlg,
|
|
MAKEINTRESOURCE(IDS_DRIVENOTREADY),
|
|
NULL,
|
|
MB_SETFOREGROUND | MB_ICONEXCLAMATION | MB_OK,
|
|
pFormatInfo->wszDriveName[0]);
|
|
|
|
// BUGBUG - Retry? (only if we can get rid of the shell dialog that tells
|
|
// you that you don't have a drive inserted. otherwise leave it alone.
|
|
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: FormatCallback
|
|
//
|
|
// Synopsis: Called from within the FMIFS DLL's Format function, this
|
|
// updates the format dialog's status bar and responds to
|
|
// format completion/error notifications.
|
|
//
|
|
// Arguments: [PacketType] -- Type of packet (ie: % complete, error, etc)
|
|
// [PacketLength] -- Size, in bytes, of the packet
|
|
// [pPacketData] -- Pointer to the packet
|
|
//
|
|
// Returns: BOOLEAN continuation value
|
|
//
|
|
// History: 2-14-95 davepl Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
BOOLEAN FormatCallback(FMIFS_PACKET_TYPE PacketType,
|
|
ULONG PacketLength,
|
|
PVOID pPacketData)
|
|
{
|
|
UINT iMessageID = IDS_FORMATFAILED;
|
|
BOOL fFailed = FALSE;
|
|
LPFORMATINFO pFormatInfo;
|
|
|
|
Assert(g_iTLSFormatInfo);
|
|
|
|
//
|
|
// Grab the FORMATINFO structure for this thread
|
|
//
|
|
|
|
if (NULL == (pFormatInfo = GetFormatInfoPtr()))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// If the user has signalled to abort the format, return
|
|
// FALSE out of here right now
|
|
//
|
|
|
|
if (pFormatInfo->fShouldCancel)
|
|
{
|
|
pFormatInfo->fCancelled = TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// I could table-drive this, but it compiles surprisingly well...
|
|
//
|
|
|
|
switch(PacketType)
|
|
{
|
|
case FmIfsIncompatibleFileSystem:
|
|
fFailed = TRUE;
|
|
iMessageID = IDS_INCOMPATIBLEFS;
|
|
break;
|
|
|
|
case FmIfsIncompatibleMedia:
|
|
fFailed = TRUE;
|
|
iMessageID = IDS_INCOMPATIBLEMEDIA;
|
|
break;
|
|
|
|
case FmIfsAccessDenied:
|
|
fFailed = TRUE;
|
|
iMessageID = IDS_ACCESSDENIED;
|
|
break;
|
|
|
|
case FmIfsMediaWriteProtected:
|
|
fFailed = TRUE;
|
|
iMessageID = IDS_WRITEPROTECTED;
|
|
break;
|
|
|
|
case FmIfsCantLock:
|
|
fFailed = TRUE;
|
|
iMessageID = IDS_CANTLOCK;
|
|
break;
|
|
|
|
case FmIfsCantQuickFormat:
|
|
fFailed = TRUE;
|
|
iMessageID = IDS_CANTQUICKFORMAT;
|
|
break;
|
|
|
|
case FmIfsIoError:
|
|
fFailed = TRUE;
|
|
iMessageID = IDS_IOERROR;
|
|
// FUTURE Consider showing head/track etc where error was
|
|
break;
|
|
|
|
case FmIfsBadLabel:
|
|
fFailed = TRUE;
|
|
iMessageID = IDS_BADLABEL;
|
|
break;
|
|
|
|
case FmIfsPercentCompleted:
|
|
{
|
|
FMIFS_PERCENT_COMPLETE_INFORMATION * pPercent =
|
|
(FMIFS_PERCENT_COMPLETE_INFORMATION *) pPacketData;
|
|
|
|
SendDlgItemMessage(pFormatInfo->hDlg, IDC_FMTPROGRESS,
|
|
PBM_SETPOS,
|
|
pPercent->PercentCompleted, 0);
|
|
break;
|
|
}
|
|
|
|
case FmIfsFinished:
|
|
{
|
|
//
|
|
// Format is done; check for failure or success
|
|
//
|
|
|
|
FMIFS_FINISHED_INFORMATION * pFinishedInfo =
|
|
(FMIFS_FINISHED_INFORMATION *) pPacketData;
|
|
|
|
pFormatInfo->fFinishedOK = pFinishedInfo->Success;
|
|
|
|
if (pFinishedInfo->Success)
|
|
{
|
|
//
|
|
// If "Enable Compression" is checked, try to enable filesystem compression
|
|
//
|
|
|
|
if (SendDlgItemMessage(pFormatInfo->hDlg, IDC_ECCHECK, BM_GETCHECK, 0, 0))
|
|
{
|
|
BOOL bStatus = FALSE;
|
|
#ifdef HAVE_FMIFS_SUPPORT
|
|
bStatus = pFormatInfo->pFMIFS->EnableVolumeCompression(pFormatInfo->wszDriveName,
|
|
COMPRESSION_FORMAT_DEFAULT);
|
|
#endif
|
|
if (FALSE == bStatus)
|
|
|
|
{
|
|
ShellMessageBox(HINST_THISDLL,
|
|
pFormatInfo->hDlg,
|
|
MAKEINTRESOURCE(IDS_CANTENABLECOMP),
|
|
NULL,
|
|
MB_SETFOREGROUND | MB_ICONINFORMATION | MB_OK);
|
|
}
|
|
}
|
|
//
|
|
// Even though its a quick format, the progress meter should
|
|
// show 100% when the "Format Complete" requester is up
|
|
//
|
|
|
|
SendDlgItemMessage(pFormatInfo->hDlg, IDC_FMTPROGRESS,
|
|
PBM_SETPOS,
|
|
100 /* Percent Complete */, 0);
|
|
|
|
// FUTURE Consider showing format stats, ie: ser no, bytes, etc
|
|
|
|
ShellMessageBox(HINST_THISDLL,
|
|
pFormatInfo->hDlg,
|
|
MAKEINTRESOURCE(IDS_FORMATCOMPLETE),
|
|
NULL,
|
|
MB_SETFOREGROUND | MB_ICONINFORMATION | MB_OK);
|
|
|
|
//
|
|
// Restore the dialog title, reset progress and flags
|
|
//
|
|
|
|
SendDlgItemMessage(pFormatInfo->hDlg, IDC_FMTPROGRESS,
|
|
PBM_SETPOS,
|
|
0 /* Reset Percent Complete */, 0);
|
|
|
|
//
|
|
// Set the focus onto the Close button
|
|
//
|
|
|
|
pFormatInfo->fCancelled = FALSE;
|
|
}
|
|
else
|
|
{
|
|
fFailed = TRUE;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If we received any kind of failure information, put up a final
|
|
// "Format Failed" message. UNLESS we've already put up some nice message
|
|
//
|
|
|
|
if (fFailed && !pFormatInfo->fErrorAlready)
|
|
{
|
|
ShellMessageBox(HINST_THISDLL,
|
|
pFormatInfo->hDlg,
|
|
MAKEINTRESOURCE(iMessageID),
|
|
NULL,
|
|
MB_SETFOREGROUND | MB_ICONEXCLAMATION | MB_OK);
|
|
pFormatInfo->fErrorAlready = TRUE;
|
|
}
|
|
|
|
return (BOOLEAN) (fFailed == FALSE);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: BeginFormat
|
|
//
|
|
// Synopsis: Spun off as its own thread, this ghosts all controls in the
|
|
// dialog except "Cancel", then does the actual format
|
|
//
|
|
// Arguments: [pIn] -- FORMATINFO structure pointer as a void *
|
|
//
|
|
// Returns: HRESULT thread exit code
|
|
//
|
|
// History: 2-14-95 davepl Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
DWORD WINAPI BeginFormat(LPVOID pIn)
|
|
{
|
|
LPFORMATINFO pFormatInfo = pIn;
|
|
int n;
|
|
FMIFS_MEDIA_TYPE MediaType;
|
|
LPCWSTR pwszFileSystemName;
|
|
BOOLEAN fQuickFormat;
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// Save the FORAMTINFO ptr for this thread, to be used in the format
|
|
// callback function
|
|
//
|
|
|
|
if (S_OK != (hr = StuffFormatInfoPtr(pFormatInfo)))
|
|
{
|
|
PostMessage(pFormatInfo->hDlg, (UINT) PWM_FORMATDONE, 0, 0);
|
|
return (DWORD) hr;
|
|
}
|
|
|
|
//
|
|
// Set the window title to indicate format in proress...
|
|
//
|
|
|
|
SetWindowTitle(pFormatInfo, TRUE);
|
|
|
|
//
|
|
// Determine the user's choice of filesystem
|
|
//
|
|
|
|
n = SendDlgItemMessage(pFormatInfo->hDlg, IDC_FSCOMBO, CB_GETCURSEL, 0, 0);
|
|
|
|
switch((FILESYSENUM) n)
|
|
{
|
|
case e_FAT:
|
|
pwszFileSystemName = cwsz_FAT;
|
|
break;
|
|
|
|
case e_NTFS:
|
|
pwszFileSystemName = cwsz_NTFS;
|
|
break;
|
|
|
|
case e_OFS:
|
|
pwszFileSystemName = cwsz_OFS;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Determine the user's choice of media formats
|
|
//
|
|
|
|
n = SendDlgItemMessage(pFormatInfo->hDlg, IDC_CAPCOMBO, CB_GETCURSEL, 0, 0);
|
|
MediaType = pFormatInfo->rgMedia[n];
|
|
|
|
//
|
|
// Get the cluster size. First selection ("Use Default") yields a zero,
|
|
// while the next 4 select 512, 1024, 2048, or 4096
|
|
//
|
|
|
|
n = SendDlgItemMessage(pFormatInfo->hDlg, IDC_ASCOMBO, CB_GETCURSEL, 0, 0);
|
|
pFormatInfo->dwClusterSize = n ? (256 << n) : 0;
|
|
|
|
//
|
|
// Quickformatting?
|
|
//
|
|
|
|
fQuickFormat = (BOOLEAN) SendDlgItemMessage(pFormatInfo->hDlg, IDC_QFCHECK, BM_GETCHECK, 0, 0);
|
|
|
|
//
|
|
// Do the format.
|
|
//
|
|
|
|
#ifdef HAVE_FMIFS_SUPPORT
|
|
pFormatInfo->pFMIFS->FormatEx(pFormatInfo->wszDriveName,
|
|
MediaType,
|
|
(PWSTR) pwszFileSystemName,
|
|
pFormatInfo->wszVolName,
|
|
fQuickFormat,
|
|
pFormatInfo->dwClusterSize,
|
|
FormatCallback);
|
|
#else
|
|
pFormatInfo->pFMIFS->FormatEx(pFormatInfo->wszDriveName,
|
|
MediaType,
|
|
(PWSTR) pwszFileSystemName,
|
|
pFormatInfo->wszVolName,
|
|
fQuickFormat,
|
|
FormatCallback);
|
|
#endif
|
|
|
|
|
|
//
|
|
// Success or failure, we should fire a notification on the disk
|
|
// since we don't really know the state after the format
|
|
//
|
|
|
|
SHChangeNotify(SHCNE_UPDATEITEM, SHCNF_PATHW, (LPVOID) pFormatInfo->wszDriveName, NULL);
|
|
|
|
|
|
//
|
|
// Release the TLS index
|
|
//
|
|
|
|
UnstuffFormatInfoPtr();
|
|
|
|
//
|
|
// Post a message back to the DialogProc thread to let it know
|
|
// the format is done. We post the message since otherwise the
|
|
// DialogProc thread will be too busy waiting for this thread
|
|
// to exit to be able to process the PWM_FORMATDONE message
|
|
// immediately.
|
|
//
|
|
|
|
PostMessage(pFormatInfo->hDlg, (UINT) PWM_FORMATDONE, 0, 0);
|
|
return (DWORD) S_OK;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: FormatDlgProc
|
|
//
|
|
// Synopsis: DLGPROC for the format dialog
|
|
//
|
|
// Arguments: [hDlg] -- Typical
|
|
// [wMsg] -- Typical
|
|
// [wParam] -- Typical
|
|
// [lParam] -- For WM_INIT, carries the FORMATINFO structure
|
|
// pointer passed to DialogBoxParam() when the
|
|
// dialog was created.
|
|
//
|
|
// History: 2-14-95 davepl Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
int CALLBACK FormatDlgProc(HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
int ID = GET_WM_COMMAND_ID(wParam, lParam);
|
|
int CMD = GET_WM_COMMAND_CMD(wParam, lParam);
|
|
|
|
// Grab our previously cached pointer to the FORMATINFO struct (see WM_INITDIALOG)
|
|
|
|
LPFORMATINFO pFormatInfo = (LPFORMATINFO) GetWindowLong(hDlg, DWL_USER);
|
|
|
|
switch (wMsg) {
|
|
|
|
case PWM_FORMATDONE:
|
|
{
|
|
//
|
|
// Format is done. Reset the window title and clear the progress meter
|
|
//
|
|
|
|
SetWindowTitle(pFormatInfo, FALSE);
|
|
SendDlgItemMessage(pFormatInfo->hDlg, IDC_FMTPROGRESS, PBM_SETPOS, 0 /* Reset Percent Complete */, 0);
|
|
EnableControls(pFormatInfo);
|
|
|
|
if (pFormatInfo->fCancelled)
|
|
{
|
|
ShellMessageBox(HINST_THISDLL,
|
|
pFormatInfo->hDlg,
|
|
MAKEINTRESOURCE(IDS_FORMATCANCELLED),
|
|
NULL,
|
|
MB_SETFOREGROUND | MB_ICONEXCLAMATION | MB_OK);
|
|
pFormatInfo->fCancelled = FALSE;
|
|
}
|
|
CloseHandle(pFormatInfo->hThread);
|
|
pFormatInfo->hThread = NULL;
|
|
break;
|
|
}
|
|
|
|
case WM_INITDIALOG:
|
|
{
|
|
//
|
|
// Initialize the dialog and cache the FORMATINFO structure's pointer
|
|
// as our dialog's DWL_USER data
|
|
//
|
|
|
|
pFormatInfo = (LPFORMATINFO) lParam;
|
|
pFormatInfo->hDlg = hDlg;
|
|
if (FAILED(InitializeFormatDlg(pFormatInfo)))
|
|
{
|
|
EndDialog(hDlg, 0);
|
|
return -1;
|
|
}
|
|
SetWindowLong(hDlg, DWL_USER, lParam);
|
|
|
|
break;
|
|
}
|
|
|
|
case WM_DESTROY:
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
{
|
|
switch(CMD)
|
|
{
|
|
//
|
|
// User made a selection in one of the combo boxes
|
|
//
|
|
|
|
case CBN_SELCHANGE:
|
|
|
|
if (IDC_FSCOMBO == ID)
|
|
{
|
|
//
|
|
// User selected a filesystem... update the rest of the dialog
|
|
// based on this choice
|
|
//
|
|
|
|
HWND hFilesystemCombo = (HWND) lParam;
|
|
int n = (WORD) SendMessage(hFilesystemCombo, CB_GETCURSEL, 0, 0);
|
|
FileSysChange((FILESYSENUM) n, pFormatInfo);
|
|
}
|
|
|
|
//
|
|
// Codepath for controls other than combo boxes...
|
|
//
|
|
|
|
default:
|
|
|
|
switch (GET_WM_COMMAND_ID(wParam, lParam))
|
|
{
|
|
|
|
case IDC_ECCHECK:
|
|
pFormatInfo->fEnableComp = SendMessage((HWND) lParam, BM_GETCHECK, 0, 0);
|
|
break;
|
|
|
|
case IDOK:
|
|
{
|
|
DWORD dwThreadID;
|
|
|
|
//
|
|
// Get user verification for format, break out on CANCEL
|
|
//
|
|
|
|
if (IDCANCEL == ShellMessageBox(HINST_THISDLL,
|
|
hDlg,
|
|
MAKEINTRESOURCE(IDS_OKTOFORMAT),
|
|
NULL,
|
|
MB_SETFOREGROUND | MB_ICONEXCLAMATION | MB_OKCANCEL))
|
|
{
|
|
break;
|
|
}
|
|
|
|
DisableControls(pFormatInfo);
|
|
pFormatInfo->fCancelled = FALSE;
|
|
pFormatInfo->fShouldCancel = FALSE;
|
|
GetWindowText(GetDlgItem(pFormatInfo->hDlg, IDC_VLABEL), pFormatInfo->wszVolName, MAX_PATH);
|
|
pFormatInfo->hThread = CreateThread( NULL,
|
|
0,
|
|
BeginFormat,
|
|
(LPVOID) pFormatInfo,
|
|
0,
|
|
&dwThreadID );
|
|
break;
|
|
}
|
|
|
|
case IDCANCEL:
|
|
|
|
//
|
|
// If the format thread is running, wait for it. If not,
|
|
// exit the dialog
|
|
//
|
|
|
|
pFormatInfo->fShouldCancel = TRUE;
|
|
if (pFormatInfo->hThread)
|
|
{
|
|
DWORD dwWait;
|
|
do
|
|
{
|
|
dwWait = WaitForSingleObject(pFormatInfo->hThread, cdwTHREADWAIT);
|
|
} while ( WAIT_TIMEOUT == dwWait &&
|
|
IDRETRY == ShellMessageBox(HINST_THISDLL,
|
|
hDlg,
|
|
MAKEINTRESOURCE(IDS_CANTCANCELFMT),
|
|
NULL,
|
|
MB_SETFOREGROUND | MB_ICONEXCLAMATION | MB_RETRYCANCEL));
|
|
|
|
//
|
|
// If the format doesn't admit to having been killed, it didn't
|
|
// give up peacefully. Finish it...
|
|
// BUGBUG Stack cleanup
|
|
//
|
|
|
|
if (FALSE == pFormatInfo->fCancelled)
|
|
{
|
|
TerminateThread(pFormatInfo->hThread, 0);
|
|
}
|
|
|
|
CloseHandle(pFormatInfo->hThread);
|
|
pFormatInfo->hThread = NULL;
|
|
pFormatInfo->fCancelled = TRUE;
|
|
EnableControls(pFormatInfo);
|
|
}
|
|
else
|
|
{
|
|
EndDialog(hDlg, IDCANCEL);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
} // end WM_COMMAND case
|
|
|
|
case WM_HELP:
|
|
WinHelp((HWND) ((LPHELPINFO) lParam)->hItemHandle, NULL, HELP_WM_HELP,
|
|
(DWORD) (LPSTR) FmtaIds);
|
|
break;
|
|
|
|
case WM_CONTEXTMENU:
|
|
WinHelp((HWND) wParam, NULL, HELP_CONTEXTMENU,
|
|
(DWORD) (LPSTR) FmtaIds);
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: SHFormatDrive
|
|
//
|
|
// Synopsis: The SHFormatDrive API provides access to the Shell
|
|
// format dialog. This allows apps which want to format disks
|
|
// to bring up the same dialog that the Shell does to do it.
|
|
//
|
|
// NOTE that the user can format as many diskettes in the
|
|
// specified drive, or as many times, as he/she wishes to.
|
|
//
|
|
// Arguments: [hwnd] -- Parent window (Must NOT be NULL)
|
|
// [drive] -- 0 = A:, 1 = B:, etc.
|
|
// [fmtID] -- see below
|
|
// [options] -- SHFMT_OPT_FULL overrised default quickformat
|
|
// SHFMT_OPT_SYSONLY not support for NT
|
|
//
|
|
// Returns: See Notes
|
|
//
|
|
// History: 2-14-95 davepl Created
|
|
//
|
|
// Notes: BUGBUGs:
|
|
// Should return volume ID, but doesn't yet
|
|
// There's some backdoor magic about passing in the the low
|
|
// DWORD of the last disk's serial number to force the
|
|
// same type of format, still investigating it...
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
DWORD WINAPI SHFormatDrive(
|
|
HWND hwnd,
|
|
UINT drive,
|
|
UINT fmtID,
|
|
UINT options
|
|
)
|
|
{
|
|
int ret;
|
|
FMIFS fmifs;
|
|
FORMATINFO FormatInfo = { (BYTE) drive, fmtID, options, NULL};
|
|
ASSERT(drive < 26);
|
|
|
|
//
|
|
// It makes no sense for NT to "SYS" a disk
|
|
//
|
|
|
|
if (FormatInfo.options & SHFMT_OPT_SYSONLY)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// Load the FMIFS DLL and open the Format dialog
|
|
//
|
|
|
|
if (S_OK == LoadFMIFS(&fmifs))
|
|
{
|
|
FormatInfo.pFMIFS = &fmifs;
|
|
|
|
ret = DialogBoxParam(HINST_THISDLL,
|
|
MAKEINTRESOURCE(DLG_FORMATDISK),
|
|
hwnd,
|
|
FormatDlgProc,
|
|
(LPARAM) &FormatInfo);
|
|
}
|
|
else
|
|
{
|
|
Assert(0 && "Can't load FMIFS.DLL");
|
|
return SHFMT_ERROR;
|
|
}
|
|
|
|
//
|
|
// Free the FMIFS library and return a success code the caller
|
|
//
|
|
|
|
FreeLibrary(FormatInfo.pFMIFS->hFMIFS_DLL);
|
|
|
|
if (FormatInfo.fCancelled)
|
|
{
|
|
return SHFMT_CANCEL;
|
|
}
|
|
|
|
if (FormatInfo.fFinishedOK)
|
|
{
|
|
return 0; // BUGBUG FormatInfo.dwSerialNumber;
|
|
}
|
|
else
|
|
{
|
|
return SHFMT_ERROR;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CHKDSK
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
// This structure described the current chkdsk session
|
|
//
|
|
|
|
typedef struct tagChkDskInfo
|
|
{
|
|
UINT lastpercent; // last percentage complete received
|
|
UINT currentphase; // current chkdsk phase
|
|
UINT drive; // 0-based index of drive to chkdsk
|
|
LPFMIFS pFMIFS; // ptr to FMIFS structure, above
|
|
BOOL fRecovery; // Attempt to recover bad sectors
|
|
BOOL fFixErrors; // Fix filesystem errors as found
|
|
BOOL fCancelled; // Was chkdsk terminated early?
|
|
BOOL fShouldCancel; // User has clicked cancel; pending abort
|
|
HWND hDlg; // handle to the chkdsk dialog
|
|
HANDLE hThread;
|
|
BOOL fNoFinalMsg; // Do not put up a final failure message
|
|
WCHAR wszDriveName[4]; // For example, "A:\"
|
|
} CHKDSKINFO, * LPCHKDSKINFO;
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: StuffChkDskInfoPtr()
|
|
//
|
|
// Synopsis: Allocates a thread-local index slot for this thread's
|
|
// CHKDSKINFO pointer, if the index doesn't already exist.
|
|
// In any event, stores the CHKDSKINFO pointer in the slot
|
|
// and increments the index's usage count.
|
|
//
|
|
// Arguments: [pChkDskInfo] -- The pointer to store
|
|
//
|
|
// Returns: HRESULT
|
|
//
|
|
// History: 2-21-95 davepl Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
//
|
|
// Thread-Local Storage index for our CHKDSKINFO structure pointer
|
|
//
|
|
|
|
static DWORD g_iTLSChkDskInfo = 0;
|
|
static LONG g_cTLSChkDskInfo = 0; // Usage count
|
|
|
|
HRESULT StuffChkDskInfoPtr(LPCHKDSKINFO pChkDskInfo)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// Allocate an index slot for our thread-local CHKDSKINFO pointer, if one
|
|
// doesn't already exist, then stuff our CHKDSKINFO ptr at that index.
|
|
//
|
|
|
|
ENTERCRITICAL;
|
|
if (0 == g_iTLSChkDskInfo)
|
|
{
|
|
if (0 == (g_iTLSChkDskInfo = TlsAlloc()))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
g_cTLSChkDskInfo = 0;
|
|
}
|
|
if (S_OK == hr)
|
|
{
|
|
if (TlsSetValue(g_iTLSChkDskInfo, (LPVOID) pChkDskInfo))
|
|
{
|
|
g_cTLSChkDskInfo++;
|
|
}
|
|
else
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
}
|
|
LEAVECRITICAL;
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: UnstuffChkDskInfoPtr()
|
|
//
|
|
// Synopsis: Decrements the usage count on our thread-local storage
|
|
// index, and if it goes to zero the index is free'd
|
|
//
|
|
// Arguments: [none]
|
|
//
|
|
// Returns: none
|
|
//
|
|
// History: 2-21-95 davepl Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
__inline void UnstuffChkDskInfoPtr()
|
|
{
|
|
ENTERCRITICAL;
|
|
if (0 == --g_cTLSChkDskInfo)
|
|
{
|
|
TlsFree(g_iTLSChkDskInfo);
|
|
g_iTLSChkDskInfo = 0;
|
|
}
|
|
LEAVECRITICAL;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: GetChkDskInfoPtr()
|
|
//
|
|
// Synopsis: Retrieves this threads CHKDSKINFO ptr by grabbing the
|
|
// thread-local value previously stuff'd
|
|
//
|
|
// Arguments: [none]
|
|
//
|
|
// Returns: The pointer, of course
|
|
//
|
|
// History: 2-21-95 davepl Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
__inline LPCHKDSKINFO GetChkDskInfoPtr()
|
|
{
|
|
return TlsGetValue(g_iTLSChkDskInfo);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: DisableChkDskControls
|
|
//
|
|
// Synopsis: Ghosts all controls except "Cancel", saving their
|
|
// previous state in the CHKDSKINFO structure
|
|
//
|
|
// Arguments: [pChkDskInfo] -- Describes a ChkDsk dialog session
|
|
//
|
|
// History: 2-21-95 davepl Created
|
|
//
|
|
// Notes: Also changes "Close" button text to read "Cancel"
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
__inline void DisableChkDskControls(LPCHKDSKINFO pChkDskInfo)
|
|
{
|
|
//
|
|
// BUGBUG (DavePl) We disable CANCEL because CHKDSK does not
|
|
// allow interruption at the filesystem level.
|
|
//
|
|
|
|
EnableWindow(GetDlgItem(pChkDskInfo->hDlg, IDC_FIXERRORS), FALSE);
|
|
EnableWindow(GetDlgItem(pChkDskInfo->hDlg, IDC_RECOVERY), FALSE);
|
|
EnableWindow(GetDlgItem(pChkDskInfo->hDlg, IDOK), FALSE);
|
|
EnableWindow(GetDlgItem(pChkDskInfo->hDlg, IDCANCEL), FALSE);
|
|
// SetWindowText(GetDlgItem(pChkDskInfo->hDlg, IDCANCEL), cwsz_Cancel);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: EnableChkDskControls
|
|
//
|
|
// Synopsis: Restores controls to the enabled/disabled state they were
|
|
// before a previous call to DisableControls().
|
|
//
|
|
// Arguments: [pChkDskInfo] -- Decribes a chkdsk dialog session
|
|
//
|
|
// History: 2-21-95 davepl Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
__inline void EnableChkDskControls(LPCHKDSKINFO pChkDskInfo)
|
|
{
|
|
EnableWindow(GetDlgItem(pChkDskInfo->hDlg, IDC_FIXERRORS), TRUE);
|
|
EnableWindow(GetDlgItem(pChkDskInfo->hDlg, IDC_RECOVERY), TRUE);
|
|
EnableWindow(GetDlgItem(pChkDskInfo->hDlg, IDOK), TRUE);
|
|
EnableWindow(GetDlgItem(pChkDskInfo->hDlg, IDCANCEL), TRUE);
|
|
// SetWindowText(GetDlgItem(pChkDskInfo->hDlg, IDCANCEL), cwsz_Close);
|
|
|
|
// Erase the current phase text
|
|
|
|
SetWindowText(GetDlgItem(pChkDskInfo->hDlg, IDC_PHASE), WTEXT(""));
|
|
pChkDskInfo->lastpercent = 101;
|
|
pChkDskInfo->currentphase = 0;
|
|
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: SetChkDskWindowTitle
|
|
//
|
|
// Synopsis: Sets the chkdsk dialog's title to "Check Disk A:" or
|
|
// "Checking Disk A:" depending on the drive letter and the
|
|
// fInProgress flag.
|
|
//
|
|
// Arguments: [pChkDskInfo] -- Carries the drive letter
|
|
// [fInProgress] -- TRUE => currently checking the disk
|
|
//
|
|
// History: 2-21-95 davepl Created
|
|
//
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
void SetChkDskWindowTitle(LPCHKDSKINFO pChkDskInfo, BOOL fInProgress)
|
|
{
|
|
WCHAR swzTmp[MAX_PATH];
|
|
|
|
LOAD_STRING( fInProgress ? IDS_CHKINPROGRESS:IDS_CHKDISK, swzTmp );
|
|
lstrcat(swzTmp, pChkDskInfo->wszDriveName);
|
|
|
|
SetWindowText(pChkDskInfo->hDlg, swzTmp);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: ChkDskCallback
|
|
//
|
|
// Synopsis: Called from within the FMIFS DLL's ChkDsk function, this
|
|
// updates the ChkDsk dialog's status bar and responds to
|
|
// chkdsk completion/error notifications.
|
|
//
|
|
// Arguments: [PacketType] -- Type of packet (ie: % complete, error, etc)
|
|
// [PacketLength] -- Size, in bytes, of the packet
|
|
// [pPacketData] -- Pointer to the packet
|
|
//
|
|
// Returns: BOOLEAN continuation value
|
|
//
|
|
// History: 2-21-95 davepl Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
BOOLEAN ChkDskCallback(FMIFS_PACKET_TYPE PacketType,
|
|
ULONG PacketLength,
|
|
PVOID pPacketData)
|
|
{
|
|
UINT iMessageID = IDS_CHKDSKFAILED;
|
|
BOOL fFailed = FALSE;
|
|
LPCHKDSKINFO pChkDskInfo;
|
|
|
|
Assert(g_iTLSChkDskInfo);
|
|
|
|
//
|
|
// Grab the CHKDSKINFO structure for this thread
|
|
//
|
|
|
|
if (NULL == (pChkDskInfo = GetChkDskInfoPtr()))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// If the user has signalled to abort the ChkDsk, return
|
|
// FALSE out of here right now
|
|
//
|
|
|
|
if (pChkDskInfo->fShouldCancel)
|
|
{
|
|
pChkDskInfo->fCancelled = TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
switch(PacketType)
|
|
{
|
|
case FmIfsAccessDenied:
|
|
fFailed = TRUE;
|
|
iMessageID = IDS_CHKACCESSDENIED;
|
|
break;
|
|
|
|
case FmIfsCheckOnReboot:
|
|
{
|
|
FMIFS_CHECKONREBOOT_INFORMATION * pRebootInfo =
|
|
(FMIFS_CHECKONREBOOT_INFORMATION *) pPacketData;
|
|
|
|
// Check to see whether or not the user wants to schedule this
|
|
// chkdsk for the next reboot, since the drive cannot be locked
|
|
// right now.
|
|
|
|
if (IDYES == ShellMessageBox(HINST_THISDLL,
|
|
pChkDskInfo->hDlg,
|
|
MAKEINTRESOURCE(IDS_CHKONREBOOT),
|
|
NULL,
|
|
MB_SETFOREGROUND | MB_ICONINFORMATION | MB_YESNO))
|
|
{
|
|
// Yes, have FMIFS schedule an autochk for us
|
|
|
|
pRebootInfo->QueryResult = TRUE;
|
|
pChkDskInfo->fNoFinalMsg = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// Nope, just fail out with "cant lock drive"
|
|
|
|
fFailed = TRUE;
|
|
iMessageID = IDS_CHKDSKFAILED;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FmIfsMediaWriteProtected:
|
|
fFailed = TRUE;
|
|
iMessageID = IDS_WRITEPROTECTED;
|
|
break;
|
|
|
|
/*
|
|
This case will show up with a checkonreboot also, so don't do the
|
|
same error twice
|
|
|
|
case FmIfsCantLock:
|
|
fFailed = TRUE;
|
|
iMessageID = IDS_CANTLOCK;
|
|
break;
|
|
*/
|
|
|
|
case FmIfsIoError:
|
|
fFailed = TRUE;
|
|
iMessageID = IDS_IOERROR;
|
|
// FUTURE Consider showing head/track etc where error was
|
|
break;
|
|
|
|
case FmIfsPercentCompleted:
|
|
{
|
|
FMIFS_PERCENT_COMPLETE_INFORMATION * pPercent =
|
|
(FMIFS_PERCENT_COMPLETE_INFORMATION *) pPacketData;
|
|
SendMessage(GetDlgItem(pChkDskInfo->hDlg, IDC_CHKDSKPROGRESS),
|
|
PBM_SETPOS,
|
|
pPercent->PercentCompleted, 0);
|
|
|
|
if (pPercent->PercentCompleted < pChkDskInfo->lastpercent)
|
|
{
|
|
//
|
|
// If this % complete is less than the last one seen,
|
|
// we have completed a phase of the chkdsk and should
|
|
// advance to the next one.
|
|
//
|
|
|
|
WCHAR wszTmp[100];
|
|
WCHAR wszFormat[100];
|
|
|
|
LOAD_STRING( IDS_CHKPHASE, wszFormat );
|
|
|
|
wsprintf(wszTmp, wszFormat, ++(pChkDskInfo->currentphase));
|
|
|
|
SetWindowText(GetDlgItem(pChkDskInfo->hDlg, IDC_PHASE), wszTmp);
|
|
}
|
|
pChkDskInfo->lastpercent = pPercent->PercentCompleted;
|
|
break;
|
|
}
|
|
|
|
case FmIfsFinished:
|
|
{
|
|
//
|
|
// ChkDsk is done; check for failure or success
|
|
//
|
|
|
|
FMIFS_FINISHED_INFORMATION * pFinishedInfo =
|
|
(FMIFS_FINISHED_INFORMATION *) pPacketData;
|
|
|
|
//
|
|
// BUGBUG !! (DavePl) ChkDsk sets an inverted success value!
|
|
//
|
|
|
|
if (pFinishedInfo->Success == FALSE)
|
|
{
|
|
//
|
|
// Since we're done, force the progress gauge to 100%, so we
|
|
// don't sit here looking stupid if the chkdsk code misled us
|
|
//
|
|
|
|
SendMessage(GetDlgItem(pChkDskInfo->hDlg, IDC_CHKDSKPROGRESS),
|
|
PBM_SETPOS,
|
|
100 /* Percent Complete */, 0);
|
|
|
|
ShellMessageBox(HINST_THISDLL,
|
|
pChkDskInfo->hDlg,
|
|
MAKEINTRESOURCE(IDS_CHKDSKCOMPLETE),
|
|
NULL,
|
|
MB_SETFOREGROUND | MB_ICONINFORMATION | MB_OK);
|
|
|
|
SetWindowText(GetDlgItem(pChkDskInfo->hDlg, IDC_PHASE), WTEXT(""));
|
|
|
|
SendMessage(GetDlgItem(pChkDskInfo->hDlg, IDC_CHKDSKPROGRESS),
|
|
PBM_SETPOS,
|
|
0 /* Reset Percent Complete */, 0);
|
|
}
|
|
else
|
|
{
|
|
iMessageID = IDS_CHKDSKFAILED;
|
|
fFailed = TRUE;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If we received any kind of failure information, put up a final
|
|
// "ChkDsk Failed" message.
|
|
//
|
|
|
|
if (fFailed && FALSE == pChkDskInfo->fNoFinalMsg)
|
|
{
|
|
pChkDskInfo->fNoFinalMsg = TRUE;
|
|
|
|
ShellMessageBox(HINST_THISDLL,
|
|
pChkDskInfo->hDlg,
|
|
MAKEINTRESOURCE(iMessageID),
|
|
NULL,
|
|
MB_SETFOREGROUND | MB_ICONEXCLAMATION | MB_OK);
|
|
|
|
}
|
|
|
|
return (BOOLEAN) (fFailed == FALSE);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: BeginChkDsk
|
|
//
|
|
// Synopsis: Spun off as its own thread, this ghosts all controls in the
|
|
// dialog except "Cancel", then does the actual ChkDsk
|
|
//
|
|
// Arguments: [pIn] -- CHKDSKINFO structure pointer as a void *
|
|
//
|
|
// Returns: HRESULT thread exit code
|
|
//
|
|
// History: 2-21-95 davepl Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
DWORD WINAPI BeginChkDsk(LPVOID pIn)
|
|
{
|
|
LPCHKDSKINFO pChkDskInfo = pIn;
|
|
|
|
int n;
|
|
|
|
HRESULT hr = S_OK;
|
|
WCHAR swzFileSystem[MAX_PATH];
|
|
|
|
//
|
|
// Save the CHKDSKINFO ptr for this thread, to be used in the ChkDsk
|
|
// callback function
|
|
//
|
|
|
|
if (S_OK != (hr = StuffChkDskInfoPtr(pChkDskInfo)))
|
|
{
|
|
PostMessage(pChkDskInfo->hDlg, (UINT) PWM_CHKDSKDONE, 0, 0);
|
|
return (DWORD) hr;
|
|
}
|
|
|
|
//
|
|
// Get the filesystem in use on the device
|
|
//
|
|
|
|
if (FALSE == GetVolumeInformationW(pChkDskInfo->wszDriveName,
|
|
NULL, 0,
|
|
NULL, NULL, NULL,
|
|
swzFileSystem, MAX_PATH))
|
|
{
|
|
PostMessage(pChkDskInfo->hDlg, (UINT) PWM_CHKDSKDONE, 0, 0);
|
|
return (HRESULT_FROM_WIN32(GetLastError()));
|
|
}
|
|
|
|
//
|
|
// Set the window title to indicate ChkDsk in proress...
|
|
//
|
|
|
|
SetChkDskWindowTitle(pChkDskInfo, TRUE);
|
|
|
|
pChkDskInfo->fNoFinalMsg = FALSE;
|
|
|
|
//
|
|
// Should we try data recovery?
|
|
//
|
|
|
|
pChkDskInfo->fRecovery = (BOOLEAN) SendMessage(GetDlgItem(pChkDskInfo->hDlg, IDC_RECOVERY), BM_GETCHECK, 0, 0);
|
|
|
|
//
|
|
// Should we fix filesystem errors?
|
|
//
|
|
|
|
pChkDskInfo->fFixErrors = (BOOLEAN) SendMessage(GetDlgItem(pChkDskInfo->hDlg, IDC_FIXERRORS), BM_GETCHECK, 0, 0);
|
|
|
|
//
|
|
// Do the ChkDsk.
|
|
//
|
|
|
|
pChkDskInfo->pFMIFS->ChkDsk(pChkDskInfo->wszDriveName,
|
|
swzFileSystem,
|
|
(BOOLEAN) pChkDskInfo->fFixErrors,
|
|
FALSE, /* Verbose */
|
|
FALSE, /* Only if dirty */
|
|
(BOOLEAN) pChkDskInfo->fRecovery, /* Recovery */
|
|
NULL, /* Frag path */
|
|
FALSE, /* Extend */
|
|
ChkDskCallback); /* Callback fn */
|
|
//
|
|
// Release the TLS index
|
|
//
|
|
|
|
UnstuffChkDskInfoPtr();
|
|
|
|
//
|
|
// Post a message back to the DialogProc thread to let it know
|
|
// the chkdsk is done. We post the message since otherwise the
|
|
// DialogProc thread will be too busy waiting for this thread
|
|
// to exit to be able to process the PWM_CHKDSKDONE message
|
|
// immediately.
|
|
//
|
|
|
|
PostMessage(pChkDskInfo->hDlg, (UINT) PWM_CHKDSKDONE, 0, 0);
|
|
return (DWORD) S_OK;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: ChkDskDlgProc
|
|
//
|
|
// Synopsis: DLGPROC for the chkdsk dialog
|
|
//
|
|
// Arguments: [hDlg] -- Typical
|
|
// [wMsg] -- Typical
|
|
// [wParam] -- Typical
|
|
// [lParam] -- For WM_INIT, carries the CHKDSKINFO structure
|
|
// pointer passed to DialogBoxParam() when the
|
|
// dialog was created.
|
|
//
|
|
// History: 2-22-95 davepl Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
int CALLBACK ChkDskDlgProc(HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
int ID = GET_WM_COMMAND_ID(wParam, lParam);
|
|
|
|
// Grab our previously cached pointer to the CHKDSKINFO struct (see WM_INITDIALOG)
|
|
|
|
LPCHKDSKINFO pChkDskInfo = (LPCHKDSKINFO) GetWindowLong(hDlg, DWL_USER);
|
|
|
|
switch (wMsg) {
|
|
|
|
case PWM_CHKDSKDONE:
|
|
{
|
|
//
|
|
// chdsk is done. Reset the window title and clear the progress meter
|
|
//
|
|
|
|
SetChkDskWindowTitle(pChkDskInfo, FALSE);
|
|
|
|
SendMessage(GetDlgItem(pChkDskInfo->hDlg, IDC_CHKDSKPROGRESS),
|
|
PBM_SETPOS,
|
|
0 /* Reset Percent Complete */, 0);
|
|
|
|
EnableChkDskControls(pChkDskInfo);
|
|
|
|
if (pChkDskInfo->fCancelled)
|
|
{
|
|
ShellMessageBox(HINST_THISDLL,
|
|
pChkDskInfo->hDlg,
|
|
MAKEINTRESOURCE(IDS_CHKDSKCANCELLED),
|
|
NULL,
|
|
MB_SETFOREGROUND | MB_ICONEXCLAMATION | MB_OK);
|
|
}
|
|
CloseHandle(pChkDskInfo->hThread);
|
|
pChkDskInfo->hThread = NULL;
|
|
EndDialog(hDlg, 0);
|
|
break;
|
|
}
|
|
|
|
case WM_INITDIALOG:
|
|
{
|
|
//
|
|
// Initialize the dialog and cache the CHKDSKINFO structure's pointer
|
|
// as our dialog's DWL_USER data
|
|
//
|
|
|
|
pChkDskInfo = (LPCHKDSKINFO) lParam;
|
|
pChkDskInfo->hDlg = hDlg;
|
|
SetWindowLong(hDlg, DWL_USER, lParam);
|
|
|
|
//
|
|
// Set the dialog title to indicate which drive we are dealing with
|
|
//
|
|
|
|
lstrcpyW(pChkDskInfo->wszDriveName, WTEXT("A:\\"));
|
|
ASSERT(pChkDskInfo->drive < 26);
|
|
pChkDskInfo->wszDriveName[0] += (WCHAR) pChkDskInfo->drive;
|
|
SetChkDskWindowTitle(pChkDskInfo, FALSE);
|
|
|
|
break;
|
|
}
|
|
|
|
case WM_DESTROY:
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
{
|
|
switch (ID)
|
|
{
|
|
case IDC_FIXERRORS:
|
|
pChkDskInfo->fFixErrors = SendMessage((HWND) lParam, BM_GETCHECK, 0, 0);
|
|
break;
|
|
|
|
case IDC_RECOVERY:
|
|
pChkDskInfo->fRecovery = SendMessage((HWND) lParam, BM_GETCHECK, 0, 0);
|
|
break;
|
|
|
|
case IDOK:
|
|
{
|
|
DWORD dwThreadID;
|
|
|
|
//
|
|
// Get user verification for chkdsk, break out on CANCEL
|
|
//
|
|
|
|
DisableChkDskControls(pChkDskInfo);
|
|
pChkDskInfo->fShouldCancel = FALSE;
|
|
pChkDskInfo->fCancelled = FALSE;
|
|
pChkDskInfo->hThread = CreateThread( NULL,
|
|
0,
|
|
BeginChkDsk,
|
|
(LPVOID) pChkDskInfo,
|
|
0,
|
|
&dwThreadID );
|
|
break;
|
|
}
|
|
|
|
case IDCANCEL:
|
|
|
|
//
|
|
// If the chdsk thread is running, wait for it. If not,
|
|
// exit the dialog
|
|
//
|
|
|
|
pChkDskInfo->fShouldCancel = TRUE;
|
|
if (pChkDskInfo->hThread)
|
|
{
|
|
DWORD dwWait;
|
|
do
|
|
{
|
|
dwWait = WaitForSingleObject(pChkDskInfo->hThread, cdwTHREADWAIT);
|
|
} while ( WAIT_TIMEOUT == dwWait &&
|
|
IDRETRY == ShellMessageBox(HINST_THISDLL,
|
|
hDlg,
|
|
MAKEINTRESOURCE(IDS_CANTCANCELCHKDSK),
|
|
NULL,
|
|
MB_SETFOREGROUND | MB_ICONEXCLAMATION | MB_RETRYCANCEL));
|
|
|
|
//
|
|
// If the chkdsk doesn't admit to having been killed, it didn't
|
|
// give up peacefully. Finish it...
|
|
// BUGBUG Stack cleanup
|
|
//
|
|
|
|
if (FALSE == pChkDskInfo->fCancelled)
|
|
{
|
|
TerminateThread(pChkDskInfo->hThread, 0);
|
|
}
|
|
|
|
CloseHandle(pChkDskInfo->hThread);
|
|
pChkDskInfo->hThread = NULL;
|
|
pChkDskInfo->fCancelled = TRUE;
|
|
EnableChkDskControls(pChkDskInfo);
|
|
}
|
|
else
|
|
{
|
|
EndDialog(hDlg, IDCANCEL);
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case WM_HELP:
|
|
WinHelp((HWND) ((LPHELPINFO) lParam)->hItemHandle, NULL, HELP_WM_HELP,
|
|
(DWORD) (LPSTR) ChkaIds);
|
|
break;
|
|
|
|
case WM_CONTEXTMENU:
|
|
WinHelp((HWND) wParam, NULL, HELP_CONTEXTMENU,
|
|
(DWORD) (LPSTR) ChkaIds);
|
|
break;
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: SHChkDskDrive
|
|
//
|
|
// Synopsis: Displays the "Check Disk" dialog and calls chkdsk on the
|
|
// drive in question, as appropriate
|
|
//
|
|
// Arguments: [hwnd] -- Parent window (Must NOT be NULL)
|
|
// [drive] -- 0 = A:, 1 = B:, etc.
|
|
//
|
|
// Returns: HRESULT
|
|
//
|
|
// History: 2-14-95 davepl Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
static BOOL fChkdskActive[26];
|
|
|
|
DWORD WINAPI SHChkDskDrive(
|
|
HWND hwnd,
|
|
UINT drive
|
|
)
|
|
{
|
|
int ret = S_OK;
|
|
FMIFS fmifs;
|
|
|
|
//
|
|
// We use a last percentage-complete value of 101, to guarantee that the
|
|
// next one received will be less, indicating next (first) phase
|
|
//
|
|
|
|
CHKDSKINFO ChkDskInfo = { 101, 0, drive, NULL, FALSE, FALSE, FALSE, FALSE };
|
|
|
|
//
|
|
// Cheap semaphore to prevent multiple chkdsks of the same drive
|
|
//
|
|
|
|
ENTERCRITICAL;
|
|
if (fChkdskActive[drive])
|
|
{
|
|
LEAVECRITICAL;
|
|
return (DWORD)E_FAIL;
|
|
}
|
|
fChkdskActive[drive] = 1;
|
|
LEAVECRITICAL;
|
|
|
|
//
|
|
// Load the FMIFS DLL and open the ChkDsk dialog
|
|
//
|
|
|
|
if (S_OK == LoadFMIFS(&fmifs))
|
|
{
|
|
ChkDskInfo.pFMIFS = &fmifs;
|
|
|
|
ret = DialogBoxParam(HINST_THISDLL,
|
|
MAKEINTRESOURCE(DLG_CHKDSK),
|
|
hwnd,
|
|
ChkDskDlgProc,
|
|
(LPARAM) &ChkDskInfo);
|
|
|
|
if (-1 == ret)
|
|
{
|
|
ret = GetLastError();
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
Assert(0 && "Can't load FMIFS.DLL");
|
|
fChkdskActive[drive] = 0;
|
|
return (DWORD) E_OUTOFMEMORY;
|
|
}
|
|
|
|
//
|
|
// Free the FMIFS library and return a success code the caller
|
|
//
|
|
|
|
FreeLibrary(ChkDskInfo.pFMIFS->hFMIFS_DLL);
|
|
|
|
fChkdskActive[drive] = 0;
|
|
return (DWORD) S_OK;
|
|
}
|
|
|
|
#endif // WINNT
|