mirror of
https://github.com/reactos/reactos.git
synced 2025-07-27 07:41:51 +00:00
[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:
parent
7f03ff50e9
commit
16d08be7b0
9 changed files with 439 additions and 99 deletions
|
@ -39,6 +39,47 @@ WINAPI
|
||||||
VDDTerminateVDM(VOID);
|
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 */
|
/* IRQ services */
|
||||||
|
|
||||||
WORD
|
WORD
|
||||||
|
@ -122,7 +163,7 @@ VDDInstallIOHook(
|
||||||
_In_ HANDLE hVdd,
|
_In_ HANDLE hVdd,
|
||||||
_In_ WORD cPortRange,
|
_In_ WORD cPortRange,
|
||||||
_In_ PVDD_IO_PORTRANGE pPortRange,
|
_In_ PVDD_IO_PORTRANGE pPortRange,
|
||||||
_In_ PVDD_IO_HANDLERS IOhandler);
|
_In_ PVDD_IO_HANDLERS IoHandlers);
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
WINAPI
|
WINAPI
|
||||||
|
|
|
@ -27,6 +27,8 @@
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
#include "hardware/ps2.h"
|
#include "hardware/ps2.h"
|
||||||
|
|
||||||
|
#include "vddsup.h"
|
||||||
|
|
||||||
/* PRIVATE FUNCTIONS **********************************************************/
|
/* PRIVATE FUNCTIONS **********************************************************/
|
||||||
|
|
||||||
static inline VOID DosSetPspCommandLine(WORD Segment, LPCSTR CommandLine)
|
static inline VOID DosSetPspCommandLine(WORD Segment, LPCSTR CommandLine)
|
||||||
|
@ -509,6 +511,9 @@ DWORD DosLoadExecutable(IN DOS_EXEC_TYPE LoadType,
|
||||||
setSS(LoadSegment + Header->e_ss);
|
setSS(LoadSegment + Header->e_ss);
|
||||||
setSP(Header->e_sp);
|
setSP(Header->e_sp);
|
||||||
|
|
||||||
|
/* Notify VDDs of process execution */
|
||||||
|
VDDCreateUserHook(Segment);
|
||||||
|
|
||||||
/* Execute */
|
/* Execute */
|
||||||
DosSetProcessContext(Segment);
|
DosSetProcessContext(Segment);
|
||||||
CpuExecute(LoadSegment + Header->e_cs, Header->e_ip);
|
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;
|
*((LPWORD)SEG_OFF_TO_PTR(Segment, 0xFFFE)) = 0;
|
||||||
|
|
||||||
|
/* Notify VDDs of process execution */
|
||||||
|
VDDCreateUserHook(Segment);
|
||||||
|
|
||||||
/* Execute */
|
/* Execute */
|
||||||
DosSetProcessContext(Segment);
|
DosSetProcessContext(Segment);
|
||||||
CpuExecute(Segment, 0x100);
|
CpuExecute(Segment, 0x100);
|
||||||
|
@ -850,6 +858,9 @@ VOID DosTerminateProcess(WORD Psp, BYTE ReturnCode, WORD KeepResident)
|
||||||
/* Check if this PSP is it's own parent */
|
/* Check if this PSP is it's own parent */
|
||||||
if (PspBlock->ParentPsp == Psp) goto Done;
|
if (PspBlock->ParentPsp == Psp) goto Done;
|
||||||
|
|
||||||
|
/* Notify VDDs of process termination */
|
||||||
|
VDDTerminateUserHook(Psp);
|
||||||
|
|
||||||
if (KeepResident == 0)
|
if (KeepResident == 0)
|
||||||
{
|
{
|
||||||
for (i = 0; i < PspBlock->HandleTableSize; i++)
|
for (i = 0; i < PspBlock->HandleTableSize; i++)
|
||||||
|
|
|
@ -497,19 +497,23 @@ EmulatorWriteIo(PFAST486_STATE State,
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
WINAPI
|
WINAPI
|
||||||
VDDInstallIOHook(HANDLE hVdd,
|
VDDInstallIOHook(IN HANDLE hVdd,
|
||||||
WORD cPortRange,
|
IN WORD cPortRange,
|
||||||
PVDD_IO_PORTRANGE pPortRange,
|
IN PVDD_IO_PORTRANGE pPortRange,
|
||||||
PVDD_IO_HANDLERS IOhandler)
|
IN PVDD_IO_HANDLERS IoHandlers)
|
||||||
{
|
{
|
||||||
|
WORD i;
|
||||||
|
|
||||||
/* Check validity of the VDD handle */
|
/* 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 */
|
/* Loop for each range of I/O ports */
|
||||||
while (cPortRange--)
|
while (cPortRange--)
|
||||||
{
|
{
|
||||||
WORD i;
|
|
||||||
|
|
||||||
/* Register the range of I/O ports */
|
/* Register the range of I/O ports */
|
||||||
for (i = pPortRange->First; i <= pPortRange->Last; ++i)
|
for (i = pPortRange->First; i <= pPortRange->Last; ++i)
|
||||||
{
|
{
|
||||||
|
@ -544,12 +548,11 @@ VDDInstallIOHook(HANDLE hVdd,
|
||||||
IoPortProc[i].IoHandlers.OutsD = NULL;
|
IoPortProc[i].IoHandlers.OutsD = NULL;
|
||||||
|
|
||||||
/* Save our handlers */
|
/* Save our handlers */
|
||||||
IoPortProc[i].VddIoHandlers = *IOhandler;
|
IoPortProc[i].VddIoHandlers = *IoHandlers;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Go to the next range */
|
/* Go to the next range */
|
||||||
++pPortRange;
|
++pPortRange;
|
||||||
++IOhandler;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -557,18 +560,22 @@ VDDInstallIOHook(HANDLE hVdd,
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
WINAPI
|
WINAPI
|
||||||
VDDDeInstallIOHook(HANDLE hVdd,
|
VDDDeInstallIOHook(IN HANDLE hVdd,
|
||||||
WORD cPortRange,
|
IN WORD cPortRange,
|
||||||
PVDD_IO_PORTRANGE pPortRange)
|
IN PVDD_IO_PORTRANGE pPortRange)
|
||||||
{
|
{
|
||||||
|
WORD i;
|
||||||
|
|
||||||
/* Check validity of the VDD handle */
|
/* 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 */
|
/* Loop for each range of I/O ports */
|
||||||
while (cPortRange--)
|
while (cPortRange--)
|
||||||
{
|
{
|
||||||
WORD i;
|
|
||||||
|
|
||||||
/* Unregister the range of I/O ports */
|
/* Unregister the range of I/O ports */
|
||||||
for (i = pPortRange->First; i <= pPortRange->Last; ++i)
|
for (i = pPortRange->First; i <= pPortRange->Last; ++i)
|
||||||
{
|
{
|
||||||
|
|
|
@ -388,7 +388,12 @@ VDDInstallMemoryHook(IN HANDLE hVdd,
|
||||||
PLIST_ENTRY Pointer;
|
PLIST_ENTRY Pointer;
|
||||||
|
|
||||||
/* Check validity of the VDD handle */
|
/* 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;
|
if (dwCount == 0) return FALSE;
|
||||||
|
|
||||||
/* Make sure none of these pages are already allocated */
|
/* Make sure none of these pages are already allocated */
|
||||||
|
@ -407,7 +412,11 @@ VDDInstallMemoryHook(IN HANDLE hVdd,
|
||||||
{
|
{
|
||||||
/* Create and initialize a new hook entry... */
|
/* Create and initialize a new hook entry... */
|
||||||
Hook = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(*Hook));
|
Hook = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(*Hook));
|
||||||
if (Hook == NULL) return FALSE;
|
if (Hook == NULL)
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_OUTOFMEMORY);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
Hook->hVdd = hVdd;
|
Hook->hVdd = hVdd;
|
||||||
Hook->Count = 0;
|
Hook->Count = 0;
|
||||||
|
@ -456,6 +465,13 @@ VDDDeInstallMemoryHook(IN HANDLE hVdd,
|
||||||
PVOID Address = (PVOID)REAL_TO_PHYS(FirstPage * PAGE_SIZE);
|
PVOID Address = (PVOID)REAL_TO_PHYS(FirstPage * PAGE_SIZE);
|
||||||
SIZE_T Size = (LastPage - FirstPage + 1) * 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;
|
if (dwCount == 0) return FALSE;
|
||||||
|
|
||||||
/* Commit the pages */
|
/* Commit the pages */
|
||||||
|
@ -504,6 +520,13 @@ VDDAllocMem(IN HANDLE hVdd,
|
||||||
ULONG LastPage = ((ULONG_PTR)PHYS_TO_REAL(Address) + Size - 1) >> 12;
|
ULONG LastPage = ((ULONG_PTR)PHYS_TO_REAL(Address) + Size - 1) >> 12;
|
||||||
SIZE_T RealSize = (LastPage - FirstPage + 1) * PAGE_SIZE;
|
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;
|
if (Size == 0) return FALSE;
|
||||||
|
|
||||||
/* Fixup the address */
|
/* Fixup the address */
|
||||||
|
@ -545,6 +568,13 @@ VDDFreeMem(IN HANDLE hVdd,
|
||||||
ULONG LastPage = ((ULONG_PTR)PHYS_TO_REAL(Address) + Size - 1) >> 12;
|
ULONG LastPage = ((ULONG_PTR)PHYS_TO_REAL(Address) + Size - 1) >> 12;
|
||||||
SIZE_T RealSize = (LastPage - FirstPage + 1) * PAGE_SIZE;
|
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;
|
if (Size == 0) return FALSE;
|
||||||
|
|
||||||
/* Fixup the address */
|
/* Fixup the address */
|
||||||
|
|
|
@ -26,6 +26,9 @@
|
||||||
#include <winuser.h>
|
#include <winuser.h>
|
||||||
#include <subsys/win/vdm.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>
|
#include <vddsvc.h>
|
||||||
|
|
||||||
DWORD WINAPI SetLastConsoleEventActive(VOID);
|
DWORD WINAPI SetLastConsoleEventActive(VOID);
|
||||||
|
@ -50,7 +53,7 @@ DWORD WINAPI SetLastConsoleEventActive(VOID);
|
||||||
/*
|
/*
|
||||||
* Activate this line for Win2k compliancy
|
* Activate this line for Win2k compliancy
|
||||||
*/
|
*/
|
||||||
// #define WIN2K_COMPLIANT
|
#define WIN2K_COMPLIANT
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Activate this line if you want advanced hardcoded debug facilities
|
* Activate this line if you want advanced hardcoded debug facilities
|
||||||
|
|
|
@ -233,3 +233,6 @@
|
||||||
@ stdcall VDDSimulate16()
|
@ stdcall VDDSimulate16()
|
||||||
@ stdcall host_simulate() VDDSimulate16
|
@ stdcall host_simulate() VDDSimulate16
|
||||||
@ stdcall VDDTerminateVDM()
|
@ stdcall VDDTerminateVDM()
|
||||||
|
|
||||||
|
@ stdcall VDDInstallUserHook(long ptr ptr ptr ptr)
|
||||||
|
@ stdcall VDDDeInstallUserHook(long)
|
||||||
|
|
|
@ -25,6 +25,20 @@ typedef struct _VDD_MODULE
|
||||||
VDD_PROC DispatchRoutine;
|
VDD_PROC DispatchRoutine;
|
||||||
} VDD_MODULE, *PVDD_MODULE;
|
} 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 **********************************************************/
|
/* PRIVATE VARIABLES **********************************************************/
|
||||||
|
|
||||||
// TODO: Maybe use a linked list.
|
// 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 HANDLE_TO_ENTRY(Handle) ((Handle) - 1)
|
||||||
#define IS_VALID_HANDLE(Handle) ((Handle) > 0 && (Handle) <= MAX_VDD_MODULES)
|
#define IS_VALID_HANDLE(Handle) ((Handle) > 0 && (Handle) <= MAX_VDD_MODULES)
|
||||||
|
|
||||||
|
static LIST_ENTRY VddUserHooksList = {&VddUserHooksList, &VddUserHooksList};
|
||||||
|
|
||||||
/* PRIVATE FUNCTIONS **********************************************************/
|
/* PRIVATE FUNCTIONS **********************************************************/
|
||||||
|
|
||||||
static USHORT GetNextFreeVDDEntry(VOID)
|
static USHORT GetNextFreeVDDEntry(VOID)
|
||||||
|
@ -144,7 +160,7 @@ static VOID WINAPI ThirdPartyVDDBop(LPWORD Stack)
|
||||||
goto Quit;
|
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 */
|
/* Register the VDD DLL */
|
||||||
VDDList[Entry].hDll = hDll;
|
VDDList[Entry].hDll = hDll;
|
||||||
|
@ -347,6 +363,145 @@ Quit:
|
||||||
|
|
||||||
/* PUBLIC FUNCTIONS ***********************************************************/
|
/* 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)
|
VOID VDDSupInitialize(VOID)
|
||||||
{
|
{
|
||||||
/* Register the 3rd-party VDD BOP Handler */
|
/* Register the 3rd-party VDD BOP Handler */
|
||||||
|
|
|
@ -11,6 +11,11 @@
|
||||||
|
|
||||||
/* FUNCTIONS ******************************************************************/
|
/* FUNCTIONS ******************************************************************/
|
||||||
|
|
||||||
|
VOID VDDCreateUserHook(USHORT DosPDB);
|
||||||
|
VOID VDDTerminateUserHook(USHORT DosPDB);
|
||||||
|
VOID VDDBlockUserHook(VOID);
|
||||||
|
VOID VDDResumeUserHook(VOID);
|
||||||
|
|
||||||
VOID VDDSupInitialize(VOID);
|
VOID VDDSupInitialize(VOID);
|
||||||
|
|
||||||
#endif // _VDDSUP_H_
|
#endif // _VDDSUP_H_
|
||||||
|
|
|
@ -16,11 +16,12 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* DEBUGGING HELPERS **********************************************************/
|
||||||
|
|
||||||
// Enable this define to use DPRINT1 instead of MessageBox
|
// Enable this define to use DPRINT1 instead of MessageBox
|
||||||
// #define DBG_SILENT
|
// #define DBG_SILENT
|
||||||
|
|
||||||
/* GLOBALS ********************************************************************/
|
|
||||||
|
|
||||||
#ifdef DBG_SILENT
|
#ifdef DBG_SILENT
|
||||||
|
|
||||||
#define VDD_DBG(...) \
|
#define VDD_DBG(...) \
|
||||||
|
@ -81,8 +82,14 @@
|
||||||
#define VDD_DBG VddDbgMsg
|
#define VDD_DBG VddDbgMsg
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* GLOBALS ********************************************************************/
|
||||||
|
|
||||||
HANDLE hVdd = NULL;
|
HANDLE hVdd = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
/* VDD I/O PORTS TESTING ******************************************************/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Port hooks (serial ports) -- Each port range is for testing different port handlers.
|
* 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}
|
{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
|
VOID
|
||||||
WINAPI
|
WINAPI
|
||||||
PortInB(IN USHORT Port,
|
PortInB(IN USHORT Port,
|
||||||
|
@ -151,8 +138,6 @@ PortOutW(IN USHORT Port,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
WINAPI
|
WINAPI
|
||||||
PortInsB(IN USHORT Port,
|
PortInsB(IN USHORT Port,
|
||||||
|
@ -192,7 +177,6 @@ PortOutsW(IN USHORT Port,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
VDD_IO_HANDLERS PortHandlers[NUM_PORTS] =
|
VDD_IO_HANDLERS PortHandlers[NUM_PORTS] =
|
||||||
{
|
{
|
||||||
{PortInB, NULL , NULL , NULL , PortOutB, NULL , NULL , NULL },
|
{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},
|
{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
|
#ifndef PAGE_SIZE
|
||||||
|
@ -300,60 +287,66 @@ FindHookableMemory(IN USHORT StartSegment,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BOOLEAN
|
/* VDD USER HOOKS TESTING *****************************************************/
|
||||||
RegisterVDD(BOOLEAN Register)
|
|
||||||
|
VOID
|
||||||
|
WINAPI
|
||||||
|
Create1Handler(USHORT DosPDB)
|
||||||
{
|
{
|
||||||
BOOLEAN Success = FALSE;
|
VDD_DBG("Create1Handler(0x%04x)", DosPDB);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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
|
VOID
|
||||||
WINAPI
|
WINAPI
|
||||||
|
@ -385,7 +378,99 @@ TestVDDDispatch(VOID)
|
||||||
setCF(0);
|
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
|
BOOL
|
||||||
WINAPI // VDDInitialize
|
WINAPI // VDDInitialize
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue