mirror of
https://github.com/peteratebs/rtfsprorelease.git
synced 2025-06-19 01:05:39 -04:00
922 lines
33 KiB
C
922 lines
33 KiB
C
/*
|
|
* EBS - RTFS (Real Time File Manager)
|
|
*
|
|
* Copyright EBS Inc. 1993-2005
|
|
* All rights reserved.
|
|
* This code may not be redistributed in source or linkable object form
|
|
* without the consent of its author.
|
|
*/
|
|
/* drwindev.c - Access windows XP block devices directly
|
|
|
|
Summary
|
|
|
|
Description
|
|
Provides a device driver that reads and writes data to devices
|
|
mounted under Windows XP such as the system's hard disk or removable
|
|
devices sdcard, compact flash, a usb drive or floppy disk.
|
|
|
|
*/
|
|
|
|
// Use this to force exact match on disk size for format testing otherwise the vaules returned from Windows are used.
|
|
// Required for format testing because windows does not return exact correct values
|
|
// #define FORCE_LBAVALUE (0x77B0000 + 0x8000) // 64 GB SDXC card
|
|
// #define FORCE_LBAVALUE (0x58F8000) // 48 GB SDXC card
|
|
// #define FORCE_LBAVALUE (0x77B0000 + 0x8000) // 64 GB SDXC card
|
|
// #define FORCE_LBAVALUE (0xED4000) /* 8 gig */
|
|
// #define FORCE_LBAVALUE (0xED4000/2) /* 4 gig */
|
|
// #define FORCE_LBAVALUE (0xED4000/4) /* 2 gig */
|
|
|
|
#ifdef _MSC_VER
|
|
#define _WIN32_WINNT 0x0600
|
|
#include <windows.h>
|
|
#include <winioctl.h>
|
|
#include <stdio.h>
|
|
#include "rtfs.h"
|
|
/* windev - Device driver that acceses XP devices directly */
|
|
#include <stdio.h>
|
|
#include <io.h>
|
|
#include <fcntl.h>
|
|
#include <sys\types.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#else
|
|
#include "rtfs.h"
|
|
#define HOST_INVALID_HANDLE_VALUE -1
|
|
#define HOST_HANDLE int
|
|
|
|
#endif
|
|
|
|
#if (INCLUDE_WINDEV)
|
|
|
|
#define HOST_INVALID_HANDLE_VALUE INVALID_HANDLE_VALUE
|
|
#define HOST_HANDLE HANDLE
|
|
|
|
|
|
// interval to check media presence
|
|
#define WINDOWS_WINDEV_SPRINTF sprintf
|
|
#define MAX_WINDEV_DEVICES 10
|
|
|
|
//if you do not want non-removable media to be accessible for safety reasons set this to 1
|
|
#define REMOVABLE_MEDIA_ONLY 0
|
|
|
|
int num_windev_devices = -1;
|
|
struct windev_device {
|
|
int device_number; // windev_device_names[device_number] is device name
|
|
HOST_HANDLE hDevice;
|
|
BOOLEAN media_installed;
|
|
int num_partitions;
|
|
char *partition_names[26];
|
|
DEV_GEOMETRY gc; /* RTFS Geometry structure */
|
|
BOOLEAN is_removable;
|
|
dword bytes_per_sector;
|
|
unsigned long long mediasize;
|
|
int driveno; // which drive we're associated with
|
|
int logical_unit_number; // assign logical uint number (index in map_lun_to_windev_devices[] */
|
|
};
|
|
struct windev_device windev_devices[MAX_WINDEV_DEVICES];
|
|
struct windev_device *currentDevice;
|
|
struct windev_device *map_lun_to_windev_devices[MAX_WINDEV_DEVICES];
|
|
|
|
|
|
static int BLK_DEV_VIRT_blkmedia_io(void *devhandle, void *pdrive, dword sector, void *buffer, dword count, BOOLEAN reading);
|
|
static int BLK_DEV_VIRT_device_configure_volume(struct rtfs_volume_resource_request *prequest_block, struct rtfs_volume_resource_reply *pvolume_config_block);
|
|
static int BLK_DEV_VIRT_blkmedia_ioctl(void *devhandle, void *pdrive, int opcode, int iArgs, void *vargs);
|
|
static int BLK_DEV_VIRT_device_configure_media(struct rtfs_media_insert_args *pmedia_parms, struct rtfs_media_resource_reply *pmedia_config_block, int sector_buffer_required);
|
|
static void insert_win_device_to_rtfs(struct windev_device *pdevice);
|
|
|
|
char print_buffer[128];
|
|
|
|
/*
|
|
*
|
|
* Perform io to and from the win dev disk.
|
|
*
|
|
* If the reading flag is true copy data from the hostdisk (read).
|
|
* else copy to the hostdisk. (write).
|
|
*
|
|
*/
|
|
|
|
// public function prototypes
|
|
BOOLEAN windev_io(int driveno, dword block, void *buffer, word count, BOOLEAN reading);
|
|
int windev_perform_device_ioctl(int driveno, int opcode, void * pargs);
|
|
|
|
// private function prototypes
|
|
static BOOLEAN win_dev_seek(int logical_unit_number, dword block);
|
|
static BOOLEAN win_dev_write(int logical_unit_number, void *buffer, word count);
|
|
static BOOLEAN win_dev_read(int logical_unit_number, void *buffer, word count);
|
|
//static BOOLEAN win_dev_check_change(int logical_unit_number);
|
|
static BOOLEAN win_dev_enum_devices(void);
|
|
static HOST_HANDLE map_win_logical_unit(int logical_unit_number);
|
|
static int win_select_device_for_lun(int logical_unit_number);
|
|
static BOOLEAN win_dev_get_layout(HOST_HANDLE hDevice,int device_number,struct windev_device *pdevice_info);
|
|
|
|
static int media_is_writable=0;
|
|
static int driver_is_initialized=0;
|
|
|
|
int show_block_reads = 0;
|
|
dword break_on = 0xffffffff;
|
|
BOOLEAN windev_io(int driveno, dword block, void *buffer, word count, BOOLEAN reading) /*__fn__*/
|
|
{
|
|
DDRIVE *pdr;
|
|
BOOLEAN ret_val;
|
|
pdr = pc_drno_to_drive_struct(driveno);
|
|
if (!pdr)
|
|
return(FALSE);
|
|
#if (0)
|
|
if (reading)
|
|
{
|
|
printf("Reading sector %d to %d \n", block, block+count-1);
|
|
}
|
|
else
|
|
{
|
|
|
|
printf("Writing sector %d to %d \n", block, block+count-1);
|
|
}
|
|
#endif
|
|
if (!win_dev_seek(pdr->logical_unit_number, block))
|
|
{
|
|
//ERTFS_ASSERT(rtfs_debug_zero())
|
|
return(FALSE);
|
|
}
|
|
if (reading)
|
|
ret_val = win_dev_read(pdr->logical_unit_number, buffer, count);
|
|
else
|
|
{
|
|
if (!media_is_writable)
|
|
{
|
|
if (block==0 && (*(((byte *)buffer)+510) == 0x66 && *(((byte *)buffer)+511) == 0xAA))
|
|
{
|
|
printf("Writing invalid signature to media to make it writable\n");
|
|
printf("You must remove and re-insert the media before you can write\n\
|
|
To it ..... \n");
|
|
}
|
|
else
|
|
{
|
|
printf("Rtfs tried to write to write protected media\n");
|
|
printf("Use the HACKWIN7 shell command to make it writable with Rtfs or..\n");
|
|
printf("Failsafe may be trying to create a journal\n");
|
|
printf("Re-start Rtfs with Failsafe AUTO disabled\n");
|
|
return FALSE;
|
|
}
|
|
}
|
|
ret_val = win_dev_write(pdr->logical_unit_number, buffer, count);
|
|
}
|
|
if (reading && block==0)
|
|
{
|
|
if (*(((byte *)buffer)+510) == 0x66 && *(((byte *)buffer)+511) == 0xAA)
|
|
{
|
|
printf("The media is writable with Rtfs but not visible to Windows\n");
|
|
printf("Use the HACKWIN7 shell command to make it visible to windows\n");
|
|
media_is_writable=1;
|
|
if (reading)
|
|
*((byte *)buffer+510) = 0x55;
|
|
}
|
|
else if (*(((byte *)buffer)+510) == 0x55 && *(((byte *)buffer)+511) == 0xAA)
|
|
{
|
|
printf("The media is readable with Rtfs and visible to Windows\n");
|
|
printf("Use the HACKWIN7 shell command to make it writable with Rtfs\n");
|
|
printf("Use the HACKWIN7 again to make it visible to windows\n");
|
|
media_is_writable=0;
|
|
}
|
|
}
|
|
return ret_val;
|
|
}
|
|
|
|
/**
|
|
* This function "inserts" a windows device into the rtfs system. If this is not called the device may be
|
|
* inserted but RTFS will not be aware of it.
|
|
*/
|
|
static void insert_win_device_to_rtfs(struct windev_device *pdevice){
|
|
/* Set up mount parameters and call Rtfs to mount the device */
|
|
extern int show_block_reads;
|
|
struct rtfs_media_insert_args rtfs_insert_parms;
|
|
/* register with Rtfs File System */
|
|
rtfs_insert_parms.devhandle = (void*)pdevice; /* Not used just a handle */
|
|
rtfs_insert_parms.device_type = 999; /* not used because private versions of configure and release, but must be non zero */
|
|
rtfs_insert_parms.unit_number = 0;
|
|
|
|
rtfs_insert_parms.numheads = pdevice->gc.dev_geometry_heads;
|
|
rtfs_insert_parms.secptrk = pdevice->gc.dev_geometry_secptrack;
|
|
rtfs_insert_parms.numcyl = pdevice->gc.dev_geometry_cylinders;
|
|
rtfs_insert_parms.media_size_sectors = pdevice->gc.dev_geometry_lbas;
|
|
|
|
rtfs_insert_parms.sector_size_bytes = (dword) 512;
|
|
rtfs_insert_parms.eraseblock_size_sectors = 0;
|
|
rtfs_insert_parms.write_protect = 0;
|
|
|
|
rtfs_insert_parms.device_io = BLK_DEV_VIRT_blkmedia_io;
|
|
rtfs_insert_parms.device_ioctl = BLK_DEV_VIRT_blkmedia_ioctl;
|
|
rtfs_insert_parms.device_erase = 0;
|
|
rtfs_insert_parms.device_configure_media = BLK_DEV_VIRT_device_configure_media;
|
|
rtfs_insert_parms.device_configure_volume = BLK_DEV_VIRT_device_configure_volume;
|
|
|
|
pc_rtfs_media_insert(&rtfs_insert_parms);
|
|
}
|
|
|
|
/*
|
|
* Remove the device from Rtfs and label it not installed so that other drives may insert it to Rtfs
|
|
*/
|
|
static void win_device_remove_event(struct windev_device *pdevice_info)
|
|
{
|
|
pdevice_info->media_installed = 0;
|
|
pc_rtfs_media_alert((void*)pdevice_info,RTFS_ALERT_EJECT,NULL);
|
|
}
|
|
|
|
|
|
HOST_HANDLE map_win_logical_unit(int logical_unit_number)
|
|
{
|
|
if (map_lun_to_windev_devices[logical_unit_number])
|
|
{
|
|
return(map_lun_to_windev_devices[logical_unit_number]->hDevice);
|
|
}
|
|
return(HOST_INVALID_HANDLE_VALUE);
|
|
}
|
|
|
|
//void dismount_win_device(void *devhandle)
|
|
//{
|
|
// shutdown_win_device(devhandle);
|
|
//}
|
|
|
|
// these defines will probably need to be changed
|
|
#define USE_DYNAMIC_ALLOCATION 1
|
|
|
|
#define DEFAULT_OPERATING_POLICY 0
|
|
#define DEFAULT_NUM_SECTOR_BUFFERS 10
|
|
#define DEFAULT_NUM_FAT_BUFFERS 2
|
|
#define DEFAULT_FATBUFFER_PAGESIZE_SECTORS 8
|
|
|
|
#define DEFAULT_NUM_FILE_BUFFERS 0
|
|
#define DEFAULT_FILE_BUFFER_SIZE_SECTORS 0
|
|
|
|
#define DEFAULT_FAILSAFE_RESTORE_BUFFERSIZE_SECTORS 64
|
|
#define DEFAULT_NUM_FAILSAFE_BLOCKMAPS 1024
|
|
#define DEFAULT_FAILSAFE_INDEX_BUFFERSIZE_SECTORS 128
|
|
|
|
static byte windevdisk_sectorbuffer[512];
|
|
|
|
#if(!USE_DYNAMIC_ALLOCATION)
|
|
|
|
/* === pparms->blkbuff_memory one for each sector buffer */
|
|
static BLKBUFF _blkbuff_memory[DEFAULT_NUM_SECTOR_BUFFERS];
|
|
static byte _sector_buffer_memory[DEFAULT_NUM_SECTOR_BUFFERS*512];
|
|
|
|
/* === pparms->fatbuff_memory one for each FAT page */
|
|
static FATBUFF _fatbuff_memory[DEFAULT_NUM_FAT_BUFFERS];
|
|
static byte _fat_buffer_memory[DEFAULT_NUM_FAT_BUFFERS*512];
|
|
static byte windevdisk_sectorbuffer
|
|
|
|
|
|
|
|
#if (INCLUDE_FAILSAFE_CODE)
|
|
static FAILSAFECONTEXT fs_context;
|
|
static byte fs_buffer[DEFAULT_FAILSAFE_RESTORE_BUFFERSIZE_SECTORS*512]; /*(512(sector_size) * 64(DEFAULT_FAILSAFE_RESTORE_BUFFERSIZE_SECTORS)) */
|
|
static byte fs_index_buffer[DEFAULT_FAILSAFE_INDEX_BUFFERSIZE_SECTORS*512]; /*(512(sector_size) * 64(DEFAULT_FAILSAFE_RESTORE_BUFFERSIZE_SECTORS)) */
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
/* IO routine installed by BLK_DEV_hostdisk_Mount */
|
|
static int BLK_DEV_VIRT_blkmedia_io(void *devhandle, void *pdrive, dword sector, void *buffer, dword count, BOOLEAN reading)
|
|
{
|
|
RTFS_ARGSUSED_PVOID(devhandle);
|
|
RTFS_ARGSUSED_PVOID(pdrive);
|
|
return(windev_io(((DDRIVE*)pdrive)->driveno, sector, buffer, (word)count, reading));
|
|
}
|
|
|
|
static int BLK_DEV_VIRT_blkmedia_ioctl(void *devhandle, void *pdrive, int opcode, int iArgs, void *vargs)
|
|
{
|
|
|
|
RTFS_ARGSUSED_INT(iArgs);
|
|
RTFS_ARGSUSED_PVOID(vargs);
|
|
switch(opcode)
|
|
{
|
|
case RTFS_IOCTL_FORMAT:
|
|
break;
|
|
case RTFS_IOCTL_INITCACHE:
|
|
case RTFS_IOCTL_FLUSHCACHE:
|
|
break;
|
|
}
|
|
return(0);
|
|
|
|
}
|
|
|
|
static int BLK_DEV_VIRT_device_configure_media(struct rtfs_media_insert_args *pmedia_parms, struct rtfs_media_resource_reply *pmedia_config_block, int sector_buffer_required)
|
|
{
|
|
|
|
pmedia_config_block->requested_driveid = (int) ('P'-'A');
|
|
pmedia_config_block->requested_max_partitions = 2;
|
|
pmedia_config_block->use_fixed_drive_id = 1;
|
|
/* June 2013 - this was incorrect */
|
|
/* pmedia_config_block->device_sector_buffer_size_bytes = 64; */
|
|
|
|
if (sector_buffer_required)
|
|
pmedia_config_block->device_sector_buffer_size_bytes = 64*512;
|
|
/* June 2013 - this was incorrect */
|
|
/* pmedia_config_block->device_sector_buffer_size_bytes = pmedia_parms->sector_size_bytes * pmedia_parms->eraseblock_size_sectors; */
|
|
#if(USE_DYNAMIC_ALLOCATION == 0)
|
|
#error - Fix me..
|
|
#else
|
|
pmedia_config_block->use_dynamic_allocation = 1;
|
|
#endif
|
|
/* 0 if successful
|
|
-1 if unsupported device type
|
|
-2 if out of resources
|
|
*/
|
|
return(0);
|
|
}
|
|
#if (INCLUDE_FAILSAFE_CODE)
|
|
/* In evaluation mode this flag instructs host disk and host dev device drivers whether to
|
|
autoenable falisafe */
|
|
extern BOOLEAN auto_failsafe_mode;
|
|
#endif
|
|
static int BLK_DEV_VIRT_device_configure_volume(struct rtfs_volume_resource_request *prequest_block, struct rtfs_volume_resource_reply *pvolume_config_block)
|
|
{
|
|
|
|
#if (INCLUDE_FAILSAFE_CODE)
|
|
if (!auto_failsafe_mode)
|
|
pvolume_config_block->drive_operating_policy =DRVPOL_DISABLE_AUTOFAILSAFE;
|
|
else
|
|
#endif
|
|
pvolume_config_block->drive_operating_policy = DEFAULT_OPERATING_POLICY;
|
|
pvolume_config_block->n_sector_buffers = DEFAULT_NUM_SECTOR_BUFFERS;
|
|
pvolume_config_block->n_fat_buffers = DEFAULT_NUM_FAT_BUFFERS;
|
|
pvolume_config_block->fat_buffer_page_size_sectors = DEFAULT_FATBUFFER_PAGESIZE_SECTORS;
|
|
pvolume_config_block->n_file_buffers = DEFAULT_NUM_FILE_BUFFERS;
|
|
pvolume_config_block->file_buffer_size_sectors = DEFAULT_FILE_BUFFER_SIZE_SECTORS;
|
|
if (prequest_block->failsafe_available)
|
|
{
|
|
pvolume_config_block->fsrestore_buffer_size_sectors = DEFAULT_FAILSAFE_RESTORE_BUFFERSIZE_SECTORS;
|
|
pvolume_config_block->fsindex_buffer_size_sectors = DEFAULT_FAILSAFE_INDEX_BUFFERSIZE_SECTORS;
|
|
pvolume_config_block->fsjournal_n_blockmaps = DEFAULT_NUM_FAILSAFE_BLOCKMAPS;
|
|
#if (INCLUDE_FAILSAFE_CODE)
|
|
#if(USE_DYNAMIC_ALLOCATION == 0)
|
|
pvolume_config_block->fsfailsafe_context_memory = &fs_context;
|
|
pvolume_config_block->failsafe_buffer_memory = &fs_buffer[0];
|
|
pvolume_config_block->failsafe_indexbuffer_memory = &fs_index_buffer[0];
|
|
#endif
|
|
#endif
|
|
}
|
|
/* Tell Rtfs to dynamically allocate buffers */
|
|
#if(USE_DYNAMIC_ALLOCATION)
|
|
pvolume_config_block->use_dynamic_allocation = 1;
|
|
#else
|
|
pvolume_config_block->blkbuff_memory = &_blkbuff_memory[0];
|
|
pvolume_config_block->fatbuff_memory = &_fatbuff_memory[0];
|
|
pvolume_config_block->sector_buffer_memory = (void *) &_sector_buffer_memory[0];
|
|
pvolume_config_block->fat_buffer_memory = (void *) &_fat_buffer_memory[0];
|
|
#endif
|
|
|
|
return(0);
|
|
}
|
|
static void PollDeviceReady(void);
|
|
/**
|
|
* This is an initialization routine for the windows driver for Rtfs.
|
|
*/
|
|
static RTFS_DEVI_POLL_REQUEST_VECTOR poll_device_vector_storage;
|
|
BOOLEAN BLK_DEV_windev_Mount(void)
|
|
{
|
|
#if(!REMOVABLE_MEDIA_ONLY)
|
|
printf("Mounting WINDEV DRIVER on P:\n\n");
|
|
printf("WARNING: REMOVABLE_MEDIA_ONLY is not set. All drives will be accessable, please be careful what you write to.\n\n");
|
|
#else
|
|
printf("Mounting WINDEV DRIVER on P:\n\n");
|
|
printf("REMOVABLE_MEDIA_ONLY is set. Only removable media will be accessable.\n\n");
|
|
#endif
|
|
driver_is_initialized=1;
|
|
pc_rtfs_register_poll_devices_ready_handler(&poll_device_vector_storage, PollDeviceReady);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
#ifdef _MSC_VER
|
|
|
|
|
|
|
|
|
|
|
|
BOOLEAN win_dev_seek(int logical_unit_number, dword block)
|
|
{
|
|
LARGE_INTEGER liDistanceToMove;
|
|
LARGE_INTEGER NewFilePointer;
|
|
HOST_HANDLE hDevice;
|
|
hDevice = map_win_logical_unit(logical_unit_number);
|
|
|
|
if (hDevice == HOST_INVALID_HANDLE_VALUE)
|
|
return(FALSE);
|
|
|
|
|
|
liDistanceToMove.QuadPart = block;
|
|
liDistanceToMove.QuadPart *= 512;
|
|
hDevice = map_win_logical_unit(logical_unit_number);
|
|
|
|
if (!SetFilePointerEx(hDevice,
|
|
liDistanceToMove,
|
|
&NewFilePointer,
|
|
FILE_BEGIN) )
|
|
{
|
|
ERTFS_ASSERT(rtfs_debug_zero())
|
|
return(FALSE);
|
|
}
|
|
if (liDistanceToMove.QuadPart != NewFilePointer.QuadPart)
|
|
{
|
|
ERTFS_ASSERT(rtfs_debug_zero())
|
|
return(FALSE);
|
|
}
|
|
return(TRUE);
|
|
}
|
|
|
|
BOOLEAN win_dev_write(int logical_unit_number, void *buffer, word count)
|
|
{
|
|
unsigned long n_to_write;
|
|
unsigned long bytes_written;
|
|
HOST_HANDLE hDevice;
|
|
hDevice = map_win_logical_unit(logical_unit_number);
|
|
|
|
// printf("Not writing.. U crazy \n");
|
|
// if (1)
|
|
// return(FALSE);
|
|
if (hDevice == HOST_INVALID_HANDLE_VALUE)
|
|
return(FALSE);
|
|
|
|
n_to_write = (unsigned long) count;
|
|
n_to_write *= 512;
|
|
if (!WriteFile(hDevice,
|
|
buffer,
|
|
n_to_write,
|
|
&bytes_written,
|
|
NULL))
|
|
{
|
|
|
|
ERTFS_ASSERT(rtfs_debug_zero())
|
|
return(FALSE);
|
|
}
|
|
if (n_to_write != bytes_written)
|
|
{
|
|
ERTFS_ASSERT(rtfs_debug_zero())
|
|
return(FALSE);
|
|
}
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
BOOLEAN win_dev_read(int logical_unit_number, void *buffer, word count)
|
|
{
|
|
unsigned long n_to_read;
|
|
unsigned long bytes_read;
|
|
HOST_HANDLE hDevice;
|
|
hDevice = map_win_logical_unit(logical_unit_number);
|
|
if (hDevice == HOST_INVALID_HANDLE_VALUE)
|
|
return(FALSE);
|
|
n_to_read = (unsigned long) count;
|
|
n_to_read *= 512;
|
|
|
|
if (!ReadFile(hDevice,
|
|
buffer,
|
|
n_to_read,
|
|
&bytes_read,
|
|
NULL))
|
|
{
|
|
ERTFS_ASSERT(rtfs_debug_zero())
|
|
return(FALSE);
|
|
}
|
|
if (n_to_read != bytes_read)
|
|
{
|
|
ERTFS_ASSERT(rtfs_debug_zero())
|
|
return(FALSE);
|
|
}
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
char *windev_device_names[] =
|
|
{
|
|
"\\\\.\\PhysicalDrive0",
|
|
"\\\\.\\PhysicalDrive1",
|
|
"\\\\.\\PhysicalDrive2",
|
|
"\\\\.\\PhysicalDrive3",
|
|
"\\\\.\\PhysicalDrive4",
|
|
"\\\\.\\PhysicalDrive5",
|
|
"\\\\.\\PhysicalDrive6",
|
|
"\\\\.\\PhysicalDrive7",
|
|
"\\\\.\\PhysicalDrive8",
|
|
"\\\\.\\PhysicalDrive9",
|
|
};
|
|
|
|
|
|
static BOOL get_drive_geometry(HOST_HANDLE hDevice,struct windev_device *pdevice_info)
|
|
{
|
|
DISK_GEOMETRY dg;
|
|
BOOL bResult; /* results flag */
|
|
DWORD junk; /* discard results */
|
|
|
|
pdevice_info->gc.dev_geometry_heads = 0;
|
|
pdevice_info->gc.dev_geometry_cylinders = 0;
|
|
pdevice_info->gc.dev_geometry_secptrack = 0;
|
|
pdevice_info->gc.dev_geometry_lbas = 0;
|
|
pdevice_info->gc.fmt_parms_valid = 0;
|
|
|
|
if (0)
|
|
{
|
|
DISK_GEOMETRY_EX dg;
|
|
|
|
bResult = DeviceIoControl(hDevice, /* device to be queried */
|
|
IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, /* operation to perform */
|
|
NULL, 0, /* no input buffer */
|
|
&dg, sizeof(dg), /* output buffer */
|
|
&junk, /* # bytes returned */
|
|
(LPOVERLAPPED) NULL); /* synchronous I/O */
|
|
if (bResult)
|
|
{
|
|
pdevice_info->gc.dev_geometry_cylinders = (dword) dg.Geometry.Cylinders.LowPart;
|
|
pdevice_info->gc.dev_geometry_secptrack = (int) dg.Geometry.SectorsPerTrack;
|
|
pdevice_info->gc.dev_geometry_heads = (int) dg.Geometry.TracksPerCylinder;
|
|
pdevice_info->gc.dev_geometry_lbas = (dword)(dg.DiskSize.QuadPart/512);
|
|
printf("lbas by _ex method %d %X\n", pdevice_info->gc.dev_geometry_lbas, pdevice_info->gc.dev_geometry_lbas);
|
|
}
|
|
}
|
|
bResult = DeviceIoControl(hDevice, /* device to be queried */
|
|
IOCTL_DISK_GET_DRIVE_GEOMETRY, /* operation to perform */
|
|
NULL, 0, /* no input buffer */
|
|
&dg, sizeof(dg), /* output buffer */
|
|
&junk, /* # bytes returned */
|
|
(LPOVERLAPPED) NULL); /* synchronous I/O */
|
|
if (bResult)
|
|
{
|
|
pdevice_info->gc.dev_geometry_cylinders = (dword) dg.Cylinders.LowPart;
|
|
pdevice_info->gc.dev_geometry_secptrack = (int) dg.SectorsPerTrack;
|
|
pdevice_info->gc.dev_geometry_heads = (int) dg.TracksPerCylinder;
|
|
pdevice_info->gc.dev_geometry_lbas = (dword) (dg.Cylinders.LowPart * dg.TracksPerCylinder * dg.SectorsPerTrack);
|
|
pdevice_info->bytes_per_sector = dg.BytesPerSector;
|
|
#ifdef FORCE_LBAVALUE
|
|
printf("lbas by _hcn method %d %X\n", pdevice_info->gc.dev_geometry_lbas, pdevice_info->gc.dev_geometry_lbas);
|
|
pdevice_info->gc.dev_geometry_lbas = FORCE_LBAVALUE;
|
|
printf("Forced lbas to %d %X\n", pdevice_info->gc.dev_geometry_lbas, pdevice_info->gc.dev_geometry_lbas);
|
|
#endif
|
|
if (dg.MediaType == RemovableMedia)
|
|
pdevice_info->is_removable = TRUE;
|
|
else
|
|
pdevice_info->is_removable = FALSE;
|
|
}
|
|
|
|
return (bResult);
|
|
}
|
|
|
|
int device_is_fixed[MAX_WINDEV_DEVICES];
|
|
|
|
/**
|
|
* This function creates and maintains a list of devices that are currently attached to the computer and
|
|
* can be accessed. If a new device has been inserted then this function returns TRUE indicating that a
|
|
* change has occured. If REMOVABLE MEDIA ONLY is set then this function ignores media that is not removable.
|
|
*/
|
|
BOOLEAN win_dev_enum_devices()
|
|
{
|
|
int i;
|
|
HOST_HANDLE hDevice;
|
|
BOOLEAN retVal = FALSE;
|
|
DWORD dwBytesReturned=0;
|
|
//on the first run initialize all structures to a starting, invalid, state.
|
|
if(num_windev_devices == -1){
|
|
memset(map_lun_to_windev_devices, 0, sizeof(map_lun_to_windev_devices));
|
|
num_windev_devices = 0;
|
|
memset(windev_devices, 0, sizeof(windev_devices));
|
|
|
|
for (i = 0; i < MAX_WINDEV_DEVICES; i++)
|
|
{
|
|
windev_devices[i].hDevice = HOST_INVALID_HANDLE_VALUE;
|
|
windev_devices[i].media_installed = 0;
|
|
}
|
|
num_windev_devices = 0;
|
|
retVal = TRUE;
|
|
}
|
|
|
|
for(i = 0; i < MAX_WINDEV_DEVICES; i++){
|
|
|
|
if (device_is_fixed[i])
|
|
continue;
|
|
|
|
//if a device exists in the list but is no longer accesible the release the handle and invalidate the
|
|
//stucture
|
|
if(windev_devices[i].hDevice != HOST_INVALID_HANDLE_VALUE){
|
|
if (!DeviceIoControl(windev_devices[i].hDevice, IOCTL_STORAGE_CHECK_VERIFY, NULL, 0, NULL, 0,
|
|
&dwBytesReturned, NULL))
|
|
{
|
|
CloseHandle(windev_devices[i].hDevice);
|
|
windev_devices[i].hDevice = HOST_INVALID_HANDLE_VALUE;
|
|
num_windev_devices -= 1;
|
|
}
|
|
}
|
|
else{//else if a structure does not currenlty contain a device try to fill it with one
|
|
|
|
hDevice = CreateFile(windev_device_names[i], /* */
|
|
GENERIC_READ|GENERIC_WRITE, /* read write access to the drive */
|
|
FILE_SHARE_READ|FILE_SHARE_WRITE, /* share mode */
|
|
NULL, /* default security attributes */
|
|
OPEN_EXISTING, /* disposition */
|
|
FILE_FLAG_DELETE_ON_CLOSE|FILE_FLAG_NO_BUFFERING|FILE_FLAG_WRITE_THROUGH, /* file attributes */
|
|
NULL); /* do not copy file attributes */
|
|
if (hDevice != HOST_INVALID_HANDLE_VALUE)//if a new device exists
|
|
{
|
|
if (get_drive_geometry(hDevice,&windev_devices[num_windev_devices]))//get information about the device
|
|
{
|
|
#if(REMOVABLE_MEDIA_ONLY)
|
|
if(!windev_devices[num_windev_devices].is_removable){
|
|
CloseHandle(hDevice);
|
|
device_is_fixed[i] = 1;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
win_dev_get_layout(hDevice,i,&windev_devices[num_windev_devices]);
|
|
num_windev_devices += 1;
|
|
retVal = TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
return(retVal);
|
|
}
|
|
|
|
static BOOLEAN win_dev_get_layout(HOST_HANDLE hDevice,int device_number,struct windev_device *pdevice_info)
|
|
{
|
|
byte buffer[2048];
|
|
dword BytesReturned;
|
|
|
|
if (hDevice != HOST_INVALID_HANDLE_VALUE)
|
|
{
|
|
pdevice_info->hDevice = hDevice;
|
|
pdevice_info->device_number = device_number;
|
|
pdevice_info->num_partitions = 0;
|
|
|
|
if (!DeviceIoControl(hDevice,
|
|
IOCTL_DISK_GET_DRIVE_LAYOUT, /* dwIoControlCode */
|
|
NULL, /* lpInBuffer */
|
|
0, /* nInBufferSize */
|
|
(LPVOID) buffer, /* output buffer */
|
|
(DWORD) 2048, /* size of output buffer */
|
|
(LPDWORD) &BytesReturned, /* number of bytes returned */
|
|
NULL))
|
|
{
|
|
DWORD dw = GetLastError();
|
|
pdevice_info->media_installed = 0;
|
|
dw = GetLastError();
|
|
return(FALSE);
|
|
}
|
|
else
|
|
{
|
|
PDRIVE_LAYOUT_INFORMATION playout;
|
|
PPARTITION_INFORMATION ppartitions;
|
|
dword i;
|
|
pdevice_info->media_installed = 0;
|
|
|
|
playout = (PDRIVE_LAYOUT_INFORMATION) buffer;
|
|
ppartitions = playout->PartitionEntry;
|
|
pdevice_info->mediasize = playout->PartitionEntry->PartitionLength.QuadPart;
|
|
|
|
if (!ppartitions->RecognizedPartition)
|
|
{
|
|
pdevice_info->num_partitions = 1;
|
|
pdevice_info->partition_names[0] = "No partition table found.";
|
|
}
|
|
else
|
|
{
|
|
|
|
for (i = 0; i < playout->PartitionCount; i++, ppartitions++)
|
|
{
|
|
pdevice_info->num_partitions += 1;
|
|
|
|
switch(ppartitions->PartitionType)
|
|
{
|
|
case 1: /* PARTITION_FAT_12: */
|
|
pdevice_info->partition_names[i] = "A FAT12 file system partition. ";
|
|
break;
|
|
case 4: /* PARTITION_FAT_16: */
|
|
case 6:
|
|
pdevice_info->partition_names[i] = "A FAT16 file system partition. ";
|
|
break;
|
|
case 0xe:
|
|
case 0xc:
|
|
case 0x55:
|
|
case 0xb: /* PARTITION_FAT32: */
|
|
pdevice_info->partition_names[i] = "A FAT32 file system partition. ";
|
|
break;
|
|
case PARTITION_EXTENDED:
|
|
pdevice_info->partition_names[i] = "An extended partition. ";
|
|
break;
|
|
case PARTITION_IFS:
|
|
pdevice_info->partition_names[i] = "An IFS exFat partition. ";
|
|
break;
|
|
case PARTITION_LDM:
|
|
pdevice_info->partition_names[i] = "A logical disk manager (LDM) partition. ";
|
|
break;
|
|
case PARTITION_NTFT:
|
|
pdevice_info->partition_names[i] = "An NTFT partition. ";
|
|
break;
|
|
case VALID_NTFT:
|
|
pdevice_info->partition_names[i] = "A valid NTFT petition.";
|
|
break;
|
|
default:
|
|
pdevice_info->partition_names[i] = "No partiton";
|
|
pdevice_info->num_partitions -= 1;
|
|
if (ppartitions->PartitionType != 0)
|
|
{
|
|
WINDOWS_WINDEV_SPRINTF(print_buffer,"[Partition # %d] Unknown Type [%d]\n", i, ppartitions->PartitionType );
|
|
rtfs_kern_puts((byte *)print_buffer);
|
|
pdevice_info->partition_names[i] = "Unknown partiton type";
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return(TRUE);
|
|
}
|
|
|
|
/*
|
|
* This method is a thread. One of these threads is spawned for each Drive that is available in Rtfs(HEREHERE
|
|
* this is not currently implemented). The method polls Windows for insertion events. If a media is inserted to
|
|
* the machine and is chosen to be inserted into Rtfs then all this thread does is wait until the media is removed
|
|
* from the machine. Once this occurs the user is asked if they would like to insert one of the remaining media
|
|
* into Rtfs. If they choose a media then it is inserted and listens for a removal of that media. If they do not
|
|
* choose to insert any new media (-1) then the thread waits until a new media is inserted then asks the user to
|
|
* select the media they would like to insert into Rtfs.
|
|
*/
|
|
bool recentRemoval = FALSE;
|
|
int inserted_one_shot = 0;
|
|
static void PollDeviceReady(void)
|
|
{
|
|
int logical_unit_number = (int) 0;
|
|
int device_number = -1;
|
|
bool changed = TRUE;
|
|
char cont[5];
|
|
if (!driver_is_initialized)
|
|
return;
|
|
// for(;;)
|
|
{
|
|
DWORD dwBytesReturned=0;
|
|
//check to see if we have a media to check
|
|
if(currentDevice != NULL && currentDevice->hDevice != NULL &&
|
|
currentDevice->hDevice != HOST_INVALID_HANDLE_VALUE){
|
|
// if this is false then the device is no longer present
|
|
if (!DeviceIoControl(currentDevice->hDevice, IOCTL_STORAGE_CHECK_VERIFY, NULL, 0, NULL, 0,
|
|
&dwBytesReturned, NULL))
|
|
{
|
|
// tell the rest of the world that media is not present
|
|
printf("\nDrive [%s] was removed. Press Return.\n", windev_device_names[currentDevice->device_number]);
|
|
//remove from rtfs
|
|
currentDevice->media_installed = 0;
|
|
pc_rtfs_media_alert((void*)currentDevice,RTFS_ALERT_EJECT,NULL);
|
|
|
|
//close the handle cause it no longer exists
|
|
CloseHandle(currentDevice->hDevice);
|
|
currentDevice->hDevice = HOST_INVALID_HANDLE_VALUE;
|
|
|
|
//no longer have a current device
|
|
currentDevice = NULL;
|
|
|
|
//decrease device count
|
|
num_windev_devices -= 1;
|
|
//indicate a removal has occured and we should enumerate the devices
|
|
recentRemoval = TRUE;
|
|
}
|
|
}
|
|
else // have no media so see if a change has occured and ask the user if they would like to insert something
|
|
{
|
|
|
|
changed = win_dev_enum_devices();
|
|
/*recentRemoval is needed so that when an inserted drive is removed
|
|
since we already removed it in the if statement win_dev_enum_devices will
|
|
not detect a change. But if there was a recentRemoval we need to ask if
|
|
we need to mount again.*/
|
|
if(changed || recentRemoval ){
|
|
recentRemoval = FALSE;
|
|
currentDevice = NULL;
|
|
|
|
if(num_windev_devices == 0){
|
|
printf("There is no media currently available, press Return.");
|
|
rtfs_kern_gets((byte*)cont);
|
|
device_number = -1;
|
|
}
|
|
else{
|
|
int i;
|
|
printf("\n\nChange in inserted media detected.\n\n");
|
|
for (i = 0; i < num_windev_devices; i++)//for each device list some info about it
|
|
{
|
|
|
|
if (windev_devices[i].num_partitions==1)
|
|
{
|
|
printf("Device #%d, <%15.15s> contains 1 partition size == %I64d\n", i, windev_device_names[windev_devices[i].device_number], windev_devices[i].mediasize);
|
|
printf("...Partition: %s\n\n", windev_devices[i].partition_names[0]);
|
|
}
|
|
else
|
|
{
|
|
int j;
|
|
printf("Device #%d, <%15.15s> contains multiple partitions size == %I64d\n", i, windev_device_names[windev_devices[i].device_number], windev_devices[i].mediasize);
|
|
for (j = 0; j < windev_devices[i].num_partitions;j++)
|
|
{
|
|
printf("...Partition (%d): %s\n", j, windev_devices[i].partition_names[j]);
|
|
}
|
|
printf("\n");
|
|
}
|
|
}
|
|
printf("Select which device you would like to mount on Rtfs, select -1 to not mount a device. Device #: ");
|
|
rtfs_kern_gets((byte*)cont);
|
|
device_number = atoi(cont);
|
|
#if(!REMOVABLE_MEDIA_ONLY)
|
|
/* Don't allow device zero. that's probably the primary device */
|
|
while (device_number == 0)
|
|
{
|
|
printf("You selected zero (that\'s too dangerous ? please select again) or -1 #: ");
|
|
rtfs_kern_gets((byte*)cont);
|
|
device_number = atoi(cont);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
}
|
|
|
|
if(device_number != -1 && //make sure they selected the device
|
|
windev_devices[device_number].hDevice != NULL && //make sure their selection was valid
|
|
windev_devices[device_number].hDevice != HOST_INVALID_HANDLE_VALUE &&//make sure their selection was valid
|
|
!windev_devices[device_number].media_installed)//make sure the media is not already installed on another drive
|
|
{
|
|
map_lun_to_windev_devices[logical_unit_number] = &windev_devices[device_number];
|
|
windev_devices[device_number].logical_unit_number = logical_unit_number;
|
|
|
|
currentDevice = &windev_devices[device_number];
|
|
|
|
/* It isn;t writable until we detect AA66 in the first sector */
|
|
media_is_writable=0;
|
|
|
|
printf("\nDrive [%s] was inserted \n", windev_device_names[currentDevice->device_number]);
|
|
//insert into Rtfs
|
|
insert_win_device_to_rtfs(currentDevice);
|
|
|
|
currentDevice->media_installed = 1;
|
|
|
|
printf("Should this device be write protected? (y/n) ");
|
|
rtfs_kern_gets((byte*)cont);
|
|
if(cont[0] == 'y' || cont[0] == 'Y'){
|
|
pc_rtfs_media_alert((void*)currentDevice,RTFS_ALERT_WPSET,NULL);
|
|
}
|
|
else{
|
|
pc_rtfs_media_alert((void*)currentDevice,RTFS_ALERT_WPCLEAR,NULL);
|
|
}
|
|
inserted_one_shot = 1;
|
|
|
|
}
|
|
else if(device_number != -1){//if we did not choose to skip insertion but still missed if then the media is not avail
|
|
printf("Invalid Selection: The media selected is not available. If you think there is an error please re-insert the media.");
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
/* Note: hostdevice_media_parms is initialized here but declare in hostdisk.c, this is done to allow the
|
|
common handlers for all "virtual" devices to reside in hostdisk.c */
|
|
|
|
void shutdown_win_device(void *devhandle)
|
|
{
|
|
struct windev_device *pDevice;
|
|
|
|
pDevice = (struct windev_device *)devhandle;
|
|
printf("shutdown_win_device() setting installed to 0, and closing \n");
|
|
pDevice->media_installed = 0;
|
|
|
|
// media's gone, so the handle's no good
|
|
if (pDevice->hDevice != HOST_INVALID_HANDLE_VALUE && pDevice->hDevice != NULL)
|
|
CloseHandle(pDevice->hDevice);
|
|
pDevice->hDevice = HOST_INVALID_HANDLE_VALUE;
|
|
}
|
|
|
|
#else
|
|
BOOLEAN win_dev_seek(int logical_unit_number, dword block)
|
|
{
|
|
return(0);
|
|
}
|
|
BOOLEAN win_dev_write(int logical_unit_number, void *buffer, word count)
|
|
{
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
BOOLEAN win_dev_read(int logical_unit_number, void *buffer, word count)
|
|
{
|
|
return(TRUE);
|
|
}
|
|
void PollDeviceReady(void)
|
|
{
|
|
}
|
|
#endif /* _MSC_VER */
|
|
|
|
#endif /* (INCLUDE_WINDEV) */
|