diff options
author | Javier <dev.git@javispedro.com> | 2022-04-16 19:55:32 +0200 |
---|---|---|
committer | Javier <dev.git@javispedro.com> | 2022-04-16 19:55:32 +0200 |
commit | 9cf5dd38521565ff889dc6b07187742ac67a7454 (patch) | |
tree | 7d20fdde1a00796047ffeca56a17677ef4883d73 | |
parent | 1075670224d66edba07aa5c100917f3ace7d628c (diff) | |
download | vbados-9cf5dd38521565ff889dc6b07187742ac67a7454.tar.gz vbados-9cf5dd38521565ff889dc6b07187742ac67a7454.zip |
avoid leaking HMA on install error
-rw-r--r-- | README.md | 25 | ||||
-rw-r--r-- | dostsr.h | 27 | ||||
-rw-r--r-- | mousetsr.h | 2 | ||||
-rw-r--r-- | mousmain.c | 10 | ||||
-rw-r--r-- | sfmain.c | 14 |
5 files changed, 53 insertions, 25 deletions
@@ -175,6 +175,7 @@ changing file attributes (like setting a file to read-only...). The drives can also be accessed from within Windows 3.x . It uses around 10KiB of memory, and auto-installs to an UMB if available. +This is still much less memory than a SMB client and network stack! ### Usage @@ -243,11 +244,12 @@ Please see the [OpenWatcom documentation for the syntax of the TZ variable](http For example, if your local timezone is 8 hours earlier than UTC (e.g. PST), run `set TZ=PST8`. -# Building +# Building the source This requires [OpenWatcom 2.0](http://open-watcom.github.io/) to build, and I have only tried with the latest (March 2022) snapshot, -albeit it likely work with older versions. Might even work with 1.9. +albeit it may likely work with older versions, starting from 1.9. + I have tested building it on a Linux host as well as building on MS-DOS itself (with the source code being on a VBSF shared folder :) ). @@ -261,7 +263,7 @@ vbsf.exe plus the Windows 3.x driver (oemsetup.inf and vbmouse.drv). The two TSRs have a resident part (which stays in memory) and a transient part (which is only used to handle command line arguments, load the resident part, and configure it; but otherwise doesn't stay in memory). The resident part is entirely in one segment (`RESGROUP`), including all the data -it will need. All other segments will be dropped once the driver is installed +it will need. All other segments will be unloaded once the driver is installed (including the C runtime!). VBMOUSE is the only "native" free DOS mouse driver written in C I'm aware of. @@ -284,13 +286,13 @@ You will notice that most auxiliary functions are in .h files. This is due to laziness on my part. While most of the time these auxiliary functions are only used by one tool and one segment (i.e. the resident part uses it but not the transient part), -sometimes I need the same function different segments/binaries. The only way to do -is to build the multiple file several times with different settings. To avoid +sometimes I need the same function in different segments/binaries. The only way to do +that is to build the multiple file several times with different settings. To avoid that and the resulting makefile complications, I just put all auxiliary functions directly in the header files. * [mousmain.c](../tree/mousemain.c) is the transient part of the mouse driver, - while [mousetsr.c](../tree/mousetsr.c) is the resident part. + while [mousetsr.c](../tree/mousetsr.c) is the resident part. For example here is the [entry point for int33](https://git.javispedro.com/cgit/vbados.git/tree/mousetsr.c?id=8aea756f5094de4b357c125b75973d82328e0c31#n1055). A single function, `handle_mouse_event`, takes the mouse events from all the different sources (PS/2, VirtualBox, Windows386, etc.), and posts @@ -301,7 +303,7 @@ directly in the header files. * [sfmain.c](../tree/sfmain.c) and [sftsr.c](../tree/sftsr.c) are the transient/resident part (respectively) of the shared folders TSR. - This includes the entry point for int 2Fh/ah=11h, a.k.a. the "network redirector" interface. + This includes the entry point for int 2Fh/ah=11h, a.k.a. the "network redirector" interface. While the interface is undocumented, it is similar to a VFS layer, implementing the usual file system calls (open, close, readdir, mkdir, etc.). It uses lots of MS-DOS internals, @@ -315,11 +317,13 @@ directly in the header files. * [vbox.h](../tree/vbox.h), [vbox.c](../tree/vbox.c) implement initialization of the [VirtualBox guest-host interface](#virtualbox-communication), including PCI BIOS access and Virtual DMA. - [vboxdev.h](../tree/vboxdev.h) contains all the defines/struct from upstream + +* [vboxdev.h](../tree/vboxdev.h) contains all the defines/struct from upstream VirtualBox that are used in this driver (this file is a poor mix and mash of VirtualBox additions header files and thus is the only file of this repo under the MIT license). - [vboxhgcm.h](../tree/vboxhgcm.h), [vboxshfl.h](../tree/vboxshfl.h) contains + +* [vboxhgcm.h](../tree/vboxhgcm.h), [vboxshfl.h](../tree/vboxshfl.h) contains auxiliary functions for the HGCM (Host-Guest Communication) protocol and the shared folders protocol (both are only used by VBSF). @@ -358,7 +362,8 @@ directly in the header files. * [int33.h](../tree/int33.h) wrappers and defines for the int33 mouse API. * [int4Bvds.h](../tree/int4Bvds.h) wrappers for the - [Virtual DMA services](https://en.wikipedia.org/wiki/Virtual_DMA_Services). + [Virtual DMA services](https://en.wikipedia.org/wiki/Virtual_DMA_Services), + used for VirtualBox communication under protected mode. * [unixtime.h](../tree/unixtime.h) a (probably wrong) function to convert UNIX into DOS times, since we can't use the C runtime from the TSR. @@ -96,9 +96,6 @@ static __segment reallocate_to_umb(segment_t cur_seg, unsigned segment_size) // Create a new program instance including PSP at the new_segment copy_program(new_segment_psp, old_segment_psp, segment_size); - // Tell DOS to "switch" to the new program - dos_set_psp(new_segment_psp); - // Return the new segment return new_segment; } else { @@ -111,4 +108,28 @@ static __segment reallocate_to_umb(segment_t cur_seg, unsigned segment_size) } } +/** Called in case there is an error and we should free our HMA segment. */ +static void cancel_reallocation(segment_t new_seg) +{ + segment_t new_segment_psp = new_seg - (DOS_PSP_SIZE/16); + dos_free(new_segment_psp); +} + +/** Called right before doing the TSR call. + * Frees the old code segment. */ +static void finish_reallocation(segment_t old_segment_psp, segment_t new_seg) +{ + segment_t new_segment_psp = new_seg - (DOS_PSP_SIZE/16); + + // Tell DOS that we are "switching" to the new program in the HMA + dos_set_psp(new_segment_psp); + + // We are about to free() the old code segment, + // which is likely where the currently running function code resides. + dos_free(old_segment_psp); + + // Nothing should try to allocate memory between this and the actual TSR call, + // since it could overwrite the currently running code... ! +} + #endif // DOSTSR_H @@ -37,7 +37,7 @@ /** Enable the wheel. */ #define USE_WHEEL 1 /** Trace events verbosily */ -#define TRACE_EVENTS 0 +#define TRACE_EVENTS 1 #define VERSION_MAJOR 0 #define VERSION_MINOR 5 @@ -308,10 +308,7 @@ static __declspec(aborts) int install_driver(LPTSRDATA data, bool high) // If we reallocated ourselves to UMB, // it's time to free our initial conventional memory allocation if (high) { - // We are about to free() our own code segment. - // Nothing should try to allocate memory between this and the TSR call - // below, since it could overwrite our code... - dos_free(_psp); + finish_reallocation(_psp, FP_SEG(data)); } _dos_keep(EXIT_SUCCESS, get_paragraphs(resident_size)); @@ -479,7 +476,10 @@ int main(int argc, const char *argv[]) deallocate_environment(_psp); } err = configure_driver(data); - if (err) return EXIT_FAILURE; + if (err) { + if (high) cancel_reallocation(FP_SEG(data)); + return EXIT_FAILURE; + } return install_driver(data, high); } else if (stricmp(argv[argi], "uninstall") == 0) { if (!data) return driver_not_found(); @@ -426,10 +426,7 @@ static __declspec(aborts) int install_driver(LPTSRDATA data, bool high) // If we reallocated ourselves to UMB, // it's time to free our initial conventional memory allocation if (high) { - // We are about to free() our own code segment. - // Nothing should try to allocate memory between this and the TSR call - // below, since it could overwrite our code... - dos_free(_psp); + finish_reallocation(_psp, FP_SEG(data)); } _dos_keep(EXIT_SUCCESS, get_paragraphs(resident_size)); @@ -570,9 +567,14 @@ int main(int argc, const char *argv[]) deallocate_environment(_psp); } err = configure_driver(data); - if (err) return EXIT_FAILURE; + if (err) { + if (high) cancel_reallocation(FP_SEG(data)); + return EXIT_FAILURE; + } err = automount(data); - if (err) return EXIT_FAILURE; + if (err) { + // Automount errors are not fatal + } return install_driver(data, high); } else if (stricmp(argv[argi], "uninstall") == 0) { if (!data) return driver_not_found(); |