windows-nt/Source/XPSP1/NT/base/fs/hsm/wsb/wsbfmt.cpp

638 lines
16 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1999 Microsoft Corporation
Module Name:
wsbfmt.cpp
Abstract:
This module implements file-system formatting support routines
Author:
Ravisankar Pudipeddi [ravisp] 19, January 2000
Revision History:
--*/
#include <stdafx.h>
extern "C" {
#include <ntdddisk.h>
#include <fmifs.h>
}
#include <wsbfmt.h>
#define MAX_FS_NAME_SIZE 256
#define MAX_PARAMS 20
#define INVALID_KEY 0
typedef struct _FORMAT_PARAMS {
PWSTR volumeSpec;
PWSTR label;
PWSTR fsName;
LONG fsType;
ULONG fsflags;
ULONG allocationUnitSize; // Cluster size in Bytes
HRESULT result;
ULONG threadId;
PFMIFS_ENABLECOMP_ROUTINE compressRoutine;
PFMIFS_FORMAT_ROUTINE formatRoutine;
PFMIFS_FORMATEX2_ROUTINE formatRoutineEx;
BOOLEAN quick;
BOOLEAN force;
BOOLEAN cancel;
} FORMAT_PARAMS, *PFORMAT_PARAMS;
typedef struct _FM_ENTRY {
ULONG key;
PFORMAT_PARAMS val;
} FM_ENTRY, *PFM_ENTRY;
static FM_ENTRY formatParamsTable[MAX_PARAMS];
static PFMIFS_FORMATEX2_ROUTINE FormatRoutineEx = NULL;
static PFMIFS_FORMAT_ROUTINE FormatRoutine = NULL;
static PFMIFS_SETLABEL_ROUTINE LabelRoutine = NULL;
static PFMIFS_ENABLECOMP_ROUTINE CompressRoutine = NULL;
static HINSTANCE IfsDllHandle = NULL;
void MountFileSystem(PWSTR volumeSpec);
HRESULT GetFormatParam(IN ULONG key, OUT PFORMAT_PARAMS *fp)
/*++
Routine Description:
Returns the format parameter structure indexed by the
supplied key
Arguments:
key - key indexing the format params
fp - pointer to format params returned in this var.
Return Value:
S_OK if found
S_FALSE if not
--*/
{
HRESULT hr = S_FALSE;
ULONG i;
WsbTraceIn(OLESTR("GetFormatParam"), OLESTR(""));
for (i = 0; i < MAX_PARAMS; i++) {
if (formatParamsTable[i].key == key) {
hr = S_OK;
*fp = formatParamsTable[i].val;
break;
}
}
WsbTraceOut(OLESTR("GetFormatParam"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
return hr;
}
HRESULT SetFormatParam(IN ULONG key, IN PFORMAT_PARAMS fp)
/*++
Routine Description:
Finds a free slot and stores the supplied format params,
indexed by the key
Arguments:
key - key indexing the format params
fp - pointer to format params
Return Value:
S_OK - Found a slot and stored the format params
E_OUTOFMEMORY - Couldn't find a slot: too many formats in progress
--*/
{
HRESULT hr = E_OUTOFMEMORY;
ULONG i;
WsbTraceIn(OLESTR("SetFormatParam"), OLESTR(""));
for (i = 0; i < MAX_PARAMS; i++) {
if (formatParamsTable[i].key == INVALID_KEY) {
hr = S_OK;
formatParamsTable[i].val = fp;
formatParamsTable[i].key = key;
break;
}
}
WsbTraceOut(OLESTR("SetFormatParam"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
return hr;
}
HRESULT DeleteFormatParam(IN ULONG key)
/*++
Routine Description:
Locates the format params indexed by the key, deletes all allocated structures
and frees up the slot
Arguments:
key - key indexing the format params
Return Value:
S_OK - if format params found and deleted
E_FAIL - if not
--*/
{
PFORMAT_PARAMS formatParams;
HRESULT hr = E_FAIL;
ULONG i;
WsbTraceIn(OLESTR("DeleteFormatParam"), OLESTR(""));
for (i = 0; i < MAX_PARAMS; i++) {
if (formatParamsTable[i].key == key) {
hr = S_OK;
formatParams = formatParamsTable[i].val;
if (formatParams) {
if (formatParams->volumeSpec) {
delete [] formatParams->volumeSpec;
}
if (formatParams->label) {
delete [] formatParams->label;
}
if (formatParams->fsName) {
delete [] formatParams->fsName;
}
}
formatParamsTable[i].key = INVALID_KEY;
formatParamsTable[i].val = NULL;
break;
}
}
WsbTraceOut(OLESTR("DeleteFormatParam"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
return hr;
}
BOOL
LoadIfsDll(void)
/*++
Routine Description:
Loads the FMIFS DLL and stores the handle to it in IfsDllHandle
Also sets the FormatXXX, LabelXXX, CompressXXX routines
Arguments:
None
Return Value:
TRUE if dll was loaded successfully
FALSE if not
--*/
{
BOOL retVal = TRUE;
WsbTraceIn(OLESTR("LoadIfsDll"), OLESTR(""));
if (IfsDllHandle != NULL) {
// Library is already loaded and the routines needed
// have been located.
retVal = TRUE;
goto exit;
}
IfsDllHandle = LoadLibrary(L"fmifs.dll");
if (IfsDllHandle == (HANDLE)NULL) {
// FMIFS not available.
retVal = FALSE;
goto exit;
}
// Library is loaded. Locate the two routines needed
FormatRoutineEx = (PFMIFS_FORMATEX2_ROUTINE) GetProcAddress(IfsDllHandle, "FormatEx2");
FormatRoutine = (PFMIFS_FORMAT_ROUTINE) GetProcAddress(IfsDllHandle, "Format");
LabelRoutine = (PFMIFS_SETLABEL_ROUTINE) GetProcAddress(IfsDllHandle, "SetLabel");
CompressRoutine = (PFMIFS_ENABLECOMP_ROUTINE) GetProcAddress(IfsDllHandle,
"EnableVolumeCompression");
if (!FormatRoutine || !LabelRoutine || !FormatRoutineEx) {
// Couldn't find something, so shut down all access
// to the library by ensuring FormatRoutine is NULL
FreeLibrary(IfsDllHandle);
FormatRoutine = NULL;
FormatRoutineEx = NULL;
LabelRoutine = NULL;
retVal = FALSE;
}
exit:
WsbTraceOut(OLESTR("LoadIfsDll"), OLESTR("result = <%ls>"), WsbBoolAsString(retVal));
return retVal;
}
void
UnloadIfsDll(void)
/*++
Routine Description:
Unloads the FMIFS dll
Arguments:
none
Return Value:
TRUE if unloaded
--*/
{
WsbTraceIn(OLESTR("UnloadIfsDll"), OLESTR(""));
if (IfsDllHandle != (HANDLE) NULL) {
FreeLibrary(IfsDllHandle);
FormatRoutine = NULL;
FormatRoutineEx = NULL;
IfsDllHandle = NULL;
LabelRoutine = NULL;
}
WsbTraceOut(OLESTR("UnloadIfsDll"), OLESTR(""));
}
BOOL
FmIfsCallback(IN FMIFS_PACKET_TYPE PacketType,
IN ULONG PacketLength,
IN PVOID PacketData)
/*++
Routine Description:
This routine gets callbacks from fmifs.dll regarding
progress and status of the ongoing format
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.
--*/
{
BOOL ret = TRUE;
WCHAR driveName[256];
PFORMAT_PARAMS formatParams;
UNREFERENCED_PARAMETER(PacketLength);
WsbTraceIn(OLESTR("FmIfsCallback"), OLESTR(""));
if (GetFormatParam(GetCurrentThreadId(), &formatParams) != S_OK) {
formatParams->result = E_FAIL;
goto exit;
}
//
// Cancel if needed
//
if (formatParams->cancel) {
formatParams->result = E_ABORT;
} else {
switch (PacketType) {
case FmIfsPercentCompleted:
if (((PFMIFS_PERCENT_COMPLETE_INFORMATION)
PacketData)->PercentCompleted % 10 == 0) {
WsbTrace(L"FmIfsPercentCompleted: %d%%\n",
((PFMIFS_PERCENT_COMPLETE_INFORMATION)
PacketData)->PercentCompleted);
}
break;
case FmIfsFormatReport:
WsbTrace(OLESTR("Format total kB: %d available kB %d\n"),
((PFMIFS_FORMAT_REPORT_INFORMATION)PacketData)->KiloBytesTotalDiskSpace,
((PFMIFS_FORMAT_REPORT_INFORMATION)PacketData)->KiloBytesAvailable);
break;
case FmIfsIncompatibleFileSystem:
formatParams->result = WSB_E_INCOMPATIBLE_FILE_SYSTEM;
break;
case FmIfsInsertDisk:
break;
case FmIfsFormattingDestination:
break;
case FmIfsIncompatibleMedia:
formatParams->result = WSB_E_BAD_MEDIA;
break;
case FmIfsAccessDenied:
formatParams->result = E_ACCESSDENIED;
break;
case FmIfsMediaWriteProtected:
formatParams->result = WSB_E_WRITE_PROTECTED;
break;
case FmIfsCantLock:
formatParams->result = WSB_E_CANT_LOCK;
break;
case FmIfsBadLabel:
formatParams->result = WSB_E_BAD_LABEL;
break;
case FmIfsCantQuickFormat:
formatParams->result = WSB_E_CANT_QUICK_FORMAT;
break;
case FmIfsIoError:
formatParams->result = WSB_E_IO_ERROR;
break;
case FmIfsVolumeTooSmall:
formatParams->result = WSB_E_VOLUME_TOO_SMALL;
break;
case FmIfsVolumeTooBig:
formatParams->result = WSB_E_VOLUME_TOO_BIG;
break;
case FmIfsClusterSizeTooSmall:
formatParams->result = E_FAIL;
break;
case FmIfsClusterSizeTooBig:
formatParams->result = E_FAIL;
break;
case FmIfsClustersCountBeyond32bits:
formatParams->result = E_FAIL;
break;
case FmIfsFinished:
if (formatParams->result == S_OK) {
ret = ((PFMIFS_FINISHED_INFORMATION) PacketData)->Success;
if (ret) {
MountFileSystem(formatParams->volumeSpec);
WsbTrace(OLESTR("Format finished for %S filesystem on %S label %S\n"),
formatParams->fsName, formatParams->volumeSpec, formatParams->label );
if ((formatParams->compressRoutine != NULL) && !wcscmp(formatParams->fsName , L"NTFS") && (formatParams->fsflags & WSBFMT_ENABLE_VOLUME_COMPRESSION)) {
swprintf(driveName, L"%s\\", formatParams->volumeSpec);
(formatParams->compressRoutine)(driveName, COMPRESSION_FORMAT_DEFAULT);
}
} else {
WsbTrace(OLESTR("Format finished failure with ret = %d\n"),ret);
formatParams->result = WSB_E_FORMAT_FAILED;
}
ret = FALSE;
}
break;
default:
break;
}
}
exit:
if (formatParams->result != S_OK) {
ret = FALSE;
}
WsbTraceOut(OLESTR("FmIfsCallback"), OLESTR("result = <%ls>"), WsbBoolAsString(ret));
return ret;
}
void
MountFileSystem(PWSTR mountPoint)
/*++
Routine Description:
Ensures a filesystem is mounted at the given root:
a) Opens the mount point and closes it.
b) Does a FindFirstFile on the mount point
The latter may sound redundant but is not because if we create the first
FAT32 filesystem then just opening and closing is not enough
Arguments:
mountPoint - path name to the root of filesystem to be mounted
Return Value:
none
--*/
{
WCHAR buffer[1024];
HANDLE handle;
WIN32_FIND_DATA fileData;
WsbTraceIn(OLESTR("MountFileSystem"), OLESTR(""));
handle = CreateFile(mountPoint, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
0, OPEN_EXISTING, 0, 0);
if (handle != INVALID_HANDLE_VALUE)
CloseHandle(handle);
swprintf(buffer,L"%s\\*.*",mountPoint);
/*
* Go ahead and try to find the first file, this will make sure that
* the file system is mounted
*/
handle = FindFirstFile(buffer, &fileData);
if (handle != INVALID_HANDLE_VALUE) {
FindClose(handle);
}
WsbTraceOut(OLESTR("MountFileSystem"), OLESTR(""));
}
void
FormatVolume(IN PFORMAT_PARAMS params)
/*++
Routine Description:
This routine format the volume described by params
Arguments:
params - pointer to the FORMAT_PARAMS describing the volume,
file system to be formatted to, quick/force etc.
Return Value:
None.
params->result contains the result of this operation
--*/
{
FMIFS_FORMATEX2_PARAM exParam;
HRESULT hr = S_OK;
WsbTraceIn(OLESTR("FormatVolume"), OLESTR(""));
/*
* Get the object corresponding to the storage Id and
* and notify all clients that the region has changed
* i.e. there is a format in progress on that region
*/
memset(&exParam, 0, sizeof(exParam));
exParam.Major = 1;
exParam.Minor = 0;
if (params->quick) {
exParam.Flags |= FMIFS_FORMAT_QUICK;
}
if (params->force) {
exParam.Flags |= FMIFS_FORMAT_FORCE;
}
exParam.LabelString = params->label;
exParam.ClusterSize = params->allocationUnitSize;
(params->formatRoutineEx)(params->volumeSpec,
FmMediaUnknown,
params->fsName,
&exParam,
(FMIFS_CALLBACK)&FmIfsCallback);
if (params->result == NULL) {
/* Format is successful so we lock unlock the filesystem */
MountFileSystem(params->volumeSpec);
}
DeleteFormatParam(params->threadId);
WsbTraceOut(OLESTR("FormatVolume"), OLESTR(""));
}
HRESULT
FormatPartition(IN PWSTR volumeSpec,
IN LONG fsType,
IN PWSTR label,
IN ULONG fsflags,
IN BOOLEAN quick,
IN BOOLEAN force,
IN ULONG allocationUnitSize)
/*++
Routine Description:
Entry point for formatting a volume.
No defaults are assumed and all parameters need to be supplied
Arguments:
volumeSpec - Drive letter or name of volume
fsType - One of FSTYPE_FAT, FSTYPE_FAT32, FSTYE_NTFS
label - Volume label to be assigned to the partition/volume
fsflags - Flags describing desired characteristics
quick - If TRUE, a quick format is attempted
force - If TRUE a force format is done
allocationUnitSize -
cluster size
Return Value:
Result of the operation
--*/
{
FORMAT_PARAMS params;
WsbTraceIn(OLESTR("FormatPartition"), OLESTR(""));
if (fsType > 0 && !LoadIfsDll()) // fsType is +ve for FAT, FAT32 and NTFS which are supported by fmifs
{
// could not load the Dll
WsbTrace(OLESTR("Can't load fmifs.dll\n"));
return E_FAIL;
}
params.volumeSpec = new WCHAR[wcslen(volumeSpec) + 1];
if (params.volumeSpec == NULL) {
return E_INVALIDARG;
}
params.label = new WCHAR[wcslen(label) + 1];
if (params.label == NULL) {
delete [] params.volumeSpec;
return E_INVALIDARG;
}
params.fsName = new WCHAR[MAX_FS_NAME_SIZE];
if (params.fsName == NULL) {
delete [] params.volumeSpec;
delete [] params.label;
return E_INVALIDARG;
}
if (fsType > 0) {
wcscpy(params.fsName, (fsType == FSTYPE_FAT ? L"FAT" :
(fsType == FSTYPE_FAT32 ? L"FAT32" : L"NTFS")));
}
wcscpy(params.volumeSpec, volumeSpec);
wcscpy(params.label, label);
params.fsType = fsType;
params.fsflags = fsflags;
params.allocationUnitSize = allocationUnitSize;
params.quick = quick;
params.force = force;
params.result = S_OK;
params.cancel = FALSE;
params.formatRoutine = FormatRoutine;
params.formatRoutineEx = FormatRoutineEx;
params.compressRoutine = CompressRoutine;
params.threadId = GetCurrentThreadId();
if (SetFormatParam(params.threadId, &params) != S_OK) {
delete [] params.label;
delete [] params.volumeSpec;
delete [] params.fsName;
return E_OUTOFMEMORY;
};
FormatVolume(&params);
WsbTraceOut(OLESTR("FormatPartition"), OLESTR("result = <%ls>"), WsbHrAsString(params.result));
return params.result;
}