diff --git a/reactos/include/ddk/nt_vdd.h b/reactos/include/ddk/nt_vdd.h index e8d4a6678c3..2da16b55c8c 100644 --- a/reactos/include/ddk/nt_vdd.h +++ b/reactos/include/ddk/nt_vdd.h @@ -39,6 +39,47 @@ WINAPI VDDTerminateVDM(VOID); +/* VDD User Hooks */ + +typedef VOID +(WINAPI *PFNVDD_UCREATE)(USHORT DosPDB); + +typedef VOID +(WINAPI *PFNVDD_UTERMINATE)(USHORT DosPDB); + +typedef VOID +(WINAPI *PFNVDD_UBLOCK)(VOID); + +typedef VOID +(WINAPI *PFNVDD_URESUME)(VOID); + +// NOTE: Kept there for WinDDK compatibility, but it is in any case unused. +#ifndef NO_NTVDD_COMPAT +typedef struct _VDD_USER_HANDLERS { + HANDLE hvdd; + PFNVDD_UCREATE ucr_handler; + PFNVDD_UTERMINATE uterm_handler; + PFNVDD_UBLOCK ublock_handler; + PFNVDD_URESUME uresume_handler; + struct _VDD_USER_HANDLERS* next; +} VDD_USER_HANDLERS, *PVDD_USER_HANDLERS; +#endif + +BOOL +WINAPI +VDDInstallUserHook( + _In_ HANDLE hVdd, + _In_ PFNVDD_UCREATE Ucr_Handler, + _In_ PFNVDD_UTERMINATE Uterm_Handler, + _In_ PFNVDD_UBLOCK Ublock_Handler, + _In_ PFNVDD_URESUME Uresume_Handler); + +BOOL +WINAPI +VDDDeInstallUserHook( + _In_ HANDLE hVdd); + + /* IRQ services */ WORD @@ -122,7 +163,7 @@ VDDInstallIOHook( _In_ HANDLE hVdd, _In_ WORD cPortRange, _In_ PVDD_IO_PORTRANGE pPortRange, - _In_ PVDD_IO_HANDLERS IOhandler); + _In_ PVDD_IO_HANDLERS IoHandlers); VOID WINAPI diff --git a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/process.c b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/process.c index 93c10831513..a5140777f4d 100644 --- a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/process.c +++ b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/process.c @@ -27,6 +27,8 @@ #include "io.h" #include "hardware/ps2.h" +#include "vddsup.h" + /* PRIVATE FUNCTIONS **********************************************************/ static inline VOID DosSetPspCommandLine(WORD Segment, LPCSTR CommandLine) @@ -509,6 +511,9 @@ DWORD DosLoadExecutable(IN DOS_EXEC_TYPE LoadType, setSS(LoadSegment + Header->e_ss); setSP(Header->e_sp); + /* Notify VDDs of process execution */ + VDDCreateUserHook(Segment); + /* Execute */ DosSetProcessContext(Segment); CpuExecute(LoadSegment + Header->e_cs, Header->e_ip); @@ -596,6 +601,9 @@ DWORD DosLoadExecutable(IN DOS_EXEC_TYPE LoadType, */ *((LPWORD)SEG_OFF_TO_PTR(Segment, 0xFFFE)) = 0; + /* Notify VDDs of process execution */ + VDDCreateUserHook(Segment); + /* Execute */ DosSetProcessContext(Segment); CpuExecute(Segment, 0x100); @@ -613,7 +621,7 @@ Cleanup: { /* It was not successful, cleanup the DOS memory */ if (EnvBlock) DosFreeMemory(EnvBlock); - if (Segment) DosFreeMemory(Segment); + if (Segment) DosFreeMemory(Segment); } /* Unmap the file*/ @@ -850,6 +858,9 @@ VOID DosTerminateProcess(WORD Psp, BYTE ReturnCode, WORD KeepResident) /* Check if this PSP is it's own parent */ if (PspBlock->ParentPsp == Psp) goto Done; + /* Notify VDDs of process termination */ + VDDTerminateUserHook(Psp); + if (KeepResident == 0) { for (i = 0; i < PspBlock->HandleTableSize; i++) diff --git a/reactos/subsystems/mvdm/ntvdm/io.c b/reactos/subsystems/mvdm/ntvdm/io.c index ca8e207760c..775fe939fd0 100644 --- a/reactos/subsystems/mvdm/ntvdm/io.c +++ b/reactos/subsystems/mvdm/ntvdm/io.c @@ -497,19 +497,23 @@ EmulatorWriteIo(PFAST486_STATE State, BOOL WINAPI -VDDInstallIOHook(HANDLE hVdd, - WORD cPortRange, - PVDD_IO_PORTRANGE pPortRange, - PVDD_IO_HANDLERS IOhandler) +VDDInstallIOHook(IN HANDLE hVdd, + IN WORD cPortRange, + IN PVDD_IO_PORTRANGE pPortRange, + IN PVDD_IO_HANDLERS IoHandlers) { + WORD i; + /* Check validity of the VDD handle */ - if (hVdd == NULL || hVdd == INVALID_HANDLE_VALUE) return FALSE; + if (hVdd == NULL || hVdd == INVALID_HANDLE_VALUE) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } /* Loop for each range of I/O ports */ while (cPortRange--) { - WORD i; - /* Register the range of I/O ports */ for (i = pPortRange->First; i <= pPortRange->Last; ++i) { @@ -544,12 +548,11 @@ VDDInstallIOHook(HANDLE hVdd, IoPortProc[i].IoHandlers.OutsD = NULL; /* Save our handlers */ - IoPortProc[i].VddIoHandlers = *IOhandler; + IoPortProc[i].VddIoHandlers = *IoHandlers; } /* Go to the next range */ ++pPortRange; - ++IOhandler; } return TRUE; @@ -557,18 +560,22 @@ VDDInstallIOHook(HANDLE hVdd, VOID WINAPI -VDDDeInstallIOHook(HANDLE hVdd, - WORD cPortRange, - PVDD_IO_PORTRANGE pPortRange) +VDDDeInstallIOHook(IN HANDLE hVdd, + IN WORD cPortRange, + IN PVDD_IO_PORTRANGE pPortRange) { + WORD i; + /* Check validity of the VDD handle */ - if (hVdd == NULL || hVdd == INVALID_HANDLE_VALUE) return; + if (hVdd == NULL || hVdd == INVALID_HANDLE_VALUE) + { + SetLastError(ERROR_INVALID_PARAMETER); + return; + } /* Loop for each range of I/O ports */ while (cPortRange--) { - WORD i; - /* Unregister the range of I/O ports */ for (i = pPortRange->First; i <= pPortRange->Last; ++i) { diff --git a/reactos/subsystems/mvdm/ntvdm/memory.c b/reactos/subsystems/mvdm/ntvdm/memory.c index de9b18e771c..0b1c21996f1 100644 --- a/reactos/subsystems/mvdm/ntvdm/memory.c +++ b/reactos/subsystems/mvdm/ntvdm/memory.c @@ -388,7 +388,12 @@ VDDInstallMemoryHook(IN HANDLE hVdd, PLIST_ENTRY Pointer; /* Check validity of the VDD handle */ - if (hVdd == NULL || hVdd == INVALID_HANDLE_VALUE) return FALSE; + if (hVdd == NULL || hVdd == INVALID_HANDLE_VALUE) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + if (dwCount == 0) return FALSE; /* Make sure none of these pages are already allocated */ @@ -407,7 +412,11 @@ VDDInstallMemoryHook(IN HANDLE hVdd, { /* Create and initialize a new hook entry... */ Hook = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(*Hook)); - if (Hook == NULL) return FALSE; + if (Hook == NULL) + { + SetLastError(ERROR_OUTOFMEMORY); + return FALSE; + } Hook->hVdd = hVdd; Hook->Count = 0; @@ -456,6 +465,13 @@ VDDDeInstallMemoryHook(IN HANDLE hVdd, PVOID Address = (PVOID)REAL_TO_PHYS(FirstPage * PAGE_SIZE); SIZE_T Size = (LastPage - FirstPage + 1) * PAGE_SIZE; + /* Check validity of the VDD handle */ + if (hVdd == NULL || hVdd == INVALID_HANDLE_VALUE) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + if (dwCount == 0) return FALSE; /* Commit the pages */ @@ -504,6 +520,13 @@ VDDAllocMem(IN HANDLE hVdd, ULONG LastPage = ((ULONG_PTR)PHYS_TO_REAL(Address) + Size - 1) >> 12; SIZE_T RealSize = (LastPage - FirstPage + 1) * PAGE_SIZE; + /* Check validity of the VDD handle */ + if (hVdd == NULL || hVdd == INVALID_HANDLE_VALUE) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + if (Size == 0) return FALSE; /* Fixup the address */ @@ -545,6 +568,13 @@ VDDFreeMem(IN HANDLE hVdd, ULONG LastPage = ((ULONG_PTR)PHYS_TO_REAL(Address) + Size - 1) >> 12; SIZE_T RealSize = (LastPage - FirstPage + 1) * PAGE_SIZE; + /* Check validity of the VDD handle */ + if (hVdd == NULL || hVdd == INVALID_HANDLE_VALUE) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + if (Size == 0) return FALSE; /* Fixup the address */ diff --git a/reactos/subsystems/mvdm/ntvdm/ntvdm.h b/reactos/subsystems/mvdm/ntvdm/ntvdm.h index caf24d291f0..fddda0e2352 100644 --- a/reactos/subsystems/mvdm/ntvdm/ntvdm.h +++ b/reactos/subsystems/mvdm/ntvdm/ntvdm.h @@ -26,6 +26,9 @@ #include #include +// Do not include stuff that is only defined +// for backwards compatibility in nt_vdd.h +#define NO_NTVDD_COMPAT #include DWORD WINAPI SetLastConsoleEventActive(VOID); @@ -50,7 +53,7 @@ DWORD WINAPI SetLastConsoleEventActive(VOID); /* * Activate this line for Win2k compliancy */ -// #define WIN2K_COMPLIANT +#define WIN2K_COMPLIANT /* * Activate this line if you want advanced hardcoded debug facilities diff --git a/reactos/subsystems/mvdm/ntvdm/ntvdm.spec b/reactos/subsystems/mvdm/ntvdm/ntvdm.spec index 18adf3c8604..f1b643c7dbd 100644 --- a/reactos/subsystems/mvdm/ntvdm/ntvdm.spec +++ b/reactos/subsystems/mvdm/ntvdm/ntvdm.spec @@ -233,3 +233,6 @@ @ stdcall VDDSimulate16() @ stdcall host_simulate() VDDSimulate16 @ stdcall VDDTerminateVDM() + +@ stdcall VDDInstallUserHook(long ptr ptr ptr ptr) +@ stdcall VDDDeInstallUserHook(long) diff --git a/reactos/subsystems/mvdm/ntvdm/vddsup.c b/reactos/subsystems/mvdm/ntvdm/vddsup.c index a3eb1cd75ce..63468261d99 100644 --- a/reactos/subsystems/mvdm/ntvdm/vddsup.c +++ b/reactos/subsystems/mvdm/ntvdm/vddsup.c @@ -25,6 +25,20 @@ typedef struct _VDD_MODULE VDD_PROC DispatchRoutine; } VDD_MODULE, *PVDD_MODULE; +// WARNING: A structure with the same name exists in nt_vdd.h, +// however it is not declared because its inclusion was prevented +// with #define NO_NTVDD_COMPAT, see ntvdm.h +typedef struct _VDD_USER_HANDLERS +{ + LIST_ENTRY Entry; + + HANDLE hVdd; + PFNVDD_UCREATE Ucr_Handler; + PFNVDD_UTERMINATE Uterm_Handler; + PFNVDD_UBLOCK Ublock_Handler; + PFNVDD_URESUME Uresume_Handler; +} VDD_USER_HANDLERS, *PVDD_USER_HANDLERS; + /* PRIVATE VARIABLES **********************************************************/ // TODO: Maybe use a linked list. @@ -37,6 +51,8 @@ static VDD_MODULE VDDList[MAX_VDD_MODULES] = {{NULL}}; #define HANDLE_TO_ENTRY(Handle) ((Handle) - 1) #define IS_VALID_HANDLE(Handle) ((Handle) > 0 && (Handle) <= MAX_VDD_MODULES) +static LIST_ENTRY VddUserHooksList = {&VddUserHooksList, &VddUserHooksList}; + /* PRIVATE FUNCTIONS **********************************************************/ static USHORT GetNextFreeVDDEntry(VOID) @@ -144,7 +160,7 @@ static VOID WINAPI ThirdPartyVDDBop(LPWORD Stack) goto Quit; } - /* If we arrived there, that means everything is OK */ + /* If we reached this point, that means everything is OK */ /* Register the VDD DLL */ VDDList[Entry].hDll = hDll; @@ -347,6 +363,145 @@ Quit: /* PUBLIC FUNCTIONS ***********************************************************/ +/* + * NOTE: This function can be called multiple times by the same VDD, if + * it wants to install different hooks for a same action. The most recent + * registered hooks are called first. + */ +BOOL +WINAPI +VDDInstallUserHook(IN HANDLE hVdd, + IN PFNVDD_UCREATE Ucr_Handler, + IN PFNVDD_UTERMINATE Uterm_Handler, + IN PFNVDD_UBLOCK Ublock_Handler, + IN PFNVDD_URESUME Uresume_Handler) +{ + PVDD_USER_HANDLERS UserHook; + + /* Check validity of the VDD handle */ + if (hVdd == NULL || hVdd == INVALID_HANDLE_VALUE) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + // NOTE: If we want that a VDD can install hooks only once, it's here + // that we need to check whether a hook entry is already registered. + + /* Create and initialize a new hook entry... */ + UserHook = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(*UserHook)); + if (UserHook == NULL) + { + SetLastError(ERROR_OUTOFMEMORY); + return FALSE; + } + + UserHook->hVdd = hVdd; + UserHook->Ucr_Handler = Ucr_Handler; + UserHook->Uterm_Handler = Uterm_Handler; + UserHook->Ublock_Handler = Ublock_Handler; + UserHook->Uresume_Handler = Uresume_Handler; + + /* ... and add it at the top of the list of hooks */ + InsertHeadList(&VddUserHooksList, &UserHook->Entry); + + return TRUE; +} + +/* + * NOTE: This function uninstalls the latest installed hooks for a given VDD. + * It can be called multiple times by the same VDD to uninstall many hooks + * installed by multiple invocations of VDDInstallUserHook. + */ +BOOL +WINAPI +VDDDeInstallUserHook(IN HANDLE hVdd) +{ + PLIST_ENTRY Pointer; + PVDD_USER_HANDLERS UserHook; + + /* Check validity of the VDD handle */ + if (hVdd == NULL || hVdd == INVALID_HANDLE_VALUE) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + /* Uninstall the latest installed hooks */ + for (Pointer = VddUserHooksList.Flink; Pointer != &VddUserHooksList; Pointer = Pointer->Flink) + { + UserHook = CONTAINING_RECORD(Pointer, VDD_USER_HANDLERS, Entry); + if (UserHook->hVdd == hVdd) + { + RemoveEntryList(&UserHook->Entry); + RtlFreeHeap(RtlGetProcessHeap(), 0, UserHook); + return TRUE; + } + } + + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; +} + +/* + * Internal functions for calling the VDD user hooks. + * Their names come directly from the Windows 2kX DDK. + */ + +VOID VDDCreateUserHook(USHORT DosPDB) +{ + PLIST_ENTRY Pointer; + PVDD_USER_HANDLERS UserHook; + + /* Call the hooks starting from the most recent ones */ + for (Pointer = VddUserHooksList.Flink; Pointer != &VddUserHooksList; Pointer = Pointer->Flink) + { + UserHook = CONTAINING_RECORD(Pointer, VDD_USER_HANDLERS, Entry); + if (UserHook->Ucr_Handler) UserHook->Ucr_Handler(DosPDB); + } +} + +VOID VDDTerminateUserHook(USHORT DosPDB) +{ + PLIST_ENTRY Pointer; + PVDD_USER_HANDLERS UserHook; + + /* Call the hooks starting from the most recent ones */ + for (Pointer = VddUserHooksList.Flink; Pointer != &VddUserHooksList; Pointer = Pointer->Flink) + { + UserHook = CONTAINING_RECORD(Pointer, VDD_USER_HANDLERS, Entry); + if (UserHook->Uterm_Handler) UserHook->Uterm_Handler(DosPDB); + } +} + +VOID VDDBlockUserHook(VOID) +{ + PLIST_ENTRY Pointer; + PVDD_USER_HANDLERS UserHook; + + /* Call the hooks starting from the most recent ones */ + for (Pointer = VddUserHooksList.Flink; Pointer != &VddUserHooksList; Pointer = Pointer->Flink) + { + UserHook = CONTAINING_RECORD(Pointer, VDD_USER_HANDLERS, Entry); + if (UserHook->Ublock_Handler) UserHook->Ublock_Handler(); + } +} + +VOID VDDResumeUserHook(VOID) +{ + PLIST_ENTRY Pointer; + PVDD_USER_HANDLERS UserHook; + + /* Call the hooks starting from the most recent ones */ + for (Pointer = VddUserHooksList.Flink; Pointer != &VddUserHooksList; Pointer = Pointer->Flink) + { + UserHook = CONTAINING_RECORD(Pointer, VDD_USER_HANDLERS, Entry); + if (UserHook->Uresume_Handler) UserHook->Uresume_Handler(); + } +} + + + VOID VDDSupInitialize(VOID) { /* Register the 3rd-party VDD BOP Handler */ diff --git a/reactos/subsystems/mvdm/ntvdm/vddsup.h b/reactos/subsystems/mvdm/ntvdm/vddsup.h index 3b55e0bb337..478f6b0a676 100644 --- a/reactos/subsystems/mvdm/ntvdm/vddsup.h +++ b/reactos/subsystems/mvdm/ntvdm/vddsup.h @@ -11,6 +11,11 @@ /* FUNCTIONS ******************************************************************/ +VOID VDDCreateUserHook(USHORT DosPDB); +VOID VDDTerminateUserHook(USHORT DosPDB); +VOID VDDBlockUserHook(VOID); +VOID VDDResumeUserHook(VOID); + VOID VDDSupInitialize(VOID); #endif // _VDDSUP_H_ diff --git a/reactos/subsystems/mvdm/samples/testvdd/testvdd.c b/reactos/subsystems/mvdm/samples/testvdd/testvdd.c index a4f49576e01..de3e016c258 100644 --- a/reactos/subsystems/mvdm/samples/testvdd/testvdd.c +++ b/reactos/subsystems/mvdm/samples/testvdd/testvdd.c @@ -16,11 +16,12 @@ #define NDEBUG #include + +/* DEBUGGING HELPERS **********************************************************/ + // Enable this define to use DPRINT1 instead of MessageBox // #define DBG_SILENT -/* GLOBALS ********************************************************************/ - #ifdef DBG_SILENT #define VDD_DBG(...) \ @@ -81,8 +82,14 @@ #define VDD_DBG VddDbgMsg #endif + +/* GLOBALS ********************************************************************/ + HANDLE hVdd = NULL; + +/* VDD I/O PORTS TESTING ******************************************************/ + /* * Port hooks (serial ports) -- Each port range is for testing different port handlers. */ @@ -96,26 +103,6 @@ VDD_IO_PORTRANGE PortDefs[NUM_PORTS] = {0x2E8, 0x2EF} }; -// PFNVDD_INB PortInB; -// PFNVDD_INW PortInW; -// PFNVDD_INSB PortInsB; -// PFNVDD_INSW PortInsW; -// PFNVDD_OUTB PortOutB; -// PFNVDD_OUTW PortOutW; -// PFNVDD_OUTSB PortOutsB; -// PFNVDD_OUTSW PortOutsW; - -// VDD_IO_HANDLERS PortHandlers[NUM_PORTS] = -// { - // {PortInB, NULL , NULL , NULL , PortOutB, NULL , NULL , NULL }, - // {PortInB, PortInW, NULL , NULL , PortOutB, PortOutW, NULL , NULL }, - // {PortInB, NULL , PortInsB, NULL , PortOutB, NULL , PortOutsB, NULL }, - // {PortInB, NULL , NULL , PortInsW, PortOutB, NULL , NULL , PortOutsW}, -// }; - - -/* PRIVATE FUNCTIONS **********************************************************/ - VOID WINAPI PortInB(IN USHORT Port, @@ -151,8 +138,6 @@ PortOutW(IN USHORT Port, } - - VOID WINAPI PortInsB(IN USHORT Port, @@ -192,7 +177,6 @@ PortOutsW(IN USHORT Port, } - VDD_IO_HANDLERS PortHandlers[NUM_PORTS] = { {PortInB, NULL , NULL , NULL , PortOutB, NULL , NULL , NULL }, @@ -201,8 +185,11 @@ VDD_IO_HANDLERS PortHandlers[NUM_PORTS] = {PortInB, NULL , NULL , PortInsW, PortOutB, NULL , NULL , PortOutsW}, }; + +/* VDD MEMORY HOOKS TESTING ***************************************************/ + /* - * Memory hooking. Everything should be page-rounded. + * Everything should be page-rounded. */ #ifndef PAGE_SIZE @@ -300,60 +287,66 @@ FindHookableMemory(IN USHORT StartSegment, } -BOOLEAN -RegisterVDD(BOOLEAN Register) +/* VDD USER HOOKS TESTING *****************************************************/ + +VOID +WINAPI +Create1Handler(USHORT DosPDB) { - BOOLEAN Success = FALSE; - - if (Register) - { - /* Hook some IO ports */ - VDD_DBG("VDDInstallIOHook"); - Success = VDDInstallIOHook(hVdd, NUM_PORTS, PortDefs, PortHandlers); - if (!Success) - { - VDD_DBG("Unable to hook IO ports, terminate..."); - VDDTerminateVDM(); - } - - /* Add a memory handler */ - VDD_DBG("FindHookableMemory"); - HookedAddress = FindHookableMemory(MEM_SEG_START, 0x0000, - &HookedSegment, &HookedOffset); - if (HookedAddress == NULL) - { - VDD_DBG("Unable to install memory handler, terminate..."); - VDDTerminateVDM(); - } - VDD_DBG("Initialization finished!"); - } - else - { - Success = VDDFreeMem(hVdd, HookedAddress, MEM_SIZE); - if (!Success) VDD_DBG("Unable to free memory"); - - /* Uninstall the memory handler */ - VDD_DBG("VDDDeInstallMemoryHook"); - Success = VDDDeInstallMemoryHook(hVdd, HookedAddress, MEM_SIZE); - if (!Success) VDD_DBG("Memory handler uninstall failed"); - - VDD_DBG("VdmUnmapFlat"); - Success = VdmUnmapFlat(HookedSegment, HookedOffset, HookedAddress, getMODE()); - // FreeVDMPointer(GetVDMAddress(HookedSegment, HookedOffset), MEM_SIZE, HookedAddress, (getMSW() & MSW_PE)); - if (!Success) VDD_DBG("VdmUnmapFlat failed!"); - - /* Deregister the hooked IO ports */ - VDD_DBG("VDDDeInstallIOHook"); - VDDDeInstallIOHook(hVdd, NUM_PORTS, PortDefs); - - VDD_DBG("Cleanup finished!"); - Success = TRUE; - } - - return Success; + VDD_DBG("Create1Handler(0x%04x)", DosPDB); } -/* PUBLIC FUNCTIONS ***********************************************************/ +VOID +WINAPI +Create2Handler(USHORT DosPDB) +{ + VDD_DBG("Create2Handler(0x%04x)", DosPDB); +} + +VOID +WINAPI +Terminate1Handler(USHORT DosPDB) +{ + VDD_DBG("Terminate1Handler(0x%04x)", DosPDB); +} + +VOID +WINAPI +Terminate2Handler(USHORT DosPDB) +{ + VDD_DBG("Terminate2Handler(0x%04x)", DosPDB); +} + +VOID +WINAPI +Block1Handler(VOID) +{ + VDD_DBG("Block1Handler"); +} + +VOID +WINAPI +Block2Handler(VOID) +{ + VDD_DBG("Block2Handler"); +} + +VOID +WINAPI +Resume1Handler(VOID) +{ + VDD_DBG("Resume1Handler"); +} + +VOID +WINAPI +Resume2Handler(VOID) +{ + VDD_DBG("Resume2Handler"); +} + + +/* VDD INITIALIZATION AND REGISTRATION ****************************************/ VOID WINAPI @@ -385,7 +378,99 @@ TestVDDDispatch(VOID) setCF(0); } -/* ENTRY-POINT ****************************************************************/ +BOOLEAN +RegisterVDD(BOOLEAN Register) +{ + BOOLEAN Success = FALSE; + + if (Register) + { + /* Hook some IO ports */ + VDD_DBG("VDDInstallIOHook"); + Success = VDDInstallIOHook(hVdd, NUM_PORTS, PortDefs, PortHandlers); + if (!Success) + { + VDD_DBG("Unable to hook IO ports, terminate..."); + VDDTerminateVDM(); + } + + /* Add a memory handler */ + VDD_DBG("FindHookableMemory"); + HookedAddress = FindHookableMemory(MEM_SEG_START, 0x0000, + &HookedSegment, &HookedOffset); + if (HookedAddress == NULL) + { + VDD_DBG("Unable to install memory handler, terminate..."); + VDDTerminateVDM(); + } + + /* Add some user hooks -- Test order of initialization and calling */ + VDD_DBG("VDDInstallUserHook (1)"); + Success = VDDInstallUserHook(hVdd, + Create1Handler, + Terminate1Handler, + Block1Handler, + Resume1Handler); + if (!Success) + { + VDD_DBG("Unable to install user hooks (1)..."); + } + + VDD_DBG("VDDInstallUserHook (2)"); + Success = VDDInstallUserHook(hVdd, + Create2Handler, + Terminate2Handler, + Block2Handler, + Resume2Handler); + if (!Success) + { + VDD_DBG("Unable to install user hooks (2)..."); + } + + /* We have finished! */ + VDD_DBG("Initialization finished!"); + } + else + { + /* Remove the user hooks */ + VDD_DBG("VDDDeInstallUserHook (1)"); + Success = VDDDeInstallUserHook(hVdd); + if (!Success) VDD_DBG("Unable to uninstall user hooks (1)"); + + // TODO: See which hooks are still existing there... + + VDD_DBG("VDDDeInstallUserHook (2)"); + Success = VDDDeInstallUserHook(hVdd); + if (!Success) VDD_DBG("Unable to uninstall user hooks (2)"); + + VDD_DBG("VDDDeInstallUserHook (3)"); + Success = VDDDeInstallUserHook(hVdd); + if (!Success) VDD_DBG("EXPECTED ERROR: Unable to uninstall user hooks (3)"); + else VDD_DBG("UNEXPECTED ERROR: Uninstalling user hooks (3) succeeded?!"); + + /* Uninstall the memory handler */ + Success = VDDFreeMem(hVdd, HookedAddress, MEM_SIZE); + if (!Success) VDD_DBG("Unable to free memory"); + + VDD_DBG("VDDDeInstallMemoryHook"); + Success = VDDDeInstallMemoryHook(hVdd, HookedAddress, MEM_SIZE); + if (!Success) VDD_DBG("Memory handler uninstall failed"); + + VDD_DBG("VdmUnmapFlat"); + Success = VdmUnmapFlat(HookedSegment, HookedOffset, HookedAddress, getMODE()); + // FreeVDMPointer(GetVDMAddress(HookedSegment, HookedOffset), MEM_SIZE, HookedAddress, (getMSW() & MSW_PE)); + if (!Success) VDD_DBG("VdmUnmapFlat failed!"); + + /* Deregister the hooked IO ports */ + VDD_DBG("VDDDeInstallIOHook"); + VDDDeInstallIOHook(hVdd, NUM_PORTS, PortDefs); + + VDD_DBG("Cleanup finished!"); + Success = TRUE; + } + + return Success; +} BOOL WINAPI // VDDInitialize