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.
1792 lines
51 KiB
1792 lines
51 KiB
|
|
/*++
|
|
|
|
Copyright (c) 1993-1994 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
fmifs.c
|
|
|
|
Abstract:
|
|
|
|
This module contains the set of routines that work with the fmifs.dll
|
|
|
|
Author:
|
|
|
|
Bob Rinne (bobri) 11/15/93
|
|
|
|
Environment:
|
|
|
|
User process.
|
|
|
|
Notes:
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "fdisk.h"
|
|
#include "shellapi.h"
|
|
#include "fmifs.h"
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
|
|
//
|
|
// defines unique to this module
|
|
//
|
|
|
|
#define FS_CANCELUPDATE (WM_USER + 0)
|
|
#define FS_FINISHED (WM_USER + 1)
|
|
|
|
BOOLEAN
|
|
FmIfsCallback(
|
|
IN FMIFS_PACKET_TYPE PacketType,
|
|
IN DWORD PacketLength,
|
|
IN PVOID PacketData
|
|
);
|
|
|
|
//
|
|
// Externals needed for IFS Dll support (format and label)
|
|
//
|
|
|
|
HINSTANCE IfsDllHandle = NULL;
|
|
PFMIFS_FORMAT_ROUTINE FormatRoutine = NULL;
|
|
PFMIFS_SETLABEL_ROUTINE LabelRoutine = NULL;
|
|
|
|
#ifdef DOUBLE_SPACE_SUPPORT_INCLUDED
|
|
PFMIFS_DOUBLESPACE_CREATE_ROUTINE DblSpaceCreateRoutine = NULL;
|
|
PFMIFS_DOUBLESPACE_MOUNT_ROUTINE DblSpaceMountRoutine = NULL;
|
|
PFMIFS_DOUBLESPACE_DELETE_ROUTINE DblSpaceDeleteRoutine = NULL;
|
|
PFMIFS_DOUBLESPACE_DISMOUNT_ROUTINE DblSpaceDismountRoutine = NULL;
|
|
PFMIFS_DOUBLESPACE_QUERY_INFO_ROUTINE DblSpaceQueryInfoRoutine = NULL;
|
|
|
|
BOOLEAN DoubleSpaceSupported = TRUE;
|
|
#endif
|
|
|
|
// HACK HACK - clean this up if it works.
|
|
|
|
#define SELECTED_REGION(i) (SelectedDS[i]->RegionArray[SelectedRG[i]])
|
|
#define MaxMembersInFtSet 32
|
|
extern DWORD SelectionCount;
|
|
extern PDISKSTATE SelectedDS[MaxMembersInFtSet];
|
|
extern ULONG SelectedRG[MaxMembersInFtSet];
|
|
|
|
VOID
|
|
setUnicode(
|
|
char *astring,
|
|
WCHAR *wstring
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Convert an ansii string to Unicode. Internal routine to fmifs module.
|
|
|
|
Arguments:
|
|
|
|
astring - ansii string to convert to Unicode
|
|
wstring - resulting string location
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
|
|
int len = lstrlen(astring)+1;
|
|
|
|
MultiByteToWideChar( CP_ACP, 0, astring, len, wstring, len );
|
|
}
|
|
|
|
BOOL
|
|
LoadIfsDll(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine will determine if the IFS Dll needs to be loaded. If
|
|
so, it will load it and locate the format and label routines in the
|
|
dll.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
TRUE if Dll is loaded and the routines needed have been found
|
|
FALSE if something fails
|
|
|
|
--*/
|
|
|
|
{
|
|
if (FormatRoutine) {
|
|
|
|
// Library is already loaded and the routines needed
|
|
// have been located.
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
IfsDllHandle = LoadLibrary(TEXT("fmifs.dll"));
|
|
if (IfsDllHandle == (HANDLE)NULL) {
|
|
|
|
// FMIFS not available.
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
// Library is loaded. Locate the two routines needed by
|
|
// Disk Administrator.
|
|
|
|
FormatRoutine = (PVOID)GetProcAddress(IfsDllHandle, "Format");
|
|
LabelRoutine = (PVOID)GetProcAddress(IfsDllHandle, "SetLabel");
|
|
if (!FormatRoutine || !LabelRoutine) {
|
|
|
|
// something didn't get found so shut down all accesses
|
|
// to the library by insuring FormatRoutine is NULL
|
|
|
|
FreeLibrary(IfsDllHandle);
|
|
FormatRoutine = NULL;
|
|
return FALSE;
|
|
}
|
|
|
|
#ifdef DOUBLE_SPACE_SUPPORT_INCLUDED
|
|
DblSpaceMountRoutine = (PVOID)GetProcAddress(IfsDllHandle, "DoubleSpaceMount");
|
|
DblSpaceDismountRoutine = (PVOID)GetProcAddress(IfsDllHandle, "DoubleSpaceDismount");
|
|
DblSpaceCreateRoutine = (PVOID)GetProcAddress(IfsDllHandle, "DoubleSpaceCreate");
|
|
DblSpaceDeleteRoutine = (PVOID)GetProcAddress(IfsDllHandle, "DoubleSpaceDelete");
|
|
DblSpaceQueryInfoRoutine = (PVOID)GetProcAddress(IfsDllHandle, "FmifsQueryDriveInformation");
|
|
|
|
if (!DblSpaceMountRoutine || !DblSpaceDismountRoutine || !DblSpaceQueryInfoRoutine) {
|
|
|
|
// didn't get all of the DoubleSpace support routines
|
|
// Allow format and label, just don't do DoubleSpace
|
|
|
|
DoubleSpaceSupported = FALSE;
|
|
}
|
|
|
|
if (DblSpaceCreateRoutine && DblSpaceDeleteRoutine) {
|
|
|
|
// Everything is there for read/write double space support.
|
|
// This will change certain dialogs to allow creation and
|
|
// deletion of double space volumes.
|
|
|
|
IsFullDoubleSpace = TRUE;
|
|
}
|
|
#endif
|
|
return TRUE;
|
|
}
|
|
|
|
VOID
|
|
UnloadIfsDll(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine will free the FmIfs DLL if it was loaded.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
if (FormatRoutine) {
|
|
FreeLibrary(IfsDllHandle);
|
|
FormatRoutine = NULL;
|
|
IfsDllHandle = NULL;
|
|
LabelRoutine = NULL;
|
|
#ifdef DOUBLE_SPACE_SUPPORT_INCLUDED
|
|
DblSpaceDismountRoutine = NULL;
|
|
DblSpaceMountRoutine = NULL;
|
|
DblSpaceCreateRoutine = NULL;
|
|
DblSpaceDeleteRoutine = NULL;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
PFORMAT_PARAMS ParamsForCallBack = NULL;
|
|
|
|
BOOLEAN
|
|
FmIfsCallback(
|
|
IN FMIFS_PACKET_TYPE PacketType,
|
|
IN DWORD PacketLength,
|
|
IN PVOID PacketData
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine gets callbacks from fmifs.dll regarding
|
|
progress and status of the ongoing format or doublespace
|
|
create. It runs in the same thread as the format or create,
|
|
which is a separate thread from the "cancel" button. If
|
|
the user hits "cancel", this routine notices on the next
|
|
callback and cancels the format or double space create.
|
|
|
|
Arguments:
|
|
|
|
[PacketType] -- an fmifs packet type
|
|
[PacketLength] -- length of the packet data
|
|
[PacketData] -- data associated with the packet
|
|
|
|
Return Value:
|
|
|
|
TRUE if the fmifs activity should continue, FALSE if the
|
|
activity should halt immediately. Thus, we return FALSE if
|
|
the user has hit "cancel" and we wish fmifs to clean up and
|
|
return from the Format() entrypoint call.
|
|
|
|
--*/
|
|
|
|
{
|
|
PFORMAT_PARAMS formatParams = ParamsForCallBack;
|
|
HWND hDlg = formatParams->DialogHwnd;
|
|
|
|
// Quit if told to do so..
|
|
|
|
if (formatParams->Cancel) {
|
|
formatParams->Result = MSG_FORMAT_CANCELLED;
|
|
return FALSE;
|
|
}
|
|
|
|
switch (PacketType) {
|
|
case FmIfsPercentCompleted:
|
|
|
|
PostMessage(hDlg,
|
|
FS_CANCELUPDATE,
|
|
((PFMIFS_PERCENT_COMPLETE_INFORMATION)PacketData)->PercentCompleted,
|
|
0);
|
|
break;
|
|
|
|
case FmIfsFormatReport:
|
|
|
|
formatParams->TotalSpace = ((PFMIFS_FORMAT_REPORT_INFORMATION)PacketData)->KiloBytesTotalDiskSpace;
|
|
formatParams->SpaceAvailable = ((PFMIFS_FORMAT_REPORT_INFORMATION)PacketData)->KiloBytesAvailable;
|
|
break;
|
|
|
|
case FmIfsIncompatibleFileSystem:
|
|
|
|
formatParams->Result = MSG_INCOMPATIBLE_FILE_SYSTEM;
|
|
break;
|
|
|
|
case FmIfsInsertDisk:
|
|
|
|
break;
|
|
|
|
case FmIfsFormattingDestination:
|
|
|
|
break;
|
|
|
|
case FmIfsIncompatibleMedia:
|
|
|
|
formatParams->Result = MSG_INCOMPATIBLE_MEDIA;
|
|
break;
|
|
|
|
case FmIfsAccessDenied:
|
|
|
|
formatParams->Result = MSG_FORMAT_ACCESS_DENIED;
|
|
break;
|
|
|
|
case FmIfsMediaWriteProtected:
|
|
|
|
formatParams->Result = MSG_WRITE_PROTECTED;
|
|
break;
|
|
|
|
case FmIfsCantLock:
|
|
|
|
formatParams->Result = MSG_FORMAT_CANT_LOCK;
|
|
break;
|
|
|
|
case FmIfsBadLabel:
|
|
|
|
formatParams->Result = MSG_BAD_LABEL;
|
|
break;
|
|
|
|
case FmIfsCantQuickFormat:
|
|
|
|
formatParams->Result = MSG_CANT_QUICK_FORMAT;
|
|
break;
|
|
|
|
case FmIfsIoError:
|
|
|
|
formatParams->Result = MSG_IO_ERROR;
|
|
break;
|
|
|
|
case FmIfsFinished:
|
|
|
|
PostMessage(hDlg,
|
|
FS_FINISHED,
|
|
0,
|
|
0);
|
|
return FALSE;
|
|
break;
|
|
|
|
#ifdef DOUBLE_SPACE_SUPPORT_INCLUDED
|
|
case FmIfsDblspaceCreateFailed:
|
|
formatParams->Result = MSG_CANT_CREATE_DBLSPACE;
|
|
break;
|
|
|
|
case FmIfsDblspaceMountFailed:
|
|
formatParams->Result = MSG_CANT_MOUNT_DBLSPACE;
|
|
break;
|
|
|
|
case FmIfsDblspaceDriveLetterFailed:
|
|
formatParams->Result = MSG_DBLSPACE_LETTER_FAILED;
|
|
break;
|
|
|
|
case FmIfsDblspaceCreated:
|
|
|
|
// Save the name of the double space file.
|
|
|
|
if (formatParams->DblspaceFileName = (PWSTR) Malloc(PacketLength)) {
|
|
memcpy(formatParams->DblspaceFileName, PacketData, PacketLength);
|
|
}
|
|
break;
|
|
|
|
case FmIfsDblspaceMounted:
|
|
break;
|
|
#endif
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return (formatParams->Result) ? FALSE : TRUE;
|
|
}
|
|
|
|
#ifdef DOUBLE_SPACE_SUPPORT_INCLUDED
|
|
ULONG MountDismountResult;
|
|
#define MOUNT_DISMOUNT_SUCCESS 0
|
|
|
|
BOOLEAN
|
|
FmIfsMountDismountCallback(
|
|
IN FMIFS_PACKET_TYPE PacketType,
|
|
IN DWORD PacketLength,
|
|
IN PVOID PacketData
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine gets callbacks from fmifs.dll regarding
|
|
progress and status of the ongoing format or doublespace
|
|
|
|
Arguments:
|
|
|
|
[PacketType] -- an fmifs packet type
|
|
[PacketLength] -- length of the packet data
|
|
[PacketData] -- data associated with the packet
|
|
|
|
Return Value:
|
|
|
|
TRUE if the fmifs activity should continue, FALSE if the
|
|
activity should halt immediately. Thus, we return FALSE if
|
|
the user has hit "cancel" and we wish fmifs to clean up and
|
|
return from the Format() entrypoint call.
|
|
|
|
--*/
|
|
|
|
{
|
|
switch (PacketType) {
|
|
case FmIfsDblspaceMounted:
|
|
MountDismountResult = MOUNT_DISMOUNT_SUCCESS;
|
|
break;
|
|
}
|
|
return TRUE;
|
|
}
|
|
#endif
|
|
|
|
VOID
|
|
FormatVolume(
|
|
IN PVOID ThreadParameter
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine converts the strings in the formatParams structure
|
|
and calls the fmifs routines to perform the format.
|
|
|
|
It assumes it is called by a separate thread and will exit the
|
|
thread on completion of the format.
|
|
|
|
Arguments:
|
|
|
|
ThreadParameter - a pointer to the FORMAT_PARAMS structure
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
PFORMAT_PARAMS formatParams = (PFORMAT_PARAMS) ThreadParameter;
|
|
PPERSISTENT_REGION_DATA regionData;
|
|
DWORD index;
|
|
WCHAR unicodeLabel[100],
|
|
unicodeFsType[20],
|
|
driveLetter[4];
|
|
|
|
// The fmifs interface doesn't allow for a context parameter
|
|
// therefore the formatparams must be passed through an external.
|
|
|
|
ParamsForCallBack = formatParams;
|
|
|
|
// set up a unicode drive letter.
|
|
|
|
regionData = (PPERSISTENT_REGION_DATA) formatParams->RegionData;
|
|
driveLetter[1] = L':';
|
|
driveLetter[2] = 0;
|
|
driveLetter[0] = (WCHAR) regionData->DriveLetter;
|
|
|
|
// convert label to unicode
|
|
|
|
setUnicode(formatParams->Label,
|
|
unicodeLabel);
|
|
|
|
// convert filesystem type to unicode
|
|
|
|
for (index = 0;
|
|
unicodeFsType[index] = (WCHAR)(formatParams->FileSystem[index]);
|
|
index++) {
|
|
// operation done in for loop
|
|
}
|
|
|
|
(*FormatRoutine)(driveLetter,
|
|
FmMediaUnknown,
|
|
unicodeFsType,
|
|
unicodeLabel,
|
|
(BOOLEAN)formatParams->QuickFormat,
|
|
&FmIfsCallback);
|
|
|
|
// Set the synchronization event to inform the windisk thread
|
|
// that this is complete and all handles have been closed.
|
|
|
|
formatParams->ThreadIsDone = 1;
|
|
ExitThread(0L);
|
|
}
|
|
|
|
#ifdef DOUBLE_SPACE_SUPPORT_INCLUDED
|
|
VOID
|
|
FmIfsCreateDblspace(
|
|
IN PVOID ThreadParameter
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine converts the strings in the formatParams structure
|
|
and calls the fmifs routines to perform the double space create.
|
|
|
|
It assumes it is called by a separate thread and will exit the
|
|
thread on completion of the create.
|
|
|
|
Arguments:
|
|
|
|
ThreadParameter - a pointer to the FORMAT_PARAMS structure
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
PFORMAT_PARAMS formatParams = (PFORMAT_PARAMS) ThreadParameter;
|
|
PPERSISTENT_REGION_DATA regionData;
|
|
DWORD index;
|
|
UCHAR letter;
|
|
WCHAR unicodeLabel[100],
|
|
newDriveLetter[4],
|
|
driveLetter[4];
|
|
|
|
// The fmifs interface doesn't allow for a context parameter
|
|
// therefore the formatparams must be passed through an external.
|
|
|
|
ParamsForCallBack = formatParams;
|
|
|
|
// set up a unicode drive letter.
|
|
|
|
regionData = (PPERSISTENT_REGION_DATA) formatParams->RegionData;
|
|
driveLetter[1] = L':';
|
|
driveLetter[2] = 0;
|
|
driveLetter[0] = (WCHAR) regionData->DriveLetter;
|
|
|
|
// set up the new letter
|
|
|
|
newDriveLetter[1] = L':';
|
|
newDriveLetter[2] = 0;
|
|
|
|
// Choose the first available. This should come from the dialog
|
|
// newDriveLetter[0] = (WCHAR) formatParams->NewLetter;
|
|
|
|
for (letter='C'; letter <= 'Z'; letter++) {
|
|
if (DriveLetterIsAvailable((CHAR)letter)) {
|
|
newDriveLetter[0] = (WCHAR) letter;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// convert label to unicode
|
|
|
|
setUnicode(formatParams->Label,
|
|
unicodeLabel);
|
|
|
|
(*DblSpaceCreateRoutine)(driveLetter,
|
|
formatParams->SpaceAvailable * 1024 * 1024,
|
|
unicodeLabel,
|
|
newDriveLetter,
|
|
&FmIfsCallback);
|
|
ExitThread(0L);
|
|
}
|
|
|
|
BOOL
|
|
FmIfsDismountDblspace(
|
|
IN CHAR DriveLetter
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Convert the name provided into unicode and call the
|
|
FmIfs support routine.
|
|
|
|
Arguments:
|
|
|
|
DriveLetter - the drive letter to dismount.
|
|
|
|
Return Value:
|
|
|
|
TRUE - it worked.
|
|
|
|
--*/
|
|
|
|
{
|
|
WCHAR unicodeLetter[4];
|
|
ULONG index;
|
|
|
|
unicodeLetter[0] = (WCHAR) DriveLetter;
|
|
unicodeLetter[1] = (WCHAR) ':';
|
|
unicodeLetter[2] = 0;
|
|
|
|
// The only way to communicate with the fmifs callback
|
|
// is through global externals.
|
|
|
|
MountDismountResult = MSG_CANT_DISMOUNT_DBLSPACE;
|
|
|
|
(*DblSpaceDismountRoutine)(unicodeLetter, &FmIfsMountDismountCallback);
|
|
|
|
return MountDismountResult;
|
|
}
|
|
|
|
BOOL
|
|
FmIfsMountDblspace(
|
|
IN PCHAR FileName,
|
|
IN CHAR HostDrive,
|
|
IN CHAR NewDrive
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Convert the arguments into unicode characters and
|
|
call the FmIfs support routine to mount the double
|
|
space volume.
|
|
|
|
Arguments:
|
|
|
|
FileName - ASCII file name (i.e. dblspace.xxx)
|
|
HostDrive - Drive drive letter containing double space volume
|
|
NewDrive - Drive letter to be assigned to the volume
|
|
|
|
Return Value:
|
|
|
|
TRUE it worked.
|
|
|
|
--*/
|
|
|
|
{
|
|
WCHAR wideFileName[40];
|
|
WCHAR wideHostDrive[4];
|
|
WCHAR wideNewDrive[4];
|
|
ULONG index;
|
|
|
|
// convert the double space file name.
|
|
|
|
for (index = 0; wideFileName[index] = (WCHAR) FileName[index]; index++) {
|
|
// all work done in for expression
|
|
}
|
|
|
|
// convert the drive names.
|
|
|
|
wideNewDrive[1] = wideHostDrive[1] = (WCHAR) ':';
|
|
wideNewDrive[2] = wideHostDrive[2] = 0;
|
|
|
|
wideNewDrive[0] = (WCHAR) NewDrive;
|
|
wideHostDrive[0] = (WCHAR) HostDrive;
|
|
|
|
// The only way to communicate with the fmifs callback
|
|
// is through global externals.
|
|
|
|
MountDismountResult = MSG_CANT_MOUNT_DBLSPACE;
|
|
|
|
(*DblSpaceMountRoutine)(wideHostDrive,
|
|
wideFileName,
|
|
wideNewDrive,
|
|
&FmIfsMountDismountCallback);
|
|
return MountDismountResult;
|
|
}
|
|
|
|
BOOLEAN
|
|
FmIfsQueryInformation(
|
|
IN PWSTR DosDriveName,
|
|
OUT PBOOLEAN IsRemovable,
|
|
OUT PBOOLEAN IsFloppy,
|
|
OUT PBOOLEAN IsCompressed,
|
|
OUT PBOOLEAN Error,
|
|
OUT PWSTR NtDriveName,
|
|
IN ULONG MaxNtDriveNameLength,
|
|
OUT PWSTR CvfFileName,
|
|
IN ULONG MaxCvfFileNameLength,
|
|
OUT PWSTR HostDriveName,
|
|
IN ULONG MaxHostDriveNameLength
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Call through the pointer to the routine in the fmifs dll.
|
|
|
|
Arguments:
|
|
|
|
Same as the Fmifs routine in the DLL.
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
|
|
{
|
|
if (!DblSpaceQueryInfoRoutine) {
|
|
return FALSE;
|
|
}
|
|
return (*DblSpaceQueryInfoRoutine)(DosDriveName,
|
|
IsRemovable,
|
|
IsFloppy,
|
|
IsCompressed,
|
|
Error,
|
|
NtDriveName,
|
|
MaxNtDriveNameLength,
|
|
CvfFileName,
|
|
MaxCvfFileNameLength,
|
|
HostDriveName,
|
|
MaxHostDriveNameLength);
|
|
}
|
|
#endif
|
|
|
|
BOOL CALLBACK
|
|
CancelDlgProc(
|
|
IN HWND hDlg,
|
|
IN UINT uMsg,
|
|
IN WPARAM wParam,
|
|
IN LPARAM lParam
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dialog procedure for the modeless progress & cancel 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:
|
|
|
|
standard Windows dialog procedure
|
|
|
|
Return Values:
|
|
|
|
standard Windows dialog procedure
|
|
|
|
--*/
|
|
|
|
{
|
|
static DWORD percentDrawn;
|
|
static RECT rectGG; // GasGauge rectangle
|
|
static BOOL captionIsLoaded;
|
|
static PFORMAT_PARAMS formatParams;
|
|
TCHAR title[100],
|
|
templateString[100];
|
|
|
|
switch (uMsg) {
|
|
case WM_INITDIALOG: {
|
|
PPERSISTENT_REGION_DATA regionData;
|
|
HANDLE threadHandle;
|
|
DWORD threadId;
|
|
HWND hwndGauge = GetDlgItem(hDlg, IDC_GASGAUGE);
|
|
|
|
// set up the dialog handle in the parameter block so the
|
|
// call back routine can communicate with this routine
|
|
// and initialize static variables.
|
|
|
|
formatParams = (PFORMAT_PARAMS) lParam;
|
|
formatParams->DialogHwnd = hDlg;
|
|
regionData = (PPERSISTENT_REGION_DATA) formatParams->RegionData;
|
|
percentDrawn = 0;
|
|
captionIsLoaded = FALSE;
|
|
|
|
// Set the caption string.
|
|
|
|
LoadString(hModule, IDS_FORMAT_TITLE, templateString, sizeof(templateString)/sizeof(TCHAR));
|
|
wsprintf(title,
|
|
templateString,
|
|
regionData->DriveLetter);
|
|
SetWindowText(hDlg, title);
|
|
|
|
#ifdef DOUBLE_SPACE_SUPPORT_INCLUDED
|
|
if (formatParams->DoubleSpace) {
|
|
|
|
// start the double space create thread
|
|
|
|
threadHandle = CreateThread(NULL,
|
|
0,
|
|
(LPTHREAD_START_ROUTINE) FmIfsCreateDblspace,
|
|
(LPVOID) formatParams,
|
|
(DWORD) 0,
|
|
(LPDWORD) &threadId);
|
|
} else {
|
|
#endif
|
|
|
|
// start the format thread
|
|
|
|
threadHandle = CreateThread(NULL,
|
|
0,
|
|
(LPTHREAD_START_ROUTINE) FormatVolume,
|
|
(LPVOID) formatParams,
|
|
(DWORD) 0,
|
|
(LPDWORD) &threadId);
|
|
#ifdef DOUBLE_SPACE_SUPPORT_INCLUDED
|
|
}
|
|
#endif
|
|
if (!threadHandle) {
|
|
// can't do it now.
|
|
|
|
formatParams->Result = MSG_COULDNT_CREATE_THREAD;
|
|
EndDialog(hDlg, FALSE);
|
|
return TRUE;
|
|
}
|
|
|
|
// no need to keep the handle around.
|
|
|
|
CloseHandle(threadHandle);
|
|
|
|
// Get the coordinates of the gas gauge static control rectangle,
|
|
// and convert them to dialog client area coordinates
|
|
|
|
GetClientRect(hwndGauge, &rectGG);
|
|
ClientToScreen(hwndGauge, (LPPOINT)&rectGG.left);
|
|
ClientToScreen(hwndGauge, (LPPOINT)&rectGG.right);
|
|
ScreenToClient(hDlg, (LPPOINT)&rectGG.left);
|
|
ScreenToClient(hDlg, (LPPOINT)&rectGG.right);
|
|
return TRUE;
|
|
}
|
|
|
|
case WM_COMMAND:
|
|
|
|
switch (wParam) {
|
|
case IDCANCEL:
|
|
|
|
formatParams->Result = MSG_FORMAT_CANCELLED;
|
|
formatParams->Cancel = TRUE;
|
|
EndDialog(hDlg, FALSE);
|
|
}
|
|
return TRUE;
|
|
|
|
case WM_PAINT: {
|
|
INT width = rectGG.right - rectGG.left;
|
|
INT height = rectGG.bottom - rectGG.top;
|
|
INT nDivideRects;
|
|
HDC hDC;
|
|
PAINTSTRUCT ps;
|
|
TCHAR buffer[100];
|
|
SIZE size;
|
|
INT xText,
|
|
yText,
|
|
byteCount;
|
|
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 (!captionIsLoaded) {
|
|
UINT resourceId = IDS_PERCENTCOMPLETE;
|
|
|
|
if (formatParams->QuickFormat) {
|
|
resourceId = IDS_QUICK_FORMAT;
|
|
}
|
|
#ifdef DOUBLE_SPACE_SUPPORT_INCLUDED
|
|
if (formatParams->DoubleSpace) {
|
|
resourceId = IDS_CREATING_DBLSPACE;
|
|
}
|
|
#endif
|
|
LoadString(hModule,
|
|
resourceId,
|
|
buffer,
|
|
sizeof(buffer)/sizeof(TCHAR));
|
|
if (!formatParams->QuickFormat) {
|
|
SetDlgItemText(hDlg, IDC_TEXT, buffer);
|
|
}
|
|
captionIsLoaded = TRUE;
|
|
}
|
|
|
|
if (formatParams->QuickFormat) {
|
|
nDivideRects = 0;
|
|
byteCount = lstrlen(buffer);
|
|
} else {
|
|
byteCount = wsprintf(buffer, TEXT("%3d%%"), percentDrawn);
|
|
nDivideRects = (width * percentDrawn) / 100;
|
|
}
|
|
|
|
GetTextExtentPoint(hDC, buffer, lstrlen(buffer), &size);
|
|
xText = rectGG.left + (width - size.cx) / 2;
|
|
yText = rectGG.top + (height - size.cy) / 2;
|
|
|
|
|
|
// 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,
|
|
byteCount/sizeof(TCHAR),
|
|
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,
|
|
byteCount/sizeof(TCHAR),
|
|
NULL);
|
|
EndPaint(hDlg, &ps);
|
|
return TRUE;
|
|
}
|
|
|
|
case FS_CANCELUPDATE:
|
|
|
|
// wParam = % completed
|
|
|
|
percentDrawn = (INT)wParam;
|
|
InvalidateRect(hDlg, &rectGG, TRUE);
|
|
UpdateWindow(hDlg);
|
|
return TRUE;
|
|
|
|
case FS_FINISHED:
|
|
|
|
EndDialog(hDlg, TRUE);
|
|
return TRUE;
|
|
|
|
default:
|
|
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
INT
|
|
LabelDlgProc(
|
|
IN HWND hDlg,
|
|
IN UINT wMsg,
|
|
IN WPARAM wParam,
|
|
IN LPARAM lParam)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine manages the label dialog.
|
|
Upon completion of the dialog it will end the dialog with a result of
|
|
TRUE to indicate that all is set up for the label operation. FALSE if
|
|
the label operation has been cancelled by the user.
|
|
|
|
Arguments:
|
|
|
|
Standard Windows dialog procedure.
|
|
|
|
Return Value:
|
|
|
|
Standard Windows dialog procedure.
|
|
|
|
--*/
|
|
|
|
{
|
|
static PLABEL_PARAMS labelParams;
|
|
static PREGION_DESCRIPTOR regionDescriptor;
|
|
static PPERSISTENT_REGION_DATA regionData;
|
|
char text[100];
|
|
TCHAR uniText[100];
|
|
int labelSize;
|
|
TCHAR title[100],
|
|
templateString[100];
|
|
|
|
switch (wMsg) {
|
|
case WM_INITDIALOG:
|
|
|
|
labelParams = (PLABEL_PARAMS) lParam;
|
|
regionDescriptor = labelParams->RegionDescriptor;
|
|
regionData = PERSISTENT_DATA(regionDescriptor);
|
|
|
|
// Set the caption string.
|
|
//
|
|
LoadString(hModule, IDS_LABEL_TITLE, templateString, sizeof(templateString)/sizeof(TCHAR));
|
|
wsprintf(title,
|
|
templateString,
|
|
regionData->DriveLetter);
|
|
SetWindowText(hDlg, title);
|
|
|
|
// Convert the volume label into the proper type for windows.
|
|
|
|
wsprintf(text, "%ws", regionData->VolumeLabel);
|
|
UnicodeHack(text, uniText);
|
|
SetDlgItemText(hDlg, IDC_NAME, uniText);
|
|
return TRUE;
|
|
|
|
case WM_COMMAND:
|
|
switch (wParam) {
|
|
|
|
case FD_IDHELP:
|
|
|
|
DialogHelp(HC_DM_DLG_LABEL);
|
|
break;
|
|
|
|
case IDCANCEL:
|
|
|
|
EndDialog(hDlg, FALSE);
|
|
break;
|
|
|
|
case IDOK:
|
|
|
|
labelSize = GetDlgItemText(hDlg, IDC_NAME, text, 100);
|
|
UnicodeHack(text, labelParams->NewLabel);
|
|
EndDialog(hDlg, TRUE);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
#define NUM_FSTYPES 2
|
|
#define MAX_FSTYPENAME_SIZE 6
|
|
|
|
// HPFS is not supported -- therefore commented out.
|
|
|
|
TCHAR *FsTypes[NUM_FSTYPES + 1] = { "NTFS",
|
|
/* "HPFS", */
|
|
"FAT" };
|
|
WCHAR *UnicodeFsTypes[NUM_FSTYPES] = { L"NTFS",
|
|
/* L"HPFS", */
|
|
L"FAT" };
|
|
|
|
BOOL CALLBACK
|
|
FormatDlgProc(
|
|
IN HWND hDlg,
|
|
IN UINT wMsg,
|
|
IN WPARAM wParam,
|
|
IN LPARAM lParam)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine manages the format dialog. Upon completion it ends the
|
|
dialog with a result value of TRUE to indicate that the format operation
|
|
is to take place. FALSE is the result if the user cancels out of the
|
|
dialog.
|
|
|
|
Arguments:
|
|
|
|
Standard Windows dialog procedure.
|
|
|
|
Return Value:
|
|
|
|
Standard Windows dialog procedure.
|
|
|
|
--*/
|
|
|
|
{
|
|
static HWND hwndCombo;
|
|
static PFORMAT_PARAMS formatParams;
|
|
static PREGION_DESCRIPTOR regionDescriptor;
|
|
static PPERSISTENT_REGION_DATA regionData;
|
|
char text[40];
|
|
TCHAR uniText[40];
|
|
INT i;
|
|
DWORD selection;
|
|
BOOL quickFormat = FALSE;
|
|
HWND hwndButton;
|
|
TCHAR title[100],
|
|
templateString[100];
|
|
|
|
UNREFERENCED_PARAMETER(lParam);
|
|
|
|
switch (wMsg) {
|
|
case WM_INITDIALOG: {
|
|
PWSTR typeName = NULL,
|
|
volumeLabel = NULL;
|
|
WCHAR driveLetter = L' ';
|
|
|
|
// since the format params are static reset the quick format boolean.
|
|
|
|
formatParams = (PFORMAT_PARAMS) lParam;
|
|
formatParams->QuickFormat = FALSE;
|
|
|
|
// get format params, set static values and
|
|
// get information about the volume
|
|
|
|
hwndCombo = GetDlgItem(hDlg, IDC_FSTYPE);
|
|
regionDescriptor = formatParams->RegionDescriptor;
|
|
DetermineRegionInfo(regionDescriptor,
|
|
&typeName,
|
|
&volumeLabel,
|
|
&driveLetter);
|
|
regionData = PERSISTENT_DATA(regionDescriptor);
|
|
|
|
// Set the caption string.
|
|
|
|
LoadString(hModule, IDS_FORMAT_TITLE, templateString, sizeof(templateString)/sizeof(TCHAR));
|
|
wsprintf(title,
|
|
templateString,
|
|
regionData->DriveLetter);
|
|
SetWindowText(hDlg, title);
|
|
|
|
// Convert the volume label into the proper type for windows
|
|
// and set default values.
|
|
|
|
wsprintf(text, "%ws", regionData->VolumeLabel);
|
|
UnicodeHack(text, uniText);
|
|
SetDlgItemText(hDlg, IDC_NAME, uniText);
|
|
CheckDlgButton(hDlg, IDC_VERIFY, quickFormat);
|
|
SendDlgItemMessage(hDlg, IDOK, EM_SETSEL, 0, -1);
|
|
|
|
// If this volume is a mirror or stripe with parity,
|
|
// disable Quick Format.
|
|
|
|
if (regionData->FtObject != NULL &&
|
|
(regionData->FtObject->Set->Type == Mirror ||
|
|
regionData->FtObject->Set->Type == StripeWithParity)) {
|
|
|
|
hwndButton = GetDlgItem(hDlg, IDC_VERIFY);
|
|
|
|
if (hwndButton != NULL) {
|
|
|
|
EnableWindow(hwndButton, FALSE);
|
|
}
|
|
}
|
|
|
|
selection = 0;
|
|
if (IsDiskRemovable[regionDescriptor->Disk]) {
|
|
|
|
// If removable, start from the bottom of the list so FAT is first.
|
|
// Load the available File system types.
|
|
|
|
for (i = NUM_FSTYPES - 1; i >= 0; i--) {
|
|
|
|
// Fill the drop down list.
|
|
|
|
SendMessage(hwndCombo, CB_ADDSTRING, 0, (LONG)FsTypes[i]);
|
|
}
|
|
|
|
} else {
|
|
|
|
// Load the available File system types.
|
|
|
|
for (i = 0; i < NUM_FSTYPES; i++) {
|
|
|
|
// While filling in the drop down, determine which FS
|
|
// this volume is already formated for and make it the
|
|
// default (if not found, NTFS is the default).
|
|
|
|
if (wcscmp(typeName, UnicodeFsTypes[i]) == 0) {
|
|
selection = i;
|
|
}
|
|
|
|
// set the FS type into the dialog.
|
|
|
|
SendMessage(hwndCombo, CB_ADDSTRING, 0, (LONG)FsTypes[i]);
|
|
}
|
|
}
|
|
|
|
SendMessage(hwndCombo, CB_SETCURSEL, selection, 0);
|
|
return TRUE;
|
|
break;
|
|
}
|
|
|
|
case WM_COMMAND:
|
|
|
|
switch (wParam) {
|
|
|
|
case FD_IDHELP:
|
|
|
|
DialogHelp(HC_DM_DLG_FORMAT);
|
|
break;
|
|
|
|
case IDCANCEL:
|
|
|
|
EndDialog(hDlg, FALSE);
|
|
break;
|
|
|
|
case IDOK: {
|
|
int labelSize;
|
|
|
|
// pull the parameters from the dialog
|
|
// and return with success.
|
|
|
|
selection = SendMessage(hwndCombo, CB_GETCURSEL, 0, 0);
|
|
SendMessage(hwndCombo,
|
|
CB_GETLBTEXT,
|
|
selection,
|
|
(LONG)formatParams->FileSystem);
|
|
labelSize = GetDlgItemText(hDlg,
|
|
IDC_NAME,
|
|
(LPTSTR) formatParams->Label,
|
|
100);
|
|
if (IsDlgButtonChecked(hDlg, IDC_VERIFY)) {
|
|
formatParams->QuickFormat = TRUE;
|
|
}
|
|
EndDialog(hDlg, TRUE);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
VOID
|
|
FormatPartition(
|
|
PREGION_DESCRIPTOR RegionDescriptor
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Insure the IFS Dll is loaded and start the dialog for format
|
|
of a volume.
|
|
|
|
Arguments:
|
|
|
|
RegionDescriptor - The region to format.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
static FORMAT_PARAMS formatParams; // this is passed to other threads
|
|
// it cannot be located on the stack
|
|
PPERSISTENT_REGION_DATA regionData;
|
|
int doFormat;
|
|
ULONG diskSize;
|
|
PWSTR tempName,
|
|
tempLabel,
|
|
typeName;
|
|
TCHAR label[100],
|
|
fileSystem[10],
|
|
message[300],
|
|
msgProto[300],
|
|
title[200];
|
|
|
|
// Make sure format of this partition is allowed. It is not allowed
|
|
// if it is the boot partition (or sys partition on x86).
|
|
|
|
if ((DeletionIsAllowed(RegionDescriptor)) != NO_ERROR) {
|
|
ErrorDialog(MSG_CANT_FORMAT_WINNT);
|
|
return;
|
|
}
|
|
|
|
// must have a drive letter
|
|
|
|
regionData = PERSISTENT_DATA(RegionDescriptor);
|
|
if (!regionData->DriveLetter) {
|
|
ErrorDialog(MSG_CANT_FORMAT_NO_LETTER);
|
|
return;
|
|
}
|
|
|
|
// can only do this is the dll is loaded.
|
|
|
|
if (!LoadIfsDll()) {
|
|
|
|
// could not load the dll
|
|
|
|
ErrorDialog(MSG_CANT_LOAD_FMIFS);
|
|
return;
|
|
}
|
|
|
|
// set up the parameters and get the information from the user.
|
|
|
|
formatParams.RegionDescriptor = RegionDescriptor;
|
|
formatParams.Result = 0;
|
|
formatParams.RegionData = regionData;
|
|
formatParams.Label = (PUCHAR) label;
|
|
formatParams.FileSystem = (PUCHAR) fileSystem;
|
|
formatParams.QuickFormat = formatParams.Cancel =
|
|
formatParams.DoubleSpace = FALSE;
|
|
formatParams.TotalSpace = formatParams.SpaceAvailable = 0;
|
|
doFormat = DialogBoxParam(hModule,
|
|
MAKEINTRESOURCE(IDD_PARTITIONFORMAT),
|
|
hwndFrame,
|
|
FormatDlgProc,
|
|
(ULONG) &formatParams);
|
|
if (doFormat) {
|
|
|
|
// do an are you sure message.
|
|
|
|
doFormat = ConfirmationDialog(MSG_CONFIRM_FORMAT,
|
|
MB_ICONQUESTION | MB_YESNO);
|
|
if (doFormat == IDYES) {
|
|
|
|
if (IsDiskRemovable[RegionDescriptor->Disk]) {
|
|
PWSTR typeName,
|
|
volumeLabel;
|
|
BOOLEAN volumeChanged = FALSE;
|
|
|
|
if (!RegionDescriptor->PartitionNumber) {
|
|
|
|
// TODO: something has changed where the code gets to this
|
|
// point with an incorrect partition number - This happens
|
|
// when a partition is deleted and added to removable media.
|
|
// For removable media the partition number is always 1.
|
|
|
|
RegionDescriptor->PartitionNumber = 1;
|
|
}
|
|
if (GetVolumeTypeAndSize(RegionDescriptor->Disk,
|
|
RegionDescriptor->PartitionNumber,
|
|
&volumeLabel,
|
|
&typeName,
|
|
&diskSize) == OK_STATUS) {
|
|
|
|
// Verify that this is still the same device.
|
|
|
|
if (typeName) {
|
|
if (!lstrcmpiW(typeName, L"raw")) {
|
|
Free(typeName);
|
|
typeName = Malloc((wcslen(wszUnknown) * sizeof(WCHAR)) + sizeof(WCHAR));
|
|
lstrcpyW(typeName, wszUnknown);
|
|
}
|
|
} else {
|
|
typeName = Malloc((wcslen(wszUnknown) * sizeof(WCHAR)) + sizeof(WCHAR));
|
|
lstrcpyW(typeName, wszUnknown);
|
|
}
|
|
if (regionData) {
|
|
if (regionData->VolumeLabel) {
|
|
if (wcscmp(regionData->VolumeLabel, volumeLabel)) {
|
|
volumeChanged = TRUE;
|
|
}
|
|
}
|
|
if (regionData->TypeName) {
|
|
|
|
// It is possible the region has no type
|
|
// or is of type "Unformatted".
|
|
// This says it is ok to format.
|
|
|
|
if (*regionData->TypeName) {
|
|
|
|
if (wcscmp(regionData->TypeName, wszUnformatted)) {
|
|
|
|
// It has a type and it isn't
|
|
// unformatted - see if it is
|
|
// the same as before.
|
|
|
|
if (wcscmp(regionData->TypeName, typeName)) {
|
|
volumeChanged = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Disks[RegionDescriptor->Disk]->DiskSizeMB != (diskSize/1024)) {
|
|
volumeChanged = TRUE;
|
|
}
|
|
if (volumeChanged) {
|
|
|
|
ErrorDialog(MSG_VOLUME_CHANGED);
|
|
|
|
// since the user was told the volume changed,
|
|
// update the display.
|
|
|
|
SetCursor(hcurWait);
|
|
if (GetVolumeTypeAndSize(RegionDescriptor->Disk,
|
|
RegionDescriptor->PartitionNumber,
|
|
&tempLabel,
|
|
&tempName,
|
|
&diskSize) == OK_STATUS) {
|
|
Free(typeName);
|
|
typeName = tempName;
|
|
Free(volumeLabel);
|
|
volumeLabel = tempLabel;
|
|
}
|
|
if (regionData->VolumeLabel) {
|
|
Free(regionData->VolumeLabel);
|
|
}
|
|
regionData->VolumeLabel = volumeLabel;
|
|
if (regionData->TypeName) {
|
|
Free(regionData->TypeName);
|
|
}
|
|
regionData->TypeName = typeName;
|
|
SetCursor(hcurNormal);
|
|
TotalRedrawAndRepaint();
|
|
return;
|
|
} else {
|
|
if (volumeLabel) {
|
|
Free(volumeLabel);
|
|
}
|
|
if (typeName) {
|
|
Free(typeName);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Insure the partition is not to big if the requested format
|
|
// is FAT.
|
|
|
|
if (!strcmpi(formatParams.FileSystem, "FAT")) {
|
|
|
|
if (GetVolumeSizeMB(RegionDescriptor->Disk,
|
|
RegionDescriptor->PartitionNumber,
|
|
&diskSize)) {
|
|
if (diskSize > (4*1024)) {
|
|
ErrorDialog(MSG_TOO_BIG_FOR_FAT);
|
|
TotalRedrawAndRepaint();
|
|
return;
|
|
}
|
|
} else {
|
|
|
|
// Just try the format anyway.
|
|
|
|
}
|
|
}
|
|
|
|
// Initialize synchronization event to know when the
|
|
// format thread is really complete.
|
|
|
|
formatParams.ThreadIsDone = 0;
|
|
|
|
// user still wants to format.
|
|
|
|
DialogBoxParam(hModule,
|
|
MAKEINTRESOURCE(IDD_FORMATCANCEL),
|
|
hwndFrame,
|
|
CancelDlgProc,
|
|
(ULONG) &formatParams);
|
|
if (formatParams.Result) {
|
|
|
|
// the format failed.
|
|
|
|
ErrorDialog(formatParams.Result);
|
|
} else {
|
|
|
|
LoadString(hModule,
|
|
IDS_FORMATCOMPLETE,
|
|
title,
|
|
sizeof(title)/sizeof(TCHAR));
|
|
LoadString(hModule,
|
|
IDS_FORMATSTATS,
|
|
msgProto,
|
|
sizeof(msgProto)/sizeof(TCHAR));
|
|
wsprintf(message,
|
|
msgProto,
|
|
formatParams.TotalSpace,
|
|
formatParams.SpaceAvailable);
|
|
MessageBox(GetActiveWindow(),
|
|
message,
|
|
title,
|
|
MB_ICONINFORMATION | MB_OK);
|
|
|
|
}
|
|
|
|
// Synchronize with the format thread just in case
|
|
// the user did a cancel and the format thread is
|
|
// still buzy verifying 50MB or some such thing.
|
|
// Rather than use an event this is a polling loop.
|
|
|
|
SetCursor(hcurWait);
|
|
while (!formatParams.ThreadIsDone) {
|
|
Sleep(1000);
|
|
}
|
|
SetCursor(hcurNormal);
|
|
|
|
// If the format was successful, update the volume
|
|
// information in the data structures.
|
|
|
|
if (!formatParams.Result) {
|
|
|
|
// get the new label and FsType regardless of success of the
|
|
// format (i.e. user cancel may have occurred, so this stuff
|
|
// is not what it used to be even if the format failed.
|
|
|
|
{
|
|
// force mount by filesystem. This is done with the
|
|
// extra \ on the end of the path. This must be done
|
|
// in order to get the FS type. Otherwise the filesystem
|
|
// recognisor may allow the open without actually getting
|
|
// the file system involved.
|
|
|
|
char ntDeviceName[100];
|
|
STATUS_CODE sc;
|
|
HANDLE_T handle;
|
|
|
|
sprintf(ntDeviceName, "\\DosDevices\\%c:\\", regionData->DriveLetter);
|
|
sc = LowOpenNtName(ntDeviceName, &handle);
|
|
if (sc == OK_STATUS) {
|
|
LowCloseDisk(handle);
|
|
}
|
|
}
|
|
typeName = NULL;
|
|
GetTypeName(RegionDescriptor->Disk, RegionDescriptor->PartitionNumber, &typeName);
|
|
|
|
if (!typeName) {
|
|
|
|
// Failed to get the type after a cancel. This means
|
|
// GetTypeName() could not open the volume for some reason.
|
|
// This has been seen on Alpha's and x86 with large
|
|
// hardware raid devices. Exiting and starting
|
|
// over will get an FS type. For now, don't change the
|
|
// data structures.
|
|
|
|
TotalRedrawAndRepaint();
|
|
return;
|
|
}
|
|
|
|
tempLabel = NULL;
|
|
if (GetVolumeLabel(RegionDescriptor->Disk, RegionDescriptor->PartitionNumber, &tempLabel) == NO_ERROR) {
|
|
|
|
if (tempLabel) {
|
|
Free(regionData->VolumeLabel);
|
|
regionData->VolumeLabel = Malloc((lstrlenW(tempLabel) + 1) * sizeof(WCHAR));
|
|
lstrcpyW(regionData->VolumeLabel, tempLabel);
|
|
}
|
|
} else {
|
|
*regionData->VolumeLabel = 0;
|
|
}
|
|
|
|
// update the type name.
|
|
|
|
if (regionData->TypeName) {
|
|
Free(regionData->TypeName);
|
|
regionData->TypeName = typeName;
|
|
}
|
|
|
|
// update the file system type information for all
|
|
// components of this region (i.e. fix up FT structures if
|
|
// it is an FT item). This is done via knowledge about multiple
|
|
// selections as opposed to walking through the FtObject list.
|
|
|
|
if (SelectionCount > 1) {
|
|
PPERSISTENT_REGION_DATA passedRegionData;
|
|
ULONG index;
|
|
|
|
// Need to update all involved.
|
|
|
|
passedRegionData = regionData;
|
|
|
|
for (index = 0; index < SelectionCount; index++) {
|
|
RegionDescriptor = &SELECTED_REGION(index);
|
|
regionData = PERSISTENT_DATA(RegionDescriptor);
|
|
|
|
if (regionData == passedRegionData) {
|
|
continue;
|
|
}
|
|
|
|
if (regionData->VolumeLabel) {
|
|
Free(regionData->VolumeLabel);
|
|
regionData->VolumeLabel = NULL;
|
|
}
|
|
if (tempLabel) {
|
|
regionData->VolumeLabel = Malloc((lstrlenW(tempLabel) + 1) * sizeof(WCHAR));
|
|
lstrcpyW(regionData->VolumeLabel, tempLabel);
|
|
}
|
|
|
|
if (regionData->TypeName) {
|
|
Free(regionData->TypeName);
|
|
}
|
|
regionData->TypeName = Malloc((lstrlenW(passedRegionData->TypeName) + 1) * sizeof(WCHAR));
|
|
lstrcpyW(regionData->TypeName, passedRegionData->TypeName);
|
|
}
|
|
}
|
|
|
|
if (tempLabel) {
|
|
Free(tempLabel);
|
|
}
|
|
}
|
|
|
|
// force screen update.
|
|
|
|
TotalRedrawAndRepaint();
|
|
}
|
|
}
|
|
}
|
|
|
|
VOID
|
|
LabelPartition(
|
|
PREGION_DESCRIPTOR RegionDescriptor
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Insure the IFS Dll is loaded and start the dialog for label
|
|
of a volume.
|
|
|
|
Arguments:
|
|
|
|
RegionDescriptor - the region for the label.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
int doLabel;
|
|
DWORD ec;
|
|
TCHAR label[100];
|
|
WCHAR unicodeLabel[100];
|
|
LABEL_PARAMS labelParams;
|
|
WCHAR driveLetter[4];
|
|
PWSTR tmpLabel;
|
|
PPERSISTENT_REGION_DATA regionData;
|
|
|
|
if (!LoadIfsDll()) {
|
|
|
|
// could not load the Dll
|
|
|
|
ErrorDialog(MSG_CANT_LOAD_FMIFS);
|
|
return;
|
|
}
|
|
labelParams.RegionDescriptor = RegionDescriptor;
|
|
labelParams.NewLabel = (LPTSTR)label;
|
|
doLabel = DialogBoxParam(hModule,
|
|
MAKEINTRESOURCE(IDD_PARTITIONLABEL),
|
|
hwndFrame,
|
|
LabelDlgProc,
|
|
(ULONG) &labelParams);
|
|
if (doLabel) {
|
|
|
|
regionData = PERSISTENT_DATA(RegionDescriptor);
|
|
|
|
if (IsDiskRemovable[RegionDescriptor->Disk]) {
|
|
PWSTR typeName,
|
|
volumeLabel;
|
|
ULONG diskSize;
|
|
BOOLEAN volumeChanged = FALSE;
|
|
|
|
if (GetVolumeTypeAndSize(RegionDescriptor->Disk,
|
|
RegionDescriptor->PartitionNumber,
|
|
&volumeLabel,
|
|
&typeName,
|
|
&diskSize) == OK_STATUS) {
|
|
// Verify that this is still the same device.
|
|
|
|
if (regionData) {
|
|
if (regionData->VolumeLabel) {
|
|
if (wcscmp(regionData->VolumeLabel, volumeLabel)) {
|
|
volumeChanged = TRUE;
|
|
}
|
|
}
|
|
if (regionData->TypeName) {
|
|
if (wcscmp(regionData->TypeName, typeName)) {
|
|
volumeChanged = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Disks[RegionDescriptor->Disk]->DiskSizeMB != (diskSize/1024)) {
|
|
volumeChanged = TRUE;
|
|
}
|
|
|
|
if (volumeChanged) {
|
|
PWSTR tempName,
|
|
tempLabel;
|
|
|
|
ErrorDialog(MSG_VOLUME_CHANGED);
|
|
|
|
// since the user was told the volume changed,
|
|
// update the display.
|
|
|
|
SetCursor(hcurWait);
|
|
if (GetVolumeTypeAndSize(RegionDescriptor->Disk,
|
|
RegionDescriptor->PartitionNumber,
|
|
&tempLabel,
|
|
&tempName,
|
|
&diskSize) == OK_STATUS) {
|
|
Free(typeName);
|
|
typeName = tempName;
|
|
Free(volumeLabel);
|
|
volumeLabel = tempLabel;
|
|
}
|
|
if (regionData->VolumeLabel) {
|
|
Free(regionData->VolumeLabel);
|
|
}
|
|
regionData->VolumeLabel = volumeLabel;
|
|
if (regionData->TypeName) {
|
|
Free(regionData->TypeName);
|
|
}
|
|
regionData->TypeName = typeName;
|
|
SetCursor(hcurNormal);
|
|
TotalRedrawAndRepaint();
|
|
return;
|
|
} else {
|
|
Free(volumeLabel);
|
|
Free(typeName);
|
|
}
|
|
}
|
|
}
|
|
driveLetter[1] = L':';
|
|
driveLetter[2] = 0;
|
|
driveLetter[0] = (WCHAR)regionData->DriveLetter;
|
|
|
|
// convert to unicode - use variable doLabel as an index.
|
|
|
|
setUnicode(label,
|
|
unicodeLabel);
|
|
|
|
// perform the label.
|
|
|
|
SetCursor(hcurWait);
|
|
(*LabelRoutine)(driveLetter, unicodeLabel);
|
|
|
|
ec = GetLastError();
|
|
|
|
if (ec != NO_ERROR) {
|
|
SetCursor(hcurNormal);
|
|
ErrorDialog(ec);
|
|
SetCursor(hcurWait);
|
|
}
|
|
|
|
// get the new label to be certain it took and update
|
|
// the internal structures.
|
|
|
|
if (GetVolumeLabel(RegionDescriptor->Disk, RegionDescriptor->PartitionNumber, &tmpLabel) == NO_ERROR) {
|
|
Free(regionData->VolumeLabel);
|
|
regionData->VolumeLabel = Malloc((lstrlenW(tmpLabel) + 1) * sizeof(WCHAR));
|
|
lstrcpyW(regionData->VolumeLabel, tmpLabel);
|
|
} else {
|
|
*regionData->VolumeLabel = 0;
|
|
}
|
|
|
|
// update the label for all
|
|
// components of this region (i.e. fix up FT structures if
|
|
// it is an FT item). This is done via knowledge about multiple
|
|
// selections as opposed to walking through the FtObject list.
|
|
|
|
if (SelectionCount > 1) {
|
|
PPERSISTENT_REGION_DATA passedRegionData;
|
|
ULONG index;
|
|
|
|
// Need to update all involved.
|
|
|
|
passedRegionData = regionData;
|
|
|
|
for (index = 0; index < SelectionCount; index++) {
|
|
RegionDescriptor = &SELECTED_REGION(index);
|
|
regionData = PERSISTENT_DATA(RegionDescriptor);
|
|
|
|
if (regionData == passedRegionData) {
|
|
continue;
|
|
}
|
|
|
|
if (regionData->VolumeLabel) {
|
|
Free(regionData->VolumeLabel);
|
|
regionData->VolumeLabel = NULL;
|
|
}
|
|
if (tmpLabel) {
|
|
regionData->VolumeLabel = Malloc((lstrlenW(tmpLabel) + 1) * sizeof(WCHAR));
|
|
lstrcpyW(regionData->VolumeLabel, tmpLabel);
|
|
} else {
|
|
*regionData->VolumeLabel = 0;
|
|
}
|
|
}
|
|
}
|
|
if (tmpLabel) {
|
|
Free(tmpLabel);
|
|
}
|
|
SetCursor(hcurNormal);
|
|
|
|
// force screen update.
|
|
|
|
TotalRedrawAndRepaint();
|
|
}
|
|
}
|