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.
377 lines
8.4 KiB
377 lines
8.4 KiB
/*++
|
|
|
|
Copyright (c) 1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
format.cpp
|
|
|
|
Abstract:
|
|
|
|
Routines to format volumes, using file-system information passed
|
|
in. Uses undocumented fmifs calls.
|
|
|
|
|
|
Authors:
|
|
|
|
Steve DeVos (Veritas) (v-stevde) 15-May-1998
|
|
Guhan Suriyanarayanan (guhans) 21-Aug-1999
|
|
|
|
Environment:
|
|
|
|
User-mode only.
|
|
|
|
Revision History:
|
|
|
|
15-May-1998 v-stevde Initial creation
|
|
21-Aug-1999 guhans Cleaned up and re-wrote this module.
|
|
|
|
--*/
|
|
|
|
#include "stdafx.h"
|
|
#include <winioctl.h>
|
|
#include "fmifs.h"
|
|
#include "asr_fmt.h"
|
|
#include "asr_dlg.h"
|
|
|
|
BOOL g_bFormatInProgress = FALSE;
|
|
BOOL g_bFormatSuccessful = FALSE;
|
|
INT g_iFormatPercentComplete = 0;
|
|
|
|
HINSTANCE g_hIfsDll = NULL;
|
|
|
|
INT FormatVolumeThread(PASRFMT_VOLUME_INFO pVolume);
|
|
|
|
PFMIFS_FORMATEX_ROUTINE g_FormatRoutineEx = NULL;
|
|
|
|
|
|
BOOL
|
|
FormatInitialise() {
|
|
//
|
|
// Loadlib if needed
|
|
//
|
|
if (!g_hIfsDll) {
|
|
g_hIfsDll = LoadLibrary(L"fmifs.dll");
|
|
if (!g_hIfsDll) {
|
|
//
|
|
// FMIFS not available
|
|
//
|
|
return FALSE;
|
|
}
|
|
|
|
g_FormatRoutineEx = (PFMIFS_FORMATEX_ROUTINE)GetProcAddress(g_hIfsDll, "FormatEx");
|
|
if (!g_FormatRoutineEx) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
IsFsTypeOkay(
|
|
IN PASRFMT_VOLUME_INFO pVolume,
|
|
OUT PBOOL pIsLabelIntact
|
|
)
|
|
{
|
|
WCHAR currentFSName[ASRFMT_CCH_FS_NAME];
|
|
WCHAR szVolumeGuid[ASRFMT_CCH_VOLUME_GUID];
|
|
WCHAR currentLabel[ASRFMT_CCH_VOLUME_LABEL];
|
|
|
|
DWORD cchGuid = 0;
|
|
BOOL fsOkay = TRUE,
|
|
result = TRUE;
|
|
|
|
ASSERT(pIsLabelIntact);
|
|
|
|
ZeroMemory(currentFSName, sizeof(WCHAR) * ASRFMT_CCH_FS_NAME);
|
|
*pIsLabelIntact = TRUE;
|
|
|
|
if (wcslen(pVolume->szGuid) >= ASRFMT_CCH_VOLUME_GUID) {
|
|
return TRUE; // something's wrong with this GUID
|
|
}
|
|
|
|
if ((wcslen(pVolume->szFsName) <= 0)) {
|
|
return TRUE; // no check for RAW volumes
|
|
}
|
|
|
|
//
|
|
// We don't want the "please insert floppy in drive A" messages ...
|
|
//
|
|
SetErrorMode(SEM_FAILCRITICALERRORS);
|
|
|
|
//
|
|
// GetVolumeInformation needs the volume guid in the dos-name-space, while the
|
|
// the sif file has the volume guid in the nt-name-space. Convert
|
|
// the name by changing the \??\ at the beginning to \\?\, and adding
|
|
// a back-slash at the end.
|
|
//
|
|
cchGuid = wcslen(pVolume->szGuid);
|
|
wcsncpy(szVolumeGuid, pVolume->szGuid, cchGuid);
|
|
szVolumeGuid[1] = L'\\';
|
|
szVolumeGuid[cchGuid] = L'\\'; // Trailing back-slash
|
|
szVolumeGuid[cchGuid+1] = L'\0';
|
|
|
|
fsOkay = TRUE;
|
|
//
|
|
// Call GetVolumeInfo to see if the FS is the same
|
|
//
|
|
result = GetVolumeInformation(szVolumeGuid,
|
|
currentLabel, // lpVolumeNameBuffer
|
|
ASRFMT_CCH_VOLUME_LABEL, // nVolumeNameSize
|
|
NULL, // lpVolumeSerialNumber
|
|
NULL, // lpMaximumComponentLength
|
|
NULL, // lpFileSystemFlags
|
|
currentFSName,
|
|
ASRFMT_CCH_FS_NAME
|
|
);
|
|
|
|
if ((!result) ||
|
|
wcscmp(currentFSName, pVolume->szFsName)
|
|
) {
|
|
fsOkay = FALSE;
|
|
*pIsLabelIntact = FALSE;
|
|
}
|
|
|
|
if (wcscmp(currentLabel, pVolume->szLabel)) {
|
|
*pIsLabelIntact = FALSE;
|
|
}
|
|
|
|
|
|
/* if (fsOkay) {
|
|
//
|
|
//
|
|
// Call FindFirst in root to see if drive is readable.
|
|
// guhans: If drive is empty but formatted, this will still
|
|
// say fsOkay = FALSE;
|
|
//
|
|
hFindData = FindFirstFile(szPath, &win32FindData);
|
|
|
|
if (!hFindData || (INVALID_HANDLE_VALUE == hFindData)) {
|
|
fsOkay = FALSE;
|
|
}
|
|
}
|
|
*/
|
|
|
|
return fsOkay;
|
|
|
|
}
|
|
|
|
|
|
BOOL
|
|
IsVolumeIntact(
|
|
IN PASRFMT_VOLUME_INFO pVolume
|
|
){
|
|
|
|
|
|
//
|
|
// Call autochk to see if the FS is intact
|
|
//
|
|
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
///
|
|
// Asynchronous function to launch the format routine.
|
|
//
|
|
BOOL
|
|
FormatVolume(
|
|
IN PASRFMT_VOLUME_INFO pVolume
|
|
)
|
|
{
|
|
HANDLE hThread = NULL;
|
|
|
|
//
|
|
// Set the global flags
|
|
//
|
|
g_bFormatInProgress = TRUE;
|
|
g_bFormatSuccessful = TRUE;
|
|
g_iFormatPercentComplete = 0;
|
|
|
|
//
|
|
// Loadlib if needed
|
|
//
|
|
if (!g_hIfsDll && !FormatInitialise()) {
|
|
g_bFormatSuccessful = FALSE;
|
|
g_bFormatInProgress = FALSE;
|
|
return FALSE;
|
|
}
|
|
|
|
hThread = CreateThread(
|
|
NULL,
|
|
0,
|
|
(LPTHREAD_START_ROUTINE) FormatVolumeThread,
|
|
pVolume,
|
|
0,
|
|
NULL
|
|
);
|
|
if (!hThread || (INVALID_HANDLE_VALUE == hThread)) {
|
|
g_bFormatSuccessful = FALSE;
|
|
g_bFormatInProgress = FALSE;
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
FormatCleanup() {
|
|
|
|
if (g_hIfsDll) {
|
|
FreeLibrary(g_hIfsDll);
|
|
g_hIfsDll = NULL;
|
|
g_FormatRoutineEx = NULL;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
FmIfsCallback(
|
|
IN FMIFS_PACKET_TYPE PacketType,
|
|
IN DWORD PacketLength,
|
|
IN PVOID PacketData
|
|
)
|
|
{
|
|
|
|
switch (PacketType) {
|
|
case FmIfsPercentCompleted:
|
|
g_iFormatPercentComplete = ((PFMIFS_PERCENT_COMPLETE_INFORMATION)PacketData)->PercentCompleted ;
|
|
break;
|
|
|
|
case FmIfsFormattingDestination:
|
|
case FmIfsInsertDisk:
|
|
case FmIfsFormatReport:
|
|
case FmIfsHiddenStatus:
|
|
default:
|
|
break;
|
|
|
|
case FmIfsFinished:
|
|
g_bFormatSuccessful = g_bFormatSuccessful &&
|
|
((PFMIFS_FINISHED_INFORMATION) PacketData)->Success;
|
|
g_iFormatPercentComplete = 101;
|
|
g_bFormatInProgress = FALSE;
|
|
break;
|
|
|
|
case FmIfsIncompatibleFileSystem:
|
|
case FmIfsIncompatibleMedia:
|
|
case FmIfsAccessDenied:
|
|
case FmIfsMediaWriteProtected:
|
|
case FmIfsCantLock:
|
|
case FmIfsBadLabel:
|
|
case FmIfsCantQuickFormat:
|
|
case FmIfsIoError:
|
|
case FmIfsVolumeTooSmall:
|
|
case FmIfsVolumeTooBig:
|
|
case FmIfsClusterSizeTooSmall:
|
|
case FmIfsClusterSizeTooBig:
|
|
g_bFormatSuccessful = FALSE;
|
|
break;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
INT FormatVolumeThread(PASRFMT_VOLUME_INFO pVolume)
|
|
{
|
|
WCHAR szPath[ASRFMT_CCH_DEVICE_PATH + 1];
|
|
|
|
swprintf(szPath, TEXT("\\\\?%s"), pVolume->szGuid+3);
|
|
|
|
(g_FormatRoutineEx)(szPath,
|
|
FmMediaUnknown,
|
|
pVolume->szFsName,
|
|
pVolume->szLabel,
|
|
#if 0
|
|
TRUE, // Quick Format for testing
|
|
#else
|
|
g_bQuickFormat,
|
|
#endif
|
|
pVolume->dwClusterSize,
|
|
(FMIFS_CALLBACK) &FmIfsCallback
|
|
);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
VOID
|
|
MountFileSystem(
|
|
IN PASRFMT_VOLUME_INFO pVolume
|
|
)
|
|
/*++
|
|
|
|
(based on code in base\fs\utils\hsm\wsb\wsbfmt.cpp)
|
|
|
|
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:
|
|
|
|
|
|
Return Value:
|
|
|
|
none
|
|
|
|
--*/
|
|
{
|
|
WCHAR szPath[ASRFMT_CCH_DEVICE_PATH + 1];
|
|
HANDLE handle = NULL;
|
|
WIN32_FIND_DATA win32FindData;
|
|
|
|
if (!pVolume) {
|
|
ASSERT(0 && L"pVolume is NULL");
|
|
return;
|
|
}
|
|
|
|
if (!memcmp(pVolume->szDosPath, ASRFMT_WSZ_DOS_DEVICES_PREFIX, ASRFMT_CB_DOS_DEVICES_PREFIX)) {
|
|
swprintf(szPath, L"\\\\?\\%ws", pVolume->szDosPath + wcslen(ASRFMT_WSZ_DOS_DEVICES_PREFIX));
|
|
}
|
|
else {
|
|
swprintf(szPath, L"\\\\%ws", pVolume->szDosPath + 2);
|
|
}
|
|
handle = CreateFile(
|
|
szPath,
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
0,
|
|
OPEN_EXISTING,
|
|
0,
|
|
0
|
|
);
|
|
if ((handle) && (INVALID_HANDLE_VALUE != handle)) {
|
|
CloseHandle(handle);
|
|
}
|
|
|
|
//
|
|
// Try to find the first file, this will make sure that
|
|
// the file system is mounted
|
|
//
|
|
if (!memcmp(pVolume->szDosPath, ASRFMT_WSZ_DOS_DEVICES_PREFIX, ASRFMT_CB_DOS_DEVICES_PREFIX)) {
|
|
swprintf(szPath, L"\\\\?\\%ws\\*", pVolume->szDosPath + wcslen(ASRFMT_WSZ_DOS_DEVICES_PREFIX));
|
|
}
|
|
else {
|
|
swprintf(szPath, L"\\\\%ws\\*", pVolume->szDosPath + 2);
|
|
}
|
|
|
|
handle = FindFirstFile(szPath, &win32FindData);
|
|
if ((handle) && (INVALID_HANDLE_VALUE != handle)) {
|
|
FindClose(handle);
|
|
}
|
|
|
|
}
|