|
|
/******************************Module*Header*******************************\
* Module Name: dvpe.cxx * * Contains all of GDI's private VideoPort APIs. * * Note that for videoport support, WIN32K.SYS and DXAPI.SYS are closely * linked. DXAPI.SYS provides two services: * * 1. It handles the "software autoflipping" support for the videoports, * where the CPU handles the videoport field-done interrupt to * flip the overlay and do "bob" and "weave" for better video * quality. * 2. It provides the public DirectDraw entry points that are callable * by other kernel-mode WDM drivers (there is a corresponding DXAPI.SYS * module on Memphis/Win95 that exposes the same interface). * * All of the non-paged code for videoports has to go into DXAPI.SYS since * WIN32K.SYS is marked entirely as pageable. WIN32K.SYS handles some * functionality on behalf of DXAPI.SYS, such as object opens and closes, * since only WIN32K.SYS can access GDI's handle table. * * Created: 17-Oct-1996 * Author: Lingyun Wang [LingyunW] * * Copyright (c) 1996-1999 Microsoft Corporation * \**************************************************************************/
#include "precomp.hxx"
extern PEPROCESS gpepSession;
VOID vDdDxApiFreeDirectDraw( DXOBJ* pDxObj, BOOL bDoCallBack );
/////////////////////////////////////////////////////////////////////////
// DXAPI concerns:
//
// - Document that call-back may not occur in context of same process
// - Refuse to open surface, videoport objects while full-screen
// Keep DirectDraw open so that POSTFULLSCREEN and DOSBOX can be honored
// - See InitKernelInterface for init restrictions
// - Flush DMA buffer before mode changes?
// - Invalidate dxapi data after mode change?
// - Right now, DirectDraw DXAPI objects have to be closed last
/////////////////////////////////////////////////////////////////////////
// VPE concerns:
//
// - Make sure VideoPort's not duplicated on same device
// - Document that display driver cannot use pool-allocated memory for
// dwReserved fields on Synchronize calls
// - Close DxVideoPort objects on full-screen switch?
// No, to support hardware that can DMA even while full-screen!
// Okay, but what about mode changes? There's no way they'll not
// be able to drop frames
// - Never close DxDirectDraw objects?
/*****************************Private*Routine******************************\
* ULONG vDdNullCallBack * * The DXAPI register routines require a close call-back routine to notify * the client that the object is going away. Since we're really DirectDraw, * we already know when the object is going away; hence, this routine doesn't * need to do anything. * * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo] * Wrote it. \**************************************************************************/
ULONG vDdNullCallBack( DWORD dwFlags, PVOID pContext, DWORD dwParam1, DWORD dwParam2 ) { return 0; }
/*****************************Private*Routine******************************\
* VOID vDdUnloadDxApiImage * * This routine performs the actual unload of DXAPI.SYS. * * 28-Oct-1997 -by- smac * Wrote it. \**************************************************************************/
VOID vDdUnloadDxApiImage( EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal ) { EDD_VIDEOPORT* peVideoPort; EDD_VIDEOPORT* peVideoPortNext; EDD_SURFACE* peSurface; EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal;
DD_ASSERTDEVLOCK(peDirectDrawGlobal);
// Notify clients that the resources are lost and clean up
for (peDirectDrawLocal = peDirectDrawGlobal->peDirectDrawLocalList; peDirectDrawLocal != NULL; peDirectDrawLocal = peDirectDrawLocal->peDirectDrawLocalNext) { // If any video port still exist (which should not be the case)
// delete all of the video port objects since the video port assumes
// that DXAPI.SYS is loaded.
for (peVideoPort = peDirectDrawLocal->peVideoPort_DdList; peVideoPort != NULL; peVideoPort = peVideoPortNext) { // Don't reference peVideoPort after it's been deleted!
peVideoPortNext = peVideoPort->peVideoPort_DdNext; bDdDeleteVideoPortObject(peVideoPort->hGet(), NULL); }
// If a surface still has a client using it, shut it down.
peSurface = peDirectDrawLocal->peSurface_Enum(NULL);
while (peSurface) { if (peSurface->hSurface != NULL) { vDdDxApiFreeSurface( (DXOBJ*) peSurface->hSurface, FALSE ); peSurface->hSurface = NULL; } if( peSurface->peDxSurface != NULL ) { vDdLoseDxObjects( peDirectDrawGlobal, peSurface->peDxSurface->pDxObj_List, (PVOID) peSurface->peDxSurface, LO_SURFACE ); } peSurface = peDirectDrawLocal->peSurface_Enum(peSurface); } } if (peDirectDrawGlobal->hDirectDraw != NULL) { vDdDxApiFreeDirectDraw( (DXOBJ*) peDirectDrawGlobal->hDirectDraw, FALSE ); } if( peDirectDrawGlobal->peDxDirectDraw != NULL ) { vDdLoseDxObjects( peDirectDrawGlobal, peDirectDrawGlobal->peDxDirectDraw->pDxObj_List, (PVOID) peDirectDrawGlobal->peDxDirectDraw, LO_DIRECTDRAW ); }
EngUnloadImage(peDirectDrawGlobal->hDxApi);
//
// Free the memory associate with the module
//
peDirectDrawGlobal->hDxApi = NULL; peDirectDrawGlobal->dwDxApiRefCnt = 0; }
/*****************************Private*Routine******************************\
* BOOL bDdLoadDxApi * * This routine loads up DXAPI.SYS and allocates the non-paged DXAPI * structures. * * Returns: FALSE only if a DXAPI resource could not be allocated. * * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo] * Wrote it. * 16-Oct-1977 -by- smac * Broke it out into a separate function. \**************************************************************************/
BOOL bDdLoadDxApi( EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal ) { EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal; HANDLE hDxApi; PFNDXAPIINITIALIZE pfnDxApiInitialize; DDOPENDIRECTDRAWIN OpenDirectDrawIn; DDOPENDIRECTDRAWOUT OpenDirectDrawOut; DWORD dwRet;
DD_ASSERTDEVLOCK(peDirectDrawLocal->peDirectDrawGlobal); peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
/*
* Don't load if it's already loaded */ if (peDirectDrawGlobal->hDxApi == NULL) { ASSERTGDI((peDirectDrawGlobal->hDirectDraw == NULL) && (peDirectDrawGlobal->hDxApi == NULL), "Expected NULL hDirectDraw and hDxApi");
BOOL loaded;
hDxApi = DxEngLoadImage(L"drivers\\dxapi.sys",FALSE); if (hDxApi) { peDirectDrawGlobal->hDxApi = hDxApi; peDirectDrawGlobal->pfnDxApi = (LPDXAPI) EngFindImageProcAddress(hDxApi, "_DxApi"); peDirectDrawGlobal->pfnAutoflipUpdate = (PFNAUTOFLIPUPDATE) EngFindImageProcAddress(hDxApi, "_DxAutoflipUpdate"); peDirectDrawGlobal->pfnLoseObject = (PFNLOSEOBJECT) EngFindImageProcAddress(hDxApi, "_DxLoseObject"); pfnDxApiInitialize = (PFNDXAPIINITIALIZE) EngFindImageProcAddress(hDxApi, "_DxApiInitialize"); peDirectDrawGlobal->pfnEnableIRQ = (PFNENABLEIRQ) EngFindImageProcAddress(hDxApi, "_DxEnableIRQ"); peDirectDrawGlobal->pfnUpdateCapture = (PFNUPDATECAPTURE) EngFindImageProcAddress(hDxApi, "_DxUpdateCapture");
ASSERTGDI(peDirectDrawGlobal->pfnDxApi != NULL, "Couldn't find DxApi'"); ASSERTGDI(peDirectDrawGlobal->pfnAutoflipUpdate != NULL, "Couldn't find DxAutoflipUpdate"); ASSERTGDI(peDirectDrawGlobal->pfnLoseObject != NULL, "Couldn't find DxLoseObject"); ASSERTGDI(peDirectDrawGlobal->pfnEnableIRQ != NULL, "Couldn't find DxEnableIRQ"); ASSERTGDI(peDirectDrawGlobal->pfnUpdateCapture != NULL, "Couldn't find DxUpdateCapture"); ASSERTGDI(pfnDxApiInitialize != NULL, "Couldn't find DxApiInitialize");
// By explicitly passing dxapi.sys its private win32k.sys
// entry points, we don't have to export them from win32k.sys,
// thus preventing any drivers from using those entry points
// for their own nefarious purposes.
pfnDxApiInitialize(DdDxApiOpenDirectDraw, DdDxApiOpenVideoPort, DdDxApiOpenSurface, DdDxApiCloseHandle, DdDxApiGetKernelCaps, DdDxApiOpenCaptureDevice, DdDxApiLockDevice, DdDxApiUnlockDevice);
// EngLoadImage always makes the entire driver pageable, but
// DXAPI.SYS handles the DPC for the videoport interrupt and
// so cannot be entirely pageable. Consequently, we reset
// the paging now:
MmResetDriverPaging(pfnDxApiInitialize);
// Now open the DXAPI version of DirectDraw:
OpenDirectDrawIn.pfnDirectDrawClose = vDdNullCallBack; OpenDirectDrawIn.pContext = NULL; OpenDirectDrawIn.dwDirectDrawHandle = (ULONG_PTR) peDirectDrawLocal->hGet();
peDirectDrawGlobal->pfnDxApi(DD_DXAPI_OPENDIRECTDRAW, &OpenDirectDrawIn, sizeof(OpenDirectDrawIn), &OpenDirectDrawOut, sizeof(OpenDirectDrawOut));
if (OpenDirectDrawOut.ddRVal == DD_OK) { // Success!
peDirectDrawGlobal->hDirectDraw = OpenDirectDrawOut.hDirectDraw; }
peDirectDrawGlobal->dwDxApiRefCnt = 1; } else { WARNING("bDdLoadDxApi: Couldn't load dxapi.sys\n"); return(FALSE); } } else { peDirectDrawGlobal->dwDxApiRefCnt++; }
return(TRUE); }
/*****************************Private*Routine******************************\
* VOID vDdUnloadDxApi * * This routine unloads DXAPI.SYS * * 22-Oct-1997 -by- smac \**************************************************************************/
VOID vDdUnloadDxApi( EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal ) { DDCLOSEHANDLE CloseHandle; DWORD dwRet;
if ((peDirectDrawGlobal->hDxApi != NULL) && (peDirectDrawGlobal->dwDxApiRefCnt > 0 )) { if( --peDirectDrawGlobal->dwDxApiRefCnt == 0 ) { if (peDirectDrawGlobal->hDirectDraw != NULL) { CloseHandle.hHandle = peDirectDrawGlobal->hDirectDraw;
peDirectDrawGlobal->pfnDxApi(DD_DXAPI_CLOSEHANDLE, &CloseHandle, sizeof(CloseHandle), &dwRet, sizeof(dwRet));
ASSERTGDI(dwRet == DD_OK, "Unexpected failure from close");
peDirectDrawGlobal->hDirectDraw = NULL; }
vDdUnloadDxApiImage( peDirectDrawGlobal ); } } }
/*****************************Private*Routine******************************\
* BOOL bDdEnableSoftwareAutoflipping * * This routine loads up DXAPI.SYS, allocates the non-paged DXAPI structures * required for software autoflipping, and enables the videoport interrupt. * * Returns: FALSE only if a DXAPI resource could not be allocated. May * return TRUE even if the interrupt hasn't been successfully * enabled (because I expect that interrupts will be usable * on the majority of systems that support videoports, and this * simplifies other code by allowing it to assume that all the * DXAPI structures have been allocated). * * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo] * Wrote it. \**************************************************************************/
BOOL bDdEnableSoftwareAutoflipping( EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal, EDD_VIDEOPORT* peVideoPort, DWORD dwVideoPortID, BOOL bFirst ) { EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal; HANDLE hDxApi; PFNDXAPIINITIALIZE pfnDxApiInitialize; DDOPENDIRECTDRAWIN OpenDirectDrawIn; DDOPENDIRECTDRAWOUT OpenDirectDrawOut; DDOPENVIDEOPORTIN OpenVideoPortIn; DDOPENVIDEOPORTOUT OpenVideoPortOut; DWORD dwRet; UNICODE_STRING UnicodeString;
DD_ASSERTDEVLOCK(peVideoPort->peDirectDrawGlobal);
peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
// Create a DXAPI DirectDraw object, which we'll need for software
// autoflipping.
if (bFirst) { bDdLoadDxApi( peDirectDrawLocal ); }
if (peDirectDrawGlobal->hDirectDraw != NULL) { ASSERTGDI(peVideoPort->hVideoPort == NULL, "Expected NULL hVideoPort");
OpenVideoPortIn.hDirectDraw = peDirectDrawGlobal->hDirectDraw; OpenVideoPortIn.pfnVideoPortClose = vDdNullCallBack; OpenVideoPortIn.pContext = NULL; OpenVideoPortIn.dwVideoPortHandle = dwVideoPortID;
peDirectDrawGlobal->pfnDxApi(DD_DXAPI_OPENVIDEOPORT, &OpenVideoPortIn, sizeof(OpenVideoPortIn), &OpenVideoPortOut, sizeof(OpenVideoPortOut));
if (OpenVideoPortOut.ddRVal == DD_OK) { peVideoPort->hVideoPort = OpenVideoPortOut.hVideoPort; return(TRUE); } }
return(FALSE); }
/******************************Public*Routine******************************\
* VOID vDdNotifyEvent * * This routine calls back to all registered DXAPI clients when a particular * event (like mode change notification) occurs. * * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo] * Wrote it. \**************************************************************************/
VOID vDdNotifyEvent( EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal, DWORD dwEvent ) { EDD_DXDIRECTDRAW* peDxDirectDraw; DXAPI_EVENT* pDxEvent;
peDxDirectDraw = peDirectDrawGlobal->peDxDirectDraw;
if (peDxDirectDraw != NULL) { DD_ASSERTDEVLOCK(peDirectDrawGlobal);
for (pDxEvent = peDxDirectDraw->pDxEvent_PassiveList; pDxEvent != NULL; pDxEvent = pDxEvent->pDxEvent_Next) { if (pDxEvent->dwEvent == dwEvent) { pDxEvent->pfnCallBack(pDxEvent->dwEvent,pDxEvent->pContext, 0, 0); } } } }
/******************************Public*Routine******************************\
* DXAPI_OBJECT* pDdDxObjHandleAllocate * * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo] * Wrote it. \**************************************************************************/
DXOBJ* pDdDxObjHandleAllocate( DXTYPE iDxType, LPDD_NOTIFYCALLBACK pfnClose, DWORD dwEvent, PVOID pvContext ) { DXOBJ* pDxObj;
ASSERTGDI(pfnClose != NULL, "pDdDxObjHandleAllocate: DXAPI client must supply Close function");
pDxObj = (DXOBJ*) PALLOCNONPAGED(sizeof(*pDxObj),'xxdG'); if (pDxObj != NULL) { pDxObj->iDxType = iDxType; pDxObj->pfnClose = pfnClose; pDxObj->pContext = pvContext; pDxObj->dwEvent = dwEvent; pDxObj->pDxObj_Next = NULL; pDxObj->dwFlags = 0; pDxObj->pepSession = gpepSession; }
return(pDxObj); }
// Should be macro for free build.
PVOID pDdDxObjDataAllocate( ULONG cj, ULONG tag ) { return (PALLOCNONPAGED(cj,tag)); }
VOID vDdDxObjFree( PVOID pvDxObj ) { VFREEMEM(pvDxObj); }
/******************************Public*Routine******************************\
* VOID vDdQueryMiniportDxApiSupport * * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo] * Wrote it. \**************************************************************************/
VOID vDdQueryMiniportDxApiSupport( EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal ) { BOOL bMiniportSupport;
// Assume failure.
bMiniportSupport = FALSE;
if (bDdIoQueryInterface(peDirectDrawGlobal, &GUID_DxApi, sizeof(DXAPI_INTERFACE), DXAPI_HALVERSION, (INTERFACE *)&peDirectDrawGlobal->DxApiInterface)) { ASSERTGDI((peDirectDrawGlobal->DxApiInterface. InterfaceReference == NULL) && (peDirectDrawGlobal->DxApiInterface. InterfaceDereference == NULL), "Miniport shouldn't modify InterfaceReference/Dereference");
// Assert some stuff about hooked entry points?
peDirectDrawGlobal->HwDeviceExtension = peDirectDrawGlobal->DxApiInterface.Context; bMiniportSupport = TRUE; }
// Even if the miniport doesn't support DXAPI accelerations, we still
// allow DXAPI to work (the DXAPI Lock call doesn't require that the
// miniport support DXAPI, for example).
if (!bMiniportSupport) { // Zero out any capabilities:
RtlZeroMemory(&peDirectDrawGlobal->DxApiInterface, sizeof(peDirectDrawGlobal->DxApiInterface)); } }
/******************************Public*Routine******************************\
* DWORD vDdSynchronizeSurface * * Updates the EDD_DXSURFACE structure using the master EDD_SURFACE * structure, with some help from the driver. * * Analagous to Win95's SyncKernelSurface routine. * * This routine lets a driver use fields from the larger, pageable version * of the DD_SURFACE_* structures used by the display driver to set * fields in the smaller, non-pageable version of the corresponding * DDSURFACEDATA structure used by the miniport. * * NOTE: The display driver may NOT use the reserved fields to point to * allocated memory, for two reasons: * * 1. We don't call them when the surfaces is freed, so they'd * lose memory; * 2. We only let display drivers allocate paged memory, which * they can't use in the miniport since they'll be at raised * IRQL when we call them. * * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo] * Wrote it. \**************************************************************************/
VOID vDdSynchronizeSurface( EDD_SURFACE* peSurface ) { EDD_DXSURFACE* peDxSurface; EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal; DD_SYNCSURFACEDATA SyncSurfaceData;
peDirectDrawGlobal = peSurface->peDirectDrawGlobal;
peDxSurface = peSurface->peDxSurface; if (peDxSurface != NULL) { RtlZeroMemory(&SyncSurfaceData, sizeof(SyncSurfaceData));
SyncSurfaceData.lpDD = peDirectDrawGlobal; SyncSurfaceData.lpDDSurface = peSurface; SyncSurfaceData.dwSurfaceOffset = (DWORD) peSurface->fpVidMem; SyncSurfaceData.fpLockPtr = peSurface->fpVidMem + (FLATPTR) peDirectDrawGlobal->HalInfo.vmiData.pvPrimary; SyncSurfaceData.lPitch = peSurface->lPitch;
EDD_DEVLOCK eDevLock(peDirectDrawGlobal);
// Call the driver to let it fill in the rest of the values:
if ((!peDirectDrawGlobal->bSuspended) && (peDirectDrawGlobal->DxApiCallBacks.SyncSurfaceData)) { peDirectDrawGlobal-> DxApiCallBacks.SyncSurfaceData(&SyncSurfaceData); }
// Fields updated by the driver:
peDxSurface->dwSurfaceOffset = SyncSurfaceData.dwSurfaceOffset; peDxSurface->fpLockPtr = SyncSurfaceData.fpLockPtr; peDxSurface->lPitch = SyncSurfaceData.lPitch; peDxSurface->dwOverlayOffset = SyncSurfaceData.dwOverlayOffset; peDxSurface->dwDriverReserved1 = SyncSurfaceData.dwDriverReserved1; peDxSurface->dwDriverReserved2 = SyncSurfaceData.dwDriverReserved2; peDxSurface->dwDriverReserved3 = SyncSurfaceData.dwDriverReserved3; peDxSurface->dwDriverReserved4 = SyncSurfaceData.dwDriverReserved4;
// Fields taken straight from the surface structure:
peDxSurface->ddsCaps = peSurface->ddsCaps.dwCaps; peDxSurface->dwWidth = peSurface->wWidth; peDxSurface->dwHeight = peSurface->wHeight; peDxSurface->dwOverlayFlags = peSurface->dwOverlayFlags; peDxSurface->dwFormatFlags = peSurface->ddpfSurface.dwFlags; peDxSurface->dwFormatFourCC = peSurface->ddpfSurface.dwFourCC; peDxSurface->dwFormatBitCount = peSurface->ddpfSurface.dwRGBBitCount; peDxSurface->dwRBitMask = peSurface->ddpfSurface.dwRBitMask; peDxSurface->dwGBitMask = peSurface->ddpfSurface.dwGBitMask; peDxSurface->dwBBitMask = peSurface->ddpfSurface.dwBBitMask; peDxSurface->dwOverlaySrcWidth = peSurface->dwOverlaySrcWidth; peDxSurface->dwOverlaySrcHeight = peSurface->dwOverlaySrcHeight; peDxSurface->dwOverlayDestWidth = peSurface->dwOverlayDestWidth; peDxSurface->dwOverlayDestHeight = peSurface->dwOverlayDestHeight; } }
/******************************Public*Routine******************************\
* DWORD vDdSynchronizeVideoPort * * Updates the EDD_DXVIDEOPORT structure using the master EDD_VIDEOPORT * structure, with some help from the driver. * * Analagous to Win95's SyncKernelVideoPort routine. * * This routine lets a driver use fields from the larger, pageable version * of the DD_VIDEOPORT_LOCAL structure used by the display driver to set * fields in the smaller, non-pageable version of the corresponding * DDVIDEOPORTDATA structure used by the miniport. * * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo] * Wrote it. \**************************************************************************/
VOID vDdSynchronizeVideoPort( EDD_VIDEOPORT* peVideoPort ) { EDD_DXVIDEOPORT* peDxVideoPort; EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal; DD_SYNCVIDEOPORTDATA SyncVideoPortData;
peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
peDxVideoPort = peVideoPort->peDxVideoPort; if (peDxVideoPort != NULL) { RtlZeroMemory(&SyncVideoPortData, sizeof(SyncVideoPortData));
SyncVideoPortData.lpDD = peDirectDrawGlobal; SyncVideoPortData.lpVideoPort = peVideoPort; SyncVideoPortData.dwVBIHeight = peVideoPort->ddvpInfo.dwVBIHeight;
if (peVideoPort->ddvpInfo.dwVPFlags & DDVP_PRESCALE) { SyncVideoPortData.dwHeight = peVideoPort->ddvpInfo.dwPrescaleHeight; } else if (peVideoPort->ddvpInfo.dwVPFlags & DDVP_CROP) { SyncVideoPortData.dwHeight = peVideoPort->ddvpInfo.rCrop.bottom - peVideoPort->ddvpInfo.rCrop.top; } else { SyncVideoPortData.dwHeight = peVideoPort->ddvpDesc.dwFieldHeight; } if (peVideoPort->ddvpInfo.dwVPFlags & DDVP_INTERLEAVE) { SyncVideoPortData.dwHeight *= 2; }
EDD_DEVLOCK eDevLock(peDirectDrawGlobal);
// Call the driver to let it fill in the rest of the values:
if ((peDirectDrawGlobal->bSuspended) && (peDirectDrawGlobal->DxApiCallBacks.SyncVideoPortData)) { peDirectDrawGlobal-> DxApiCallBacks.SyncVideoPortData(&SyncVideoPortData); }
// Fields updated by the driver:
peDxVideoPort->dwOriginOffset = SyncVideoPortData.dwOriginOffset; peDxVideoPort->dwHeight = SyncVideoPortData.dwHeight; peDxVideoPort->dwVBIHeight = SyncVideoPortData.dwVBIHeight; peDxVideoPort->dwDriverReserved1 = SyncVideoPortData.dwDriverReserved1; peDxVideoPort->dwDriverReserved2 = SyncVideoPortData.dwDriverReserved2; peDxVideoPort->dwDriverReserved3 = SyncVideoPortData.dwDriverReserved3;
// Fields taken straight from the videoport structure:
peDxVideoPort->dwVideoPortId = peVideoPort->ddvpDesc.dwVideoPortID; peDxVideoPort->dwVPFlags = peVideoPort->ddvpInfo.dwVPFlags; if( ( peDxVideoPort->dwVBIHeight > 0 ) && ( peDxVideoPort->dwVPFlags & DDVP_INTERLEAVE ) && !( peDxVideoPort->dwVPFlags & DDVP_VBINOINTERLEAVE ) ) { peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_VBI_INTERLEAVED; } else { peDxVideoPort->flFlags &= ~DD_DXVIDEOPORT_FLAG_VBI_INTERLEAVED; } } }
/******************************Public*Routine******************************\
* HANDLE hDdOpenDxApiSurface * * Opens a DXAPI representation of a surface * * 20-Oct-1997 -by- smac * Wrote it. \**************************************************************************/
HANDLE hDdOpenDxApiSurface( EDD_SURFACE* peSurface ) { DDOPENSURFACEIN OpenSurfaceIn; DDOPENSURFACEOUT OpenSurfaceOut; HANDLE hHandle;
hHandle = NULL;
// Allocate a DXAPI object:
OpenSurfaceIn.hDirectDraw = peSurface->peDirectDrawGlobal->hDirectDraw; OpenSurfaceIn.dwSurfaceHandle = (ULONG_PTR) peSurface->hGet(); OpenSurfaceIn.pfnSurfaceClose = vDdNullCallBack;
peSurface->peDirectDrawGlobal->pfnDxApi(DD_DXAPI_OPENSURFACE, &OpenSurfaceIn, sizeof(OpenSurfaceIn), &OpenSurfaceOut, sizeof(OpenSurfaceOut));
if( ( OpenSurfaceOut.ddRVal == DD_OK ) && ( OpenSurfaceOut.hSurface != NULL ) ) { hHandle = OpenSurfaceOut.hSurface; vDdSynchronizeSurface( peSurface ); }
return hHandle; }
/******************************Public*Routine******************************\
* HANDLE hDdCloseDxApiSurface * * Closes a DXAPI representation of a surface * * 21-Oct-1997 -by- smac * Wrote it. \**************************************************************************/
VOID vDdCloseDxApiSurface( EDD_SURFACE* peSurface ) { DDCLOSEHANDLE CloseHandle; DWORD dwRet;
CloseHandle.hHandle = peSurface->hSurface;
peSurface->peDirectDrawGlobal->pfnDxApi(DD_DXAPI_CLOSEHANDLE, &CloseHandle, sizeof(CloseHandle), &dwRet, sizeof(dwRet));
ASSERTGDI(dwRet == DD_OK, "Expected DD_OK");
peSurface->hSurface = NULL; }
/******************************Public*Routine******************************\
* BOOL bDdUpdateLinksAndSynchronize * * A bidirectional link is maintained between a videoport and its active * surfaces: * * 1. From each surface to the active videoport; * 2. From the videoport to each of its active surfaces. * * This routine does all the maintaining of those links, automatically * removing links from surfaces that are no longer used, and informing * the software autoflipper of the change. * * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo] * Wrote it. \**************************************************************************/
BOOL bDdUpdateLinksAndSynchronize( EDD_VIDEOPORT* peVideoPort, BOOL bNewVideo, // FALSE if 'video' parameters should
EDD_SURFACE** apeNewVideo, // be ignored and current video state
ULONG cAutoflipVideo, // should remain unchanged
BOOL bNewVbi, // FALSE if 'VBI' parameters should
EDD_SURFACE** apeNewVbi, // be ignored and current VBI state
ULONG cAutoflipVbi // should remain unchanged
) { EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal; EDD_DXVIDEOPORT* peDxVideoPort; // EDD_SURFACE* apeTempVideo[MAX_AUTOFLIP_BUFFERS];
// EDD_SURFACE* apeTempVbi[MAX_AUTOFLIP_BUFFERS];
EDD_DXSURFACE* apeDxNewVideo[MAX_AUTOFLIP_BUFFERS]; EDD_DXSURFACE* apeDxNewVbi[MAX_AUTOFLIP_BUFFERS]; ULONG i; BOOL bOk;
peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal; peDxVideoPort = peVideoPort->peDxVideoPort;
if (peDxVideoPort == NULL) return(TRUE);
DD_ASSERTDEVLOCK(peDirectDrawGlobal);
// First, check to make sure the surfaces have been opened
bOk = TRUE; for (i = 0; i < cAutoflipVideo; i++) { if( ( apeNewVideo[i] == NULL ) || ( apeNewVideo[i]->hSurface == NULL ) ) { bOk = FALSE; } } for (i = 0; i < cAutoflipVbi; i++) { if( ( apeNewVbi[i] == NULL ) || ( apeNewVbi[i]->hSurface == NULL ) ) { bOk = FALSE; } }
if (!bOk) { return(FALSE); }
// Remove the videoport links from the old surfaces, and stash a copy
// of the list for later:
for (i = 0; i < peVideoPort->cAutoflipVideo; i++) { peVideoPort->apeSurfaceVideo[i]->lpVideoPort = NULL; if( peVideoPort->apeSurfaceVideo[i]->peDxSurface != NULL ) { peVideoPort->apeSurfaceVideo[i]->peDxSurface->peDxVideoPort = NULL; } } for (i = 0; i < peVideoPort->cAutoflipVbi; i++) { peVideoPort->apeSurfaceVbi[i]->lpVideoPort = NULL; if( peVideoPort->apeSurfaceVbi[i]->peDxSurface != NULL ) { peVideoPort->apeSurfaceVbi[i]->peDxSurface->peDxVideoPort = NULL; } }
// Now add the links to the new surfaces:
for (i = 0; i < cAutoflipVideo; i++) { peVideoPort->apeSurfaceVideo[i] = apeNewVideo[i]; apeNewVideo[i]->lpVideoPort = peVideoPort; apeDxNewVideo[i] = apeNewVideo[i]->peDxSurface; } for (i = 0; i < cAutoflipVbi; i++) { peVideoPort->apeSurfaceVbi[i] = apeNewVbi[i]; apeNewVbi[i]->lpVideoPort = peVideoPort; apeDxNewVbi[i] = apeNewVbi[i]->peDxSurface; }
// Now modify the autoflip buffers, being careful to synchronize with
// the software-autoflip DPC. Note that this does stuff like sets
// peDxVideoPort->cAutoflipVbi.
peDirectDrawGlobal->pfnAutoflipUpdate(peDxVideoPort, apeDxNewVideo, cAutoflipVideo, apeDxNewVbi, cAutoflipVbi);
peVideoPort->cAutoflipVideo = cAutoflipVideo; peVideoPort->cAutoflipVbi = cAutoflipVbi;
// Finally, Update some last public fields in the videoport structure:
peVideoPort->dwNumAutoflip = cAutoflipVideo; peVideoPort->dwNumVBIAutoflip = cAutoflipVbi; peVideoPort->lpSurface = (cAutoflipVideo == 0) ? NULL : apeNewVideo[0]; peVideoPort->lpVBISurface = (cAutoflipVbi == 0) ? NULL : apeNewVbi[0];
return(TRUE); }
/******************************Public*Routine******************************\
* VOID vDdDxApiFreeDirectDraw * * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo] * Wrote it. \**************************************************************************/
VOID vDdDxApiFreeDirectDraw( DXOBJ* pDxObj, BOOL bDoCallBack ) { EDD_DXDIRECTDRAW* peDxDirectDraw; DXOBJ* pDxTmp;
ASSERTGDI(pDxObj->iDxType == DXT_DIRECTDRAW, "Invalid object");
peDxDirectDraw = pDxObj->peDxDirectDraw;
EDD_DEVLOCK eDevLock(peDxDirectDraw->hdev);
if (bDoCallBack) { pDxObj->pfnClose(pDxObj->dwEvent,pDxObj->pContext, 0, 0); }
// Remove this DXOBJ instance from the list hanging off the DXAPI object:
if (peDxDirectDraw->pDxObj_List == pDxObj) { peDxDirectDraw->pDxObj_List = pDxObj->pDxObj_Next; } else { for (pDxTmp = peDxDirectDraw->pDxObj_List; pDxTmp->pDxObj_Next != pDxObj; pDxTmp = pDxTmp->pDxObj_Next) { ASSERTGDI(pDxTmp->iDxType == DXT_DIRECTDRAW, "Unexpected type"); ASSERTGDI(pDxTmp->pDxObj_Next != NULL, "Couldn't find node"); }
pDxTmp->pDxObj_Next = pDxObj->pDxObj_Next; }
// Free the DXOBJ instance:
pDxObj->iDxType = DXT_INVALID; vDdDxObjFree(pDxObj);
// If there are no more DXOBJ instances of the DirectDraw DXAPI object,
// we can free the non-paged DXAPI part of the DirectDraw structure:
if (peDxDirectDraw->pDxObj_List == NULL) { if ((peDxDirectDraw->pDxEvent_PassiveList != NULL) || (peDxDirectDraw->pDxEvent_DispatchList[CLIENT_DISPATCH_LIST] != NULL)) { KdPrint(("vDdDxApiFreeDirectDraw: A kernel-mode DXAPI client didn't unregister all\n")); KdPrint((" its events when it received CLOSE call-backs. This will cause at\n")); KdPrint((" best a memory leak and at worst a crash!\n")); RIP("The DXAPI client must be fixed."); }
if (peDxDirectDraw->peDirectDrawGlobal != NULL) { peDxDirectDraw->peDirectDrawGlobal->peDxDirectDraw = NULL; } vDdDxObjFree(peDxDirectDraw); } }
/******************************Public*Routine******************************\
* VOID vDdDxApiFreeVideoPort * * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo] * Wrote it. \**************************************************************************/
VOID vDdDxApiFreeVideoPort( DXOBJ* pDxObj, BOOL bDoCallBack ) { EDD_DXDIRECTDRAW* peDxDirectDraw; EDD_DXVIDEOPORT* peDxVideoPort; DXOBJ* pDxObjTmp; DXAPI_EVENT* pDxEventTmp;
ASSERTGDI(pDxObj->iDxType == DXT_VIDEOPORT, "Invalid object");
peDxVideoPort = pDxObj->peDxVideoPort; peDxDirectDraw = peDxVideoPort->peDxDirectDraw;
EDD_DEVLOCK eDevLock(peDxDirectDraw->hdev);
if (bDoCallBack) { pDxObj->pfnClose(pDxObj->dwEvent, pDxObj->pContext, 0, 0); }
// Remove this DXOBJ instance from the list hanging off the DXAPI object:
if (peDxVideoPort->pDxObj_List == pDxObj) { peDxVideoPort->pDxObj_List = pDxObj->pDxObj_Next; } else { for (pDxObjTmp = peDxVideoPort->pDxObj_List; pDxObjTmp->pDxObj_Next != pDxObj; pDxObjTmp = pDxObjTmp->pDxObj_Next) { ASSERTGDI(pDxObjTmp->iDxType == DXT_VIDEOPORT, "Unexpected type"); ASSERTGDI(pDxObjTmp->pDxObj_Next != NULL, "Couldn't find node"); }
pDxObjTmp->pDxObj_Next = pDxObj->pDxObj_Next; }
// Free the notification event if one is present
if (peDxVideoPort->pNotifyEvent != NULL) { PKEVENT pTemp = NULL; HANDLE hEvent = peDxVideoPort->pNotifyEventHandle; NTSTATUS Status;
peDxVideoPort->pNotifyEvent = NULL; peDxVideoPort->pNotifyEventHandle = NULL;
// Make sure that the handle hasn't been freed by the OS already
Status = ObReferenceObjectByHandle( hEvent, 0, 0, KernelMode, (PVOID *) &pTemp, NULL ); if ((pTemp != NULL) && (Status != STATUS_INVALID_HANDLE)) { ObDereferenceObject(pTemp); ZwClose (hEvent); }
// Un-page lock memory
peDxVideoPort->pNotifyBuffer = NULL; if (peDxVideoPort->pNotifyMdl != NULL) { MmUnlockPages (peDxVideoPort->pNotifyMdl); IoFreeMdl (peDxVideoPort->pNotifyMdl); peDxVideoPort->pNotifyMdl = NULL; } }
// Free the DXOBJ instance:
pDxObj->iDxType = DXT_INVALID; vDdDxObjFree(pDxObj);
// If there are no more DXOBJ instances of the VideoPort DXAPI object,
// we can free the non-paged DXAPI part of the VideoPort structure:
if (peDxVideoPort->pDxObj_List == NULL) { ASSERTGDI(peDxDirectDraw != NULL, "Unexpected NULL peDxDirectDraw");
for (pDxEventTmp = peDxDirectDraw->pDxEvent_DispatchList[CLIENT_DISPATCH_LIST]; pDxEventTmp != NULL; pDxEventTmp = pDxEventTmp->pDxEvent_Next) { if (pDxEventTmp->peDxVideoPort == peDxVideoPort) { KdPrint(("vDdDxApiFreeVideoPort: A kernel-mode DXAPI client didn't unregister all\n")); KdPrint((" its videoport events when it received CLOSE call-backs. This will\n")); KdPrint((" cause at best a memory leak and at worst a crash!\n")); RIP("The DXAPI client must be fixed."); } }
if (peDxVideoPort->peVideoPort != NULL) { // If we are actually freeing the video port, we need to lose
// any capture objects that are associated with it
while( peDxVideoPort->peDxCapture != NULL ) { vDdLoseDxObjects( peDxDirectDraw->peDirectDrawGlobal, peDxVideoPort->peDxCapture->pDxObj_List, (PVOID) peDxVideoPort->peDxCapture, LO_CAPTURE ); }
peDxVideoPort->peVideoPort->peDxVideoPort = NULL; } vDdDxObjFree(peDxVideoPort); } }
/******************************Public*Routine******************************\
* VOID vDdDxApiFreeCapture * * 10-Apr-1998 -by- Scott MacDonald [smac] * Wrote it. \**************************************************************************/
VOID vDdDxApiFreeCapture( DXOBJ* pDxObj, BOOL bDoCallBack ) { EDD_DXCAPTURE* peDxCapture; EDD_DXVIDEOPORT* peDxVideoPort;
ASSERTGDI(pDxObj->iDxType == DXT_CAPTURE, "Invalid object");
peDxCapture = pDxObj->peDxCapture; peDxVideoPort = peDxCapture->peDxVideoPort;
if (bDoCallBack) { pDxObj->pfnClose(pDxObj->dwEvent, pDxObj->pContext, 0, 0); }
// Free the DXOBJ instance:
pDxObj->iDxType = DXT_INVALID; vDdDxObjFree(pDxObj);
// Unassociate the capture object from the video port. Since this
// must be synchronized with the DPC, we need to call DxApi to do this.
if( peDxVideoPort != NULL ) { EDD_DXDIRECTDRAW* peDxDirectDraw; EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
peDxDirectDraw = peDxVideoPort->peDxDirectDraw; EDD_DEVLOCK eDevLock(peDxDirectDraw->hdev); peDirectDrawGlobal = peDxDirectDraw->peDirectDrawGlobal; peDirectDrawGlobal->pfnUpdateCapture( peDxVideoPort, peDxCapture, TRUE ); }
vDdDxObjFree(peDxCapture); }
/******************************Public*Routine******************************\
* VOID vDdDxApiFreeSurface * * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo] * Wrote it. \**************************************************************************/
VOID vDdDxApiFreeSurface( DXOBJ* pDxObj, BOOL bDoCallBack ) { EDD_DXSURFACE* peDxSurface; EDD_DXDIRECTDRAW* peDxDirectDraw; DXOBJ* pDxTmp;
ASSERTGDI(pDxObj->iDxType == DXT_SURFACE, "Invalid object");
peDxSurface = pDxObj->peDxSurface; peDxDirectDraw = peDxSurface->peDxDirectDraw;
EDD_DEVLOCK eDevLock(peDxDirectDraw->hdev);
if (bDoCallBack) { pDxObj->pfnClose(pDxObj->dwEvent, pDxObj->pContext, 0, 0); }
// Remove this DXOBJ instance from the list hanging off the DXAPI object:
if (peDxSurface->pDxObj_List == pDxObj) { peDxSurface->pDxObj_List = pDxObj->pDxObj_Next; } else { for (pDxTmp = peDxSurface->pDxObj_List; pDxTmp->pDxObj_Next != pDxObj; pDxTmp = pDxTmp->pDxObj_Next) { ASSERTGDI(pDxTmp->iDxType == DXT_SURFACE, "Unexpected type"); ASSERTGDI(pDxTmp->pDxObj_Next != NULL, "Couldn't find node"); }
pDxTmp->pDxObj_Next = pDxObj->pDxObj_Next; }
// Free the DXOBJ instance:
pDxObj->iDxType = DXT_INVALID; vDdDxObjFree(pDxObj);
// If there are no more DXOBJ instances of the Surface DXAPI object,
// we can free the non-paged DXAPI part of the Surface structure:
if (peDxSurface->pDxObj_List == NULL) { if (peDxSurface->peSurface != NULL) { peDxSurface->peSurface->peDxSurface = NULL; } vDdDxObjFree(peDxSurface); } }
/******************************Public*Routine******************************\
* VOID vDdStopVideoPort * * Makes an emergency stop of the videoport. * * 16-Feb-1997 -by- J. Andrew Goossen [andrewgo] * Wrote it. \**************************************************************************/
VOID vDdStopVideoPort( EDD_VIDEOPORT* peVideoPort ) { EDD_DXVIDEOPORT* peDxVideoPort; DD_UPDATEVPORTDATA UpdateVPortData; EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal; BOOL b;
peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal; peDxVideoPort = peVideoPort->peDxVideoPort;
// Stop the videoport itself:
UpdateVPortData.lpDD = peDirectDrawGlobal; UpdateVPortData.lpVideoPort = peVideoPort; UpdateVPortData.lplpDDVBISurface = NULL; UpdateVPortData.lplpDDSurface = NULL; UpdateVPortData.lpVideoInfo = NULL; UpdateVPortData.dwNumAutoflip = 0; UpdateVPortData.dwFlags = DDRAWI_VPORTSTOP;
EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
ASSERTGDI(peDirectDrawGlobal->VideoPortCallBacks.UpdateVideoPort != NULL, "Videoport object shouldn't have been created if UpdateVideoPort NULL");
// Disable video port VSYNC IRQ
if (peDxVideoPort != NULL) { // Shut down software autoflipping (the autoflipping routine peeks
// at these values, so this is sufficient):
peDxVideoPort->bSoftwareAutoflip = FALSE; peDxVideoPort->flFlags &= ~(DD_DXVIDEOPORT_FLAG_AUTOFLIP|DD_DXVIDEOPORT_FLAG_AUTOFLIP_VBI); peDxVideoPort->bSkip = FALSE; peDxVideoPort->dwSetStateField = 0;
if (peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_ON) { peDxVideoPort->flFlags &= ~DD_DXVIDEOPORT_FLAG_ON; peDirectDrawGlobal->pfnEnableIRQ(peDxVideoPort, FALSE ); } }
if (!peDirectDrawGlobal->bSuspended && (peDirectDrawGlobal->VideoPortCallBacks.UpdateVideoPort != NULL)) { peDirectDrawGlobal->VideoPortCallBacks.UpdateVideoPort(&UpdateVPortData); }
// Update the links to reflect the fact that no surface is a
// destination for this videoport anymore:
b = bDdUpdateLinksAndSynchronize(peVideoPort, TRUE, NULL, 0, TRUE, NULL, 0);
ASSERTGDI(b, "vDdStopVideoPort: Shouldn't fail bDdUpdateLinkAndSynchronize"); }
/******************************Public*Routine******************************\
* VOID LoseDxObjects * * Notifies all clients using the resource that it can't be used anymore. * It also notifies DXAPI.SYS that the resource is unusable. * * 04-Nov-1997 -by- smac * Wrote it. \**************************************************************************/
VOID vDdLoseDxObjects( EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal, DXOBJ* pDxObj, PVOID pDxThing, DWORD dwType ) { if( pDxObj != NULL ) { while( pDxObj != NULL ) { pDxObj->pfnClose(pDxObj->dwEvent, pDxObj->pContext, 0, 0); pDxObj = pDxObj->pDxObj_Next; }
peDirectDrawGlobal->pfnLoseObject( pDxThing, (LOTYPE) dwType ); } }
/******************************Public*Routine******************************\
* BOOL bDdDeleteVideoPortObject * * Deletes a kernel-mode representation of the videoport object. * * 16-Feb-1997 -by- J. Andrew Goossen [andrewgo] * Wrote it. \**************************************************************************/
BOOL bDdDeleteVideoPortObject( HANDLE hVideoPort, DWORD* pdwRet // For returning driver return code, may be NULL
) { BOOL bRet; DWORD dwRet; EDD_DXVIDEOPORT* peDxVideoPort; EDD_VIDEOPORT* peVideoPort; EDD_VIDEOPORT* peTmp; VOID* pvRemove; EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal; EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal; DD_DESTROYVPORTDATA DestroyVPortData; DXOBJ* pDxObj; DXOBJ* pDxObjNext;
bRet = FALSE; dwRet = DDHAL_DRIVER_HANDLED;
peVideoPort = (EDD_VIDEOPORT*) DdHmgLock((HDD_OBJ) hVideoPort, DD_VIDEOPORT_TYPE, FALSE);
if (peVideoPort != NULL) { peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
// Make sure the videoport has been turned off:
vDdStopVideoPort(peVideoPort);
// If there are any capture objects associated witht he video port,
// lose them now
peDxVideoPort = peVideoPort->peDxVideoPort; while( peDxVideoPort && (peDxVideoPort->peDxCapture != NULL) ) { vDdLoseDxObjects( peDirectDrawGlobal, peDxVideoPort->peDxCapture->pDxObj_List, (PVOID) peDxVideoPort->peDxCapture, LO_CAPTURE ); }
// Free the DXAPI instance of the videoport object
if (peVideoPort->hVideoPort != NULL) { vDdDxApiFreeVideoPort( (DXOBJ*) peVideoPort->hVideoPort, FALSE); peVideoPort->hVideoPort = NULL; peDxVideoPort = peVideoPort->peDxVideoPort; }
// Notify clients that their open objects are lost
if (peDxVideoPort) { vDdLoseDxObjects( peDirectDrawGlobal, peDxVideoPort->pDxObj_List, (PVOID) peDxVideoPort, LO_VIDEOPORT ); }
pvRemove = DdHmgRemoveObject((HDD_OBJ) hVideoPort, DdHmgQueryLock((HDD_OBJ) hVideoPort), 0, TRUE, DD_VIDEOPORT_TYPE);
ASSERTGDI(pvRemove != NULL, "Outstanding surfaces locks");
// Hold the devlock while we call the driver and while we muck
// around in the videoport list:
EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
if (peVideoPort->fl & DD_VIDEOPORT_FLAG_DRIVER_CREATED) { // Call the driver if it created the object:
if (peDirectDrawGlobal->VideoPortCallBacks.DestroyVideoPort) { DestroyVPortData.lpDD = peDirectDrawGlobal; DestroyVPortData.lpVideoPort = peVideoPort; DestroyVPortData.ddRVal = DDERR_GENERIC;
dwRet = peDirectDrawGlobal-> VideoPortCallBacks.DestroyVideoPort(&DestroyVPortData); } }
// Remove from the videoport linked-list:
peDirectDrawLocal = peVideoPort->peDirectDrawLocal;
if (peDirectDrawLocal->peVideoPort_DdList == peVideoPort) { peDirectDrawLocal->peVideoPort_DdList = peVideoPort->peVideoPort_DdNext; } else { for (peTmp = peDirectDrawLocal->peVideoPort_DdList; peTmp->peVideoPort_DdNext != peVideoPort; peTmp = peTmp->peVideoPort_DdNext) ;
peTmp->peVideoPort_DdNext = peVideoPort->peVideoPort_DdNext; }
// Unload DXAPI.SYS if no other video port is using it
if (peDirectDrawLocal->peVideoPort_DdList == NULL) { vDdUnloadDxApi( peDirectDrawGlobal ); }
// We're all done with this object, so free the memory and
// leave:
DdFreeObject(peVideoPort, DD_VIDEOPORT_TYPE);
bRet = TRUE; } else { WARNING1("bDdDeleteVideoPortObject: Bad handle or object was busy\n"); }
if (pdwRet != NULL) { *pdwRet = dwRet; }
return(bRet); }
/******************************Public*Routine******************************\
* DWORD DdDxApiOpenDirectDraw * * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo] * Wrote it. \**************************************************************************/
VOID APIENTRY DdDxApiOpenDirectDraw( DDOPENDIRECTDRAWIN* pOpenDirectDrawIn, DDOPENDIRECTDRAWOUT* pOpenDirectDrawOut, PKDEFERRED_ROUTINE pfnEventDpc, ULONG DxApiPrivateVersionNumber ) { HANDLE hDirectDraw; EDD_LOCK_DIRECTDRAW eLockDirectDraw; EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal; EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal; DXOBJ* pDxObj; EDD_DXDIRECTDRAW* peDxDirectDraw;
ASSERTGDI(KeGetCurrentIrql() == PASSIVE_LEVEL, "DdDxApiOpenDirectDraw: Callable only at passive level (it's not pageable)");
hDirectDraw = 0; // Assume failure
// We use the private version number to ensure consistency between
// win32k.sys and dxapi.sys. Since dxapi.sys is dynamically loaded,
// I am worried about a scenario where a service pack is applied that
// updates both dxapi.sys and win32k.sys -- if the machine isn't
// rebooted, the old win32k.sys will remain loaded but the new dxapi.sys
// may be loaded, possibly causing a crash.
peDirectDrawLocal = eLockDirectDraw.peLock((HANDLE) pOpenDirectDrawIn->dwDirectDrawHandle); if ((peDirectDrawLocal != NULL) || (DxApiPrivateVersionNumber != DXAPI_PRIVATE_VERSION_NUMBER)) { peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal; pDxObj = pDdDxObjHandleAllocate(DXT_DIRECTDRAW, pOpenDirectDrawIn->pfnDirectDrawClose, DDNOTIFY_CLOSEDIRECTDRAW, pOpenDirectDrawIn->pContext); if (pDxObj != NULL) { // Among other things, enforce synchronization while we muck
// around in the global DirectDraw object:
EDD_DEVLOCK eDevLock(peDirectDrawGlobal);
peDxDirectDraw = peDirectDrawGlobal->peDxDirectDraw; if (peDxDirectDraw != NULL) { // Just add this object to the list hanging off the DirectDraw
// object:
pDxObj->peDxDirectDraw = peDxDirectDraw; pDxObj->pDxObj_Next = peDxDirectDraw->pDxObj_List; peDxDirectDraw->pDxObj_List = pDxObj;
// Success!
hDirectDraw = (HANDLE) pDxObj; } else { peDxDirectDraw = (EDD_DXDIRECTDRAW*) pDdDxObjDataAllocate( sizeof(*peDxDirectDraw), 'dxdG'); if (peDxDirectDraw) { RtlZeroMemory(peDxDirectDraw, sizeof(*peDxDirectDraw));
pDxObj->peDxDirectDraw = peDxDirectDraw;
// We need to access some capabilities at raised IRQL,
// so copy those from the paged 'peDirectDrawGlobal'
// to the non-paged 'peDxDirectDraw' now:
peDxDirectDraw->DxApiInterface = peDirectDrawGlobal->DxApiInterface; peDxDirectDraw->HwDeviceExtension = peDirectDrawGlobal->HwDeviceExtension; peDxDirectDraw->dwIRQCaps = peDirectDrawGlobal->DDKernelCaps.dwIRQCaps; peDxDirectDraw->peDirectDrawGlobal = peDirectDrawGlobal; peDxDirectDraw->hdev = peDirectDrawGlobal->hdev;
peDirectDrawGlobal->peDxDirectDraw = peDxDirectDraw;
peDxDirectDraw->pDxObj_List = pDxObj;
// Initialize our kernel structures use for interrupts
// and handling raised IRQL callers.
KeInitializeDpc(&peDxDirectDraw->EventDpc, pfnEventDpc, peDxDirectDraw);
KeInitializeSpinLock(&peDxDirectDraw->SpinLock);
// Success!
hDirectDraw = (HANDLE) pDxObj; } }
if (!hDirectDraw) { vDdDxObjFree(pDxObj); } } } else { WARNING("DdDxApiOpenDirectDraw: Invalid dwDirectDrawHandle, failing\n"); }
pOpenDirectDrawOut->hDirectDraw = hDirectDraw; pOpenDirectDrawOut->ddRVal = (hDirectDraw != NULL) ? DD_OK : DDERR_GENERIC; }
/******************************Public*Routine******************************\
* DWORD DdDxApiOpenVideoPort * * This routine lets a driver use fields from the larger, pageable version * of the DD_SURFACE_* structures used by the display driver to set * fields in the smaller, non-pageable version of the corresponding * DDSURFACEDATA structure used by the miniport. * * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo] * Wrote it. \**************************************************************************/
VOID APIENTRY DdDxApiOpenVideoPort( DDOPENVIDEOPORTIN* pOpenVideoPortIn, DDOPENVIDEOPORTOUT* pOpenVideoPortOut ) { HANDLE hVideoPort; DXOBJ* pDxObjDirectDraw; DXOBJ* pDxObj; EDD_DXDIRECTDRAW* peDxDirectDraw; EDD_DXVIDEOPORT* peDxVideoPort; EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal; EDD_LOCK_VIDEOPORT eLockVideoPort; EDD_VIDEOPORT* peVideoPort; BOOL bFound; EDD_DIRECTDRAW_LOCAL* peTempDirectDrawLocal; EDD_VIDEOPORT* peTempVideoPort;
ASSERTGDI(KeGetCurrentIrql() == PASSIVE_LEVEL, "DdDxApiOpenVideoPort: Callable only at passive level (it's not pageable)");
hVideoPort = 0; // Assume failure
pDxObjDirectDraw = (DXOBJ*) pOpenVideoPortIn->hDirectDraw;
ASSERTGDI((pDxObjDirectDraw != NULL) && (pDxObjDirectDraw->iDxType == DXT_DIRECTDRAW), "DdDxApiOpenVideoPort: Invalid hDirectDraw, we're about to crash");
peDxDirectDraw = pDxObjDirectDraw->peDxDirectDraw;
// Among other things, enforce synchronization while we muck around
// in the DirectDraw object:
EDD_DEVLOCK eDevLock(peDxDirectDraw->hdev);
if (!peDxDirectDraw->bLost) { peDirectDrawGlobal = peDxDirectDraw->peDirectDrawGlobal;
// We need to get a handle to the video port, so we need to
// go looking for it.
bFound = FALSE; peTempDirectDrawLocal = peDirectDrawGlobal->peDirectDrawLocalList; while( ( peTempDirectDrawLocal != NULL ) && !bFound ) { peTempVideoPort = peTempDirectDrawLocal->peVideoPort_DdList; while( peTempVideoPort != NULL ) { if( peTempVideoPort->ddvpDesc.dwVideoPortID == pOpenVideoPortIn->dwVideoPortHandle ) { bFound = TRUE; break; } peTempVideoPort = peTempVideoPort->peVideoPort_DdNext; } peTempDirectDrawLocal = peTempDirectDrawLocal->peDirectDrawLocalNext; } if( bFound ) { peVideoPort = eLockVideoPort.peLock( (HANDLE) peTempVideoPort->hGet()); if ((peVideoPort != NULL) && (peVideoPort->peDirectDrawGlobal == peDirectDrawGlobal)) { pDxObj = pDdDxObjHandleAllocate(DXT_VIDEOPORT, pOpenVideoPortIn->pfnVideoPortClose, DDNOTIFY_CLOSEVIDEOPORT, pOpenVideoPortIn->pContext); if (pDxObj != NULL) {
peDxVideoPort = peVideoPort->peDxVideoPort; if (peDxVideoPort != NULL) { // Just add this object to the list hanging off the
// surface object:
pDxObj->peDxVideoPort = peDxVideoPort; pDxObj->pDxObj_Next = peDxVideoPort->pDxObj_List; peDxVideoPort->pDxObj_List = pDxObj;
// Success!
hVideoPort = (HANDLE) pDxObj; } else { peDxVideoPort = (EDD_DXVIDEOPORT*) pDdDxObjDataAllocate( sizeof(*peDxVideoPort), 'sxdG'); if (peDxVideoPort) { RtlZeroMemory(peDxVideoPort, sizeof(*peDxVideoPort));
pDxObj->peDxVideoPort = peDxVideoPort;
peVideoPort->peDxVideoPort = peDxVideoPort;
peDxVideoPort->pDxObj_List = pDxObj; peDxVideoPort->peVideoPort = peVideoPort; peDxVideoPort->peDxDirectDraw = peDxDirectDraw;
peDxVideoPort->iCurrentVideo = 1; peDxVideoPort->dwVideoPortID = peVideoPort->ddvpDesc.dwVideoPortID;
vDdSynchronizeVideoPort(peVideoPort);
// Success!
hVideoPort = (HANDLE) pDxObj; } }
if (!hVideoPort) { vDdDxObjFree(pDxObj); } } } else { WARNING("DdDxApiOpenVideoPort: Invalid dwSurfaceHandle, failing.\n"); } } else { WARNING("DdDxApiOpenVideoPort: Invalid dwSurfaceHandle, failing.\n"); } } else { WARNING("DdDxApiOpenVideoPort: DirectDraw object is lost"); }
pOpenVideoPortOut->hVideoPort = hVideoPort; pOpenVideoPortOut->ddRVal = (hVideoPort != NULL) ? DD_OK : DDERR_GENERIC; }
/******************************Public*Routine******************************\
* DWORD DdDxApiOpenSurface * * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo] * Wrote it. \**************************************************************************/
VOID APIENTRY DdDxApiOpenSurface( DDOPENSURFACEIN* pOpenSurfaceIn, DDOPENSURFACEOUT* pOpenSurfaceOut ) { HANDLE hSurface; DXOBJ* pDxObjDirectDraw; DXOBJ* pDxObj; EDD_DXDIRECTDRAW* peDxDirectDraw; EDD_DXSURFACE* peDxSurface; EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal; EDD_LOCK_SURFACE eLockSurface; EDD_SURFACE* peSurface;
ASSERTGDI(KeGetCurrentIrql() == PASSIVE_LEVEL, "DdDxApiOpenSurface: Callable only at passive level (it's not pageable)");
hSurface = 0; // Assume failure
pDxObjDirectDraw = (DXOBJ*) pOpenSurfaceIn->hDirectDraw;
ASSERTGDI((pDxObjDirectDraw != NULL) && (pDxObjDirectDraw->iDxType == DXT_DIRECTDRAW), "DdDxApiOpenSurface: Invalid hDirectDraw, we're about to crash");
peDxDirectDraw = pDxObjDirectDraw->peDxDirectDraw;
// Among other things, enforce synchronization while we muck around
// in the DirectDraw object:
EDD_DEVLOCK eDevLock(peDxDirectDraw->hdev);
if (!peDxDirectDraw->bLost) { peDirectDrawGlobal = peDxDirectDraw->peDirectDrawGlobal;
peSurface = eLockSurface.peLock((HANDLE) pOpenSurfaceIn->dwSurfaceHandle); if ((peSurface != NULL) && (peSurface->peDirectDrawGlobal == peDirectDrawGlobal)) { pDxObj = pDdDxObjHandleAllocate(DXT_SURFACE, pOpenSurfaceIn->pfnSurfaceClose, DDNOTIFY_CLOSESURFACE, pOpenSurfaceIn->pContext); if (pDxObj != NULL) { peDxSurface = peSurface->peDxSurface; if (peDxSurface != NULL) { // Just add this object to the list hanging off the
// surface object:
pDxObj->peDxSurface = peDxSurface; pDxObj->pDxObj_Next = peDxSurface->pDxObj_List; peDxSurface->pDxObj_List = pDxObj;
// Success!
hSurface = (HANDLE) pDxObj; } else { peDxSurface = (EDD_DXSURFACE*) pDdDxObjDataAllocate( sizeof(*peDxSurface), 'sxdG'); if (peDxSurface) { RtlZeroMemory(peDxSurface, sizeof(*peDxSurface));
pDxObj->peDxSurface = peDxSurface;
peSurface->peDxSurface = peDxSurface;
peDxSurface->pDxObj_List = pDxObj; peDxSurface->peSurface = peSurface; peDxSurface->peDxDirectDraw = peDxDirectDraw; if( peDirectDrawGlobal->HalInfo.ddCaps.dwCaps2 & DDCAPS2_CANBOBINTERLEAVED ) { peDxSurface->flFlags |= DD_DXSURFACE_FLAG_CAN_BOB_INTERLEAVED; } if( peDirectDrawGlobal->HalInfo.ddCaps.dwCaps2 & DDCAPS2_CANBOBNONINTERLEAVED ) { peDxSurface->flFlags |= DD_DXSURFACE_FLAG_CAN_BOB_NONINTERLEAVED; }
// Success!
hSurface = (HANDLE) pDxObj; } }
vDdSynchronizeSurface(peSurface);
if (!hSurface) { vDdDxObjFree(pDxObj); } } } else { WARNING("DdDxApiOpenSurface: Invalid dwSurfaceHandle, failing.\n"); } } else { WARNING("DdDxApiOpenSurface: DirectDraw object lost\n"); }
pOpenSurfaceOut->hSurface = hSurface; pOpenSurfaceOut->ddRVal = (hSurface != NULL) ? DD_OK : DDERR_GENERIC; }
/******************************Public*Routine******************************\
* DWORD DdDxApiCloseHandle * * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo] * Wrote it. \**************************************************************************/
VOID APIENTRY DdDxApiCloseHandle( DDCLOSEHANDLE* pCloseHandle, DWORD* pdwRet ) { DXOBJ* pDxObj = (DXOBJ*) pCloseHandle->hHandle;
ASSERTGDI(KeGetCurrentIrql() == PASSIVE_LEVEL, "DdDxApiCloseHandle: Callable only at passive level (it's not pageable)"); ASSERTGDI(pCloseHandle->hHandle != NULL, "DdDxApiCloseHandle: Trying to close NULL handle");
switch(pDxObj->iDxType) { case DXT_DIRECTDRAW: vDdDxApiFreeDirectDraw(pDxObj, TRUE); break;
case DXT_VIDEOPORT: vDdDxApiFreeVideoPort(pDxObj, FALSE); break;
case DXT_SURFACE: vDdDxApiFreeSurface(pDxObj, FALSE); break;
case DXT_CAPTURE: vDdDxApiFreeCapture(pDxObj, FALSE); break;
case DXT_INVALID: RIP("DdDxApiCloseHandle: Invalid surface. Same handle probably closed twice"); break;
default: RIP("DdDxApiCloseHandle: Invalid surface."); break; }
*pdwRet = DD_OK; }
/******************************Public*Routine******************************\
* DWORD DdDxApiOpenCaptureDevice * * 01-Nov-1997 -by- smac * Wrote it. \**************************************************************************/
VOID APIENTRY DdDxApiOpenCaptureDevice( DDOPENVPCAPTUREDEVICEIN* pOpenCaptureDeviceIn, DDOPENVPCAPTUREDEVICEOUT* pOpenCaptureDeviceOut ) { HANDLE hCaptureDevice; DXOBJ* pDxObjDirectDraw; DXOBJ* pDxObjVideoPort; DXOBJ* pDxObj; EDD_DXDIRECTDRAW* peDxDirectDraw; EDD_DXVIDEOPORT* peDxVideoPort; EDD_DXCAPTURE* peDxCapture; EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal; DWORD dwRet;
ASSERTGDI(KeGetCurrentIrql() == PASSIVE_LEVEL, "DdDxApiOpenVideoPort: Callable only at passive level (it's not pageable)");
hCaptureDevice = 0; // Assume failure
pDxObjDirectDraw = (DXOBJ*) pOpenCaptureDeviceIn->hDirectDraw; pDxObjVideoPort = (DXOBJ*) pOpenCaptureDeviceIn->hVideoPort;
ASSERTGDI((pDxObjDirectDraw != NULL) && (pDxObjDirectDraw->iDxType == DXT_DIRECTDRAW), "DdDxApiOpenCaptureDevice: Invalid hDirectDraw, we're about to crash"); ASSERTGDI((pDxObjVideoPort != NULL) && (pDxObjVideoPort->iDxType == DXT_VIDEOPORT), "DdDxApiOpenCaptureDevice: Invalid hVideoPort, we're about to crash");
peDxDirectDraw = pDxObjDirectDraw->peDxDirectDraw; peDxVideoPort = pDxObjVideoPort->peDxVideoPort;
ASSERTGDI((pOpenCaptureDeviceIn->dwFlags == DDOPENCAPTURE_VIDEO) || (pOpenCaptureDeviceIn->dwFlags == DDOPENCAPTURE_VBI), "DdDxApiOpenCaptureDevice: Invalid flags specified"); ASSERTGDI((pOpenCaptureDeviceIn->dwCaptureEveryNFields != 0), "DdDxApiOpenCaptureDevice: Invalid dwCaptureEveryNFields specified"); ASSERTGDI((pOpenCaptureDeviceIn->pfnCaptureClose != 0), "DdDxApiOpenCaptureDevice: Invalid pfnCaptureClose specified");
// Among other things, enforce synchronization while we muck around
// in the DirectDraw object:
EDD_DEVLOCK eDevLock(peDxDirectDraw->hdev);
dwRet = DDERR_INVALIDPARAMS; if ((!peDxDirectDraw->bLost) && (!peDxVideoPort->bLost)) { // Only do this if the device actually supports capturing
dwRet = DDERR_CURRENTLYNOTAVAIL; peDirectDrawGlobal = peDxDirectDraw->peDirectDrawGlobal; if ((peDirectDrawGlobal->DDKernelCaps.dwCaps & (DDKERNELCAPS_CAPTURE_SYSMEM|DDKERNELCAPS_CAPTURE_NONLOCALVIDMEM)) && (peDxDirectDraw->DxApiInterface.DxTransfer != NULL)) { #if 0 // fix bug 169385
// See capturing target is matched.
if (((pOpenCaptureDeviceIn->dwFlags & DDOPENCAPTURE_VBI) && (peDxVideoPort->cAutoflipVbi > 0)) || ((pOpenCaptureDeviceIn->dwFlags & DDOPENCAPTURE_VIDEO) && (peDxVideoPort->cAutoflipVideo > 0))) { #endif
// Allocate the object. We only allow one handle per object.
dwRet = DDERR_OUTOFMEMORY; pDxObj = pDdDxObjHandleAllocate(DXT_CAPTURE, pOpenCaptureDeviceIn->pfnCaptureClose, DDNOTIFY_CLOSECAPTURE, pOpenCaptureDeviceIn->pContext); if (pDxObj != NULL) { peDxCapture = (EDD_DXCAPTURE*) pDdDxObjDataAllocate( sizeof(*peDxCapture), 'sxdG'); if (peDxCapture) { RtlZeroMemory(peDxCapture, sizeof(*peDxCapture)); pDxObj->peDxCapture = peDxCapture;
peDxCapture->pDxObj_List = pDxObj; peDxCapture->peDxVideoPort = peDxVideoPort; peDxCapture->dwStartLine = pOpenCaptureDeviceIn->dwStartLine; peDxCapture->dwEndLine = pOpenCaptureDeviceIn->dwEndLine; peDxCapture->dwCaptureCountDown = 1; peDxCapture->dwCaptureEveryNFields = pOpenCaptureDeviceIn->dwCaptureEveryNFields; if (pOpenCaptureDeviceIn->dwFlags & DDOPENCAPTURE_VBI ) { peDxCapture->flFlags = DD_DXCAPTURE_FLAG_VBI; } else { peDxCapture->flFlags = DD_DXCAPTURE_FLAG_VIDEO; }
// Now we need to put the capture object into the list
// of active capture objects, but since this list is
// walked at DPC time, we need to call DxApi to do this.
peDirectDrawGlobal->pfnUpdateCapture( peDxVideoPort, peDxCapture, FALSE );
// Success!
hCaptureDevice = (HANDLE) pDxObj; dwRet = DD_OK; }
if (!hCaptureDevice) { vDdDxObjFree(pDxObj); } } #if 0 // fix bug 169385
} else { WARNING("DdDxApiOpenCaptureDevice: VideoPort doesn't have surface requested by driver.\n"); } #endif
} else { WARNING("DdDxApiOpenCaptureDevice: Device does not support capture, failing.\n"); } } else { WARNING("DdDxApiOpenCaptureDevice: DirectDraw or VideoPort object is not valid, failing.\n"); }
pOpenCaptureDeviceOut->hCapture = hCaptureDevice; pOpenCaptureDeviceOut->ddRVal = dwRet; }
/******************************Public*Routine******************************\
* DWORD DdDxApiGetKernelCaps * * 01-Nov-1997 -by- smac * Wrote it. \**************************************************************************/
VOID APIENTRY DdDxApiGetKernelCaps( HANDLE hDirectDraw, DDGETKERNELCAPSOUT* pGetKernelCaps ) { DXOBJ* pDxObjDirectDraw; EDD_DXDIRECTDRAW* peDxDirectDraw; EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
ASSERTGDI(KeGetCurrentIrql() == PASSIVE_LEVEL, "DdDxApiGetKernelCaps: Callable only at passive level (it's not pageable)");
pDxObjDirectDraw = (DXOBJ*) hDirectDraw;
ASSERTGDI((pDxObjDirectDraw != NULL) && (pDxObjDirectDraw->iDxType == DXT_DIRECTDRAW), "DdDxApiGetKernelCaps: Invalid hDirectDraw, we're about to crash");
peDxDirectDraw = pDxObjDirectDraw->peDxDirectDraw;
// Among other things, enforce synchronization while we muck around
// in the DirectDraw object:
EDD_DEVLOCK eDevLock(peDxDirectDraw->hdev);
if (!peDxDirectDraw->bLost) { peDirectDrawGlobal = peDxDirectDraw->peDirectDrawGlobal;
pGetKernelCaps->ddRVal = DD_OK; pGetKernelCaps->dwCaps = peDirectDrawGlobal->DDKernelCaps.dwCaps; pGetKernelCaps->dwIRQCaps = peDirectDrawGlobal->DDKernelCaps.dwIRQCaps; } else { pGetKernelCaps->ddRVal = DXERR_OUTOFCAPS; pGetKernelCaps->dwCaps = 0; pGetKernelCaps->dwIRQCaps = 0; } }
/******************************Public*Routine******************************\
* VOID DdDxApiLockDevice * * 05-Jun-1998 -by- agodfrey \**************************************************************************/
VOID APIENTRY DdDxApiLockDevice( HDEV hdev ) { DxEngLockHdev(hdev); }
/******************************Public*Routine******************************\
* VOID DdDxApiUnlockDevice * * 05-Jun-1998 -by- agodfrey \**************************************************************************/
VOID APIENTRY DdDxApiUnlockDevice( HDEV hdev ) { DxEngUnlockHdev(hdev); }
/******************************Public*Routine******************************\
* DWORD DxDvpCanCreateVideoPort * * Queries the driver to determine whether it can support a DirectDraw * videoPort. * * 3-Oct-1996 -by- Lingyun Wang [lingyunw] * Wrote it. \**************************************************************************/
DWORD APIENTRY DxDvpCanCreateVideoPort( HANDLE hDirectDraw, PDD_CANCREATEVPORTDATA puCanCreateVPortData ) { DWORD dwRet; DD_CANCREATEVPORTDATA CanCreateVideoPort; DDVIDEOPORTDESC VideoPortDescription;
__try { CanCreateVideoPort = ProbeAndReadStructure(puCanCreateVPortData, DD_CANCREATEVPORTDATA);
VideoPortDescription = ProbeAndReadStructure(CanCreateVideoPort.lpDDVideoPortDesc, DDVIDEOPORTDESC); } __except(EXCEPTION_EXECUTE_HANDLER) { return(DDHAL_DRIVER_NOTHANDLED); }
dwRet = DDHAL_DRIVER_NOTHANDLED; CanCreateVideoPort.ddRVal = DDERR_GENERIC;
EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal; EDD_LOCK_DIRECTDRAW eLockDirectDraw; EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
peDirectDrawLocal = eLockDirectDraw.peLock(hDirectDraw);
// For now, do now enable VPE on Terminal Server due to problems
// loading DXAPI.SYS into session space vs. non-session space
{ if (peDirectDrawLocal != NULL) { peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
CanCreateVideoPort.lpDD = peDirectDrawGlobal; CanCreateVideoPort.lpDDVideoPortDesc = &VideoPortDescription;
EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
if ((!peDirectDrawGlobal->bSuspended) && (peDirectDrawGlobal->VideoPortCallBacks.CanCreateVideoPort)) { dwRet = peDirectDrawGlobal-> VideoPortCallBacks.CanCreateVideoPort(&CanCreateVideoPort); } } else { WARNING("DxDvpCanCreateSurface: Invalid object\n"); } }
// We have to wrap this in another try-except because the user-mode
// memory containing the input may have been deallocated by now:
__try { ProbeAndWriteRVal(&puCanCreateVPortData->ddRVal, CanCreateVideoPort.ddRVal); } __except(EXCEPTION_EXECUTE_HANDLER) { } return(dwRet); }
/*****************************Private*Routine******************************\
* HANDLE DxDvpCreateVideoPort * * Notifies the HAL after a video port is created. * * This is an optional call for the driver, but we always have to 'hook' * this call from user-mode DirectDraw. * * Question: A user-mode application could have absolute garbage in * lpDDVideoPortDesc and get it by the driver, because the * driver would only be monitoring for invalid data in its * CanCreateVideoPort call. So should we call the driver's * CanCreateVideoPort here in this routine before calling * CreateVideoPort? * * History: * 2-Oct-1996 -by- Lingyun Wang [lingyunw] * Wrote it. \**************************************************************************/
HANDLE APIENTRY DxDvpCreateVideoPort( HANDLE hDirectDraw, PDD_CREATEVPORTDATA puCreateVPortData ) { HANDLE hRet; DWORD dwRet; DD_CREATEVPORTDATA CreateVPortData; DDVIDEOPORTDESC VideoPortDescription; BOOL bFirst;
__try { CreateVPortData = ProbeAndReadStructure(puCreateVPortData, DD_CREATEVPORTDATA);
VideoPortDescription = ProbeAndReadStructure(CreateVPortData.lpDDVideoPortDesc, DDVIDEOPORTDESC); } __except(EXCEPTION_EXECUTE_HANDLER) { return(DDHAL_DRIVER_NOTHANDLED); }
hRet = 0; CreateVPortData.ddRVal = DDERR_GENERIC;
EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal; EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal; EDD_LOCK_DIRECTDRAW eLockDirectDraw; EDD_VIDEOPORT* peVideoPort;
// The two items below where triple bang comments are are somewhat cryptic.
//
// 1. Ensure that not more than one VideoPort created
// 2. Scott allows CanCreateVideoPort and CreateVideoPort to be optional
peDirectDrawLocal = eLockDirectDraw.peLock(hDirectDraw);
// For now, enable VPE on Terminal Server due to conflicts loading in
// session space vs. non-session sapce.
{ if (peDirectDrawLocal != NULL) { peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
// Here we do the minimal validations checks to ensure that bad
// parameters won't crash NT. We're not more strict than
// checking for stuff that will crash us, as the user-mode part
// of DirectDraw handles that.
if (VideoPortDescription.dwVideoPortID < peDirectDrawGlobal->HalInfo.ddCaps.dwMaxVideoPorts) {
// Check for the case where a video port has been created for
// VBI or video and we are now creating the other one, in which
// case we use the existing video port.
peVideoPort = peDirectDrawLocal->peVideoPort_DdList; while ((peVideoPort != NULL) && (peVideoPort->ddvpDesc.dwVideoPortID != VideoPortDescription.dwVideoPortID)) { peVideoPort = peVideoPort->peVideoPort_DdNext; } if (peVideoPort != NULL) { peVideoPort->ddvpDesc = VideoPortDescription; CreateVPortData.ddRVal = DD_OK; hRet = peVideoPort->hGet(); } else { peVideoPort = (EDD_VIDEOPORT*) DdHmgAlloc(sizeof(EDD_VIDEOPORT), DD_VIDEOPORT_TYPE, HMGR_ALLOC_LOCK); if (peVideoPort) { // Private data:
peVideoPort->peDirectDrawGlobal = peDirectDrawGlobal; peVideoPort->peDirectDrawLocal = peDirectDrawLocal;
// Public data:
peVideoPort->lpDD = peDirectDrawGlobal; peVideoPort->ddvpDesc = VideoPortDescription;
// Hold devlock for driver call and for bDdEnableSoftware
// Autoflipping.
EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
// Add this videoport to the list hanging off the
// DirectDrawLocal object allocated for this process:
bFirst = peDirectDrawLocal->peVideoPort_DdList == NULL; peVideoPort->peVideoPort_DdNext = peDirectDrawLocal->peVideoPort_DdList; peDirectDrawLocal->peVideoPort_DdList = peVideoPort;
// Now call the driver to create its version:
CreateVPortData.lpDD = peDirectDrawGlobal; CreateVPortData.lpDDVideoPortDesc = &VideoPortDescription; CreateVPortData.lpVideoPort = peVideoPort; CreateVPortData.ddRVal = DDERR_GENERIC;
dwRet = DDHAL_DRIVER_NOTHANDLED; // Call is optional
if ((!peDirectDrawGlobal->bSuspended) && (peDirectDrawGlobal->VideoPortCallBacks.CreateVideoPort)) { dwRet = peDirectDrawGlobal-> VideoPortCallBacks.CreateVideoPort(&CreateVPortData); }
if ((dwRet == DDHAL_DRIVER_NOTHANDLED) || (CreateVPortData.ddRVal == DD_OK)) { CreateVPortData.ddRVal = DD_OK; peVideoPort->fl |= DD_VIDEOPORT_FLAG_DRIVER_CREATED; } else { WARNING("DxDvpCreateVideoPort: Driver failed call\n"); }
if ((CreateVPortData.ddRVal == DD_OK) && (bDdEnableSoftwareAutoflipping(peDirectDrawLocal, peVideoPort, VideoPortDescription.dwVideoPortID, bFirst))) { // Success!
hRet = peVideoPort->hGet();
DEC_EXCLUSIVE_REF_CNT( peVideoPort ); } else { bDdDeleteVideoPortObject(peVideoPort->hGet(), NULL);
CreateVPortData.ddRVal = DDERR_GENERIC; } } } } else { WARNING("DxDvpCreateVideoPort: Bad parameters\n"); } } else { WARNING("DxDvpCreateVideoPort: Invalid object\n"); } }
// We have to wrap this in another try-except because the user-mode
// memory containing the input may have been deallocated by now:
__try { ProbeAndWriteRVal(&puCreateVPortData->ddRVal, CreateVPortData.ddRVal); } __except(EXCEPTION_EXECUTE_HANDLER) { }
// Note that the user-mode stub always returns DDHAL_DRIVER_HANDLED
// to DirectDraw.
return(hRet); }
/*****************************Private*Routine******************************\
* DWORD DxDvpDestroyVideoPort * * Notifies the HAL when the video port is destroyed. * * History: * 2-Oct-1996 -by- Lingyun Wang [lingyunw] * Wrote it. \**************************************************************************/
DWORD APIENTRY DxDvpDestroyVideoPort( HANDLE hVideoPort, PDD_DESTROYVPORTDATA puDestroyVPortData ) { DWORD dwRet;
bDdDeleteVideoPortObject(hVideoPort, &dwRet);
__try { ProbeAndWriteRVal(&puDestroyVPortData->ddRVal, DD_OK); } __except(EXCEPTION_EXECUTE_HANDLER) { }
return(dwRet); }
/*****************************Private*Routine******************************\
* DWORD DxDvpFlipVideoPort * * Performs the physical flip, causing the video port to start writing data * to the new surface. This does not affect the actual display of this data. * * History: * 2-Oct-1996 -by- Lingyun Wang [lingyunw] * Wrote it. \**************************************************************************/
DWORD APIENTRY DxDvpFlipVideoPort( HANDLE hVideoPort, HANDLE hDDSurfaceCurrent, HANDLE hDDSurfaceTarget, PDD_FLIPVPORTDATA puFlipVPortData ) { DWORD dwRet; DD_FLIPVPORTDATA FlipVPortData;
dwRet = DDHAL_DRIVER_NOTHANDLED; FlipVPortData.ddRVal = DDERR_GENERIC;
EDD_VIDEOPORT* peVideoPort; EDD_LOCK_VIDEOPORT eLockVideoPort; EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
// 1. Make sure they're videoport surfaces, and compatible, not system surfaces?
// 2. Make sure not software autoflipping?
peVideoPort = eLockVideoPort.peLock(hVideoPort); if (peVideoPort != NULL) { peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal; if (peDirectDrawGlobal->VideoPortCallBacks.FlipVideoPort) { EDD_SURFACE* peSurfaceCurrent; EDD_SURFACE* peSurfaceTarget; EDD_LOCK_SURFACE eLockSurfaceCurrent; EDD_LOCK_SURFACE eLockSurfaceTarget;
peSurfaceCurrent = eLockSurfaceCurrent.peLock(hDDSurfaceCurrent); peSurfaceTarget = eLockSurfaceTarget.peLock(hDDSurfaceTarget);
if ((peSurfaceCurrent != NULL) && (peSurfaceTarget != NULL) && (peSurfaceCurrent->peDirectDrawGlobal == peDirectDrawGlobal) && (peSurfaceCurrent->peDirectDrawLocal == peSurfaceTarget->peDirectDrawLocal)) { FlipVPortData.lpDD = peDirectDrawGlobal; FlipVPortData.lpVideoPort = peVideoPort; FlipVPortData.lpSurfCurr = peSurfaceCurrent; FlipVPortData.lpSurfTarg = peSurfaceTarget;
{ EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
if ((!peDirectDrawGlobal->bSuspended) && (peDirectDrawGlobal->VideoPortCallBacks.FlipVideoPort)) { dwRet = peDirectDrawGlobal->VideoPortCallBacks. FlipVideoPort(&FlipVPortData); } }
if ((dwRet == DDHAL_DRIVER_HANDLED) && (FlipVPortData.ddRVal == DD_OK)) { peVideoPort->lpSurface = peSurfaceTarget; } } else { WARNING("DxDvpFlipVPort: Invalid source or target surface\n"); } } else { WARNING("DxDvpFlipVPort: Driver doesn't hook call\n"); } } else { WARNING("DxDvpFlipVPort: Invalid object\n"); }
__try { ProbeAndWriteRVal(&puFlipVPortData->ddRVal, FlipVPortData.ddRVal); } __except(EXCEPTION_EXECUTE_HANDLER) { }
return(dwRet); }
/*****************************Private*Routine******************************\
* DWORD DxGetVideoPortBandwidth * * Informs the client of bandwidth requirements for any specified format, * allowing them to better chose a format and to understand its limitations. * This information can only be given after the video port object is created * because the information in the DDVIDEOPORTDESC structure is required before * accurate bandwidth information can be supplied. * * History: * 2-Oct-1996 -by- Lingyun Wang [lingyunw] * Wrote it. \**************************************************************************/
DWORD APIENTRY DxDvpGetVideoPortBandwidth( HANDLE hVideoPort, PDD_GETVPORTBANDWIDTHDATA puGetVPortBandwidthData ) { DWORD dwRet; DD_GETVPORTBANDWIDTHDATA GetVPortBandwidthData; LPDDPIXELFORMAT pddpfFormat; DDPIXELFORMAT ddpfFormat; DDVIDEOPORTBANDWIDTH Bandwidth; LPDDVIDEOPORTBANDWIDTH puBandwidth;
__try { GetVPortBandwidthData = ProbeAndReadStructure(puGetVPortBandwidthData, DD_GETVPORTBANDWIDTHDATA);
ddpfFormat = ProbeAndReadStructure(GetVPortBandwidthData.lpddpfFormat, DDPIXELFORMAT);
puBandwidth = GetVPortBandwidthData.lpBandwidth;
Bandwidth = ProbeAndReadStructure(puBandwidth,DDVIDEOPORTBANDWIDTH); } __except(EXCEPTION_EXECUTE_HANDLER) { return(DDHAL_DRIVER_NOTHANDLED); }
dwRet = DDHAL_DRIVER_NOTHANDLED; GetVPortBandwidthData.ddRVal = DDERR_GENERIC;
EDD_VIDEOPORT* peVideoPort; EDD_LOCK_VIDEOPORT eLockVideoPort; EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
peVideoPort = eLockVideoPort.peLock(hVideoPort); if (peVideoPort != NULL) { peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
if (peDirectDrawGlobal->VideoPortCallBacks.GetVideoPortBandwidth) { GetVPortBandwidthData.lpDD = peDirectDrawGlobal; GetVPortBandwidthData.lpVideoPort = peVideoPort; GetVPortBandwidthData.lpBandwidth = &Bandwidth; GetVPortBandwidthData.lpddpfFormat = &ddpfFormat;
EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
if ((!peDirectDrawGlobal->bSuspended) && (peDirectDrawGlobal->VideoPortCallBacks.GetVideoPortBandwidth)) { dwRet = peDirectDrawGlobal->VideoPortCallBacks. GetVideoPortBandwidth(&GetVPortBandwidthData); } } else { WARNING("DxDvpGetVPortBandwidthData: Driver doesn't hook call\n"); } } else { WARNING("DxDvpGetVPortBandwidthData: Invalid object\n"); }
// We have to wrap this in another try-except because the user-mode
// memory containing the input may have been deallocated by now:
__try { ProbeAndWriteStructure(puBandwidth, Bandwidth, DDVIDEOPORTBANDWIDTH);
ProbeAndWriteRVal(&puGetVPortBandwidthData->ddRVal, GetVPortBandwidthData.ddRVal); } __except(EXCEPTION_EXECUTE_HANDLER) { }
return(dwRet); }
/*****************************Private*Routine******************************\
* DWORD DxDvpGetVideoPortField * * Sets bField to TRUE if the current field is the even field of an * interlaced signal. Otherwise, bField is set to FALSE. * * History: * 2-Oct-1996 -by- Lingyun Wang [lingyunw] * Wrote it. \**************************************************************************/
DWORD APIENTRY DxDvpGetVideoPortField( HANDLE hVideoPort, PDD_GETVPORTFIELDDATA puGetVPortFieldData ) { DWORD dwRet; DD_GETVPORTFIELDDATA GetVPortFieldData;
__try { GetVPortFieldData = ProbeAndReadStructure(puGetVPortFieldData, DD_GETVPORTFIELDDATA); } __except(EXCEPTION_EXECUTE_HANDLER) { return(DDHAL_DRIVER_NOTHANDLED); }
dwRet = DDHAL_DRIVER_NOTHANDLED; GetVPortFieldData.ddRVal = DDERR_GENERIC;
EDD_VIDEOPORT* peVideoPort; EDD_LOCK_VIDEOPORT eLockVideoPort; EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
peVideoPort = eLockVideoPort.peLock(hVideoPort); if (peVideoPort != NULL) { peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
GetVPortFieldData.lpDD = peDirectDrawGlobal; GetVPortFieldData.lpVideoPort = peVideoPort;
EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
if ((!peDirectDrawGlobal->bSuspended) && (peDirectDrawGlobal->VideoPortCallBacks.GetVideoPortField)) { dwRet = peDirectDrawGlobal-> VideoPortCallBacks.GetVideoPortField(&GetVPortFieldData); } } else { WARNING("DxDvpCanGetVPortFieldData: Invalid object\n"); }
// We have to wrap this in another try-except because the user-mode
// memory containing the input may have been deallocated by now:
__try { ProbeAndWriteRVal(&puGetVPortFieldData->ddRVal, GetVPortFieldData.ddRVal); ProbeAndWriteStructure(&puGetVPortFieldData->bField, GetVPortFieldData.bField, BOOL); } __except(EXCEPTION_EXECUTE_HANDLER) { }
return(dwRet); }
/*****************************Private*Routine******************************\
* DWORD DxDvpGetVideoPortFlipStatus * * Returns DDERR_WASSTILLDRAWING if a video VSYNC has not occurred since the * flip was performed on the specified surface. This function allows DDRAW.DLL * to fail locks on a surface that was recently flipped from so the HAL doesn't * have to account for this. * * History: * 2-Oct-1996 -by- Lingyun Wang [lingyunw] * Wrote it. \**************************************************************************/
DWORD APIENTRY DxDvpGetVideoPortFlipStatus( HANDLE hDirectDraw, PDD_GETVPORTFLIPSTATUSDATA puGetVPortFlipStatusData ) { DWORD dwRet; DD_GETVPORTFLIPSTATUSDATA GetVPortFlipStatusData;
__try { GetVPortFlipStatusData = ProbeAndReadStructure(puGetVPortFlipStatusData, DD_GETVPORTFLIPSTATUSDATA); } __except(EXCEPTION_EXECUTE_HANDLER) { return(DDHAL_DRIVER_NOTHANDLED); }
dwRet = DDHAL_DRIVER_NOTHANDLED; GetVPortFlipStatusData.ddRVal = DDERR_GENERIC;
EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal; EDD_LOCK_DIRECTDRAW eLockDirectDraw; EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
peDirectDrawLocal = eLockDirectDraw.peLock(hDirectDraw); if (peDirectDrawLocal != NULL) { peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
GetVPortFlipStatusData.lpDD = peDirectDrawGlobal;
EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
if ((!peDirectDrawGlobal->bSuspended) && (peDirectDrawGlobal->VideoPortCallBacks.GetVideoPortFlipStatus)) { dwRet = peDirectDrawGlobal-> VideoPortCallBacks.GetVideoPortFlipStatus( &GetVPortFlipStatusData); } } else { WARNING("DxDvpCanGetVPortFlipStatusData: Invalid object\n"); }
// We have to wrap this in another try-except because the user-mode
// memory containing the input may have been deallocated by now:
__try { ProbeAndWriteRVal(&puGetVPortFlipStatusData->ddRVal, GetVPortFlipStatusData.ddRVal); } __except(EXCEPTION_EXECUTE_HANDLER) { }
return(dwRet); }
/*****************************Private*Routine******************************\
* DWORD DxDvpGetVideoPortInputFormats * * Fills in the specified array with all of the formats that the video port * can accept and puts that number in dwNumFormats. If lpddpfFormats is NULL, * it only fills in dwNumFormats with the number of formats that it can support. * This function is needed because the supported formats may vary depending on * the electrical connection of the video port. * * History: * 2-Oct-1996 -by- Lingyun Wang [lingyunw] * Wrote it. \**************************************************************************/
DWORD APIENTRY DxDvpGetVideoPortInputFormats( HANDLE hVideoPort, PDD_GETVPORTINPUTFORMATDATA puGetVPortInputFormatData ) { DWORD dwRet; DD_GETVPORTINPUTFORMATDATA GetVPortInputFormatData; LPDDPIXELFORMAT puFormat; ULONG cjFormat; HANDLE hSecure;
__try { GetVPortInputFormatData = ProbeAndReadStructure(puGetVPortInputFormatData, DD_GETVPORTINPUTFORMATDATA);
puFormat = GetVPortInputFormatData.lpddpfFormat; } __except(EXCEPTION_EXECUTE_HANDLER) { return(DDHAL_DRIVER_NOTHANDLED); }
dwRet = DDHAL_DRIVER_NOTHANDLED; GetVPortInputFormatData.ddRVal = DDERR_GENERIC;
EDD_VIDEOPORT* peVideoPort; EDD_LOCK_VIDEOPORT eLockVideoPort; EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
peVideoPort = eLockVideoPort.peLock(hVideoPort); if (peVideoPort != NULL) { peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
GetVPortInputFormatData.lpDD = peDirectDrawGlobal; GetVPortInputFormatData.lpVideoPort = peVideoPort; GetVPortInputFormatData.lpddpfFormat = NULL;
EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
if ((!peDirectDrawGlobal->bSuspended) && (peDirectDrawGlobal->VideoPortCallBacks.GetVideoPortInputFormats)) { dwRet = peDirectDrawGlobal->VideoPortCallBacks. GetVideoPortInputFormats(&GetVPortInputFormatData);
cjFormat = GetVPortInputFormatData.dwNumFormats * sizeof(DDPIXELFORMAT);
if ((dwRet == DDHAL_DRIVER_HANDLED) && (GetVPortInputFormatData.ddRVal == DD_OK) && (cjFormat > 0) && (puFormat != NULL) && !BALLOC_OVERFLOW1(GetVPortInputFormatData.dwNumFormats, DDPIXELFORMAT)) { GetVPortInputFormatData.ddRVal = DDERR_GENERIC; hSecure = 0;
__try { ProbeForWrite(puFormat, cjFormat, sizeof(UCHAR));
hSecure = MmSecureVirtualMemory(puFormat, cjFormat, PAGE_READWRITE); } __except(EXCEPTION_EXECUTE_HANDLER) { }
if (hSecure) { GetVPortInputFormatData.lpddpfFormat = puFormat;
dwRet = peDirectDrawGlobal->VideoPortCallBacks. GetVideoPortInputFormats(&GetVPortInputFormatData);
MmUnsecureVirtualMemory(hSecure); } else { WARNING("DxDvpGetVideoPortInputFormats: Bad destination buffer\n"); } } } } else { WARNING("DxDvpGetVPortInputFormatData: Invalid object\n"); }
// We have to wrap this in another try-except because the user-mode
// memory containing the input may have been deallocated by now:
__try { ProbeAndWriteRVal(&puGetVPortInputFormatData->ddRVal, GetVPortInputFormatData.ddRVal); ProbeAndWriteUlong(&puGetVPortInputFormatData->dwNumFormats, GetVPortInputFormatData.dwNumFormats); } __except(EXCEPTION_EXECUTE_HANDLER) { }
return(dwRet); }
/*****************************Private*Routine******************************\
* DWORD DxDvpGetVideoPortOutputFormats * * Fills in the specified array with all of the formats that can be written * to the frame buffer based on the specified input format and puts that * number in dwNumFormats. If lpddpfOutputFormats is NULL, it only fills * in dwNumFormats with the number of formats that can be written to the * frame buffer. * * History: * 2-Oct-1996 -by- Lingyun Wang [lingyunw] * Wrote it. \**************************************************************************/
DWORD APIENTRY DxDvpGetVideoPortOutputFormats( HANDLE hVideoPort, PDD_GETVPORTOUTPUTFORMATDATA puGetVPortOutputFormatData ) { DWORD dwRet; DD_GETVPORTOUTPUTFORMATDATA GetVPortOutputFormatData; LPDDPIXELFORMAT puOutputFormats; DDPIXELFORMAT ddpfInputFormat; ULONG cjFormat; HANDLE hSecure;
__try { GetVPortOutputFormatData = ProbeAndReadStructure(puGetVPortOutputFormatData, DD_GETVPORTOUTPUTFORMATDATA);
ddpfInputFormat = ProbeAndReadStructure(GetVPortOutputFormatData.lpddpfInputFormat, DDPIXELFORMAT);
puOutputFormats = GetVPortOutputFormatData.lpddpfOutputFormats; } __except(EXCEPTION_EXECUTE_HANDLER) { return(DDHAL_DRIVER_NOTHANDLED); }
dwRet = DDHAL_DRIVER_NOTHANDLED; GetVPortOutputFormatData.ddRVal = DDERR_GENERIC;
EDD_VIDEOPORT* peVideoPort; EDD_LOCK_VIDEOPORT eLockVideoPort; EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
peVideoPort = eLockVideoPort.peLock(hVideoPort); if (peVideoPort != NULL) { peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
GetVPortOutputFormatData.lpDD = peDirectDrawGlobal; GetVPortOutputFormatData.lpVideoPort = peVideoPort; GetVPortOutputFormatData.lpddpfInputFormat = &ddpfInputFormat; GetVPortOutputFormatData.lpddpfOutputFormats = NULL;
EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
if ((!peDirectDrawGlobal->bSuspended) && (peDirectDrawGlobal->VideoPortCallBacks.GetVideoPortOutputFormats)) { dwRet = peDirectDrawGlobal->VideoPortCallBacks. GetVideoPortOutputFormats(&GetVPortOutputFormatData);
cjFormat = GetVPortOutputFormatData.dwNumFormats * sizeof(DDPIXELFORMAT);
if ((dwRet == DDHAL_DRIVER_HANDLED) && (GetVPortOutputFormatData.ddRVal == DD_OK) && (cjFormat > 0) && (puOutputFormats != NULL) && !BALLOC_OVERFLOW1(GetVPortOutputFormatData.dwNumFormats, DDPIXELFORMAT)) { GetVPortOutputFormatData.ddRVal = DDERR_GENERIC; hSecure = 0;
__try { ProbeForWrite(puOutputFormats, cjFormat, sizeof(UCHAR));
hSecure = MmSecureVirtualMemory(puOutputFormats, cjFormat, PAGE_READWRITE); } __except(EXCEPTION_EXECUTE_HANDLER) { }
if (hSecure) { GetVPortOutputFormatData.lpddpfOutputFormats = puOutputFormats;
dwRet = peDirectDrawGlobal->VideoPortCallBacks. GetVideoPortOutputFormats(&GetVPortOutputFormatData);
MmUnsecureVirtualMemory(hSecure); } else { WARNING("DxDvpGetVideoPortOutputFormats: Bad destination buffer\n"); } } } } else { WARNING("DxDvpGetVPortOutputFormatData: Invalid object\n"); }
// We have to wrap this in another try-except because the user-mode
// memory containing the input may have been deallocated by now:
__try { ProbeAndWriteRVal(&puGetVPortOutputFormatData->ddRVal, GetVPortOutputFormatData.ddRVal); ProbeAndWriteUlong(&puGetVPortOutputFormatData->dwNumFormats, GetVPortOutputFormatData.dwNumFormats); } __except(EXCEPTION_EXECUTE_HANDLER) { }
return(dwRet); }
/*****************************Private*Routine******************************\
* DWORD DxGetVideoPortLine * * Returns the current line counter of the video port. * * This function is only required if the driver sets the DDVPCAPS_READBACKLINE * flag. * * History: * 2-Oct-1996 -by- Lingyun Wang [lingyunw] * Wrote it. \**************************************************************************/
DWORD APIENTRY DxDvpGetVideoPortLine( HANDLE hVideoPort, PDD_GETVPORTLINEDATA puGetVPortLineData ) { DWORD dwRet; DD_GETVPORTLINEDATA GetVPortLineData;
dwRet = DDHAL_DRIVER_NOTHANDLED; GetVPortLineData.ddRVal = DDERR_GENERIC;
EDD_VIDEOPORT* peVideoPort; EDD_LOCK_VIDEOPORT eLockVideoPort; EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
peVideoPort = eLockVideoPort.peLock(hVideoPort); if (peVideoPort != NULL) { peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
GetVPortLineData.lpDD = peDirectDrawGlobal; GetVPortLineData.lpVideoPort = peVideoPort;
EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
if ((!peDirectDrawGlobal->bSuspended) && (peDirectDrawGlobal->VideoPortCallBacks.GetVideoPortLine)) { dwRet = peDirectDrawGlobal-> VideoPortCallBacks.GetVideoPortLine(&GetVPortLineData); } } else { WARNING("DxDvpGetVPortLineData: Invalid object\n"); }
__try { ProbeAndWriteStructure(puGetVPortLineData, GetVPortLineData, DD_GETVPORTLINEDATA); } __except(EXCEPTION_EXECUTE_HANDLER) { }
return(dwRet); }
/*****************************Private*Routine******************************\
* DWORD DxGetVideoPortConnectInfo * * Fills in the specified array with all of the connection combinations * supported by the specified video port and puts that number in dwNumEntries. * If lpConnect is NULL, it only fills in dwNumEntries with the number of * DDVIDEOPORTCONNECT entries supported. * * History: * 2-Oct-1996 -by- Lingyun Wang [lingyunw] * Wrote it. \**************************************************************************/
DWORD APIENTRY DxDvpGetVideoPortConnectInfo( HANDLE hDirectDraw, PDD_GETVPORTCONNECTDATA puGetVPortConnectData ) { DWORD dwRet; DD_GETVPORTCONNECTDATA GetVPortConnectData; DDVIDEOPORTCONNECT* puConnect; ULONG cjConnect; HANDLE hSecure;
__try { GetVPortConnectData = ProbeAndReadStructure(puGetVPortConnectData, DD_GETVPORTCONNECTDATA);
puConnect = GetVPortConnectData.lpConnect; } __except(EXCEPTION_EXECUTE_HANDLER) { return(DDHAL_DRIVER_NOTHANDLED); }
dwRet = DDHAL_DRIVER_NOTHANDLED; GetVPortConnectData.ddRVal = DDERR_GENERIC;
EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal; EDD_LOCK_DIRECTDRAW eLockDirectDraw; EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
peDirectDrawLocal = eLockDirectDraw.peLock(hDirectDraw); if (peDirectDrawLocal != NULL) { peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
GetVPortConnectData.lpDD = peDirectDrawGlobal; GetVPortConnectData.lpConnect = NULL;
EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
if ((!peDirectDrawGlobal->bSuspended) && (peDirectDrawGlobal->VideoPortCallBacks.GetVideoPortConnectInfo)) { dwRet = peDirectDrawGlobal-> VideoPortCallBacks.GetVideoPortConnectInfo( &GetVPortConnectData);
cjConnect = GetVPortConnectData.dwNumEntries * sizeof(DDVIDEOPORTCONNECT);
if ((dwRet == DDHAL_DRIVER_HANDLED) && (GetVPortConnectData.ddRVal == DD_OK) && (cjConnect > 0) && (puConnect != NULL) && !BALLOC_OVERFLOW1(GetVPortConnectData.dwNumEntries, DDVIDEOPORTCONNECT)) { GetVPortConnectData.ddRVal = DDERR_GENERIC; hSecure = 0;
__try { ProbeForWrite(puConnect, cjConnect, sizeof(UCHAR));
hSecure = MmSecureVirtualMemory(puConnect, cjConnect, PAGE_READWRITE); } __except(EXCEPTION_EXECUTE_HANDLER) { }
if (hSecure) { GetVPortConnectData.lpConnect = puConnect;
dwRet = peDirectDrawGlobal->VideoPortCallBacks. GetVideoPortConnectInfo(&GetVPortConnectData);
MmUnsecureVirtualMemory(hSecure); } else { WARNING("DxDvpGetVideoPortConnectInfo: Bad destination buffer\n"); } } } } else { WARNING("DxDvpGetVPortConnectData: Invalid object\n"); }
// We have to wrap this in another try-except because the user-mode
// memory containing the input may have been deallocated by now:
__try { ProbeAndWriteRVal(&puGetVPortConnectData->ddRVal, GetVPortConnectData.ddRVal); ProbeAndWriteUlong(&puGetVPortConnectData->dwNumEntries, GetVPortConnectData.dwNumEntries); } __except(EXCEPTION_EXECUTE_HANDLER) { }
return(dwRet); }
/*****************************Private*Routine******************************\
* DxDvpGetVideoSignalStatus * * If the video port is receiving a good signal, the HAL should set dwStatus * to DDVPSQ_SIGNALOK; otherwise, it should set dwStatus to DDVPSQ_NOSIGNAL. * *History: * 2-Oct-1996 -by- Lingyun Wang [lingyunw] * Wrote it. \**************************************************************************/
DWORD APIENTRY DxDvpGetVideoSignalStatus( HANDLE hVideoPort, PDD_GETVPORTSIGNALDATA puGetVPortSignalData ) { DWORD dwRet; DD_GETVPORTSIGNALDATA GetVPortSignalData;
dwRet = DDHAL_DRIVER_NOTHANDLED; GetVPortSignalData.ddRVal = DDERR_GENERIC;
EDD_VIDEOPORT* peVideoPort; EDD_LOCK_VIDEOPORT eLockVideoPort; EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
peVideoPort = eLockVideoPort.peLock(hVideoPort); if (peVideoPort != NULL) { peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
GetVPortSignalData.lpDD = peDirectDrawGlobal; GetVPortSignalData.lpVideoPort = peVideoPort;
EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
if ((!peDirectDrawGlobal->bSuspended) && (peDirectDrawGlobal->VideoPortCallBacks.GetVideoSignalStatus)) { dwRet = peDirectDrawGlobal-> VideoPortCallBacks.GetVideoSignalStatus(&GetVPortSignalData); } } else { WARNING("DxDvpGetVPortSignalData: Invalid object\n"); }
__try { ProbeAndWriteStructure(puGetVPortSignalData, GetVPortSignalData, DD_GETVPORTSIGNALDATA); } __except(EXCEPTION_EXECUTE_HANDLER) { }
return(dwRet); }
/*****************************Private*Routine******************************\
* DWORD DxDvpUpdateVideoPort * * Starts, stops, and changes the video port. dwFlags can contain either * DDRAWI_VPORTSTART, DDRAWI_VPORTSTOP, or DDRAWI_VPORTUPDATE. To accommodate * auto-flipping, lplpDDSurface and lplpDDVBISurface point to an array of * surface structures rather than to a single structure. If autoflipping is * requested, the dwNumAutoflip field contains the number of surfaces in the * list. * * History: * 2-Oct-1996 -by- Lingyun Wang [lingyunw] * Wrote it. \**************************************************************************/
DWORD APIENTRY DxDvpUpdateVideoPort( HANDLE hVideoPort, HANDLE* phSurfaceVideo, HANDLE* phSurfaceVbi, PDD_UPDATEVPORTDATA puUpdateVPortData ) { DWORD dwRet; DD_UPDATEVPORTDATA UpdateVPortData; DDVIDEOPORTINFO VideoPortInfo; DDPIXELFORMAT ddpfInputFormat; DDPIXELFORMAT ddpfVBIInputFormat; DDPIXELFORMAT ddpfVBIOutputFormat; HANDLE ahSurfaceVideo[MAX_AUTOFLIP_BUFFERS]; HANDLE ahSurfaceVbi[MAX_AUTOFLIP_BUFFERS]; EDD_SURFACE* apeSurfaceVideo[MAX_AUTOFLIP_BUFFERS]; EDD_SURFACE* apeSurfaceVbi[MAX_AUTOFLIP_BUFFERS]; DD_SURFACE_INT* apDDSurfaceVideo[MAX_AUTOFLIP_BUFFERS]; DD_SURFACE_INT* apDDSurfaceVbi[MAX_AUTOFLIP_BUFFERS]; ULONG cAutoflipVideo; ULONG cAutoflipVbi; EDD_DXVIDEOPORT* peDxVideoPort;
__try { UpdateVPortData = ProbeAndReadStructure(puUpdateVPortData, DD_UPDATEVPORTDATA);
// Handle VideoPortInfo structure:
if (UpdateVPortData.dwFlags != DDRAWI_VPORTSTOP) { VideoPortInfo = ProbeAndReadStructure(UpdateVPortData.lpVideoInfo, DDVIDEOPORTINFO);
if (VideoPortInfo.lpddpfInputFormat != NULL) { ddpfInputFormat = ProbeAndReadStructure(VideoPortInfo.lpddpfInputFormat, DDPIXELFORMAT);
VideoPortInfo.lpddpfInputFormat = &ddpfInputFormat; } if (VideoPortInfo.dwVBIHeight > 0) { if (VideoPortInfo.lpddpfVBIInputFormat != NULL) { ddpfVBIInputFormat = ProbeAndReadStructure(VideoPortInfo.lpddpfVBIInputFormat, DDPIXELFORMAT);
VideoPortInfo.lpddpfVBIInputFormat = &ddpfVBIInputFormat; } if (VideoPortInfo.lpddpfVBIOutputFormat != NULL) { ddpfVBIOutputFormat = ProbeAndReadStructure(VideoPortInfo.lpddpfVBIOutputFormat, DDPIXELFORMAT);
VideoPortInfo.lpddpfVBIOutputFormat = &ddpfVBIOutputFormat; } } else { VideoPortInfo.lpddpfVBIInputFormat = NULL; VideoPortInfo.lpddpfVBIOutputFormat = NULL; } }
// Handle arrays of surfaces:
cAutoflipVbi = 0; cAutoflipVideo = 0;
if (UpdateVPortData.dwFlags != DDRAWI_VPORTSTOP) { cAutoflipVideo = min(UpdateVPortData.dwNumAutoflip, MAX_AUTOFLIP_BUFFERS); if ((cAutoflipVideo == 0) && (UpdateVPortData.lplpDDSurface != NULL)) { cAutoflipVideo = 1; }
cAutoflipVbi = min(UpdateVPortData.dwNumVBIAutoflip, MAX_AUTOFLIP_BUFFERS); if ((cAutoflipVbi == 0) && (UpdateVPortData.lplpDDVBISurface != NULL)) { cAutoflipVbi = 1; } } if (cAutoflipVideo) { ProbeForRead(phSurfaceVideo, cAutoflipVideo * sizeof(HANDLE), sizeof(HANDLE)); RtlCopyMemory(ahSurfaceVideo, phSurfaceVideo, cAutoflipVideo * sizeof(HANDLE)); } if (cAutoflipVbi) { ProbeForRead(phSurfaceVbi, cAutoflipVbi * sizeof(HANDLE), sizeof(HANDLE)); RtlCopyMemory(ahSurfaceVbi, phSurfaceVbi, cAutoflipVbi * sizeof(HANDLE)); } } __except(EXCEPTION_EXECUTE_HANDLER) { return(DDHAL_DRIVER_NOTHANDLED); }
dwRet = DDHAL_DRIVER_NOTHANDLED; UpdateVPortData.ddRVal = DDERR_GENERIC;
EDD_VIDEOPORT* peVideoPort; EDD_LOCK_VIDEOPORT eLockVideoPort; EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal; ULONG i; EDD_SURFACE* peSurface;
BOOL bUpdateOK = TRUE;
peVideoPort = eLockVideoPort.peLock(hVideoPort); if (peVideoPort != NULL) { peDxVideoPort = peVideoPort->peDxVideoPort; peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
// Lock all the surfaces. Note that bDdUpdateLinksAndSynchronize
// will check for failure of DdHmgLock (the pointer will be NULL):
for (i = 0; i < cAutoflipVideo; i++) { apeSurfaceVideo[i] = (EDD_SURFACE*) DdHmgLock((HDD_OBJ) ahSurfaceVideo[i], DD_SURFACE_TYPE, FALSE); } for (i = 0; i < cAutoflipVbi; i++) { apeSurfaceVbi[i] = (EDD_SURFACE*) DdHmgLock((HDD_OBJ) ahSurfaceVbi[i], DD_SURFACE_TYPE, FALSE); }
EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
if ((!peDirectDrawGlobal->bSuspended) && (peDirectDrawGlobal->VideoPortCallBacks.UpdateVideoPort) && (bUpdateOK = bDdUpdateLinksAndSynchronize( peVideoPort, TRUE, // Update video
apeSurfaceVideo, cAutoflipVideo, TRUE, // Update VBI
apeSurfaceVbi, cAutoflipVbi))) { UpdateVPortData.lpDD = peDirectDrawGlobal; UpdateVPortData.lpVideoPort = peVideoPort; UpdateVPortData.lplpDDSurface = NULL; UpdateVPortData.lplpDDVBISurface = NULL; UpdateVPortData.dwNumAutoflip = cAutoflipVideo; UpdateVPortData.dwNumVBIAutoflip = cAutoflipVbi; UpdateVPortData.lpVideoInfo = (UpdateVPortData.dwFlags == DDRAWI_VPORTSTOP) ? NULL : &VideoPortInfo;
if (cAutoflipVideo != 0) { for (i = 0; i < cAutoflipVideo; i++) { apDDSurfaceVideo[i] = apeSurfaceVideo[i]; } UpdateVPortData.lplpDDSurface = apDDSurfaceVideo; } if (cAutoflipVbi != 0) { for (i = 0; i < cAutoflipVbi; i++) { apDDSurfaceVbi[i] = apeSurfaceVbi[i]; } UpdateVPortData.lplpDDVBISurface = apDDSurfaceVbi; }
// Turn off software autoflipping if necessary:
if (UpdateVPortData.dwFlags == DDRAWI_VPORTSTOP) { peDxVideoPort->bSoftwareAutoflip = FALSE; peDxVideoPort->flFlags &= ~(DD_DXVIDEOPORT_FLAG_AUTOFLIP|DD_DXVIDEOPORT_FLAG_AUTOFLIP_VBI);
// Disable the video port VSYNC IRQ now
if( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_ON ) { peDxVideoPort->flFlags &= ~DD_DXVIDEOPORT_FLAG_ON; peDirectDrawGlobal->pfnEnableIRQ(peDxVideoPort, FALSE ); } }
// We don't allow switching back to hardware once software
// autoflipping has started (for various reasons, among
// them being how do we synchronize -- the hardware would
// start autoflipping before we could turn off the software
// autoflipping).
if (peDxVideoPort->bSoftwareAutoflip) { VideoPortInfo.dwVPFlags &= ~DDVP_AUTOFLIP; }
// Make the HAL call:
dwRet = peDirectDrawGlobal-> VideoPortCallBacks.UpdateVideoPort(&UpdateVPortData);
// If we failed due to a request for hardware autoflipping,
// try again with software autoflipping.
if ((dwRet == DDHAL_DRIVER_HANDLED) && (UpdateVPortData.ddRVal != DD_OK) && (peDirectDrawGlobal->DDKernelCaps.dwCaps & DDKERNELCAPS_AUTOFLIP)) { VideoPortInfo.dwVPFlags &= ~DDVP_AUTOFLIP;
dwRet = peDirectDrawGlobal-> VideoPortCallBacks.UpdateVideoPort(&UpdateVPortData);
if ((dwRet == DDHAL_DRIVER_HANDLED) && (UpdateVPortData.ddRVal == DD_OK)) { KdPrint(("DxDvpUpdateVideoPort: Software autoflipping\n"));
peDxVideoPort->bSoftwareAutoflip = TRUE; UpdateVPortData.ddRVal = DD_OK; } } if ((UpdateVPortData.ddRVal == DD_OK) && peDxVideoPort->bSoftwareAutoflip) { if( cAutoflipVideo > 0 ) { peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_AUTOFLIP; } if( cAutoflipVbi > 0 ) { peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_AUTOFLIP_VBI; } } }
if (!bUpdateOK) { WARNING("DxDvpUpdateVideoPort: failed on bDdUpdateLinksAndSynchronize"); }
if ((dwRet == DDHAL_DRIVER_HANDLED) && (UpdateVPortData.ddRVal == DD_OK)) { // Success!
peVideoPort->dwNumAutoflip = cAutoflipVideo; peVideoPort->dwNumVBIAutoflip = cAutoflipVbi; if (UpdateVPortData.dwFlags != DDRAWI_VPORTSTOP) { peVideoPort->ddvpInfo = VideoPortInfo;
if (VideoPortInfo.lpddpfInputFormat != NULL) { peVideoPort->ddvpInfo.lpddpfInputFormat = &peVideoPort->ddpfInputFormat;
peVideoPort->ddpfInputFormat = ddpfInputFormat; } else { peVideoPort->ddvpInfo.lpddpfInputFormat = NULL; } } }
// Update various DXAPI state to reflect the changes:
vDdSynchronizeVideoPort(peVideoPort);
// If it wasn't previously on, enable the video port VSYNC IRQ now
//
// if bDdUpdateLinksAndSynchronize failed, don't enable.
if( (bUpdateOK) && (UpdateVPortData.dwFlags != DDRAWI_VPORTSTOP) && !(peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_ON) ) { peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_ON; peDirectDrawGlobal->pfnEnableIRQ(peDxVideoPort, TRUE ); }
// Unlock the memory that I've locked
for (i = 0; i < cAutoflipVideo; i++) { if( apeSurfaceVideo[i] != NULL ) DEC_EXCLUSIVE_REF_CNT( apeSurfaceVideo[i] ); } for (i = 0; i < cAutoflipVbi; i++) { if( apeSurfaceVbi[i] != NULL ) DEC_EXCLUSIVE_REF_CNT( apeSurfaceVbi[i] ); }
} else { WARNING("DxDvpUpdateVPortData: Invalid object\n"); }
// We have to wrap this in another try-except because the user-mode
// memory containing the input may have been deallocated by now:
__try { ProbeAndWriteRVal(&puUpdateVPortData->ddRVal, UpdateVPortData.ddRVal); } __except(EXCEPTION_EXECUTE_HANDLER) { }
return(dwRet); }
/*****************************Private*Routine******************************\
* DWORD DxDvpWaitForVideoPortSync * * Returns at the beginning or end of either the video VSYNC or the specified * line. If the sync does not occur before the number of milliseconds * specified in dwTimeOut has elapsed, the HAL should return * DDERR_VIDEONOTACTIVE. * * History: * 2-Oct-1996 -by- Lingyun Wang [lingyunw] * Wrote it. \**************************************************************************/
DWORD APIENTRY DxDvpWaitForVideoPortSync( HANDLE hVideoPort, PDD_WAITFORVPORTSYNCDATA puWaitForVPortSyncData ) { DWORD dwRet; DD_WAITFORVPORTSYNCDATA WaitForVPortSyncData;
__try { WaitForVPortSyncData = ProbeAndReadStructure(puWaitForVPortSyncData, DD_WAITFORVPORTSYNCDATA); } __except(EXCEPTION_EXECUTE_HANDLER) { return(DDHAL_DRIVER_NOTHANDLED); }
dwRet = DDHAL_DRIVER_NOTHANDLED; WaitForVPortSyncData.ddRVal = DDERR_GENERIC;
EDD_VIDEOPORT* peVideoPort; EDD_LOCK_VIDEOPORT eLockVideoPort; EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
peVideoPort = eLockVideoPort.peLock(hVideoPort); if (peVideoPort != NULL) { peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
WaitForVPortSyncData.lpDD = peDirectDrawGlobal; WaitForVPortSyncData.lpVideoPort = peVideoPort;
// Cap the number of milliseconds to wait to something reasonable:
if (WaitForVPortSyncData.dwTimeOut > 6 * peVideoPort->ddvpDesc.dwMicrosecondsPerField) { WaitForVPortSyncData.dwTimeOut = 6 * peVideoPort->ddvpDesc.dwMicrosecondsPerField; }
EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
if ((!peDirectDrawGlobal->bSuspended) && (peDirectDrawGlobal->VideoPortCallBacks.WaitForVideoPortSync)) { dwRet = peDirectDrawGlobal->VideoPortCallBacks. WaitForVideoPortSync(&WaitForVPortSyncData); } } else { WARNING("DxDvpWaitForVPortSyncData: Invalid object\n"); }
// We have to wrap this in another try-except because the user-mode
// memory containing the input may have been deallocated by now:
__try { ProbeAndWriteRVal(&puWaitForVPortSyncData->ddRVal, WaitForVPortSyncData.ddRVal); } __except(EXCEPTION_EXECUTE_HANDLER) { }
return(dwRet); }
/*****************************Private*Routine******************************\
* DWORD DxDvpColorControl * * Gets or sets the current color controls associated with the video port. * * History: * 2-Oct-1996 -by- Lingyun Wang [lingyunw] * Wrote it. \**************************************************************************/
DWORD APIENTRY DxDvpColorControl( HANDLE hVideoPort, PDD_VPORTCOLORDATA puVPortColorData ) { DWORD dwRet; DD_VPORTCOLORDATA VPortColorData; DDCOLORCONTROL ColorData;
__try { VPortColorData = ProbeAndReadStructure(puVPortColorData, DD_VPORTCOLORDATA);
ColorData = ProbeAndReadStructure(VPortColorData.lpColorData, DDCOLORCONTROL); } __except(EXCEPTION_EXECUTE_HANDLER) { return(DDHAL_DRIVER_NOTHANDLED); }
dwRet = DDHAL_DRIVER_NOTHANDLED; VPortColorData.ddRVal = DDERR_GENERIC;
EDD_VIDEOPORT* peVideoPort; EDD_LOCK_VIDEOPORT eLockVideoPort; EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
peVideoPort = eLockVideoPort.peLock(hVideoPort); if (peVideoPort != NULL) { peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
VPortColorData.lpDD = peDirectDrawGlobal; VPortColorData.lpVideoPort = peVideoPort; VPortColorData.lpColorData = &ColorData;
EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
if ((!peDirectDrawGlobal->bSuspended) && (peDirectDrawGlobal->VideoPortCallBacks.ColorControl)) { dwRet = peDirectDrawGlobal-> VideoPortCallBacks.ColorControl(&VPortColorData); } } else { WARNING("DxDvpColorControl: Invalid object\n"); }
// We have to wrap this in another try-except because the user-mode
// memory containing the input may have been deallocated by now:
__try { ProbeAndWriteRVal(&puVPortColorData->ddRVal, VPortColorData.ddRVal); } __except(EXCEPTION_EXECUTE_HANDLER) { } return(dwRet); }
/*****************************Private*Routine******************************\
* DWORD DxDvpAcquireNotification * * Sets up the user mode notification of video port vsyncs. * * History: * 10-Oct-2000 -Scott MacDonald [smac] * Wrote it. \**************************************************************************/
DWORD APIENTRY DxDvpAcquireNotification( HANDLE hVideoPort, HANDLE * phEvent, LPDDVIDEOPORTNOTIFY pNotify ) { PKEVENT pEvent = NULL; EDD_VIDEOPORT* peVideoPort; EDD_LOCK_VIDEOPORT eLockVideoPort; EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal; PMDL mdl; LPDDVIDEOPORTNOTIFY pLockedBuffer;
__try { ProbeAndWriteHandle(phEvent, NULL); } __except(EXCEPTION_EXECUTE_HANDLER) { return DDHAL_DRIVER_NOTHANDLED; }
// First check the caps to see if this device even supports a vport IRQ
peVideoPort = eLockVideoPort.peLock(hVideoPort); if ((peVideoPort != NULL) && (peVideoPort->peDxVideoPort->pNotifyEvent == NULL)) { peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal; if (peDirectDrawGlobal->DDKernelCaps.dwIRQCaps & DDIRQ_VPORT0_VSYNC ) { // Now setup the buffer so it can be accessed at DPC level
mdl = IoAllocateMdl(pNotify, sizeof(DDVIDEOPORTNOTIFY), FALSE, FALSE, NULL); if (mdl != NULL) { __try { MmProbeAndLockPages (mdl, KernelMode, IoWriteAccess); } __except(EXCEPTION_EXECUTE_HANDLER) { IoFreeMdl (mdl); mdl = NULL; } }
if (mdl != NULL) { pLockedBuffer = (LPDDVIDEOPORTNOTIFY) MmGetSystemAddressForMdlSafe (mdl, NormalPagePriority); if (pLockedBuffer == NULL) { MmUnlockPages (mdl); IoFreeMdl (mdl); } else { // Now set up the event that we trigger
HANDLE h = NULL;
ZwCreateEvent( &h, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE );
if (h != NULL) { (VOID) ObReferenceObjectByHandle( h, 0, 0, KernelMode, (PVOID *) &pEvent, NULL ); }
if (pEvent != NULL) { ObDereferenceObject(pEvent); peVideoPort->peDxVideoPort->pNotifyBuffer = pLockedBuffer; peVideoPort->peDxVideoPort->pNotifyMdl = mdl; peVideoPort->peDxVideoPort->pNotifyEvent = pEvent; peVideoPort->peDxVideoPort->pNotifyEventHandle = h;
__try { ProbeAndWriteHandle(phEvent, h); } __except(EXCEPTION_EXECUTE_HANDLER) { } } else { MmUnlockPages (mdl); IoFreeMdl (mdl); } } // force software autoflipping
peVideoPort->peDxVideoPort->bSoftwareAutoflip = TRUE; } } }
return 0; }
/*****************************Private*Routine******************************\
* DWORD DxDvpReleaseNotification * * Stops up the user mode notification of video port vsyncs. * * History: * 10-Oct-2000 -Scott MacDonald [smac] * Wrote it. \**************************************************************************/
DWORD APIENTRY DxDvpReleaseNotification( HANDLE hVideoPort, HANDLE pEvent ) { EDD_VIDEOPORT* peVideoPort; EDD_LOCK_VIDEOPORT eLockVideoPort;
peVideoPort = eLockVideoPort.peLock(hVideoPort); if ((peVideoPort != NULL) && (peVideoPort->peDxVideoPort->pNotifyEventHandle == pEvent) && (pEvent != NULL)) { PKEVENT pTemp = NULL; NTSTATUS Status;
peVideoPort->peDxVideoPort->pNotifyEvent = NULL; peVideoPort->peDxVideoPort->pNotifyEventHandle = NULL;
// Make sure that the handle hasn't been freed by the OS already
Status = ObReferenceObjectByHandle( pEvent, 0, 0, KernelMode, (PVOID *) &pTemp, NULL ); if ((pTemp != NULL) && (Status != STATUS_INVALID_HANDLE)) { ObDereferenceObject(pTemp); ZwClose (pEvent); }
peVideoPort->peDxVideoPort->pNotifyBuffer = NULL; if (peVideoPort->peDxVideoPort->pNotifyMdl != NULL) { MmUnlockPages (peVideoPort->peDxVideoPort->pNotifyMdl); IoFreeMdl (peVideoPort->peDxVideoPort->pNotifyMdl); peVideoPort->peDxVideoPort->pNotifyMdl = NULL; } }
return 0; }
|