mirror of
https://github.com/fadden/ciderpress.git
synced 2024-11-23 11:33:58 +00:00
d42b9c6dc0
The static analyzer was annoyed that the return value from calls to CString::LoadString() was being ignored. This adds a wrapper function that checks the value and logs a failure message if the string can't be found.
680 lines
24 KiB
C++
680 lines
24 KiB
C++
/*
|
|
* CiderPress
|
|
* Copyright (C) 2007 by faddenSoft, LLC. All Rights Reserved.
|
|
* See the file LICENSE for distribution terms.
|
|
*/
|
|
/*
|
|
* Allow the user to select a disk volume.
|
|
*/
|
|
#include "stdafx.h"
|
|
#include "OpenVolumeDialog.h"
|
|
#include "Main.h"
|
|
#include "../diskimg/Win32Extra.h" // need disk geometry calls
|
|
#include "../diskimg/ASPI.h"
|
|
|
|
|
|
BEGIN_MESSAGE_MAP(OpenVolumeDialog, CDialog)
|
|
ON_COMMAND(IDHELP, OnHelp)
|
|
//ON_NOTIFY(NM_CLICK, IDC_VOLUME_LIST, OnListClick)
|
|
ON_NOTIFY(LVN_ITEMCHANGED, IDC_VOLUME_LIST, OnListChange)
|
|
ON_NOTIFY(NM_DBLCLK, IDC_VOLUME_LIST, OnListDblClick)
|
|
ON_CBN_SELCHANGE(IDC_VOLUME_FILTER, OnVolumeFilterSelChange)
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
BOOL OpenVolumeDialog::OnInitDialog(void)
|
|
{
|
|
/*
|
|
* Sets up the list of drives.
|
|
*/
|
|
|
|
CDialog::OnInitDialog(); // do any DDX init stuff
|
|
const Preferences* pPreferences = GET_PREFERENCES();
|
|
long defaultFilter;
|
|
|
|
/* highlight/select entire line, not just filename */
|
|
CListCtrl* pListView = (CListCtrl*) GetDlgItem(IDC_VOLUME_LIST);
|
|
ASSERT(pListView != NULL);
|
|
|
|
ListView_SetExtendedListViewStyleEx(pListView->m_hWnd,
|
|
LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
|
|
|
|
/* disable the OK button until they click on something */
|
|
CButton* pButton = (CButton*) GetDlgItem(IDOK);
|
|
ASSERT(pButton != NULL);
|
|
|
|
pButton->EnableWindow(FALSE);
|
|
|
|
/* if the read-only state is fixed, don't let them change it */
|
|
if (!fAllowROChange) {
|
|
CButton* pButton;
|
|
pButton = (CButton*) GetDlgItem(IDC_OPENVOL_READONLY);
|
|
ASSERT(pButton != NULL);
|
|
pButton->EnableWindow(FALSE);
|
|
}
|
|
|
|
/* prep the combo box */
|
|
CComboBox* pCombo = (CComboBox*) GetDlgItem(IDC_VOLUME_FILTER);
|
|
ASSERT(pCombo != NULL);
|
|
defaultFilter = pPreferences->GetPrefLong(kPrVolumeFilter);
|
|
if (defaultFilter >= kBoth && defaultFilter <= kPhysical)
|
|
pCombo->SetCurSel(defaultFilter);
|
|
else {
|
|
LOGI("GLITCH: invalid defaultFilter in prefs (%d)", defaultFilter);
|
|
pCombo->SetCurSel(kLogical);
|
|
}
|
|
|
|
/* two columns */
|
|
CRect rect;
|
|
pListView->GetClientRect(&rect);
|
|
int width;
|
|
|
|
width = pListView->GetStringWidth(L"XXVolume or Device NameXXmmmmmm");
|
|
pListView->InsertColumn(0, L"Volume or Device Name", LVCFMT_LEFT, width);
|
|
pListView->InsertColumn(1, L"Remarks", LVCFMT_LEFT,
|
|
rect.Width() - width - ::GetSystemMetrics(SM_CXVSCROLL));
|
|
|
|
// Load the drive list.
|
|
LoadDriveList();
|
|
|
|
// Kluge the physical drive 0 stuff.
|
|
DiskImg::SetAllowWritePhys0(GET_PREFERENCES()->GetPrefBool(kPrOpenVolumePhys0));
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void OpenVolumeDialog::DoDataExchange(CDataExchange* pDX)
|
|
{
|
|
DDX_Check(pDX, IDC_OPENVOL_READONLY, fReadOnly);
|
|
LOGI("DoDataExchange: fReadOnly==%d", fReadOnly);
|
|
}
|
|
|
|
void OpenVolumeDialog::LoadDriveList(void)
|
|
{
|
|
CWaitCursor waitc;
|
|
CComboBox* pCombo;
|
|
CListCtrl* pListView;
|
|
int itemIndex = 0;
|
|
int filterSelection;
|
|
|
|
pListView = (CListCtrl*) GetDlgItem(IDC_VOLUME_LIST);
|
|
ASSERT(pListView != NULL);
|
|
pCombo = (CComboBox*) GetDlgItem(IDC_VOLUME_FILTER);
|
|
ASSERT(pCombo != NULL);
|
|
|
|
pListView->DeleteAllItems();
|
|
|
|
/*
|
|
* Load the logical and physical drive sets as needed. Do the "physical"
|
|
* set first because it's usually what we want.
|
|
*/
|
|
filterSelection = pCombo->GetCurSel();
|
|
if (filterSelection == kPhysical || filterSelection == kBoth)
|
|
LoadPhysicalDriveList(pListView, &itemIndex);
|
|
if (filterSelection == kLogical || filterSelection == kBoth)
|
|
LoadLogicalDriveList(pListView, &itemIndex);
|
|
}
|
|
|
|
bool OpenVolumeDialog::LoadLogicalDriveList(CListCtrl* pListView, int* pItemIndex)
|
|
{
|
|
DWORD drivesAvailable;
|
|
bool isWin9x = IsWin9x();
|
|
int itemIndex = *pItemIndex;
|
|
|
|
ASSERT(pListView != NULL);
|
|
|
|
drivesAvailable = GetLogicalDrives();
|
|
if (drivesAvailable == 0) {
|
|
LOGI("GetLogicalDrives failed, err=0x%08lx", drivesAvailable);
|
|
return false;
|
|
}
|
|
LOGI("GetLogicalDrives returned 0x%08lx", drivesAvailable);
|
|
|
|
// SetErrorMode(SEM_FAILCRITICALERRORS)
|
|
|
|
/* run through the list, from A-Z */
|
|
int i;
|
|
for (i = 0; i < kMaxLogicalDrives; i++) {
|
|
fVolumeInfo[i].driveType = DRIVE_UNKNOWN;
|
|
|
|
if ((drivesAvailable >> i) & 0x01) {
|
|
WCHAR driveName[] = L"_:\\";
|
|
driveName[0] = 'A' + i;
|
|
|
|
unsigned int driveType;
|
|
const WCHAR* driveTypeComment = NULL;
|
|
BOOL result;
|
|
|
|
driveType = fVolumeInfo[i].driveType = GetDriveType(driveName);
|
|
switch (driveType) {
|
|
case DRIVE_UNKNOWN:
|
|
// The drive type cannot be determined.
|
|
break;
|
|
case DRIVE_NO_ROOT_DIR:
|
|
// The root path is invalid. For example, no volume is mounted at the path.
|
|
break;
|
|
case DRIVE_REMOVABLE:
|
|
// The disk can be removed from the drive.
|
|
driveTypeComment = L"Removable";
|
|
break;
|
|
case DRIVE_FIXED:
|
|
// The disk cannot be removed from the drive.
|
|
driveTypeComment = L"Local Disk";
|
|
break;
|
|
case DRIVE_REMOTE:
|
|
// The drive is a remote (network) drive.
|
|
driveTypeComment = L"Network";
|
|
break;
|
|
case DRIVE_CDROM:
|
|
// The drive is a CD-ROM drive.
|
|
driveTypeComment = L"CD-ROM";
|
|
break;
|
|
case DRIVE_RAMDISK:
|
|
// The drive is a RAM disk.
|
|
break;
|
|
default:
|
|
LOGI("UNKNOWN DRIVE TYPE %d", driveType);
|
|
break;
|
|
}
|
|
|
|
if (driveType == DRIVE_CDROM && !DiskImgLib::Global::GetHasSPTI()) {
|
|
/* use "physical" device via ASPI instead */
|
|
LOGI("Not including CD-ROM '%ls' in logical drive list",
|
|
driveName);
|
|
continue;
|
|
}
|
|
|
|
WCHAR volNameBuf[256];
|
|
WCHAR fsNameBuf[64];
|
|
const WCHAR* errorComment = NULL;
|
|
//DWORD fsFlags;
|
|
CString entryName, entryRemarks;
|
|
|
|
result = ::GetVolumeInformation(driveName, volNameBuf,
|
|
NELEM(volNameBuf), NULL, NULL, NULL /*&fsFlags*/, fsNameBuf,
|
|
NELEM(fsNameBuf));
|
|
if (result == FALSE) {
|
|
DWORD err = GetLastError();
|
|
if (err == ERROR_UNRECOGNIZED_VOLUME) {
|
|
// Win2K: media exists but format not recognized
|
|
errorComment = L"Non-Windows format";
|
|
} else if (err == ERROR_NOT_READY) {
|
|
// Win2K: device exists but no media loaded
|
|
if (isWin9x) {
|
|
LOGI("Not showing drive '%ls': not ready",
|
|
driveName);
|
|
continue; // safer not to show it
|
|
} else
|
|
errorComment = L"Not ready";
|
|
} else if (err == ERROR_PATH_NOT_FOUND /*Win2K*/ ||
|
|
err == ERROR_INVALID_DATA /*Win98*/)
|
|
{
|
|
// Win2K/Win98: device letter not in use
|
|
LOGI("GetVolumeInformation '%ls': nothing there",
|
|
driveName);
|
|
continue;
|
|
} else if (err == ERROR_INVALID_PARAMETER) {
|
|
// Win2K: device is already open
|
|
//LOGI("GetVolumeInformation '%ls': currently open??",
|
|
// driveName);
|
|
errorComment = L"(currently open?)";
|
|
//continue;
|
|
} else if (err == ERROR_ACCESS_DENIED) {
|
|
// Win2K: disk is open no-read-sharing elsewhere
|
|
errorComment = L"(already open read-write)";
|
|
} else if (err == ERROR_GEN_FAILURE) {
|
|
// Win98: floppy format not recognzied
|
|
// --> we don't want to access ProDOS floppies via A: in
|
|
// Win98, so we skip it here
|
|
LOGI("GetVolumeInformation '%ls': general failure",
|
|
driveName);
|
|
continue;
|
|
} else if (err == ERROR_INVALID_FUNCTION) {
|
|
// Win2K: CD-ROM with HFS
|
|
if (driveType == DRIVE_CDROM)
|
|
errorComment = L"Non-Windows format";
|
|
else
|
|
errorComment = L"(invalid disc?)";
|
|
} else {
|
|
LOGI("GetVolumeInformation '%ls' failed: %ld",
|
|
driveName, GetLastError());
|
|
continue;
|
|
}
|
|
ASSERT(errorComment != NULL);
|
|
|
|
entryName.Format(L"(%c:)", 'A' + i);
|
|
if (driveTypeComment != NULL)
|
|
entryRemarks.Format(L"%ls - %ls", driveTypeComment,
|
|
errorComment);
|
|
else
|
|
entryRemarks.Format(L"%ls", errorComment);
|
|
} else {
|
|
entryName.Format(L"%ls (%c:)", volNameBuf, 'A' + i);
|
|
if (driveTypeComment != NULL)
|
|
entryRemarks.Format(L"%ls", driveTypeComment);
|
|
else
|
|
entryRemarks = "";
|
|
}
|
|
|
|
pListView->InsertItem(itemIndex, entryName);
|
|
pListView->SetItemText(itemIndex, 1, entryRemarks);
|
|
pListView->SetItemData(itemIndex, (DWORD) i + 'A');
|
|
//LOGI("%%%% added logical %d", itemIndex);
|
|
itemIndex++;
|
|
} else {
|
|
LOGI(" (drive %c not available)", i + 'A');
|
|
}
|
|
}
|
|
|
|
*pItemIndex = itemIndex;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool OpenVolumeDialog::LoadPhysicalDriveList(CListCtrl* pListView, int* pItemIndex)
|
|
{
|
|
/*
|
|
* I don't see a clever way to do this in Win2K except to open the first 8
|
|
* or so devices and see what happens.
|
|
*
|
|
* Win9x isn't much better, though you can be reasonably confident that there
|
|
* are at most 4 floppy drives and 4 hard drives.
|
|
*
|
|
* TODO: check again for a better way
|
|
*/
|
|
|
|
bool isWin9x = IsWin9x();
|
|
int itemIndex = *pItemIndex;
|
|
int i;
|
|
|
|
if (isWin9x) {
|
|
// fairly arbitrary choices
|
|
const int kMaxFloppies = 4;
|
|
const int kMaxHardDrives = 8;
|
|
|
|
for (i = 0; i < kMaxFloppies; i++) {
|
|
CString driveName, remark;
|
|
bool result;
|
|
|
|
result = HasPhysicalDriveWin9x(i, &remark);
|
|
if (result) {
|
|
driveName.Format(L"Floppy disk %d", i);
|
|
pListView->InsertItem(itemIndex, driveName);
|
|
pListView->SetItemText(itemIndex, 1, remark);
|
|
pListView->SetItemData(itemIndex, (DWORD) i);
|
|
//LOGI("%%%% added floppy %d", itemIndex);
|
|
itemIndex++;
|
|
}
|
|
}
|
|
for (i = 0; i < kMaxHardDrives; i++) {
|
|
CString driveName, remark;
|
|
bool result;
|
|
|
|
result = HasPhysicalDriveWin9x(i + 128, &remark);
|
|
if (result) {
|
|
driveName.Format(L"Hard drive %d", i);
|
|
pListView->InsertItem(itemIndex, driveName);
|
|
pListView->SetItemText(itemIndex, 1, remark);
|
|
pListView->SetItemData(itemIndex, (DWORD) i + 128);
|
|
//LOGI("%%%% added HD %d", itemIndex);
|
|
itemIndex++;
|
|
}
|
|
}
|
|
} else {
|
|
for (i = 0; i < kMaxPhysicalDrives; i++) {
|
|
CString driveName, remark;
|
|
bool result;
|
|
|
|
result = HasPhysicalDriveWin2K(i + 128, &remark);
|
|
if (result) {
|
|
driveName.Format(L"Physical disk %d", i);
|
|
pListView->InsertItem(itemIndex, driveName);
|
|
pListView->SetItemText(itemIndex, 1, remark);
|
|
pListView->SetItemData(itemIndex, (DWORD) i + 128); // HD volume
|
|
itemIndex++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (DiskImgLib::Global::GetHasASPI()) {
|
|
LOGI("IGNORING ASPI");
|
|
#if 0 // can we remove this?
|
|
DIError dierr;
|
|
DiskImgLib::ASPI* pASPI = DiskImgLib::Global::GetASPI();
|
|
ASPIDevice* deviceArray = NULL;
|
|
int numDevices;
|
|
|
|
dierr = pASPI->GetAccessibleDevices(
|
|
ASPI::kDevMaskCDROM | ASPI::kDevMaskHardDrive,
|
|
&deviceArray, &numDevices);
|
|
if (dierr == kDIErrNone) {
|
|
LOGI("Adding %d ASPI CD-ROM devices", numDevices);
|
|
for (i = 0; i < numDevices; i++) {
|
|
CString driveName, remark;
|
|
CString addr, vendor, product;
|
|
DWORD aspiAddr;
|
|
|
|
addr.Format("ASPI %d:%d:%d",
|
|
deviceArray[i].GetAdapter(),
|
|
deviceArray[i].GetTarget(),
|
|
deviceArray[i].GetLun());
|
|
vendor = deviceArray[i].GetVendorID();
|
|
vendor.TrimRight();
|
|
product = deviceArray[i].GetProductID();
|
|
product.TrimRight();
|
|
|
|
driveName.Format("%s %s", vendor, product);
|
|
if (deviceArray[i].GetDeviceType() == ASPIDevice::kTypeCDROM)
|
|
remark = "CD-ROM";
|
|
else if (deviceArray[i].GetDeviceType() == ASPIDevice::kTypeDASD)
|
|
remark = "Direct-access device";
|
|
if (!deviceArray[i].GetDeviceReady())
|
|
remark += " - Not ready";
|
|
|
|
aspiAddr = (DWORD) 0xaa << 24 |
|
|
(DWORD) deviceArray[i].GetAdapter() << 16 |
|
|
(DWORD) deviceArray[i].GetTarget() << 8 |
|
|
(DWORD) deviceArray[i].GetLun();
|
|
//LOGI("ADDR for '%s' is 0x%08lx",
|
|
// (const char*) driveName, aspiAddr);
|
|
|
|
pListView->InsertItem(itemIndex, driveName);
|
|
pListView->SetItemText(itemIndex, 1, remark);
|
|
pListView->SetItemData(itemIndex, aspiAddr);
|
|
itemIndex++;
|
|
}
|
|
}
|
|
|
|
delete[] deviceArray;
|
|
#endif
|
|
}
|
|
|
|
*pItemIndex = itemIndex;
|
|
return true;
|
|
}
|
|
|
|
bool OpenVolumeDialog::HasPhysicalDriveWin9x(int unit, CString* pRemark)
|
|
{
|
|
HANDLE handle = NULL;
|
|
const int VWIN32_DIOC_DOS_INT13 = 4;
|
|
const int CARRY_FLAG = 1;
|
|
BOOL result;
|
|
typedef struct _DIOC_REGISTERS {
|
|
DWORD reg_EBX;
|
|
DWORD reg_EDX;
|
|
DWORD reg_ECX;
|
|
DWORD reg_EAX;
|
|
DWORD reg_EDI;
|
|
DWORD reg_ESI;
|
|
DWORD reg_Flags;
|
|
} DIOC_REGISTERS, *PDIOC_REGISTERS;
|
|
DIOC_REGISTERS reg = {0};
|
|
DWORD lastError, cb;
|
|
unsigned char buf[512];
|
|
|
|
if (unit > 4)
|
|
return false; // floppy drives only
|
|
|
|
handle = CreateFile(L"\\\\.\\vwin32", 0, 0, NULL,
|
|
OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, NULL);
|
|
if (handle == INVALID_HANDLE_VALUE) {
|
|
LOGI(" Unable to open vwin32: %ld", ::GetLastError());
|
|
return false;
|
|
}
|
|
|
|
#if 0 // didn't do what I wanted
|
|
reg.reg_EAX = MAKEWORD(0, 0x00); // func 0x00 == reset controller
|
|
reg.reg_EDX = MAKEWORD(unit, 0); // specify driver
|
|
result = DeviceIoControl(handle, VWIN32_DIOC_DOS_INT13, ®,
|
|
sizeof(reg), ®, sizeof(reg), &cb, 0);
|
|
LOGI(" DriveReset(drive=0x%02x) result=%d carry=%d",
|
|
unit, result, reg.reg_Flags & CARRY_FLAG);
|
|
#endif
|
|
|
|
reg.reg_EAX = MAKEWORD(1, 0x02); // read 1 sector
|
|
reg.reg_EBX = (DWORD) buf;
|
|
reg.reg_ECX = MAKEWORD(1, 0); // sector 0 (+1), cylinder 0
|
|
reg.reg_EDX = MAKEWORD(unit, 0); // head
|
|
|
|
result = DeviceIoControl(handle, VWIN32_DIOC_DOS_INT13, ®,
|
|
sizeof(reg) /*bytes*/, ®, sizeof(reg) /*bytes*/, &cb, 0);
|
|
lastError = GetLastError();
|
|
::CloseHandle(handle);
|
|
|
|
if (result == 0 || (reg.reg_Flags & CARRY_FLAG)) {
|
|
int ah = HIBYTE(reg.reg_EAX);
|
|
LOGI(" DevIoCtrl(unit=%02xh) failed: result=%d lastErr=%d Flags=0x%08lx",
|
|
unit, result, lastError, reg.reg_Flags);
|
|
LOGI(" AH=%d (EAX=0x%08lx) byte=0x%02x", ah, reg.reg_EAX, buf[0]);
|
|
if (ah != 1) {
|
|
// failure code 1 means "invalid parameter", drive doesn't exist
|
|
// mine returns 128, "timeout", when no disk is in the drive
|
|
*pRemark = "Not ready";
|
|
return true;
|
|
} else
|
|
return false;
|
|
}
|
|
|
|
*pRemark = "Removable";
|
|
|
|
return true;
|
|
}
|
|
|
|
bool OpenVolumeDialog::HasPhysicalDriveWin2K(int unit, CString* pRemark)
|
|
{
|
|
HANDLE hDevice; // handle to the drive to be examined
|
|
DISK_GEOMETRY dg; // disk drive geometry structure
|
|
DISK_GEOMETRY_EX dge; // extended geometry request buffer
|
|
BOOL result; // results flag
|
|
DWORD junk; // discard results
|
|
LONGLONG diskSize; // size of the drive, in bytes
|
|
CString fileName;
|
|
DWORD err;
|
|
|
|
/*
|
|
* See if the drive is there.
|
|
*/
|
|
ASSERT(unit >= 128 && unit < 160); // arbitrary max
|
|
fileName.Format(L"\\\\.\\PhysicalDrive%d", unit - 128);
|
|
|
|
hDevice = ::CreateFile(fileName, // drive to open
|
|
0, // no access to the drive
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE, // share mode
|
|
NULL, // default security attributes
|
|
OPEN_EXISTING, // disposition
|
|
0, // file attributes
|
|
NULL); // do not copy file attributes
|
|
|
|
if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
|
|
return false;
|
|
|
|
/*
|
|
* Try to get the drive geometry. First try with the fancy WinXP call,
|
|
* then fall back to the Win2K call if it doesn't exist.
|
|
*/
|
|
result = ::DeviceIoControl(hDevice,
|
|
IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,
|
|
NULL, 0, // input buffer
|
|
&dge, sizeof(dge), // output buffer + size in bytes
|
|
&junk, // # bytes returned
|
|
(LPOVERLAPPED) NULL); // synchronous I/O
|
|
if (result) {
|
|
diskSize = dge.DiskSize.QuadPart;
|
|
LOGI(" EX results for device %02xh", unit);
|
|
LOGI(" Disk size = %I64d (bytes) = %I64d (MB)",
|
|
diskSize, diskSize / (1024*1024));
|
|
if (diskSize > 1024*1024*1024)
|
|
pRemark->Format(L"Size is %.2fGB",
|
|
(double) diskSize / (1024.0 * 1024.0 * 1024.0));
|
|
else
|
|
pRemark->Format(L"Size is %.2fMB",
|
|
(double) diskSize / (1024.0 * 1024.0));
|
|
} else {
|
|
// Win2K shows ERROR_INVALID_FUNCTION or ERROR_NOT_SUPPORTED
|
|
LOGI("IOCTL_DISK_GET_DRIVE_GEOMETRY_EX failed, error was %ld",
|
|
GetLastError());
|
|
result = ::DeviceIoControl(hDevice, // device to be queried
|
|
IOCTL_DISK_GET_DRIVE_GEOMETRY, // operation to perform
|
|
NULL, 0, // no input buffer
|
|
&dg, sizeof(dg), // output buffer + size in bytes
|
|
&junk, // # bytes returned
|
|
(LPOVERLAPPED) NULL); // synchronous I/O
|
|
|
|
if (result) {
|
|
LOGI(" Results for device %02xh", unit);
|
|
LOGI(" Cylinders = %I64d", dg.Cylinders.QuadPart);
|
|
LOGI(" Tracks per cylinder = %ld", (ULONG) dg.TracksPerCylinder);
|
|
LOGI(" Sectors per track = %ld", (ULONG) dg.SectorsPerTrack);
|
|
LOGI(" Bytes per sector = %ld", (ULONG) dg.BytesPerSector);
|
|
|
|
diskSize = dg.Cylinders.QuadPart * (ULONG)dg.TracksPerCylinder *
|
|
(ULONG)dg.SectorsPerTrack * (ULONG)dg.BytesPerSector;
|
|
LOGI("Disk size = %I64d (bytes) = %I64d (MB)", diskSize,
|
|
diskSize / (1024 * 1024));
|
|
if (diskSize > 1024*1024*1024)
|
|
pRemark->Format(L"Size is %.2fGB",
|
|
(double) diskSize / (1024.0 * 1024.0 * 1024.0));
|
|
else
|
|
pRemark->Format(L"Size is %.2fMB",
|
|
(double) diskSize / (1024.0 * 1024.0));
|
|
} else {
|
|
err = GetLastError();
|
|
}
|
|
}
|
|
|
|
::CloseHandle(hDevice);
|
|
|
|
if (!result) {
|
|
LOGI("DeviceIoControl(IOCTL_DISK_GET_DRIVE_GEOMETRY) failed (err=%ld)",
|
|
err);
|
|
*pRemark = "Not ready";
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void OpenVolumeDialog::OnListChange(NMHDR*, LRESULT* pResult)
|
|
{
|
|
CListCtrl* pListView = (CListCtrl*) GetDlgItem(IDC_VOLUME_LIST);
|
|
CButton* pButton = (CButton*) GetDlgItem(IDOK);
|
|
pButton->EnableWindow(pListView->GetSelectedCount() != 0);
|
|
//LOGI("ENABLE %d", pListView->GetSelectedCount() != 0);
|
|
|
|
*pResult = 0;
|
|
}
|
|
|
|
void OpenVolumeDialog::OnListDblClick(NMHDR* pNotifyStruct, LRESULT* pResult)
|
|
{
|
|
CListCtrl* pListView = (CListCtrl*) GetDlgItem(IDC_VOLUME_LIST);
|
|
CButton* pButton = (CButton*) GetDlgItem(IDOK);
|
|
|
|
if (pListView->GetSelectedCount() != 0) {
|
|
pButton->EnableWindow();
|
|
OnOK();
|
|
}
|
|
|
|
*pResult = 0;
|
|
}
|
|
|
|
void OpenVolumeDialog::OnVolumeFilterSelChange(void)
|
|
{
|
|
CComboBox* pCombo = (CComboBox*) GetDlgItem(IDC_VOLUME_FILTER);
|
|
ASSERT(pCombo != NULL);
|
|
LOGI("+++ SELECTION IS NOW %d", pCombo->GetCurSel());
|
|
LoadDriveList();
|
|
}
|
|
|
|
void OpenVolumeDialog::OnOK(void)
|
|
{
|
|
/*
|
|
* Figure out the (zero-based) drive letter.
|
|
*/
|
|
CListCtrl* pListView = (CListCtrl*) GetDlgItem(IDC_VOLUME_LIST);
|
|
ASSERT(pListView != NULL);
|
|
|
|
if (pListView->GetSelectedCount() != 1) {
|
|
CString msg, failed;
|
|
CheckedLoadString(&failed, IDS_FAILED);
|
|
CheckedLoadString(&msg, IDS_VOLUME_SELECT_ONE);
|
|
MessageBox(msg, failed, MB_OK);
|
|
return;
|
|
}
|
|
|
|
POSITION posn;
|
|
posn = pListView->GetFirstSelectedItemPosition();
|
|
if (posn == NULL) {
|
|
ASSERT(false);
|
|
return;
|
|
}
|
|
int num = pListView->GetNextSelectedItem(posn);
|
|
DWORD driveID = pListView->GetItemData(num);
|
|
UINT formatID = 0;
|
|
|
|
if (HIBYTE(HIWORD(driveID)) == 0xaa) {
|
|
// TODO: remove this?
|
|
fChosenDrive.Format(L"%hs%d:%d:%d\\",
|
|
DiskImgLib::kASPIDev,
|
|
LOBYTE(HIWORD(driveID)),
|
|
HIBYTE(LOWORD(driveID)),
|
|
LOBYTE(LOWORD(driveID)));
|
|
//ForceReadOnly(true);
|
|
} else if (driveID >= 'A' && driveID <= 'Z') {
|
|
/*
|
|
* Do we want to let them do this? We show some logical drives
|
|
* that we don't want them to actually use.
|
|
*/
|
|
switch (fVolumeInfo[driveID-'A'].driveType) {
|
|
case DRIVE_REMOVABLE:
|
|
case DRIVE_FIXED:
|
|
break; // allow
|
|
case DRIVE_CDROM: //formatID = IDS_VOLUME_NO_CDROM;
|
|
ForceReadOnly(true);
|
|
break;
|
|
case DRIVE_REMOTE: formatID = IDS_VOLUME_NO_REMOTE;
|
|
break;
|
|
case DRIVE_RAMDISK: formatID = IDS_VOLUME_NO_RAMDISK;
|
|
break;
|
|
case DRIVE_UNKNOWN:
|
|
case DRIVE_NO_ROOT_DIR:
|
|
default: formatID = IDS_VOLUME_NO_GENERIC;
|
|
break;
|
|
}
|
|
|
|
fChosenDrive.Format(L"%c:\\", driveID);
|
|
} else if ((driveID >= 0 && driveID < 4) ||
|
|
(driveID >= 0x80 && driveID < 0x88))
|
|
{
|
|
fChosenDrive.Format(L"%02x:\\", driveID);
|
|
} else {
|
|
ASSERT(false);
|
|
return;
|
|
}
|
|
|
|
if (formatID != 0) {
|
|
CString msg, notAllowed;
|
|
|
|
CheckedLoadString(¬Allowed, IDS_NOT_ALLOWED);
|
|
CheckedLoadString(&msg, formatID);
|
|
MessageBox(msg, notAllowed, MB_OK);
|
|
} else {
|
|
Preferences* pPreferences = GET_PREFERENCES_WR();
|
|
CComboBox* pCombo = (CComboBox*) GetDlgItem(IDC_VOLUME_FILTER);
|
|
pPreferences->SetPrefLong(kPrVolumeFilter, pCombo->GetCurSel());
|
|
LOGI("SETTING PREF TO %ld", pCombo->GetCurSel());
|
|
|
|
CDialog::OnOK();
|
|
}
|
|
}
|
|
|
|
void OpenVolumeDialog::ForceReadOnly(bool readOnly) const
|
|
{
|
|
CButton* pButton = (CButton*) GetDlgItem(IDC_OPENVOL_READONLY);
|
|
ASSERT(pButton != NULL);
|
|
|
|
if (readOnly)
|
|
pButton->SetCheck(BST_CHECKED);
|
|
else
|
|
pButton->SetCheck(BST_UNCHECKED);
|
|
LOGW("FORCED READ ONLY %d", readOnly);
|
|
}
|