WindowsXP/windows/core/ntgdi/gre/watchdog.cxx
2025-04-27 07:49:33 -04:00

3338 lines
83 KiB
C++

/******************************Module*Header*******************************\
* Module Name: watchdog.cxx *
* *
* Copyright (c) 1990-2002 Microsoft Corporation *
* *
* This module hooks the display drivers "Drv" entry points. It will *
* enter/exit the watchdog appropriately, and set up try/except blocks to *
* catch threads that get stuck in a driver. *
* *
* Erick Smith - ericks - *
\**************************************************************************/
#include "precomp.hxx"
#include "muclean.hxx"
#define MAKESOFTWAREEXCEPTION(Severity, Facility, Exception) \
((DWORD) ((Severity << 30) | (1 << 29) | (Facility << 16) | (Exception)))
#define SE_THREAD_STUCK MAKESOFTWAREEXCEPTION(3,0,1)
typedef struct _CONTEXT_NODE
{
PVOID Context;
PLDEV pldev;
} CONTEXT_NODE, *PCONTEXT_NODE;
PASSOCIATION_NODE gAssociationList = NULL;
//
// The following routines are used to maintain an association between the
// data actually passed into a driver entry point, and the LDEV for the
// driver. We need this association because we need access to the LDEV
// in order to look up the actual driver entry point.
//
// For example, when the system call the DrvEnablePDEV entry point, the
// driver will create it's own PDEV structure. We will create an
// association node to associate this driver created PDEV with the LDEV for
// that driver. Now on subsequent calls into the driver, we can retrieve
// the PDEV via various methods, and then use that to find the LDEV. Once we
// have the LDEV we can look up the correct entry point into the driver.
//
PASSOCIATION_NODE
AssociationCreateNode(
VOID
)
{
PASSOCIATION_NODE Node;
Node = (PASSOCIATION_NODE) PALLOCMEM(sizeof(ASSOCIATION_NODE), GDITAG_DRVSUP);
return Node;
}
VOID
AssociationDeleteNode(
PASSOCIATION_NODE Node
)
{
if (Node) {
VFREEMEM(Node);
}
}
VOID
AssociationInsertNode(
PASSOCIATION_NODE Node
)
{
GreAcquireFastMutex(gAssociationListMutex);
Node->next = gAssociationList;
gAssociationList = Node;
GreReleaseFastMutex(gAssociationListMutex);
}
VOID
AssociationInsertNodeAtTail(
PASSOCIATION_NODE Node
)
{
GreAcquireFastMutex(gAssociationListMutex);
if (gAssociationList) {
PASSOCIATION_NODE Curr;
Curr = gAssociationList;
while (Curr && Curr->next) {
Curr = Curr->next;
}
//
// The following test for NULL is not really required, but I
// added it to make prefast happy.
//
if (Curr) {
Curr->next = Node;
}
} else {
gAssociationList = Node;
}
GreReleaseFastMutex(gAssociationListMutex);
}
PASSOCIATION_NODE
AssociationRemoveNode(
ULONG_PTR key
)
{
PASSOCIATION_NODE Node;
GreAcquireFastMutex(gAssociationListMutex);
//
// first find the correct node
//
Node = gAssociationList;
while (Node && (Node->key != key)) {
Node = Node->next;
}
if (Node) {
if (gAssociationList == Node) {
gAssociationList = Node->next;
} else {
PASSOCIATION_NODE curr = gAssociationList;
while (curr && (curr->next != Node)) {
curr = curr->next;
}
if (curr) {
curr->next = Node->next;
}
}
}
GreReleaseFastMutex(gAssociationListMutex);
return Node;
}
BOOLEAN
AssociationIsNodeInList(
PASSOCIATION_NODE Node
)
{
PASSOCIATION_NODE Curr = gAssociationList;
while (Curr) {
//
// We only have to check if the key and the hsurf value
// are similar.
//
if ((Curr->key == Node->key) &&
(Curr->hsurf == Node->hsurf)) {
return TRUE;
}
Curr = Curr->next;
}
return FALSE;
}
ULONG_PTR
AssociationRetrieveData(
ULONG_PTR key
)
{
PASSOCIATION_NODE Node;
GreAcquireFastMutex(gAssociationListMutex);
Node = gAssociationList;
while (Node) {
if (Node->key == key) {
break;
}
Node = Node->next;
}
GreReleaseFastMutex(gAssociationListMutex);
if (Node) {
return Node->data;
} else {
return NULL;
}
}
PFN
dhpdevRetrievePfn(
ULONG_PTR dhpdev,
ULONG Index
)
{
PLDEV pldev = (PLDEV)AssociationRetrieveData(dhpdev);
return pldev->apfnDriver[Index];
}
PLDEV
dhpdevRetrieveLdev(
DHPDEV dhpdev
)
{
return (PLDEV)AssociationRetrieveData((ULONG_PTR)dhpdev);
}
ULONG
WatchdogDrvGetModesEmpty(
IN HANDLE hDriver,
IN ULONG cjSize,
OUT DEVMODEW *pdm
)
/*++
Routine Description:
This function replaces a drivers DrvGetModes function when
and EA has occured. We do this so that we can stop reporting
modes for this device.
--*/
{
//
// Indicate NO modes!
//
return 0;
}
VOID
WatchdogRecoveryThread(
IN PVOID Context
)
{
VIDEO_WIN32K_CALLBACKS_PARAMS Params;
UNREFERENCED_PARAMETER(Context);
Params.CalloutType = VideoChangeDisplaySettingsCallout;
Params.Param = 0;
Params.PhysDisp = NULL;
Params.Status = 0;
//
// It is possible we'll hit an EA and try to recover for USER has
// finished initializing. Therefore the VideoPortCallout may fail
// with a STATUS_INVALID_HANDLE. We'll keep trying (with a delay)
// until we get a different status code.
//
do {
VideoPortCallout(&Params);
if (Params.Status == STATUS_INVALID_HANDLE) {
ZwYieldExecution();
}
} while (Params.Status == STATUS_INVALID_HANDLE);
PsTerminateSystemThread(STATUS_SUCCESS);
}
VOID
HandleStuckThreadException(
PLDEV pldev
)
/*++
Wake up a user mode thread waiting to reset the display resolution.
--*/
{
PKEVENT StuckThreadEvent;
UNICODE_STRING EventName;
HANDLE EventHandle;
HANDLE ThreadHandle;
OBJECT_ATTRIBUTES ObjectAttributes;
NTSTATUS Status;
//
// First disable all entries in the dispatch table in the pldev. This
// way we can stop future threads from entring the driver.
//
pldev->bThreadStuck = TRUE;
//
// Replacd the DrvGetModes function for the driver such that the
// driver reports no modes!
//
pldev->apfn[INDEX_DrvGetModes] = (PFN) WatchdogDrvGetModesEmpty;
//
// Remove non-vga device from graphics device list to stop the
// system from trying to continue using the current device.
//
// What do we do about multi-mon?
//
DrvPrepareForEARecovery();
//
// Create a thread to do the work of changing the display resolution.
//
InitializeObjectAttributes(&ObjectAttributes,
NULL,
OBJ_KERNEL_HANDLE,
NULL,
NULL);
Status = PsCreateSystemThread(&ThreadHandle,
(ACCESS_MASK) 0,
&ObjectAttributes,
NtCurrentProcess(),
NULL,
WatchdogRecoveryThread,
NULL);
if (NT_SUCCESS(Status) == TRUE) {
ZwClose(ThreadHandle);
} else {
DbgPrint("Warning, we failed to create the Recovery Thread\n");
}
//
// Clean up any pending drivers locks that this thread is holding
//
GreFreeSemaphoresForCurrentThread();
}
DHPDEV APIENTRY
WatchdogDrvEnablePDEV(
DEVMODEW *pdm,
LPWSTR pwszLogAddress,
ULONG cPat,
HSURF *phsurfPatterns,
ULONG cjCaps,
ULONG *pdevcaps,
ULONG cjDevInfo,
DEVINFO *pdi,
HDEV hdev,
LPWSTR pwszDeviceName,
HANDLE hDriver
)
{
PDEV *ppdev = (PDEV *)hdev;
DHPDEV dhpdevRet = NULL;
if (ppdev->pldev->bThreadStuck == FALSE) {
PFN_DrvEnablePDEV pfn = (PFN_DrvEnablePDEV) ppdev->pldev->apfnDriver[INDEX_DrvEnablePDEV];
PASSOCIATION_NODE Node = AssociationCreateNode();
if (Node) {
Node->data = (ULONG_PTR)ppdev->pldev;
Node->key = NULL;
__try {
Node->key = (ULONG_PTR)pfn(pdm,
pwszLogAddress,
cPat,
phsurfPatterns,
cjCaps,
(GDIINFO *)pdevcaps,
cjDevInfo,
pdi,
hdev,
pwszDeviceName,
hDriver);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
//
// Handle stuck thread excepton
//
HandleStuckThreadException(ppdev->pldev);
}
if (Node->key) {
dhpdevRet = (DHPDEV) Node->key;
AssociationInsertNode(Node);
} else {
AssociationDeleteNode(Node);
}
}
}
return dhpdevRet;
}
VOID APIENTRY
WatchdogDrvCompletePDEV(
DHPDEV dhpdev,
HDEV hdev
)
{
PFN_DrvCompletePDEV pfn = (PFN_DrvCompletePDEV) dhpdevRetrievePfn((ULONG_PTR)dhpdev,INDEX_DrvCompletePDEV);
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev(dhpdev)->bThreadStuck) {
return;
}
__try {
pfn(dhpdev, hdev);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
//
// Handle stuck thread excepton
//
HandleStuckThreadException(dhpdevRetrieveLdev(dhpdev));
}
}
VOID APIENTRY
WatchdogDrvDisablePDEV(
DHPDEV dhpdev
)
{
PFN_DrvDisablePDEV pfn = (PFN_DrvDisablePDEV) dhpdevRetrievePfn((ULONG_PTR)dhpdev,INDEX_DrvDisablePDEV);
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev(dhpdev)->bThreadStuck) {
return;
}
__try {
pfn(dhpdev);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
//
// Handle stuck thread excepton
//
HandleStuckThreadException(dhpdevRetrieveLdev(dhpdev));
}
AssociationDeleteNode(AssociationRemoveNode((ULONG_PTR)dhpdev));
}
HSURF APIENTRY
WatchdogDrvEnableSurface(
DHPDEV dhpdev
)
{
PFN_DrvEnableSurface pfn = (PFN_DrvEnableSurface) dhpdevRetrievePfn((ULONG_PTR)dhpdev,INDEX_DrvEnableSurface);
HSURF hsurfRet = NULL;
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev(dhpdev)->bThreadStuck) {
return NULL;
}
__try {
hsurfRet = pfn(dhpdev);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
//
// Handle stuck thread excepton
//
HandleStuckThreadException(dhpdevRetrieveLdev(dhpdev));
}
return hsurfRet;
}
VOID APIENTRY
WatchdogDrvDisableSurface(
DHPDEV dhpdev
)
{
PFN_DrvDisableSurface pfn = (PFN_DrvDisableSurface) dhpdevRetrievePfn((ULONG_PTR)dhpdev,INDEX_DrvDisableSurface);
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev(dhpdev)->bThreadStuck) {
return;
}
__try {
pfn(dhpdev);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
//
// Handle stuck thread excepton
//
HandleStuckThreadException(dhpdevRetrieveLdev(dhpdev));
}
}
BOOL APIENTRY
WatchdogDrvAssertMode(
DHPDEV dhpdev,
BOOL bEnable
)
{
PFN_DrvAssertMode pfn = (PFN_DrvAssertMode) dhpdevRetrievePfn((ULONG_PTR)dhpdev,INDEX_DrvAssertMode);
BOOL bRet = TRUE;
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev(dhpdev)->bThreadStuck) {
return TRUE;
}
__try {
bRet = pfn(dhpdev, bEnable);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
//
// Handle stuck thread excepton
//
HandleStuckThreadException(dhpdevRetrieveLdev(dhpdev));
}
return bRet;
}
BOOL APIENTRY
WatchdogDrvResetPDEV(
DHPDEV dhpdevOld,
DHPDEV dhpdevNew
)
{
PFN_DrvResetPDEV pfn = (PFN_DrvResetPDEV) dhpdevRetrievePfn((ULONG_PTR)dhpdevOld,INDEX_DrvResetPDEV);
BOOL bRet = TRUE;
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev(dhpdevOld)->bThreadStuck) {
return TRUE;
}
__try {
bRet = pfn(dhpdevOld, dhpdevNew);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
//
// Handle stuck thread excepton
//
HandleStuckThreadException(dhpdevRetrieveLdev(dhpdevOld));
}
return bRet;
}
HBITMAP APIENTRY
WatchdogDrvCreateDeviceBitmap(
DHPDEV dhpdev,
SIZEL sizl,
ULONG iFormat
)
{
PFN_DrvCreateDeviceBitmap pfn = (PFN_DrvCreateDeviceBitmap) dhpdevRetrievePfn((ULONG_PTR)dhpdev,INDEX_DrvCreateDeviceBitmap);
HBITMAP hbitmapRet = NULL;
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev(dhpdev)->bThreadStuck == FALSE) {
PASSOCIATION_NODE Node = AssociationCreateNode();
if (Node) {
__try {
hbitmapRet = pfn(dhpdev, sizl, iFormat);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
//
// Handle stuck thread excepton
//
HandleStuckThreadException(dhpdevRetrieveLdev(dhpdev));
}
if (hbitmapRet && ((ULONG_PTR)hbitmapRet != -1)) {
//
// Get the DHSURF that is associated with the hbitmap, and
// cache it away so we can look it up when a DrvDeleteDeviceBitmap
// call comes down.
//
SURFREF so;
so.vAltCheckLockIgnoreStockBit((HSURF)hbitmapRet);
Node->key = (ULONG_PTR)so.ps->dhsurf();
Node->data = (ULONG_PTR)dhpdevRetrieveLdev(dhpdev);
Node->hsurf = (ULONG_PTR)hbitmapRet;
//
// If an association node already exists, with this association
// then use it.
//
if (AssociationIsNodeInList(Node) == FALSE) {
AssociationInsertNodeAtTail(Node);
} else {
AssociationDeleteNode(Node);
}
} else {
AssociationDeleteNode(Node);
}
}
}
return hbitmapRet;
}
VOID APIENTRY
WatchdogDrvDeleteDeviceBitmap(
IN DHSURF dhsurf
)
{
PFN_DrvDeleteDeviceBitmap pfn = (PFN_DrvDeleteDeviceBitmap) dhpdevRetrievePfn((ULONG_PTR)dhsurf,INDEX_DrvDeleteDeviceBitmap);
if (dhpdevRetrieveLdev((DHPDEV)dhsurf)->bThreadStuck) {
return;
}
__try {
pfn(dhsurf);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
//
// Handle stuck thread excepton
//
HandleStuckThreadException(dhpdevRetrieveLdev((DHPDEV)dhsurf));
}
AssociationDeleteNode(AssociationRemoveNode((ULONG_PTR)dhsurf));
}
BOOL APIENTRY
WatchdogDrvRealizeBrush(
BRUSHOBJ *pbo,
SURFOBJ *psoTarget,
SURFOBJ *psoPattern,
SURFOBJ *psoMask,
XLATEOBJ *pxlo,
ULONG iHatch
)
{
PFN_DrvRealizeBrush pfn = (PFN_DrvRealizeBrush) dhpdevRetrievePfn((ULONG_PTR)psoTarget->dhpdev,INDEX_DrvRealizeBrush);
BOOL bRet = TRUE;
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev(psoTarget->dhpdev)->bThreadStuck) {
return TRUE;
}
__try {
bRet = pfn(pbo, psoTarget, psoPattern, psoMask, pxlo, iHatch);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
//
// Handle stuck thread excepton
//
HandleStuckThreadException(dhpdevRetrieveLdev(psoTarget->dhpdev));
}
return bRet;
}
ULONG APIENTRY
WatchdogDrvDitherColor(
DHPDEV dhpdev,
ULONG iMode,
ULONG rgb,
ULONG *pul
)
{
PFN_DrvDitherColor pfn = (PFN_DrvDitherColor) dhpdevRetrievePfn((ULONG_PTR)dhpdev,INDEX_DrvDitherColor);
ULONG ulRet = 0;
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev(dhpdev)->bThreadStuck) {
return 0;
}
__try {
ulRet = pfn(dhpdev, iMode, rgb, pul);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
//
// Handle stuck thread excepton
//
HandleStuckThreadException(dhpdevRetrieveLdev(dhpdev));
}
return ulRet;
}
BOOL APIENTRY
WatchdogDrvStrokePath(
SURFOBJ *pso,
PATHOBJ *ppo,
CLIPOBJ *pco,
XFORMOBJ *pxo,
BRUSHOBJ *pbo,
POINTL *pptlBrushOrg,
LINEATTRS *plineattrs,
MIX mix
)
{
PFN_DrvStrokePath pfn = (PFN_DrvStrokePath) dhpdevRetrievePfn((ULONG_PTR)pso->dhpdev,INDEX_DrvStrokePath);
BOOL bRet = TRUE;
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev(pso->dhpdev)->bThreadStuck) {
return TRUE;
}
__try {
bRet = pfn(pso, ppo, pco, pxo, pbo, pptlBrushOrg, plineattrs, mix);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
//
// Handle stuck thread excepton
//
HandleStuckThreadException(dhpdevRetrieveLdev(pso->dhpdev));
}
return bRet;
}
BOOL APIENTRY
WatchdogDrvFillPath(
SURFOBJ *pso,
PATHOBJ *ppo,
CLIPOBJ *pco,
BRUSHOBJ *pbo,
POINTL *pptlBrushOrg,
MIX mix,
FLONG flOptions
)
{
PFN_DrvFillPath pfn = (PFN_DrvFillPath) dhpdevRetrievePfn((ULONG_PTR)pso->dhpdev,INDEX_DrvFillPath);
BOOL bRet = TRUE;
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev(pso->dhpdev)->bThreadStuck) {
return TRUE;
}
__try {
bRet = pfn(pso, ppo, pco, pbo, pptlBrushOrg, mix, flOptions);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
//
// Handle stuck thread excepton
//
HandleStuckThreadException(dhpdevRetrieveLdev(pso->dhpdev));
}
return bRet;
}
BOOL APIENTRY
WatchdogDrvStrokeAndFillPath(
SURFOBJ *pso,
PATHOBJ *ppo,
CLIPOBJ *pco,
XFORMOBJ *pxo,
BRUSHOBJ *pboStroke,
LINEATTRS *plineattrs,
BRUSHOBJ *pboFill,
POINTL *pptlBrushOrg,
MIX mixFill,
FLONG flOptions
)
{
PFN_DrvStrokeAndFillPath pfn = (PFN_DrvStrokeAndFillPath) dhpdevRetrievePfn((ULONG_PTR)pso->dhpdev,INDEX_DrvStrokeAndFillPath);
BOOL bRet = TRUE;
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev(pso->dhpdev)->bThreadStuck) {
return TRUE;
}
__try {
bRet = pfn(pso, ppo, pco, pxo, pboStroke, plineattrs, pboFill, pptlBrushOrg, mixFill, flOptions);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
//
// Handle stuck thread excepton
//
HandleStuckThreadException(dhpdevRetrieveLdev(pso->dhpdev));
}
return bRet;
}
BOOL APIENTRY
WatchdogDrvBitBlt(
SURFOBJ *psoDst,
SURFOBJ *psoSrc,
SURFOBJ *psoMask,
CLIPOBJ *pco,
XLATEOBJ *pxlo,
RECTL *prclDst,
POINTL *pptlSrc,
POINTL *pptlMask,
BRUSHOBJ *pbo,
POINTL *pptlBrush,
ROP4 rop4
)
{
SURFOBJ *psoDevice = (psoDst->dhpdev) ? psoDst : psoSrc;
PFN_DrvBitBlt pfn = (PFN_DrvBitBlt) dhpdevRetrievePfn((ULONG_PTR)psoDevice->dhpdev,INDEX_DrvBitBlt);
BOOL bRet = TRUE;
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev(psoDevice->dhpdev)->bThreadStuck) {
return TRUE;
}
__try {
bRet = pfn(psoDst, psoSrc, psoMask, pco, pxlo, prclDst, pptlSrc, pptlMask, pbo, pptlBrush, rop4);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
//
// Handle stuck thread excepton
//
HandleStuckThreadException(dhpdevRetrieveLdev(psoDevice->dhpdev));
}
return bRet;
}
BOOL APIENTRY
WatchdogDrvCopyBits(
SURFOBJ *psoDst,
SURFOBJ *psoSrc,
CLIPOBJ *pco,
XLATEOBJ *pxlo,
RECTL *prclDst,
POINTL *pptlSrc
)
{
SURFOBJ *psoDevice = (psoDst->dhpdev) ? psoDst : psoSrc;
PFN_DrvCopyBits pfn = (PFN_DrvCopyBits) dhpdevRetrievePfn((ULONG_PTR)psoDevice->dhpdev,INDEX_DrvCopyBits);
BOOL bRet = TRUE;
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev(psoDevice->dhpdev)->bThreadStuck) {
return TRUE;
}
__try {
bRet = pfn(psoDst, psoSrc, pco, pxlo, prclDst, pptlSrc);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
//
// Handle stuck thread excepton
//
HandleStuckThreadException(dhpdevRetrieveLdev(psoDevice->dhpdev));
}
return bRet;
}
BOOL APIENTRY
WatchdogDrvStretchBlt(
SURFOBJ *psoDst,
SURFOBJ *psoSrc,
SURFOBJ *psoMask,
CLIPOBJ *pco,
XLATEOBJ *pxlo,
COLORADJUSTMENT *pca,
POINTL *pptlHTOrg,
RECTL *prclDst,
RECTL *prclSrc,
POINTL *pptlMask,
ULONG iMode
)
{
SURFOBJ *psoDevice = (psoDst->dhpdev) ? psoDst : psoSrc;
PFN_DrvStretchBlt pfn = (PFN_DrvStretchBlt) dhpdevRetrievePfn((ULONG_PTR)psoDevice->dhpdev,INDEX_DrvStretchBlt);
BOOL bRet = TRUE;
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev(psoDevice->dhpdev)->bThreadStuck) {
return TRUE;
}
__try {
bRet = pfn(psoDst, psoSrc, psoMask, pco, pxlo, pca, pptlHTOrg, prclDst, prclSrc, pptlMask, iMode);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
//
// Handle stuck thread excepton
//
HandleStuckThreadException(dhpdevRetrieveLdev(psoDevice->dhpdev));
}
return bRet;
}
ULONG APIENTRY
WatchdogDrvSetPalette(
DHPDEV dhpdev,
PALOBJ *ppalo,
FLONG fl,
ULONG iStart,
ULONG cColors
)
{
PFN_DrvSetPalette pfn = (PFN_DrvSetPalette) dhpdevRetrievePfn((ULONG_PTR)dhpdev,INDEX_DrvSetPalette);
ULONG ulRet = 0;
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev(dhpdev)->bThreadStuck) {
return 0;
}
__try {
ulRet = pfn(dhpdev, ppalo, fl, iStart, cColors);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
//
// Handle stuck thread excepton
//
HandleStuckThreadException(dhpdevRetrieveLdev(dhpdev));
}
return ulRet;
}
BOOL APIENTRY
WatchdogDrvTextOut(
SURFOBJ *pso,
STROBJ *pstro,
FONTOBJ *pfo,
CLIPOBJ *pco,
RECTL *prclExtra,
RECTL *prclOpaque,
BRUSHOBJ *pboFore,
BRUSHOBJ *pboOpaque,
POINTL *pptlOrg,
MIX mix
)
{
PFN_DrvTextOut pfn = (PFN_DrvTextOut) dhpdevRetrievePfn((ULONG_PTR)pso->dhpdev,INDEX_DrvTextOut);
BOOL bRet = TRUE;
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev(pso->dhpdev)->bThreadStuck) {
return TRUE;
}
__try {
bRet = pfn(pso, pstro, pfo, pco, prclExtra, prclOpaque, pboFore, pboOpaque, pptlOrg, mix);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
//
// Handle stuck thread excepton
//
HandleStuckThreadException(dhpdevRetrieveLdev(pso->dhpdev));
}
return bRet;
}
ULONG APIENTRY
WatchdogDrvEscape(
SURFOBJ *pso,
ULONG iEsc,
ULONG cjIn,
PVOID pvIn,
ULONG cjOut,
PVOID pvOut
)
{
PFN_DrvEscape pfn = (PFN_DrvEscape) dhpdevRetrievePfn((ULONG_PTR)pso->dhpdev,INDEX_DrvEscape);
ULONG ulRet = 0;
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev(pso->dhpdev)->bThreadStuck) {
return 0;
}
__try {
ulRet = pfn(pso, iEsc, cjIn, pvIn, cjOut, pvOut);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
//
// Handle stuck thread excepton
//
HandleStuckThreadException(dhpdevRetrieveLdev(pso->dhpdev));
}
return ulRet;
}
ULONG APIENTRY
WatchdogDrvDrawEscape(
IN SURFOBJ *pso,
IN ULONG iEsc,
IN CLIPOBJ *pco,
IN RECTL *prcl,
IN ULONG cjIn,
IN PVOID pvIn
)
{
PFN_DrvDrawEscape pfn = (PFN_DrvDrawEscape) dhpdevRetrievePfn((ULONG_PTR)pso->dhpdev,INDEX_DrvDrawEscape);
ULONG ulRet = -1;
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev(pso->dhpdev)->bThreadStuck) {
return -1;
}
__try {
ulRet = pfn(pso, iEsc, pco, prcl, cjIn, pvIn);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
//
// Handle stuck thread excepton
//
HandleStuckThreadException(dhpdevRetrieveLdev(pso->dhpdev));
}
return ulRet;
}
ULONG APIENTRY
WatchdogDrvSetPointerShape(
SURFOBJ *pso,
SURFOBJ *psoMask,
SURFOBJ *psoColor,
XLATEOBJ *pxlo,
LONG xHot,
LONG yHot,
LONG x,
LONG y,
RECTL *prcl,
FLONG fl
)
{
PFN_DrvSetPointerShape pfn = (PFN_DrvSetPointerShape) dhpdevRetrievePfn((ULONG_PTR)pso->dhpdev,INDEX_DrvSetPointerShape);
ULONG ulRet = 0;
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev(pso->dhpdev)->bThreadStuck) {
return 0;
}
__try {
ulRet = pfn(pso, psoMask, psoColor, pxlo, xHot, yHot, x, y, prcl, fl);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
//
// Handle stuck thread excepton
//
HandleStuckThreadException(dhpdevRetrieveLdev(pso->dhpdev));
}
return ulRet;
}
VOID APIENTRY
WatchdogDrvMovePointer(
SURFOBJ *pso,
LONG x,
LONG y,
RECTL *prcl
)
{
PFN_DrvMovePointer pfn = (PFN_DrvMovePointer) dhpdevRetrievePfn((ULONG_PTR)pso->dhpdev,INDEX_DrvMovePointer);
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev(pso->dhpdev)->bThreadStuck) {
return;
}
__try {
pfn(pso, x, y, prcl);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
//
// Handle stuck thread excepton
//
HandleStuckThreadException(dhpdevRetrieveLdev(pso->dhpdev));
}
}
BOOL APIENTRY
WatchdogDrvLineTo(
SURFOBJ *pso,
CLIPOBJ *pco,
BRUSHOBJ *pbo,
LONG x1,
LONG y1,
LONG x2,
LONG y2,
RECTL *prclBounds,
MIX mix
)
{
PFN_DrvLineTo pfn = (PFN_DrvLineTo) dhpdevRetrievePfn((ULONG_PTR)pso->dhpdev,INDEX_DrvLineTo);
BOOL bRet = TRUE;
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev(pso->dhpdev)->bThreadStuck) {
return TRUE;
}
__try {
bRet = pfn(pso, pco, pbo, x1, y1, x2, y2, prclBounds, mix);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
//
// Handle stuck thread excepton
//
HandleStuckThreadException(dhpdevRetrieveLdev(pso->dhpdev));
}
return bRet;
}
VOID APIENTRY
WatchdogDrvSynchronize(
DHPDEV dhpdev,
RECTL *prcl
)
{
PFN_DrvSynchronize pfn = (PFN_DrvSynchronize) dhpdevRetrievePfn((ULONG_PTR)dhpdev,INDEX_DrvSynchronize);
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev(dhpdev)->bThreadStuck) {
return;
}
__try {
pfn(dhpdev, prcl);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
//
// Handle stuck thread excepton
//
HandleStuckThreadException(dhpdevRetrieveLdev(dhpdev));
}
}
ULONG_PTR APIENTRY
WatchdogDrvSaveScreenBits(
SURFOBJ *pso,
ULONG iMode,
ULONG_PTR ident,
RECTL *prcl
)
{
PFN_DrvSaveScreenBits pfn = (PFN_DrvSaveScreenBits) dhpdevRetrievePfn((ULONG_PTR)pso->dhpdev,INDEX_DrvSaveScreenBits);
ULONG_PTR ulptrRet = 0;
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev(pso->dhpdev)->bThreadStuck) {
return 0;
}
__try {
ulptrRet = pfn(pso, iMode, ident, prcl);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
//
// Handle stuck thread excepton
//
HandleStuckThreadException(dhpdevRetrieveLdev(pso->dhpdev));
}
return ulptrRet;
}
DWORD APIENTRY
WatchdogDrvSetPixelFormat(
IN SURFOBJ *pso,
IN LONG iPixelFormat,
IN HWND hwnd
)
{
PFN_DrvSetPixelFormat pfn = (PFN_DrvSetPixelFormat) dhpdevRetrievePfn((ULONG_PTR)pso->dhpdev,INDEX_DrvSetPixelFormat);
DWORD dwRet = FALSE;
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev(pso->dhpdev)->bThreadStuck) {
return 0;
}
__try {
dwRet = pfn(pso, iPixelFormat, hwnd);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
//
// Handle stuck thread excepton
//
HandleStuckThreadException(dhpdevRetrieveLdev(pso->dhpdev));
}
return dwRet;
}
LONG APIENTRY
WatchdogDrvDescribePixelFormat(
IN DHPDEV dhpdev,
IN LONG iPixelFormat,
IN ULONG cjpdf,
OUT PIXELFORMATDESCRIPTOR *ppfd
)
{
PFN_DrvDescribePixelFormat pfn = (PFN_DrvDescribePixelFormat) dhpdevRetrievePfn((ULONG_PTR)dhpdev,INDEX_DrvDescribePixelFormat);
LONG lRet = 0;
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev(dhpdev)->bThreadStuck) {
return 0;
}
__try {
lRet = pfn(dhpdev, iPixelFormat, cjpdf, ppfd);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
//
// Handle stuck thread excepton
//
HandleStuckThreadException(dhpdevRetrieveLdev(dhpdev));
}
return lRet;
}
BOOL APIENTRY
WatchdogDrvSwapBuffers(
IN SURFOBJ *pso,
IN WNDOBJ *pwo
)
{
PFN_DrvSwapBuffers pfn = (PFN_DrvSwapBuffers) dhpdevRetrievePfn((ULONG_PTR)pso->dhpdev,INDEX_DrvSwapBuffers);
BOOL bRet = FALSE;
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev(pso->dhpdev)->bThreadStuck) {
return 0;
}
__try {
bRet = pfn(pso, pwo);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
//
// Handle stuck thread excepton
//
HandleStuckThreadException(dhpdevRetrieveLdev(pso->dhpdev));
}
return bRet;
}
DWORD APIENTRY
WatchdogDdContextCreate(
LPD3DNTHAL_CONTEXTCREATEDATA pccd
)
{
PLDEV pldev = (PLDEV)AssociationRetrieveData((ULONG_PTR)pccd->lpDDLcl->lpGbl->dhpdev);
LPD3DNTHAL_CONTEXTCREATECB pfn = (LPD3DNTHAL_CONTEXTCREATECB) pldev->apfnDriver[INDEX_DdContextCreate];
DWORD dwRet = DDHAL_DRIVER_NOTHANDLED;
PCONTEXT_NODE Node;
//
// Return early if we are in a thread stuck condition
//
if (pldev->bThreadStuck) {
return 0;
}
Node = (PCONTEXT_NODE)PALLOCMEM(sizeof(ASSOCIATION_NODE), GDITAG_DRVSUP);
if (Node) {
__try {
dwRet = pfn(pccd);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
HandleStuckThreadException(pldev);
}
if (dwRet == DDHAL_DRIVER_HANDLED) {
//
// Store the dwhContext and the associated dhpdev
//
Node->Context = (PVOID)pccd->dwhContext;
Node->pldev = pldev;
pccd->dwhContext = (DWORD_PTR)Node;
} else {
VFREEMEM(Node);
}
}
return dwRet;
}
DWORD APIENTRY
WatchdogDdContextDestroy(
LPD3DNTHAL_CONTEXTDESTROYDATA pcdd
)
{
PCONTEXT_NODE Node = (PCONTEXT_NODE) pcdd->dwhContext;
LPD3DNTHAL_CONTEXTDESTROYCB pfn = (LPD3DNTHAL_CONTEXTDESTROYCB) Node->pldev->apfnDriver[INDEX_DdContextDestroy];
DWORD dwRet = 0;
//
// Return early if we are in a thread stuck condition
//
if (Node->pldev->bThreadStuck) {
return 0;
}
//
// Restore driver created context
//
pcdd->dwhContext = (DWORD_PTR) Node->Context;
__try {
dwRet = pfn(pcdd);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
HandleStuckThreadException(dhpdevRetrieveLdev((DHPDEV)pcdd->dwhContext));
}
//
// Resore our context, just in case this stucture is re-used
//
pcdd->dwhContext = (DWORD_PTR) Node;
if (dwRet == DDHAL_DRIVER_HANDLED) {
VFREEMEM(Node);
}
return dwRet;
}
DWORD APIENTRY
WatchdogDdCanCreateSurface(
PDD_CANCREATESURFACEDATA lpCanCreateSurface
)
{
PDD_CANCREATESURFACE pfn = (PDD_CANCREATESURFACE) dhpdevRetrievePfn((ULONG_PTR)lpCanCreateSurface->lpDD->dhpdev,INDEX_DdCanCreateSurface);
DWORD dwRet = 0;
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev((DHPDEV)lpCanCreateSurface->lpDD->dhpdev)->bThreadStuck) {
return 0;
}
__try {
dwRet = pfn(lpCanCreateSurface);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
HandleStuckThreadException(dhpdevRetrieveLdev((DHPDEV)lpCanCreateSurface->lpDD->dhpdev));
}
return dwRet;
}
DWORD APIENTRY
WatchdogDdCreateSurface(
PDD_CREATESURFACEDATA lpCreateSurface
)
{
PDD_CREATESURFACE pfn = (PDD_CREATESURFACE) dhpdevRetrievePfn((ULONG_PTR)lpCreateSurface->lpDD->dhpdev,INDEX_DdCreateSurface);
DWORD dwRet = 0;
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev((DHPDEV)lpCreateSurface->lpDD->dhpdev)->bThreadStuck) {
return 0;
}
__try {
dwRet = pfn(lpCreateSurface);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
HandleStuckThreadException(dhpdevRetrieveLdev((DHPDEV)lpCreateSurface->lpDD->dhpdev));
}
return dwRet;
}
DWORD APIENTRY
WatchdogDdDestroySurface(
PDD_DESTROYSURFACEDATA lpDestroySurface
)
{
PDD_SURFCB_DESTROYSURFACE pfn = (PDD_SURFCB_DESTROYSURFACE) dhpdevRetrievePfn((ULONG_PTR)lpDestroySurface->lpDD->dhpdev,INDEX_DdDestroySurface);
DWORD dwRet = 0;
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev((DHPDEV)lpDestroySurface->lpDD->dhpdev)->bThreadStuck) {
return 0;
}
__try {
dwRet = pfn(lpDestroySurface);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
HandleStuckThreadException(dhpdevRetrieveLdev((DHPDEV)lpDestroySurface->lpDD->dhpdev));
}
return dwRet;
}
DWORD APIENTRY
WatchdogDdLockSurface(
PDD_LOCKDATA lpLockSurface
)
{
PDD_SURFCB_LOCK pfn = (PDD_SURFCB_LOCK) dhpdevRetrievePfn((ULONG_PTR)lpLockSurface->lpDD->dhpdev,INDEX_DdLockSurface);
DWORD dwRet = 0;
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev((DHPDEV)lpLockSurface->lpDD->dhpdev)->bThreadStuck) {
return 0;
}
__try {
dwRet = pfn(lpLockSurface);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
HandleStuckThreadException(dhpdevRetrieveLdev((DHPDEV)lpLockSurface->lpDD->dhpdev));
}
return dwRet;
}
DWORD APIENTRY
WatchdogDdUnlockSurface(
PDD_UNLOCKDATA lpUnlockSurface
)
{
PDD_SURFCB_UNLOCK pfn = (PDD_SURFCB_UNLOCK) dhpdevRetrievePfn((ULONG_PTR)lpUnlockSurface->lpDD->dhpdev,INDEX_DdUnlockSurface);
DWORD dwRet = 0;
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev((DHPDEV)lpUnlockSurface->lpDD->dhpdev)->bThreadStuck) {
return 0;
}
__try {
dwRet = pfn(lpUnlockSurface);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
HandleStuckThreadException(dhpdevRetrieveLdev((DHPDEV)lpUnlockSurface->lpDD->dhpdev));
}
return dwRet;
}
#if 0
//
// I'm not sure how I can hook this one since a DD_DRVSETCOLORKEYDATA
// structure doesn't have a way to look up the dhpdev!
//
DWORD APIENTRY
WatchdogDdSetColorKey(
PDD_DRVSETCOLORKEYDATA lpSetColorKey
)
{
PDD_SURFCB_SETCOLORKEY pfn = (PDD_SURFCB_SETCOLORKEY)dhpdevRetrievePfn((ULONG_PTR)lpSetColorKey->lpDD->dhpdev,INDEX_DdSetColorKey);
DWORD dwRet;
__try {
dwRet = pfn(lpSetColorKey);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
HandleStuckThreadException();
}
return dwRet;
}
#endif
DWORD APIENTRY
WatchdogDdGetScanLine(
PDD_GETSCANLINEDATA pGetScanLine
)
{
PDD_GETSCANLINE pfn = (PDD_GETSCANLINE)dhpdevRetrievePfn((ULONG_PTR)pGetScanLine->lpDD->dhpdev,INDEX_DdGetScanLine);
DWORD dwRet = 0;
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev((DHPDEV)pGetScanLine->lpDD->dhpdev)->bThreadStuck) {
return 0;
}
__try {
dwRet = pfn(pGetScanLine);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
HandleStuckThreadException(dhpdevRetrieveLdev((DHPDEV)pGetScanLine->lpDD->dhpdev));
}
return dwRet;
}
DWORD APIENTRY
WatchdogDdCreatePalette(
PDD_CREATEPALETTEDATA lpCreatePalette
)
{
PDD_CREATEPALETTE pfn = (PDD_CREATEPALETTE) dhpdevRetrievePfn((ULONG_PTR)lpCreatePalette->lpDD->dhpdev,INDEX_DdCreatePalette);
DWORD dwRet = 0;
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev((DHPDEV)lpCreatePalette->lpDD->dhpdev)->bThreadStuck) {
return 0;
}
__try {
dwRet = pfn(lpCreatePalette);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
HandleStuckThreadException(dhpdevRetrieveLdev((DHPDEV)lpCreatePalette->lpDD->dhpdev));
}
return dwRet;
}
DWORD APIENTRY
WatchdogDdMapMemory(
PDD_MAPMEMORYDATA lpMapMemory
)
{
PDD_MAPMEMORY pfn = (PDD_MAPMEMORY) dhpdevRetrievePfn((ULONG_PTR)lpMapMemory->lpDD->dhpdev,INDEX_DdMapMemory);
DWORD dwRet = 0;
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev((DHPDEV)lpMapMemory->lpDD->dhpdev)->bThreadStuck) {
return 0;
}
__try {
dwRet = pfn(lpMapMemory);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
HandleStuckThreadException(dhpdevRetrieveLdev((DHPDEV)lpMapMemory->lpDD->dhpdev));
}
return dwRet;
}
DWORD APIENTRY
WatchdogDdWaitForVerticalBlank(
PDD_WAITFORVERTICALBLANKDATA lpWaitForVerticalBlank
)
{
PDD_WAITFORVERTICALBLANK pfn = (PDD_WAITFORVERTICALBLANK) dhpdevRetrievePfn((ULONG_PTR)lpWaitForVerticalBlank->lpDD->dhpdev,INDEX_DdWaitForVerticalBlank);
DWORD dwRet = 0;
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev((DHPDEV)lpWaitForVerticalBlank->lpDD->dhpdev)->bThreadStuck) {
return 0;
}
__try {
dwRet = pfn(lpWaitForVerticalBlank);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
HandleStuckThreadException(dhpdevRetrieveLdev((DHPDEV)lpWaitForVerticalBlank->lpDD->dhpdev));
}
return dwRet;
}
DWORD APIENTRY
WatchdogDdFlip(
PDD_FLIPDATA lpFlip
)
{
PDD_SURFCB_FLIP pfn = (PDD_SURFCB_FLIP) dhpdevRetrievePfn((ULONG_PTR)lpFlip->lpDD->dhpdev,INDEX_DdFlip);
DWORD dwRet = 0;
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev((DHPDEV)lpFlip->lpDD->dhpdev)->bThreadStuck) {
return 0;
}
__try {
dwRet = pfn(lpFlip);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
HandleStuckThreadException(dhpdevRetrieveLdev((DHPDEV)lpFlip->lpDD->dhpdev));
}
return dwRet;
}
DWORD APIENTRY
WatchdogDdGetDriverState(
PDD_GETDRIVERSTATEDATA pgdsd
)
{
PCONTEXT_NODE Node = (PCONTEXT_NODE) pgdsd->dwhContext;
PDD_GETDRIVERSTATE pfn = (PDD_GETDRIVERSTATE) Node->pldev->apfnDriver[INDEX_DdGetDriverState];
DWORD dwRet = 0;
//
// how can I validate if I created this dwhcontext?
//
if (pfn == NULL) {
pgdsd->ddRVal = D3DNTHAL_CONTEXT_BAD;
return DDHAL_DRIVER_HANDLED;
}
if (Node->pldev->bThreadStuck) {
return 0;
}
//
// restore original context
//
pgdsd->dwhContext = (DWORD_PTR) Node->Context;
__try {
dwRet = pfn(pgdsd);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
HandleStuckThreadException(Node->pldev);
}
//
// save our context again in case this structure is re-used
//
pgdsd->dwhContext = (DWORD_PTR) Node;
return dwRet;
}
//
// TODO: I don't think I want to check in with this macro to build
// functions, but for now lets use it.
//
#define BUILD_FUNCTION_1(Func, ArgType, FuncType) \
DWORD APIENTRY \
WatchdogDd##Func( \
ArgType lp##Func) \
{ \
FuncType pfn = (FuncType) dhpdevRetrievePfn((ULONG_PTR)lp##Func->lpDD->dhpdev,INDEX_Dd##Func); \
DWORD dwRet = 0; \
\
if (dhpdevRetrieveLdev((DHPDEV)lp##Func->lpDD->dhpdev)->bThreadStuck) { \
return 0; \
} \
\
__try { \
\
dwRet = pfn(lp##Func); \
\
} __except(GetExceptionCode() == SE_THREAD_STUCK) {\
\
HandleStuckThreadException(dhpdevRetrieveLdev((DHPDEV)lp##Func->lpDD->dhpdev));\
\
}\
\
return dwRet;\
}
#define BUILD_FUNCTION_2(Func, ArgType, FuncType) \
DWORD APIENTRY \
WatchdogDd##Func( \
ArgType lp##Func) \
{ \
PCONTEXT_NODE Node = (PCONTEXT_NODE) lp##Func->dwhContext; \
FuncType pfn = (FuncType) Node->pldev->apfnDriver[INDEX_Dd##Func]; \
DWORD dwRet = 0; \
\
if (pfn == NULL) {\
lp##Func->ddrval = D3DNTHAL_CONTEXT_BAD; \
return DDHAL_DRIVER_HANDLED; \
}\
\
if (Node->pldev->bThreadStuck) { \
return 0; \
} \
\
lp##Func->dwhContext = (DWORD_PTR) Node->Context; \
\
__try { \
\
dwRet = pfn(lp##Func); \
\
} __except(GetExceptionCode() == SE_THREAD_STUCK) {\
\
HandleStuckThreadException(Node->pldev);\
\
}\
\
lp##Func->dwhContext = (DWORD_PTR) Node; \
\
return dwRet;\
}
#define BUILD_FUNCTION_3(Func, ArgType, FuncType) \
DWORD APIENTRY \
WatchdogDd##Func( \
ArgType lp##Func) \
{ \
FuncType pfn = (FuncType) dhpdevRetrievePfn((ULONG_PTR)lp##Func->lpDD->lpGbl->dhpdev,INDEX_Dd##Func); \
DWORD dwRet = 0; \
\
if (dhpdevRetrieveLdev((DHPDEV)lp##Func->lpDD->lpGbl->dhpdev)->bThreadStuck) { \
return 0; \
} \
\
__try { \
\
dwRet = pfn(lp##Func); \
\
} __except(GetExceptionCode() == SE_THREAD_STUCK) {\
\
HandleStuckThreadException(dhpdevRetrieveLdev((DHPDEV)lp##Func->lpDD->lpGbl->dhpdev));\
\
}\
\
return dwRet;\
}
#define BUILD_FUNCTION_4(Func, ArgType, FuncType) \
DWORD APIENTRY \
WatchdogDd##Func( \
ArgType lp##Func) \
{ \
FuncType pfn = (FuncType) dhpdevRetrievePfn((ULONG_PTR)lp##Func->lpDDLcl->lpGbl->dhpdev,INDEX_Dd##Func); \
DWORD dwRet = 0; \
\
if (dhpdevRetrieveLdev((DHPDEV)lp##Func->lpDDLcl->lpGbl->dhpdev)->bThreadStuck) { \
return 0; \
} \
\
__try { \
\
dwRet = pfn(lp##Func); \
\
} __except(GetExceptionCode() == SE_THREAD_STUCK) {\
\
HandleStuckThreadException(dhpdevRetrieveLdev((DHPDEV)lp##Func->lpDDLcl->lpGbl->dhpdev));\
\
}\
\
return dwRet;\
}
#define BUILD_FUNCTION_5(Func, ArgType, FuncType) \
DWORD APIENTRY \
WatchdogDd##Func( \
ArgType lp##Func) \
{ \
FuncType pfn = (FuncType) dhpdevRetrievePfn((ULONG_PTR)lp##Func->pDDLcl->lpGbl->dhpdev,INDEX_Dd##Func); \
DWORD dwRet = 0; \
\
if (dhpdevRetrieveLdev((DHPDEV)lp##Func->pDDLcl->lpGbl->dhpdev)->bThreadStuck) { \
return 0; \
} \
\
__try { \
\
dwRet = pfn(lp##Func); \
\
} __except(GetExceptionCode() == SE_THREAD_STUCK) {\
\
HandleStuckThreadException(dhpdevRetrieveLdev((DHPDEV)lp##Func->pDDLcl->lpGbl->dhpdev));\
\
}\
\
return dwRet;\
}
BUILD_FUNCTION_1(Lock, PDD_LOCKDATA, PDD_SURFCB_LOCK);
BUILD_FUNCTION_1(Unlock, PDD_UNLOCKDATA, PDD_SURFCB_UNLOCK);
BUILD_FUNCTION_1(Blt, PDD_BLTDATA, PDD_SURFCB_BLT);
BUILD_FUNCTION_1(AddAttachedSurface, PDD_ADDATTACHEDSURFACEDATA, PDD_SURFCB_ADDATTACHEDSURFACE);
BUILD_FUNCTION_1(GetBltStatus, PDD_GETBLTSTATUSDATA, PDD_SURFCB_GETBLTSTATUS);
BUILD_FUNCTION_1(GetFlipStatus, PDD_GETFLIPSTATUSDATA, PDD_SURFCB_GETFLIPSTATUS);
BUILD_FUNCTION_1(UpdateOverlay, PDD_UPDATEOVERLAYDATA, PDD_SURFCB_UPDATEOVERLAY);
BUILD_FUNCTION_1(SetOverlayPosition, PDD_SETOVERLAYPOSITIONDATA, PDD_SURFCB_SETOVERLAYPOSITION);
BUILD_FUNCTION_1(SetPalette, PDD_SETPALETTEDATA, PDD_SURFCB_SETPALETTE);
BUILD_FUNCTION_1(DestroyPalette, PDD_DESTROYPALETTEDATA, PDD_PALCB_DESTROYPALETTE);
BUILD_FUNCTION_1(SetEntries, PDD_SETENTRIESDATA, PDD_PALCB_SETENTRIES);
BUILD_FUNCTION_1(ColorControl, PDD_COLORCONTROLDATA, PDD_COLORCB_COLORCONTROL);
BUILD_FUNCTION_1(CanCreateD3DBuffer, PDD_CANCREATESURFACEDATA, PDD_CANCREATESURFACE);
BUILD_FUNCTION_1(CreateD3DBuffer, PDD_CREATESURFACEDATA, PDD_CREATESURFACE);
BUILD_FUNCTION_1(DestroyD3DBuffer, PDD_DESTROYSURFACEDATA, PDD_SURFCB_DESTROYSURFACE);
BUILD_FUNCTION_1(LockD3DBuffer, PDD_LOCKDATA, PDD_SURFCB_LOCK);
BUILD_FUNCTION_1(UnlockD3DBuffer, PDD_UNLOCKDATA, PDD_SURFCB_UNLOCK);
BUILD_FUNCTION_1(GetAvailDriverMemory, PDD_GETAVAILDRIVERMEMORYDATA, PDD_GETAVAILDRIVERMEMORY);
BUILD_FUNCTION_1(AlphaBlt, PDD_BLTDATA, PDD_ALPHABLT);
BUILD_FUNCTION_2(DrawPrimitives2, LPD3DNTHAL_DRAWPRIMITIVES2DATA, LPD3DNTHAL_DRAWPRIMITIVES2CB);
BUILD_FUNCTION_2(ValidateTextureStageState, LPD3DNTHAL_VALIDATETEXTURESTAGESTATEDATA, LPD3DNTHAL_VALIDATETEXTURESTAGESTATECB);
BUILD_FUNCTION_3(SyncSurfaceData, PDD_SYNCSURFACEDATA, PDD_KERNELCB_SYNCSURFACE);
BUILD_FUNCTION_3(SyncVideoPortData, PDD_SYNCVIDEOPORTDATA, PDD_KERNELCB_SYNCVIDEOPORT);
BUILD_FUNCTION_4(CreateSurfaceEx, PDD_CREATESURFACEEXDATA, PDD_CREATESURFACEEX);
BUILD_FUNCTION_5(DestroyDDLocal, PDD_DESTROYDDLOCALDATA, PDD_DESTROYDDLOCAL);
BUILD_FUNCTION_1(FreeDriverMemory, PDD_FREEDRIVERMEMORYDATA, PDD_FREEDRIVERMEMORY);
BUILD_FUNCTION_1(SetExclusiveMode, PDD_SETEXCLUSIVEMODEDATA, PDD_SETEXCLUSIVEMODE);
BUILD_FUNCTION_1(FlipToGDISurface, PDD_FLIPTOGDISURFACEDATA, PDD_FLIPTOGDISURFACE);
DWORD APIENTRY
WatchdogDdGetDriverInfo(
PDD_GETDRIVERINFODATA lpGetDriverInfo
)
{
PDD_GETDRIVERINFO pfn = (PDD_GETDRIVERINFO) dhpdevRetrievePfn((ULONG_PTR)lpGetDriverInfo->dhpdev,INDEX_DdGetDriverInfo);
DWORD dwRet = 0;
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev((DHPDEV)lpGetDriverInfo->dhpdev)->bThreadStuck) {
return 0;
}
__try {
dwRet = pfn(lpGetDriverInfo);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
HandleStuckThreadException(dhpdevRetrieveLdev((DHPDEV)lpGetDriverInfo->dhpdev));
}
if ((dwRet == DDHAL_DRIVER_HANDLED) &&
(lpGetDriverInfo->ddRVal == DD_OK)) {
PLDEV pldev = dhpdevRetrieveLdev((DHPDEV)lpGetDriverInfo->dhpdev);
if (IsEqualGUID(&lpGetDriverInfo->guidInfo, &GUID_ColorControlCallbacks)) {
PDD_COLORCONTROLCALLBACKS Callbacks = (PDD_COLORCONTROLCALLBACKS) lpGetDriverInfo->lpvData;
if (Callbacks->dwFlags & DDHAL_COLOR_COLORCONTROL) {
if (Callbacks->ColorControl != WatchdogDdColorControl) {
pldev->apfnDriver[INDEX_DdColorControl] = (PFN)Callbacks->ColorControl;
}
Callbacks->ColorControl = WatchdogDdColorControl;
}
} else if (IsEqualGUID(&lpGetDriverInfo->guidInfo, &GUID_D3DCallbacks)) {
LPD3DNTHAL_CALLBACKS Callbacks = (LPD3DNTHAL_CALLBACKS) lpGetDriverInfo->lpvData;
if (Callbacks->ContextCreate) {
if (Callbacks->ContextCreate != WatchdogDdContextCreate) {
pldev->apfnDriver[INDEX_DdContextCreate] = (PFN)Callbacks->ContextCreate;
}
Callbacks->ContextCreate = WatchdogDdContextCreate;
}
if (Callbacks->ContextDestroy) {
if (Callbacks->ContextDestroy != WatchdogDdContextDestroy) {
pldev->apfnDriver[INDEX_DdContextDestroy] = (PFN)Callbacks->ContextDestroy;
}
Callbacks->ContextDestroy = WatchdogDdContextDestroy;
}
} else if (IsEqualGUID(&lpGetDriverInfo->guidInfo, &GUID_D3DCallbacks3)) {
LPD3DNTHAL_CALLBACKS3 Callbacks = (LPD3DNTHAL_CALLBACKS3) lpGetDriverInfo->lpvData;
if (Callbacks->DrawPrimitives2) {
if (Callbacks->DrawPrimitives2 != WatchdogDdDrawPrimitives2) {
pldev->apfnDriver[INDEX_DdDrawPrimitives2] = (PFN)Callbacks->DrawPrimitives2;
}
Callbacks->DrawPrimitives2 = WatchdogDdDrawPrimitives2;
}
if (Callbacks->ValidateTextureStageState) {
if (Callbacks->ValidateTextureStageState != WatchdogDdValidateTextureStageState) {
pldev->apfnDriver[INDEX_DdValidateTextureStageState] = (PFN)Callbacks->ValidateTextureStageState;
}
Callbacks->ValidateTextureStageState = WatchdogDdValidateTextureStageState;
}
} else if (IsEqualGUID(&lpGetDriverInfo->guidInfo, &GUID_KernelCallbacks)) {
PDD_KERNELCALLBACKS Callbacks = (PDD_KERNELCALLBACKS) lpGetDriverInfo->lpvData;
if (Callbacks->dwFlags & DDHAL_KERNEL_SYNCSURFACEDATA) {
if (Callbacks->SyncSurfaceData != WatchdogDdSyncSurfaceData) {
pldev->apfnDriver[INDEX_DdSyncSurfaceData] = (PFN)Callbacks->SyncSurfaceData;
}
Callbacks->SyncSurfaceData = WatchdogDdSyncSurfaceData;
}
if (Callbacks->dwFlags & DDHAL_KERNEL_SYNCVIDEOPORTDATA) {
if (Callbacks->SyncVideoPortData != WatchdogDdSyncVideoPortData) {
pldev->apfnDriver[INDEX_DdSyncVideoPortData] = (PFN)Callbacks->SyncVideoPortData;
}
Callbacks->SyncVideoPortData = WatchdogDdSyncVideoPortData;
}
} else if (IsEqualGUID(&lpGetDriverInfo->guidInfo, &GUID_MiscellaneousCallbacks)) {
PDD_MISCELLANEOUSCALLBACKS Callbacks = (PDD_MISCELLANEOUSCALLBACKS) lpGetDriverInfo->lpvData;
if (Callbacks->dwFlags & DDHAL_MISCCB32_GETAVAILDRIVERMEMORY) {
if (Callbacks->GetAvailDriverMemory != WatchdogDdGetAvailDriverMemory) {
pldev->apfnDriver[INDEX_DdGetAvailDriverMemory] = (PFN)Callbacks->GetAvailDriverMemory;
}
Callbacks->GetAvailDriverMemory = WatchdogDdGetAvailDriverMemory;
}
} else if (IsEqualGUID(&lpGetDriverInfo->guidInfo, &GUID_Miscellaneous2Callbacks)) {
PDD_MISCELLANEOUS2CALLBACKS Callbacks = (PDD_MISCELLANEOUS2CALLBACKS) lpGetDriverInfo->lpvData;
if (Callbacks->dwFlags & DDHAL_MISC2CB32_ALPHABLT) {
if (Callbacks->AlphaBlt != WatchdogDdAlphaBlt) {
pldev->apfnDriver[INDEX_DdAlphaBlt] = (PFN)Callbacks->AlphaBlt;
}
Callbacks->AlphaBlt = WatchdogDdAlphaBlt;
}
if (Callbacks->dwFlags & DDHAL_MISC2CB32_CREATESURFACEEX) {
if (Callbacks->CreateSurfaceEx != WatchdogDdCreateSurfaceEx) {
pldev->apfnDriver[INDEX_DdCreateSurfaceEx] = (PFN)Callbacks->CreateSurfaceEx;
}
Callbacks->CreateSurfaceEx = WatchdogDdCreateSurfaceEx;
}
if (Callbacks->dwFlags & DDHAL_MISC2CB32_GETDRIVERSTATE) {
if (Callbacks->GetDriverState != WatchdogDdGetDriverState) {
pldev->apfnDriver[INDEX_DdGetDriverState] = (PFN)Callbacks->GetDriverState;
}
Callbacks->GetDriverState = WatchdogDdGetDriverState;
}
if (Callbacks->dwFlags & DDHAL_MISC2CB32_DESTROYDDLOCAL) {
if (Callbacks->DestroyDDLocal != WatchdogDdDestroyDDLocal) {
pldev->apfnDriver[INDEX_DdDestroyDDLocal] = (PFN)Callbacks->DestroyDDLocal;
}
Callbacks->DestroyDDLocal = WatchdogDdDestroyDDLocal;
}
} else if (IsEqualGUID(&lpGetDriverInfo->guidInfo, &GUID_MotionCompCallbacks)) {
//
// TODO: Still need to implement
//
} else if (IsEqualGUID(&lpGetDriverInfo->guidInfo, &GUID_NTCallbacks)) {
PDD_NTCALLBACKS Callbacks = (PDD_NTCALLBACKS) lpGetDriverInfo->lpvData;
if (Callbacks->dwFlags & DDHAL_NTCB32_FREEDRIVERMEMORY) {
if (Callbacks->FreeDriverMemory != WatchdogDdFreeDriverMemory) {
pldev->apfnDriver[INDEX_DdFreeDriverMemory] = (PFN)Callbacks->FreeDriverMemory;
}
Callbacks->FreeDriverMemory = WatchdogDdFreeDriverMemory;
}
if (Callbacks->dwFlags & DDHAL_NTCB32_SETEXCLUSIVEMODE) {
if (Callbacks->SetExclusiveMode != WatchdogDdSetExclusiveMode) {
pldev->apfnDriver[INDEX_DdSetExclusiveMode] = (PFN)Callbacks->SetExclusiveMode;
}
Callbacks->SetExclusiveMode = WatchdogDdSetExclusiveMode;
}
if (Callbacks->dwFlags & DDHAL_NTCB32_FLIPTOGDISURFACE) {
if (Callbacks->FlipToGDISurface != WatchdogDdFlipToGDISurface) {
pldev->apfnDriver[INDEX_DdFlipToGDISurface] = (PFN)Callbacks->FlipToGDISurface;
}
Callbacks->FlipToGDISurface = WatchdogDdFlipToGDISurface;
}
} else if (IsEqualGUID(&lpGetDriverInfo->guidInfo, &GUID_VideoPortCallbacks)) {
//
// TODO: Still need to implement
//
}
}
return dwRet;
}
BOOL APIENTRY
WatchdogDrvGetDirectDrawInfo(
DHPDEV dhpdev,
DD_HALINFO *pHalInfo,
DWORD *pdwNumHeaps,
VIDEOMEMORY *pvmList,
DWORD *pdwNumFourCCCodes,
DWORD *pdwFourCC
)
{
PFN_DrvGetDirectDrawInfo pfn = (PFN_DrvGetDirectDrawInfo) dhpdevRetrievePfn((ULONG_PTR)dhpdev,INDEX_DrvGetDirectDrawInfo);
BOOL bRet = 0;
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev(dhpdev)->bThreadStuck) {
return 0;
}
__try {
bRet = pfn(dhpdev, pHalInfo, pdwNumHeaps, pvmList, pdwNumFourCCCodes, pdwFourCC);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
//
// Handle stuck thread excepton
//
HandleStuckThreadException(dhpdevRetrieveLdev(dhpdev));
}
//
// If the function succeeded, then try to capture the DdGetDriverInfo
// function from pHalInfo.
//
if (bRet) {
PLDEV pldev = dhpdevRetrieveLdev(dhpdev);
if (pHalInfo->GetDriverInfo) {
if (pHalInfo->GetDriverInfo != WatchdogDdGetDriverInfo) {
pldev->apfnDriver[INDEX_DdGetDriverInfo] = (PFN)pHalInfo->GetDriverInfo;
}
pHalInfo->GetDriverInfo = WatchdogDdGetDriverInfo;
}
if (pHalInfo->lpD3DHALCallbacks) {
LPD3DNTHAL_CALLBACKS lpD3DHALCallbacks;
lpD3DHALCallbacks = (LPD3DNTHAL_CALLBACKS)pHalInfo->lpD3DHALCallbacks;
//
// Create copy of D3DHALCallbacks info - This is done to safely
// latch the callbacks witout actually changing driver local data
//
memcpy(&pldev->D3DHALCallbacks,
lpD3DHALCallbacks,
min(sizeof(pldev->D3DHALCallbacks), lpD3DHALCallbacks->dwSize));
pHalInfo->lpD3DHALCallbacks = lpD3DHALCallbacks = &pldev->D3DHALCallbacks;
if (lpD3DHALCallbacks->ContextCreate &&
lpD3DHALCallbacks->ContextDestroy) {
if (lpD3DHALCallbacks->ContextCreate != WatchdogDdContextCreate) {
pldev->apfnDriver[INDEX_DdContextCreate] = (PFN)lpD3DHALCallbacks->ContextCreate;
}
if (lpD3DHALCallbacks->ContextDestroy != WatchdogDdContextDestroy) {
pldev->apfnDriver[INDEX_DdContextDestroy] = (PFN)lpD3DHALCallbacks->ContextDestroy;
}
lpD3DHALCallbacks->ContextCreate = WatchdogDdContextCreate;
lpD3DHALCallbacks->ContextDestroy = WatchdogDdContextDestroy;
}
}
if (pHalInfo->lpD3DBufCallbacks) {
PDD_D3DBUFCALLBACKS lpD3DBufCallbacks;
lpD3DBufCallbacks = pHalInfo->lpD3DBufCallbacks;
//
// Create copy of D3DBufCallbacks info - This is done to safely
// latch the callbacks witout actually changing driver local data
//
memcpy(&pldev->D3DBufCallbacks,
lpD3DBufCallbacks,
min(sizeof(pldev->D3DBufCallbacks), lpD3DBufCallbacks->dwSize));
lpD3DBufCallbacks = pHalInfo->lpD3DBufCallbacks = &pldev->D3DBufCallbacks;
if ((lpD3DBufCallbacks->dwSize > FIELD_OFFSET(DD_D3DBUFCALLBACKS, CanCreateD3DBuffer)) &&
(lpD3DBufCallbacks->CanCreateD3DBuffer)) {
if (lpD3DBufCallbacks->CanCreateD3DBuffer != WatchdogDdCanCreateD3DBuffer) {
pldev->apfnDriver[INDEX_DdCanCreateD3DBuffer] = (PFN)lpD3DBufCallbacks->CanCreateD3DBuffer;
}
lpD3DBufCallbacks->CanCreateD3DBuffer = WatchdogDdCanCreateD3DBuffer;
}
if ((lpD3DBufCallbacks->dwSize > FIELD_OFFSET(DD_D3DBUFCALLBACKS, CreateD3DBuffer)) &&
(lpD3DBufCallbacks->CreateD3DBuffer)) {
if (lpD3DBufCallbacks->CreateD3DBuffer != WatchdogDdCreateD3DBuffer) {
pldev->apfnDriver[INDEX_DdCreateD3DBuffer] = (PFN)lpD3DBufCallbacks->CreateD3DBuffer;
}
lpD3DBufCallbacks->CreateD3DBuffer = WatchdogDdCreateD3DBuffer;
}
if ((lpD3DBufCallbacks->dwSize > FIELD_OFFSET(DD_D3DBUFCALLBACKS, DestroyD3DBuffer)) &&
(lpD3DBufCallbacks->DestroyD3DBuffer)) {
if (lpD3DBufCallbacks->DestroyD3DBuffer != WatchdogDdDestroyD3DBuffer) {
pldev->apfnDriver[INDEX_DdDestroyD3DBuffer] = (PFN)lpD3DBufCallbacks->DestroyD3DBuffer;
}
lpD3DBufCallbacks->DestroyD3DBuffer = WatchdogDdDestroyD3DBuffer;
}
if ((lpD3DBufCallbacks->dwSize > FIELD_OFFSET(DD_D3DBUFCALLBACKS, LockD3DBuffer)) &&
(lpD3DBufCallbacks->LockD3DBuffer)) {
if (lpD3DBufCallbacks->LockD3DBuffer != WatchdogDdLockD3DBuffer) {
pldev->apfnDriver[INDEX_DdLockD3DBuffer] = (PFN)lpD3DBufCallbacks->LockD3DBuffer;
}
lpD3DBufCallbacks->LockD3DBuffer = WatchdogDdLockD3DBuffer;
}
if ((lpD3DBufCallbacks->dwSize > FIELD_OFFSET(DD_D3DBUFCALLBACKS, UnlockD3DBuffer)) &&
(lpD3DBufCallbacks->UnlockD3DBuffer)) {
if (lpD3DBufCallbacks->UnlockD3DBuffer != WatchdogDdUnlockD3DBuffer) {
pldev->apfnDriver[INDEX_DdUnlockD3DBuffer] = (PFN)lpD3DBufCallbacks->UnlockD3DBuffer;
}
lpD3DBufCallbacks->UnlockD3DBuffer = WatchdogDdUnlockD3DBuffer;
}
}
}
return bRet;
}
BOOL APIENTRY
WatchdogDrvEnableDirectDraw(
DHPDEV dhpdev,
DD_CALLBACKS *pCallBacks,
DD_SURFACECALLBACKS *pSurfaceCallBacks,
DD_PALETTECALLBACKS *pPaletteCallBacks
)
{
PFN_DrvEnableDirectDraw pfn = (PFN_DrvEnableDirectDraw) dhpdevRetrievePfn((ULONG_PTR)dhpdev,INDEX_DrvEnableDirectDraw);
BOOL bRet = FALSE;
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev(dhpdev)->bThreadStuck) {
return FALSE;
}
__try {
bRet = pfn(dhpdev, pCallBacks, pSurfaceCallBacks, pPaletteCallBacks);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
//
// Handle stuck thread excepton
//
HandleStuckThreadException(dhpdevRetrieveLdev(dhpdev));
}
//
// If the function succeeded, then try to capture the Callback functions.
//
if (bRet) {
PLDEV pldev = dhpdevRetrieveLdev(dhpdev);
//
// Capture generic callbacks
//
if (pCallBacks->dwFlags & DDHAL_CB32_CANCREATESURFACE) {
if (pCallBacks->CanCreateSurface != WatchdogDdCanCreateSurface) {
pldev->apfnDriver[INDEX_DdCanCreateSurface] = (PFN)pCallBacks->CanCreateSurface;
}
pCallBacks->CanCreateSurface = WatchdogDdCanCreateSurface;
}
if (pCallBacks->dwFlags & DDHAL_CB32_CREATESURFACE) {
if (pCallBacks->CreateSurface != WatchdogDdCreateSurface) {
pldev->apfnDriver[INDEX_DdCreateSurface] = (PFN)pCallBacks->CreateSurface;
}
pCallBacks->CreateSurface = WatchdogDdCreateSurface;
}
if (pCallBacks->dwFlags & DDHAL_CB32_CREATEPALETTE) {
if (pCallBacks->CreatePalette != WatchdogDdCreatePalette) {
pldev->apfnDriver[INDEX_DdCreatePalette] = (PFN)pCallBacks->CreatePalette;
}
pCallBacks->CreatePalette = WatchdogDdCreatePalette;
}
if (pCallBacks->dwFlags & DDHAL_CB32_GETSCANLINE) {
if (pCallBacks->GetScanLine != WatchdogDdGetScanLine) {
pldev->apfnDriver[INDEX_DdGetScanLine] = (PFN)pCallBacks->GetScanLine;
}
pCallBacks->GetScanLine = WatchdogDdGetScanLine;
}
if (pCallBacks->dwFlags & DDHAL_CB32_MAPMEMORY) {
if (pCallBacks->MapMemory != WatchdogDdMapMemory) {
pldev->apfnDriver[INDEX_DdMapMemory] = (PFN)pCallBacks->MapMemory;
}
pCallBacks->MapMemory = WatchdogDdMapMemory;
}
#if 0
//
// We can't hook this because there is no way to get the dhpdev
// back
//
if (pCallBacks->dwFlags & DDHAL_CB32_SETCOLORKEY) {
if (pCallBacks->SetColorKey != WatchdogDdSetColorKey) {
pldev->apfnDriver[INDEX_DdSetColorKey] = (PFN)pCallBacks->SetColorKey;
}
pCallBacks->SetColorKey = WatchdogDdSetColorKey;
}
#endif
if (pCallBacks->dwFlags & DDHAL_CB32_WAITFORVERTICALBLANK) {
if (pCallBacks->WaitForVerticalBlank != WatchdogDdWaitForVerticalBlank) {
pldev->apfnDriver[INDEX_DdWaitForVerticalBlank] = (PFN)pCallBacks->WaitForVerticalBlank;
}
pCallBacks->WaitForVerticalBlank = WatchdogDdWaitForVerticalBlank;
}
//
// Capture Surface Callbacks
//
if (pSurfaceCallBacks->dwFlags & DDHAL_SURFCB32_DESTROYSURFACE) {
if (pSurfaceCallBacks->DestroySurface != WatchdogDdDestroySurface) {
pldev->apfnDriver[INDEX_DdDestroySurface] = (PFN)pSurfaceCallBacks->DestroySurface;
}
pSurfaceCallBacks->DestroySurface = WatchdogDdDestroySurface;
}
if (pSurfaceCallBacks->dwFlags & DDHAL_SURFCB32_FLIP) {
if (pSurfaceCallBacks->Flip != WatchdogDdFlip) {
pldev->apfnDriver[INDEX_DdFlip] = (PFN)pSurfaceCallBacks->Flip;
}
pSurfaceCallBacks->Flip = WatchdogDdFlip;
}
#if 0
//
// SetClipList is obsolete
//
if (pSurfaceCallBacks->dwFlags & DDHAL_SURFCB32_SETCLIPLIST) {
if (pSurfaceCallBacks->SetClipList != WatchdogDdSetClipList) {
pldev->apfnDriver[INDEX_DdSetClipList] = (PFN)pSurfaceCallBacks->SetClipList;
}
pSurfaceCallBacks->SetClipList = WatchdogDdSetClipList;
}
#endif
if (pSurfaceCallBacks->dwFlags & DDHAL_SURFCB32_LOCK) {
if (pSurfaceCallBacks->Lock != WatchdogDdLock) {
pldev->apfnDriver[INDEX_DdLock] = (PFN)pSurfaceCallBacks->Lock;
}
pSurfaceCallBacks->Lock = WatchdogDdLock;
}
if (pSurfaceCallBacks->dwFlags & DDHAL_SURFCB32_UNLOCK) {
if (pSurfaceCallBacks->Unlock != WatchdogDdUnlock) {
pldev->apfnDriver[INDEX_DdUnlock] = (PFN)pSurfaceCallBacks->Unlock;
}
pSurfaceCallBacks->Unlock = WatchdogDdUnlock;
}
if (pSurfaceCallBacks->dwFlags & DDHAL_SURFCB32_BLT) {
if (pSurfaceCallBacks->Blt != WatchdogDdBlt) {
pldev->apfnDriver[INDEX_DdBlt] = (PFN)pSurfaceCallBacks->Blt;
}
pSurfaceCallBacks->Blt = WatchdogDdBlt;
}
#if 0
//
// We can't hook this because there is no way to get the dhpdev
// back
//
if (pSurfaceCallBacks->dwFlags & DDHAL_SURFCB32_SETCOLORKEY) {
if (pSurfaceCallBacks->SetColorKey != WatchdogDdSetColorKey) {
pldev->apfnDriver[INDEX_DdSetColorKey] = (PFN)pSurfaceCallBacks->SetColorKey;
}
pSurfaceCallBacks->SetColorKey = WatchdogDdSetColorKey;
}
#endif
if (pSurfaceCallBacks->dwFlags & DDHAL_SURFCB32_ADDATTACHEDSURFACE) {
if (pSurfaceCallBacks->AddAttachedSurface != WatchdogDdAddAttachedSurface) {
pldev->apfnDriver[INDEX_DdAddAttachedSurface] = (PFN)pSurfaceCallBacks->AddAttachedSurface;
}
pSurfaceCallBacks->AddAttachedSurface = WatchdogDdAddAttachedSurface;
}
if (pSurfaceCallBacks->dwFlags & DDHAL_SURFCB32_GETBLTSTATUS) {
if (pSurfaceCallBacks->GetBltStatus != WatchdogDdGetBltStatus) {
pldev->apfnDriver[INDEX_DdGetBltStatus] = (PFN)pSurfaceCallBacks->GetBltStatus;
}
pSurfaceCallBacks->GetBltStatus = WatchdogDdGetBltStatus;
}
if (pSurfaceCallBacks->dwFlags & DDHAL_SURFCB32_GETFLIPSTATUS) {
if (pSurfaceCallBacks->GetFlipStatus != WatchdogDdGetFlipStatus) {
pldev->apfnDriver[INDEX_DdGetFlipStatus] = (PFN)pSurfaceCallBacks->GetFlipStatus;
}
pSurfaceCallBacks->GetFlipStatus = WatchdogDdGetFlipStatus;
}
if (pSurfaceCallBacks->dwFlags & DDHAL_SURFCB32_UPDATEOVERLAY) {
if (pSurfaceCallBacks->UpdateOverlay != WatchdogDdUpdateOverlay) {
pldev->apfnDriver[INDEX_DdUpdateOverlay] = (PFN)pSurfaceCallBacks->UpdateOverlay;
}
pSurfaceCallBacks->UpdateOverlay = WatchdogDdUpdateOverlay;
}
if (pSurfaceCallBacks->dwFlags & DDHAL_SURFCB32_SETOVERLAYPOSITION) {
if (pSurfaceCallBacks->SetOverlayPosition != WatchdogDdSetOverlayPosition) {
pldev->apfnDriver[INDEX_DdSetOverlayPosition] = (PFN)pSurfaceCallBacks->SetOverlayPosition;
}
pSurfaceCallBacks->SetOverlayPosition = WatchdogDdSetOverlayPosition;
}
if (pSurfaceCallBacks->dwFlags & DDHAL_SURFCB32_SETPALETTE) {
if (pSurfaceCallBacks->SetPalette != WatchdogDdSetPalette) {
pldev->apfnDriver[INDEX_DdSetPalette] = (PFN)pSurfaceCallBacks->SetPalette;
}
pSurfaceCallBacks->SetPalette = WatchdogDdSetPalette;
}
//
// Capture Palette Callbacks
//
if (pPaletteCallBacks->dwFlags & DDHAL_PALCB32_DESTROYPALETTE) {
if (pPaletteCallBacks->DestroyPalette != WatchdogDdDestroyPalette) {
pldev->apfnDriver[INDEX_DdDestroyPalette] = (PFN)pPaletteCallBacks->DestroyPalette;
}
pPaletteCallBacks->DestroyPalette = WatchdogDdDestroyPalette;
}
if (pPaletteCallBacks->dwFlags & DDHAL_PALCB32_SETENTRIES) {
if (pPaletteCallBacks->SetEntries != WatchdogDdSetEntries) {
pldev->apfnDriver[INDEX_DdSetEntries] = (PFN)pPaletteCallBacks->SetEntries;
}
pPaletteCallBacks->SetEntries = WatchdogDdSetEntries;
}
}
return bRet;
}
VOID APIENTRY
WatchdogDrvDisableDirectDraw(
DHPDEV dhpdev
)
{
PFN_DrvDisableDirectDraw pfn = (PFN_DrvDisableDirectDraw) dhpdevRetrievePfn((ULONG_PTR)dhpdev,INDEX_DrvDisableDirectDraw);
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev(dhpdev)->bThreadStuck) {
return;
}
__try {
pfn(dhpdev);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
//
// Handle stuck thread excepton
//
HandleStuckThreadException(dhpdevRetrieveLdev(dhpdev));
}
}
BOOL APIENTRY
WatchdogDrvIcmSetDeviceGammaRamp(
IN DHPDEV dhpdev,
IN ULONG iFormat,
IN LPVOID ipRamp
)
{
PFN_DrvIcmSetDeviceGammaRamp pfn = (PFN_DrvIcmSetDeviceGammaRamp) dhpdevRetrievePfn((ULONG_PTR)dhpdev,INDEX_DrvIcmSetDeviceGammaRamp);
BOOL bRet = TRUE;
if (dhpdevRetrieveLdev(dhpdev)->bThreadStuck) {
return bRet;
}
__try {
bRet = pfn(dhpdev, iFormat, ipRamp);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
//
// Handle stuck thread excepton
//
HandleStuckThreadException(dhpdevRetrieveLdev(dhpdev));
}
return bRet;
}
BOOL APIENTRY
WatchdogDrvStretchBltROP(
SURFOBJ *psoDst,
SURFOBJ *psoSrc,
SURFOBJ *psoMask,
CLIPOBJ *pco,
XLATEOBJ *pxlo,
COLORADJUSTMENT *pca,
POINTL *pptlHTOrg,
RECTL *prclDst,
RECTL *prclSrc,
POINTL *pptlMask,
ULONG iMode,
BRUSHOBJ *pbo,
DWORD rop4
)
{
SURFOBJ *psoDevice = (psoDst->dhpdev) ? psoDst : psoSrc;
PFN_DrvStretchBltROP pfn = (PFN_DrvStretchBltROP) dhpdevRetrievePfn((ULONG_PTR)psoDevice->dhpdev,INDEX_DrvStretchBltROP);
BOOL bRet = TRUE;
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev(psoDevice->dhpdev)->bThreadStuck) {
return TRUE;
}
__try {
bRet = pfn(psoDst, psoSrc, psoMask, pco, pxlo, pca, pptlHTOrg, prclDst, prclSrc, pptlMask, iMode, pbo, rop4);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
//
// Handle stuck thread excepton
//
HandleStuckThreadException(dhpdevRetrieveLdev(psoDevice->dhpdev));
}
return bRet;
}
BOOL APIENTRY
WatchdogDrvPlgBlt(
IN SURFOBJ *psoTrg,
IN SURFOBJ *psoSrc,
IN SURFOBJ *psoMsk,
IN CLIPOBJ *pco,
IN XLATEOBJ *pxlo,
IN COLORADJUSTMENT *pca,
IN POINTL *pptlBrushOrg,
IN POINTFIX *pptfx,
IN RECTL *prcl,
IN POINTL *pptl,
IN ULONG iMode
)
{
PFN_DrvPlgBlt pfn = (PFN_DrvPlgBlt) dhpdevRetrievePfn((ULONG_PTR)psoTrg->dhpdev,INDEX_DrvPlgBlt);
BOOL bRet = TRUE;
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev(psoTrg->dhpdev)->bThreadStuck) {
return TRUE;
}
__try {
bRet = pfn(psoTrg, psoSrc, psoMsk, pco, pxlo, pca, pptlBrushOrg, pptfx, prcl, pptl, iMode);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
//
// Handle stuck thread excepton
//
HandleStuckThreadException(dhpdevRetrieveLdev(psoTrg->dhpdev));
}
return bRet;
}
BOOL APIENTRY
WatchdogDrvAlphaBlend(
SURFOBJ *psoDest,
SURFOBJ *psoSrc,
CLIPOBJ *pco,
XLATEOBJ *pxlo,
RECTL *prclDest,
RECTL *prclSrc,
BLENDOBJ *pBlendObj
)
{
SURFOBJ *psoDevice = (psoDest->dhpdev) ? psoDest : psoSrc;
PFN_DrvAlphaBlend pfn = (PFN_DrvAlphaBlend) dhpdevRetrievePfn((ULONG_PTR)psoDevice->dhpdev,INDEX_DrvAlphaBlend);
BOOL bRet = TRUE;
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev(psoDevice->dhpdev)->bThreadStuck) {
return TRUE;
}
__try {
bRet = pfn(psoDest, psoSrc, pco, pxlo, prclDest, prclSrc, pBlendObj);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
//
// Handle stuck thread excepton
//
HandleStuckThreadException(dhpdevRetrieveLdev(psoDevice->dhpdev));
}
return bRet;
}
BOOL APIENTRY
WatchdogDrvGradientFill(
SURFOBJ *psoDest,
CLIPOBJ *pco,
XLATEOBJ *pxlo,
TRIVERTEX *pVertex,
ULONG nVertex,
PVOID pMesh,
ULONG nMesh,
RECTL *prclExtents,
POINTL *pptlDitherOrg,
ULONG ulMode
)
{
PFN_DrvGradientFill pfn = (PFN_DrvGradientFill) dhpdevRetrievePfn((ULONG_PTR)psoDest->dhpdev,INDEX_DrvGradientFill);
BOOL bRet = TRUE;
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev(psoDest->dhpdev)->bThreadStuck) {
return TRUE;
}
__try {
bRet = pfn(psoDest, pco, pxlo, pVertex, nVertex, pMesh, nMesh, prclExtents, pptlDitherOrg, ulMode);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
//
// Handle stuck thread excepton
//
HandleStuckThreadException(dhpdevRetrieveLdev(psoDest->dhpdev));
}
return bRet;
}
BOOL APIENTRY
WatchdogDrvTransparentBlt(
SURFOBJ *psoDst,
SURFOBJ *psoSrc,
CLIPOBJ *pco,
XLATEOBJ *pxlo,
RECTL *prclDst,
RECTL *prclSrc,
ULONG iTransColor,
ULONG ulReserved
)
{
SURFOBJ *psoDevice = (psoDst->dhpdev) ? psoDst : psoSrc;
PFN_DrvTransparentBlt pfn = (PFN_DrvTransparentBlt) dhpdevRetrievePfn((ULONG_PTR)psoDevice->dhpdev,INDEX_DrvTransparentBlt);
BOOL bRet = TRUE;
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev(psoDevice->dhpdev)->bThreadStuck) {
return TRUE;
}
__try {
bRet = pfn(psoDst, psoSrc, pco, pxlo, prclDst, prclSrc, iTransColor, ulReserved);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
//
// Handle stuck thread excepton
//
HandleStuckThreadException(dhpdevRetrieveLdev(psoDevice->dhpdev));
}
return bRet;
}
HBITMAP APIENTRY
WatchdogDrvDeriveSurface(
DD_DIRECTDRAW_GLOBAL *pDirectDraw,
DD_SURFACE_LOCAL *pSurface
)
{
PFN_DrvDeriveSurface pfn = (PFN_DrvDeriveSurface) dhpdevRetrievePfn((ULONG_PTR)pDirectDraw->dhpdev, INDEX_DrvDeriveSurface);
HBITMAP hBitmap = NULL;
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev((DHPDEV)pDirectDraw->dhpdev)->bThreadStuck == FALSE) {
PASSOCIATION_NODE Node = AssociationCreateNode();
if (Node) {
__try {
hBitmap = pfn(pDirectDraw, pSurface);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
//
// Handle stuck thread excepton
//
HandleStuckThreadException(dhpdevRetrieveLdev((DHPDEV)pDirectDraw->dhpdev));
}
if (hBitmap) {
//
// Get the DHSURF that is associated with the hbitmap, and
// cache it away so we can look it up when a DrvDeleteDeviceBitmap
// call comes down.
//
SURFREF so;
so.vAltCheckLockIgnoreStockBit((HSURF)hBitmap);
Node->key = (ULONG_PTR)so.ps->dhsurf();
Node->data = (ULONG_PTR)dhpdevRetrieveLdev((DHPDEV)pDirectDraw->dhpdev);
Node->hsurf = (ULONG_PTR)hBitmap;
//
// If an association node already exists, with this association
// then use it.
//
if (AssociationIsNodeInList(Node) == FALSE) {
AssociationInsertNodeAtTail(Node);
} else {
AssociationDeleteNode(Node);
}
} else {
AssociationDeleteNode(Node);
}
}
}
return hBitmap;
}
VOID APIENTRY
WatchdogDrvNotify(
IN SURFOBJ *pso,
IN ULONG iType,
IN PVOID pvData
)
{
PFN_DrvNotify pfn = (PFN_DrvNotify) dhpdevRetrievePfn((ULONG_PTR)pso->dhpdev, INDEX_DrvNotify);
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev(pso->dhpdev)->bThreadStuck) {
return;
}
__try {
pfn(pso, iType, pvData);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
//
// Handle stuck thread excepton
//
HandleStuckThreadException(dhpdevRetrieveLdev(pso->dhpdev));
}
}
VOID APIENTRY
WatchdogDrvSynchronizeSurface(
IN SURFOBJ *pso,
IN RECTL *prcl,
IN FLONG fl
)
{
PFN_DrvSynchronizeSurface pfn = (PFN_DrvSynchronizeSurface) dhpdevRetrievePfn((ULONG_PTR)pso->dhpdev, INDEX_DrvSynchronizeSurface);
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev(pso->dhpdev)->bThreadStuck) {
return;
}
__try {
pfn(pso, prcl, fl);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
//
// Handle stuck thread excepton
//
HandleStuckThreadException(dhpdevRetrieveLdev(pso->dhpdev));
}
}
VOID APIENTRY
WatchdogDrvResetDevice(
DHPDEV dhpdev,
PVOID Reserved
)
{
PFN_DrvResetDevice pfn = (PFN_DrvResetDevice) dhpdevRetrievePfn((ULONG_PTR)dhpdev,INDEX_DrvResetDevice);
//
// Return early if we are in a thread stuck condition
//
if (dhpdevRetrieveLdev(dhpdev)->bThreadStuck) {
return;
}
__try {
pfn(dhpdev, Reserved);
} __except(GetExceptionCode() == SE_THREAD_STUCK) {
//
// Handle stuck thread excepton
//
HandleStuckThreadException(dhpdevRetrieveLdev(dhpdev));
}
}
//
// The following table contains the replacement functions which
// hooks the real driver entry points, and set up the try/except
// handlers.
//
PFN WatchdogTable[INDEX_LAST] =
{
(PFN)WatchdogDrvEnablePDEV,
(PFN)WatchdogDrvCompletePDEV,
(PFN)WatchdogDrvDisablePDEV,
(PFN)WatchdogDrvEnableSurface,
(PFN)WatchdogDrvDisableSurface,
(PFN)WatchdogDrvAssertMode,
0, // DrvOffset - obsolete
(PFN)WatchdogDrvResetPDEV,
0, // DrvDisableDriver - don't hook
0, // not assigned
(PFN)WatchdogDrvCreateDeviceBitmap,
(PFN)WatchdogDrvDeleteDeviceBitmap,
(PFN)WatchdogDrvRealizeBrush,
(PFN)WatchdogDrvDitherColor,
(PFN)WatchdogDrvStrokePath,
(PFN)WatchdogDrvFillPath,
(PFN)WatchdogDrvStrokeAndFillPath,
0, // DrvPaint - obsolete
(PFN)WatchdogDrvBitBlt,
(PFN)WatchdogDrvCopyBits,
(PFN)WatchdogDrvStretchBlt,
0, // not assigned
(PFN)WatchdogDrvSetPalette,
(PFN)WatchdogDrvTextOut,
(PFN)WatchdogDrvEscape,
(PFN)WatchdogDrvDrawEscape,
0, // DrvQueryFont
0, // DrvQueryFontTree
0, // DrvQueryFontData
(PFN)WatchdogDrvSetPointerShape,
(PFN)WatchdogDrvMovePointer,
(PFN)WatchdogDrvLineTo,
0, // DrvSendPage
0, // DrvStartPage
0, // DrvEndDoc
0, // DrvStartDoc
0, // not assigned
0, // DrvGetGlyphMode
(PFN)WatchdogDrvSynchronize,
0, // not assigned
(PFN)WatchdogDrvSaveScreenBits,
0, // DrvGetModes - don't hook
0, // DrvFree
0, // DrvDestroyFont
0, // DrvQueryFontCaps
0, // DrvLoadFontFile
0, // DrvUnloadFontFile
0, // DrvFontManagement
0, // DrvQueryTrueTypeTable
0, // DrvQueryTrueTypeOutline
0, // DrvGetTrueTypeFile
0, // DrvQueryFontFile
0, // DrvMovePanning
0, // DrvQueryAdvanceWidths
(PFN)WatchdogDrvSetPixelFormat,
(PFN)WatchdogDrvDescribePixelFormat,
(PFN)WatchdogDrvSwapBuffers,
0, // DrvStartBanding
0, // DrvNextBand
(PFN)WatchdogDrvGetDirectDrawInfo,
(PFN)WatchdogDrvEnableDirectDraw,
(PFN)WatchdogDrvDisableDirectDraw,
0, // DrvQuerySpoolType
0, // not assigned
0, // DrvIcmCreateColorTransform
0, // DrvIcmDeleteColorTransform
0, // DrvIcmCheckBitmapBits
(PFN)WatchdogDrvIcmSetDeviceGammaRamp,
(PFN)WatchdogDrvGradientFill,
(PFN)WatchdogDrvStretchBltROP,
(PFN)WatchdogDrvPlgBlt,
(PFN)WatchdogDrvAlphaBlend,
0, // DrvSynthesizeFont
0, // DrvGetSynthesizedFontFiles
(PFN)WatchdogDrvTransparentBlt,
0, // DrvQueryPerBandInfo
0, // DrvQueryDeviceSupport
0, // reserved
0, // reserved
0, // reserved
0, // reserved
0, // reserved
0, // reserved
0, // reserved
0, // reserved
(PFN)WatchdogDrvDeriveSurface,
0, // DrvQueryGlyphAttrs
(PFN)WatchdogDrvNotify,
(PFN)WatchdogDrvSynchronizeSurface,
(PFN)WatchdogDrvResetDevice,
0, // reserved
0, // reserved
0 // reserved
};
BOOL
WatchdogIsFunctionHooked(
IN PLDEV pldev,
IN ULONG functionIndex
)
/*++
Routine Description:
This function checks to see whether the Create/DeleteDeviceBitmap
driver entry points are hooked.
Return Value:
TRUE if the entry point is hooked,
FALSE otherwise
--*/
{
ASSERTGDI(functionIndex < INDEX_LAST, "functionIndex out of range");
return pldev->apfn[functionIndex] == WatchdogTable[functionIndex];
}