[NTVDM][DDK]

Implement VDD user hooks: they are called when a DOS program is started or terminated, and when the VM enters a blocking state or is resumed.

[NTVDM]
- Do some parameter checks and set last errors in VDD memory helpers.
- Fix a bug in VDDInstallIOHook when installing IO hooks: the IoHandlers pointer MUST NEVER be incremented!!

[TESTVDD]: Update my test VDD with tests for the user hooks.

svn path=/trunk/; revision=67671
This commit is contained in:
Hermès Bélusca-Maïto 2015-05-11 23:04:24 +00:00
parent 7f03ff50e9
commit 16d08be7b0
9 changed files with 439 additions and 99 deletions

View file

@ -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

View file

@ -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++)

View file

@ -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)
{

View file

@ -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 */

View file

@ -26,6 +26,9 @@
#include <winuser.h>
#include <subsys/win/vdm.h>
// Do not include stuff that is only defined
// for backwards compatibility in nt_vdd.h
#define NO_NTVDD_COMPAT
#include <vddsvc.h>
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

View file

@ -233,3 +233,6 @@
@ stdcall VDDSimulate16()
@ stdcall host_simulate() VDDSimulate16
@ stdcall VDDTerminateVDM()
@ stdcall VDDInstallUserHook(long ptr ptr ptr ptr)
@ stdcall VDDDeInstallUserHook(long)

View file

@ -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 */

View file

@ -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_

View file

@ -16,11 +16,12 @@
#define NDEBUG
#include <debug.h>
/* 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