diff options
-rw-r--r-- | int21dos.h | 10 | ||||
-rw-r--r-- | mousetsr.h | 7 | ||||
-rw-r--r-- | mousmain.c | 2 | ||||
-rw-r--r-- | sfmain.c | 2 | ||||
-rw-r--r-- | sftsr.c | 109 | ||||
-rw-r--r-- | sftsr.h | 7 | ||||
-rw-r--r-- | vbox.c | 28 | ||||
-rw-r--r-- | vbox.h | 15 | ||||
-rw-r--r-- | vboxdev.h | 51 |
9 files changed, 161 insertions, 70 deletions
@@ -354,11 +354,11 @@ enum DOS_REDIR_SUBFUNCTION { }; enum OPENEX_ACTIONS { - OPENEX_FAIL_IF_EXISTS = 0x0000, - OPENEX_OPEN_IF_EXISTS = 0x0001, - OPENEX_REPLACE_IF_EXISTS = 0x0002, - OPENEX_FAIL_IF_NEW = 0x0000, - OPENEX_CREATE_IF_NEW = 0x0100, + OPENEX_FAIL_IF_EXISTS = 0x00, + OPENEX_OPEN_IF_EXISTS = 0x01, + OPENEX_REPLACE_IF_EXISTS = 0x02, + OPENEX_FAIL_IF_NEW = 0x00, + OPENEX_CREATE_IF_NEW = 0x10, }; enum OPENEX_MODE { @@ -58,6 +58,10 @@ #if USE_VIRTUALBOX #include "vbox.h" + +/** Size of the VBox buffer. The maximum message length that may be sent. + * Enough to fit a set_pointer_shape message with a 16x16 cursor. */ +#define VBOX_BUFFER_SIZE (1024 + 32 + 24 + 20) #endif struct point { @@ -188,11 +192,12 @@ typedef struct tsrdata { /** Have VirtualBox absolute coordinates. */ bool vbhaveabs : 1; struct vboxcomm vb; + char vbbuf[VBOX_BUFFER_SIZE]; #endif #if USE_VMWARE /** VMware is available. */ - bool vmwavail : 1; + bool vmwavail; #endif } TSRDATA; @@ -98,7 +98,7 @@ static int set_virtualbox_integration(LPTSRDATA data, bool enable) return err; } - err = vbox_init_buffer(&data->vb); + err = vbox_init_buffer(&data->vb, VBOX_BUFFER_SIZE); if (err) { fprintf(stderr, "Cannot lock buffer used for VirtualBox communication, err=%d\n", err); return err; @@ -353,7 +353,7 @@ static int configure_driver(LPTSRDATA data) return -1; } - err = vbox_init_buffer(&data->vb); + err = vbox_init_buffer(&data->vb, VBOX_BUFFER_SIZE); if (err) { fprintf(stderr, "Cannot lock buffer used for VirtualBox communication, err=%ld\n", err); return -1; @@ -33,7 +33,10 @@ static SHFLSTRING_WITH_BUF(shflstr, SHFL_MAX_LEN); static SHFLDIRINFO_WITH_NAME_BUF(shfldirinfo, SHFL_MAX_LEN); -static SHFLCREATEPARMS createparms; +static union { + SHFLVOLINFO volinfo; + SHFLCREATEPARMS create; +} parms; static uint8_t map_shfl_attr_to_dosattr(const SHFLFSOBJATTR *a) { @@ -366,50 +369,50 @@ static void handle_create_open_ex(union INTPACK __far *r) copy_drive_relative_filename(&shflstr.shflstr, path); translate_filename_to_host(&shflstr.shflstr); - memset(&createparms, 0, sizeof(SHFLCREATEPARMS)); + memset(&parms.create, 0, sizeof(SHFLCREATEPARMS)); if (action & OPENEX_REPLACE_IF_EXISTS) { - createparms.CreateFlags |= SHFL_CF_ACT_REPLACE_IF_EXISTS; + parms.create.CreateFlags |= SHFL_CF_ACT_REPLACE_IF_EXISTS; } else if (action & OPENEX_OPEN_IF_EXISTS) { - createparms.CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS; + parms.create.CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS; } else { - createparms.CreateFlags |= SHFL_CF_ACT_FAIL_IF_EXISTS; + parms.create.CreateFlags |= SHFL_CF_ACT_FAIL_IF_EXISTS; } if (action & OPENEX_CREATE_IF_NEW) { - createparms.CreateFlags |= SHFL_CF_ACT_CREATE_IF_NEW; + parms.create.CreateFlags |= SHFL_CF_ACT_CREATE_IF_NEW; } else { - createparms.CreateFlags |= SHFL_CF_ACT_FAIL_IF_NEW; + parms.create.CreateFlags |= SHFL_CF_ACT_FAIL_IF_NEW; } if ((mode & OPENEX_MODE_RDWR) == OPENEX_MODE_RDWR) { - createparms.CreateFlags |= SHFL_CF_ACCESS_READWRITE; + parms.create.CreateFlags |= SHFL_CF_ACCESS_READWRITE; } else if (mode & OPENEX_MODE_WRITE) { - createparms.CreateFlags |= SHFL_CF_ACCESS_WRITE; + parms.create.CreateFlags |= SHFL_CF_ACCESS_WRITE; } else { - createparms.CreateFlags |= SHFL_CF_ACCESS_READ; + parms.create.CreateFlags |= SHFL_CF_ACCESS_READ; } - if (!(createparms.CreateFlags & SHFL_CF_ACCESS_WRITE)) { + if (!(parms.create.CreateFlags & SHFL_CF_ACCESS_WRITE)) { // Do we really want to create new files without opening them for writing? - createparms.CreateFlags |= SHFL_CF_ACT_FAIL_IF_NEW; + parms.create.CreateFlags |= SHFL_CF_ACT_FAIL_IF_NEW; } - dlog_print("vbox createparms flags="); - dlog_printx(createparms.CreateFlags); + dlog_print("vbox create flags="); + dlog_printx(parms.create.CreateFlags); dlog_endline(); - err = vbox_shfl_open(&data.vb, data.hgcm_client_id, root, &shflstr.shflstr, &createparms); + err = vbox_shfl_open(&data.vb, data.hgcm_client_id, root, &shflstr.shflstr, &parms.create); if (err) { set_vbox_err(r, err); return; } dlog_print("vbox success result="); - dlog_printd(createparms.Result); + dlog_printd(parms.create.Result); dlog_print(" openfile="); dlog_printu(openfile); dlog_endline(); - switch (createparms.Result) { + switch (parms.create.Result) { case SHFL_PATH_NOT_FOUND: set_dos_err(r, DOS_ERROR_PATH_NOT_FOUND); return; @@ -427,16 +430,16 @@ static void handle_create_open_ex(union INTPACK __far *r) break; } - if (createparms.Handle == SHFL_HANDLE_NIL) { + if (parms.create.Handle == SHFL_HANDLE_NIL) { set_dos_err(r, DOS_ERROR_GEN_FAILURE); return; } data.files[openfile].root = root; - data.files[openfile].handle = createparms.Handle; + data.files[openfile].handle = parms.create.Handle; // Fill in the SFT - map_shfl_info_to_dossft(sft, &createparms.Info); + map_shfl_info_to_dossft(sft, &parms.create.Info); sft->open_mode = mode; sft->dev_info = 0x8040 | drive; // "Network drive, unwritten to" sft->f_pos = 0; @@ -687,16 +690,16 @@ static void handle_getattr(union INTPACK __far *r) copy_drive_relative_filename(&shflstr.shflstr, path); translate_filename_to_host(&shflstr.shflstr); - memset(&createparms, 0, sizeof(SHFLCREATEPARMS)); - createparms.CreateFlags = SHFL_CF_LOOKUP; + memset(&parms.create, 0, sizeof(SHFLCREATEPARMS)); + parms.create.CreateFlags = SHFL_CF_LOOKUP; err = vbox_shfl_open(&data.vb, data.hgcm_client_id, root, - &shflstr.shflstr, &createparms); + &shflstr.shflstr, &parms.create); if (err) { set_vbox_err(r, err); return; } - switch (createparms.Result) { + switch (parms.create.Result) { case SHFL_PATH_NOT_FOUND: set_dos_err(r, DOS_ERROR_PATH_NOT_FOUND); return; @@ -707,7 +710,7 @@ static void handle_getattr(union INTPACK __far *r) break; } - map_shfl_info_to_getattr(r, &createparms.Info); + map_shfl_info_to_getattr(r, &parms.create.Info); clear_dos_err(r); } @@ -721,19 +724,19 @@ static vboxerr open_search_dir(SHFLROOT root, const char __far *path) copy_drive_relative_dirname(&shflstr.shflstr, path); translate_filename_to_host(&shflstr.shflstr); - memset(&createparms, 0, sizeof(SHFLCREATEPARMS)); - createparms.CreateFlags = SHFL_CF_DIRECTORY + memset(&parms.create, 0, sizeof(SHFLCREATEPARMS)); + parms.create.CreateFlags = SHFL_CF_DIRECTORY | SHFL_CF_ACT_OPEN_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW | SHFL_CF_ACCESS_READ; err = vbox_shfl_open(&data.vb, data.hgcm_client_id, root, - &shflstr.shflstr, &createparms); + &shflstr.shflstr, &parms.create); if (err) { dlog_puts("open search dir failed"); return err; } - switch (createparms.Result) { + switch (parms.create.Result) { case SHFL_PATH_NOT_FOUND: return VERR_PATH_NOT_FOUND; case SHFL_FILE_NOT_FOUND: @@ -742,13 +745,13 @@ static vboxerr open_search_dir(SHFLROOT root, const char __far *path) break; } - if (createparms.Handle == SHFL_HANDLE_NIL) { + if (parms.create.Handle == SHFL_HANDLE_NIL) { dlog_puts("open search dir returned no handle..."); return VERR_INVALID_HANDLE; } data.files[SEARCH_DIR_FILE].root = root; - data.files[SEARCH_DIR_FILE].handle = createparms.Handle; + data.files[SEARCH_DIR_FILE].handle = parms.create.Handle; return 0; } @@ -965,17 +968,17 @@ static void handle_chdir(union INTPACK __far *r) copy_drive_relative_filename(&shflstr.shflstr, path); translate_filename_to_host(&shflstr.shflstr); - memset(&createparms, 0, sizeof(SHFLCREATEPARMS)); - createparms.CreateFlags = SHFL_CF_LOOKUP; + memset(&parms.create, 0, sizeof(SHFLCREATEPARMS)); + parms.create.CreateFlags = SHFL_CF_LOOKUP; err = vbox_shfl_open(&data.vb, data.hgcm_client_id, root, - &shflstr.shflstr, &createparms); + &shflstr.shflstr, &parms.create); if (err) { set_vbox_err(r, err); return; } - switch (createparms.Result) { + switch (parms.create.Result) { case SHFL_PATH_NOT_FOUND: case SHFL_FILE_NOT_FOUND: set_dos_err(r, DOS_ERROR_PATH_NOT_FOUND); @@ -985,7 +988,7 @@ static void handle_chdir(union INTPACK __far *r) } // Also check whether it is really a directory - if (!(map_shfl_attr_to_dosattr(&createparms.Info.Attr) & _A_SUBDIR)) { + if (!(map_shfl_attr_to_dosattr(&parms.create.Info.Attr) & _A_SUBDIR)) { set_dos_err(r, DOS_ERROR_PATH_NOT_FOUND); return; } @@ -1007,18 +1010,18 @@ static void handle_mkdir(union INTPACK __far *r) copy_drive_relative_filename(&shflstr.shflstr, path); translate_filename_to_host(&shflstr.shflstr); - memset(&createparms, 0, sizeof(SHFLCREATEPARMS)); - createparms.CreateFlags = SHFL_CF_DIRECTORY + memset(&parms.create, 0, sizeof(SHFLCREATEPARMS)); + parms.create.CreateFlags = SHFL_CF_DIRECTORY | SHFL_CF_ACT_FAIL_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW; err = vbox_shfl_open(&data.vb, data.hgcm_client_id, root, - &shflstr.shflstr, &createparms); + &shflstr.shflstr, &parms.create); if (err) { set_vbox_err(r, err); return; } - switch (createparms.Result) { + switch (parms.create.Result) { case SHFL_PATH_NOT_FOUND: case SHFL_FILE_NOT_FOUND: set_dos_err(r, DOS_ERROR_PATH_NOT_FOUND); @@ -1057,6 +1060,27 @@ static void handle_rmdir(union INTPACK __far *r) clear_dos_err(r); } +static void handle_get_disk_free(union INTPACK __far *r) +{ + const unsigned long total_space = 10 * 1024 * 1024UL; + const unsigned long free_space = 4 * 1024 * 1024UL; + const unsigned cluster_bytes = 4 * 4096UL; + + // TODO SHFLVOLINFO + + r->h.ah = 0; // media ID byte + r->h.al = 4; /* Sectors per cluster */ + r->x.cx = 4096; /* Bytes per sector */ + r->x.bx = total_space / cluster_bytes; /* Total clusters */ + r->x.dx = free_space / cluster_bytes; /* Number of available clusters */ + + dlog_print("disk free"); + dlog_printd(r->x.dx); + dlog_endline(); + + clear_dos_err(r); +} + static bool int2f_11_handler(union INTPACK r) #pragma aux int2f_11_handler "*" parm caller [] value [al] modify [ax bx cx dx si di es gs fs] { @@ -1128,7 +1152,10 @@ static bool int2f_11_handler(union INTPACK r) handle_rmdir(&r); return true; case DOS_FN_GET_DISK_FREE: - // We don't support this + handle_get_disk_free(&r); + return true; + case DOS_FN_SEEK_END: + // I have no testcase for this function, so unsupported set_dos_err(&r, DOS_ERROR_INVALID_FUNCTION); return true; } @@ -33,9 +33,13 @@ /** Maximum number of open files */ #define NUM_FILES 40 -/** Directory enumeration needs an open file, this is its index. */ +/** Directory enumeration needs an open file, this is its index in the "openfile" table. */ #define SEARCH_DIR_FILE 0 +/** Size of the VBox buffer. The maximum message length that may be sent. + * Enough to fit an HGCM connect call, which is actually larger than most other calls we use ( <= 7 args ). */ +#define VBOX_BUFFER_SIZE (200) + typedef struct { uint32_t root; uint64_t handle; @@ -65,6 +69,7 @@ typedef struct { // VirtualBox communication struct vboxcomm vb; + char vbbuf[VBOX_BUFFER_SIZE]; uint32_t hgcm_client_id; } TSRDATA; @@ -77,18 +77,19 @@ int vbox_init_device(LPVBOXCOMM vb) return 0; } -int vbox_init_buffer(LPVBOXCOMM vb) +int vbox_init_buffer(LPVBOXCOMM vb, unsigned size) { + vb->dds.regionSize = size; + vb->dds.segOrSelector = FP_SEG(&vb->buf); + vb->dds.offset = FP_OFF(&vb->buf); + vb->dds.bufferId = 0; + vb->dds.physicalAddress = 0; + vb->vds = false; + if (vds_available()) { // Use the Virtual DMA Service to get the physical address of this buffer int err; - vb->dds.regionSize = sizeof(vb->buf); - vb->dds.segOrSelector = FP_SEG(&vb->buf); - vb->dds.offset = FP_OFF(&vb->buf); - vb->dds.bufferId = 0; - vb->dds.physicalAddress = 0; - err = vds_lock_dma_buffer_region(&vb->dds, VDS_NO_AUTO_ALLOC); if (err) { // As far as I have seen, most VDS providers always keep low memory contiguous, @@ -98,12 +99,11 @@ int vbox_init_buffer(LPVBOXCOMM vb) dlog_endline(); return err; } - } else { - vb->dds.regionSize = 0; // So that we don't try to unlock it later - vb->dds.segOrSelector = FP_SEG(&vb->buf); - vb->dds.offset = FP_OFF(&vb->buf); - vb->dds.bufferId = 0; + vb->vds = true; + } else { + // If VDS is not available, + // we assume a 1:1 mapping between linear and physical addresses vb->dds.physicalAddress = linear_addr(&vb->buf); } @@ -112,8 +112,7 @@ int vbox_init_buffer(LPVBOXCOMM vb) int vbox_release_buffer(LPVBOXCOMM vb) { - if (vds_available() && vb->dds.regionSize) { - + if (vb->vds && vds_available()) { int err = vds_unlock_dma_buffer_region(&vb->dds, 0); if (err) { dlog_print("Error while VDS unlocking, err="); @@ -122,6 +121,7 @@ int vbox_release_buffer(LPVBOXCOMM vb) // Ignore the error, it's not like we can do anything } } + vb->vds = false; vb->dds.regionSize = 0; vb->dds.segOrSelector = 0; vb->dds.offset = 0; @@ -31,14 +31,17 @@ #include "utils.h" #include "vboxdev.h" -/** Size of the VBox buffer. The maximum message length that may be sent. */ -// Enough to fit a set_pointer_shape message with a 16x16 cursor -#define VBOX_BUFFER_SIZE (1024 + 32 + 24 + 20) - +/** Struct containing all the information required to send a VirtualBox message. */ typedef struct vboxcomm { + /** The IO port of the VirtualBox pci device, found by vbox_init_device(). */ uint16_t iobase; - char buf[VBOX_BUFFER_SIZE]; + /** Whether we are using VDS or not. */ + bool vds; + /** The VDS (Virtual DMA service) descriptor corresponding to the buffer that we will use. + * Initialized by vbox_init_buffer(), even if we don't use VDS. */ VDSDDS dds; + /** We assume the actual buffer comes in memory after this struct. */ + char buf[]; } vboxcomm_t; typedef vboxcomm_t * PVBOXCOMM; typedef vboxcomm_t __far * LPVBOXCOMM; @@ -65,7 +68,7 @@ extern int vbox_init_device(LPVBOXCOMM vb); /** Prepares the buffer used for communicating with VBox and * computes its physical address (using VDS if necessary). */ -extern int vbox_init_buffer(LPVBOXCOMM vb); +extern int vbox_init_buffer(LPVBOXCOMM vb, unsigned size); /** Releases/unlocks buffer, no further use possible. */ extern int vbox_release_buffer(LPVBOXCOMM vb); @@ -1408,6 +1408,57 @@ typedef struct _SHFLDIRINFO SHFLSTRING name; } SHFLDIRINFO, *PSHFLDIRINFO; +/** + * Shared folder filesystem properties. + */ +typedef struct SHFLFSPROPERTIES +{ + /** The maximum size of a filesystem object name. + * This does not include the '\\0'. */ + uint32_t cbMaxComponent; + + /** True if the filesystem is remote. + * False if the filesystem is local. */ + bool fRemote; + + /** True if the filesystem is case sensitive. + * False if the filesystem is case insensitive. */ + bool fCaseSensitive; + + /** True if the filesystem is mounted read only. + * False if the filesystem is mounted read write. */ + bool fReadOnly; + + /** True if the filesystem can encode unicode object names. + * False if it can't. */ + bool fSupportsUnicode; + + /** True if the filesystem is compresses. + * False if it isn't or we don't know. */ + bool fCompressed; + + /** True if the filesystem compresses of individual files. + * False if it doesn't or we don't know. */ + bool fFileCompression; + + /** @todo more? */ +} SHFLFSPROPERTIES; +AssertCompileSize(SHFLFSPROPERTIES, 12); +/** Pointer to a shared folder filesystem properties structure. */ +typedef SHFLFSPROPERTIES *PSHFLFSPROPERTIES; +/** Pointer to a const shared folder filesystem properties structure. */ +typedef SHFLFSPROPERTIES const *PCSHFLFSPROPERTIES; + +typedef struct _SHFLVOLINFO +{ + uint64_t ullTotalAllocationBytes; + uint64_t ullAvailableAllocationBytes; + uint32_t ulBytesPerAllocationUnit; + uint32_t ulBytesPerSector; + uint32_t ulSerial; + SHFLFSPROPERTIES fsProperties; +} SHFLVOLINFO, *PSHFLVOLINFO; + #define SHFL_LIST_NONE 0 #define SHFL_LIST_RETURN_ONE 1 #define SHFL_LIST_RESTART 2 |