mirror of
https://github.com/kanjitalk755/macemu.git
synced 2024-10-18 00:23:59 +00:00
cdenable interface
This commit is contained in:
parent
67399201bb
commit
c26be68be4
182
BasiliskII/src/Windows/cdenable/cache.cpp
Executable file
182
BasiliskII/src/Windows/cdenable/cache.cpp
Executable file
@ -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; i<NBLOCKS; i++) {
|
||||||
|
if(cptr->LRU[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
|
50
BasiliskII/src/Windows/cdenable/cache.h
Executable file
50
BasiliskII/src/Windows/cdenable/cache.h
Executable file
@ -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
|
60
BasiliskII/src/Windows/cdenable/cdenable.h
Executable file
60
BasiliskII/src/Windows/cdenable/cdenable.h
Executable file
@ -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)
|
190
BasiliskII/src/Windows/cdenable/eject_nt.cpp
Executable file
190
BasiliskII/src/Windows/cdenable/eject_nt.cpp
Executable file
@ -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 <winioctl.h>
|
||||||
|
|
||||||
|
// 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"
|
44
BasiliskII/src/Windows/cdenable/eject_nt.h
Executable file
44
BasiliskII/src/Windows/cdenable/eject_nt.h
Executable file
@ -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_
|
345
BasiliskII/src/Windows/cdenable/ntcd.cpp
Executable file
345
BasiliskII/src/Windows/cdenable/ntcd.cpp
Executable file
@ -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 <windows.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
#include <winioctl.h>
|
||||||
|
#include <winsvc.h>
|
||||||
|
#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
|
||||||
|
|
99
BasiliskII/src/Windows/cdenable/ntcd.h
Executable file
99
BasiliskII/src/Windows/cdenable/ntcd.h
Executable file
@ -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_
|
Loading…
Reference in New Issue
Block a user