From c26be68be4ba1426cc3df86952109488c3cefaaf Mon Sep 17 00:00:00 2001 From: gbeauche <> Date: Sun, 5 Dec 2004 15:03:05 +0000 Subject: [PATCH] cdenable interface --- BasiliskII/src/Windows/cdenable/cache.cpp | 182 ++++++++++ BasiliskII/src/Windows/cdenable/cache.h | 50 +++ BasiliskII/src/Windows/cdenable/cdenable.h | 60 ++++ BasiliskII/src/Windows/cdenable/eject_nt.cpp | 190 ++++++++++ BasiliskII/src/Windows/cdenable/eject_nt.h | 44 +++ BasiliskII/src/Windows/cdenable/ntcd.cpp | 345 +++++++++++++++++++ BasiliskII/src/Windows/cdenable/ntcd.h | 99 ++++++ 7 files changed, 970 insertions(+) create mode 100755 BasiliskII/src/Windows/cdenable/cache.cpp create mode 100755 BasiliskII/src/Windows/cdenable/cache.h create mode 100755 BasiliskII/src/Windows/cdenable/cdenable.h create mode 100755 BasiliskII/src/Windows/cdenable/eject_nt.cpp create mode 100755 BasiliskII/src/Windows/cdenable/eject_nt.h create mode 100755 BasiliskII/src/Windows/cdenable/ntcd.cpp create mode 100755 BasiliskII/src/Windows/cdenable/ntcd.h diff --git a/BasiliskII/src/Windows/cdenable/cache.cpp b/BasiliskII/src/Windows/cdenable/cache.cpp new file mode 100755 index 00000000..3cbf3871 --- /dev/null +++ b/BasiliskII/src/Windows/cdenable/cache.cpp @@ -0,0 +1,182 @@ +/* + * cache.cpp - simple floppy/cd cache for Win32 + * + * Basilisk II (C) 1997-1999 Christian Bauer + * + * Windows platform specific code copyright (C) Lauri Pesonen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + Note that this is particularly silly cache code + and doesn't even use hash buckets. It is sufficient + for floppies and maybe emulated cd's but that's it. +*/ + +#include "sysdeps.h" +#include "windows.h" +#include "cache.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +void cache_clear( cachetype *cptr ) +{ + if(cptr->inited) { + cptr->res_count = 0; + memset( cptr->LRU, 0, NBLOCKS * sizeof(int) ); + } +} + +static int init( cachetype *cptr, int sector_size ) +{ + cache_clear( cptr ); + cptr->sector_size = sector_size; + cptr->blocks = (char *)VirtualAlloc( + NULL, NBLOCKS*sector_size, + MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE ); + cptr->block = (int *)VirtualAlloc( + NULL, NBLOCKS*sizeof(int), + MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE ); + cptr->LRU = (DWORD *)VirtualAlloc( + NULL, NBLOCKS*sizeof(DWORD), + MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE ); + return(cptr->blocks != NULL); +} + +static void final( cachetype *cptr ) +{ + if(cptr->blocks) { + VirtualFree( cptr->blocks, 0, MEM_RELEASE ); + cptr->blocks = 0; + } + if(cptr->block) { + VirtualFree( cptr->block, 0, MEM_RELEASE ); + cptr->block = 0; + } + if(cptr->LRU) { + VirtualFree( cptr->LRU, 0, MEM_RELEASE ); + cptr->LRU = 0; + } + cptr->inited = 0; +} + +void cache_init( cachetype *cptr ) +{ + cptr->inited = 0; +} + +void cache_final( cachetype *cptr ) +{ + if(cptr->inited) { + final( cptr ); + cptr->inited = 0; + } +} + +static int in_cache( cachetype *cptr, int block ) +{ + int i; + for(i=cptr->res_count-1; i>=0; i--) { + if(cptr->block[i] == block) return(i); + } + return(-1); +} + +static int get_LRU( cachetype *cptr ) +{ + int i, result = 0; + DWORD mtime = cptr->LRU[0]; + + for(i=1; iLRU[i] < mtime) { + mtime = cptr->LRU[i]; + result = i; + } + } + return(result); +} + +void cache_put( cachetype *cptr, int block, char *buf, int ss ) +{ + int inx; + + if(!cptr->inited) { + if(!init(cptr,ss)) return; + cptr->inited = 1; + } + inx = in_cache( cptr, block ); + if(inx < 0) { + if(cptr->res_count == NBLOCKS) { + inx = get_LRU( cptr ); + } else { + inx = cptr->res_count++; + } + cptr->block[inx] = block; + } + cptr->LRU[inx] = GetTickCount(); + memcpy( cptr->blocks + inx * ss, buf, ss ); +} + +int cache_get( cachetype *cptr, int block, char *buf ) +{ + int inx; + + if(!cptr->inited) return(0); + + inx = in_cache( cptr, block ); + if(inx >= 0) { + memcpy( buf, cptr->blocks + inx * cptr->sector_size, cptr->sector_size ); + return(1); + } else { + return(0); + } +} + +void cache_remove( cachetype *cptr, int block, int ss ) +{ + int inx, from; + + if(!cptr->inited) { + if(!init(cptr,ss)) return; + cptr->inited = 1; + } + inx = in_cache( cptr, block ); + if(inx >= 0) { + if(cptr->res_count > 1) { + from = cptr->res_count-1; + cptr->block[inx] = cptr->block[from]; + cptr->LRU[inx] = cptr->LRU[from]; + memcpy( + cptr->blocks + inx * cptr->sector_size, + cptr->blocks + from * cptr->sector_size, + cptr->sector_size + ); + } + cptr->res_count--; + } +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/BasiliskII/src/Windows/cdenable/cache.h b/BasiliskII/src/Windows/cdenable/cache.h new file mode 100755 index 00000000..20074081 --- /dev/null +++ b/BasiliskII/src/Windows/cdenable/cache.h @@ -0,0 +1,50 @@ +/* + * cache.cpp - simple floppy/cd cache for Win32 + * + * Basilisk II (C) 1997-1999 Christian Bauer + * + * Windows platform specific code copyright (C) Lauri Pesonen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _CACHE_H_ +#define _CACHE_H_ +#define NBLOCKS 1000 + +typedef struct { + int inited; + int res_count; + int sector_size; + char *blocks; + int *block; + DWORD *LRU; +} cachetype; + +void cache_init( cachetype *cptr ); +void cache_clear( cachetype *cptr ); +void cache_final( cachetype *cptr ); +int cache_get( cachetype *cptr, int block, char *buf ); +void cache_put( cachetype *cptr, int block, char *buf, int ss ); +void cache_remove( cachetype *cptr, int block, int ss ); +#endif + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/BasiliskII/src/Windows/cdenable/cdenable.h b/BasiliskII/src/Windows/cdenable/cdenable.h new file mode 100755 index 00000000..ec40a7b0 --- /dev/null +++ b/BasiliskII/src/Windows/cdenable/cdenable.h @@ -0,0 +1,60 @@ +/* + * cdenable.h - cdenable.vxd definitions + * + * Basilisk II (C) 1997-1999 Christian Bauer + * + * Windows platform specific code copyright (C) Lauri Pesonen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// max read requests, if larger -> STATUS_INVALID_PARAMETER +#define CDENABLE_MAX_TRANSFER_SIZE (0x10000) + + +// A structure representing the instance information associated with +// a particular device +typedef struct _DEVICE_EXTENSION +{ + // not needed. + ULONG StateVariable; +} DEVICE_EXTENSION, *PDEVICE_EXTENSION; + + +// Define the various device type values. Note that values used by Microsoft +// Corporation are in the range 0-32767, and 32768-65535 are reserved for use +// by customers. +#define FILE_DEVICE_CDENABLE 0x00008301 + + +// Target NT version, internal version +#define CDENABLE_CURRENT_VERSION 0x04000100 + + +// Macro definition for defining IOCTL and FSCTL function control codes. Note +// that function codes 0-2047 are reserved for Microsoft Corporation, and +// 2048-4095 are reserved for customers. +#define CDENABLE_IOCTL_READ 0x830 +#define CDENABLE_IOCTL_GET_VERSION 0x831 + + +#define IOCTL_CDENABLE_READ CTL_CODE(FILE_DEVICE_CDENABLE, \ + CDENABLE_IOCTL_READ, \ + METHOD_BUFFERED, \ + FILE_ANY_ACCESS) +#define IOCTL_CDENABLE_GET_VERSION CTL_CODE(FILE_DEVICE_CDENABLE, \ + CDENABLE_IOCTL_GET_VERSION, \ + METHOD_BUFFERED, \ + FILE_ANY_ACCESS) diff --git a/BasiliskII/src/Windows/cdenable/eject_nt.cpp b/BasiliskII/src/Windows/cdenable/eject_nt.cpp new file mode 100755 index 00000000..102ed1ff --- /dev/null +++ b/BasiliskII/src/Windows/cdenable/eject_nt.cpp @@ -0,0 +1,190 @@ +/* + * eject_nt.cpp - cd eject routines for WinNT (derived from MS samples) + * + * Basilisk II (C) 1997-1999 Christian Bauer + * + * Windows platform specific code copyright (C) Lauri Pesonen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "sysdeps.h" + +#include "windows.h" +#include + +// Prototypes + +extern "C" { + +#include "eject_nt.h" + +LPTSTR szVolumeFormat = TEXT("\\\\.\\%c:"); +LPTSTR szRootFormat = TEXT("%c:\\"); +LPTSTR szErrorFormat = TEXT("Error %d: %s\n"); + +void ReportError(LPTSTR szMsg) +{ + // _tprintf(szErrorFormat, GetLastError(), szMsg); +} + +HANDLE OpenVolume(TCHAR cDriveLetter) +{ + HANDLE hVolume; + UINT uDriveType; + TCHAR szVolumeName[8]; + TCHAR szRootName[5]; + DWORD dwAccessFlags; + + wsprintf(szRootName, szRootFormat, cDriveLetter); + + uDriveType = GetDriveType(szRootName); + switch(uDriveType) { + case DRIVE_REMOVABLE: + dwAccessFlags = GENERIC_READ | GENERIC_WRITE; + break; + case DRIVE_CDROM: + dwAccessFlags = GENERIC_READ; + break; + default: + // _tprintf(TEXT("Cannot eject. Drive type is incorrect.\n")); + return INVALID_HANDLE_VALUE; + } + + wsprintf(szVolumeName, szVolumeFormat, cDriveLetter); + + hVolume = CreateFile( szVolumeName, + dwAccessFlags, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + 0, + NULL ); + if (hVolume == INVALID_HANDLE_VALUE) + ReportError(TEXT("CreateFile")); + + return hVolume; +} + +BOOL CloseVolume(HANDLE hVolume) +{ + return CloseHandle(hVolume); +} + +#define LOCK_TIMEOUT 1000 // 1 second +#define LOCK_RETRIES 20 + +BOOL LockVolume(HANDLE hVolume) +{ + DWORD dwBytesReturned; + DWORD dwSleepAmount; + int nTryCount; + + dwSleepAmount = LOCK_TIMEOUT / LOCK_RETRIES; + + // Do this in a loop until a timeout period has expired + for (nTryCount = 0; nTryCount < LOCK_RETRIES; nTryCount++) { + if (DeviceIoControl(hVolume, + FSCTL_LOCK_VOLUME, + NULL, 0, + NULL, 0, + &dwBytesReturned, + NULL)) + return TRUE; + + Sleep(dwSleepAmount); + } + + return FALSE; +} + +BOOL DismountVolume(HANDLE hVolume) +{ + DWORD dwBytesReturned; + + return DeviceIoControl( hVolume, + FSCTL_DISMOUNT_VOLUME, + NULL, 0, + NULL, 0, + &dwBytesReturned, + NULL); +} + +BOOL PreventRemovalOfVolume(HANDLE hVolume, BOOL fPreventRemoval) +{ + DWORD dwBytesReturned; + PREVENT_MEDIA_REMOVAL PMRBuffer; + + PMRBuffer.PreventMediaRemoval = fPreventRemoval; + + return DeviceIoControl( hVolume, + IOCTL_STORAGE_MEDIA_REMOVAL, + &PMRBuffer, sizeof(PREVENT_MEDIA_REMOVAL), + NULL, 0, + &dwBytesReturned, + NULL); +} + +BOOL AutoEjectVolume( HANDLE hVolume, BOOL reload ) +{ + DWORD dwBytesReturned; + + return DeviceIoControl( hVolume, + reload ? IOCTL_STORAGE_LOAD_MEDIA : IOCTL_STORAGE_EJECT_MEDIA, + NULL, 0, + NULL, 0, + &dwBytesReturned, + NULL); +} + +BOOL EjectVolume( TCHAR cDriveLetter, BOOL reload ) +{ + HANDLE hVolume; + + BOOL fRemoveSafely = FALSE; + BOOL fAutoEject = FALSE; + + // Open the volume. + hVolume = OpenVolume(cDriveLetter); + if (hVolume == INVALID_HANDLE_VALUE) + return FALSE; + + // Lock and dismount the volume. + if (LockVolume(hVolume) && DismountVolume(hVolume)) { + fRemoveSafely = TRUE; + + // Set prevent removal to false and eject the volume. + if (PreventRemovalOfVolume(hVolume, FALSE) && + AutoEjectVolume(hVolume,reload)) + fAutoEject = TRUE; + } + + // Close the volume so other processes can use the drive. + if (!CloseVolume(hVolume)) + return FALSE; + + /* + if (fAutoEject) + printf("Media in Drive %c has been ejected safely.\n", cDriveLetter); + else { + if (fRemoveSafely) + printf("Media in Drive %c can be safely removed.\n", cDriveLetter); + } + */ + + return TRUE; +} + +} // extern "C" diff --git a/BasiliskII/src/Windows/cdenable/eject_nt.h b/BasiliskII/src/Windows/cdenable/eject_nt.h new file mode 100755 index 00000000..e72a7a67 --- /dev/null +++ b/BasiliskII/src/Windows/cdenable/eject_nt.h @@ -0,0 +1,44 @@ +/* + * eject_nt.cpp - cd eject routines for WinNT (derived from MS samples) + * + * Basilisk II (C) 1997-1999 Christian Bauer + * + * Windows platform specific code copyright (C) Lauri Pesonen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _EJECT_NT_H_ +#define _EJECT_NT_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + +BOOL EjectVolume(TCHAR cDriveLetter,BOOL reload); + +HANDLE OpenVolume(TCHAR cDriveLetter); +BOOL LockVolume(HANDLE hVolume); +BOOL DismountVolume(HANDLE hVolume); +BOOL PreventRemovalOfVolume(HANDLE hVolume, BOOL fPrevent); +BOOL AutoEjectVolume(HANDLE hVolume,BOOL reload); +BOOL CloseVolume(HANDLE hVolume); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif //_EJECT_NT_H_ diff --git a/BasiliskII/src/Windows/cdenable/ntcd.cpp b/BasiliskII/src/Windows/cdenable/ntcd.cpp new file mode 100755 index 00000000..a1b9a4c5 --- /dev/null +++ b/BasiliskII/src/Windows/cdenable/ntcd.cpp @@ -0,0 +1,345 @@ +/* + * ntcd.cpp - Interface to cdenable.sys driver + * + * Basilisk II (C) 1997-1999 Christian Bauer + * + * Windows platform specific code copyright (C) Lauri Pesonen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "sysdeps.h" +#include + +extern "C" { + +#include +#include +#include "ntcd.h" +#include "cdenable.h" + +static char *sDriverShort = "cdenable"; +static char *sDriverLong = "System32\\Drivers\\cdenable.sys"; +static char *sCompleteName = "\\\\.\\cdenable"; + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +// Start type must be SERVICE_AUTO_START or lower, in order +// it to start automatically and allow the mechanism work +// for users with no admin rights. +static BOOL InstallDriver( + IN SC_HANDLE SchSCManager, + IN LPCTSTR DriverName, + IN LPCTSTR ServiceExe +) +{ + SC_HANDLE schService; + DWORD err; + + schService = CreateService ( + SchSCManager, // SCManager database + DriverName, // name of service + DriverName, // name to display + SERVICE_ALL_ACCESS, // desired access + SERVICE_KERNEL_DRIVER, // service type + SERVICE_AUTO_START, // SERVICE_DEMAND_START, // start type + SERVICE_ERROR_NORMAL, // error control type + ServiceExe, // service's binary + NULL, // no load ordering group + NULL, // no tag identifier + NULL, // no dependencies + NULL, // LocalSystem account + NULL // no password + ); + + if (schService == NULL) { + err = GetLastError(); + if (err == ERROR_SERVICE_EXISTS) { + return TRUE; + } else { + return FALSE; + } + } + CloseServiceHandle (schService); + return TRUE; +} + +static BOOL RemoveDriver( + IN SC_HANDLE SchSCManager, + IN LPCTSTR DriverName +) +{ + SC_HANDLE schService; + BOOL ret; + + schService = OpenService (SchSCManager, + DriverName, + SERVICE_ALL_ACCESS + ); + if (schService == NULL) return FALSE; + ret = DeleteService (schService); + CloseServiceHandle (schService); + return ret; +} + +static BOOL StartDriver( + IN SC_HANDLE SchSCManager, + IN LPCTSTR DriverName +) { + SC_HANDLE schService; + BOOL ret; + DWORD err; + + schService = OpenService (SchSCManager, + DriverName, + SERVICE_ALL_ACCESS + ); + if (schService == NULL) return FALSE; + ret = StartService (schService, // service identifier + 0, // number of arguments + NULL // pointer to arguments + ); + if(ret == 0) { + err = GetLastError(); + if (err == ERROR_SERVICE_ALREADY_RUNNING) { + ret = TRUE; + } else { + ret = FALSE; + } + } + CloseServiceHandle (schService); + return ret; +} + +static BOOL StopDriver( + IN SC_HANDLE SchSCManager, + IN LPCTSTR DriverName +) +{ + SC_HANDLE schService; + BOOL ret; + SERVICE_STATUS serviceStatus; + + schService = OpenService (SchSCManager, + DriverName, + SERVICE_ALL_ACCESS + ); + if (schService == NULL) return FALSE; + ret = ControlService (schService, + SERVICE_CONTROL_STOP, + &serviceStatus + ); + CloseServiceHandle (schService); + return ret; +} + +static BOOL __cdecl start_driver( void ) +{ + SC_HANDLE schSCManager; + BOOL ret = FALSE; + + schSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); + if(!schSCManager) return(FALSE); + if(!InstallDriver( schSCManager, sDriverShort, sDriverLong )) { + CloseServiceHandle( schSCManager ); + return(FALSE); + } + ret = StartDriver( schSCManager, sDriverShort ); + if(!ret) { + (void)RemoveDriver( schSCManager, sDriverShort ); + } + CloseServiceHandle( schSCManager ); + return( ret ); +} + +static BOOL __cdecl stop_driver( void ) +{ + SC_HANDLE schSCManager; + BOOL ret = FALSE; + + schSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); + if(!schSCManager) return(FALSE); + if(StopDriver( schSCManager, sDriverShort )) ret = TRUE; + CloseServiceHandle( schSCManager ); + return( ret ); +} + +static BOOL __cdecl remove_driver( void ) +{ + SC_HANDLE schSCManager; + BOOL ret = FALSE; + + schSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); + if(!schSCManager) return(FALSE); + if(RemoveDriver( schSCManager, sDriverShort )) ret = TRUE; + CloseServiceHandle( schSCManager ); + return( ret ); +} + + + +// Exported stuff begins + +int CdenableSysReadCdBytes( HANDLE h, DWORD start, DWORD count, char *buf ) +{ + HANDLE hDevice; + int ret; + DWORD nb; + DWORD in_buffer[10]; + DWORD out_buffer[10]; + + ret = 0; + + in_buffer[0] = (DWORD)h; + in_buffer[1] = (DWORD)start; + in_buffer[2] = (DWORD)count; + in_buffer[3] = (DWORD)buf; + out_buffer[0] = 0; + + hDevice = CreateFile (sCompleteName, + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + + if (hDevice == ((HANDLE)-1)) { + ret = 0; + } else { + if ( DeviceIoControl( hDevice, + IOCTL_CDENABLE_READ, + (LPVOID)in_buffer, 16, + (LPVOID)out_buffer, 4, + &nb, NULL ) ) + { + if(out_buffer[0] != 0) ret = count; + } + CloseHandle (hDevice); + } + + return ret; +} + +int CdenableSysReadCdSectors( HANDLE h, DWORD start, DWORD count, char *buf ) +{ + return( CdenableSysReadCdBytes( h, (start<<11), (count<<11), buf ) ); +} + +int CdenableSysWriteCdBytes( HANDLE h, DWORD start, DWORD count, char *buf ) +{ + return( 0 ); + + /* + HANDLE hDevice; + int ret; + DWORD nb; + DWORD in_buffer[10]; + DWORD out_buffer[10]; + + ret = 0; + + in_buffer[0] = (DWORD)h; + in_buffer[1] = (DWORD)start; + in_buffer[2] = (DWORD)count; + in_buffer[3] = (DWORD)buf; + out_buffer[0] = 0; + + hDevice = CreateFile (sCompleteName, + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + + if (hDevice == ((HANDLE)-1)) { + ret = 0; + } else { + if ( DeviceIoControl( hDevice, + IOCTL_CDENABLE_WRITE, + (LPVOID)in_buffer, 16, + (LPVOID)out_buffer, 4, + &nb, NULL ) ) + { + if(out_buffer[0] != 0) ret = count; + } + CloseHandle (hDevice); + } + + return ret; + */ +} + +int CdenableSysWriteCdSectors( HANDLE h, DWORD start, DWORD count, char *buf ) +{ + // return( CdenableSysWriteCdBytes( h, (start<<11), (count<<11), buf ) ); + return( 0 ); +} + +BOOL CdenableSysInstallStart(void) +{ + return(start_driver()); +} + +void CdenableSysStopRemove(void) +{ + stop_driver(); + remove_driver(); +} + +DWORD CdenableSysGetVersion( void ) +{ + HANDLE hDevice; + DWORD ret; + DWORD nb; + DWORD out_buffer[10]; + + ret = 0; + out_buffer[0] = 0; + hDevice = CreateFile (sCompleteName, + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + if (hDevice == ((HANDLE)-1)) { + ret = 0; + } else { + if ( DeviceIoControl( hDevice, + IOCTL_CDENABLE_GET_VERSION, + NULL, 0, + (LPVOID)out_buffer, 4, + &nb, NULL ) ) + { + ret = out_buffer[0]; + } + CloseHandle (hDevice); + } + return ret; +} + +#ifdef __cplusplus +} //extern "C" +#endif + diff --git a/BasiliskII/src/Windows/cdenable/ntcd.h b/BasiliskII/src/Windows/cdenable/ntcd.h new file mode 100755 index 00000000..01380f0d --- /dev/null +++ b/BasiliskII/src/Windows/cdenable/ntcd.h @@ -0,0 +1,99 @@ +/* + * ntcd.h - Interface to cdenable.sys driver + * + * Basilisk II (C) 1997-1999 Christian Bauer + * + * Windows platform specific code copyright (C) Lauri Pesonen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +/* + Installs the driver, if not already installed. + Starts the driver, if not already running. + + You can either always call "CdenableSysInstallStart" when your + program fires up and "CdenableSysStopRemove" when it terminates, + or just let the installation program call "CdenableSysInstallStart" + and leave it always be present. + + I recommend the latter option. Calling "CdenableSysInstallStart" + always doesn't hurt anything, it will immediately return + with success if the service is running. + + Returns non-zero if installation/startup was succesfull, + zero if anything failed. + Returns non-zero also if the driver was already running. + + The file "cdenable.sys" must already have been copied to + the directory "System32\Drivers" +*/ + +#ifndef _NT_CD_H_ +#define _NT_CD_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + +BOOL CdenableSysInstallStart(void); + + +/* + Stops and removes the driver. See above. + This must be called when new version of the driver is updated. +*/ +void CdenableSysStopRemove(void); + + +/* + HANDLE h: returned from CreateFile ( "\\\\.\\X:", GENERIC_READ, ... ); + Returns the bytes actually read (==count), 0 on failure. + NOTE: in my code, start and count are always aligned to + sector boundaries (2048 bytes). + I cannot guarantee that this works if they are not. + Max read is 64 kb. + Synchronous read, but quite fast. +*/ +int CdenableSysReadCdBytes( HANDLE h, DWORD start, DWORD count, char *buf ); + + +/* + Same as SysReadCdBytes, but "start" and "count" are in 2048 byte + sectors. +*/ +int CdenableSysReadCdSectors( HANDLE h, DWORD start, DWORD count, char *buf ); + + +/* + Ditto for writing stuff. + Not a cd of course but removable & hd media are supported now. +*/ +int CdenableSysWriteCdBytes( HANDLE h, DWORD start, DWORD count, char *buf ); +int CdenableSysWriteCdSectors( HANDLE h, DWORD start, DWORD count, char *buf ); + + +/* + Returns CDENABLE_CURRENT_VERSION (of the driver). +*/ +DWORD CdenableSysGetVersion( void ); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif //_NT_CD_H_