windows-nt/Source/XPSP1/NT/base/fs/utils/dfrg/uicommon.cpp
2020-09-26 16:20:57 +08:00

335 lines
8.9 KiB
C++

#include "stdafx.h"
#ifdef OFFLINEDK
extern "C"{
#include <stdio.h>
}
#endif
#ifdef BOOTIME
#include "Offline.h"
#else
#include "Windows.h"
#endif
#include <winioctl.h>
extern "C" {
#include "SysStruc.h"
}
#include "ErrMacro.h"
#include "DfrgCmn.h"
#include "DfrgRes.h"
#include "Alloc.h"
#define THIS_MODULE 'U'
#include "logfile.h"
//
// start of helpers for IsValidVolume functions below
//
/////////////////////////////////////////
// Is this a valid drive type?
// Check if we have a drive that is even in the ball park.
//
static BOOL IsValidDriveType(UINT uDriveType)
{
//sks bug #211782 take out CDROM and RAMDISK to allow for DVD-RAM drives
if (uDriveType == DRIVE_UNKNOWN ||
uDriveType == DRIVE_NO_ROOT_DIR ||
uDriveType == DRIVE_REMOTE
) {
return FALSE;
}
return TRUE;
}
/////////////////////////////////////////
// Get a handle to a volume
//
static HANDLE GetVolumeHandle(PTCHAR cVolume)
{
HANDLE hVolume = INVALID_HANDLE_VALUE;
// Get a handle to the volume
UINT uiErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
hVolume = CreateFile(cVolume,
0,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_NO_BUFFERING,
NULL);
SetErrorMode(uiErrorMode);
return hVolume;
}
/////////////////////////////////////////
// Is this volume valid (actual work routine)
//
// Note: volumeName is required to get volumeLabel and fileSystem
//
static BOOL IsValidVolumeCheck(HANDLE hVolume, // IN volume handle
UINT uDriveType, // IN drive type
PTCHAR volumeName, // IN volume name
PTCHAR volumeLabel, // OUT volume label
PTCHAR fileSystem) // OUT file system
{
require(hVolume != INVALID_HANDLE_VALUE && hVolume != NULL);
require(volumeName != NULL);
BOOL bReturn = FALSE; // assume not valid
HANDLE hFsDevInfo = NULL;
FILE_FS_DEVICE_INFORMATION * pFsDevInfo = NULL;
// clear return values
if (volumeLabel != NULL) {
_tcscpy(volumeLabel, TEXT(""));
}
if (fileSystem != NULL) {
_tcscpy(fileSystem, TEXT(""));
}
__try {
// read-only, network, etc. check
if (!AllocateMemory(sizeof(FILE_FS_DEVICE_INFORMATION) + MAX_PATH,
&hFsDevInfo, (void**) &pFsDevInfo)) {
EH(FALSE);
__leave;
}
IO_STATUS_BLOCK IoStatus = {0};
NTSTATUS Status = NtQueryVolumeInformationFile(hVolume,
&IoStatus,
pFsDevInfo,
sizeof(FILE_FS_DEVICE_INFORMATION) + 50,
FileFsDeviceInformation);
if (NT_SUCCESS(Status)) {
if (pFsDevInfo->Characteristics &
(FILE_READ_ONLY_DEVICE | FILE_WRITE_ONCE_MEDIA | FILE_REMOTE_DEVICE)) {
__leave;
}
}
else {
__leave;
}
// media check
if (uDriveType == DRIVE_REMOVABLE) {
DISK_GEOMETRY medias[20];
DWORD nummedias = 0;
DWORD numbytes;
if (DeviceIoControl(hVolume, IOCTL_STORAGE_GET_MEDIA_TYPES,
NULL, 0, medias, 20 * sizeof(DISK_GEOMETRY), &numbytes, NULL)) {
nummedias = numbytes / sizeof(DISK_GEOMETRY);
for (UINT i=0; i<nummedias; i++) {
switch (medias[i].MediaType) {
// these are OK
case F3_20Pt8_512: // 3.5", 20.8MB, 512 bytes/sector
case FixedMedia: // Fixed hard disk media
case F3_120M_512: // 3.5", 120M Floppy
case F3_128Mb_512: // 3.5" MO 128Mb 512 bytes/sector
case F3_230Mb_512: // 3.5" MO 230Mb 512 bytes/sector
break;
// but nothing else is
default:
__leave;
break;
}
}
}
else {
GetLastError(); // debug
// TODO: figure out why JAZ drives fail on the above call
// we should probably __leave here, but then JAZ drives are filtered out
// maybe we should EH so at least it will register albeit every second or two
// question: do or should every removable drive type report supported media?
// EH(FALSE);
// __leave;
}
}
// file system check
TCHAR tmpVolumeLabel[100];
TCHAR tmpFileSystem[20];
TCHAR tmpVolumeName[GUID_LENGTH];
_tcscpy(tmpVolumeName, volumeName);
if (volumeName[_tcslen(tmpVolumeName) - 1] != TEXT('\\')){
_tcscat(tmpVolumeName, TEXT("\\"));
}
BOOL isOk = GetVolumeInformation(tmpVolumeName,
tmpVolumeLabel,
100,
NULL,
NULL,
NULL,
tmpFileSystem,
20);
if (!isOk) {
__leave;
}
if (volumeLabel != NULL) {
_tcscpy(volumeLabel, tmpVolumeLabel);
}
if (fileSystem != NULL) {
_tcscpy(fileSystem, tmpFileSystem);
}
// Only NTFS, FAT or FAT32
if (_tcscmp(tmpFileSystem, TEXT("NTFS")) &&
_tcscmp(tmpFileSystem, TEXT("FAT")) &&
_tcscmp(tmpFileSystem, TEXT("FAT32"))) {
__leave; // if none of the above, bail
}
bReturn = TRUE; // all the checks "passed"
}
__finally {
if (hFsDevInfo) {
EH_ASSERT(GlobalUnlock(hFsDevInfo) == FALSE);
EH_ASSERT(GlobalFree(hFsDevInfo) == NULL);
}
}
return bReturn;
}
/////////////////////////////////////////
// Is this volume valid (drive letter only version)
//
BOOL IsValidVolume(TCHAR cDrive)
{
// Check if we have a drive that is even in the ball park.
// If so, then continue on and gather more data (mostly for removable drives)
TCHAR cRootPath[100];
_stprintf(cRootPath, TEXT("%c:\\"), cDrive);
UINT uDriveType = GetDriveType(cRootPath);
if (!IsValidDriveType(uDriveType)) {
return FALSE;
}
// Get a handle to the volume
TCHAR cVolume[MAX_PATH];
_stprintf(cVolume, TEXT("\\\\.\\%c:"), cDrive);
HANDLE hVolume = GetVolumeHandle(cVolume);
if (hVolume == INVALID_HANDLE_VALUE) {
return FALSE;
}
// check volume
BOOL bReturn = IsValidVolumeCheck(hVolume, uDriveType, cVolume, NULL, NULL);
CloseHandle(hVolume);
return bReturn;
}
/////////////////////////////////////////
// Is this volume valid (version 2)
//
// INPUT:
// volumeName
//
// OUTPUT:
// volumeLabel
// fileSystem
//
BOOL IsValidVolume(PTCHAR volumeName, PTCHAR volumeLabel, PTCHAR fileSystem)
{
BOOL bReturn = FALSE; // assume error
if(!volumeName) {
assert(0);
return FALSE;
}
// Check if we have a drive that is even in the ball park.
// If so, then continue on and gather more data (mostly for removable drives)
UINT uDriveType = GetDriveType(volumeName);
if (!IsValidDriveType(uDriveType)) {
return FALSE;
}
//sks 8/30/2000 fix for prefix bug #109657
TCHAR tmpVolumeName[GUID_LENGTH + 1];
_tcsncpy(tmpVolumeName, volumeName, GUID_LENGTH);
tmpVolumeName[GUID_LENGTH] = (TCHAR) NULL;
// strip off the trailing whack
if (tmpVolumeName[_tcslen(tmpVolumeName)-1] == TEXT('\\')){
tmpVolumeName[_tcslen(tmpVolumeName)-1] = (TCHAR) NULL;
}
// Get a handle to the volume
HANDLE hVolume = GetVolumeHandle(tmpVolumeName);
if (hVolume == INVALID_HANDLE_VALUE) {
return FALSE;
}
// check volume
bReturn = IsValidVolumeCheck(hVolume, uDriveType, volumeName, volumeLabel, fileSystem);
CloseHandle(hVolume);
return bReturn;
}
// is the file system supported?
BOOL IsVolumeWriteable(PTCHAR volumeName, DWORD* dLastError)
{
*dLastError = 0;
// create a temp file name
TCHAR cTempFile[MAX_PATH + 50];
if (0 == GetTempFileName(volumeName, L"DFRG", 0, cTempFile)) {
*dLastError = GetLastError();
return FALSE;
}
// get rid of the temp file
DeleteFile(cTempFile);
// true means that we can write to it
return TRUE;
}