|
|
#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; }
|