|
|
/******************************Module*Header*******************************\
* Module Name: dciman.c * * * * Client side stubs for DCIMAN functions. * * * * Created: 07-Sep-1994 * * Author: Andre Vachon [andreva] * * * * Copyright (c) 1994-1998 Microsoft Corporation * \**************************************************************************/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <stddef.h>
#include <windows.h>
#include <winspool.h>
#include <wingdip.h>
#include <ddrawp.h>
#include <winddi.h>
#include "dciddi.h"
#include "dciman.h"
#include <ddrawi.h>
#include <ddrawgdi.h>
#if DBG
#define RIP(x) {DbgPrint(x); DbgBreakPoint();}
#define ASSERTGDI(x,y) if(!(x)) RIP(y)
#define WARNING(x) {DbgPrint(x);}
#else
#define ASSERTGDI(x,y)
#define WARNING(x)
#endif
typedef struct _WINWATCH *PWINWATCH;
typedef struct _WINWATCH {
PWINWATCH pWinWatchNext; HWND hwnd; BOOL changed; ULONG lprgndataSize; LPRGNDATA lprgndata;
} WINWATCH, *PWINWATCH;
//
// The following structure incorporates the DirectDraw structures required
// to identify a surface. It is allocated before the start of the
// DCISURFACEINFO structure.
//
typedef struct _DCIMAN_SURF { BOOL SurfaceLost; // True if the surface can no
// longer be accessed because
// a mode change occured
DDRAWI_DIRECTDRAW_GBL DirectDrawGlobal; // Identifies device
DDRAWI_DDRAWSURFACE_GBL SurfaceGlobal; // Identifies surface
DDRAWI_DDRAWSURFACE_LCL SurfaceLocal; // Identifies surface
DDHAL_DDCALLBACKS DDCallbacks; // Contains address of CreateSurface
// call for BeginAccess
DDHAL_DDSURFACECALLBACKS DDSurfaceCallbacks;// Contains addresses of Lock, Unlock,
// and DestroySurface calls for
// BeginAccess and EndAccess
} DCIMAN_SURF, *PDCIMAN_SURF;
//
// We maintain a linked list of all winwatch's so that we can notify their
// owners whenever we notice that the clippping has changed. The list may
// be accessed only while holding the gcsWinWatchLock critical section.
//
CRITICAL_SECTION gcsWinWatchLock;
PWINWATCH gpWinWatchList = NULL;
/******************************Private*Routine*****************************\
* dciCreateSurface * * History: 1-Aug-1998 Jerry Van Aken [jvanaken] wrote it. \**************************************************************************/
static BOOL bCreateSurface(PDCIMAN_SURF pPrivate) { DDSURFACEDESC ddsd; DDHAL_CREATESURFACEDATA csd; LPDDRAWI_DDRAWSURFACE_LCL pSurfaceLocal = &pPrivate->SurfaceLocal;
//
// Fill in DDSURFACEDESC struct for CreateSurface call.
//
ZeroMemory(&ddsd, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_VISIBLE;
//
// Fill in DDHAL_CREATESURFACEDATA struct for CreateSurface call.
//
csd.lpDD = pPrivate->SurfaceGlobal.lpDD; csd.lpDDSurfaceDesc = &ddsd; csd.lplpSList = &pSurfaceLocal; csd.dwSCnt = 1; csd.ddRVal = DDERR_GENERIC; csd.CreateSurface = pPrivate->DDCallbacks.CreateSurface;
if ((pPrivate->DDCallbacks.dwFlags & DDHAL_CB32_CREATESURFACE) && (csd.CreateSurface != NULL) && ((*csd.CreateSurface)(&csd) == DDHAL_DRIVER_HANDLED) && (csd.ddRVal == DD_OK)) { return TRUE; } return FALSE; }
/******************************Private*Routine*****************************\
* dciCreateSurface * * History: 1-Aug-1998 Jerry Van Aken [jvanaken] wrote it. \**************************************************************************/
static BOOL bDestroySurface(PDCIMAN_SURF pPrivate) { DDHAL_DESTROYSURFACEDATA dsd;
dsd.lpDD = pPrivate->SurfaceGlobal.lpDD; dsd.lpDDSurface = &pPrivate->SurfaceLocal; dsd.ddRVal = DDERR_GENERIC; dsd.DestroySurface = pPrivate->DDSurfaceCallbacks.DestroySurface;
if ((pPrivate->DDSurfaceCallbacks.dwFlags & DDHAL_SURFCB32_DESTROYSURFACE) && (dsd.DestroySurface != NULL) && ((*dsd.DestroySurface)(&dsd) == DDHAL_DRIVER_HANDLED) && (dsd.ddRVal == DD_OK)) { return TRUE; } return FALSE; }
/******************************Public*Routine******************************\
* DciOpenProvider * * History: 1-Aug-1998 Jerry Van Aken [jvanaken] added multimon support. \**************************************************************************/
HDC WINAPI DCIOpenProvider( void ) { HANDLE h; DWORD iDevice; BOOL (WINAPI *pfnEnum)(LPVOID, DWORD, DISPLAY_DEVICEW *, DWORD); int cMonitors = GetSystemMetrics(SM_CMONITORS);
if (cMonitors <= 1) { //
// This is a single-monitor system.
//
return CreateDCW(L"Display", NULL, NULL, NULL); }
//
// This is a multimon system. Get the DC for the primary monitor.
//
h = GetModuleHandle("user32.dll");
(FARPROC)pfnEnum = GetProcAddress(h, "EnumDisplayDevicesW");
if (pfnEnum == NULL) { return NULL; }
for (iDevice = 0; iDevice < (DWORD)cMonitors; ++iDevice) { DISPLAY_DEVICEW dd;
ZeroMemory(&dd, sizeof(dd)); dd.cb = sizeof(dd);
if (!(*pfnEnum)(NULL, iDevice, &dd, 0)) { return NULL; }
if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) { //
// Return the DC for the primary monitor.
//
return CreateDCW(NULL, dd.DeviceName, NULL, NULL); } }
return NULL; }
/******************************Public*Routine******************************\
* DciCloseProvider * * History: \**************************************************************************/
void WINAPI DCICloseProvider( HDC hdc ) { DeleteDC(hdc); }
/******************************Public*Routine******************************\
* DciEnum * * History: \**************************************************************************/
int WINAPI DCIEnum( HDC hdc, LPRECT lprDst, LPRECT lprSrc, LPVOID lpFnCallback, LPVOID lpContext ) { return DCI_FAIL_UNSUPPORTED; }
/******************************Public*Routine******************************\
* DciCreatePrimarySurface * * History: \**************************************************************************/
int WINAPI DCICreatePrimary( HDC hdc, LPDCISURFACEINFO *lplpSurface ) { int iRet; LPDCISURFACEINFO lpSurface; PDCIMAN_SURF pPrivate; DDHALINFO HalInfo; DDHAL_DDCALLBACKS DDCallbacks; DDHAL_DDPALETTECALLBACKS DDPaletteCallbacks; BOOL NewMode;
*lplpSurface = NULL; iRet = DCI_FAIL_GENERIC;
pPrivate = (PDCIMAN_SURF) LocalAlloc(LMEM_ZEROINIT, sizeof(DCIMAN_SURF) + sizeof(DCISURFACEINFO)); if (pPrivate != NULL) { //
// We store private DCIMAN information in the DCIMAN_SURF structure
// that immediately preceeds the DCISURFACEINFO structure we'll give
// out.
//
lpSurface = (LPDCISURFACEINFO) (pPrivate + 1);
if (DdCreateDirectDrawObject(&pPrivate->DirectDrawGlobal, hdc)) { if (DdReenableDirectDrawObject(&pPrivate->DirectDrawGlobal, &NewMode) && DdQueryDirectDrawObject(&pPrivate->DirectDrawGlobal, &HalInfo, &pPrivate->DDCallbacks, &pPrivate->DDSurfaceCallbacks, &DDPaletteCallbacks, NULL, NULL, NULL, NULL, NULL, NULL)) { //
// Build the required DirectDraw links for the 'global' and
// 'local' surfaces.
//
pPrivate->SurfaceLost = FALSE; pPrivate->DirectDrawGlobal.vmiData = HalInfo.vmiData; pPrivate->SurfaceLocal.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; pPrivate->SurfaceLocal.lpGbl = &pPrivate->SurfaceGlobal; pPrivate->SurfaceLocal.hDDSurface = 0; pPrivate->SurfaceGlobal.lpDD = &pPrivate->DirectDrawGlobal; pPrivate->SurfaceGlobal.wHeight = (WORD) HalInfo.vmiData.dwDisplayHeight; pPrivate->SurfaceGlobal.wWidth = (WORD) HalInfo.vmiData.dwDisplayWidth; pPrivate->SurfaceGlobal.lPitch = HalInfo.vmiData.lDisplayPitch;
if (bCreateSurface(pPrivate)) { //
// Associate an hwnd of '-1' with this surface to let the
// kernel know that the application may be drawing to any
// window, so Visrgn notifications should happen when any
// window changes.
//
if (DdResetVisrgn(&pPrivate->SurfaceLocal, (HWND) -1)) { lpSurface->dwSize = sizeof(DCISURFACEINFO);
if (HalInfo.vmiData.ddpfDisplay.dwRGBBitCount <= 8) { lpSurface->dwCompression = BI_RGB; } else { lpSurface->dwCompression = BI_BITFIELDS; }
lpSurface->dwDCICaps = DCI_PRIMARY | DCI_VISIBLE; lpSurface->dwMask[0] = HalInfo.vmiData.ddpfDisplay.dwRBitMask; lpSurface->dwMask[1] = HalInfo.vmiData.ddpfDisplay.dwGBitMask; lpSurface->dwMask[2] = HalInfo.vmiData.ddpfDisplay.dwBBitMask; lpSurface->dwWidth = HalInfo.vmiData.dwDisplayWidth; lpSurface->dwHeight = HalInfo.vmiData.dwDisplayHeight; lpSurface->lStride = HalInfo.vmiData.lDisplayPitch; lpSurface->dwBitCount = HalInfo.vmiData.ddpfDisplay.dwRGBBitCount; lpSurface->dwOffSurface = 0; lpSurface->wSelSurface = 0; lpSurface->wReserved = 0; lpSurface->dwReserved1 = 0; lpSurface->dwReserved2 = 0; lpSurface->dwReserved3 = 0; lpSurface->BeginAccess = NULL; lpSurface->EndAccess = NULL; lpSurface->DestroySurface = NULL;
*lplpSurface = lpSurface; return(DCI_OK); }
//
// The call to DdResetVisrgn failed.
//
bDestroySurface(pPrivate); } } else { //
// DirectDraw is not supported on this device.
//
iRet = DCI_FAIL_UNSUPPORTED; }
DdDeleteDirectDrawObject(&pPrivate->DirectDrawGlobal); } else { //
// DirectDraw is not supported on this device.
//
iRet = DCI_FAIL_UNSUPPORTED; }
LocalFree(pPrivate); } else { //
// Can't allocate memory for PDCIMAN_SURF struct.
//
iRet = DCI_ERR_OUTOFMEMORY; }
*lplpSurface = NULL;
return iRet; }
/******************************Public*Routine******************************\
* GdiDciCreateOffscreenSurface * * Stub to call CreateOffscreenSurface * * History: \**************************************************************************/
int WINAPI DCICreateOffscreen( HDC hdc, DWORD dwCompression, DWORD dwRedMask, DWORD dwGreenMask, DWORD dwBlueMask, DWORD dwWidth, DWORD dwHeight, DWORD dwDCICaps, DWORD dwBitCount, LPDCIOFFSCREEN *lplpSurface ) { return DCI_FAIL_UNSUPPORTED; }
/******************************Public*Routine******************************\
* DciCreateOverlay * * History: \**************************************************************************/
int WINAPI DCICreateOverlay( HDC hdc, LPVOID lpOffscreenSurf, LPDCIOVERLAY FAR *lplpSurface ) { return DCI_FAIL_UNSUPPORTED; }
/******************************Public*Routine******************************\
* WinWatchOpen * * History: \**************************************************************************/
HWINWATCH WINAPI WinWatchOpen( HWND hwnd ) { HDC hdc; PWINWATCH pwatch;
EnterCriticalSection(&gcsWinWatchLock);
pwatch = (PWINWATCH) LocalAlloc(LPTR, sizeof(WINWATCH));
if (pwatch) { pwatch->hwnd = hwnd; pwatch->changed = FALSE; pwatch->lprgndataSize = 0; pwatch->lprgndata = NULL;
//
// Add this to the head of the list.
//
pwatch->pWinWatchNext = gpWinWatchList; gpWinWatchList = pwatch; }
LeaveCriticalSection(&gcsWinWatchLock);
return (HWINWATCH) (pwatch); }
/******************************Public*Routine******************************\
* WinWatchClose * * History: \**************************************************************************/
void WINAPI WinWatchClose( HWINWATCH hWW ) { PWINWATCH pwatch = (PWINWATCH) hWW; PWINWATCH ptmp;
EnterCriticalSection(&gcsWinWatchLock);
if (gpWinWatchList == pwatch) { //
// The specified winwatch is at the head of the list.
//
gpWinWatchList = pwatch->pWinWatchNext; LocalFree(pwatch->lprgndata); LocalFree(pwatch); } else { for (ptmp = gpWinWatchList; ptmp != NULL; ptmp = ptmp->pWinWatchNext) { if (ptmp->pWinWatchNext == pwatch) { //
// We've found the specified winwatch in the list.
//
ptmp->pWinWatchNext = pwatch->pWinWatchNext; LocalFree(pwatch->lprgndata); LocalFree(pwatch);
break; } } }
LeaveCriticalSection(&gcsWinWatchLock); }
/******************************Public*Routine******************************\
* WinWatchGetClipList * * History: \**************************************************************************/
UINT WINAPI WinWatchGetClipList( HWINWATCH hWW, LPRECT prc, // May be NULL
UINT size, LPRGNDATA prd ) { PWINWATCH pwatch = (PWINWATCH) hWW; DWORD dwSize; DWORD dwNewSize; UINT dwRet;
//
// The first time after the VisRgn has changed, we download and
// cache a copy of the clipping region. We do this because the VisRgn
// can change under our implementation even between doing a BeginAccess/
// EndAccess, and we should at least maintain a consistent copy of what
// we think is the current VisRgn.
//
// Mostly, we do this so that the following scenario doesn't happen:
//
// 1. The app calls WinWatchGetClipList to ascertain the clip size;
// 2. The VisRgn gets more complex;
// 3. The app then calls WinWatchGetClipList with a buffer size
// allocated from the return code of step 1., and the call fails
// because now the buffer isn't long enough. The problem is that
// most applications probably wouldn't expect this second call to
// fail, and so would keep on using what is now a completely invalid
// region buffer.
//
if (pwatch->changed) { pwatch->changed = FALSE;
//
// Assume failure.
//
pwatch->lprgndataSize = 0;
dwSize = GetWindowRegionData(pwatch->hwnd, 0, NULL);
if (dwSize != 0) {
Try_Again:
if (pwatch->lprgndata != NULL) { LocalFree(pwatch->lprgndata); }
pwatch->lprgndata = LocalAlloc(0, dwSize);
if (pwatch->lprgndata != NULL) { dwNewSize = GetWindowRegionData(pwatch->hwnd, dwSize, pwatch->lprgndata);
if (dwNewSize == dwSize) { //
// Success! (Note that the docs are wrong and NT does
// not return '1' for success -- it returns the size
// of the buffer.)
//
pwatch->lprgndataSize = dwSize; } else if (dwSize != 0) { //
// Since dwSize is not zero, which would indicate failure
// or success, then we know that the clipping region grew
// in size between the time we queried the size and the
// time we tried to download it. This is a pretty rare
// event, and the chances of it happening again are slight
// (it's more likely that it will shrink the second time,
// anyway), so we just try it again.
//
dwSize = dwNewSize;
goto Try_Again; } } } }
//
// Now use the cached copy to handle any queries.
//
dwRet = 0;
if (size < pwatch->lprgndataSize) { dwRet = pwatch->lprgndataSize; } else { if (pwatch->lprgndataSize != 0) { RtlCopyMemory(prd, pwatch->lprgndata, pwatch->lprgndataSize); dwRet = 1; } }
return dwRet; }
/******************************Public*Routine******************************\
* WinWatchDidStatusChange * * History: \**************************************************************************/
BOOL WINAPI WinWatchDidStatusChange( HWINWATCH hWW ) { PWINWATCH pwatch = (PWINWATCH) hWW;
return pwatch->changed; }
/******************************Public*Routine******************************\
* GetWindowRegionData * * History: \**************************************************************************/
DWORD WINAPI GetWindowRegionData( HWND hwnd, DWORD size, LPRGNDATA prd ) { HDC hdc; DWORD dwRet = 0;
hdc = GetDC(hwnd); if (hdc) { dwRet = GetDCRegionData(hdc, size, prd); ReleaseDC(hwnd, hdc); }
return dwRet; }
/******************************Public*Routine******************************\
* GetDCRegionData * * History: \**************************************************************************/
DWORD WINAPI GetDCRegionData( HDC hdc, DWORD size, LPRGNDATA prd ) { HRGN hrgn; DWORD num; LPRGNDATA lpdata;
hrgn = CreateRectRgn(0, 0, 0, 0); if (hrgn == NULL) { WARNING("GetDCRegionData - CreateRectRgn failed.\n"); return 0; }
GetRandomRgn(hdc, hrgn, 4);
num = GetRegionData(hrgn, size, prd);
DeleteObject(hrgn); return num; }
/******************************Public*Routine******************************\
* WinWatchNotify * * History: \**************************************************************************/
BOOL WINAPI WinWatchNotify( HWINWATCH hWW, WINWATCHNOTIFYPROC NotifyCallback, LPARAM NotifyParam ) { return FALSE; }
/******************************Private*Routine*****************************\
* bDisplayModeChanged * * History: 9-Feb-1999 John Stephens [johnstep] wrote it. \**************************************************************************/
static BOOL bDisplayModeChanged(PDCIMAN_SURF pPrivate) { LPDCISURFACEINFO lpSurface; DDHALINFO HalInfo; lpSurface = (LPDCISURFACEINFO) (pPrivate + 1); if (DdQueryDirectDrawObject(&pPrivate->DirectDrawGlobal, &HalInfo, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) {
return (lpSurface->dwWidth != HalInfo.vmiData.dwDisplayWidth) || (lpSurface->dwHeight != HalInfo.vmiData.dwDisplayHeight) || (lpSurface->lStride != HalInfo.vmiData.lDisplayPitch) || (lpSurface->dwBitCount != HalInfo.vmiData.ddpfDisplay.dwRGBBitCount); }
//
// If we cannot even query the DirectDraw object, then we cannot make any
// assumptions about the current display mode, so it may have changed.
//
return TRUE; }
/******************************Public*Routine******************************\
* DciBeginAccess * * History: \**************************************************************************/
DCIRVAL WINAPI DCIBeginAccess( LPDCISURFACEINFO lpSurface, int x, int y, int dx, int dy ) { DCIRVAL iRet; PDCIMAN_SURF pPrivate; DDHAL_LOCKDATA LockData; BOOL NewMode; PWINWATCH pwatch;
iRet = DCI_FAIL_GENERIC;
pPrivate = ((PDCIMAN_SURF) lpSurface) - 1;
__try { //
// Fail if the mode changed.
//
if (pPrivate->SurfaceLost) { return DCI_FAIL_INVALIDSURFACE; }
LockData.lpDD = &pPrivate->DirectDrawGlobal; LockData.lpDDSurface = &pPrivate->SurfaceLocal; LockData.bHasRect = TRUE; LockData.rArea.left = x; LockData.rArea.top = y; LockData.rArea.right = x + dx; LockData.rArea.bottom = y + dy; LockData.dwFlags = DDLOCK_SURFACEMEMORYPTR;
//
// The DCI specification says we could return DCI_STATUS_WASSTILLDRAWING
// if the accelerator was still busy, but the previous release of DCI on
// Windows NT 3.51 did not support that feature, so we will endeavor to
// remain backwards compatible and do the wait explicitly on behalf of
// the application.
//
Try_Again:
do {
//
// Hold the DCI critical section while calling the kernel to do the
// lock because the kernel surface lock API does not have waiting
// semantics; it will fail if another thread is currently in the
// kernel locking the same surface. This is the expected behaviour
// for DirectDraw, but some clients of DCI -- OpenGL in particular --
// do not expect this. So we will protect them against themselves
// by acquiring the WinWatch lock before calling the kernel.
//
// This lock is also needed for traversing the WinWatchList.
//
EnterCriticalSection(&gcsWinWatchLock);
do { pPrivate->DDSurfaceCallbacks.Lock(&LockData);
} while (LockData.ddRVal == DDERR_WASSTILLDRAWING);
if (LockData.ddRVal == DDERR_VISRGNCHANGED) { if (!DdResetVisrgn(&pPrivate->SurfaceLocal, (HWND) -1)) { WARNING("DCIBeginAccess - ResetVisRgn failed\n"); }
//
// The VisRgn has changed, and we can't be sure what window it
// was for. So we'll mark all WinWatches as having dirty VisRgns.
// This effect of this is that some of the WinWatches will have to
// re-download their clipping information when they don't really
// have to because their specific window has not changed.
//
// Note that the WinWatchLock must be held here.
//
for (pwatch = gpWinWatchList; pwatch != NULL; pwatch = pwatch->pWinWatchNext) { pwatch->changed = TRUE; } }
LeaveCriticalSection(&gcsWinWatchLock);
} while (LockData.ddRVal == DDERR_VISRGNCHANGED);
//
// 'Surface Lost' means that some sort of mode change occured, and
// we have to re-enable DirectDraw.
//
if (LockData.ddRVal == DDERR_SURFACELOST) { if (!DdReenableDirectDrawObject(&pPrivate->DirectDrawGlobal, &NewMode)) { //
// We're still in full-screen mode:
//
iRet = DCI_ERR_SURFACEISOBSCURED; } else { if (!bDisplayModeChanged(pPrivate)) { //
// We switched back to the same mode. Now that we've re-enabled
// DirectDraw, we can try again:
//
bDestroySurface(pPrivate); if (bCreateSurface(pPrivate) && DdResetVisrgn(&pPrivate->SurfaceLocal, (HWND) -1)) { goto Try_Again; } else { WARNING("DCIBeginAccess - couldn't recreate surface.\n"); } }
//
// We can't reenable the surface, perhaps because a resolution
// switch or colour depth change occured. Mark this surface as
// unusable -- the application will have to reinitialize:
//
pPrivate->SurfaceLost = TRUE; iRet = DCI_FAIL_INVALIDSURFACE;
//
// Unmap the frame buffer now:
//
if (!bDestroySurface(pPrivate) || !DdDeleteDirectDrawObject(&pPrivate->DirectDrawGlobal)) { WARNING("DCIBeginAccess - failed to delete surface.\n"); } } }
if (LockData.ddRVal == DD_OK) { //
// Return the pointer to the frame buffer in the DCI structure.
// We always return DCI_STATUS_POINTERCHANGED because it's possible
// that the Lock() call mapped the frame buffer to a different
// virtual address than it was previously.
//
lpSurface->wSelSurface = 0;
//
// DirectDraw has a goofy convention where it returns a pointer to
// the upper-left corner of the specified rectangle. We have to
// undo that for DCI:
//
lpSurface->dwOffSurface = (ULONG_PTR) LockData.lpSurfData - (y * lpSurface->lStride) - (x * (lpSurface->dwBitCount >> 3));
iRet = DCI_STATUS_POINTERCHANGED; } } __except(EXCEPTION_EXECUTE_HANDLER) { WARNING("DCIBeginAccess - exception caused by invalid surface pointer.\n"); return DCI_FAIL_GENERIC; }
return iRet; }
/******************************Public*Routine******************************\
* DciEndAccess * * History: \**************************************************************************/
void WINAPI DCIEndAccess( LPDCISURFACEINFO pdci ) { DDHAL_UNLOCKDATA UnlockData; PDCIMAN_SURF pPrivate = ((PDCIMAN_SURF) pdci) - 1;
__try { if (!(pPrivate->SurfaceLost)) { UnlockData.lpDD = &pPrivate->DirectDrawGlobal; UnlockData.lpDDSurface = &pPrivate->SurfaceLocal;
//
// For the same reasons as stated in DCIBeginAccess, protect against
// two threads trying to unlock the same surface at the same time
// in kernel -- kernel would simply fail the call instead of waiting,
// and DCI apps won't expect that.
//
EnterCriticalSection(&gcsWinWatchLock);
pPrivate->DDSurfaceCallbacks.Unlock(&UnlockData);
LeaveCriticalSection(&gcsWinWatchLock);
if (UnlockData.ddRVal != DD_OK) { WARNING("DCIEndAccess - failed Unlock\n"); } }
//
// The application shouldn't try to access the frame buffer after
// after having called EndAccess.
//
pdci->wSelSurface = 0; pdci->dwOffSurface = 0; } __except(EXCEPTION_EXECUTE_HANDLER) { WARNING("DCIEndAccess - exception caused by invalid surface pointer.\n"); } }
/******************************Public*Routine******************************\
* DciDestroy * * History: \**************************************************************************/
void WINAPI DCIDestroy( LPDCISURFACEINFO pdci ) { PDCIMAN_SURF pPrivate;
if (pdci != NULL) { pPrivate = ((PDCIMAN_SURF) pdci) - 1;
if (!(pPrivate->SurfaceLost)) { DDHAL_DESTROYSURFACEDATA dsd;
dsd.lpDD = pPrivate->SurfaceGlobal.lpDD; dsd.lpDDSurface = &pPrivate->SurfaceLocal; dsd.ddRVal = DDERR_GENERIC; dsd.DestroySurface = pPrivate->DDSurfaceCallbacks.DestroySurface;
if (!(pPrivate->DDSurfaceCallbacks.dwFlags & DDHAL_SURFCB32_DESTROYSURFACE) || (dsd.DestroySurface == NULL) || ((*dsd.DestroySurface)(&dsd) != DDHAL_DRIVER_HANDLED) || !DdDeleteDirectDrawObject(&pPrivate->DirectDrawGlobal)) { WARNING("DCIDestroy - failed to delete surface.\n"); } }
LocalFree(pPrivate); } }
DCIRVAL WINAPI DCIDraw( LPDCIOFFSCREEN pdci ) { return DCI_FAIL_UNSUPPORTED; }
DCIRVAL WINAPI DCISetClipList( LPDCIOFFSCREEN pdci, LPRGNDATA prd ) { return DCI_FAIL_UNSUPPORTED; }
DCIRVAL WINAPI DCISetDestination( LPDCIOFFSCREEN pdci, LPRECT dst, LPRECT src ) { return DCI_FAIL_UNSUPPORTED; }
DCIRVAL WINAPI DCISetSrcDestClip( LPDCIOFFSCREEN pdci, LPRECT srcrc, LPRECT destrc, LPRGNDATA prd ) { return DCI_FAIL_UNSUPPORTED; }
|