From 7787631c6ee37a489732c95cb0864422e3a3bdd1 Mon Sep 17 00:00:00 2001 From: pixel Date: Sun, 12 Oct 2003 05:15:00 +0000 Subject: AT LAST!!! Windows 2k/XP CD reading works using raw ioctls!!!! HURRAY!!!!!!!! --- MSVC/Tools/Tools.vcproj | 12 ++++ MSVC/Tools/master.mak | 9 +-- PE/nmakefile | 2 +- PE/pepatch.cpp | 7 +++ Xenogears/main_dump.cpp | 2 +- cd-tool.cpp | 2 +- includes/cdabstract.h | 40 ++++++++++++- includes/cdreader.h | 11 ++-- lib/cdabstract.cpp | 147 ++++++++++++++++++++++++++++++++++++++++++++++-- lib/cdreader.cpp | 56 ++++++++++++++++++ 10 files changed, 270 insertions(+), 18 deletions(-) diff --git a/MSVC/Tools/Tools.vcproj b/MSVC/Tools/Tools.vcproj index 2e2174b..a8c93ac 100644 --- a/MSVC/Tools/Tools.vcproj +++ b/MSVC/Tools/Tools.vcproj @@ -106,6 +106,9 @@ + + @@ -127,6 +130,15 @@ + + + + + + diff --git a/MSVC/Tools/master.mak b/MSVC/Tools/master.mak index 82a7f16..11ee305 100644 --- a/MSVC/Tools/master.mak +++ b/MSVC/Tools/master.mak @@ -48,9 +48,9 @@ _XSD=xsd.exe #define our basic link line for managed code !IFDEF DEBUG -_LINK=link.exe /INCREMENTAL /NOLOGO /DEBUG /SUBSYSTEM:CONSOLE /MACHINE:I386 /NODEFAULTLIB:LIBC +_LINK=link.exe /INCREMENTAL /NOLOGO /DEBUG /MACHINE:I386 /NODEFAULTLIB:LIBC USER32.LIB !ELSE -_LINK=link.exe /INCREMENTAL /NOLOGO /SUBSYSTEM:CONSOLE /MACHINE:I386 /NODEFAULTLIB:LIBCD +_LINK=link.exe /INCREMENTAL /NOLOGO /MACHINE:I386 /NODEFAULTLIB:LIBCD USER32.LIB !ENDIF #this is used for compiling C# samples @@ -134,8 +134,9 @@ _RMDIR=deltree /y .cpp.exe: if not exist $(_OUTDIR) md $(_OUTDIR) $(_CL) $(_CDFLAGS) $*.cpp - if not exist $*.res $(_LINK) $(_LFLAGS) $(_LIBS) $*.obj - if exist $*.res $(_LINK) $(_LFLAGS) $(_LIBS) $*.obj $*.res + if not exist $*.res $(_LINK) /SUBSYSTEM:CONSOLE $(_LFLAGS) $(_LIBS) $*.obj + if exist $*.res $(_LINK) /SUBSYSTEM:CONSOLE $(_LFLAGS) $(_LIBS) $*.obj $*.res + if exist $*.paq copy /b $*.exe+$*.paq $*.exe .lex.c: if not exist $(_OUTDIR) md $(_OUTDIR) diff --git a/PE/nmakefile b/PE/nmakefile index bafe2fe..158bcf9 100644 --- a/PE/nmakefile +++ b/PE/nmakefile @@ -9,7 +9,7 @@ _LIBS = "..\MSVC\Baltisot - generic\Release\Baltisot - generic.lib" "..\MSVC\PSX #------------------------------------------------------------------ -TARGETS = reinsert.res extract.exe extract-rooms.exe extract-various.exe reinsert.exe compil.c compil.exe compilall.exe +TARGETS = reinsert.res pepatch.res extract.exe extract-rooms.exe extract-various.exe reinsert.exe compil.c compil.exe compilall.exe pepatch.exe all : $(TARGETS) diff --git a/PE/pepatch.cpp b/PE/pepatch.cpp index e69de29..be67faf 100644 --- a/PE/pepatch.cpp +++ b/PE/pepatch.cpp @@ -0,0 +1,7 @@ +#include + +CODE_BEGINS +virtual int startup() throw (GeneralException) { + return 0; +} +CODE_ENDS diff --git a/Xenogears/main_dump.cpp b/Xenogears/main_dump.cpp index 65b7466..1610ec1 100644 --- a/Xenogears/main_dump.cpp +++ b/Xenogears/main_dump.cpp @@ -99,7 +99,7 @@ virtual int startup() throw (GeneralException) iso_filename = argv[2]; printm(M_STATUS, "Begin processing iso file.\n"); - f_iso = open_iso(iso_filename); + f_iso = cdabstract::open_cd(iso_filename); if (check_iso()) { printm(M_ERROR, "Invalid iso file for " + title + "\n"); diff --git a/cd-tool.cpp b/cd-tool.cpp index e748aec..d5d766b 100644 --- a/cd-tool.cpp +++ b/cd-tool.cpp @@ -113,7 +113,7 @@ virtual int startup() throw (GeneralException) { exit(-1); } - iso_r = open_iso(iso_name); + iso_r = cdabstract::open_cd(iso_name); cdutil = new cdutils(iso_r); diff --git a/includes/cdabstract.h b/includes/cdabstract.h index 66aa909..60061d4 100644 --- a/includes/cdabstract.h +++ b/includes/cdabstract.h @@ -1,8 +1,44 @@ #ifndef __CD_ABSTRACT_H__ #define __CD_ABSTRACT_H__ -#include "Handle.h" +#if defined (_MSC_VER) || defined (__MINGW32__) +#include + +#define IOCTL_SCSI_BASE 0x00000004 + +#define METHOD_BUFFERED 0 +#define METHOD_OUT_DIRECT 2 + +#define FILE_ANY_ACCESS 0 +#define FILE_READ_ACCESS 0x0001 + +#define CTL_CODE( DevType, Function, Method, Access ) ( \ + ((DevType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \ +) +#define IOCTL_SCSI_GET_ADDRESS CTL_CODE( IOCTL_SCSI_BASE, 0x0406, METHOD_BUFFERED, FILE_ANY_ACCESS ) +#define FILE_DEVICE_CD_ROM 0x00000002 +#define IOCTL_CDROM_BASE FILE_DEVICE_CD_ROM +#define IOCTL_CDROM_RAW_READ CTL_CODE(IOCTL_CDROM_BASE, 0x000F, METHOD_OUT_DIRECT, FILE_READ_ACCESS) + +#endif + +#include +#include +#include -Handle * open_iso(const String &); +class cdabstract : public Base { + public: + static Handle * open_cd(const String &); + static bool canprobe(); + static std::vector probe() throw (GeneralException); +#if defined (_MSC_VER) || defined (__MINGW32__) + protected: + static HANDLE OpenIOCTLFile(char cLetter); + static void GetIOCTLAdapter(HANDLE hF, int * iDA, int * iDT, int * iDL); +#endif + private: + static bool subprobe(String &); + friend class cdreader; +}; #endif diff --git a/includes/cdreader.h b/includes/cdreader.h index 8ebe362..acf6765 100644 --- a/includes/cdreader.h +++ b/includes/cdreader.h @@ -1,11 +1,11 @@ #ifndef __CDREADER_H__ #define __CDREADER_H__ -#ifdef __cplusplus #include #include #include #include +#include "cdabstract.h" class cdreader : public Handle { public: @@ -15,6 +15,9 @@ class cdreader : public Handle { virtual bool CanWrite() const; virtual bool CanRead() const; virtual bool CanSeek() const; +#if defined (_MSC_VER) || defined (__MINGW32__) + virtual void close() throw (GeneralException); +#endif virtual ssize_t read(void *buf, size_t count) throw (GeneralException); virtual off_t seek(off_t, int = SEEK_SET) throw (GeneralException); virtual String GetName() const; @@ -25,9 +28,9 @@ class cdreader : public Handle { private: String n; int sector; +#if defined (_MSC_VER) || defined (__MINGW32__) + HANDLE hF; +#endif }; -#else -#error This only works with a C++ compiler -#endif #endif diff --git a/lib/cdabstract.cpp b/lib/cdabstract.cpp index b79960f..f5f0d08 100644 --- a/lib/cdabstract.cpp +++ b/lib/cdabstract.cpp @@ -2,14 +2,151 @@ #include "Input.h" #include "cdreader.h" -Handle * open_iso(const String & nom) { -#ifdef USE_CDREADER +#ifdef __linux__ +#include +#include +#include +#include +#endif + +#if defined (_MSC_VER) || defined (__MINGW32__) +#include +#endif + +Handle * cdabstract::open_cd(const String & nom) { if (nom.extract(0, 2).toupper() == "CD:") { return new cdreader(nom.extract(3)); } else { -#else - { -#endif return new Input(nom); } } + +bool cdabstract::canprobe() { +#ifdef __linux__ + return true; +#endif +#if defined (_MSC_VER) || defined (_MINGW32) + OSVERSIONINFO ov; + memset(&ov, 0, sizeof(OSVERSIONINFO)); + ov.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + + GetVersionEx(&ov); + + return ((ov.dwPlatformId == VER_PLATFORM_WIN32_NT) && (ov.dwMajorVersion > 4)); +#endif + return false; +} + +std::vector cdabstract::probe() throw (GeneralException) { + std::vector r; + String probed; + + if (!canprobe()) + throw GeneralException("Can't probe CD devices on this platform."); + +#ifdef __linux__ +#endif + +#if defined (_MSC_VER) || defined (__MINGW32__) +#endif + + return r; +} + +#if defined (_MSC_VER) || defined (__MINGW32__) +HANDLE cdabstract::OpenIOCTLFile(char cLetter) { + HANDLE hF; + char szFName[16]; + OSVERSIONINFO ov; + DWORD dwFlags; + DWORD dwIOCTLAttr = 0; + + memset(&ov, 0, sizeof(OSVERSIONINFO)); + ov.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&ov); + + if((ov.dwPlatformId == VER_PLATFORM_WIN32_NT) && (ov.dwMajorVersion > 4)) + dwFlags = GENERIC_READ | GENERIC_WRITE; // add gen write on W2k/XP + else dwFlags = GENERIC_READ; + + wsprintf(szFName, "\\\\.\\%c:", cLetter); + + hF = CreateFile(szFName, dwFlags, FILE_SHARE_READ, // open drive + NULL, OPEN_EXISTING, dwIOCTLAttr, NULL); + + if (hF == INVALID_HANDLE_VALUE) { // mmm... no success? + dwFlags ^= GENERIC_WRITE; // -> try write toggle + hF = CreateFile(szFName, dwFlags, FILE_SHARE_READ, // -> open drive again + NULL, OPEN_EXISTING, dwIOCTLAttr, NULL); + if (hF == INVALID_HANDLE_VALUE) + return NULL; + } + return hF; +} + +typedef struct { + ULONG Length; + UCHAR PortNumber; + UCHAR PathId; + UCHAR TargetId; + UCHAR Lun; +} SCSI_ADDRESS, *PSCSI_ADDRESS; + +void cdabstract::GetIOCTLAdapter(HANDLE hF, int * iDA, int * iDT, int * iDL) { + char szBuf[1024]; + PSCSI_ADDRESS pSA; + DWORD dwRet; + + *iDA = *iDT = *iDL = -1; + + if (hF == NULL) + return; + + memset(szBuf,0,1024); + + pSA = (PSCSI_ADDRESS)szBuf; + pSA->Length = sizeof(SCSI_ADDRESS); + + if (!DeviceIoControl(hF, IOCTL_SCSI_GET_ADDRESS, NULL, 0, pSA, + sizeof(SCSI_ADDRESS), &dwRet, NULL)) + return; + + *iDA = pSA->PortNumber; + *iDT = pSA->TargetId; + *iDL = pSA->Lun; +} +#endif + +bool cdabstract::subprobe(String & probed) { +#ifdef __linux__ + int h, caps; + + h = open(probed.to_charp(), O_RDONLY | O_NONBLOCK); + + if (ioctl(h, CDROM_GET_CAPABILITY, &caps) < 0) { + close(h); + return false; + } else { + close(h); + return true; + } +#endif + +#if defined (_MSC_VER) || defined (__MINGW32__) + int iDA, iDT, iDL; + char letter[4]; + HANDLE h; + + if (GetDriveType(probed.to_charp()) == DRIVE_CDROM) { + h = OpenIOCTLFile(probed[0]); + GetIOCTLAdapter(h, &iDA, &iDT, &iDL); + CloseHandle(h); + if ((iDA != -1) && (iDT != -1) && (iDL != -1)) { + probed += String().set(" [%i:%i:%i]", iDA, iDT, iDL); + return true; + } + } +#endif + + return false; +} diff --git a/lib/cdreader.cpp b/lib/cdreader.cpp index 32e815f..5e88e98 100644 --- a/lib/cdreader.cpp +++ b/lib/cdreader.cpp @@ -12,6 +12,7 @@ #else #define _(x) x #endif +#include "cdabstract.h" bool cdreader::CanWrite() const { return 0; @@ -120,5 +121,60 @@ void cdreader::getsector(void *buf, int sec) throw (GeneralException) { sector++; } +#endif + +#if defined (_MSC_VER) || defined (__MINGW32__) +cdreader::cdreader(const String & no) throw (GeneralException) : + Handle(-1), n(no), sector(0) { + if (!(hF = cdabstract::OpenIOCTLFile(no[0]))) + throw GeneralException("Error opening device " + no); +} + +cdreader::cdreader(const cdreader & i) : Handle(i), n(i.n), hF(i.hF) { +} + +void cdreader::close() throw (GeneralException) { + CloseHandle(hF); +} + +typedef enum _TRACK_MODE_TYPE { + YellowMode2, + XAForm2, + CDDA +} TRACK_MODE_TYPE, *PTRACK_MODE_TYPE; + +typedef struct _RAW_READ_INFO { + LARGE_INTEGER DiskOffset; + ULONG SectorCount; + TRACK_MODE_TYPE TrackMode; +} RAW_READ_INFO, *PRAW_READ_INFO; + +void cdreader::getsector(void *buf, int sec) throw (GeneralException) { + RAW_READ_INFO rawIOCTL; + DWORD dwRet; + BOOL bStat; + bool done = false; + if (sec >= 0) + sector = sec; + + rawIOCTL.DiskOffset.QuadPart = sector * 2048; + rawIOCTL.SectorCount = 1; + rawIOCTL.TrackMode = YellowMode2; + + while (!done) { + SetLastError(0); + bStat = DeviceIoControl(hF, IOCTL_CDROM_RAW_READ, + &rawIOCTL, sizeof(RAW_READ_INFO), + buf, 2352, &dwRet, NULL); + if (!bStat) { + DWORD dwErrCode = GetLastError(); + if (dwErrCode != ERROR_IO_PENDING) { + throw GeneralException("Gave up on reading CD"); + } + } else { + done = true; + } + } +} #endif -- cgit v1.2.3