aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--int21dos.h2
-rw-r--r--sftsr.c84
-rw-r--r--vboxdev.h70
-rw-r--r--vboxshfl.h48
4 files changed, 186 insertions, 18 deletions
diff --git a/int21dos.h b/int21dos.h
index a827b8f..30aa68b 100644
--- a/int21dos.h
+++ b/int21dos.h
@@ -33,7 +33,7 @@ enum dos_error {
DOS_ERROR_INVALID_FUNCTION = 1,
DOS_ERROR_FILE_NOT_FOUND = 2,
DOS_ERROR_PATH_NOT_FOUND = 3,
- DOS_ERROR_ERROR_TOO_MANY_OPEN_FILES = 4,
+ DOS_ERROR_TOO_MANY_OPEN_FILES = 4,
DOS_ERROR_ACCESS_DENIED = 5,
DOS_ERROR_INVALID_HANDLE = 6,
DOS_ERROR_ARENA_TRASHED = 7,
diff --git a/sftsr.c b/sftsr.c
index 3f95323..a213200 100644
--- a/sftsr.c
+++ b/sftsr.c
@@ -31,7 +31,7 @@ TSRDATA data;
/** Private buffer for VirtualBox filenames. */
static SHFLSTRING_WITH_BUF(shflstr, SHFL_MAX_LEN);
-static SHFLDIRINFO_WITH_BUF(shfldirinfo, SHFL_MAX_LEN);
+static SHFLDIRINFO_WITH_NAME_BUF(shfldirinfo, SHFL_MAX_LEN);
static SHFLCREATEPARMS createparms;
@@ -122,11 +122,15 @@ static bool is_call_for_mounted_drive(union INTPACK __far *r)
static void clear_dos_err(union INTPACK __far *r)
{
+ dlog_puts("->ok");
r->x.flags &= ~INTR_CF;
}
static void set_dos_err(union INTPACK __far *r, int err)
{
+ dlog_print("->dos error ");
+ dlog_printd(err);
+ dlog_endline();
r->x.flags |= INTR_CF;
r->x.ax = err;
}
@@ -148,6 +152,10 @@ static int vbox_err_to_dos(int32_t err)
return DOS_ERROR_NO_MORE_FILES;
case VERR_ALREADY_EXISTS:
return DOS_ERROR_FILE_EXISTS;
+ case VERR_TOO_MANY_OPEN_FILES:
+ return DOS_ERROR_TOO_MANY_OPEN_FILES;
+ case VERR_WRITE_PROTECT:
+ return DOS_ERROR_WRITE_PROTECT;
default:
return DOS_ERROR_GEN_FAILURE;
}
@@ -155,13 +163,16 @@ static int vbox_err_to_dos(int32_t err)
static void set_vbox_err(union INTPACK __far *r, int32_t err)
{
- dlog_print("vbox error ");
- dlog_printx(err >> 16);
- dlog_print(":");
- dlog_printx(err & 0xFFFF);
+ dlog_print("->vbox error ");
+ if (err < INT16_MIN || err > INT16_MAX) {
+ dlog_printx(err >> 16);
+ dlog_print(":");
+ dlog_printx(err & 0xFFFF);
+ } else {
+ dlog_printd(err);
+ }
dlog_endline();
- r->x.flags |= INTR_CF;
- r->x.ax = vbox_err_to_dos(err);
+ set_dos_err(r, vbox_err_to_dos(err));
}
static int my_strrchr(const char __far *str, char c)
@@ -345,7 +356,7 @@ static void handle_create_open_ex(union INTPACK __far *r)
openfile = find_free_openfile();
if (!openfile) {
- set_dos_err(r, DOS_ERROR_ERROR_TOO_MANY_OPEN_FILES);
+ set_dos_err(r, DOS_ERROR_TOO_MANY_OPEN_FILES);
return;
}
@@ -374,6 +385,11 @@ static void handle_create_open_ex(union INTPACK __far *r)
createparms.CreateFlags |= SHFL_CF_ACCESS_READ;
}
+ if (!(createparms.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;
+ }
+
dlog_print("vbox createparms flags=");
dlog_printx(createparms.CreateFlags);
dlog_endline();
@@ -613,6 +629,45 @@ static void handle_delete(union INTPACK __far *r)
clear_dos_err(r);
}
+static void handle_rename(union INTPACK __far *r)
+{
+ const char __far *src = data.dossda->fn1;
+ int srcdrive = drive_letter_to_index(src[0]);
+ const char __far *dst = data.dossda->fn2;
+ int dstdrive = drive_letter_to_index(dst[0]);
+ SHFLROOT root = data.drives[srcdrive].root;
+ int32_t err;
+
+ dlog_print("handle_rename ");
+ dlog_fprint(src);
+ dlog_print(" to ");
+ dlog_fprint(dst);
+ dlog_endline();
+
+ if (srcdrive != dstdrive) {
+ set_dos_err(r, DOS_ERROR_NOT_SAME_DEVICE);
+ return;
+ }
+
+ copy_drive_relative_filename(&shflstr.shflstr, src);
+ translate_filename_to_host(&shflstr.shflstr);
+
+ // Reusing shfldirinfo buffer space here
+ // Hoping no one does concurrent find_next and rename
+ copy_drive_relative_filename(&shfldirinfo.dirinfo.name, dst);
+ translate_filename_to_host(&shfldirinfo.dirinfo.name);
+
+ err = vbox_shfl_rename(&data.vb, data.hgcm_client_id, root,
+ &shflstr.shflstr, &shfldirinfo.dirinfo.name,
+ SHFL_RENAME_DIR | SHFL_RENAME_FILE);
+ if (err) {
+ set_vbox_err(r, err);
+ return;
+ }
+
+ clear_dos_err(r);
+}
+
static void handle_getattr(union INTPACK __far *r)
{
const char __far *path = data.dossda->fn1;
@@ -624,7 +679,7 @@ static void handle_getattr(union INTPACK __far *r)
dlog_fprint(path);
dlog_endline();
- copy_drive_relative_dirname(&shflstr.shflstr, path);
+ copy_drive_relative_filename(&shflstr.shflstr, path);
translate_filename_to_host(&shflstr.shflstr);
memset(&createparms, 0, sizeof(SHFLCREATEPARMS));
@@ -750,8 +805,6 @@ static int32_t find_next_from_vbox(uint8_t search_attr)
return VERR_INVALID_HANDLE;
}
- shfldirinfo.dirinfo.name.u16Size = sizeof(shfldirinfo.buf);
-
while (1) { // Loop until we have a valid file (or an error)
unsigned size = sizeof(shfldirinfo), resume = 0, count = 0;
dlog_puts("calling vbox list");
@@ -760,6 +813,12 @@ static int32_t find_next_from_vbox(uint8_t search_attr)
data.files[SEARCH_DIR_FILE].root, data.files[SEARCH_DIR_FILE].handle,
SHFL_LIST_RETURN_ONE, &size, &shflstr.shflstr, &shfldirinfo.dirinfo,
&resume, &count);
+
+ // Reset the size of the buffer here since VirtualBox "shortens" it,
+ // (since it expects to fit in more entries in the same space, but
+ // we won't allow that via SHFL_LIST_RETURN_ONE).
+ shfldirinfo.dirinfo.name.u16Size = sizeof(shfldirinfo.buf);
+
if (err) {
return err;
}
@@ -1033,6 +1092,9 @@ static bool int2f_11_handler(union INTPACK r)
case DOS_FN_DELETE:
handle_delete(&r);
return true;
+ case DOS_FN_RENAME:
+ handle_rename(&r);
+ return true;
case DOS_FN_GET_FILE_ATTR:
handle_getattr(&r);
return true;
diff --git a/vboxdev.h b/vboxdev.h
index 15db0e1..062c9dc 100644
--- a/vboxdev.h
+++ b/vboxdev.h
@@ -54,6 +54,28 @@
#define VERR_INVALID_HANDLE (-4)
/** Invalid loader handle. */
#define VWRN_INVALID_HANDLE 4
+/** Failed to lock the address range. */
+#define VERR_LOCK_FAILED (-5)
+/** Invalid memory pointer. */
+#define VERR_INVALID_POINTER (-6)
+/** Failed to patch the IDT. */
+#define VERR_IDT_FAILED (-7)
+/** Memory allocation failed. */
+#define VERR_NO_MEMORY (-8)
+/** Already loaded. */
+#define VERR_ALREADY_LOADED (-9)
+/** Permission denied. */
+#define VERR_PERMISSION_DENIED (-10)
+/** Permission denied. */
+#define VINF_PERMISSION_DENIED 10
+/** Version mismatch. */
+#define VERR_VERSION_MISMATCH (-11)
+/** The request function is not implemented. */
+#define VERR_NOT_IMPLEMENTED (-12)
+/** The request function is not implemented. */
+#define VINF_NOT_IMPLEMENTED 12
+/** Invalid flags was given. */
+#define VERR_INVALID_FLAGS (-13)
#define VERR_FILE_IO_ERROR (-100)
/** File/Device open failed. */
@@ -72,6 +94,50 @@
#define VERR_TOO_MANY_OPEN_FILES (-106)
/** Seek error. */
#define VERR_SEEK (-107)
+/** Seek below file start. */
+#define VERR_NEGATIVE_SEEK (-108)
+/** Trying to seek on device. */
+#define VERR_SEEK_ON_DEVICE (-109)
+/** Reached the end of the file. */
+#define VERR_EOF (-110)
+/** Reached the end of the file. */
+#define VINF_EOF 110
+/** Generic file read error. */
+#define VERR_READ_ERROR (-111)
+/** Generic file write error. */
+#define VERR_WRITE_ERROR (-112)
+/** Write protect error. */
+#define VERR_WRITE_PROTECT (-113)
+/** Sharing violation, file is being used by another process. */
+#define VERR_SHARING_VIOLATION (-114)
+/** Unable to lock a region of a file. */
+#define VERR_FILE_LOCK_FAILED (-115)
+/** File access error, another process has locked a portion of the file. */
+#define VERR_FILE_LOCK_VIOLATION (-116)
+/** File or directory can't be created. */
+#define VERR_CANT_CREATE (-117)
+/** Directory can't be deleted. */
+#define VERR_CANT_DELETE_DIRECTORY (-118)
+/** Can't move file to another disk. */
+#define VERR_NOT_SAME_DEVICE (-119)
+/** The filename or extension is too long. */
+#define VERR_FILENAME_TOO_LONG (-120)
+/** Media not present in drive. */
+#define VERR_MEDIA_NOT_PRESENT (-121)
+/** The type of media was not recognized. Not formatted? */
+#define VERR_MEDIA_NOT_RECOGNIZED (-122)
+/** Can't unlock - region was not locked. */
+#define VERR_FILE_NOT_LOCKED (-123)
+/** Unrecoverable error: lock was lost. */
+#define VERR_FILE_LOCK_LOST (-124)
+/** Can't delete directory with files. */
+#define VERR_DIR_NOT_EMPTY (-125)
+/** A directory operation was attempted on a non-directory object. */
+#define VERR_NOT_A_DIRECTORY (-126)
+/** A non-directory operation was attempted on a directory object. */
+#define VERR_IS_A_DIRECTORY (-127)
+/** Tried to grow a file beyond the limit imposed by the process or the filesystem. */
+#define VERR_FILE_TOO_BIG (-128)
/** @name Generic Directory Enumeration Status Codes
* @{
@@ -1286,6 +1352,10 @@ typedef struct _SHFLCREATEPARMS
/** Lock entire object. */
#define SHFL_LOCK_ENTIRE (0x8)
+#define SHFL_RENAME_FILE (0x1)
+#define SHFL_RENAME_DIR (0x2)
+#define SHFL_RENAME_REPLACE_IF_EXISTS (0x4)
+
/** @name Shared Folders mappings.
* @{
*/
diff --git a/vboxshfl.h b/vboxshfl.h
index 04afed0..36cd818 100644
--- a/vboxshfl.h
+++ b/vboxshfl.h
@@ -22,17 +22,19 @@
#include "vboxhgcm.h"
-#define SHFLSTRING_WITH_BUF(name, size) \
+#define SHFLSTRING_WITH_BUF(varname, bufsize) \
struct { \
SHFLSTRING shflstr; \
- char buf[size]; \
- } name = { {size, 0} }
+ char buf[bufsize]; \
+ } varname = { .shflstr = { .u16Size = bufsize} }
-#define SHFLDIRINFO_WITH_BUF(name, size) \
+#define SHFLDIRINFO_WITH_NAME_BUF(varname, bufsize) \
struct { \
SHFLDIRINFO dirinfo; \
- char buf[size]; \
- } name
+ char buf[bufsize]; \
+ } varname = { \
+ .dirinfo = { .name = { .u16Size = bufsize} } \
+ }
static inline unsigned shflstring_size_with_buf(const SHFLSTRING *str)
{
@@ -429,6 +431,40 @@ static int32_t vbox_shfl_remove(LPVBOXCOMM vb, hgcm_client_id_t client_id, SHFLR
return req->header.result;
}
+static int32_t vbox_shfl_rename(LPVBOXCOMM vb, hgcm_client_id_t client_id, SHFLROOT root,
+ const SHFLSTRING *src, const SHFLSTRING *dst, unsigned flags)
+{
+ VMMDevHGCMCall __far *req = (void __far *) vb->buf;
+ vbox_hgcm_init_call(req, client_id, SHFL_FN_RENAME, 4);
+
+ // arg 0 in uint32 "root"
+ req->aParms[0].type = VMMDevHGCMParmType_32bit;
+ req->aParms[0].u.value32 = root;
+
+ // arg 1 in shflstring "src"
+ req->aParms[1].type = VMMDevHGCMParmType_LinAddr;
+ req->aParms[1].u.Pointer.size = shflstring_size_with_buf(src);
+ req->aParms[1].u.Pointer.u.linearAddr = linear_addr(src);
+
+ // arg 2 in shflstring "dst"
+ req->aParms[2].type = VMMDevHGCMParmType_LinAddr;
+ req->aParms[2].u.Pointer.size = shflstring_size_with_buf(dst);
+ req->aParms[2].u.Pointer.u.linearAddr = linear_addr(dst);
+
+ // arg 3 in uint32 "flags"
+ req->aParms[3].type = VMMDevHGCMParmType_32bit;
+ req->aParms[3].u.value32 = flags;
+
+ vbox_send_request(vb->iobase, vb->dds.physicalAddress);
+
+ if (req->header.header.rc < 0) {
+ return req->header.header.rc;
+ } else if (req->header.header.rc == VINF_HGCM_ASYNC_EXECUTE) {
+ vbox_hgcm_wait(&req->header);
+ }
+
+ return req->header.result;
+}
static int32_t vbox_shfl_set_utf8(LPVBOXCOMM vb, hgcm_client_id_t client_id)
{