From 3ea5a913a9050d492e82a80cfdcc6b6e03679b73 Mon Sep 17 00:00:00 2001 From: Peter Veenstra Date: Thu, 22 Jun 2006 13:15:07 +0000 Subject: [PATCH] Add rewriten form of patch "[ 1498334 ] CD Images unmounting" created by Kronutz Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@2658 --- include/dos_system.h | 4 +- src/dos/dos_files.cpp | 4 +- src/dos/dos_mscdex.cpp | 205 +++++++++++++++++++++++++------------- src/dos/dos_programs.cpp | 57 ++++++++--- src/dos/drive_fat.cpp | 7 +- src/dos/drive_iso.cpp | 15 ++- src/dos/drive_local.cpp | 20 +++- src/dos/drive_virtual.cpp | 7 +- src/dos/drives.h | 9 +- 9 files changed, 239 insertions(+), 89 deletions(-) diff --git a/include/dos_system.h b/include/dos_system.h index b49a0508..0e1311e1 100644 --- a/include/dos_system.h +++ b/include/dos_system.h @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: dos_system.h,v 1.35 2006-04-23 14:20:57 c2woody Exp $ */ +/* $Id: dos_system.h,v 1.36 2006-06-22 13:15:07 qbix79 Exp $ */ #ifndef DOSBOX_DOS_SYSTEM_H #define DOSBOX_DOS_SYSTEM_H @@ -229,6 +229,8 @@ public: virtual void EmptyCache(void) { dirCache.EmptyCache(); }; virtual bool isRemote(void)=0; virtual bool isRemovable(void)=0; + virtual Bits UnMount(void)=0; + char * GetInfo(void); char curdir[DOS_PATHLENGTH]; char info[256]; diff --git a/src/dos/dos_files.cpp b/src/dos/dos_files.cpp index 0eedde22..9d6d350a 100644 --- a/src/dos/dos_files.cpp +++ b/src/dos/dos_files.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: dos_files.cpp,v 1.74 2006-05-28 09:40:42 qbix79 Exp $ */ +/* $Id: dos_files.cpp,v 1.75 2006-06-22 13:15:07 qbix79 Exp $ */ #include #include @@ -535,7 +535,7 @@ bool DOS_SetFileAttr(char * name,Bit16u attr) Bit16u attrTemp; char fullname[DOS_PATHLENGTH];Bit8u drive; if (!DOS_MakeName(name,fullname,&drive)) return false; - if (strcmp(Drives[drive]->GetInfo(),"CDRom.")==0 || strcmp(Drives[drive]->GetInfo(),"isoDrive")==0) { + if (strncmp(Drives[drive]->GetInfo(),"CDRom ",6)==0 || strncmp(Drives[drive]->GetInfo(),"isoDrive ",9)==0) { DOS_SetError(DOSERR_ACCESS_DENIED); return false; } diff --git a/src/dos/dos_mscdex.cpp b/src/dos/dos_mscdex.cpp index 0bf8fffa..01aa8fdf 100644 --- a/src/dos/dos_mscdex.cpp +++ b/src/dos/dos_mscdex.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: dos_mscdex.cpp,v 1.42 2006-04-21 08:35:31 qbix79 Exp $ */ +/* $Id: dos_mscdex.cpp,v 1.43 2006-06-22 13:15:07 qbix79 Exp $ */ #include #include @@ -107,6 +107,7 @@ public: bool GetSubChannelData (Bit8u subUnit, Bit8u& attr, Bit8u& track, Bit8u &index, TMSF& rel, TMSF& abs); + int RemoveDrive (Bit16u _drive); int AddDrive (Bit16u _drive, char* physicalPath, Bit8u& subUnit); void GetDrives (PhysPt data); void GetDriverInfo (PhysPt data); @@ -197,10 +198,113 @@ Bit8u CMscdex::GetSubUnit(Bit16u _drive) return 0xff; }; +int CMscdex::RemoveDrive(Bit16u _drive) +{ + Bit16u idx = MSCDEX_MAX_DRIVES; + for (Bit16u i=0; i=MSCDEX_MAX_DRIVES) return 4; + if (GetNumDrives()) { + // Error check, driveletter have to be in a row + if (dinfo[0].drive-1!=_drive && dinfo[numDrives-1].drive+1!=_drive) + return 1; + } + // Set return type to ok + int result = 0; + // Get Mounttype and init needed cdrom interface + switch (CDROM_GetMountType(physicalPath,forceCD)) { + case 0x00: { + LOG(LOG_MISC,LOG_NORMAL)("MSCDEX: Mounting physical cdrom: %s" ,physicalPath); +#if defined (WIN32) + // Check OS + OSVERSIONINFO osi; + osi.dwOSVersionInfoSize = sizeof(osi); + GetVersionEx(&osi); + if ((osi.dwPlatformId==VER_PLATFORM_WIN32_NT) && (osi.dwMajorVersion>4)) { + // only WIN NT/200/XP + if (useCdromInterface==CDROM_USE_IOCTL) { + cdrom[numDrives] = new CDROM_Interface_Ioctl(); + LOG(LOG_MISC,LOG_NORMAL)("MSCDEX: IOCTL Interface."); + break; + } + } + if (useCdromInterface==CDROM_USE_ASPI) { + // all Wins - ASPI + cdrom[numDrives] = new CDROM_Interface_Aspi(); + LOG(LOG_MISC,LOG_NORMAL)("MSCDEX: ASPI Interface."); + break; + } +#endif +#if defined (LINUX) || defined(OS2) + // Always use IOCTL in Linux or OS/2 + cdrom[numDrives] = new CDROM_Interface_Ioctl(); + LOG(LOG_MISC,LOG_NORMAL)("MSCDEX: IOCTL Interface."); +#else + // Default case windows and other oses + cdrom[numDrives] = new CDROM_Interface_SDL(); + LOG(LOG_MISC,LOG_NORMAL)("MSCDEX: SDL Interface."); +#endif + } break; + case 0x01: // iso cdrom interface + LOG(LOG_MISC,LOG_NORMAL)("MSCDEX: Mounting iso file as cdrom: %s", physicalPath); + cdrom[numDrives] = new CDROM_Interface_Image((Bit8u)numDrives); + break; + case 0x02: // fake cdrom interface (directories) + cdrom[numDrives] = new CDROM_Interface_Fake; + LOG(LOG_MISC,LOG_NORMAL)("MSCDEX: Mounting directory as cdrom: %s",physicalPath); + LOG(LOG_MISC,LOG_NORMAL)("MSCDEX: You wont have full MSCDEX support !"); + result = 5; + break; + default : // weird result + return 6; + }; + + if (!cdrom[numDrives]->SetDevice(physicalPath,forceCD)) { +// delete cdrom[numDrives] ; mount seems to delete it + return 3; + } + + + if (rootDriverHeaderSeg==0) { Bit16u driverSize = sizeof(DOS_DeviceHeader::sDeviceHeader) + 10; // 10 = Bytes for 3 callbacks @@ -246,75 +350,36 @@ int CMscdex::AddDrive(Bit16u _drive, char* physicalPath, Bit8u& subUnit) rootDriverHeaderSeg = seg; - } else { - // Error check, driveletter have to be in a row - if (dinfo[numDrives-1].drive+1!=_drive) return 1; - }; - - if (GetNumDrives()+14)) { - // only WIN NT/200/XP - if (useCdromInterface==CDROM_USE_IOCTL) { - cdrom[numDrives] = new CDROM_Interface_Ioctl(); - LOG(LOG_MISC,LOG_NORMAL)("MSCDEX: IOCTL Interface."); - break; - } - } - if (useCdromInterface==CDROM_USE_ASPI) { - // all Wins - ASPI - cdrom[numDrives] = new CDROM_Interface_Aspi(); - LOG(LOG_MISC,LOG_NORMAL)("MSCDEX: ASPI Interface."); - break; - } - #endif - #if defined (LINUX) || defined(OS2) - // Always use IOCTL in Linux or OS/2 -// if (useCdromInterface==CDROM_USE_IOCTL) { - cdrom[numDrives] = new CDROM_Interface_Ioctl(); - LOG(LOG_MISC,LOG_NORMAL)("MSCDEX: IOCTL Interface."); - break; -// } - #endif - cdrom[numDrives] = new CDROM_Interface_SDL(); - LOG(LOG_MISC,LOG_NORMAL)("MSCDEX: SDL Interface."); - } break; - case 0x01 : // iso cdrom interface - LOG(LOG_MISC,LOG_NORMAL)("MSCDEX: Mounting iso file as cdrom: %s", physicalPath); - cdrom[numDrives] = new CDROM_Interface_Image((Bit8u)numDrives); - break; - case 0x02 : // fake cdrom interface (directories) - cdrom[numDrives] = new CDROM_Interface_Fake; - LOG(LOG_MISC,LOG_NORMAL)("MSCDEX: Mounting directory as cdrom: %s",physicalPath); - LOG(LOG_MISC,LOG_NORMAL)("MSCDEX: You wont have full MSCDEX support !"); - result = 5; - break; - default : // weird result - return 6; - }; - if (!cdrom[numDrives]->SetDevice(physicalPath,forceCD)) return 3; - subUnit = (Bit8u)numDrives; - // Set drive + } else if (GetNumDrives() == 0) { DOS_DeviceHeader devHeader(PhysMake(rootDriverHeaderSeg,0)); - devHeader.SetNumSubUnits(devHeader.GetNumSubUnits()+1); + Bit16u off = sizeof(DOS_DeviceHeader::sDeviceHeader); + devHeader.SetDriveLetter(_drive+1); + devHeader.SetStrategy(off); + devHeader.SetInterrupt(off+5); + } + + subUnit = (Bit8u)numDrives; + // Set drive + DOS_DeviceHeader devHeader(PhysMake(rootDriverHeaderSeg,0)); + devHeader.SetNumSubUnits(devHeader.GetNumSubUnits()+1); + + if (dinfo[0].drive-1==_drive) { + CDROM_Interface *_cdrom = cdrom[numDrives]; + for (Bit16u i=GetNumDrives(); i>0; i--) { + dinfo[i] = dinfo[i-1]; + cdrom[i] = cdrom[i-1]; + } + cdrom[0] = _cdrom; + dinfo[0].drive = (Bit8u)_drive; + dinfo[0].physDrive = toupper(physicalPath[0]); + } else { dinfo[numDrives].drive = (Bit8u)_drive; dinfo[numDrives].physDrive = toupper(physicalPath[0]); - numDrives++; - // stop audio - StopAudio(subUnit); - return result; } - return 4; + numDrives++; + // stop audio + StopAudio(subUnit); + return result; }; PhysPt CMscdex::GetDefaultBuffer(void) @@ -1134,6 +1199,12 @@ int MSCDEX_AddDrive(char driveLetter, const char* physicalPath, Bit8u& subUnit) return result; }; +int MSCDEX_RemoveDrive(char driveLetter) +{ + if(!mscdex) return 0; + return mscdex->RemoveDrive(driveLetter-'A'); +}; + bool MSCDEX_GetVolumeName(Bit8u subUnit, char* name) { return mscdex->GetVolumeName(subUnit,name); diff --git a/src/dos/dos_programs.cpp b/src/dos/dos_programs.cpp index f0eef1a0..6a43bf0b 100644 --- a/src/dos/dos_programs.cpp +++ b/src/dos/dos_programs.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: dos_programs.cpp,v 1.61 2006-06-01 06:44:22 qbix79 Exp $ */ +/* $Id: dos_programs.cpp,v 1.62 2006-06-22 13:15:07 qbix79 Exp $ */ #include #include @@ -51,23 +51,26 @@ public: DOS_Drive * newdrive;char drive; std::string label; std::string umount; + /* Check for unmounting */ if (cmd->FindString("-u",umount,false)) { umount[0] = toupper(umount[0]); int i_drive = umount[0]-'A'; if(i_drive < DOS_DRIVES && Drives[i_drive]) { - try { /* Check if virtualdrive */ - if( dynamic_cast(Drives[i_drive]) == 0 ) throw 0; - } - catch(...) { + switch (Drives[i_drive]->UnMount()) { + case 0: + Drives[i_drive] = 0; + if(i_drive == DOS_GetDefaultDrive()) + DOS_SetDrive(toupper('Z') - 'A'); + WriteOut(MSG_Get("PROGRAM_MOUNT_UMOUNT_SUCCES"),umount[0]); + break; + case 1: WriteOut(MSG_Get("PROGRAM_MOUNT_UMOUNT_NO_VIRTUAL")); - return; + break; + case 2: + WriteOut(MSG_Get("MSCDEX_ERROR_MULTIPLE_CDROMS")); + break; } - if(i_drive == DOS_GetDefaultDrive()) - DOS_SetDrive(toupper('Z') - 'A'); - delete Drives[i_drive]; - Drives[i_drive] = 0; - WriteOut(MSG_Get("PROGRAM_MOUNT_UMOUNT_SUCCES"),umount[0]); } else { WriteOut(MSG_Get("PROGRAM_MOUNT_UMOUNT_NOT_MOUNTED"),umount[0]); } @@ -229,6 +232,10 @@ public: case 5 : WriteOut(MSG_Get("MSCDEX_LIMITED_SUPPORT")); break; default : WriteOut(MSG_Get("MSCDEX_UNKNOWN_ERROR")); break; }; + if (error && error!=5) { + delete newdrive; + return; + } } else { /* Give a warning when mount c:\ or the / */ #if defined (WIN32) || defined(OS2) @@ -657,6 +664,32 @@ public: Bit32u imagesize; char drive; std::string label; + std::string umount; + /* Check for unmounting */ + if (cmd->FindString("-u",umount,false)) { + umount[0] = toupper(umount[0]); + int i_drive = umount[0]-'A'; + if (i_drive < DOS_DRIVES && Drives[i_drive]) { + switch (Drives[i_drive]->UnMount()) { + case 0: + Drives[i_drive] = 0; + if (i_drive == DOS_GetDefaultDrive()) + DOS_SetDrive(toupper('Z') - 'A'); + WriteOut(MSG_Get("PROGRAM_MOUNT_UMOUNT_SUCCES"),umount[0]); + break; + case 1: + WriteOut(MSG_Get("PROGRAM_MOUNT_UMOUNT_NO_VIRTUAL")); + break; + case 2: + WriteOut(MSG_Get("MSCDEX_ERROR_MULTIPLE_CDROMS")); + break; + } + } else { + WriteOut(MSG_Get("PROGRAM_MOUNT_UMOUNT_NOT_MOUNTED"),umount[0]); + } + return; + } + std::string type="hdd"; std::string fstype="fat"; @@ -777,7 +810,7 @@ public: case 5 : WriteOut(MSG_Get("MSCDEX_LIMITED_SUPPORT")); break; default : WriteOut(MSG_Get("MSCDEX_UNKNOWN_ERROR")); break; }; - if (error) { + if (error && error!=5) { delete newdrive; return; } diff --git a/src/dos/drive_fat.cpp b/src/dos/drive_fat.cpp index 2183a2fc..c7921c0f 100644 --- a/src/dos/drive_fat.cpp +++ b/src/dos/drive_fat.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: drive_fat.cpp,v 1.15 2006-05-31 14:22:00 qbix79 Exp $ */ +/* $Id: drive_fat.cpp,v 1.16 2006-06-22 13:15:07 qbix79 Exp $ */ #include #include @@ -704,6 +704,11 @@ Bit32u fatDrive::getFirstFreeClust(void) { bool fatDrive::isRemote(void) { return false; } bool fatDrive::isRemovable(void) { return false; } +Bits fatDrive::UnMount(void) { + delete this; + return 0; +} + Bit8u fatDrive::GetMediaByte(void) { return loadedDisk->GetBiosType(); } bool fatDrive::FileCreate(DOS_File **file, char *name, Bit16u attributes) { diff --git a/src/dos/drive_iso.cpp b/src/dos/drive_iso.cpp index d0d42e55..8fde0b10 100644 --- a/src/dos/drive_iso.cpp +++ b/src/dos/drive_iso.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: drive_iso.cpp,v 1.13 2006-04-23 14:20:58 c2woody Exp $ */ +/* $Id: drive_iso.cpp,v 1.14 2006-06-22 13:15:07 qbix79 Exp $ */ #include #include @@ -138,6 +138,7 @@ Bit16u isoFile::GetInformation(void) return 0x40; // read-only drive } +int MSCDEX_RemoveDrive(char driveLetter); int MSCDEX_AddDrive(char driveLetter, const char* physicalPath, Bit8u& subUnit); bool MSCDEX_HasMediaChanged(Bit8u subUnit); bool MSCDEX_GetVolumeName(Bit8u subUnit, char* name); @@ -153,7 +154,9 @@ isoDrive::isoDrive(char driveLetter, const char *fileName, Bit8u mediaid, int &e if (!error) { if (loadImage()) { - strcpy(info, "isoDrive"); + strcpy(info, "isoDrive "); + strcat(info, fileName); + this->driveLetter = driveLetter; this->mediaid = mediaid; char buffer[32] = { 0 }; if (!MSCDEX_GetVolumeName(subUnit, buffer)) strcpy(buffer, ""); @@ -373,6 +376,14 @@ bool isoDrive::isRemovable(void) return true; } +Bits isoDrive::UnMount(void) { + if(MSCDEX_RemoveDrive(driveLetter)) { + delete this; + return 0; + } + return 2; +} + int isoDrive::GetDirIterator(const isoDirEntry* de) { int dirIterator = nextFreeDirIterator; diff --git a/src/dos/drive_local.cpp b/src/dos/drive_local.cpp index 4683b245..699745c6 100644 --- a/src/dos/drive_local.cpp +++ b/src/dos/drive_local.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: drive_local.cpp,v 1.68 2006-05-14 19:57:24 qbix79 Exp $ */ +/* $Id: drive_local.cpp,v 1.69 2006-06-22 13:15:07 qbix79 Exp $ */ #include #include @@ -411,6 +411,11 @@ bool localDrive::isRemovable(void) { return false; } +Bits localDrive::UnMount(void) { + delete this; + return 0; +} + localDrive::localDrive(const char * startdir,Bit16u _bytes_sector,Bit8u _sectors_cluster,Bit16u _total_clusters,Bit16u _free_clusters,Bit8u _mediaid) { strcpy(basedir,startdir); sprintf(info,"local directory %s",startdir); @@ -535,6 +540,7 @@ bool localFile::UpdateDateTimeFromHost(void) { // CDROM DRIVE // ******************************************** +int MSCDEX_RemoveDrive(char driveLetter); int MSCDEX_AddDrive(char driveLetter, const char* physicalPath, Bit8u& subUnit); bool MSCDEX_HasMediaChanged(Bit8u subUnit); bool MSCDEX_GetVolumeName(Bit8u subUnit, char* name); @@ -545,7 +551,9 @@ cdromDrive::cdromDrive(const char driveLetter, const char * startdir,Bit16u _byt { // Init mscdex error = MSCDEX_AddDrive(driveLetter,startdir,subUnit); - strcpy(info,"CDRom."); + strcpy(info, "CDRom "); + strcat(info, startdir); + this->driveLetter = driveLetter; // Get Volume Label char name[32]; if (MSCDEX_GetVolumeName(subUnit,name)) dirCache.SetLabel(name); @@ -632,3 +640,11 @@ bool cdromDrive::isRemote(void) { bool cdromDrive::isRemovable(void) { return true; } + +Bits cdromDrive::UnMount(void) { + if(MSCDEX_RemoveDrive(driveLetter)) { + delete this; + return 0; + } + return 2; +} diff --git a/src/dos/drive_virtual.cpp b/src/dos/drive_virtual.cpp index 19c52d46..7ac1d0e2 100644 --- a/src/dos/drive_virtual.cpp +++ b/src/dos/drive_virtual.cpp @@ -176,7 +176,7 @@ bool Virtual_Drive::TestDir(char * dir) { } bool Virtual_Drive::FileStat(const char* name, FileStat_Block * const stat_block){ - VFILE_Block * cur_file=first_file; + VFILE_Block * cur_file=first_file; while (cur_file) { if (strcasecmp(name,cur_file->name)==0) { stat_block->attr=DOS_ATTR_ARCHIVE; @@ -267,3 +267,8 @@ bool Virtual_Drive::isRemote(void) { bool Virtual_Drive::isRemovable(void) { return false; } + +Bits Virtual_Drive::UnMount(void) { + return 1; +} + diff --git a/src/dos/drives.h b/src/dos/drives.h index 30503d1e..e7c1707d 100644 --- a/src/dos/drives.h +++ b/src/dos/drives.h @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: drives.h,v 1.32 2006-04-17 10:45:32 qbix79 Exp $ */ +/* $Id: drives.h,v 1.33 2006-06-22 13:15:07 qbix79 Exp $ */ #ifndef _DRIVES_H__ #define _DRIVES_H__ @@ -50,6 +50,7 @@ public: virtual Bit8u GetMediaByte(void); virtual bool isRemote(void); virtual bool isRemovable(void); + virtual Bits UnMount(void); private: char basedir[CROSS_LEN]; friend void DOS_Shell::CMD_SUBST(char* args); @@ -142,6 +143,7 @@ public: virtual Bit8u GetMediaByte(void); virtual bool isRemote(void); virtual bool isRemovable(void); + virtual Bits UnMount(void); public: Bit32u getAbsoluteSectFromBytePos(Bit32u startClustNum, Bit32u bytePos); Bit32u getSectorSize(void); @@ -204,8 +206,10 @@ public: virtual void SetDir(const char* path); virtual bool isRemote(void); virtual bool isRemovable(void); + virtual Bits UnMount(void); private: Bit8u subUnit; + char driveLetter; }; #ifdef _MSC_VER @@ -304,6 +308,7 @@ public: virtual void EmptyCache(void){} virtual bool isRemote(void); virtual bool isRemovable(void); + virtual Bits UnMount(void); bool readSector(Bit8u *buffer, Bit32u sector); virtual char const* GetLabel(void) {return discLabel;}; private: @@ -335,6 +340,7 @@ private: isoDirEntry rootEntry; Bit8u mediaid; Bit8u subUnit; + char driveLetter; char discLabel[32]; }; @@ -360,6 +366,7 @@ public: void EmptyCache(void){} bool isRemote(void); virtual bool isRemovable(void); + virtual Bits UnMount(void); private: VFILE_Block * search_file; };