mirror of
https://github.com/kanjitalk755/macemu.git
synced 2025-08-05 06:26:32 +00:00
Merge pull request #251 from rakslice/cd_eject_lock
Sort out the situation with CD ejection on Windows and real CD drives generally
This commit is contained in:
@@ -24,6 +24,10 @@
|
||||
|
||||
#include <winioctl.h>
|
||||
|
||||
#define DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
// Prototypes
|
||||
|
||||
extern "C" {
|
||||
@@ -128,12 +132,17 @@ BOOL PreventRemovalOfVolume(HANDLE hVolume, BOOL fPreventRemoval)
|
||||
|
||||
PMRBuffer.PreventMediaRemoval = fPreventRemoval;
|
||||
|
||||
return DeviceIoControl( hVolume,
|
||||
IOCTL_STORAGE_MEDIA_REMOVAL,
|
||||
BOOL ret = DeviceIoControl( hVolume,
|
||||
IOCTL_STORAGE_EJECTION_CONTROL,
|
||||
&PMRBuffer, sizeof(PREVENT_MEDIA_REMOVAL),
|
||||
NULL, 0,
|
||||
&dwBytesReturned,
|
||||
NULL);
|
||||
D(bug(" PreventRemoval IOCTL returned %d\n", ret));
|
||||
if (!ret) {
|
||||
D(bug(" failed, last error %d\n", GetLastError()));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
BOOL AutoEjectVolume( HANDLE hVolume, BOOL reload )
|
||||
|
@@ -60,12 +60,23 @@ struct file_handle {
|
||||
loff_t file_size; // Size of file data (only valid if is_file is true)
|
||||
cachetype cache;
|
||||
bool is_media_present;
|
||||
bool is_tray_locked;
|
||||
HANDLE storage_ejection_handle; // Handle used for storage ejection prevention
|
||||
|
||||
#if defined(BINCUE)
|
||||
bool is_bincue; // Flag: BIN CUE file
|
||||
void *bincue_fd;
|
||||
file_handle() {is_bincue = false;} // default bincue false
|
||||
#endif
|
||||
file_handle() {
|
||||
// Since our PreventRemovalOfVolume implementaion on Windows increments a lock counter,
|
||||
// let's have our own safeguard to prevent incrementing it more than once.
|
||||
is_tray_locked = false;
|
||||
storage_ejection_handle = NULL;
|
||||
#if defined(BINCUE)
|
||||
is_bincue = false; // default bincue false
|
||||
#endif
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Open file handles
|
||||
@@ -581,6 +592,10 @@ void Sys_close(void *arg)
|
||||
cache_final(&fh->cache);
|
||||
SysAllowRemoval((void *)fh);
|
||||
}
|
||||
if (fh->storage_ejection_handle != NULL) {
|
||||
CloseHandle(fh->storage_ejection_handle);
|
||||
fh->storage_ejection_handle = NULL;
|
||||
}
|
||||
if (fh->fh != NULL) {
|
||||
CloseHandle(fh->fh);
|
||||
fh->fh = NULL;
|
||||
@@ -694,6 +709,35 @@ loff_t SysGetFileSize(void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
static void PreventRemovalCommon(file_handle * fh, bool val) {
|
||||
D(bug("PreventRemovalCommon %p %d\n", fh, val));
|
||||
if (!fh) return;
|
||||
if (!fh->is_cdrom) return;
|
||||
if (!fh->name) return;
|
||||
D(bug(" seems ok to do\n"));
|
||||
|
||||
if (fh->storage_ejection_handle == NULL) {
|
||||
// we need a device handle with just FILE_READ_ATTRIBUTES
|
||||
TCHAR device_name[MAX_PATH];
|
||||
_sntprintf(device_name, lengthof(device_name), TEXT("\\\\.\\%c:"), fh->name[0]);
|
||||
|
||||
// Open device
|
||||
HANDLE h = CreateFile(
|
||||
device_name,
|
||||
FILE_READ_ATTRIBUTES,
|
||||
0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if (h == INVALID_HANDLE_VALUE) {
|
||||
D(bug(" failed to get suitable handle\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
fh->storage_ejection_handle = h;
|
||||
}
|
||||
|
||||
PreventRemovalOfVolume(fh->storage_ejection_handle, val);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Eject volume (if applicable)
|
||||
@@ -718,9 +762,9 @@ void SysEject(void *arg)
|
||||
// exactly ... need to find out
|
||||
// EjectVolume(toupper(*fh->name),false);
|
||||
|
||||
// Preventing is cumulative, try to make sure it's indeed released now
|
||||
for (int i = 0; i < 10; i++)
|
||||
PreventRemovalOfVolume(fh->fh, false);
|
||||
D(bug("SysEject disabling PreventRemoval\n"));
|
||||
PreventRemovalCommon(fh, false);
|
||||
fh->is_tray_locked = false;
|
||||
|
||||
if (!PrefsFindBool("nocdrom")) {
|
||||
DWORD dummy;
|
||||
@@ -819,12 +863,16 @@ bool SysIsDiskInserted(void *arg)
|
||||
|
||||
void SysPreventRemoval(void *arg)
|
||||
{
|
||||
D(bug("SysPreventRemoval %p\n", arg));
|
||||
file_handle *fh = (file_handle *)arg;
|
||||
if (!fh)
|
||||
return;
|
||||
|
||||
if (fh->is_cdrom && fh->fh)
|
||||
PreventRemovalOfVolume(fh->fh, true);
|
||||
if (fh->is_cdrom && fh->fh && !fh->is_tray_locked) {
|
||||
D(bug(" doing prevent removal\n"));
|
||||
PreventRemovalCommon(fh, true);
|
||||
fh->is_tray_locked = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -834,12 +882,16 @@ void SysPreventRemoval(void *arg)
|
||||
|
||||
void SysAllowRemoval(void *arg)
|
||||
{
|
||||
D(bug("SysAllowRemoval %p\n", arg));
|
||||
file_handle *fh = (file_handle *)arg;
|
||||
if (!fh)
|
||||
return;
|
||||
|
||||
if (fh->is_cdrom && fh->fh)
|
||||
PreventRemovalOfVolume(fh->fh, false);
|
||||
if (fh->is_cdrom && fh->fh) {
|
||||
D(bug(" doing allow removal\n"));
|
||||
PreventRemovalCommon(fh, false);
|
||||
fh->is_tray_locked = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@@ -351,6 +351,8 @@ void CDROMDrop(const char *path) {
|
||||
|
||||
void CDROMExit(void)
|
||||
{
|
||||
CDROMRemount(); // just to put the handles moved to the remount collection back so they get cleaned up
|
||||
|
||||
drive_vec::iterator info, end = drives.end();
|
||||
for (info = drives.begin(); info != end; ++info)
|
||||
info->close_fh();
|
||||
@@ -369,6 +371,7 @@ bool CDROMMountVolume(void *fh)
|
||||
++info;
|
||||
if (info != end) {
|
||||
if (SysIsDiskInserted(info->fh)) {
|
||||
D(bug("CDROMMountVolume doing SysPreventRemoval cdrom drive num %d\n", info->num));
|
||||
SysPreventRemoval(info->fh);
|
||||
WriteMacInt8(info->status + dsDiskInPlace, 1);
|
||||
read_toc(*info);
|
||||
@@ -538,6 +541,7 @@ int16 CDROMOpen(uint32 pb, uint32 dce)
|
||||
|
||||
// Disk in drive?
|
||||
if (SysIsDiskInserted(info->fh)) {
|
||||
D(bug("CDROMOpen doing SysPreventRemoval cdrom drive num %d\n", info->num));
|
||||
SysPreventRemoval(info->fh);
|
||||
WriteMacInt8(info->status + dsDiskInPlace, 1);
|
||||
read_toc(*info);
|
||||
@@ -670,12 +674,15 @@ int16 CDROMControl(uint32 pb, uint32 dce)
|
||||
case 7: // EjectTheDisc
|
||||
D(bug("CDROMControl EjectTheDisc\n"));
|
||||
if (ReadMacInt8(info->status + dsDiskInPlace) > 0) {
|
||||
if (info->drop) {
|
||||
if (info->drop || !SysIsFixedDisk(info->fh)) {
|
||||
SysAllowRemoval(info->fh);
|
||||
SysEject(info->fh);
|
||||
info->twok_offset = -1;
|
||||
info->close_fh();
|
||||
info->drop = false;
|
||||
if (info->drop) {
|
||||
info->close_fh();
|
||||
info->drop = false;
|
||||
info->fh = NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
remount_map.insert(std::make_pair(ReadMacInt16(pb + ioVRefNum), info->fh));
|
||||
@@ -683,9 +690,9 @@ int16 CDROMControl(uint32 pb, uint32 dce)
|
||||
D(bug("At least stop cd playback if it's some kind of CD %d,%d,%d\n",
|
||||
info->lead_out[0], info->lead_out[1], info->lead_out[2]));
|
||||
SysCDStop(info->fh, info->lead_out[0], info->lead_out[1], info->lead_out[2]);
|
||||
info->fh = NULL;
|
||||
}
|
||||
|
||||
info->fh = NULL;
|
||||
WriteMacInt8(info->status + dsDiskInPlace, 0);
|
||||
return noErr;
|
||||
} else {
|
||||
@@ -754,8 +761,10 @@ int16 CDROMControl(uint32 pb, uint32 dce)
|
||||
if (ReadMacInt8(info->status + dsDiskInPlace) > 0) {
|
||||
if (ReadMacInt16(pb + csParam) == 1)
|
||||
SysAllowRemoval(info->fh);
|
||||
else
|
||||
else {
|
||||
D(bug("SetUserEject call doing SysPreventRemoval cdrom drive num %d\n", info->num));
|
||||
SysPreventRemoval(info->fh);
|
||||
}
|
||||
return noErr;
|
||||
} else {
|
||||
return offLinErr;
|
||||
|
Reference in New Issue
Block a user