Leaked source code of windows server 2003
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

/*++
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();
}
}