windows-nt/Source/XPSP1/NT/base/fs/utils/fdisk/dblspace.c
2020-09-26 16:20:57 +08:00

1711 lines
44 KiB
C

/*++
Copyright (c) 1993 Microsoft Corporation
Module Name:
dblspace.c
Abstract:
This module contains the set of routines that deal with double space
dialogs and support.
Author:
Bob Rinne (bobri) 11/15/93
Environment:
User process.
Notes:
Revision History:
--*/
#include "fdisk.h"
#include "fmifs.h"
#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
#include <string.h>
#ifdef DOUBLE_SPACE_SUPPORT_INCLUDED
PREGION_DESCRIPTOR RegionForDblSpaceVolume;
ULONG DblSpaceThresholdSizes[] = { 10, 40, 100, (ULONG) -1 };
#define NUMBER_PARSEFORMAT_ITEMS 4
char *DblSpaceIniFileName = "%c:\\dblspace.ini";
char *DblSpaceWildCardFileName = "%c:\\dblspace.*";
char *DblSpaceParseFormat = "%s %s %d %d";
// All double space structures are chained into the base chain
// this allows for ease in initialization to determine which are
// mounted. This chain is only used for initialization.
PDBLSPACE_DESCRIPTOR DblChainBase = NULL;
PDBLSPACE_DESCRIPTOR DblChainLast = NULL;
extern BOOLEAN DoubleSpaceSupported;
#define DblSpaceMountDrive(REGDESC, DBLSPACE) \
DblSpaceChangeState(REGDESC, DBLSPACE, TRUE)
#define DblSpaceDismountDrive(REGDESC, DBLSPACE) \
DblSpaceChangeState(REGDESC, DBLSPACE, FALSE)
VOID
DblSpaceUpdateIniFile(
IN PREGION_DESCRIPTOR RegionDescriptor
)
/*++
Routine Description:
This routine is left around in case this code must update DOS
based .ini files. Currently it does nothing.
Arguments:
The region with the double space volumes.
Return Value
None
--*/
{
}
ULONG
DblSpaceChangeState(
IN PREGION_DESCRIPTOR RegionDescriptor,
IN PDBLSPACE_DESCRIPTOR DblSpacePtr,
IN BOOL Mount
)
/*++
Routine Description:
Based on the value of Mount, either mount the volume or
dismount the Double Space volume
Arguments:
RegionDescriptor - The region containing the double space volume
DriveLetter - The drive letter of the double space volume involved.
Mount - TRUE == perform a mount function
FALSE == dismount the volume
Return Value:
None
--*/
{
PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(RegionDescriptor);
WCHAR dblSpaceUniqueName[32];
ULONG index;
ULONG result = 0;
SetCursor(hcurWait);
if (Mount) {
// Call fmifs mount routine.
result = FmIfsMountDblspace(DblSpacePtr->FileName,
regionData->DriveLetter,
DblSpacePtr->NewDriveLetter);
} else {
// Call fmifs dismount routine.
result = FmIfsDismountDblspace(DblSpacePtr->DriveLetter);
}
if (!result) {
DblSpacePtr->Mounted = Mount;
if (Mount) {
DblSpacePtr->DriveLetter = DblSpacePtr->NewDriveLetter;
MarkDriveLetterUsed(DblSpacePtr->DriveLetter);
} else {
TCHAR name[4];
// remove the drive letter.
name[0] = (TCHAR)DblSpacePtr->DriveLetter;
name[1] = (TCHAR)':';
name[2] = 0;
DefineDosDevice(DDD_REMOVE_DEFINITION, (LPCTSTR) name, (LPCTSTR) NULL);
// Now update the internal structures.
MarkDriveLetterFree(DblSpacePtr->DriveLetter);
DblSpacePtr->DriveLetter = ' ';
}
if (!IsDiskRemovable[RegionDescriptor->Disk]) {
dblSpaceUniqueName[0] = (WCHAR) regionData->DriveLetter;
dblSpaceUniqueName[1] = (WCHAR) ':';
dblSpaceUniqueName[2] = (WCHAR) '\\';
index = 0;
while (dblSpaceUniqueName[index + 3] = DblSpacePtr->FileName[index]) {
index++;
}
result = DiskRegistryAssignDblSpaceLetter(dblSpaceUniqueName,
(WCHAR) DblSpacePtr->DriveLetter);
}
}
SetCursor(hcurNormal);
return result;
}
PDBLSPACE_DESCRIPTOR
DblSpaceCreateInternalStructure(
IN CHAR DriveLetter,
IN ULONG Size,
IN PCHAR Name,
IN BOOLEAN ChainIt
)
/*++
Routine Description:
This routine constructs the internal data structure that represents a
double space volume.
Arguments:
DriveLetter - drive letter for new internal structure
Size - size of the actual volume
Name - name of the containing double space file (i.e. dblspace.xxx)
Return Value:
Pointer to the new structure if created.
NULL if it couldn't be created.
--*/
{
PDBLSPACE_DESCRIPTOR dblSpace;
dblSpace = malloc(sizeof(DBLSPACE_DESCRIPTOR));
if (dblSpace) {
if (DriveLetter != ' ') {
MarkDriveLetterUsed(DriveLetter);
}
dblSpace->DriveLetter = DriveLetter;
dblSpace->DriveLetterEOS = 0;
dblSpace->NewDriveLetter = 0;
dblSpace->NewDriveLetterEOS = 0;
dblSpace->ChangeDriveLetter = FALSE;
dblSpace->Next = dblSpace->DblChainNext = NULL;
dblSpace->Mounted = FALSE;
dblSpace->ChangeMountState = FALSE;
dblSpace->AllocatedSize = Size;
dblSpace->FileName = malloc(strlen(Name) + 4);
if (dblSpace->FileName) {
// Copy the name.
strcpy(dblSpace->FileName, Name);
if (ChainIt) {
if (DblChainBase) {
DblChainLast->DblChainNext = dblSpace;
} else {
DblChainBase = dblSpace;
}
DblChainLast = dblSpace;
}
} else {
// no memory - free what is allocated and give up.
free(dblSpace);
dblSpace = NULL;
}
}
return dblSpace;
}
#define MAX_IFS_NAME_LENGTH 200
VOID
DblSpaceDetermineMounted(
VOID
)
/*++
Routine Description:
This routine walks through all of the system drive letters to see
if any are mounted double space volumes. If a mounted double space
volume is located it updates the state of that volume in the internal
data structures for the double space volumes.
Arguments:
None
Return Value:
None
--*/
{
PDBLSPACE_DESCRIPTOR dblSpace;
ULONG index;
WCHAR driveLetter[4],
ntDriveName[MAX_IFS_NAME_LENGTH],
cvfName[MAX_IFS_NAME_LENGTH],
hostDriveName[MAX_IFS_NAME_LENGTH],
compareName[MAX_IFS_NAME_LENGTH];
UINT errorMode;
BOOLEAN removable,
floppy,
compressed,
error;
driveLetter[1] = (WCHAR) ':';
driveLetter[2] = 0;
errorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
for (driveLetter[0] = (WCHAR) 'C'; driveLetter[0] < (WCHAR) 'Z'; driveLetter[0]++) {
if (DriveLetterIsAvailable((CHAR)driveLetter[0])) {
// No sense calling this stuff for something that doesn't exist
continue;
}
compressed = FALSE;
if (FmIfsQueryInformation(&driveLetter[0],
&removable,
&floppy,
&compressed,
&error,
&ntDriveName[0],
MAX_IFS_NAME_LENGTH,
&cvfName[0],
MAX_IFS_NAME_LENGTH,
&hostDriveName[0],
MAX_IFS_NAME_LENGTH)) {
// call worked, see if it is a double space volume
if (compressed) {
// now need to find this volume in the chain and
// update it mounted state.
for (dblSpace = DblChainBase;
dblSpace;
dblSpace = dblSpace->DblChainNext) {
for (index = 0;
compareName[index] = (WCHAR) dblSpace->FileName[index];
index++) {
// Everything in for loop
}
if (!wcscmp(compareName, cvfName)) {
// found a match.
dblSpace->Mounted = TRUE;
dblSpace->DriveLetter = (UCHAR) driveLetter[0];
}
}
}
}
}
SetErrorMode(errorMode);
}
VOID
DblSpaceInitialize(
VOID
)
/*++
Routine Description:
This routine goes through the disk table and searches for FAT format
partitions. When one is found, it checks for the presense of DoubleSpace
volumes and initializes the DoubleSpace support structures inside
Disk Administrator.
Arguments:
None
Return Value:
None
--*/
{
PDISKSTATE diskState;
PREGION_DESCRIPTOR regionDesc;
PPERSISTENT_REGION_DATA regionData;
PDBLSPACE_DESCRIPTOR dblSpace,
prevDblSpace;
FILE *dblSpaceIniFile,
*dblSpaceFile;
CHAR driveLetter[10];
CHAR fileName[50];
ULONG size,
mounted;
int items;
unsigned diskIndex,
regionIndex;
for (diskIndex = 0; diskIndex < DiskCount; diskIndex++) {
diskState = Disks[diskIndex];
regionDesc = diskState->RegionArray;
for (regionIndex = 0; regionIndex < diskState->RegionCount; regionIndex++) {
regionData = PERSISTENT_DATA(&regionDesc[regionIndex]);
// region may be free or something that isn't recognized by NT
if (!regionData) {
continue;
}
// region may not be formatted yet.
if (!regionData->TypeName) {
continue;
}
// Double space volumes are only allowed on FAT non-FT partitions.
if (regionData->FtObject) {
continue;
}
if (wcscmp(regionData->TypeName, L"FAT") == 0) {
WIN32_FIND_DATA findInformation;
HANDLE findHandle;
// it is possible to have a double space volume here.
// Search the root directory of the driver for files with
// the name "dblspace.xxx". These are potentially dblspace
// volumes.
prevDblSpace = NULL;
sprintf(fileName, DblSpaceWildCardFileName, regionData->DriveLetter);
findHandle = FindFirstFile(fileName, &findInformation);
while (findHandle != INVALID_HANDLE_VALUE) {
char *cp;
int i;
int save;
// There is at least one dblspace volume. Insure that
// the name is of the proper form.
save = TRUE;
cp = &findInformation.cFileName[0];
while (*cp) {
if (*cp == '.') {
break;
}
cp++;
}
if (*cp != '.') {
// not a proper dblspace volume name.
save = FALSE;
} else {
cp++;
for (i = 0; i < 3; i++, cp++) {
if ((*cp < '0') || (*cp > '9')) {
break;
}
}
if (i != 3) {
// not a proper dblspace volume name.
save = FALSE;
}
}
if (save) {
// save the information and search for more.
dblSpace =
DblSpaceCreateInternalStructure(' ',
((findInformation.nFileSizeHigh << 16) |
(findInformation.nFileSizeLow)
/ (1024 * 1024)),
&findInformation.cFileName[0],
TRUE);
if (dblSpace) {
// Assume volume is not mounted.
dblSpace->Mounted = FALSE;
dblSpace->ChangeMountState = FALSE;
// Chain in this description.
if (prevDblSpace) {
prevDblSpace->Next = dblSpace;
} else {
regionData->DblSpace = dblSpace;
}
// Keep the pointer to this one for the chain.
prevDblSpace = dblSpace;
} else {
// no memory
break;
}
}
if (!FindNextFile(findHandle, &findInformation)) {
// Technically this should double check and call
// GetLastError to see that it is ERROR_NO_MORE_FILES
// but this code doesn't do that.
FindClose(findHandle);
// Get out of the search loop.
findHandle = INVALID_HANDLE_VALUE;
}
}
}
}
}
// Now that all volumes have been located determine which volumes
// are mounted by chasing down the drive letters.
LoadIfsDll();
DblSpaceDetermineMounted();
}
PDBLSPACE_DESCRIPTOR
DblSpaceGetNextVolume(
IN PREGION_DESCRIPTOR RegionDescriptor,
IN PDBLSPACE_DESCRIPTOR DblSpace
)
/*++
Routine Description:
This routine will check the RegionDescriptor to walk the DoubleSpace volume chain
located from the persistent data.
Arguments:
RegionDescriptor - pointer to the region on the disk that is to be searched for
a DoubleSpace volume.
DblSpace - pointer to the last DoubleSpace volume located on the region.
Return Value:
pointer to the next DoubleSpace volume if found
NULL if no volume found.
--*/
{
PPERSISTENT_REGION_DATA regionData;
// If a previous DoubleSpace location was past, simply walk the chain to the next.
if (DblSpace) {
return DblSpace->Next;
}
// no previous DoubleSpace location, just get the first one and return it.
// Could get a NULL RegionDescriptor. If so, return NULL.
if (RegionDescriptor) {
regionData = PERSISTENT_DATA(RegionDescriptor);
if (!regionData) {
return NULL;
}
} else {
return NULL;
}
return regionData->DblSpace;
}
VOID
DblSpaceLinkNewVolume(
IN PREGION_DESCRIPTOR RegionDescriptor,
IN PDBLSPACE_DESCRIPTOR DblSpace
)
/*++
Routine Description:
Chain the new double space volume on the list of double space volumes
for the region.
Arguments:
RegionDescriptor - the region the double space volume has been added to.
DblSpace - the new volume internal data structure.
Return Value:
None
--*/
{
PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(RegionDescriptor);
PDBLSPACE_DESCRIPTOR prevDblSpace;
// if this is the first one, chain it first
if (!regionData->DblSpace) {
regionData->DblSpace = DblSpace;
return;
}
for (prevDblSpace = regionData->DblSpace;
prevDblSpace->Next;
prevDblSpace = prevDblSpace->Next) {
// all the work is in the for
}
// found the last one. Add the new one to the chain
prevDblSpace->Next = DblSpace;
}
BOOL
DblSpaceVolumeExists(
IN PREGION_DESCRIPTOR RegionDescriptor
)
/*++
Routine Description:
Indicate to the caller if the input region contains a DoubleSpace volume.
Arguments:
RegionDescriptor - a pointer to the region in question.
Return Value:
TRUE if this region contains DoubleSpace volume(s).
FALSE if not
--*/
{
PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(RegionDescriptor);
if (regionData) {
return(regionData->DblSpace ? TRUE : FALSE);
}
return FALSE;
}
BOOL
DblSpaceDismountedVolumeExists(
IN PREGION_DESCRIPTOR RegionDescriptor
)
/*++
Routine Description:
Indicate to the caller if the input region contains a DoubleSpace volume
that is not mounted.
Arguments:
RegionDescriptor - a pointer to the region in question.
Return Value:
TRUE if this region contains DoubleSpace volume(s).
FALSE if not
--*/
{
PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(RegionDescriptor);
PDBLSPACE_DESCRIPTOR dblSpace;
if (regionData) {
if (dblSpace = regionData->DblSpace) {
while (dblSpace) {
if (!dblSpace->Mounted) {
return TRUE;
}
dblSpace = dblSpace->Next;
}
}
}
return FALSE;
}
PDBLSPACE_DESCRIPTOR
DblSpaceFindVolume(
IN PREGION_DESCRIPTOR RegionDescriptor,
IN PCHAR Name
)
/*++
Routine Description:
Given a region and a name, locate the double space data structure.
Arguments:
RegionDescriptor - the region to search
Name - the filename wanted.
Return Value:
A pointer to a double space descriptor if found.
NULL if not found.
--*/
{
PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(RegionDescriptor);
PDBLSPACE_DESCRIPTOR dblSpace = NULL;
PCHAR string[50];
if (regionData) {
for (dblSpace = regionData->DblSpace; dblSpace; dblSpace = dblSpace->Next) {
if (strcmp(Name, dblSpace->FileName) == 0) {
// found the desired double space volume
break;
}
}
}
return dblSpace;
}
BOOL
DblSpaceDetermineUniqueFileName(
IN PREGION_DESCRIPTOR RegionDescriptor,
IN PUCHAR FileName
)
/*++
Routine Description:
This routine will search the actual partition to determine what
valid double space file name to use (i.e. dblspace.xxx where xxx
is a unique number).
Arguments:
RegionDescriptor - the region to search and determine what double space
file names are in use.
FileName - a pointer to a character buffer for the name.
Return Value:
None
--*/
{
DWORD uniqueNumber = 0;
PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(RegionDescriptor);
PDBLSPACE_DESCRIPTOR dblSpace;
do {
sprintf(FileName, "dblspace.%03d", uniqueNumber++);
if (uniqueNumber > 999) {
return FALSE;
}
} while (DblSpaceFindVolume(RegionDescriptor, FileName));
return TRUE;
}
VOID
DblSpaceRemoveVolume(
IN PREGION_DESCRIPTOR RegionDescriptor,
IN UCHAR DriveLetter
)
/*++
Routine Description:
Find the drive letter provided and unlink it from the chain.
Currently this also removes the volume for the scaffolding file.
Arguments:
RegionDescriptor - region containing the double space volume.
DriveLetter - the drive letter to remove.
Return Value:
None
--*/
{
PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(RegionDescriptor);
PDBLSPACE_DESCRIPTOR dblSpace,
prevDblSpace = NULL;
// Clean up the internal structures.
if (regionData) {
for (dblSpace = regionData->DblSpace; dblSpace; dblSpace = dblSpace->Next) {
if (dblSpace->DriveLetter == DriveLetter) {
// This is the one to delete
if (prevDblSpace) {
prevDblSpace->Next = dblSpace->Next;
} else {
regionData->DblSpace = dblSpace->Next;
}
free(dblSpace);
break;
}
prevDblSpace = dblSpace;
}
}
}
INT
CreateDblSpaceDlgProc(
IN HWND hDlg,
IN UINT wMsg,
IN WPARAM wParam,
IN LONG lParam
)
/*++
Routine Description:
This routine manages the dialog for the creation of a new double
space volume.
Arguments:
hDlg - the dialog box handle.
wMsg - the message.
wParam - the windows parameter.
lParam - depends on message type.
Return Value:
TRUE is returned back through windows if the create is successful
FALSE otherwise
--*/
{
PREGION_DESCRIPTOR regionDescriptor = &SingleSel->RegionArray[SingleSelIndex];
PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(regionDescriptor);
PDBLSPACE_DESCRIPTOR dblSpace;
static FORMAT_PARAMS formatParams; // this is passed to other threads
// it cannot be located on the stack
static HWND hwndCombo;
static DWORD sizeMB = 0,
maxSizeMB = 600,
minSizeMB = 10;
TCHAR outputString[50],
driveLetterString[4], // big enough for "x:" string.
sizeString[20], // must be big enough for an 8.3 name
letter;
FILE *dblspaceIniFile;
DWORD compressedSize,
selection;
BOOL validNumber;
CHAR fileName[50];
switch (wMsg) {
case WM_INITDIALOG:
// limit the size of string that may be entered for the label
hwndCombo = GetDlgItem(hDlg, IDC_NAME);
SendMessage(hwndCombo, EM_LIMITTEXT, 11, 0);
// set up to watch all characters that go thru the size dialog
// to allow only decimal numbers.
hwndCombo = GetDlgItem(hDlg, IDC_DBLSPACE_SIZE);
OldSizeDlgProc = (WNDPROC) SetWindowLong(hwndCombo,
GWL_WNDPROC,
(LONG)&SizeDlgProc);
// Add each available drive letter to the list of available
// drive letters and set the default letter to the first available.
hwndCombo = GetDlgItem(hDlg, IDC_DRIVELET_COMBOBOX);
driveLetterString[1] = TEXT(':');
driveLetterString[2] = 0;
for (letter='C'; letter <= 'Z'; letter++) {
if (DriveLetterIsAvailable((CHAR)letter)) {
*driveLetterString = letter;
SendMessage(hwndCombo, CB_ADDSTRING, 0, (LONG)driveLetterString);
}
}
SendMessage(hwndCombo,CB_SETCURSEL,0,0);
// Setup the min/max values and the size box.
wsprintf(outputString, TEXT("%u"), 0);
SetDlgItemText(hDlg, IDC_DBLSPACE_SIZE, outputString);
wsprintf(outputString, TEXT("%u"), minSizeMB);
SetDlgItemText(hDlg, IDC_MINMAX_MIN, outputString);
wsprintf(outputString, TEXT("%u"), maxSizeMB);
SetDlgItemText(hDlg, IDC_MINMAX_MAX, outputString);
CenterDialog(hDlg);
return TRUE;
case WM_VSCROLL:
{
switch (LOWORD(wParam)) {
case SB_LINEDOWN:
case SB_LINEUP:
// user is pressing one of the scroll buttons.
sizeMB = GetDlgItemInt(hDlg, IDC_DBLSPACE_SIZE, &validNumber, FALSE);
if (sizeMB < minSizeMB) {
sizeMB = minSizeMB + 1;
}
if (sizeMB > maxSizeMB) {
sizeMB = maxSizeMB - 1;
}
if (((sizeMB > minSizeMB) && (LOWORD(wParam) == SB_LINEDOWN))
|| ((sizeMB < maxSizeMB) && (LOWORD(wParam) == SB_LINEUP ))) {
if (sizeMB > maxSizeMB) {
sizeMB = maxSizeMB;
} else if (LOWORD(wParam) == SB_LINEUP) {
sizeMB++;
} else {
sizeMB--;
}
SetDlgItemInt(hDlg, IDC_DBLSPACE_SIZE, sizeMB, FALSE);
SendDlgItemMessage(hDlg, IDC_DBLSPACE_SIZE, EM_SETSEL, 0, -1);
#if 0
compressedSize = sizeMB * 2;
wsprintf(outputString, TEXT("%u"), compressedSize);
SetDlgItemText(hDlg, IDC_DBLSPACE_COMPRESSED, outputString);
#endif
} else {
Beep(500,100);
}
}
break;
}
case WM_COMMAND:
switch (wParam) {
case FD_IDHELP:
break;
case IDCANCEL:
EndDialog(hDlg, FALSE);
break;
case IDOK:
// can only do this if the fmifs dll supports double space.
if (!DoubleSpaceSupported) {
// could not load the dll
ErrorDialog(MSG_CANT_LOAD_FMIFS);
EndDialog(hDlg, FALSE);
break;
}
// Get the current size for this volume.
sizeMB = GetDlgItemInt(hDlg, IDC_DBLSPACE_SIZE, &validNumber, FALSE);
if (!validNumber || !sizeMB || (sizeMB > maxSizeMB) || (sizeMB < minSizeMB)) {
ErrorDialog(MSG_INVALID_SIZE);
EndDialog(hDlg, FALSE);
break;
}
// Get the currently selected item in the listbox for drive letter
selection = SendMessage(hwndCombo, CB_GETCURSEL, 0, 0);
SendMessage(hwndCombo, CB_GETLBTEXT, selection, (LONG)driveLetterString);
formatParams.RegionDescriptor = regionDescriptor;
formatParams.RegionData = regionData;
formatParams.FileSystem = NULL;
formatParams.DblspaceFileName = NULL;
formatParams.QuickFormat = formatParams.Cancel = FALSE;
formatParams.DoubleSpace = TRUE;
formatParams.TotalSpace = 0;
formatParams.SpaceAvailable = sizeMB;
formatParams.NewLetter = driveLetterString[0];
// get the label
formatParams.Label = (PUCHAR) malloc(100);
GetDlgItemText(hDlg, IDC_NAME, (LPTSTR)formatParams.Label, 100);
DialogBoxParam(hModule,
MAKEINTRESOURCE(IDD_DBLSPACE_CANCEL),
hwndFrame,
(DLGPROC) CancelDlgProc,
(ULONG) &formatParams);
if (formatParams.Result) {
// the format failed.
ErrorDialog(formatParams.Result);
EndDialog(hDlg, FALSE);
} else {
ULONG index;
TCHAR message[300],
msgProto[300],
title[200];
// save the name
if (formatParams.DblspaceFileName) {
for (index = 0;
message[index] = (TCHAR) formatParams.DblspaceFileName[index];
index++) {
}
} else {
sprintf(message, "DIDNTWORK");
}
free(formatParams.DblspaceFileName);
dblSpace = DblSpaceCreateInternalStructure(*driveLetterString,
sizeMB,
message,
FALSE);
if (dblSpace) {
DblSpaceLinkNewVolume(regionDescriptor, dblSpace);
MarkDriveLetterUsed(dblSpace->DriveLetter);
dblSpace->Mounted = TRUE;
}
LoadString(hModule,
IDS_DBLSPACECOMPLETE,
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);
EndDialog(hDlg, TRUE);
}
break;
default:
if (HIWORD(wParam) == EN_CHANGE) {
// The size value has changed. Update the compressed
// size value displayed to the user.
sizeMB = GetDlgItemInt(hDlg, IDC_DBLSPACE_SIZE, &validNumber, FALSE);
if (!validNumber) {
sizeMB = 0;
}
}
break;
}
break;
case WM_DESTROY:
// restore original subclass to window.
hwndCombo = GetDlgItem(hDlg, IDC_DBLSPACE_SIZE);
SetWindowLong(hwndCombo, GWL_WNDPROC, (LONG) OldSizeDlgProc);
break;
case WM_PAINT:
// This may be dead code that really isn't needed.
sizeMB = GetDlgItemInt(hDlg, IDC_DBLSPACE_SIZE, &validNumber, FALSE);
if (!validNumber || !sizeMB || (sizeMB > maxSizeMB) || (sizeMB < minSizeMB)) {
return FALSE;
}
SetDlgItemInt(hDlg, IDC_DBLSPACE_SIZE, sizeMB, FALSE);
SendDlgItemMessage(hDlg, IDC_DBLSPACE_SIZE, EM_SETSEL, 0, -1);
break;
}
return FALSE;
}
VOID
DblSpaceDelete(
IN PDBLSPACE_DESCRIPTOR DblSpace
)
/*++
Routine Description:
Start the dialog box for the deletion of a double space volume.
Arguments:
Param - not currently used.
Return Value:
None
--*/
{
PREGION_DESCRIPTOR regionDescriptor = &SingleSel->RegionArray[SingleSelIndex];
PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(regionDescriptor);
if (ConfirmationDialog(MSG_CONFIRM_DBLSPACE_DELETE, MB_ICONQUESTION | MB_YESNOCANCEL) == IDYES) {
// Delete the drive from view
DblSpaceRemoveVolume(regionDescriptor, DblSpace->DriveLetter);
DblSpaceUpdateIniFile(regionDescriptor);
DrawDiskBar(SingleSel);
ForceLBRedraw();
}
}
BOOLEAN
DblSpaceCreate(
IN HWND Dialog,
IN PVOID Param
)
/*++
Routine Description:
Start the dialog box for the creation of a double space volume.
Arguments:
Param - not currently used.
Return Value:
None
--*/
{
BOOLEAN result = 0;
result = DialogBoxParam(hModule,
MAKEINTRESOURCE(IDD_DBLSPACE_CREATE),
Dialog,
(DLGPROC) CreateDblSpaceDlgProc,
(ULONG) NULL);
if (result) {
DrawDiskBar(SingleSel);
ForceLBRedraw();
}
return result;
}
INT
DblSpaceMountDlgProc(
IN HWND hDlg,
IN UINT wMsg,
IN DWORD wParam,
IN LONG lParam
)
/*++
Routine Description:
Handle the dialog for double space.
Arguments:
Standard Windows dialog procedure.
Return Value:
TRUE if something was deleted.
FALSE otherwise.
--*/
{
static PDBLSPACE_DESCRIPTOR dblSpace;
HWND hwndCombo;
DWORD selection;
CHAR driveLetter;
TCHAR driveLetterString[20];
switch (wMsg) {
case WM_INITDIALOG:
dblSpace = (PDBLSPACE_DESCRIPTOR) lParam;
// Update the drive letter selections.
hwndCombo = GetDlgItem(hDlg, IDC_DRIVELET_COMBOBOX);
// Add all other available letters. Keep track of current
// letters offset to set the cursor correctly
driveLetterString[1] = TEXT(':');
driveLetterString[2] = 0;
for (driveLetter = 'C'; driveLetter <= 'Z'; driveLetter++) {
if (DriveLetterIsAvailable((CHAR)driveLetter) ||
(driveLetter == dblSpace->DriveLetter)) {
*driveLetterString = driveLetter;
SendMessage(hwndCombo, CB_ADDSTRING, 0, (LONG)driveLetterString);
}
}
// set the current selection to the appropriate index
SendMessage(hwndCombo, CB_SETCURSEL, 0, 0);
return TRUE;
case WM_COMMAND:
switch (wParam) {
case FD_IDHELP:
DialogHelp(HC_DM_DLG_DOUBLESPACE_MOUNT);
break;
case IDCANCEL:
EndDialog(hDlg, FALSE);
break;
case IDOK:
// User has selected the drive letter and wants the mount to occur.
hwndCombo = GetDlgItem(hDlg, IDC_DRIVELET_COMBOBOX);
selection = SendMessage(hwndCombo, CB_GETCURSEL, 0, 0);
SendMessage(hwndCombo,
CB_GETLBTEXT,
selection,
(LONG)driveLetterString);
dblSpace->NewDriveLetter = (UCHAR) driveLetterString[0];
EndDialog(hDlg, TRUE);
break;
}
}
return FALSE;
}
VOID
DblSpaceSetDialogState(
IN HWND hDlg,
IN PDBLSPACE_DESCRIPTOR DblSpace
)
/*++
Routine Description:
Given a double space volume this routine will update the buttons
in the dialog box to reflect they meaning.
Arguments:
hDlg - dialog handle
DblSpace - The double space volume selection for determining dialog state.
Return Value
None
--*/
{
TCHAR outputString[200];
if (DblSpace->Mounted) {
LoadString(hModule,
IDS_DBLSPACE_MOUNTED,
outputString,
sizeof(outputString)/sizeof(TCHAR));
SetDlgItemText(hDlg, IDC_MOUNT_STATE, outputString);
LoadString(hModule,
IDS_DISMOUNT,
outputString,
sizeof(outputString)/sizeof(TCHAR));
SetDlgItemText(hDlg, ID_MOUNT_OR_DISMOUNT, outputString);
outputString[1] = TEXT(':');
outputString[2] = 0;
outputString[0] = DblSpace->DriveLetter;
SetDlgItemText(hDlg, IDC_DBLSPACE_LETTER, outputString);
} else {
LoadString(hModule,
IDS_DBLSPACE_DISMOUNTED,
outputString,
sizeof(outputString)/sizeof(TCHAR));
SetDlgItemText(hDlg, IDC_MOUNT_STATE, outputString);
LoadString(hModule,
IDS_MOUNT,
outputString,
sizeof(outputString)/sizeof(TCHAR));
SetDlgItemText(hDlg, ID_MOUNT_OR_DISMOUNT, outputString);
outputString[1] = TEXT(' ');
outputString[2] = 0;
outputString[0] = TEXT(' ');
SetDlgItemText(hDlg, IDC_DBLSPACE_LETTER, outputString);
}
}
INT
DblSpaceDlgProc(
IN HWND hDlg,
IN UINT wMsg,
IN DWORD wParam,
IN LONG lParam
)
/*++
Routine Description:
Handle the dialog for double space.
Arguments:
Return Value:
TRUE if something was deleted.
FALSE otherwise.
--*/
{
static HWND hwndCombo,
mountButtonHwnd,
deleteButtonHwnd;
static PREGION_DESCRIPTOR regionDescriptor;
static PPERSISTENT_REGION_DATA regionData;
static PDBLSPACE_DESCRIPTOR firstDblSpace;
CHAR driveLetter;
PDBLSPACE_DESCRIPTOR dblSpace;
TCHAR outputString[200];
DWORD selection;
BOOLEAN result;
ULONG errorMessage;
DRAWITEMSTRUCT drawItem;
switch (wMsg) {
case WM_INITDIALOG:
regionDescriptor = &SingleSel->RegionArray[SingleSelIndex];
regionData = PERSISTENT_DATA(regionDescriptor);
hwndCombo = GetDlgItem(hDlg, IDC_DBLSPACE_VOLUME);
mountButtonHwnd = GetDlgItem(hDlg, ID_MOUNT_OR_DISMOUNT);
deleteButtonHwnd = GetDlgItem(hDlg, IDDELETE);
// place all double space file names in the selection
// box and remember the first name.
firstDblSpace = dblSpace = DblSpaceGetNextVolume(regionDescriptor, NULL);
for (; dblSpace;
dblSpace = DblSpaceGetNextVolume(regionDescriptor, dblSpace)) {
wsprintf(outputString, TEXT("%s"), dblSpace->FileName);
SendMessage(hwndCombo, CB_ADDSTRING, 0, (LONG)outputString);
}
SendMessage(hwndCombo, CB_SETCURSEL, 0, 0);
// add the drive letter
if (firstDblSpace) {
// update the allocated size.
wsprintf(outputString, TEXT("%u"), firstDblSpace->AllocatedSize);
SetDlgItemText(hDlg, IDC_DBLSPACE_ALLOCATED, outputString);
// update mount state
DblSpaceSetDialogState(hDlg, firstDblSpace);
EnableWindow(mountButtonHwnd, TRUE);
EnableWindow(deleteButtonHwnd, TRUE);
} else {
// update the Mount/Dismount button to say mount and grey it
LoadString(hModule,
IDS_MOUNT,
outputString,
sizeof(outputString)/sizeof(TCHAR));
SetDlgItemText(hDlg, ID_MOUNT_OR_DISMOUNT, outputString);
EnableWindow(mountButtonHwnd, FALSE);
EnableWindow(deleteButtonHwnd, FALSE);
}
return TRUE;
case WM_COMMAND:
switch (wParam) {
case FD_IDHELP:
DialogHelp(HC_DM_DLG_DOUBLESPACE);
break;
case IDCANCEL:
// Run the dblspace change and forget about any changes.
for (dblSpace = firstDblSpace;
dblSpace;
dblSpace = DblSpaceGetNextVolume(regionDescriptor, dblSpace)) {
dblSpace->ChangeMountState = FALSE;
dblSpace->NewDriveLetter = 0;
}
EndDialog(hDlg, FALSE);
break;
case IDOK:
EndDialog(hDlg, TRUE);
break;
case IDADD:
DblSpaceCreate(hDlg, NULL);
break;
case IDDELETE:
hwndCombo = GetDlgItem(hDlg, IDC_DBLSPACE_VOLUME);
selection = SendMessage(hwndCombo, CB_GETCURSEL, 0, 0);
SendMessage(hwndCombo,
CB_GETLBTEXT,
selection,
(LONG)outputString);
// relate the name to a double space volume
dblSpace = DblSpaceFindVolume(regionDescriptor, (PCHAR)outputString);
if (!dblSpace) {
break;
}
DblSpaceDelete(dblSpace);
break;
case ID_MOUNT_OR_DISMOUNT:
// The state of something in the dialog changed.
// Determine which double space volume is involved.
hwndCombo = GetDlgItem(hDlg, IDC_DBLSPACE_VOLUME);
selection = SendMessage(hwndCombo, CB_GETCURSEL, 0, 0);
SendMessage(hwndCombo,
CB_GETLBTEXT,
selection,
(LONG)outputString);
// relate the name to a double space volume
dblSpace = DblSpaceFindVolume(regionDescriptor, (PCHAR)outputString);
if (!dblSpace) {
break;
}
if (dblSpace->Mounted) {
// dismount the volume
errorMessage = DblSpaceDismountDrive(regionDescriptor,
dblSpace);
if (errorMessage) {
ErrorDialog(errorMessage);
} else {
// Update the dialog
DblSpaceSetDialogState(hDlg, dblSpace);
DblSpaceUpdateIniFile(regionDescriptor);
}
} else {
// mount the volume unless the user cancels out
result = DialogBoxParam(hModule,
MAKEINTRESOURCE(IDD_DBLSPACE_DRIVELET),
hwndFrame,
(DLGPROC) DblSpaceMountDlgProc,
(ULONG) dblSpace);
if (result) {
errorMessage = DblSpaceMountDrive(regionDescriptor, dblSpace);
if (errorMessage) {
ErrorDialog(errorMessage);
} else {
// Update the dialog
DblSpaceSetDialogState(hDlg, dblSpace);
DblSpaceUpdateIniFile(regionDescriptor);
}
}
}
DrawDiskBar(SingleSel);
ForceLBRedraw();
break;
default:
// The state of something in the dialog changed.
// Determine which double space volume is involved.
hwndCombo = GetDlgItem(hDlg, IDC_DBLSPACE_VOLUME);
selection = SendMessage(hwndCombo, CB_GETCURSEL, 0, 0);
SendMessage(hwndCombo,
CB_GETLBTEXT,
selection,
(LONG)outputString);
// relate the name to a double space volume
dblSpace = DblSpaceFindVolume(regionDescriptor, (PCHAR)outputString);
if (!dblSpace) {
// update the Mount/Dismount button to say mount and grey it
LoadString(hModule,
IDS_MOUNT,
outputString,
sizeof(outputString)/sizeof(TCHAR));
SetDlgItemText(hDlg, ID_MOUNT_OR_DISMOUNT, outputString);
EnableWindow(mountButtonHwnd, FALSE);
EnableWindow(deleteButtonHwnd, FALSE);
break;
} else {
EnableWindow(mountButtonHwnd, TRUE);
EnableWindow(deleteButtonHwnd, TRUE);
}
if (HIWORD(wParam) == LBN_SELCHANGE) {
// update the allocated/compressed size items
wsprintf(outputString, TEXT("%u"), dblSpace->AllocatedSize);
SetDlgItemText(hDlg, IDC_DBLSPACE_ALLOCATED, outputString);
#if 0
wsprintf(outputString, TEXT("%u"), dblSpace->AllocatedSize * 2);
SetDlgItemText(hDlg, IDC_DBLSPACE_COMPRESSED, outputString);
wsprintf(outputString, TEXT("%u.%u"), 2, 0);
SetDlgItemText(hDlg, IDC_DBLSPACE_RATIO, outputString);
#endif
// update mount state
DblSpaceSetDialogState(hDlg, dblSpace);
}
break;
}
break;
}
return FALSE;
}
VOID
DblSpace(
IN HWND Dialog,
IN PVOID Param
)
/*++
Routine Description:
Start the dialog box for double space.
Arguments:
Param - not currently used.
Return Value:
None
--*/
{
BOOLEAN result;
if (IsFullDoubleSpace) {
result = DialogBoxParam(hModule,
MAKEINTRESOURCE(IDD_DBLSPACE_FULL),
Dialog,
(DLGPROC) DblSpaceDlgProc,
(ULONG) NULL);
} else {
result = DialogBoxParam(hModule,
MAKEINTRESOURCE(IDD_DBLSPACE),
Dialog,
(DLGPROC) DblSpaceDlgProc,
(ULONG) NULL);
}
if (result) {
DrawDiskBar(SingleSel);
ForceLBRedraw();
}
}
#else
// STUBS for easy removal of DoubleSpace support.
BOOL
DblSpaceVolumeExists(
IN PREGION_DESCRIPTOR RegionDescriptor
)
{
return FALSE;
}
BOOL
DblSpaceDismountedVolumeExists(
IN PREGION_DESCRIPTOR RegionDescriptor
)
{
return FALSE;
}
BOOLEAN
DblSpaceCreate(
IN HWND Dialog,
IN PVOID Param
)
{
return FALSE;
}
VOID
DblSpaceDelete(
IN PVOID Param
)
{
}
VOID
DblSpaceMount(
IN PVOID Param
)
{
}
VOID
DblSpaceDismount(
IN PVOID Param
)
{
}
VOID
DblSpaceInitialize(
VOID
)
{
}
VOID
DblSpace(
IN HWND Dialog,
IN PVOID Param
)
{
}
PDBLSPACE_DESCRIPTOR
DblSpaceGetNextVolume(
IN PREGION_DESCRIPTOR RegionDescriptor,
IN PDBLSPACE_DESCRIPTOR DblSpace
)
{
return NULL;
}
#endif