X-Git-Url: https://git.gag.com/?p=debian%2Fcpmtools;a=blobdiff_plain;f=device_win32.c;fp=device_win32.c;h=0000000000000000000000000000000000000000;hp=1829443242c47233973a24a96e5dbb521d994e69;hb=0244ff6db7cb417c6210118e14ebc8a11924b7f6;hpb=be51a0b47ec4edacc689851a88ec6172737cb61c diff --git a/device_win32.c b/device_win32.c deleted file mode 100644 index 1829443..0000000 --- a/device_win32.c +++ /dev/null @@ -1,670 +0,0 @@ -/* #includes */ /*{{{C}}}*//*{{{*/ -#include "config.h" - -#include -#include -#include -#include - -#include "cpmdir.h" -#include "cpmfs.h" - -#ifdef USE_DMALLOC -#include -#endif -/*}}}*/ -/* types */ /*{{{*/ -#define PHYSICAL_SECTOR_1 1 /* First physical sector */ - -/* Use the INT13 interface rather than INT25/INT26. This appears to - * improve performance, but is less well tested. */ -#define USE_INT13 - -/* Windows 95 disk I/O functions - based on Stan Mitchell's DISKDUMP.C */ -#define VWIN32_DIOC_DOS_IOCTL 1 /* DOS ioctl calls 4400h-4411h */ -#define VWIN32_DIOC_DOS_INT25 2 /* absolute disk read, DOS int 25h */ -#define VWIN32_DIOC_DOS_INT26 3 /* absolute disk write, DOS int 26h */ -#define VWIN32_DIOC_DOS_INT13 4 /* BIOS INT13 functions */ - -typedef struct _DIOC_REGISTERS { - DWORD reg_EBX; - DWORD reg_EDX; - DWORD reg_ECX; - DWORD reg_EAX; - DWORD reg_EDI; - DWORD reg_ESI; - DWORD reg_Flags; - } - DIOC_REGISTERS, *PDIOC_REGISTERS; - -#define LEVEL0_LOCK 0 -#define LEVEL1_LOCK 1 -#define LEVEL2_LOCK 2 -#define LEVEL3_LOCK 3 -#define LEVEL1_LOCK_MAX_PERMISSION 0x0001 - -#define DRIVE_IS_REMOTE 0x1000 -#define DRIVE_IS_SUBST 0x8000 - -/********************************************************* - **** Note: all MS-DOS data structures must be packed **** - **** on a one-byte boundary. **** - *********************************************************/ -#pragma pack(1) - -typedef struct _DISKIO { - DWORD diStartSector; /* sector number to start at */ - WORD diSectors; /* number of sectors */ - DWORD diBuffer; /* address of buffer */ - } - DISKIO, *PDISKIO; - -typedef struct MID { - WORD midInfoLevel; /* information level, must be 0 */ - DWORD midSerialNum; /* serial number for the medium */ - char midVolLabel[11]; /* volume label for the medium */ - char midFileSysType[8]; /* type of file system as 8-byte ASCII */ - } - MID, *PMID; - -typedef struct driveparams { /* Disk geometry */ - BYTE special; - BYTE devicetype; - WORD deviceattrs; - WORD cylinders; - BYTE mediatype; - /* BPB starts here */ - WORD bytespersector; - BYTE sectorspercluster; - WORD reservedsectors; - BYTE numberofFATs; - WORD rootdirsize; - WORD totalsectors; - BYTE mediaid; - WORD sectorsperfat; - WORD sectorspertrack; - WORD heads; - DWORD hiddensectors; - DWORD bigtotalsectors; - BYTE reserved[6]; - /* BPB ends here */ - WORD sectorcount; - WORD sectortable[80]; - } DRIVEPARAMS, *PDRIVEPARAMS; -/*}}}*/ - -static char *strwin32error(void) /*{{{*/ -{ - static char buffer[1024]; - - FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - GetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */ - (LPTSTR)buffer, - 1023, NULL); - return buffer; -} -/*}}}*/ -static BOOL LockVolume( HANDLE hDisk ) /*{{{*/ -{ - DWORD ReturnedByteCount; - - return DeviceIoControl( hDisk, FSCTL_LOCK_VOLUME, NULL, 0, NULL, - 0, &ReturnedByteCount, NULL ); -} -/*}}}*/ -static BOOL UnlockVolume( HANDLE hDisk ) /*{{{*/ -{ - DWORD ReturnedByteCount; - - return DeviceIoControl( hDisk, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, - 0, &ReturnedByteCount, NULL ); -} -/*}}}*/ -static BOOL DismountVolume( HANDLE hDisk ) /*{{{*/ -{ - DWORD ReturnedByteCount; - - return DeviceIoControl( hDisk, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, - 0, &ReturnedByteCount, NULL ); -} -/*}}}*/ -static int GetDriveParams( HANDLE hVWin32Device, int volume, DRIVEPARAMS* pParam ) /*{{{*/ - { - DIOC_REGISTERS reg; - BOOL bResult; - DWORD cb; - - reg.reg_EAX = 0x440d; /* IOCTL for block device */ - reg.reg_EBX = volume; /* one-based drive number */ - reg.reg_ECX = 0x0860; /* Get Device params */ - reg.reg_EDX = (DWORD)pParam; - reg.reg_Flags = 1; /* preset the carry flag */ - - bResult = DeviceIoControl( hVWin32Device, VWIN32_DIOC_DOS_IOCTL, - ®, sizeof( reg ), ®, sizeof( reg ), &cb, 0 ); - - if ( !bResult || (reg.reg_Flags & 1) ) - return (reg.reg_EAX & 0xffff); - - return 0; - } -/*}}}*/ -static int SetDriveParams( HANDLE hVWin32Device, int volume, DRIVEPARAMS* pParam ) /*{{{*/ - { - DIOC_REGISTERS reg; - BOOL bResult; - DWORD cb; - - reg.reg_EAX = 0x440d; /* IOCTL for block device */ - reg.reg_EBX = volume; /* one-based drive number */ - reg.reg_ECX = 0x0840; /* Set Device params */ - reg.reg_EDX = (DWORD)pParam; - reg.reg_Flags = 1; /* preset the carry flag */ - - bResult = DeviceIoControl( hVWin32Device, VWIN32_DIOC_DOS_IOCTL, - ®, sizeof( reg ), ®, sizeof( reg ), &cb, 0 ); - - if ( !bResult || (reg.reg_Flags & 1) ) - return (reg.reg_EAX & 0xffff); - - return 0; - } -/*}}}*/ -static int GetMediaID( HANDLE hVWin32Device, int volume, MID* pMid ) /*{{{*/ - { - DIOC_REGISTERS reg; - BOOL bResult; - DWORD cb; - - reg.reg_EAX = 0x440d; /* IOCTL for block device */ - reg.reg_EBX = volume; /* one-based drive number */ - reg.reg_ECX = 0x0866; /* Get Media ID */ - reg.reg_EDX = (DWORD)pMid; - reg.reg_Flags = 1; /* preset the carry flag */ - - bResult = DeviceIoControl( hVWin32Device, VWIN32_DIOC_DOS_IOCTL, - ®, sizeof( reg ), ®, sizeof( reg ), &cb, 0 ); - - if ( !bResult || (reg.reg_Flags & 1) ) - return (reg.reg_EAX & 0xffff); - - return 0; - } -/*}}}*/ -static int VolumeCheck(HANDLE hVWin32Device, int volume, WORD* flags ) /*{{{*/ -{ - DIOC_REGISTERS reg; - BOOL bResult; - DWORD cb; - - reg.reg_EAX = 0x4409; /* Is Drive Remote */ - reg.reg_EBX = volume; /* one-based drive number */ - reg.reg_Flags = 1; /* preset the carry flag */ - - bResult = DeviceIoControl( hVWin32Device, VWIN32_DIOC_DOS_IOCTL, - ®, sizeof( reg ), ®, sizeof( reg ), &cb, 0 ); - - if ( !bResult || (reg.reg_Flags & 1) ) - return (reg.reg_EAX & 0xffff); - - *flags = (WORD)(reg.reg_EDX & 0xffff); - return 0; -} -/*}}}*/ -static int LockLogicalVolume(HANDLE hVWin32Device, int volume, int lock_level, int permissions) /*{{{*/ -{ - DIOC_REGISTERS reg; - BOOL bResult; - DWORD cb; - - reg.reg_EAX = 0x440d; /* generic IOCTL */ - reg.reg_ECX = 0x084a; /* lock logical volume */ - reg.reg_EBX = volume | (lock_level << 8); - reg.reg_EDX = permissions; - reg.reg_Flags = 1; /* preset the carry flag */ - - bResult = DeviceIoControl( hVWin32Device, VWIN32_DIOC_DOS_IOCTL, - ®, sizeof( reg ), ®, sizeof( reg ), &cb, 0 ); - - if ( !bResult || (reg.reg_Flags & 1) ) - return (reg.reg_EAX & 0xffff); - - return 0; -} -/*}}}*/ -static int UnlockLogicalVolume( HANDLE hVWin32Device, int volume ) /*{{{*/ -{ - DIOC_REGISTERS reg; - BOOL bResult; - DWORD cb; - - reg.reg_EAX = 0x440d; - reg.reg_ECX = 0x086a; /* lock logical volume */ - reg.reg_EBX = volume; - reg.reg_Flags = 1; /* preset the carry flag */ - - bResult = DeviceIoControl( hVWin32Device, VWIN32_DIOC_DOS_IOCTL, - ®, sizeof( reg ), ®, sizeof( reg ), &cb, 0 ); - - if ( !bResult || (reg.reg_Flags & 1) ) return -1; - return 0; -} -/*}}}*/ -static int w32mode(int mode) /*{{{*/ -{ - switch(mode) - { - case O_RDONLY: return GENERIC_READ; - case O_WRONLY: return GENERIC_WRITE; - } - return GENERIC_READ | GENERIC_WRITE; -} -/*}}}*/ - -/* Device_open -- Open an image file */ /*{{{*/ -const char *Device_open(struct Device *sb, const char *filename, int mode, const char *deviceOpts) -{ - /* Windows 95/NT: floppy drives using handles */ - if (strlen(filename) == 2 && filename[1] == ':') /* Drive name */ - { - char vname[20]; - DWORD dwVers; - - sb->fd = -1; - dwVers = GetVersion(); - - if (dwVers & 0x80000000L) /* Win32s (3.1) or Win32c (Win95) */ - { - int lock, driveno, res, permissions; - unsigned short drive_flags; - MID media; - - vname[0] = toupper(filename[0]); - driveno = vname[0] - 'A' + 1; /* 1=A: 2=B: */ - sb->drvtype = CPMDRV_WIN95; - sb->hdisk = CreateFile( "\\\\.\\vwin32", - 0, - 0, - NULL, - 0, - FILE_FLAG_DELETE_ON_CLOSE, - NULL ); - if (!sb->hdisk) - { - return "Failed to open VWIN32 driver."; - } - if (VolumeCheck(sb->hdisk, driveno, &drive_flags)) - { - CloseHandle(sb->hdisk); - return "Invalid drive"; - } - res = GetMediaID( sb->hdisk, driveno, &media ); - if ( res ) - { - const char *lboo = NULL; - - if ( res == ERROR_INVALID_FUNCTION && - (drive_flags & DRIVE_IS_REMOTE )) - lboo = "Network drive"; - else if (res == ERROR_ACCESS_DENIED) lboo = "Access denied"; - /* nb: It's perfectly legitimate for GetMediaID() to fail; most CP/M */ - /* CP/M disks won't have a media ID. */ - - if (lboo != NULL) - { - CloseHandle(sb->hdisk); - return lboo; - } - } - if (!res && - (!memcmp( media.midFileSysType, "CDROM", 5 ) || - !memcmp( media.midFileSysType, "CD001", 5 ) || - !memcmp( media.midFileSysType, "CDAUDIO", 5 ))) - { - CloseHandle(sb->hdisk); - return "CD-ROM drive"; - } - if (w32mode(mode) & GENERIC_WRITE) - { - lock = LEVEL0_LOCK; /* Exclusive access */ - permissions = 0; - } - else - { - lock = LEVEL1_LOCK; /* Allow other processes access */ - permissions = LEVEL1_LOCK_MAX_PERMISSION; - } - if (LockLogicalVolume( sb->hdisk, driveno, lock, permissions)) - { - CloseHandle(sb->hdisk); - return "Could not acquire a lock on the drive."; - } - - sb->fd = driveno; /* 1=A: 2=B: etc - we will need this later */ - - } - else - { - sprintf(vname, "\\\\.\\%s", filename); - sb->drvtype = CPMDRV_WINNT; - sb->hdisk = CreateFile(vname, /* Name */ - w32mode(mode), /* Access mode */ - FILE_SHARE_READ|FILE_SHARE_WRITE, /*Sharing*/ - NULL, /* Security attributes */ - OPEN_EXISTING, /* See MSDN */ - 0, /* Flags & attributes */ - NULL); /* Template file */ - - if (sb->hdisk != INVALID_HANDLE_VALUE) - { - sb->fd = 1; /* Arbitrary value >0 */ - if (LockVolume(sb->hdisk) == FALSE) /* Lock drive */ - { - char *lboo = strwin32error(); - CloseHandle(sb->hdisk); - sb->fd = -1; - return lboo; - } - } - else return strwin32error(); - } - sb->opened = 1; - return NULL; - } - - /* Not a floppy. Treat it as a normal file */ - - mode |= O_BINARY; - sb->fd = open(filename, mode); - if (sb->fd == -1) return strerror(errno); - sb->drvtype = CPMDRV_FILE; - sb->opened = 1; - return NULL; -} -/*}}}*/ -/* Device_setGeometry -- Set disk geometry */ /*{{{*/ -const char * Device_setGeometry(struct Device *this, int secLength, int sectrk, int tracks, off_t offset, const char *libdskGeometry) -{ - int n; - - this->secLength=secLength; - this->sectrk=sectrk; - this->tracks=tracks; - // Bill Buckels - add this->offset - this->offset=offset; - - - // Bill Buckels - not sure what to do here - if (this->drvtype == CPMDRV_WIN95) - { - DRIVEPARAMS drvp; - memset(&drvp, 0, sizeof(drvp)); - if (GetDriveParams( this->hdisk, this->fd, &drvp )) return "GetDriveParams failed"; - - drvp.bytespersector = secLength; - drvp.sectorspertrack = sectrk; - drvp.totalsectors = sectrk * tracks; - -/* Guess the cylinder/head configuration from the track count. This will - * get single-sided 80-track discs wrong, but it's that or double-sided - * 40-track (or add cylinder/head counts to diskdefs) - */ - if (tracks < 44) - { - drvp.cylinders = tracks; - drvp.heads = 1; - } - else - { - drvp.cylinders = tracks / 2; - drvp.heads = 2; - } - -/* Set up "reasonable" values for the other members */ - - drvp.sectorspercluster = 1024 / secLength; - drvp.reservedsectors = 1; - drvp.numberofFATs = 2; - drvp.sectorcount = sectrk; - drvp.rootdirsize = 64; - drvp.mediaid = 0xF0; - drvp.hiddensectors = 0; - drvp.sectorsperfat = 3; - for (n = 0; n < sectrk; n++) - { - drvp.sectortable[n*2] = n + PHYSICAL_SECTOR_1; /* Physical sector numbers */ - drvp.sectortable[n*2+1] = secLength; - } - drvp.special = 6; -/* We have not set: - - drvp.mediatype - drvp.devicetype - drvp.deviceattrs - - which should have been read correctly by GetDriveParams(). - */ - SetDriveParams( this->hdisk, this->fd, &drvp ); - } - return NULL; -} -/*}}}*/ -/* Device_close -- Close an image file */ /*{{{*/ -const char *Device_close(struct Device *sb) -{ - sb->opened = 0; - switch(sb->drvtype) - { - case CPMDRV_WIN95: - UnlockLogicalVolume(sb->hdisk, sb->fd ); - if (!CloseHandle( sb->hdisk )) return strwin32error(); - return NULL; - - case CPMDRV_WINNT: - DismountVolume(sb->hdisk); - UnlockVolume(sb->hdisk); - if (!CloseHandle(sb->hdisk)) return strwin32error(); - return NULL; - } - if (close(sb->fd)) return strerror(errno); - return NULL; -} -/*}}}*/ -/* Device_readSector -- read a physical sector */ /*{{{*/ -const char *Device_readSector(const struct Device *drive, int track, int sector, char *buf) -{ - int res; - off_t offset; - - assert(sector>=0); - assert(sectorsectrk); - assert(track>=0); - assert(tracktracks); - - offset = ((sector+track*drive->sectrk)*drive->secLength); - - if (drive->drvtype == CPMDRV_WINNT) - { - LPVOID iobuffer; - DWORD bytesread; - - // Bill Buckels - add drive->offset - if (SetFilePointer(drive->hdisk, offset+drive->offset, NULL, FILE_BEGIN) == INVALID_FILE_SIZE) - { - return strwin32error(); - } - iobuffer = VirtualAlloc(NULL, drive->secLength, MEM_COMMIT, PAGE_READWRITE); - if (!iobuffer) - { - return strwin32error(); - } - res = ReadFile(drive->hdisk, iobuffer, drive->secLength, &bytesread, NULL); - if (!res) - { - char *lboo = strwin32error(); - VirtualFree(iobuffer, drive->secLength, MEM_RELEASE); - return lboo; - } - - memcpy(buf, iobuffer, drive->secLength); - VirtualFree(iobuffer, drive->secLength, MEM_RELEASE); - - if (bytesread < (unsigned)drive->secLength) - { - memset(buf + bytesread, 0, drive->secLength - bytesread); - } - return NULL; - } - - // Bill Buckels - not sure what to do here - if (drive->drvtype == CPMDRV_WIN95) - { - DIOC_REGISTERS reg; - BOOL bResult; - DWORD cb; - -#ifdef USE_INT13 - int cyl, head; - - if (drive->tracks < 44) { cyl = track; head = 0; } - else { cyl = track/2; head = track & 1; } - - reg.reg_EAX = 0x0201; /* Read 1 sector */ - reg.reg_EBX = (DWORD)buf; - reg.reg_ECX = (cyl << 8) | (sector + PHYSICAL_SECTOR_1); - reg.reg_EDX = (head << 8) | (drive->fd - 1); - reg.reg_Flags = 1; /* preset the carry flag */ - bResult = DeviceIoControl( drive->hdisk, VWIN32_DIOC_DOS_INT13, - ®, sizeof( reg ), ®, sizeof( reg ), &cb, 0 ); -#else - DISKIO di; - - reg.reg_EAX = drive->fd - 1; /* zero-based volume number */ - reg.reg_EBX = (DWORD)&di; - reg.reg_ECX = 0xffff; /* use DISKIO structure */ - reg.reg_Flags = 1; /* preset the carry flag */ - di.diStartSector = sector+track*drive->sectrk; - di.diSectors = 1; - di.diBuffer = (DWORD)buf; - bResult = DeviceIoControl( drive->hdisk, VWIN32_DIOC_DOS_INT25, - ®, sizeof( reg ), ®, sizeof( reg ), &cb, 0 ); - -#endif - if ( !bResult || (reg.reg_Flags & 1) ) - { - if (GetLastError()) return strwin32error(); - return "Unknown read error."; - } - return 0; - } - - // Bill Buckels - add drive->offset - if (lseek(drive->fd,offset+drive->offset,SEEK_SET)==-1) - { - return strerror(errno); - } - if ((res=read(drive->fd, buf, drive->secLength)) != drive->secLength) - { - if (res==-1) - { - return strerror(errno); - } - else memset(buf+res,0,drive->secLength-res); /* hit end of disk image */ - } - return NULL; -} -/*}}}*/ -/* Device_writeSector -- write physical sector */ /*{{{*/ -const char *Device_writeSector(const struct Device *drive, int track, int sector, const char *buf) -{ - off_t offset; - int res; - - assert(sector>=0); - assert(sectorsectrk); - assert(track>=0); - assert(tracktracks); - - offset = ((sector+track*drive->sectrk)*drive->secLength); - - if (drive->drvtype == CPMDRV_WINNT) - { - LPVOID iobuffer; - DWORD byteswritten; - - // Bill Buckels - add drive->offset - if (SetFilePointer(drive->hdisk, offset+drive->offset, NULL, FILE_BEGIN) == INVALID_FILE_SIZE) - { - return strwin32error(); - } - iobuffer = VirtualAlloc(NULL, drive->secLength, MEM_COMMIT, PAGE_READWRITE); - if (!iobuffer) - { - return strwin32error(); - } - memcpy(iobuffer, buf, drive->secLength); - res = WriteFile(drive->hdisk, iobuffer, drive->secLength, &byteswritten, NULL); - if (!res || (byteswritten < (unsigned)drive->secLength)) - { - char *lboo = strwin32error(); - VirtualFree(iobuffer, drive->secLength, MEM_RELEASE); - return lboo; - } - - VirtualFree(iobuffer, drive->secLength, MEM_RELEASE); - return NULL; - } - - // Bill Buckels - not sure what to do here - if (drive->drvtype == CPMDRV_WIN95) - { - DIOC_REGISTERS reg; - BOOL bResult; - DWORD cb; - -#ifdef USE_INT13 - int cyl, head; - - if (drive->tracks < 44) { cyl = track; head = 0; } - else { cyl = track/2; head = track & 1; } - - reg.reg_EAX = 0x0301; /* Write 1 sector */ - reg.reg_EBX = (DWORD)buf; - reg.reg_ECX = (cyl << 8) | (sector + PHYSICAL_SECTOR_1); - reg.reg_EDX = (head << 8) | (drive->fd - 1); - reg.reg_Flags = 1; /* preset the carry flag */ - bResult = DeviceIoControl( drive->hdisk, VWIN32_DIOC_DOS_INT13, - ®, sizeof( reg ), ®, sizeof( reg ), &cb, 0 ); -#else - DISKIO di; - - reg.reg_EAX = drive->fd - 1; /* zero-based volume number */ - reg.reg_EBX = (DWORD)&di; - reg.reg_ECX = 0xffff; /* use DISKIO structure */ - reg.reg_Flags = 1; /* preset the carry flag */ - di.diStartSector = sector+track*drive->sectrk; - di.diSectors = 1; - di.diBuffer = (DWORD)buf; - bResult = DeviceIoControl( drive->hdisk, VWIN32_DIOC_DOS_INT26, - ®, sizeof( reg ), ®, sizeof( reg ), &cb, 0 ); -#endif - - if ( !bResult || (reg.reg_Flags & 1) ) - { - if (GetLastError()) return strwin32error(); - return "Unknown write error."; - } - return NULL; - } - - // Bill Buckels - add drive->offset - if (lseek(drive->fd,offset+drive->offset, SEEK_SET)==-1) - { - return strerror(errno); - } - if (write(drive->fd, buf, drive->secLength) == drive->secLength) return NULL; - return strerror(errno); -} -/*}}}*/