Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4061 lines
135 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: dvpe.cxx
  3. *
  4. * Contains all of GDI's private VideoPort APIs.
  5. *
  6. * Note that for videoport support, WIN32K.SYS and DXAPI.SYS are closely
  7. * linked. DXAPI.SYS provides two services:
  8. *
  9. * 1. It handles the "software autoflipping" support for the videoports,
  10. * where the CPU handles the videoport field-done interrupt to
  11. * flip the overlay and do "bob" and "weave" for better video
  12. * quality.
  13. * 2. It provides the public DirectDraw entry points that are callable
  14. * by other kernel-mode WDM drivers (there is a corresponding DXAPI.SYS
  15. * module on Memphis/Win95 that exposes the same interface).
  16. *
  17. * All of the non-paged code for videoports has to go into DXAPI.SYS since
  18. * WIN32K.SYS is marked entirely as pageable. WIN32K.SYS handles some
  19. * functionality on behalf of DXAPI.SYS, such as object opens and closes,
  20. * since only WIN32K.SYS can access GDI's handle table.
  21. *
  22. * Created: 17-Oct-1996
  23. * Author: Lingyun Wang [LingyunW]
  24. *
  25. * Copyright (c) 1996-1999 Microsoft Corporation
  26. *
  27. \**************************************************************************/
  28. #include "precomp.hxx"
  29. extern PEPROCESS gpepSession;
  30. VOID
  31. vDdDxApiFreeDirectDraw(
  32. DXOBJ* pDxObj,
  33. BOOL bDoCallBack
  34. );
  35. /////////////////////////////////////////////////////////////////////////
  36. // DXAPI concerns:
  37. //
  38. // - Document that call-back may not occur in context of same process
  39. // - Refuse to open surface, videoport objects while full-screen
  40. // Keep DirectDraw open so that POSTFULLSCREEN and DOSBOX can be honored
  41. // - See InitKernelInterface for init restrictions
  42. // - Flush DMA buffer before mode changes?
  43. // - Invalidate dxapi data after mode change?
  44. // - Right now, DirectDraw DXAPI objects have to be closed last
  45. /////////////////////////////////////////////////////////////////////////
  46. // VPE concerns:
  47. //
  48. // - Make sure VideoPort's not duplicated on same device
  49. // - Document that display driver cannot use pool-allocated memory for
  50. // dwReserved fields on Synchronize calls
  51. // - Close DxVideoPort objects on full-screen switch?
  52. // No, to support hardware that can DMA even while full-screen!
  53. // Okay, but what about mode changes? There's no way they'll not
  54. // be able to drop frames
  55. // - Never close DxDirectDraw objects?
  56. /*****************************Private*Routine******************************\
  57. * ULONG vDdNullCallBack
  58. *
  59. * The DXAPI register routines require a close call-back routine to notify
  60. * the client that the object is going away. Since we're really DirectDraw,
  61. * we already know when the object is going away; hence, this routine doesn't
  62. * need to do anything.
  63. *
  64. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  65. * Wrote it.
  66. \**************************************************************************/
  67. ULONG
  68. vDdNullCallBack(
  69. DWORD dwFlags,
  70. PVOID pContext,
  71. DWORD dwParam1,
  72. DWORD dwParam2
  73. )
  74. {
  75. return 0;
  76. }
  77. /*****************************Private*Routine******************************\
  78. * VOID vDdUnloadDxApiImage
  79. *
  80. * This routine performs the actual unload of DXAPI.SYS.
  81. *
  82. * 28-Oct-1997 -by- smac
  83. * Wrote it.
  84. \**************************************************************************/
  85. VOID
  86. vDdUnloadDxApiImage(
  87. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal
  88. )
  89. {
  90. EDD_VIDEOPORT* peVideoPort;
  91. EDD_VIDEOPORT* peVideoPortNext;
  92. EDD_SURFACE* peSurface;
  93. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal;
  94. DD_ASSERTDEVLOCK(peDirectDrawGlobal);
  95. // Notify clients that the resources are lost and clean up
  96. for (peDirectDrawLocal = peDirectDrawGlobal->peDirectDrawLocalList;
  97. peDirectDrawLocal != NULL;
  98. peDirectDrawLocal = peDirectDrawLocal->peDirectDrawLocalNext)
  99. {
  100. // If any video port still exist (which should not be the case)
  101. // delete all of the video port objects since the video port assumes
  102. // that DXAPI.SYS is loaded.
  103. for (peVideoPort = peDirectDrawLocal->peVideoPort_DdList;
  104. peVideoPort != NULL;
  105. peVideoPort = peVideoPortNext)
  106. {
  107. // Don't reference peVideoPort after it's been deleted!
  108. peVideoPortNext = peVideoPort->peVideoPort_DdNext;
  109. bDdDeleteVideoPortObject(peVideoPort->hGet(), NULL);
  110. }
  111. // If a surface still has a client using it, shut it down.
  112. peSurface = peDirectDrawLocal->peSurface_Enum(NULL);
  113. while (peSurface)
  114. {
  115. if (peSurface->hSurface != NULL)
  116. {
  117. vDdDxApiFreeSurface( (DXOBJ*) peSurface->hSurface, FALSE );
  118. peSurface->hSurface = NULL;
  119. }
  120. if( peSurface->peDxSurface != NULL )
  121. {
  122. vDdLoseDxObjects( peDirectDrawGlobal,
  123. peSurface->peDxSurface->pDxObj_List,
  124. (PVOID) peSurface->peDxSurface,
  125. LO_SURFACE );
  126. }
  127. peSurface = peDirectDrawLocal->peSurface_Enum(peSurface);
  128. }
  129. }
  130. if (peDirectDrawGlobal->hDirectDraw != NULL)
  131. {
  132. vDdDxApiFreeDirectDraw( (DXOBJ*) peDirectDrawGlobal->hDirectDraw, FALSE );
  133. }
  134. if( peDirectDrawGlobal->peDxDirectDraw != NULL )
  135. {
  136. vDdLoseDxObjects( peDirectDrawGlobal,
  137. peDirectDrawGlobal->peDxDirectDraw->pDxObj_List,
  138. (PVOID) peDirectDrawGlobal->peDxDirectDraw,
  139. LO_DIRECTDRAW );
  140. }
  141. EngUnloadImage(peDirectDrawGlobal->hDxApi);
  142. //
  143. // Free the memory associate with the module
  144. //
  145. peDirectDrawGlobal->hDxApi = NULL;
  146. peDirectDrawGlobal->dwDxApiRefCnt = 0;
  147. }
  148. /*****************************Private*Routine******************************\
  149. * BOOL bDdLoadDxApi
  150. *
  151. * This routine loads up DXAPI.SYS and allocates the non-paged DXAPI
  152. * structures.
  153. *
  154. * Returns: FALSE only if a DXAPI resource could not be allocated.
  155. *
  156. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  157. * Wrote it.
  158. * 16-Oct-1977 -by- smac
  159. * Broke it out into a separate function.
  160. \**************************************************************************/
  161. BOOL
  162. bDdLoadDxApi(
  163. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal
  164. )
  165. {
  166. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  167. HANDLE hDxApi;
  168. PFNDXAPIINITIALIZE pfnDxApiInitialize;
  169. DDOPENDIRECTDRAWIN OpenDirectDrawIn;
  170. DDOPENDIRECTDRAWOUT OpenDirectDrawOut;
  171. DWORD dwRet;
  172. DD_ASSERTDEVLOCK(peDirectDrawLocal->peDirectDrawGlobal);
  173. peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
  174. /*
  175. * Don't load if it's already loaded
  176. */
  177. if (peDirectDrawGlobal->hDxApi == NULL)
  178. {
  179. ASSERTGDI((peDirectDrawGlobal->hDirectDraw == NULL) &&
  180. (peDirectDrawGlobal->hDxApi == NULL),
  181. "Expected NULL hDirectDraw and hDxApi");
  182. BOOL loaded;
  183. hDxApi = DxEngLoadImage(L"drivers\\dxapi.sys",FALSE);
  184. if (hDxApi)
  185. {
  186. peDirectDrawGlobal->hDxApi = hDxApi;
  187. peDirectDrawGlobal->pfnDxApi = (LPDXAPI)
  188. EngFindImageProcAddress(hDxApi, "_DxApi");
  189. peDirectDrawGlobal->pfnAutoflipUpdate = (PFNAUTOFLIPUPDATE)
  190. EngFindImageProcAddress(hDxApi, "_DxAutoflipUpdate");
  191. peDirectDrawGlobal->pfnLoseObject = (PFNLOSEOBJECT)
  192. EngFindImageProcAddress(hDxApi, "_DxLoseObject");
  193. pfnDxApiInitialize = (PFNDXAPIINITIALIZE)
  194. EngFindImageProcAddress(hDxApi, "_DxApiInitialize");
  195. peDirectDrawGlobal->pfnEnableIRQ = (PFNENABLEIRQ)
  196. EngFindImageProcAddress(hDxApi, "_DxEnableIRQ");
  197. peDirectDrawGlobal->pfnUpdateCapture = (PFNUPDATECAPTURE)
  198. EngFindImageProcAddress(hDxApi, "_DxUpdateCapture");
  199. ASSERTGDI(peDirectDrawGlobal->pfnDxApi != NULL,
  200. "Couldn't find DxApi'");
  201. ASSERTGDI(peDirectDrawGlobal->pfnAutoflipUpdate != NULL,
  202. "Couldn't find DxAutoflipUpdate");
  203. ASSERTGDI(peDirectDrawGlobal->pfnLoseObject != NULL,
  204. "Couldn't find DxLoseObject");
  205. ASSERTGDI(peDirectDrawGlobal->pfnEnableIRQ != NULL,
  206. "Couldn't find DxEnableIRQ");
  207. ASSERTGDI(peDirectDrawGlobal->pfnUpdateCapture != NULL,
  208. "Couldn't find DxUpdateCapture");
  209. ASSERTGDI(pfnDxApiInitialize != NULL,
  210. "Couldn't find DxApiInitialize");
  211. // By explicitly passing dxapi.sys its private win32k.sys
  212. // entry points, we don't have to export them from win32k.sys,
  213. // thus preventing any drivers from using those entry points
  214. // for their own nefarious purposes.
  215. pfnDxApiInitialize(DdDxApiOpenDirectDraw,
  216. DdDxApiOpenVideoPort,
  217. DdDxApiOpenSurface,
  218. DdDxApiCloseHandle,
  219. DdDxApiGetKernelCaps,
  220. DdDxApiOpenCaptureDevice,
  221. DdDxApiLockDevice,
  222. DdDxApiUnlockDevice);
  223. // EngLoadImage always makes the entire driver pageable, but
  224. // DXAPI.SYS handles the DPC for the videoport interrupt and
  225. // so cannot be entirely pageable. Consequently, we reset
  226. // the paging now:
  227. MmResetDriverPaging(pfnDxApiInitialize);
  228. // Now open the DXAPI version of DirectDraw:
  229. OpenDirectDrawIn.pfnDirectDrawClose = vDdNullCallBack;
  230. OpenDirectDrawIn.pContext = NULL;
  231. OpenDirectDrawIn.dwDirectDrawHandle
  232. = (ULONG_PTR) peDirectDrawLocal->hGet();
  233. peDirectDrawGlobal->pfnDxApi(DD_DXAPI_OPENDIRECTDRAW,
  234. &OpenDirectDrawIn,
  235. sizeof(OpenDirectDrawIn),
  236. &OpenDirectDrawOut,
  237. sizeof(OpenDirectDrawOut));
  238. if (OpenDirectDrawOut.ddRVal == DD_OK)
  239. {
  240. // Success!
  241. peDirectDrawGlobal->hDirectDraw = OpenDirectDrawOut.hDirectDraw;
  242. }
  243. peDirectDrawGlobal->dwDxApiRefCnt = 1;
  244. }
  245. else
  246. {
  247. WARNING("bDdLoadDxApi: Couldn't load dxapi.sys\n");
  248. return(FALSE);
  249. }
  250. }
  251. else
  252. {
  253. peDirectDrawGlobal->dwDxApiRefCnt++;
  254. }
  255. return(TRUE);
  256. }
  257. /*****************************Private*Routine******************************\
  258. * VOID vDdUnloadDxApi
  259. *
  260. * This routine unloads DXAPI.SYS
  261. *
  262. * 22-Oct-1997 -by- smac
  263. \**************************************************************************/
  264. VOID
  265. vDdUnloadDxApi(
  266. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal
  267. )
  268. {
  269. DDCLOSEHANDLE CloseHandle;
  270. DWORD dwRet;
  271. if ((peDirectDrawGlobal->hDxApi != NULL) &&
  272. (peDirectDrawGlobal->dwDxApiRefCnt > 0 ))
  273. {
  274. if( --peDirectDrawGlobal->dwDxApiRefCnt == 0 )
  275. {
  276. if (peDirectDrawGlobal->hDirectDraw != NULL)
  277. {
  278. CloseHandle.hHandle = peDirectDrawGlobal->hDirectDraw;
  279. peDirectDrawGlobal->pfnDxApi(DD_DXAPI_CLOSEHANDLE,
  280. &CloseHandle,
  281. sizeof(CloseHandle),
  282. &dwRet,
  283. sizeof(dwRet));
  284. ASSERTGDI(dwRet == DD_OK, "Unexpected failure from close");
  285. peDirectDrawGlobal->hDirectDraw = NULL;
  286. }
  287. vDdUnloadDxApiImage( peDirectDrawGlobal );
  288. }
  289. }
  290. }
  291. /*****************************Private*Routine******************************\
  292. * BOOL bDdEnableSoftwareAutoflipping
  293. *
  294. * This routine loads up DXAPI.SYS, allocates the non-paged DXAPI structures
  295. * required for software autoflipping, and enables the videoport interrupt.
  296. *
  297. * Returns: FALSE only if a DXAPI resource could not be allocated. May
  298. * return TRUE even if the interrupt hasn't been successfully
  299. * enabled (because I expect that interrupts will be usable
  300. * on the majority of systems that support videoports, and this
  301. * simplifies other code by allowing it to assume that all the
  302. * DXAPI structures have been allocated).
  303. *
  304. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  305. * Wrote it.
  306. \**************************************************************************/
  307. BOOL
  308. bDdEnableSoftwareAutoflipping(
  309. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal,
  310. EDD_VIDEOPORT* peVideoPort,
  311. DWORD dwVideoPortID,
  312. BOOL bFirst
  313. )
  314. {
  315. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  316. HANDLE hDxApi;
  317. PFNDXAPIINITIALIZE pfnDxApiInitialize;
  318. DDOPENDIRECTDRAWIN OpenDirectDrawIn;
  319. DDOPENDIRECTDRAWOUT OpenDirectDrawOut;
  320. DDOPENVIDEOPORTIN OpenVideoPortIn;
  321. DDOPENVIDEOPORTOUT OpenVideoPortOut;
  322. DWORD dwRet;
  323. UNICODE_STRING UnicodeString;
  324. DD_ASSERTDEVLOCK(peVideoPort->peDirectDrawGlobal);
  325. peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
  326. // Create a DXAPI DirectDraw object, which we'll need for software
  327. // autoflipping.
  328. if (bFirst)
  329. {
  330. bDdLoadDxApi( peDirectDrawLocal );
  331. }
  332. if (peDirectDrawGlobal->hDirectDraw != NULL)
  333. {
  334. ASSERTGDI(peVideoPort->hVideoPort == NULL, "Expected NULL hVideoPort");
  335. OpenVideoPortIn.hDirectDraw = peDirectDrawGlobal->hDirectDraw;
  336. OpenVideoPortIn.pfnVideoPortClose = vDdNullCallBack;
  337. OpenVideoPortIn.pContext = NULL;
  338. OpenVideoPortIn.dwVideoPortHandle = dwVideoPortID;
  339. peDirectDrawGlobal->pfnDxApi(DD_DXAPI_OPENVIDEOPORT,
  340. &OpenVideoPortIn,
  341. sizeof(OpenVideoPortIn),
  342. &OpenVideoPortOut,
  343. sizeof(OpenVideoPortOut));
  344. if (OpenVideoPortOut.ddRVal == DD_OK)
  345. {
  346. peVideoPort->hVideoPort = OpenVideoPortOut.hVideoPort;
  347. return(TRUE);
  348. }
  349. }
  350. return(FALSE);
  351. }
  352. /******************************Public*Routine******************************\
  353. * VOID vDdNotifyEvent
  354. *
  355. * This routine calls back to all registered DXAPI clients when a particular
  356. * event (like mode change notification) occurs.
  357. *
  358. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  359. * Wrote it.
  360. \**************************************************************************/
  361. VOID
  362. vDdNotifyEvent(
  363. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal,
  364. DWORD dwEvent
  365. )
  366. {
  367. EDD_DXDIRECTDRAW* peDxDirectDraw;
  368. DXAPI_EVENT* pDxEvent;
  369. peDxDirectDraw = peDirectDrawGlobal->peDxDirectDraw;
  370. if (peDxDirectDraw != NULL)
  371. {
  372. DD_ASSERTDEVLOCK(peDirectDrawGlobal);
  373. for (pDxEvent = peDxDirectDraw->pDxEvent_PassiveList;
  374. pDxEvent != NULL;
  375. pDxEvent = pDxEvent->pDxEvent_Next)
  376. {
  377. if (pDxEvent->dwEvent == dwEvent)
  378. {
  379. pDxEvent->pfnCallBack(pDxEvent->dwEvent,pDxEvent->pContext, 0, 0);
  380. }
  381. }
  382. }
  383. }
  384. /******************************Public*Routine******************************\
  385. * DXAPI_OBJECT* pDdDxObjHandleAllocate
  386. *
  387. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  388. * Wrote it.
  389. \**************************************************************************/
  390. DXOBJ*
  391. pDdDxObjHandleAllocate(
  392. DXTYPE iDxType,
  393. LPDD_NOTIFYCALLBACK pfnClose,
  394. DWORD dwEvent,
  395. PVOID pvContext
  396. )
  397. {
  398. DXOBJ* pDxObj;
  399. ASSERTGDI(pfnClose != NULL,
  400. "pDdDxObjHandleAllocate: DXAPI client must supply Close function");
  401. pDxObj = (DXOBJ*) PALLOCNONPAGED(sizeof(*pDxObj),'xxdG');
  402. if (pDxObj != NULL)
  403. {
  404. pDxObj->iDxType = iDxType;
  405. pDxObj->pfnClose = pfnClose;
  406. pDxObj->pContext = pvContext;
  407. pDxObj->dwEvent = dwEvent;
  408. pDxObj->pDxObj_Next = NULL;
  409. pDxObj->dwFlags = 0;
  410. pDxObj->pepSession = gpepSession;
  411. }
  412. return(pDxObj);
  413. }
  414. // Should be macro for free build.
  415. PVOID
  416. pDdDxObjDataAllocate(
  417. ULONG cj,
  418. ULONG tag
  419. )
  420. {
  421. return (PALLOCNONPAGED(cj,tag));
  422. }
  423. VOID
  424. vDdDxObjFree(
  425. PVOID pvDxObj
  426. )
  427. {
  428. VFREEMEM(pvDxObj);
  429. }
  430. /******************************Public*Routine******************************\
  431. * VOID vDdQueryMiniportDxApiSupport
  432. *
  433. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  434. * Wrote it.
  435. \**************************************************************************/
  436. VOID
  437. vDdQueryMiniportDxApiSupport(
  438. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal
  439. )
  440. {
  441. BOOL bMiniportSupport;
  442. // Assume failure.
  443. bMiniportSupport = FALSE;
  444. if (bDdIoQueryInterface(peDirectDrawGlobal,
  445. &GUID_DxApi,
  446. sizeof(DXAPI_INTERFACE),
  447. DXAPI_HALVERSION,
  448. (INTERFACE *)&peDirectDrawGlobal->DxApiInterface))
  449. {
  450. ASSERTGDI((peDirectDrawGlobal->DxApiInterface.
  451. InterfaceReference == NULL) &&
  452. (peDirectDrawGlobal->DxApiInterface.
  453. InterfaceDereference == NULL),
  454. "Miniport shouldn't modify InterfaceReference/Dereference");
  455. // Assert some stuff about hooked entry points?
  456. peDirectDrawGlobal->HwDeviceExtension
  457. = peDirectDrawGlobal->DxApiInterface.Context;
  458. bMiniportSupport = TRUE;
  459. }
  460. // Even if the miniport doesn't support DXAPI accelerations, we still
  461. // allow DXAPI to work (the DXAPI Lock call doesn't require that the
  462. // miniport support DXAPI, for example).
  463. if (!bMiniportSupport)
  464. {
  465. // Zero out any capabilities:
  466. RtlZeroMemory(&peDirectDrawGlobal->DxApiInterface,
  467. sizeof(peDirectDrawGlobal->DxApiInterface));
  468. }
  469. }
  470. /******************************Public*Routine******************************\
  471. * DWORD vDdSynchronizeSurface
  472. *
  473. * Updates the EDD_DXSURFACE structure using the master EDD_SURFACE
  474. * structure, with some help from the driver.
  475. *
  476. * Analagous to Win95's SyncKernelSurface routine.
  477. *
  478. * This routine lets a driver use fields from the larger, pageable version
  479. * of the DD_SURFACE_* structures used by the display driver to set
  480. * fields in the smaller, non-pageable version of the corresponding
  481. * DDSURFACEDATA structure used by the miniport.
  482. *
  483. * NOTE: The display driver may NOT use the reserved fields to point to
  484. * allocated memory, for two reasons:
  485. *
  486. * 1. We don't call them when the surfaces is freed, so they'd
  487. * lose memory;
  488. * 2. We only let display drivers allocate paged memory, which
  489. * they can't use in the miniport since they'll be at raised
  490. * IRQL when we call them.
  491. *
  492. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  493. * Wrote it.
  494. \**************************************************************************/
  495. VOID
  496. vDdSynchronizeSurface(
  497. EDD_SURFACE* peSurface
  498. )
  499. {
  500. EDD_DXSURFACE* peDxSurface;
  501. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  502. DD_SYNCSURFACEDATA SyncSurfaceData;
  503. peDirectDrawGlobal = peSurface->peDirectDrawGlobal;
  504. peDxSurface = peSurface->peDxSurface;
  505. if (peDxSurface != NULL)
  506. {
  507. RtlZeroMemory(&SyncSurfaceData, sizeof(SyncSurfaceData));
  508. SyncSurfaceData.lpDD = peDirectDrawGlobal;
  509. SyncSurfaceData.lpDDSurface = peSurface;
  510. SyncSurfaceData.dwSurfaceOffset = (DWORD) peSurface->fpVidMem;
  511. SyncSurfaceData.fpLockPtr = peSurface->fpVidMem
  512. + (FLATPTR) peDirectDrawGlobal->HalInfo.vmiData.pvPrimary;
  513. SyncSurfaceData.lPitch = peSurface->lPitch;
  514. EDD_DEVLOCK eDevLock(peDirectDrawGlobal);
  515. // Call the driver to let it fill in the rest of the values:
  516. if ((!peDirectDrawGlobal->bSuspended) &&
  517. (peDirectDrawGlobal->DxApiCallBacks.SyncSurfaceData))
  518. {
  519. peDirectDrawGlobal->
  520. DxApiCallBacks.SyncSurfaceData(&SyncSurfaceData);
  521. }
  522. // Fields updated by the driver:
  523. peDxSurface->dwSurfaceOffset = SyncSurfaceData.dwSurfaceOffset;
  524. peDxSurface->fpLockPtr = SyncSurfaceData.fpLockPtr;
  525. peDxSurface->lPitch = SyncSurfaceData.lPitch;
  526. peDxSurface->dwOverlayOffset = SyncSurfaceData.dwOverlayOffset;
  527. peDxSurface->dwDriverReserved1 = SyncSurfaceData.dwDriverReserved1;
  528. peDxSurface->dwDriverReserved2 = SyncSurfaceData.dwDriverReserved2;
  529. peDxSurface->dwDriverReserved3 = SyncSurfaceData.dwDriverReserved3;
  530. peDxSurface->dwDriverReserved4 = SyncSurfaceData.dwDriverReserved4;
  531. // Fields taken straight from the surface structure:
  532. peDxSurface->ddsCaps = peSurface->ddsCaps.dwCaps;
  533. peDxSurface->dwWidth = peSurface->wWidth;
  534. peDxSurface->dwHeight = peSurface->wHeight;
  535. peDxSurface->dwOverlayFlags = peSurface->dwOverlayFlags;
  536. peDxSurface->dwFormatFlags = peSurface->ddpfSurface.dwFlags;
  537. peDxSurface->dwFormatFourCC = peSurface->ddpfSurface.dwFourCC;
  538. peDxSurface->dwFormatBitCount = peSurface->ddpfSurface.dwRGBBitCount;
  539. peDxSurface->dwRBitMask = peSurface->ddpfSurface.dwRBitMask;
  540. peDxSurface->dwGBitMask = peSurface->ddpfSurface.dwGBitMask;
  541. peDxSurface->dwBBitMask = peSurface->ddpfSurface.dwBBitMask;
  542. peDxSurface->dwOverlaySrcWidth = peSurface->dwOverlaySrcWidth;
  543. peDxSurface->dwOverlaySrcHeight = peSurface->dwOverlaySrcHeight;
  544. peDxSurface->dwOverlayDestWidth = peSurface->dwOverlayDestWidth;
  545. peDxSurface->dwOverlayDestHeight = peSurface->dwOverlayDestHeight;
  546. }
  547. }
  548. /******************************Public*Routine******************************\
  549. * DWORD vDdSynchronizeVideoPort
  550. *
  551. * Updates the EDD_DXVIDEOPORT structure using the master EDD_VIDEOPORT
  552. * structure, with some help from the driver.
  553. *
  554. * Analagous to Win95's SyncKernelVideoPort routine.
  555. *
  556. * This routine lets a driver use fields from the larger, pageable version
  557. * of the DD_VIDEOPORT_LOCAL structure used by the display driver to set
  558. * fields in the smaller, non-pageable version of the corresponding
  559. * DDVIDEOPORTDATA structure used by the miniport.
  560. *
  561. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  562. * Wrote it.
  563. \**************************************************************************/
  564. VOID
  565. vDdSynchronizeVideoPort(
  566. EDD_VIDEOPORT* peVideoPort
  567. )
  568. {
  569. EDD_DXVIDEOPORT* peDxVideoPort;
  570. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  571. DD_SYNCVIDEOPORTDATA SyncVideoPortData;
  572. peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
  573. peDxVideoPort = peVideoPort->peDxVideoPort;
  574. if (peDxVideoPort != NULL)
  575. {
  576. RtlZeroMemory(&SyncVideoPortData, sizeof(SyncVideoPortData));
  577. SyncVideoPortData.lpDD = peDirectDrawGlobal;
  578. SyncVideoPortData.lpVideoPort = peVideoPort;
  579. SyncVideoPortData.dwVBIHeight = peVideoPort->ddvpInfo.dwVBIHeight;
  580. if (peVideoPort->ddvpInfo.dwVPFlags & DDVP_PRESCALE)
  581. {
  582. SyncVideoPortData.dwHeight = peVideoPort->ddvpInfo.dwPrescaleHeight;
  583. }
  584. else if (peVideoPort->ddvpInfo.dwVPFlags & DDVP_CROP)
  585. {
  586. SyncVideoPortData.dwHeight = peVideoPort->ddvpInfo.rCrop.bottom -
  587. peVideoPort->ddvpInfo.rCrop.top;
  588. }
  589. else
  590. {
  591. SyncVideoPortData.dwHeight = peVideoPort->ddvpDesc.dwFieldHeight;
  592. }
  593. if (peVideoPort->ddvpInfo.dwVPFlags & DDVP_INTERLEAVE)
  594. {
  595. SyncVideoPortData.dwHeight *= 2;
  596. }
  597. EDD_DEVLOCK eDevLock(peDirectDrawGlobal);
  598. // Call the driver to let it fill in the rest of the values:
  599. if ((peDirectDrawGlobal->bSuspended) &&
  600. (peDirectDrawGlobal->DxApiCallBacks.SyncVideoPortData))
  601. {
  602. peDirectDrawGlobal->
  603. DxApiCallBacks.SyncVideoPortData(&SyncVideoPortData);
  604. }
  605. // Fields updated by the driver:
  606. peDxVideoPort->dwOriginOffset = SyncVideoPortData.dwOriginOffset;
  607. peDxVideoPort->dwHeight = SyncVideoPortData.dwHeight;
  608. peDxVideoPort->dwVBIHeight = SyncVideoPortData.dwVBIHeight;
  609. peDxVideoPort->dwDriverReserved1 = SyncVideoPortData.dwDriverReserved1;
  610. peDxVideoPort->dwDriverReserved2 = SyncVideoPortData.dwDriverReserved2;
  611. peDxVideoPort->dwDriverReserved3 = SyncVideoPortData.dwDriverReserved3;
  612. // Fields taken straight from the videoport structure:
  613. peDxVideoPort->dwVideoPortId = peVideoPort->ddvpDesc.dwVideoPortID;
  614. peDxVideoPort->dwVPFlags = peVideoPort->ddvpInfo.dwVPFlags;
  615. if( ( peDxVideoPort->dwVBIHeight > 0 ) &&
  616. ( peDxVideoPort->dwVPFlags & DDVP_INTERLEAVE ) &&
  617. !( peDxVideoPort->dwVPFlags & DDVP_VBINOINTERLEAVE ) )
  618. {
  619. peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_VBI_INTERLEAVED;
  620. }
  621. else
  622. {
  623. peDxVideoPort->flFlags &= ~DD_DXVIDEOPORT_FLAG_VBI_INTERLEAVED;
  624. }
  625. }
  626. }
  627. /******************************Public*Routine******************************\
  628. * HANDLE hDdOpenDxApiSurface
  629. *
  630. * Opens a DXAPI representation of a surface
  631. *
  632. * 20-Oct-1997 -by- smac
  633. * Wrote it.
  634. \**************************************************************************/
  635. HANDLE
  636. hDdOpenDxApiSurface(
  637. EDD_SURFACE* peSurface
  638. )
  639. {
  640. DDOPENSURFACEIN OpenSurfaceIn;
  641. DDOPENSURFACEOUT OpenSurfaceOut;
  642. HANDLE hHandle;
  643. hHandle = NULL;
  644. // Allocate a DXAPI object:
  645. OpenSurfaceIn.hDirectDraw = peSurface->peDirectDrawGlobal->hDirectDraw;
  646. OpenSurfaceIn.dwSurfaceHandle = (ULONG_PTR) peSurface->hGet();
  647. OpenSurfaceIn.pfnSurfaceClose = vDdNullCallBack;
  648. peSurface->peDirectDrawGlobal->pfnDxApi(DD_DXAPI_OPENSURFACE,
  649. &OpenSurfaceIn,
  650. sizeof(OpenSurfaceIn),
  651. &OpenSurfaceOut,
  652. sizeof(OpenSurfaceOut));
  653. if( ( OpenSurfaceOut.ddRVal == DD_OK ) &&
  654. ( OpenSurfaceOut.hSurface != NULL ) )
  655. {
  656. hHandle = OpenSurfaceOut.hSurface;
  657. vDdSynchronizeSurface( peSurface );
  658. }
  659. return hHandle;
  660. }
  661. /******************************Public*Routine******************************\
  662. * HANDLE hDdCloseDxApiSurface
  663. *
  664. * Closes a DXAPI representation of a surface
  665. *
  666. * 21-Oct-1997 -by- smac
  667. * Wrote it.
  668. \**************************************************************************/
  669. VOID
  670. vDdCloseDxApiSurface(
  671. EDD_SURFACE* peSurface
  672. )
  673. {
  674. DDCLOSEHANDLE CloseHandle;
  675. DWORD dwRet;
  676. CloseHandle.hHandle = peSurface->hSurface;
  677. peSurface->peDirectDrawGlobal->pfnDxApi(DD_DXAPI_CLOSEHANDLE,
  678. &CloseHandle,
  679. sizeof(CloseHandle),
  680. &dwRet,
  681. sizeof(dwRet));
  682. ASSERTGDI(dwRet == DD_OK, "Expected DD_OK");
  683. peSurface->hSurface = NULL;
  684. }
  685. /******************************Public*Routine******************************\
  686. * BOOL bDdUpdateLinksAndSynchronize
  687. *
  688. * A bidirectional link is maintained between a videoport and its active
  689. * surfaces:
  690. *
  691. * 1. From each surface to the active videoport;
  692. * 2. From the videoport to each of its active surfaces.
  693. *
  694. * This routine does all the maintaining of those links, automatically
  695. * removing links from surfaces that are no longer used, and informing
  696. * the software autoflipper of the change.
  697. *
  698. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  699. * Wrote it.
  700. \**************************************************************************/
  701. BOOL
  702. bDdUpdateLinksAndSynchronize(
  703. EDD_VIDEOPORT* peVideoPort,
  704. BOOL bNewVideo, // FALSE if 'video' parameters should
  705. EDD_SURFACE** apeNewVideo, // be ignored and current video state
  706. ULONG cAutoflipVideo, // should remain unchanged
  707. BOOL bNewVbi, // FALSE if 'VBI' parameters should
  708. EDD_SURFACE** apeNewVbi, // be ignored and current VBI state
  709. ULONG cAutoflipVbi // should remain unchanged
  710. )
  711. {
  712. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  713. EDD_DXVIDEOPORT* peDxVideoPort;
  714. // EDD_SURFACE* apeTempVideo[MAX_AUTOFLIP_BUFFERS];
  715. // EDD_SURFACE* apeTempVbi[MAX_AUTOFLIP_BUFFERS];
  716. EDD_DXSURFACE* apeDxNewVideo[MAX_AUTOFLIP_BUFFERS];
  717. EDD_DXSURFACE* apeDxNewVbi[MAX_AUTOFLIP_BUFFERS];
  718. ULONG i;
  719. BOOL bOk;
  720. peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
  721. peDxVideoPort = peVideoPort->peDxVideoPort;
  722. if (peDxVideoPort == NULL)
  723. return(TRUE);
  724. DD_ASSERTDEVLOCK(peDirectDrawGlobal);
  725. // First, check to make sure the surfaces have been opened
  726. bOk = TRUE;
  727. for (i = 0; i < cAutoflipVideo; i++)
  728. {
  729. if( ( apeNewVideo[i] == NULL ) ||
  730. ( apeNewVideo[i]->hSurface == NULL ) )
  731. {
  732. bOk = FALSE;
  733. }
  734. }
  735. for (i = 0; i < cAutoflipVbi; i++)
  736. {
  737. if( ( apeNewVbi[i] == NULL ) ||
  738. ( apeNewVbi[i]->hSurface == NULL ) )
  739. {
  740. bOk = FALSE;
  741. }
  742. }
  743. if (!bOk)
  744. {
  745. return(FALSE);
  746. }
  747. // Remove the videoport links from the old surfaces, and stash a copy
  748. // of the list for later:
  749. for (i = 0; i < peVideoPort->cAutoflipVideo; i++)
  750. {
  751. peVideoPort->apeSurfaceVideo[i]->lpVideoPort = NULL;
  752. if( peVideoPort->apeSurfaceVideo[i]->peDxSurface != NULL )
  753. {
  754. peVideoPort->apeSurfaceVideo[i]->peDxSurface->peDxVideoPort = NULL;
  755. }
  756. }
  757. for (i = 0; i < peVideoPort->cAutoflipVbi; i++)
  758. {
  759. peVideoPort->apeSurfaceVbi[i]->lpVideoPort = NULL;
  760. if( peVideoPort->apeSurfaceVbi[i]->peDxSurface != NULL )
  761. {
  762. peVideoPort->apeSurfaceVbi[i]->peDxSurface->peDxVideoPort = NULL;
  763. }
  764. }
  765. // Now add the links to the new surfaces:
  766. for (i = 0; i < cAutoflipVideo; i++)
  767. {
  768. peVideoPort->apeSurfaceVideo[i] = apeNewVideo[i];
  769. apeNewVideo[i]->lpVideoPort = peVideoPort;
  770. apeDxNewVideo[i] = apeNewVideo[i]->peDxSurface;
  771. }
  772. for (i = 0; i < cAutoflipVbi; i++)
  773. {
  774. peVideoPort->apeSurfaceVbi[i] = apeNewVbi[i];
  775. apeNewVbi[i]->lpVideoPort = peVideoPort;
  776. apeDxNewVbi[i] = apeNewVbi[i]->peDxSurface;
  777. }
  778. // Now modify the autoflip buffers, being careful to synchronize with
  779. // the software-autoflip DPC. Note that this does stuff like sets
  780. // peDxVideoPort->cAutoflipVbi.
  781. peDirectDrawGlobal->pfnAutoflipUpdate(peDxVideoPort,
  782. apeDxNewVideo,
  783. cAutoflipVideo,
  784. apeDxNewVbi,
  785. cAutoflipVbi);
  786. peVideoPort->cAutoflipVideo = cAutoflipVideo;
  787. peVideoPort->cAutoflipVbi = cAutoflipVbi;
  788. // Finally, Update some last public fields in the videoport structure:
  789. peVideoPort->dwNumAutoflip = cAutoflipVideo;
  790. peVideoPort->dwNumVBIAutoflip = cAutoflipVbi;
  791. peVideoPort->lpSurface = (cAutoflipVideo == 0) ? NULL : apeNewVideo[0];
  792. peVideoPort->lpVBISurface = (cAutoflipVbi == 0) ? NULL : apeNewVbi[0];
  793. return(TRUE);
  794. }
  795. /******************************Public*Routine******************************\
  796. * VOID vDdDxApiFreeDirectDraw
  797. *
  798. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  799. * Wrote it.
  800. \**************************************************************************/
  801. VOID
  802. vDdDxApiFreeDirectDraw(
  803. DXOBJ* pDxObj,
  804. BOOL bDoCallBack
  805. )
  806. {
  807. EDD_DXDIRECTDRAW* peDxDirectDraw;
  808. DXOBJ* pDxTmp;
  809. ASSERTGDI(pDxObj->iDxType == DXT_DIRECTDRAW, "Invalid object");
  810. peDxDirectDraw = pDxObj->peDxDirectDraw;
  811. EDD_DEVLOCK eDevLock(peDxDirectDraw->hdev);
  812. if (bDoCallBack)
  813. {
  814. pDxObj->pfnClose(pDxObj->dwEvent,pDxObj->pContext, 0, 0);
  815. }
  816. // Remove this DXOBJ instance from the list hanging off the DXAPI object:
  817. if (peDxDirectDraw->pDxObj_List == pDxObj)
  818. {
  819. peDxDirectDraw->pDxObj_List = pDxObj->pDxObj_Next;
  820. }
  821. else
  822. {
  823. for (pDxTmp = peDxDirectDraw->pDxObj_List;
  824. pDxTmp->pDxObj_Next != pDxObj;
  825. pDxTmp = pDxTmp->pDxObj_Next)
  826. {
  827. ASSERTGDI(pDxTmp->iDxType == DXT_DIRECTDRAW, "Unexpected type");
  828. ASSERTGDI(pDxTmp->pDxObj_Next != NULL, "Couldn't find node");
  829. }
  830. pDxTmp->pDxObj_Next = pDxObj->pDxObj_Next;
  831. }
  832. // Free the DXOBJ instance:
  833. pDxObj->iDxType = DXT_INVALID;
  834. vDdDxObjFree(pDxObj);
  835. // If there are no more DXOBJ instances of the DirectDraw DXAPI object,
  836. // we can free the non-paged DXAPI part of the DirectDraw structure:
  837. if (peDxDirectDraw->pDxObj_List == NULL)
  838. {
  839. if ((peDxDirectDraw->pDxEvent_PassiveList != NULL) ||
  840. (peDxDirectDraw->pDxEvent_DispatchList[CLIENT_DISPATCH_LIST] != NULL))
  841. {
  842. KdPrint(("vDdDxApiFreeDirectDraw: A kernel-mode DXAPI client didn't unregister all\n"));
  843. KdPrint((" its events when it received CLOSE call-backs. This will cause at\n"));
  844. KdPrint((" best a memory leak and at worst a crash!\n"));
  845. RIP("The DXAPI client must be fixed.");
  846. }
  847. if (peDxDirectDraw->peDirectDrawGlobal != NULL)
  848. {
  849. peDxDirectDraw->peDirectDrawGlobal->peDxDirectDraw = NULL;
  850. }
  851. vDdDxObjFree(peDxDirectDraw);
  852. }
  853. }
  854. /******************************Public*Routine******************************\
  855. * VOID vDdDxApiFreeVideoPort
  856. *
  857. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  858. * Wrote it.
  859. \**************************************************************************/
  860. VOID
  861. vDdDxApiFreeVideoPort(
  862. DXOBJ* pDxObj,
  863. BOOL bDoCallBack
  864. )
  865. {
  866. EDD_DXDIRECTDRAW* peDxDirectDraw;
  867. EDD_DXVIDEOPORT* peDxVideoPort;
  868. DXOBJ* pDxObjTmp;
  869. DXAPI_EVENT* pDxEventTmp;
  870. ASSERTGDI(pDxObj->iDxType == DXT_VIDEOPORT, "Invalid object");
  871. peDxVideoPort = pDxObj->peDxVideoPort;
  872. peDxDirectDraw = peDxVideoPort->peDxDirectDraw;
  873. EDD_DEVLOCK eDevLock(peDxDirectDraw->hdev);
  874. if (bDoCallBack)
  875. {
  876. pDxObj->pfnClose(pDxObj->dwEvent, pDxObj->pContext, 0, 0);
  877. }
  878. // Remove this DXOBJ instance from the list hanging off the DXAPI object:
  879. if (peDxVideoPort->pDxObj_List == pDxObj)
  880. {
  881. peDxVideoPort->pDxObj_List = pDxObj->pDxObj_Next;
  882. }
  883. else
  884. {
  885. for (pDxObjTmp = peDxVideoPort->pDxObj_List;
  886. pDxObjTmp->pDxObj_Next != pDxObj;
  887. pDxObjTmp = pDxObjTmp->pDxObj_Next)
  888. {
  889. ASSERTGDI(pDxObjTmp->iDxType == DXT_VIDEOPORT, "Unexpected type");
  890. ASSERTGDI(pDxObjTmp->pDxObj_Next != NULL, "Couldn't find node");
  891. }
  892. pDxObjTmp->pDxObj_Next = pDxObj->pDxObj_Next;
  893. }
  894. // Free the notification event if one is present
  895. if (peDxVideoPort->pNotifyEvent != NULL)
  896. {
  897. PKEVENT pTemp = NULL;
  898. HANDLE hEvent = peDxVideoPort->pNotifyEventHandle;
  899. NTSTATUS Status;
  900. peDxVideoPort->pNotifyEvent = NULL;
  901. peDxVideoPort->pNotifyEventHandle = NULL;
  902. // Make sure that the handle hasn't been freed by the OS already
  903. Status = ObReferenceObjectByHandle( hEvent,
  904. 0,
  905. 0,
  906. KernelMode,
  907. (PVOID *) &pTemp,
  908. NULL );
  909. if ((pTemp != NULL) && (Status != STATUS_INVALID_HANDLE))
  910. {
  911. ObDereferenceObject(pTemp);
  912. ZwClose (hEvent);
  913. }
  914. // Un-page lock memory
  915. peDxVideoPort->pNotifyBuffer = NULL;
  916. if (peDxVideoPort->pNotifyMdl != NULL)
  917. {
  918. MmUnlockPages (peDxVideoPort->pNotifyMdl);
  919. IoFreeMdl (peDxVideoPort->pNotifyMdl);
  920. peDxVideoPort->pNotifyMdl = NULL;
  921. }
  922. }
  923. // Free the DXOBJ instance:
  924. pDxObj->iDxType = DXT_INVALID;
  925. vDdDxObjFree(pDxObj);
  926. // If there are no more DXOBJ instances of the VideoPort DXAPI object,
  927. // we can free the non-paged DXAPI part of the VideoPort structure:
  928. if (peDxVideoPort->pDxObj_List == NULL)
  929. {
  930. ASSERTGDI(peDxDirectDraw != NULL, "Unexpected NULL peDxDirectDraw");
  931. for (pDxEventTmp = peDxDirectDraw->pDxEvent_DispatchList[CLIENT_DISPATCH_LIST];
  932. pDxEventTmp != NULL;
  933. pDxEventTmp = pDxEventTmp->pDxEvent_Next)
  934. {
  935. if (pDxEventTmp->peDxVideoPort == peDxVideoPort)
  936. {
  937. KdPrint(("vDdDxApiFreeVideoPort: A kernel-mode DXAPI client didn't unregister all\n"));
  938. KdPrint((" its videoport events when it received CLOSE call-backs. This will\n"));
  939. KdPrint((" cause at best a memory leak and at worst a crash!\n"));
  940. RIP("The DXAPI client must be fixed.");
  941. }
  942. }
  943. if (peDxVideoPort->peVideoPort != NULL)
  944. {
  945. // If we are actually freeing the video port, we need to lose
  946. // any capture objects that are associated with it
  947. while( peDxVideoPort->peDxCapture != NULL )
  948. {
  949. vDdLoseDxObjects( peDxDirectDraw->peDirectDrawGlobal,
  950. peDxVideoPort->peDxCapture->pDxObj_List,
  951. (PVOID) peDxVideoPort->peDxCapture,
  952. LO_CAPTURE );
  953. }
  954. peDxVideoPort->peVideoPort->peDxVideoPort = NULL;
  955. }
  956. vDdDxObjFree(peDxVideoPort);
  957. }
  958. }
  959. /******************************Public*Routine******************************\
  960. * VOID vDdDxApiFreeCapture
  961. *
  962. * 10-Apr-1998 -by- Scott MacDonald [smac]
  963. * Wrote it.
  964. \**************************************************************************/
  965. VOID
  966. vDdDxApiFreeCapture(
  967. DXOBJ* pDxObj,
  968. BOOL bDoCallBack
  969. )
  970. {
  971. EDD_DXCAPTURE* peDxCapture;
  972. EDD_DXVIDEOPORT* peDxVideoPort;
  973. ASSERTGDI(pDxObj->iDxType == DXT_CAPTURE, "Invalid object");
  974. peDxCapture = pDxObj->peDxCapture;
  975. peDxVideoPort = peDxCapture->peDxVideoPort;
  976. if (bDoCallBack)
  977. {
  978. pDxObj->pfnClose(pDxObj->dwEvent, pDxObj->pContext, 0, 0);
  979. }
  980. // Free the DXOBJ instance:
  981. pDxObj->iDxType = DXT_INVALID;
  982. vDdDxObjFree(pDxObj);
  983. // Unassociate the capture object from the video port. Since this
  984. // must be synchronized with the DPC, we need to call DxApi to do this.
  985. if( peDxVideoPort != NULL )
  986. {
  987. EDD_DXDIRECTDRAW* peDxDirectDraw;
  988. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  989. peDxDirectDraw = peDxVideoPort->peDxDirectDraw;
  990. EDD_DEVLOCK eDevLock(peDxDirectDraw->hdev);
  991. peDirectDrawGlobal = peDxDirectDraw->peDirectDrawGlobal;
  992. peDirectDrawGlobal->pfnUpdateCapture( peDxVideoPort,
  993. peDxCapture, TRUE );
  994. }
  995. vDdDxObjFree(peDxCapture);
  996. }
  997. /******************************Public*Routine******************************\
  998. * VOID vDdDxApiFreeSurface
  999. *
  1000. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  1001. * Wrote it.
  1002. \**************************************************************************/
  1003. VOID
  1004. vDdDxApiFreeSurface(
  1005. DXOBJ* pDxObj,
  1006. BOOL bDoCallBack
  1007. )
  1008. {
  1009. EDD_DXSURFACE* peDxSurface;
  1010. EDD_DXDIRECTDRAW* peDxDirectDraw;
  1011. DXOBJ* pDxTmp;
  1012. ASSERTGDI(pDxObj->iDxType == DXT_SURFACE, "Invalid object");
  1013. peDxSurface = pDxObj->peDxSurface;
  1014. peDxDirectDraw = peDxSurface->peDxDirectDraw;
  1015. EDD_DEVLOCK eDevLock(peDxDirectDraw->hdev);
  1016. if (bDoCallBack)
  1017. {
  1018. pDxObj->pfnClose(pDxObj->dwEvent, pDxObj->pContext, 0, 0);
  1019. }
  1020. // Remove this DXOBJ instance from the list hanging off the DXAPI object:
  1021. if (peDxSurface->pDxObj_List == pDxObj)
  1022. {
  1023. peDxSurface->pDxObj_List = pDxObj->pDxObj_Next;
  1024. }
  1025. else
  1026. {
  1027. for (pDxTmp = peDxSurface->pDxObj_List;
  1028. pDxTmp->pDxObj_Next != pDxObj;
  1029. pDxTmp = pDxTmp->pDxObj_Next)
  1030. {
  1031. ASSERTGDI(pDxTmp->iDxType == DXT_SURFACE, "Unexpected type");
  1032. ASSERTGDI(pDxTmp->pDxObj_Next != NULL, "Couldn't find node");
  1033. }
  1034. pDxTmp->pDxObj_Next = pDxObj->pDxObj_Next;
  1035. }
  1036. // Free the DXOBJ instance:
  1037. pDxObj->iDxType = DXT_INVALID;
  1038. vDdDxObjFree(pDxObj);
  1039. // If there are no more DXOBJ instances of the Surface DXAPI object,
  1040. // we can free the non-paged DXAPI part of the Surface structure:
  1041. if (peDxSurface->pDxObj_List == NULL)
  1042. {
  1043. if (peDxSurface->peSurface != NULL)
  1044. {
  1045. peDxSurface->peSurface->peDxSurface = NULL;
  1046. }
  1047. vDdDxObjFree(peDxSurface);
  1048. }
  1049. }
  1050. /******************************Public*Routine******************************\
  1051. * VOID vDdStopVideoPort
  1052. *
  1053. * Makes an emergency stop of the videoport.
  1054. *
  1055. * 16-Feb-1997 -by- J. Andrew Goossen [andrewgo]
  1056. * Wrote it.
  1057. \**************************************************************************/
  1058. VOID
  1059. vDdStopVideoPort(
  1060. EDD_VIDEOPORT* peVideoPort
  1061. )
  1062. {
  1063. EDD_DXVIDEOPORT* peDxVideoPort;
  1064. DD_UPDATEVPORTDATA UpdateVPortData;
  1065. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  1066. BOOL b;
  1067. peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
  1068. peDxVideoPort = peVideoPort->peDxVideoPort;
  1069. // Stop the videoport itself:
  1070. UpdateVPortData.lpDD = peDirectDrawGlobal;
  1071. UpdateVPortData.lpVideoPort = peVideoPort;
  1072. UpdateVPortData.lplpDDVBISurface = NULL;
  1073. UpdateVPortData.lplpDDSurface = NULL;
  1074. UpdateVPortData.lpVideoInfo = NULL;
  1075. UpdateVPortData.dwNumAutoflip = 0;
  1076. UpdateVPortData.dwFlags = DDRAWI_VPORTSTOP;
  1077. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  1078. ASSERTGDI(peDirectDrawGlobal->VideoPortCallBacks.UpdateVideoPort != NULL,
  1079. "Videoport object shouldn't have been created if UpdateVideoPort NULL");
  1080. // Disable video port VSYNC IRQ
  1081. if (peDxVideoPort != NULL)
  1082. {
  1083. // Shut down software autoflipping (the autoflipping routine peeks
  1084. // at these values, so this is sufficient):
  1085. peDxVideoPort->bSoftwareAutoflip = FALSE;
  1086. peDxVideoPort->flFlags &= ~(DD_DXVIDEOPORT_FLAG_AUTOFLIP|DD_DXVIDEOPORT_FLAG_AUTOFLIP_VBI);
  1087. peDxVideoPort->bSkip = FALSE;
  1088. peDxVideoPort->dwSetStateField = 0;
  1089. if (peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_ON)
  1090. {
  1091. peDxVideoPort->flFlags &= ~DD_DXVIDEOPORT_FLAG_ON;
  1092. peDirectDrawGlobal->pfnEnableIRQ(peDxVideoPort, FALSE );
  1093. }
  1094. }
  1095. if (!peDirectDrawGlobal->bSuspended &&
  1096. (peDirectDrawGlobal->VideoPortCallBacks.UpdateVideoPort != NULL))
  1097. {
  1098. peDirectDrawGlobal->VideoPortCallBacks.UpdateVideoPort(&UpdateVPortData);
  1099. }
  1100. // Update the links to reflect the fact that no surface is a
  1101. // destination for this videoport anymore:
  1102. b = bDdUpdateLinksAndSynchronize(peVideoPort, TRUE, NULL, 0, TRUE, NULL, 0);
  1103. ASSERTGDI(b, "vDdStopVideoPort: Shouldn't fail bDdUpdateLinkAndSynchronize");
  1104. }
  1105. /******************************Public*Routine******************************\
  1106. * VOID LoseDxObjects
  1107. *
  1108. * Notifies all clients using the resource that it can't be used anymore.
  1109. * It also notifies DXAPI.SYS that the resource is unusable.
  1110. *
  1111. * 04-Nov-1997 -by- smac
  1112. * Wrote it.
  1113. \**************************************************************************/
  1114. VOID
  1115. vDdLoseDxObjects(
  1116. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal,
  1117. DXOBJ* pDxObj,
  1118. PVOID pDxThing,
  1119. DWORD dwType
  1120. )
  1121. {
  1122. if( pDxObj != NULL )
  1123. {
  1124. while( pDxObj != NULL )
  1125. {
  1126. pDxObj->pfnClose(pDxObj->dwEvent, pDxObj->pContext, 0, 0);
  1127. pDxObj = pDxObj->pDxObj_Next;
  1128. }
  1129. peDirectDrawGlobal->pfnLoseObject( pDxThing, (LOTYPE) dwType );
  1130. }
  1131. }
  1132. /******************************Public*Routine******************************\
  1133. * BOOL bDdDeleteVideoPortObject
  1134. *
  1135. * Deletes a kernel-mode representation of the videoport object.
  1136. *
  1137. * 16-Feb-1997 -by- J. Andrew Goossen [andrewgo]
  1138. * Wrote it.
  1139. \**************************************************************************/
  1140. BOOL
  1141. bDdDeleteVideoPortObject(
  1142. HANDLE hVideoPort,
  1143. DWORD* pdwRet // For returning driver return code, may be NULL
  1144. )
  1145. {
  1146. BOOL bRet;
  1147. DWORD dwRet;
  1148. EDD_DXVIDEOPORT* peDxVideoPort;
  1149. EDD_VIDEOPORT* peVideoPort;
  1150. EDD_VIDEOPORT* peTmp;
  1151. VOID* pvRemove;
  1152. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  1153. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal;
  1154. DD_DESTROYVPORTDATA DestroyVPortData;
  1155. DXOBJ* pDxObj;
  1156. DXOBJ* pDxObjNext;
  1157. bRet = FALSE;
  1158. dwRet = DDHAL_DRIVER_HANDLED;
  1159. peVideoPort = (EDD_VIDEOPORT*) DdHmgLock((HDD_OBJ) hVideoPort, DD_VIDEOPORT_TYPE, FALSE);
  1160. if (peVideoPort != NULL)
  1161. {
  1162. peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
  1163. // Make sure the videoport has been turned off:
  1164. vDdStopVideoPort(peVideoPort);
  1165. // If there are any capture objects associated witht he video port,
  1166. // lose them now
  1167. peDxVideoPort = peVideoPort->peDxVideoPort;
  1168. while( peDxVideoPort && (peDxVideoPort->peDxCapture != NULL) )
  1169. {
  1170. vDdLoseDxObjects( peDirectDrawGlobal,
  1171. peDxVideoPort->peDxCapture->pDxObj_List,
  1172. (PVOID) peDxVideoPort->peDxCapture,
  1173. LO_CAPTURE );
  1174. }
  1175. // Free the DXAPI instance of the videoport object
  1176. if (peVideoPort->hVideoPort != NULL)
  1177. {
  1178. vDdDxApiFreeVideoPort( (DXOBJ*) peVideoPort->hVideoPort, FALSE);
  1179. peVideoPort->hVideoPort = NULL;
  1180. peDxVideoPort = peVideoPort->peDxVideoPort;
  1181. }
  1182. // Notify clients that their open objects are lost
  1183. if (peDxVideoPort) {
  1184. vDdLoseDxObjects( peDirectDrawGlobal,
  1185. peDxVideoPort->pDxObj_List,
  1186. (PVOID) peDxVideoPort,
  1187. LO_VIDEOPORT );
  1188. }
  1189. pvRemove = DdHmgRemoveObject((HDD_OBJ) hVideoPort,
  1190. DdHmgQueryLock((HDD_OBJ) hVideoPort),
  1191. 0,
  1192. TRUE,
  1193. DD_VIDEOPORT_TYPE);
  1194. ASSERTGDI(pvRemove != NULL, "Outstanding surfaces locks");
  1195. // Hold the devlock while we call the driver and while we muck
  1196. // around in the videoport list:
  1197. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  1198. if (peVideoPort->fl & DD_VIDEOPORT_FLAG_DRIVER_CREATED)
  1199. {
  1200. // Call the driver if it created the object:
  1201. if (peDirectDrawGlobal->VideoPortCallBacks.DestroyVideoPort)
  1202. {
  1203. DestroyVPortData.lpDD = peDirectDrawGlobal;
  1204. DestroyVPortData.lpVideoPort = peVideoPort;
  1205. DestroyVPortData.ddRVal = DDERR_GENERIC;
  1206. dwRet = peDirectDrawGlobal->
  1207. VideoPortCallBacks.DestroyVideoPort(&DestroyVPortData);
  1208. }
  1209. }
  1210. // Remove from the videoport linked-list:
  1211. peDirectDrawLocal = peVideoPort->peDirectDrawLocal;
  1212. if (peDirectDrawLocal->peVideoPort_DdList == peVideoPort)
  1213. {
  1214. peDirectDrawLocal->peVideoPort_DdList
  1215. = peVideoPort->peVideoPort_DdNext;
  1216. }
  1217. else
  1218. {
  1219. for (peTmp = peDirectDrawLocal->peVideoPort_DdList;
  1220. peTmp->peVideoPort_DdNext != peVideoPort;
  1221. peTmp = peTmp->peVideoPort_DdNext)
  1222. ;
  1223. peTmp->peVideoPort_DdNext = peVideoPort->peVideoPort_DdNext;
  1224. }
  1225. // Unload DXAPI.SYS if no other video port is using it
  1226. if (peDirectDrawLocal->peVideoPort_DdList == NULL)
  1227. {
  1228. vDdUnloadDxApi( peDirectDrawGlobal );
  1229. }
  1230. // We're all done with this object, so free the memory and
  1231. // leave:
  1232. DdFreeObject(peVideoPort, DD_VIDEOPORT_TYPE);
  1233. bRet = TRUE;
  1234. }
  1235. else
  1236. {
  1237. WARNING1("bDdDeleteVideoPortObject: Bad handle or object was busy\n");
  1238. }
  1239. if (pdwRet != NULL)
  1240. {
  1241. *pdwRet = dwRet;
  1242. }
  1243. return(bRet);
  1244. }
  1245. /******************************Public*Routine******************************\
  1246. * DWORD DdDxApiOpenDirectDraw
  1247. *
  1248. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  1249. * Wrote it.
  1250. \**************************************************************************/
  1251. VOID
  1252. APIENTRY
  1253. DdDxApiOpenDirectDraw(
  1254. DDOPENDIRECTDRAWIN* pOpenDirectDrawIn,
  1255. DDOPENDIRECTDRAWOUT* pOpenDirectDrawOut,
  1256. PKDEFERRED_ROUTINE pfnEventDpc,
  1257. ULONG DxApiPrivateVersionNumber
  1258. )
  1259. {
  1260. HANDLE hDirectDraw;
  1261. EDD_LOCK_DIRECTDRAW eLockDirectDraw;
  1262. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal;
  1263. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  1264. DXOBJ* pDxObj;
  1265. EDD_DXDIRECTDRAW* peDxDirectDraw;
  1266. ASSERTGDI(KeGetCurrentIrql() == PASSIVE_LEVEL,
  1267. "DdDxApiOpenDirectDraw: Callable only at passive level (it's not pageable)");
  1268. hDirectDraw = 0; // Assume failure
  1269. // We use the private version number to ensure consistency between
  1270. // win32k.sys and dxapi.sys. Since dxapi.sys is dynamically loaded,
  1271. // I am worried about a scenario where a service pack is applied that
  1272. // updates both dxapi.sys and win32k.sys -- if the machine isn't
  1273. // rebooted, the old win32k.sys will remain loaded but the new dxapi.sys
  1274. // may be loaded, possibly causing a crash.
  1275. peDirectDrawLocal
  1276. = eLockDirectDraw.peLock((HANDLE) pOpenDirectDrawIn->dwDirectDrawHandle);
  1277. if ((peDirectDrawLocal != NULL) ||
  1278. (DxApiPrivateVersionNumber != DXAPI_PRIVATE_VERSION_NUMBER))
  1279. {
  1280. peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
  1281. pDxObj = pDdDxObjHandleAllocate(DXT_DIRECTDRAW,
  1282. pOpenDirectDrawIn->pfnDirectDrawClose,
  1283. DDNOTIFY_CLOSEDIRECTDRAW,
  1284. pOpenDirectDrawIn->pContext);
  1285. if (pDxObj != NULL)
  1286. {
  1287. // Among other things, enforce synchronization while we muck
  1288. // around in the global DirectDraw object:
  1289. EDD_DEVLOCK eDevLock(peDirectDrawGlobal);
  1290. peDxDirectDraw = peDirectDrawGlobal->peDxDirectDraw;
  1291. if (peDxDirectDraw != NULL)
  1292. {
  1293. // Just add this object to the list hanging off the DirectDraw
  1294. // object:
  1295. pDxObj->peDxDirectDraw = peDxDirectDraw;
  1296. pDxObj->pDxObj_Next = peDxDirectDraw->pDxObj_List;
  1297. peDxDirectDraw->pDxObj_List = pDxObj;
  1298. // Success!
  1299. hDirectDraw = (HANDLE) pDxObj;
  1300. }
  1301. else
  1302. {
  1303. peDxDirectDraw = (EDD_DXDIRECTDRAW*) pDdDxObjDataAllocate(
  1304. sizeof(*peDxDirectDraw),
  1305. 'dxdG');
  1306. if (peDxDirectDraw)
  1307. {
  1308. RtlZeroMemory(peDxDirectDraw, sizeof(*peDxDirectDraw));
  1309. pDxObj->peDxDirectDraw = peDxDirectDraw;
  1310. // We need to access some capabilities at raised IRQL,
  1311. // so copy those from the paged 'peDirectDrawGlobal'
  1312. // to the non-paged 'peDxDirectDraw' now:
  1313. peDxDirectDraw->DxApiInterface
  1314. = peDirectDrawGlobal->DxApiInterface;
  1315. peDxDirectDraw->HwDeviceExtension
  1316. = peDirectDrawGlobal->HwDeviceExtension;
  1317. peDxDirectDraw->dwIRQCaps
  1318. = peDirectDrawGlobal->DDKernelCaps.dwIRQCaps;
  1319. peDxDirectDraw->peDirectDrawGlobal
  1320. = peDirectDrawGlobal;
  1321. peDxDirectDraw->hdev
  1322. = peDirectDrawGlobal->hdev;
  1323. peDirectDrawGlobal->peDxDirectDraw = peDxDirectDraw;
  1324. peDxDirectDraw->pDxObj_List = pDxObj;
  1325. // Initialize our kernel structures use for interrupts
  1326. // and handling raised IRQL callers.
  1327. KeInitializeDpc(&peDxDirectDraw->EventDpc,
  1328. pfnEventDpc,
  1329. peDxDirectDraw);
  1330. KeInitializeSpinLock(&peDxDirectDraw->SpinLock);
  1331. // Success!
  1332. hDirectDraw = (HANDLE) pDxObj;
  1333. }
  1334. }
  1335. if (!hDirectDraw)
  1336. {
  1337. vDdDxObjFree(pDxObj);
  1338. }
  1339. }
  1340. }
  1341. else
  1342. {
  1343. WARNING("DdDxApiOpenDirectDraw: Invalid dwDirectDrawHandle, failing\n");
  1344. }
  1345. pOpenDirectDrawOut->hDirectDraw = hDirectDraw;
  1346. pOpenDirectDrawOut->ddRVal = (hDirectDraw != NULL) ? DD_OK : DDERR_GENERIC;
  1347. }
  1348. /******************************Public*Routine******************************\
  1349. * DWORD DdDxApiOpenVideoPort
  1350. *
  1351. * This routine lets a driver use fields from the larger, pageable version
  1352. * of the DD_SURFACE_* structures used by the display driver to set
  1353. * fields in the smaller, non-pageable version of the corresponding
  1354. * DDSURFACEDATA structure used by the miniport.
  1355. *
  1356. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  1357. * Wrote it.
  1358. \**************************************************************************/
  1359. VOID
  1360. APIENTRY
  1361. DdDxApiOpenVideoPort(
  1362. DDOPENVIDEOPORTIN* pOpenVideoPortIn,
  1363. DDOPENVIDEOPORTOUT* pOpenVideoPortOut
  1364. )
  1365. {
  1366. HANDLE hVideoPort;
  1367. DXOBJ* pDxObjDirectDraw;
  1368. DXOBJ* pDxObj;
  1369. EDD_DXDIRECTDRAW* peDxDirectDraw;
  1370. EDD_DXVIDEOPORT* peDxVideoPort;
  1371. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  1372. EDD_LOCK_VIDEOPORT eLockVideoPort;
  1373. EDD_VIDEOPORT* peVideoPort;
  1374. BOOL bFound;
  1375. EDD_DIRECTDRAW_LOCAL* peTempDirectDrawLocal;
  1376. EDD_VIDEOPORT* peTempVideoPort;
  1377. ASSERTGDI(KeGetCurrentIrql() == PASSIVE_LEVEL,
  1378. "DdDxApiOpenVideoPort: Callable only at passive level (it's not pageable)");
  1379. hVideoPort = 0; // Assume failure
  1380. pDxObjDirectDraw = (DXOBJ*) pOpenVideoPortIn->hDirectDraw;
  1381. ASSERTGDI((pDxObjDirectDraw != NULL) &&
  1382. (pDxObjDirectDraw->iDxType == DXT_DIRECTDRAW),
  1383. "DdDxApiOpenVideoPort: Invalid hDirectDraw, we're about to crash");
  1384. peDxDirectDraw = pDxObjDirectDraw->peDxDirectDraw;
  1385. // Among other things, enforce synchronization while we muck around
  1386. // in the DirectDraw object:
  1387. EDD_DEVLOCK eDevLock(peDxDirectDraw->hdev);
  1388. if (!peDxDirectDraw->bLost)
  1389. {
  1390. peDirectDrawGlobal = peDxDirectDraw->peDirectDrawGlobal;
  1391. // We need to get a handle to the video port, so we need to
  1392. // go looking for it.
  1393. bFound = FALSE;
  1394. peTempDirectDrawLocal = peDirectDrawGlobal->peDirectDrawLocalList;
  1395. while( ( peTempDirectDrawLocal != NULL ) && !bFound )
  1396. {
  1397. peTempVideoPort = peTempDirectDrawLocal->peVideoPort_DdList;
  1398. while( peTempVideoPort != NULL )
  1399. {
  1400. if( peTempVideoPort->ddvpDesc.dwVideoPortID == pOpenVideoPortIn->dwVideoPortHandle )
  1401. {
  1402. bFound = TRUE;
  1403. break;
  1404. }
  1405. peTempVideoPort = peTempVideoPort->peVideoPort_DdNext;
  1406. }
  1407. peTempDirectDrawLocal = peTempDirectDrawLocal->peDirectDrawLocalNext;
  1408. }
  1409. if( bFound )
  1410. {
  1411. peVideoPort = eLockVideoPort.peLock(
  1412. (HANDLE) peTempVideoPort->hGet());
  1413. if ((peVideoPort != NULL) &&
  1414. (peVideoPort->peDirectDrawGlobal == peDirectDrawGlobal))
  1415. {
  1416. pDxObj = pDdDxObjHandleAllocate(DXT_VIDEOPORT,
  1417. pOpenVideoPortIn->pfnVideoPortClose,
  1418. DDNOTIFY_CLOSEVIDEOPORT,
  1419. pOpenVideoPortIn->pContext);
  1420. if (pDxObj != NULL)
  1421. {
  1422. peDxVideoPort = peVideoPort->peDxVideoPort;
  1423. if (peDxVideoPort != NULL)
  1424. {
  1425. // Just add this object to the list hanging off the
  1426. // surface object:
  1427. pDxObj->peDxVideoPort = peDxVideoPort;
  1428. pDxObj->pDxObj_Next = peDxVideoPort->pDxObj_List;
  1429. peDxVideoPort->pDxObj_List = pDxObj;
  1430. // Success!
  1431. hVideoPort = (HANDLE) pDxObj;
  1432. }
  1433. else
  1434. {
  1435. peDxVideoPort = (EDD_DXVIDEOPORT*) pDdDxObjDataAllocate(
  1436. sizeof(*peDxVideoPort),
  1437. 'sxdG');
  1438. if (peDxVideoPort)
  1439. {
  1440. RtlZeroMemory(peDxVideoPort, sizeof(*peDxVideoPort));
  1441. pDxObj->peDxVideoPort = peDxVideoPort;
  1442. peVideoPort->peDxVideoPort = peDxVideoPort;
  1443. peDxVideoPort->pDxObj_List = pDxObj;
  1444. peDxVideoPort->peVideoPort = peVideoPort;
  1445. peDxVideoPort->peDxDirectDraw = peDxDirectDraw;
  1446. peDxVideoPort->iCurrentVideo = 1;
  1447. peDxVideoPort->dwVideoPortID
  1448. = peVideoPort->ddvpDesc.dwVideoPortID;
  1449. vDdSynchronizeVideoPort(peVideoPort);
  1450. // Success!
  1451. hVideoPort = (HANDLE) pDxObj;
  1452. }
  1453. }
  1454. if (!hVideoPort)
  1455. {
  1456. vDdDxObjFree(pDxObj);
  1457. }
  1458. }
  1459. }
  1460. else
  1461. {
  1462. WARNING("DdDxApiOpenVideoPort: Invalid dwSurfaceHandle, failing.\n");
  1463. }
  1464. }
  1465. else
  1466. {
  1467. WARNING("DdDxApiOpenVideoPort: Invalid dwSurfaceHandle, failing.\n");
  1468. }
  1469. }
  1470. else
  1471. {
  1472. WARNING("DdDxApiOpenVideoPort: DirectDraw object is lost");
  1473. }
  1474. pOpenVideoPortOut->hVideoPort = hVideoPort;
  1475. pOpenVideoPortOut->ddRVal = (hVideoPort != NULL) ? DD_OK : DDERR_GENERIC;
  1476. }
  1477. /******************************Public*Routine******************************\
  1478. * DWORD DdDxApiOpenSurface
  1479. *
  1480. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  1481. * Wrote it.
  1482. \**************************************************************************/
  1483. VOID
  1484. APIENTRY
  1485. DdDxApiOpenSurface(
  1486. DDOPENSURFACEIN* pOpenSurfaceIn,
  1487. DDOPENSURFACEOUT* pOpenSurfaceOut
  1488. )
  1489. {
  1490. HANDLE hSurface;
  1491. DXOBJ* pDxObjDirectDraw;
  1492. DXOBJ* pDxObj;
  1493. EDD_DXDIRECTDRAW* peDxDirectDraw;
  1494. EDD_DXSURFACE* peDxSurface;
  1495. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  1496. EDD_LOCK_SURFACE eLockSurface;
  1497. EDD_SURFACE* peSurface;
  1498. ASSERTGDI(KeGetCurrentIrql() == PASSIVE_LEVEL,
  1499. "DdDxApiOpenSurface: Callable only at passive level (it's not pageable)");
  1500. hSurface = 0; // Assume failure
  1501. pDxObjDirectDraw = (DXOBJ*) pOpenSurfaceIn->hDirectDraw;
  1502. ASSERTGDI((pDxObjDirectDraw != NULL) &&
  1503. (pDxObjDirectDraw->iDxType == DXT_DIRECTDRAW),
  1504. "DdDxApiOpenSurface: Invalid hDirectDraw, we're about to crash");
  1505. peDxDirectDraw = pDxObjDirectDraw->peDxDirectDraw;
  1506. // Among other things, enforce synchronization while we muck around
  1507. // in the DirectDraw object:
  1508. EDD_DEVLOCK eDevLock(peDxDirectDraw->hdev);
  1509. if (!peDxDirectDraw->bLost)
  1510. {
  1511. peDirectDrawGlobal = peDxDirectDraw->peDirectDrawGlobal;
  1512. peSurface = eLockSurface.peLock((HANDLE) pOpenSurfaceIn->dwSurfaceHandle);
  1513. if ((peSurface != NULL) &&
  1514. (peSurface->peDirectDrawGlobal == peDirectDrawGlobal))
  1515. {
  1516. pDxObj = pDdDxObjHandleAllocate(DXT_SURFACE,
  1517. pOpenSurfaceIn->pfnSurfaceClose,
  1518. DDNOTIFY_CLOSESURFACE,
  1519. pOpenSurfaceIn->pContext);
  1520. if (pDxObj != NULL)
  1521. {
  1522. peDxSurface = peSurface->peDxSurface;
  1523. if (peDxSurface != NULL)
  1524. {
  1525. // Just add this object to the list hanging off the
  1526. // surface object:
  1527. pDxObj->peDxSurface = peDxSurface;
  1528. pDxObj->pDxObj_Next = peDxSurface->pDxObj_List;
  1529. peDxSurface->pDxObj_List = pDxObj;
  1530. // Success!
  1531. hSurface = (HANDLE) pDxObj;
  1532. }
  1533. else
  1534. {
  1535. peDxSurface = (EDD_DXSURFACE*) pDdDxObjDataAllocate(
  1536. sizeof(*peDxSurface),
  1537. 'sxdG');
  1538. if (peDxSurface)
  1539. {
  1540. RtlZeroMemory(peDxSurface, sizeof(*peDxSurface));
  1541. pDxObj->peDxSurface = peDxSurface;
  1542. peSurface->peDxSurface = peDxSurface;
  1543. peDxSurface->pDxObj_List = pDxObj;
  1544. peDxSurface->peSurface = peSurface;
  1545. peDxSurface->peDxDirectDraw = peDxDirectDraw;
  1546. if( peDirectDrawGlobal->HalInfo.ddCaps.dwCaps2 &
  1547. DDCAPS2_CANBOBINTERLEAVED )
  1548. {
  1549. peDxSurface->flFlags |= DD_DXSURFACE_FLAG_CAN_BOB_INTERLEAVED;
  1550. }
  1551. if( peDirectDrawGlobal->HalInfo.ddCaps.dwCaps2 &
  1552. DDCAPS2_CANBOBNONINTERLEAVED )
  1553. {
  1554. peDxSurface->flFlags |= DD_DXSURFACE_FLAG_CAN_BOB_NONINTERLEAVED;
  1555. }
  1556. // Success!
  1557. hSurface = (HANDLE) pDxObj;
  1558. }
  1559. }
  1560. vDdSynchronizeSurface(peSurface);
  1561. if (!hSurface)
  1562. {
  1563. vDdDxObjFree(pDxObj);
  1564. }
  1565. }
  1566. }
  1567. else
  1568. {
  1569. WARNING("DdDxApiOpenSurface: Invalid dwSurfaceHandle, failing.\n");
  1570. }
  1571. }
  1572. else
  1573. {
  1574. WARNING("DdDxApiOpenSurface: DirectDraw object lost\n");
  1575. }
  1576. pOpenSurfaceOut->hSurface = hSurface;
  1577. pOpenSurfaceOut->ddRVal = (hSurface != NULL) ? DD_OK : DDERR_GENERIC;
  1578. }
  1579. /******************************Public*Routine******************************\
  1580. * DWORD DdDxApiCloseHandle
  1581. *
  1582. * 14-Apr-1997 -by- J. Andrew Goossen [andrewgo]
  1583. * Wrote it.
  1584. \**************************************************************************/
  1585. VOID
  1586. APIENTRY
  1587. DdDxApiCloseHandle(
  1588. DDCLOSEHANDLE* pCloseHandle,
  1589. DWORD* pdwRet
  1590. )
  1591. {
  1592. DXOBJ* pDxObj = (DXOBJ*) pCloseHandle->hHandle;
  1593. ASSERTGDI(KeGetCurrentIrql() == PASSIVE_LEVEL,
  1594. "DdDxApiCloseHandle: Callable only at passive level (it's not pageable)");
  1595. ASSERTGDI(pCloseHandle->hHandle != NULL,
  1596. "DdDxApiCloseHandle: Trying to close NULL handle");
  1597. switch(pDxObj->iDxType)
  1598. {
  1599. case DXT_DIRECTDRAW:
  1600. vDdDxApiFreeDirectDraw(pDxObj, TRUE);
  1601. break;
  1602. case DXT_VIDEOPORT:
  1603. vDdDxApiFreeVideoPort(pDxObj, FALSE);
  1604. break;
  1605. case DXT_SURFACE:
  1606. vDdDxApiFreeSurface(pDxObj, FALSE);
  1607. break;
  1608. case DXT_CAPTURE:
  1609. vDdDxApiFreeCapture(pDxObj, FALSE);
  1610. break;
  1611. case DXT_INVALID:
  1612. RIP("DdDxApiCloseHandle: Invalid surface. Same handle probably closed twice");
  1613. break;
  1614. default:
  1615. RIP("DdDxApiCloseHandle: Invalid surface.");
  1616. break;
  1617. }
  1618. *pdwRet = DD_OK;
  1619. }
  1620. /******************************Public*Routine******************************\
  1621. * DWORD DdDxApiOpenCaptureDevice
  1622. *
  1623. * 01-Nov-1997 -by- smac
  1624. * Wrote it.
  1625. \**************************************************************************/
  1626. VOID
  1627. APIENTRY
  1628. DdDxApiOpenCaptureDevice(
  1629. DDOPENVPCAPTUREDEVICEIN* pOpenCaptureDeviceIn,
  1630. DDOPENVPCAPTUREDEVICEOUT* pOpenCaptureDeviceOut
  1631. )
  1632. {
  1633. HANDLE hCaptureDevice;
  1634. DXOBJ* pDxObjDirectDraw;
  1635. DXOBJ* pDxObjVideoPort;
  1636. DXOBJ* pDxObj;
  1637. EDD_DXDIRECTDRAW* peDxDirectDraw;
  1638. EDD_DXVIDEOPORT* peDxVideoPort;
  1639. EDD_DXCAPTURE* peDxCapture;
  1640. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  1641. DWORD dwRet;
  1642. ASSERTGDI(KeGetCurrentIrql() == PASSIVE_LEVEL,
  1643. "DdDxApiOpenVideoPort: Callable only at passive level (it's not pageable)");
  1644. hCaptureDevice = 0; // Assume failure
  1645. pDxObjDirectDraw = (DXOBJ*) pOpenCaptureDeviceIn->hDirectDraw;
  1646. pDxObjVideoPort = (DXOBJ*) pOpenCaptureDeviceIn->hVideoPort;
  1647. ASSERTGDI((pDxObjDirectDraw != NULL) &&
  1648. (pDxObjDirectDraw->iDxType == DXT_DIRECTDRAW),
  1649. "DdDxApiOpenCaptureDevice: Invalid hDirectDraw, we're about to crash");
  1650. ASSERTGDI((pDxObjVideoPort != NULL) &&
  1651. (pDxObjVideoPort->iDxType == DXT_VIDEOPORT),
  1652. "DdDxApiOpenCaptureDevice: Invalid hVideoPort, we're about to crash");
  1653. peDxDirectDraw = pDxObjDirectDraw->peDxDirectDraw;
  1654. peDxVideoPort = pDxObjVideoPort->peDxVideoPort;
  1655. ASSERTGDI((pOpenCaptureDeviceIn->dwFlags == DDOPENCAPTURE_VIDEO) ||
  1656. (pOpenCaptureDeviceIn->dwFlags == DDOPENCAPTURE_VBI),
  1657. "DdDxApiOpenCaptureDevice: Invalid flags specified");
  1658. ASSERTGDI((pOpenCaptureDeviceIn->dwCaptureEveryNFields != 0),
  1659. "DdDxApiOpenCaptureDevice: Invalid dwCaptureEveryNFields specified");
  1660. ASSERTGDI((pOpenCaptureDeviceIn->pfnCaptureClose != 0),
  1661. "DdDxApiOpenCaptureDevice: Invalid pfnCaptureClose specified");
  1662. // Among other things, enforce synchronization while we muck around
  1663. // in the DirectDraw object:
  1664. EDD_DEVLOCK eDevLock(peDxDirectDraw->hdev);
  1665. dwRet = DDERR_INVALIDPARAMS;
  1666. if ((!peDxDirectDraw->bLost) &&
  1667. (!peDxVideoPort->bLost))
  1668. {
  1669. // Only do this if the device actually supports capturing
  1670. dwRet = DDERR_CURRENTLYNOTAVAIL;
  1671. peDirectDrawGlobal = peDxDirectDraw->peDirectDrawGlobal;
  1672. if ((peDirectDrawGlobal->DDKernelCaps.dwCaps &
  1673. (DDKERNELCAPS_CAPTURE_SYSMEM|DDKERNELCAPS_CAPTURE_NONLOCALVIDMEM)) &&
  1674. (peDxDirectDraw->DxApiInterface.DxTransfer != NULL))
  1675. {
  1676. #if 0 // fix bug 169385
  1677. // See capturing target is matched.
  1678. if (((pOpenCaptureDeviceIn->dwFlags & DDOPENCAPTURE_VBI) &&
  1679. (peDxVideoPort->cAutoflipVbi > 0)) ||
  1680. ((pOpenCaptureDeviceIn->dwFlags & DDOPENCAPTURE_VIDEO) &&
  1681. (peDxVideoPort->cAutoflipVideo > 0)))
  1682. {
  1683. #endif
  1684. // Allocate the object. We only allow one handle per object.
  1685. dwRet = DDERR_OUTOFMEMORY;
  1686. pDxObj = pDdDxObjHandleAllocate(DXT_CAPTURE,
  1687. pOpenCaptureDeviceIn->pfnCaptureClose,
  1688. DDNOTIFY_CLOSECAPTURE,
  1689. pOpenCaptureDeviceIn->pContext);
  1690. if (pDxObj != NULL)
  1691. {
  1692. peDxCapture = (EDD_DXCAPTURE*) pDdDxObjDataAllocate(
  1693. sizeof(*peDxCapture),
  1694. 'sxdG');
  1695. if (peDxCapture)
  1696. {
  1697. RtlZeroMemory(peDxCapture, sizeof(*peDxCapture));
  1698. pDxObj->peDxCapture = peDxCapture;
  1699. peDxCapture->pDxObj_List = pDxObj;
  1700. peDxCapture->peDxVideoPort = peDxVideoPort;
  1701. peDxCapture->dwStartLine = pOpenCaptureDeviceIn->dwStartLine;
  1702. peDxCapture->dwEndLine = pOpenCaptureDeviceIn->dwEndLine;
  1703. peDxCapture->dwCaptureCountDown = 1;
  1704. peDxCapture->dwCaptureEveryNFields =
  1705. pOpenCaptureDeviceIn->dwCaptureEveryNFields;
  1706. if (pOpenCaptureDeviceIn->dwFlags & DDOPENCAPTURE_VBI )
  1707. {
  1708. peDxCapture->flFlags = DD_DXCAPTURE_FLAG_VBI;
  1709. }
  1710. else
  1711. {
  1712. peDxCapture->flFlags = DD_DXCAPTURE_FLAG_VIDEO;
  1713. }
  1714. // Now we need to put the capture object into the list
  1715. // of active capture objects, but since this list is
  1716. // walked at DPC time, we need to call DxApi to do this.
  1717. peDirectDrawGlobal->pfnUpdateCapture( peDxVideoPort,
  1718. peDxCapture, FALSE );
  1719. // Success!
  1720. hCaptureDevice = (HANDLE) pDxObj;
  1721. dwRet = DD_OK;
  1722. }
  1723. if (!hCaptureDevice)
  1724. {
  1725. vDdDxObjFree(pDxObj);
  1726. }
  1727. }
  1728. #if 0 // fix bug 169385
  1729. }
  1730. else
  1731. {
  1732. WARNING("DdDxApiOpenCaptureDevice: VideoPort doesn't have surface requested by driver.\n");
  1733. }
  1734. #endif
  1735. }
  1736. else
  1737. {
  1738. WARNING("DdDxApiOpenCaptureDevice: Device does not support capture, failing.\n");
  1739. }
  1740. }
  1741. else
  1742. {
  1743. WARNING("DdDxApiOpenCaptureDevice: DirectDraw or VideoPort object is not valid, failing.\n");
  1744. }
  1745. pOpenCaptureDeviceOut->hCapture = hCaptureDevice;
  1746. pOpenCaptureDeviceOut->ddRVal = dwRet;
  1747. }
  1748. /******************************Public*Routine******************************\
  1749. * DWORD DdDxApiGetKernelCaps
  1750. *
  1751. * 01-Nov-1997 -by- smac
  1752. * Wrote it.
  1753. \**************************************************************************/
  1754. VOID
  1755. APIENTRY
  1756. DdDxApiGetKernelCaps(
  1757. HANDLE hDirectDraw,
  1758. DDGETKERNELCAPSOUT* pGetKernelCaps
  1759. )
  1760. {
  1761. DXOBJ* pDxObjDirectDraw;
  1762. EDD_DXDIRECTDRAW* peDxDirectDraw;
  1763. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  1764. ASSERTGDI(KeGetCurrentIrql() == PASSIVE_LEVEL,
  1765. "DdDxApiGetKernelCaps: Callable only at passive level (it's not pageable)");
  1766. pDxObjDirectDraw = (DXOBJ*) hDirectDraw;
  1767. ASSERTGDI((pDxObjDirectDraw != NULL) &&
  1768. (pDxObjDirectDraw->iDxType == DXT_DIRECTDRAW),
  1769. "DdDxApiGetKernelCaps: Invalid hDirectDraw, we're about to crash");
  1770. peDxDirectDraw = pDxObjDirectDraw->peDxDirectDraw;
  1771. // Among other things, enforce synchronization while we muck around
  1772. // in the DirectDraw object:
  1773. EDD_DEVLOCK eDevLock(peDxDirectDraw->hdev);
  1774. if (!peDxDirectDraw->bLost)
  1775. {
  1776. peDirectDrawGlobal = peDxDirectDraw->peDirectDrawGlobal;
  1777. pGetKernelCaps->ddRVal = DD_OK;
  1778. pGetKernelCaps->dwCaps = peDirectDrawGlobal->DDKernelCaps.dwCaps;
  1779. pGetKernelCaps->dwIRQCaps = peDirectDrawGlobal->DDKernelCaps.dwIRQCaps;
  1780. }
  1781. else
  1782. {
  1783. pGetKernelCaps->ddRVal = DXERR_OUTOFCAPS;
  1784. pGetKernelCaps->dwCaps = 0;
  1785. pGetKernelCaps->dwIRQCaps = 0;
  1786. }
  1787. }
  1788. /******************************Public*Routine******************************\
  1789. * VOID DdDxApiLockDevice
  1790. *
  1791. * 05-Jun-1998 -by- agodfrey
  1792. \**************************************************************************/
  1793. VOID
  1794. APIENTRY
  1795. DdDxApiLockDevice(
  1796. HDEV hdev
  1797. )
  1798. {
  1799. DxEngLockHdev(hdev);
  1800. }
  1801. /******************************Public*Routine******************************\
  1802. * VOID DdDxApiUnlockDevice
  1803. *
  1804. * 05-Jun-1998 -by- agodfrey
  1805. \**************************************************************************/
  1806. VOID
  1807. APIENTRY
  1808. DdDxApiUnlockDevice(
  1809. HDEV hdev
  1810. )
  1811. {
  1812. DxEngUnlockHdev(hdev);
  1813. }
  1814. /******************************Public*Routine******************************\
  1815. * DWORD DxDvpCanCreateVideoPort
  1816. *
  1817. * Queries the driver to determine whether it can support a DirectDraw
  1818. * videoPort.
  1819. *
  1820. * 3-Oct-1996 -by- Lingyun Wang [lingyunw]
  1821. * Wrote it.
  1822. \**************************************************************************/
  1823. DWORD
  1824. APIENTRY
  1825. DxDvpCanCreateVideoPort(
  1826. HANDLE hDirectDraw,
  1827. PDD_CANCREATEVPORTDATA puCanCreateVPortData
  1828. )
  1829. {
  1830. DWORD dwRet;
  1831. DD_CANCREATEVPORTDATA CanCreateVideoPort;
  1832. DDVIDEOPORTDESC VideoPortDescription;
  1833. __try
  1834. {
  1835. CanCreateVideoPort
  1836. = ProbeAndReadStructure(puCanCreateVPortData,
  1837. DD_CANCREATEVPORTDATA);
  1838. VideoPortDescription
  1839. = ProbeAndReadStructure(CanCreateVideoPort.lpDDVideoPortDesc,
  1840. DDVIDEOPORTDESC);
  1841. }
  1842. __except(EXCEPTION_EXECUTE_HANDLER)
  1843. {
  1844. return(DDHAL_DRIVER_NOTHANDLED);
  1845. }
  1846. dwRet = DDHAL_DRIVER_NOTHANDLED;
  1847. CanCreateVideoPort.ddRVal = DDERR_GENERIC;
  1848. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal;
  1849. EDD_LOCK_DIRECTDRAW eLockDirectDraw;
  1850. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  1851. peDirectDrawLocal = eLockDirectDraw.peLock(hDirectDraw);
  1852. // For now, do now enable VPE on Terminal Server due to problems
  1853. // loading DXAPI.SYS into session space vs. non-session space
  1854. {
  1855. if (peDirectDrawLocal != NULL)
  1856. {
  1857. peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
  1858. CanCreateVideoPort.lpDD = peDirectDrawGlobal;
  1859. CanCreateVideoPort.lpDDVideoPortDesc = &VideoPortDescription;
  1860. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  1861. if ((!peDirectDrawGlobal->bSuspended) &&
  1862. (peDirectDrawGlobal->VideoPortCallBacks.CanCreateVideoPort))
  1863. {
  1864. dwRet = peDirectDrawGlobal->
  1865. VideoPortCallBacks.CanCreateVideoPort(&CanCreateVideoPort);
  1866. }
  1867. }
  1868. else
  1869. {
  1870. WARNING("DxDvpCanCreateSurface: Invalid object\n");
  1871. }
  1872. }
  1873. // We have to wrap this in another try-except because the user-mode
  1874. // memory containing the input may have been deallocated by now:
  1875. __try
  1876. {
  1877. ProbeAndWriteRVal(&puCanCreateVPortData->ddRVal,
  1878. CanCreateVideoPort.ddRVal);
  1879. }
  1880. __except(EXCEPTION_EXECUTE_HANDLER)
  1881. {
  1882. }
  1883. return(dwRet);
  1884. }
  1885. /*****************************Private*Routine******************************\
  1886. * HANDLE DxDvpCreateVideoPort
  1887. *
  1888. * Notifies the HAL after a video port is created.
  1889. *
  1890. * This is an optional call for the driver, but we always have to 'hook'
  1891. * this call from user-mode DirectDraw.
  1892. *
  1893. * Question: A user-mode application could have absolute garbage in
  1894. * lpDDVideoPortDesc and get it by the driver, because the
  1895. * driver would only be monitoring for invalid data in its
  1896. * CanCreateVideoPort call. So should we call the driver's
  1897. * CanCreateVideoPort here in this routine before calling
  1898. * CreateVideoPort?
  1899. *
  1900. * History:
  1901. * 2-Oct-1996 -by- Lingyun Wang [lingyunw]
  1902. * Wrote it.
  1903. \**************************************************************************/
  1904. HANDLE
  1905. APIENTRY
  1906. DxDvpCreateVideoPort(
  1907. HANDLE hDirectDraw,
  1908. PDD_CREATEVPORTDATA puCreateVPortData
  1909. )
  1910. {
  1911. HANDLE hRet;
  1912. DWORD dwRet;
  1913. DD_CREATEVPORTDATA CreateVPortData;
  1914. DDVIDEOPORTDESC VideoPortDescription;
  1915. BOOL bFirst;
  1916. __try
  1917. {
  1918. CreateVPortData =
  1919. ProbeAndReadStructure(puCreateVPortData,
  1920. DD_CREATEVPORTDATA);
  1921. VideoPortDescription
  1922. = ProbeAndReadStructure(CreateVPortData.lpDDVideoPortDesc,
  1923. DDVIDEOPORTDESC);
  1924. }
  1925. __except(EXCEPTION_EXECUTE_HANDLER)
  1926. {
  1927. return(DDHAL_DRIVER_NOTHANDLED);
  1928. }
  1929. hRet = 0;
  1930. CreateVPortData.ddRVal = DDERR_GENERIC;
  1931. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal;
  1932. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  1933. EDD_LOCK_DIRECTDRAW eLockDirectDraw;
  1934. EDD_VIDEOPORT* peVideoPort;
  1935. // The two items below where triple bang comments are are somewhat cryptic.
  1936. //
  1937. // 1. Ensure that not more than one VideoPort created
  1938. // 2. Scott allows CanCreateVideoPort and CreateVideoPort to be optional
  1939. peDirectDrawLocal = eLockDirectDraw.peLock(hDirectDraw);
  1940. // For now, enable VPE on Terminal Server due to conflicts loading in
  1941. // session space vs. non-session sapce.
  1942. {
  1943. if (peDirectDrawLocal != NULL)
  1944. {
  1945. peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
  1946. // Here we do the minimal validations checks to ensure that bad
  1947. // parameters won't crash NT. We're not more strict than
  1948. // checking for stuff that will crash us, as the user-mode part
  1949. // of DirectDraw handles that.
  1950. if (VideoPortDescription.dwVideoPortID <
  1951. peDirectDrawGlobal->HalInfo.ddCaps.dwMaxVideoPorts)
  1952. {
  1953. // Check for the case where a video port has been created for
  1954. // VBI or video and we are now creating the other one, in which
  1955. // case we use the existing video port.
  1956. peVideoPort = peDirectDrawLocal->peVideoPort_DdList;
  1957. while ((peVideoPort != NULL) &&
  1958. (peVideoPort->ddvpDesc.dwVideoPortID != VideoPortDescription.dwVideoPortID))
  1959. {
  1960. peVideoPort = peVideoPort->peVideoPort_DdNext;
  1961. }
  1962. if (peVideoPort != NULL)
  1963. {
  1964. peVideoPort->ddvpDesc = VideoPortDescription;
  1965. CreateVPortData.ddRVal = DD_OK;
  1966. hRet = peVideoPort->hGet();
  1967. }
  1968. else
  1969. {
  1970. peVideoPort = (EDD_VIDEOPORT*) DdHmgAlloc(sizeof(EDD_VIDEOPORT),
  1971. DD_VIDEOPORT_TYPE,
  1972. HMGR_ALLOC_LOCK);
  1973. if (peVideoPort)
  1974. {
  1975. // Private data:
  1976. peVideoPort->peDirectDrawGlobal = peDirectDrawGlobal;
  1977. peVideoPort->peDirectDrawLocal = peDirectDrawLocal;
  1978. // Public data:
  1979. peVideoPort->lpDD = peDirectDrawGlobal;
  1980. peVideoPort->ddvpDesc = VideoPortDescription;
  1981. // Hold devlock for driver call and for bDdEnableSoftware
  1982. // Autoflipping.
  1983. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  1984. // Add this videoport to the list hanging off the
  1985. // DirectDrawLocal object allocated for this process:
  1986. bFirst = peDirectDrawLocal->peVideoPort_DdList == NULL;
  1987. peVideoPort->peVideoPort_DdNext
  1988. = peDirectDrawLocal->peVideoPort_DdList;
  1989. peDirectDrawLocal->peVideoPort_DdList
  1990. = peVideoPort;
  1991. // Now call the driver to create its version:
  1992. CreateVPortData.lpDD = peDirectDrawGlobal;
  1993. CreateVPortData.lpDDVideoPortDesc = &VideoPortDescription;
  1994. CreateVPortData.lpVideoPort = peVideoPort;
  1995. CreateVPortData.ddRVal = DDERR_GENERIC;
  1996. dwRet = DDHAL_DRIVER_NOTHANDLED; // Call is optional
  1997. if ((!peDirectDrawGlobal->bSuspended) &&
  1998. (peDirectDrawGlobal->VideoPortCallBacks.CreateVideoPort))
  1999. {
  2000. dwRet = peDirectDrawGlobal->
  2001. VideoPortCallBacks.CreateVideoPort(&CreateVPortData);
  2002. }
  2003. if ((dwRet == DDHAL_DRIVER_NOTHANDLED) ||
  2004. (CreateVPortData.ddRVal == DD_OK))
  2005. {
  2006. CreateVPortData.ddRVal = DD_OK;
  2007. peVideoPort->fl |= DD_VIDEOPORT_FLAG_DRIVER_CREATED;
  2008. }
  2009. else
  2010. {
  2011. WARNING("DxDvpCreateVideoPort: Driver failed call\n");
  2012. }
  2013. if ((CreateVPortData.ddRVal == DD_OK) &&
  2014. (bDdEnableSoftwareAutoflipping(peDirectDrawLocal,
  2015. peVideoPort,
  2016. VideoPortDescription.dwVideoPortID,
  2017. bFirst)))
  2018. {
  2019. // Success!
  2020. hRet = peVideoPort->hGet();
  2021. DEC_EXCLUSIVE_REF_CNT( peVideoPort );
  2022. }
  2023. else
  2024. {
  2025. bDdDeleteVideoPortObject(peVideoPort->hGet(), NULL);
  2026. CreateVPortData.ddRVal = DDERR_GENERIC;
  2027. }
  2028. }
  2029. }
  2030. }
  2031. else
  2032. {
  2033. WARNING("DxDvpCreateVideoPort: Bad parameters\n");
  2034. }
  2035. }
  2036. else
  2037. {
  2038. WARNING("DxDvpCreateVideoPort: Invalid object\n");
  2039. }
  2040. }
  2041. // We have to wrap this in another try-except because the user-mode
  2042. // memory containing the input may have been deallocated by now:
  2043. __try
  2044. {
  2045. ProbeAndWriteRVal(&puCreateVPortData->ddRVal, CreateVPortData.ddRVal);
  2046. }
  2047. __except(EXCEPTION_EXECUTE_HANDLER)
  2048. {
  2049. }
  2050. // Note that the user-mode stub always returns DDHAL_DRIVER_HANDLED
  2051. // to DirectDraw.
  2052. return(hRet);
  2053. }
  2054. /*****************************Private*Routine******************************\
  2055. * DWORD DxDvpDestroyVideoPort
  2056. *
  2057. * Notifies the HAL when the video port is destroyed.
  2058. *
  2059. * History:
  2060. * 2-Oct-1996 -by- Lingyun Wang [lingyunw]
  2061. * Wrote it.
  2062. \**************************************************************************/
  2063. DWORD
  2064. APIENTRY
  2065. DxDvpDestroyVideoPort(
  2066. HANDLE hVideoPort,
  2067. PDD_DESTROYVPORTDATA puDestroyVPortData
  2068. )
  2069. {
  2070. DWORD dwRet;
  2071. bDdDeleteVideoPortObject(hVideoPort, &dwRet);
  2072. __try
  2073. {
  2074. ProbeAndWriteRVal(&puDestroyVPortData->ddRVal, DD_OK);
  2075. }
  2076. __except(EXCEPTION_EXECUTE_HANDLER)
  2077. {
  2078. }
  2079. return(dwRet);
  2080. }
  2081. /*****************************Private*Routine******************************\
  2082. * DWORD DxDvpFlipVideoPort
  2083. *
  2084. * Performs the physical flip, causing the video port to start writing data
  2085. * to the new surface. This does not affect the actual display of this data.
  2086. *
  2087. * History:
  2088. * 2-Oct-1996 -by- Lingyun Wang [lingyunw]
  2089. * Wrote it.
  2090. \**************************************************************************/
  2091. DWORD
  2092. APIENTRY
  2093. DxDvpFlipVideoPort(
  2094. HANDLE hVideoPort,
  2095. HANDLE hDDSurfaceCurrent,
  2096. HANDLE hDDSurfaceTarget,
  2097. PDD_FLIPVPORTDATA puFlipVPortData
  2098. )
  2099. {
  2100. DWORD dwRet;
  2101. DD_FLIPVPORTDATA FlipVPortData;
  2102. dwRet = DDHAL_DRIVER_NOTHANDLED;
  2103. FlipVPortData.ddRVal = DDERR_GENERIC;
  2104. EDD_VIDEOPORT* peVideoPort;
  2105. EDD_LOCK_VIDEOPORT eLockVideoPort;
  2106. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  2107. // 1. Make sure they're videoport surfaces, and compatible, not system surfaces?
  2108. // 2. Make sure not software autoflipping?
  2109. peVideoPort = eLockVideoPort.peLock(hVideoPort);
  2110. if (peVideoPort != NULL)
  2111. {
  2112. peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
  2113. if (peDirectDrawGlobal->VideoPortCallBacks.FlipVideoPort)
  2114. {
  2115. EDD_SURFACE* peSurfaceCurrent;
  2116. EDD_SURFACE* peSurfaceTarget;
  2117. EDD_LOCK_SURFACE eLockSurfaceCurrent;
  2118. EDD_LOCK_SURFACE eLockSurfaceTarget;
  2119. peSurfaceCurrent = eLockSurfaceCurrent.peLock(hDDSurfaceCurrent);
  2120. peSurfaceTarget = eLockSurfaceTarget.peLock(hDDSurfaceTarget);
  2121. if ((peSurfaceCurrent != NULL) &&
  2122. (peSurfaceTarget != NULL) &&
  2123. (peSurfaceCurrent->peDirectDrawGlobal == peDirectDrawGlobal) &&
  2124. (peSurfaceCurrent->peDirectDrawLocal
  2125. == peSurfaceTarget->peDirectDrawLocal))
  2126. {
  2127. FlipVPortData.lpDD = peDirectDrawGlobal;
  2128. FlipVPortData.lpVideoPort = peVideoPort;
  2129. FlipVPortData.lpSurfCurr = peSurfaceCurrent;
  2130. FlipVPortData.lpSurfTarg = peSurfaceTarget;
  2131. {
  2132. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  2133. if ((!peDirectDrawGlobal->bSuspended) &&
  2134. (peDirectDrawGlobal->VideoPortCallBacks.FlipVideoPort))
  2135. {
  2136. dwRet = peDirectDrawGlobal->VideoPortCallBacks.
  2137. FlipVideoPort(&FlipVPortData);
  2138. }
  2139. }
  2140. if ((dwRet == DDHAL_DRIVER_HANDLED) &&
  2141. (FlipVPortData.ddRVal == DD_OK))
  2142. {
  2143. peVideoPort->lpSurface = peSurfaceTarget;
  2144. }
  2145. }
  2146. else
  2147. {
  2148. WARNING("DxDvpFlipVPort: Invalid source or target surface\n");
  2149. }
  2150. }
  2151. else
  2152. {
  2153. WARNING("DxDvpFlipVPort: Driver doesn't hook call\n");
  2154. }
  2155. }
  2156. else
  2157. {
  2158. WARNING("DxDvpFlipVPort: Invalid object\n");
  2159. }
  2160. __try
  2161. {
  2162. ProbeAndWriteRVal(&puFlipVPortData->ddRVal, FlipVPortData.ddRVal);
  2163. }
  2164. __except(EXCEPTION_EXECUTE_HANDLER)
  2165. {
  2166. }
  2167. return(dwRet);
  2168. }
  2169. /*****************************Private*Routine******************************\
  2170. * DWORD DxGetVideoPortBandwidth
  2171. *
  2172. * Informs the client of bandwidth requirements for any specified format,
  2173. * allowing them to better chose a format and to understand its limitations.
  2174. * This information can only be given after the video port object is created
  2175. * because the information in the DDVIDEOPORTDESC structure is required before
  2176. * accurate bandwidth information can be supplied.
  2177. *
  2178. * History:
  2179. * 2-Oct-1996 -by- Lingyun Wang [lingyunw]
  2180. * Wrote it.
  2181. \**************************************************************************/
  2182. DWORD
  2183. APIENTRY
  2184. DxDvpGetVideoPortBandwidth(
  2185. HANDLE hVideoPort,
  2186. PDD_GETVPORTBANDWIDTHDATA puGetVPortBandwidthData
  2187. )
  2188. {
  2189. DWORD dwRet;
  2190. DD_GETVPORTBANDWIDTHDATA GetVPortBandwidthData;
  2191. LPDDPIXELFORMAT pddpfFormat;
  2192. DDPIXELFORMAT ddpfFormat;
  2193. DDVIDEOPORTBANDWIDTH Bandwidth;
  2194. LPDDVIDEOPORTBANDWIDTH puBandwidth;
  2195. __try
  2196. {
  2197. GetVPortBandwidthData = ProbeAndReadStructure(puGetVPortBandwidthData,
  2198. DD_GETVPORTBANDWIDTHDATA);
  2199. ddpfFormat = ProbeAndReadStructure(GetVPortBandwidthData.lpddpfFormat,
  2200. DDPIXELFORMAT);
  2201. puBandwidth = GetVPortBandwidthData.lpBandwidth;
  2202. Bandwidth = ProbeAndReadStructure(puBandwidth,DDVIDEOPORTBANDWIDTH);
  2203. }
  2204. __except(EXCEPTION_EXECUTE_HANDLER)
  2205. {
  2206. return(DDHAL_DRIVER_NOTHANDLED);
  2207. }
  2208. dwRet = DDHAL_DRIVER_NOTHANDLED;
  2209. GetVPortBandwidthData.ddRVal = DDERR_GENERIC;
  2210. EDD_VIDEOPORT* peVideoPort;
  2211. EDD_LOCK_VIDEOPORT eLockVideoPort;
  2212. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  2213. peVideoPort = eLockVideoPort.peLock(hVideoPort);
  2214. if (peVideoPort != NULL)
  2215. {
  2216. peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
  2217. if (peDirectDrawGlobal->VideoPortCallBacks.GetVideoPortBandwidth)
  2218. {
  2219. GetVPortBandwidthData.lpDD = peDirectDrawGlobal;
  2220. GetVPortBandwidthData.lpVideoPort = peVideoPort;
  2221. GetVPortBandwidthData.lpBandwidth = &Bandwidth;
  2222. GetVPortBandwidthData.lpddpfFormat = &ddpfFormat;
  2223. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  2224. if ((!peDirectDrawGlobal->bSuspended) &&
  2225. (peDirectDrawGlobal->VideoPortCallBacks.GetVideoPortBandwidth))
  2226. {
  2227. dwRet = peDirectDrawGlobal->VideoPortCallBacks.
  2228. GetVideoPortBandwidth(&GetVPortBandwidthData);
  2229. }
  2230. }
  2231. else
  2232. {
  2233. WARNING("DxDvpGetVPortBandwidthData: Driver doesn't hook call\n");
  2234. }
  2235. }
  2236. else
  2237. {
  2238. WARNING("DxDvpGetVPortBandwidthData: Invalid object\n");
  2239. }
  2240. // We have to wrap this in another try-except because the user-mode
  2241. // memory containing the input may have been deallocated by now:
  2242. __try
  2243. {
  2244. ProbeAndWriteStructure(puBandwidth, Bandwidth, DDVIDEOPORTBANDWIDTH);
  2245. ProbeAndWriteRVal(&puGetVPortBandwidthData->ddRVal,
  2246. GetVPortBandwidthData.ddRVal);
  2247. }
  2248. __except(EXCEPTION_EXECUTE_HANDLER)
  2249. {
  2250. }
  2251. return(dwRet);
  2252. }
  2253. /*****************************Private*Routine******************************\
  2254. * DWORD DxDvpGetVideoPortField
  2255. *
  2256. * Sets bField to TRUE if the current field is the even field of an
  2257. * interlaced signal. Otherwise, bField is set to FALSE.
  2258. *
  2259. * History:
  2260. * 2-Oct-1996 -by- Lingyun Wang [lingyunw]
  2261. * Wrote it.
  2262. \**************************************************************************/
  2263. DWORD
  2264. APIENTRY
  2265. DxDvpGetVideoPortField(
  2266. HANDLE hVideoPort,
  2267. PDD_GETVPORTFIELDDATA puGetVPortFieldData
  2268. )
  2269. {
  2270. DWORD dwRet;
  2271. DD_GETVPORTFIELDDATA GetVPortFieldData;
  2272. __try
  2273. {
  2274. GetVPortFieldData = ProbeAndReadStructure(puGetVPortFieldData,
  2275. DD_GETVPORTFIELDDATA);
  2276. }
  2277. __except(EXCEPTION_EXECUTE_HANDLER)
  2278. {
  2279. return(DDHAL_DRIVER_NOTHANDLED);
  2280. }
  2281. dwRet = DDHAL_DRIVER_NOTHANDLED;
  2282. GetVPortFieldData.ddRVal = DDERR_GENERIC;
  2283. EDD_VIDEOPORT* peVideoPort;
  2284. EDD_LOCK_VIDEOPORT eLockVideoPort;
  2285. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  2286. peVideoPort = eLockVideoPort.peLock(hVideoPort);
  2287. if (peVideoPort != NULL)
  2288. {
  2289. peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
  2290. GetVPortFieldData.lpDD = peDirectDrawGlobal;
  2291. GetVPortFieldData.lpVideoPort = peVideoPort;
  2292. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  2293. if ((!peDirectDrawGlobal->bSuspended) &&
  2294. (peDirectDrawGlobal->VideoPortCallBacks.GetVideoPortField))
  2295. {
  2296. dwRet = peDirectDrawGlobal->
  2297. VideoPortCallBacks.GetVideoPortField(&GetVPortFieldData);
  2298. }
  2299. }
  2300. else
  2301. {
  2302. WARNING("DxDvpCanGetVPortFieldData: Invalid object\n");
  2303. }
  2304. // We have to wrap this in another try-except because the user-mode
  2305. // memory containing the input may have been deallocated by now:
  2306. __try
  2307. {
  2308. ProbeAndWriteRVal(&puGetVPortFieldData->ddRVal,
  2309. GetVPortFieldData.ddRVal);
  2310. ProbeAndWriteStructure(&puGetVPortFieldData->bField,
  2311. GetVPortFieldData.bField,
  2312. BOOL);
  2313. }
  2314. __except(EXCEPTION_EXECUTE_HANDLER)
  2315. {
  2316. }
  2317. return(dwRet);
  2318. }
  2319. /*****************************Private*Routine******************************\
  2320. * DWORD DxDvpGetVideoPortFlipStatus
  2321. *
  2322. * Returns DDERR_WASSTILLDRAWING if a video VSYNC has not occurred since the
  2323. * flip was performed on the specified surface. This function allows DDRAW.DLL
  2324. * to fail locks on a surface that was recently flipped from so the HAL doesn't
  2325. * have to account for this.
  2326. *
  2327. * History:
  2328. * 2-Oct-1996 -by- Lingyun Wang [lingyunw]
  2329. * Wrote it.
  2330. \**************************************************************************/
  2331. DWORD
  2332. APIENTRY
  2333. DxDvpGetVideoPortFlipStatus(
  2334. HANDLE hDirectDraw,
  2335. PDD_GETVPORTFLIPSTATUSDATA puGetVPortFlipStatusData
  2336. )
  2337. {
  2338. DWORD dwRet;
  2339. DD_GETVPORTFLIPSTATUSDATA GetVPortFlipStatusData;
  2340. __try
  2341. {
  2342. GetVPortFlipStatusData = ProbeAndReadStructure(puGetVPortFlipStatusData,
  2343. DD_GETVPORTFLIPSTATUSDATA);
  2344. }
  2345. __except(EXCEPTION_EXECUTE_HANDLER)
  2346. {
  2347. return(DDHAL_DRIVER_NOTHANDLED);
  2348. }
  2349. dwRet = DDHAL_DRIVER_NOTHANDLED;
  2350. GetVPortFlipStatusData.ddRVal = DDERR_GENERIC;
  2351. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal;
  2352. EDD_LOCK_DIRECTDRAW eLockDirectDraw;
  2353. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  2354. peDirectDrawLocal = eLockDirectDraw.peLock(hDirectDraw);
  2355. if (peDirectDrawLocal != NULL)
  2356. {
  2357. peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
  2358. GetVPortFlipStatusData.lpDD = peDirectDrawGlobal;
  2359. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  2360. if ((!peDirectDrawGlobal->bSuspended) &&
  2361. (peDirectDrawGlobal->VideoPortCallBacks.GetVideoPortFlipStatus))
  2362. {
  2363. dwRet = peDirectDrawGlobal->
  2364. VideoPortCallBacks.GetVideoPortFlipStatus(
  2365. &GetVPortFlipStatusData);
  2366. }
  2367. }
  2368. else
  2369. {
  2370. WARNING("DxDvpCanGetVPortFlipStatusData: Invalid object\n");
  2371. }
  2372. // We have to wrap this in another try-except because the user-mode
  2373. // memory containing the input may have been deallocated by now:
  2374. __try
  2375. {
  2376. ProbeAndWriteRVal(&puGetVPortFlipStatusData->ddRVal,
  2377. GetVPortFlipStatusData.ddRVal);
  2378. }
  2379. __except(EXCEPTION_EXECUTE_HANDLER)
  2380. {
  2381. }
  2382. return(dwRet);
  2383. }
  2384. /*****************************Private*Routine******************************\
  2385. * DWORD DxDvpGetVideoPortInputFormats
  2386. *
  2387. * Fills in the specified array with all of the formats that the video port
  2388. * can accept and puts that number in dwNumFormats. If lpddpfFormats is NULL,
  2389. * it only fills in dwNumFormats with the number of formats that it can support.
  2390. * This function is needed because the supported formats may vary depending on
  2391. * the electrical connection of the video port.
  2392. *
  2393. * History:
  2394. * 2-Oct-1996 -by- Lingyun Wang [lingyunw]
  2395. * Wrote it.
  2396. \**************************************************************************/
  2397. DWORD
  2398. APIENTRY
  2399. DxDvpGetVideoPortInputFormats(
  2400. HANDLE hVideoPort,
  2401. PDD_GETVPORTINPUTFORMATDATA puGetVPortInputFormatData
  2402. )
  2403. {
  2404. DWORD dwRet;
  2405. DD_GETVPORTINPUTFORMATDATA GetVPortInputFormatData;
  2406. LPDDPIXELFORMAT puFormat;
  2407. ULONG cjFormat;
  2408. HANDLE hSecure;
  2409. __try
  2410. {
  2411. GetVPortInputFormatData
  2412. = ProbeAndReadStructure(puGetVPortInputFormatData,
  2413. DD_GETVPORTINPUTFORMATDATA);
  2414. puFormat = GetVPortInputFormatData.lpddpfFormat;
  2415. }
  2416. __except(EXCEPTION_EXECUTE_HANDLER)
  2417. {
  2418. return(DDHAL_DRIVER_NOTHANDLED);
  2419. }
  2420. dwRet = DDHAL_DRIVER_NOTHANDLED;
  2421. GetVPortInputFormatData.ddRVal = DDERR_GENERIC;
  2422. EDD_VIDEOPORT* peVideoPort;
  2423. EDD_LOCK_VIDEOPORT eLockVideoPort;
  2424. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  2425. peVideoPort = eLockVideoPort.peLock(hVideoPort);
  2426. if (peVideoPort != NULL)
  2427. {
  2428. peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
  2429. GetVPortInputFormatData.lpDD = peDirectDrawGlobal;
  2430. GetVPortInputFormatData.lpVideoPort = peVideoPort;
  2431. GetVPortInputFormatData.lpddpfFormat = NULL;
  2432. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  2433. if ((!peDirectDrawGlobal->bSuspended) &&
  2434. (peDirectDrawGlobal->VideoPortCallBacks.GetVideoPortInputFormats))
  2435. {
  2436. dwRet = peDirectDrawGlobal->VideoPortCallBacks.
  2437. GetVideoPortInputFormats(&GetVPortInputFormatData);
  2438. cjFormat = GetVPortInputFormatData.dwNumFormats
  2439. * sizeof(DDPIXELFORMAT);
  2440. if ((dwRet == DDHAL_DRIVER_HANDLED) &&
  2441. (GetVPortInputFormatData.ddRVal == DD_OK) &&
  2442. (cjFormat > 0) &&
  2443. (puFormat != NULL) &&
  2444. !BALLOC_OVERFLOW1(GetVPortInputFormatData.dwNumFormats, DDPIXELFORMAT))
  2445. {
  2446. GetVPortInputFormatData.ddRVal = DDERR_GENERIC;
  2447. hSecure = 0;
  2448. __try
  2449. {
  2450. ProbeForWrite(puFormat, cjFormat, sizeof(UCHAR));
  2451. hSecure = MmSecureVirtualMemory(puFormat,
  2452. cjFormat,
  2453. PAGE_READWRITE);
  2454. }
  2455. __except(EXCEPTION_EXECUTE_HANDLER)
  2456. {
  2457. }
  2458. if (hSecure)
  2459. {
  2460. GetVPortInputFormatData.lpddpfFormat = puFormat;
  2461. dwRet = peDirectDrawGlobal->VideoPortCallBacks.
  2462. GetVideoPortInputFormats(&GetVPortInputFormatData);
  2463. MmUnsecureVirtualMemory(hSecure);
  2464. }
  2465. else
  2466. {
  2467. WARNING("DxDvpGetVideoPortInputFormats: Bad destination buffer\n");
  2468. }
  2469. }
  2470. }
  2471. }
  2472. else
  2473. {
  2474. WARNING("DxDvpGetVPortInputFormatData: Invalid object\n");
  2475. }
  2476. // We have to wrap this in another try-except because the user-mode
  2477. // memory containing the input may have been deallocated by now:
  2478. __try
  2479. {
  2480. ProbeAndWriteRVal(&puGetVPortInputFormatData->ddRVal,
  2481. GetVPortInputFormatData.ddRVal);
  2482. ProbeAndWriteUlong(&puGetVPortInputFormatData->dwNumFormats,
  2483. GetVPortInputFormatData.dwNumFormats);
  2484. }
  2485. __except(EXCEPTION_EXECUTE_HANDLER)
  2486. {
  2487. }
  2488. return(dwRet);
  2489. }
  2490. /*****************************Private*Routine******************************\
  2491. * DWORD DxDvpGetVideoPortOutputFormats
  2492. *
  2493. * Fills in the specified array with all of the formats that can be written
  2494. * to the frame buffer based on the specified input format and puts that
  2495. * number in dwNumFormats. If lpddpfOutputFormats is NULL, it only fills
  2496. * in dwNumFormats with the number of formats that can be written to the
  2497. * frame buffer.
  2498. *
  2499. * History:
  2500. * 2-Oct-1996 -by- Lingyun Wang [lingyunw]
  2501. * Wrote it.
  2502. \**************************************************************************/
  2503. DWORD
  2504. APIENTRY
  2505. DxDvpGetVideoPortOutputFormats(
  2506. HANDLE hVideoPort,
  2507. PDD_GETVPORTOUTPUTFORMATDATA puGetVPortOutputFormatData
  2508. )
  2509. {
  2510. DWORD dwRet;
  2511. DD_GETVPORTOUTPUTFORMATDATA GetVPortOutputFormatData;
  2512. LPDDPIXELFORMAT puOutputFormats;
  2513. DDPIXELFORMAT ddpfInputFormat;
  2514. ULONG cjFormat;
  2515. HANDLE hSecure;
  2516. __try
  2517. {
  2518. GetVPortOutputFormatData
  2519. = ProbeAndReadStructure(puGetVPortOutputFormatData,
  2520. DD_GETVPORTOUTPUTFORMATDATA);
  2521. ddpfInputFormat
  2522. = ProbeAndReadStructure(GetVPortOutputFormatData.lpddpfInputFormat,
  2523. DDPIXELFORMAT);
  2524. puOutputFormats = GetVPortOutputFormatData.lpddpfOutputFormats;
  2525. }
  2526. __except(EXCEPTION_EXECUTE_HANDLER)
  2527. {
  2528. return(DDHAL_DRIVER_NOTHANDLED);
  2529. }
  2530. dwRet = DDHAL_DRIVER_NOTHANDLED;
  2531. GetVPortOutputFormatData.ddRVal = DDERR_GENERIC;
  2532. EDD_VIDEOPORT* peVideoPort;
  2533. EDD_LOCK_VIDEOPORT eLockVideoPort;
  2534. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  2535. peVideoPort = eLockVideoPort.peLock(hVideoPort);
  2536. if (peVideoPort != NULL)
  2537. {
  2538. peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
  2539. GetVPortOutputFormatData.lpDD = peDirectDrawGlobal;
  2540. GetVPortOutputFormatData.lpVideoPort = peVideoPort;
  2541. GetVPortOutputFormatData.lpddpfInputFormat = &ddpfInputFormat;
  2542. GetVPortOutputFormatData.lpddpfOutputFormats = NULL;
  2543. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  2544. if ((!peDirectDrawGlobal->bSuspended) &&
  2545. (peDirectDrawGlobal->VideoPortCallBacks.GetVideoPortOutputFormats))
  2546. {
  2547. dwRet = peDirectDrawGlobal->VideoPortCallBacks.
  2548. GetVideoPortOutputFormats(&GetVPortOutputFormatData);
  2549. cjFormat = GetVPortOutputFormatData.dwNumFormats
  2550. * sizeof(DDPIXELFORMAT);
  2551. if ((dwRet == DDHAL_DRIVER_HANDLED) &&
  2552. (GetVPortOutputFormatData.ddRVal == DD_OK) &&
  2553. (cjFormat > 0) &&
  2554. (puOutputFormats != NULL) &&
  2555. !BALLOC_OVERFLOW1(GetVPortOutputFormatData.dwNumFormats, DDPIXELFORMAT))
  2556. {
  2557. GetVPortOutputFormatData.ddRVal = DDERR_GENERIC;
  2558. hSecure = 0;
  2559. __try
  2560. {
  2561. ProbeForWrite(puOutputFormats,
  2562. cjFormat,
  2563. sizeof(UCHAR));
  2564. hSecure = MmSecureVirtualMemory(puOutputFormats,
  2565. cjFormat,
  2566. PAGE_READWRITE);
  2567. }
  2568. __except(EXCEPTION_EXECUTE_HANDLER)
  2569. {
  2570. }
  2571. if (hSecure)
  2572. {
  2573. GetVPortOutputFormatData.lpddpfOutputFormats
  2574. = puOutputFormats;
  2575. dwRet = peDirectDrawGlobal->VideoPortCallBacks.
  2576. GetVideoPortOutputFormats(&GetVPortOutputFormatData);
  2577. MmUnsecureVirtualMemory(hSecure);
  2578. }
  2579. else
  2580. {
  2581. WARNING("DxDvpGetVideoPortOutputFormats: Bad destination buffer\n");
  2582. }
  2583. }
  2584. }
  2585. }
  2586. else
  2587. {
  2588. WARNING("DxDvpGetVPortOutputFormatData: Invalid object\n");
  2589. }
  2590. // We have to wrap this in another try-except because the user-mode
  2591. // memory containing the input may have been deallocated by now:
  2592. __try
  2593. {
  2594. ProbeAndWriteRVal(&puGetVPortOutputFormatData->ddRVal,
  2595. GetVPortOutputFormatData.ddRVal);
  2596. ProbeAndWriteUlong(&puGetVPortOutputFormatData->dwNumFormats,
  2597. GetVPortOutputFormatData.dwNumFormats);
  2598. }
  2599. __except(EXCEPTION_EXECUTE_HANDLER)
  2600. {
  2601. }
  2602. return(dwRet);
  2603. }
  2604. /*****************************Private*Routine******************************\
  2605. * DWORD DxGetVideoPortLine
  2606. *
  2607. * Returns the current line counter of the video port.
  2608. *
  2609. * This function is only required if the driver sets the DDVPCAPS_READBACKLINE
  2610. * flag.
  2611. *
  2612. * History:
  2613. * 2-Oct-1996 -by- Lingyun Wang [lingyunw]
  2614. * Wrote it.
  2615. \**************************************************************************/
  2616. DWORD
  2617. APIENTRY
  2618. DxDvpGetVideoPortLine(
  2619. HANDLE hVideoPort,
  2620. PDD_GETVPORTLINEDATA puGetVPortLineData
  2621. )
  2622. {
  2623. DWORD dwRet;
  2624. DD_GETVPORTLINEDATA GetVPortLineData;
  2625. dwRet = DDHAL_DRIVER_NOTHANDLED;
  2626. GetVPortLineData.ddRVal = DDERR_GENERIC;
  2627. EDD_VIDEOPORT* peVideoPort;
  2628. EDD_LOCK_VIDEOPORT eLockVideoPort;
  2629. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  2630. peVideoPort = eLockVideoPort.peLock(hVideoPort);
  2631. if (peVideoPort != NULL)
  2632. {
  2633. peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
  2634. GetVPortLineData.lpDD = peDirectDrawGlobal;
  2635. GetVPortLineData.lpVideoPort = peVideoPort;
  2636. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  2637. if ((!peDirectDrawGlobal->bSuspended) &&
  2638. (peDirectDrawGlobal->VideoPortCallBacks.GetVideoPortLine))
  2639. {
  2640. dwRet = peDirectDrawGlobal->
  2641. VideoPortCallBacks.GetVideoPortLine(&GetVPortLineData);
  2642. }
  2643. }
  2644. else
  2645. {
  2646. WARNING("DxDvpGetVPortLineData: Invalid object\n");
  2647. }
  2648. __try
  2649. {
  2650. ProbeAndWriteStructure(puGetVPortLineData,
  2651. GetVPortLineData,
  2652. DD_GETVPORTLINEDATA);
  2653. }
  2654. __except(EXCEPTION_EXECUTE_HANDLER)
  2655. {
  2656. }
  2657. return(dwRet);
  2658. }
  2659. /*****************************Private*Routine******************************\
  2660. * DWORD DxGetVideoPortConnectInfo
  2661. *
  2662. * Fills in the specified array with all of the connection combinations
  2663. * supported by the specified video port and puts that number in dwNumEntries.
  2664. * If lpConnect is NULL, it only fills in dwNumEntries with the number of
  2665. * DDVIDEOPORTCONNECT entries supported.
  2666. *
  2667. * History:
  2668. * 2-Oct-1996 -by- Lingyun Wang [lingyunw]
  2669. * Wrote it.
  2670. \**************************************************************************/
  2671. DWORD
  2672. APIENTRY
  2673. DxDvpGetVideoPortConnectInfo(
  2674. HANDLE hDirectDraw,
  2675. PDD_GETVPORTCONNECTDATA puGetVPortConnectData
  2676. )
  2677. {
  2678. DWORD dwRet;
  2679. DD_GETVPORTCONNECTDATA GetVPortConnectData;
  2680. DDVIDEOPORTCONNECT* puConnect;
  2681. ULONG cjConnect;
  2682. HANDLE hSecure;
  2683. __try
  2684. {
  2685. GetVPortConnectData = ProbeAndReadStructure(puGetVPortConnectData,
  2686. DD_GETVPORTCONNECTDATA);
  2687. puConnect = GetVPortConnectData.lpConnect;
  2688. }
  2689. __except(EXCEPTION_EXECUTE_HANDLER)
  2690. {
  2691. return(DDHAL_DRIVER_NOTHANDLED);
  2692. }
  2693. dwRet = DDHAL_DRIVER_NOTHANDLED;
  2694. GetVPortConnectData.ddRVal = DDERR_GENERIC;
  2695. EDD_DIRECTDRAW_LOCAL* peDirectDrawLocal;
  2696. EDD_LOCK_DIRECTDRAW eLockDirectDraw;
  2697. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  2698. peDirectDrawLocal = eLockDirectDraw.peLock(hDirectDraw);
  2699. if (peDirectDrawLocal != NULL)
  2700. {
  2701. peDirectDrawGlobal = peDirectDrawLocal->peDirectDrawGlobal;
  2702. GetVPortConnectData.lpDD = peDirectDrawGlobal;
  2703. GetVPortConnectData.lpConnect = NULL;
  2704. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  2705. if ((!peDirectDrawGlobal->bSuspended) &&
  2706. (peDirectDrawGlobal->VideoPortCallBacks.GetVideoPortConnectInfo))
  2707. {
  2708. dwRet = peDirectDrawGlobal->
  2709. VideoPortCallBacks.GetVideoPortConnectInfo(
  2710. &GetVPortConnectData);
  2711. cjConnect = GetVPortConnectData.dwNumEntries
  2712. * sizeof(DDVIDEOPORTCONNECT);
  2713. if ((dwRet == DDHAL_DRIVER_HANDLED) &&
  2714. (GetVPortConnectData.ddRVal == DD_OK) &&
  2715. (cjConnect > 0) &&
  2716. (puConnect != NULL) &&
  2717. !BALLOC_OVERFLOW1(GetVPortConnectData.dwNumEntries, DDVIDEOPORTCONNECT))
  2718. {
  2719. GetVPortConnectData.ddRVal = DDERR_GENERIC;
  2720. hSecure = 0;
  2721. __try
  2722. {
  2723. ProbeForWrite(puConnect, cjConnect, sizeof(UCHAR));
  2724. hSecure = MmSecureVirtualMemory(puConnect,
  2725. cjConnect,
  2726. PAGE_READWRITE);
  2727. }
  2728. __except(EXCEPTION_EXECUTE_HANDLER)
  2729. {
  2730. }
  2731. if (hSecure)
  2732. {
  2733. GetVPortConnectData.lpConnect = puConnect;
  2734. dwRet = peDirectDrawGlobal->VideoPortCallBacks.
  2735. GetVideoPortConnectInfo(&GetVPortConnectData);
  2736. MmUnsecureVirtualMemory(hSecure);
  2737. }
  2738. else
  2739. {
  2740. WARNING("DxDvpGetVideoPortConnectInfo: Bad destination buffer\n");
  2741. }
  2742. }
  2743. }
  2744. }
  2745. else
  2746. {
  2747. WARNING("DxDvpGetVPortConnectData: Invalid object\n");
  2748. }
  2749. // We have to wrap this in another try-except because the user-mode
  2750. // memory containing the input may have been deallocated by now:
  2751. __try
  2752. {
  2753. ProbeAndWriteRVal(&puGetVPortConnectData->ddRVal,
  2754. GetVPortConnectData.ddRVal);
  2755. ProbeAndWriteUlong(&puGetVPortConnectData->dwNumEntries,
  2756. GetVPortConnectData.dwNumEntries);
  2757. }
  2758. __except(EXCEPTION_EXECUTE_HANDLER)
  2759. {
  2760. }
  2761. return(dwRet);
  2762. }
  2763. /*****************************Private*Routine******************************\
  2764. * DxDvpGetVideoSignalStatus
  2765. *
  2766. * If the video port is receiving a good signal, the HAL should set dwStatus
  2767. * to DDVPSQ_SIGNALOK; otherwise, it should set dwStatus to DDVPSQ_NOSIGNAL.
  2768. *
  2769. *History:
  2770. * 2-Oct-1996 -by- Lingyun Wang [lingyunw]
  2771. * Wrote it.
  2772. \**************************************************************************/
  2773. DWORD
  2774. APIENTRY
  2775. DxDvpGetVideoSignalStatus(
  2776. HANDLE hVideoPort,
  2777. PDD_GETVPORTSIGNALDATA puGetVPortSignalData
  2778. )
  2779. {
  2780. DWORD dwRet;
  2781. DD_GETVPORTSIGNALDATA GetVPortSignalData;
  2782. dwRet = DDHAL_DRIVER_NOTHANDLED;
  2783. GetVPortSignalData.ddRVal = DDERR_GENERIC;
  2784. EDD_VIDEOPORT* peVideoPort;
  2785. EDD_LOCK_VIDEOPORT eLockVideoPort;
  2786. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  2787. peVideoPort = eLockVideoPort.peLock(hVideoPort);
  2788. if (peVideoPort != NULL)
  2789. {
  2790. peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
  2791. GetVPortSignalData.lpDD = peDirectDrawGlobal;
  2792. GetVPortSignalData.lpVideoPort = peVideoPort;
  2793. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  2794. if ((!peDirectDrawGlobal->bSuspended) &&
  2795. (peDirectDrawGlobal->VideoPortCallBacks.GetVideoSignalStatus))
  2796. {
  2797. dwRet = peDirectDrawGlobal->
  2798. VideoPortCallBacks.GetVideoSignalStatus(&GetVPortSignalData);
  2799. }
  2800. }
  2801. else
  2802. {
  2803. WARNING("DxDvpGetVPortSignalData: Invalid object\n");
  2804. }
  2805. __try
  2806. {
  2807. ProbeAndWriteStructure(puGetVPortSignalData,
  2808. GetVPortSignalData,
  2809. DD_GETVPORTSIGNALDATA);
  2810. }
  2811. __except(EXCEPTION_EXECUTE_HANDLER)
  2812. {
  2813. }
  2814. return(dwRet);
  2815. }
  2816. /*****************************Private*Routine******************************\
  2817. * DWORD DxDvpUpdateVideoPort
  2818. *
  2819. * Starts, stops, and changes the video port. dwFlags can contain either
  2820. * DDRAWI_VPORTSTART, DDRAWI_VPORTSTOP, or DDRAWI_VPORTUPDATE. To accommodate
  2821. * auto-flipping, lplpDDSurface and lplpDDVBISurface point to an array of
  2822. * surface structures rather than to a single structure. If autoflipping is
  2823. * requested, the dwNumAutoflip field contains the number of surfaces in the
  2824. * list.
  2825. *
  2826. * History:
  2827. * 2-Oct-1996 -by- Lingyun Wang [lingyunw]
  2828. * Wrote it.
  2829. \**************************************************************************/
  2830. DWORD
  2831. APIENTRY
  2832. DxDvpUpdateVideoPort(
  2833. HANDLE hVideoPort,
  2834. HANDLE* phSurfaceVideo,
  2835. HANDLE* phSurfaceVbi,
  2836. PDD_UPDATEVPORTDATA puUpdateVPortData
  2837. )
  2838. {
  2839. DWORD dwRet;
  2840. DD_UPDATEVPORTDATA UpdateVPortData;
  2841. DDVIDEOPORTINFO VideoPortInfo;
  2842. DDPIXELFORMAT ddpfInputFormat;
  2843. DDPIXELFORMAT ddpfVBIInputFormat;
  2844. DDPIXELFORMAT ddpfVBIOutputFormat;
  2845. HANDLE ahSurfaceVideo[MAX_AUTOFLIP_BUFFERS];
  2846. HANDLE ahSurfaceVbi[MAX_AUTOFLIP_BUFFERS];
  2847. EDD_SURFACE* apeSurfaceVideo[MAX_AUTOFLIP_BUFFERS];
  2848. EDD_SURFACE* apeSurfaceVbi[MAX_AUTOFLIP_BUFFERS];
  2849. DD_SURFACE_INT* apDDSurfaceVideo[MAX_AUTOFLIP_BUFFERS];
  2850. DD_SURFACE_INT* apDDSurfaceVbi[MAX_AUTOFLIP_BUFFERS];
  2851. ULONG cAutoflipVideo;
  2852. ULONG cAutoflipVbi;
  2853. EDD_DXVIDEOPORT* peDxVideoPort;
  2854. __try
  2855. {
  2856. UpdateVPortData = ProbeAndReadStructure(puUpdateVPortData,
  2857. DD_UPDATEVPORTDATA);
  2858. // Handle VideoPortInfo structure:
  2859. if (UpdateVPortData.dwFlags != DDRAWI_VPORTSTOP)
  2860. {
  2861. VideoPortInfo = ProbeAndReadStructure(UpdateVPortData.lpVideoInfo,
  2862. DDVIDEOPORTINFO);
  2863. if (VideoPortInfo.lpddpfInputFormat != NULL)
  2864. {
  2865. ddpfInputFormat
  2866. = ProbeAndReadStructure(VideoPortInfo.lpddpfInputFormat,
  2867. DDPIXELFORMAT);
  2868. VideoPortInfo.lpddpfInputFormat = &ddpfInputFormat;
  2869. }
  2870. if (VideoPortInfo.dwVBIHeight > 0)
  2871. {
  2872. if (VideoPortInfo.lpddpfVBIInputFormat != NULL)
  2873. {
  2874. ddpfVBIInputFormat
  2875. = ProbeAndReadStructure(VideoPortInfo.lpddpfVBIInputFormat,
  2876. DDPIXELFORMAT);
  2877. VideoPortInfo.lpddpfVBIInputFormat = &ddpfVBIInputFormat;
  2878. }
  2879. if (VideoPortInfo.lpddpfVBIOutputFormat != NULL)
  2880. {
  2881. ddpfVBIOutputFormat
  2882. = ProbeAndReadStructure(VideoPortInfo.lpddpfVBIOutputFormat,
  2883. DDPIXELFORMAT);
  2884. VideoPortInfo.lpddpfVBIOutputFormat = &ddpfVBIOutputFormat;
  2885. }
  2886. }
  2887. else
  2888. {
  2889. VideoPortInfo.lpddpfVBIInputFormat = NULL;
  2890. VideoPortInfo.lpddpfVBIOutputFormat = NULL;
  2891. }
  2892. }
  2893. // Handle arrays of surfaces:
  2894. cAutoflipVbi = 0;
  2895. cAutoflipVideo = 0;
  2896. if (UpdateVPortData.dwFlags != DDRAWI_VPORTSTOP)
  2897. {
  2898. cAutoflipVideo = min(UpdateVPortData.dwNumAutoflip, MAX_AUTOFLIP_BUFFERS);
  2899. if ((cAutoflipVideo == 0) && (UpdateVPortData.lplpDDSurface != NULL))
  2900. {
  2901. cAutoflipVideo = 1;
  2902. }
  2903. cAutoflipVbi = min(UpdateVPortData.dwNumVBIAutoflip, MAX_AUTOFLIP_BUFFERS);
  2904. if ((cAutoflipVbi == 0) && (UpdateVPortData.lplpDDVBISurface != NULL))
  2905. {
  2906. cAutoflipVbi = 1;
  2907. }
  2908. }
  2909. if (cAutoflipVideo)
  2910. {
  2911. ProbeForRead(phSurfaceVideo,
  2912. cAutoflipVideo * sizeof(HANDLE),
  2913. sizeof(HANDLE));
  2914. RtlCopyMemory(ahSurfaceVideo,
  2915. phSurfaceVideo,
  2916. cAutoflipVideo * sizeof(HANDLE));
  2917. }
  2918. if (cAutoflipVbi)
  2919. {
  2920. ProbeForRead(phSurfaceVbi,
  2921. cAutoflipVbi * sizeof(HANDLE),
  2922. sizeof(HANDLE));
  2923. RtlCopyMemory(ahSurfaceVbi,
  2924. phSurfaceVbi,
  2925. cAutoflipVbi * sizeof(HANDLE));
  2926. }
  2927. }
  2928. __except(EXCEPTION_EXECUTE_HANDLER)
  2929. {
  2930. return(DDHAL_DRIVER_NOTHANDLED);
  2931. }
  2932. dwRet = DDHAL_DRIVER_NOTHANDLED;
  2933. UpdateVPortData.ddRVal = DDERR_GENERIC;
  2934. EDD_VIDEOPORT* peVideoPort;
  2935. EDD_LOCK_VIDEOPORT eLockVideoPort;
  2936. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  2937. ULONG i;
  2938. EDD_SURFACE* peSurface;
  2939. BOOL bUpdateOK = TRUE;
  2940. peVideoPort = eLockVideoPort.peLock(hVideoPort);
  2941. if (peVideoPort != NULL)
  2942. {
  2943. peDxVideoPort = peVideoPort->peDxVideoPort;
  2944. peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
  2945. // Lock all the surfaces. Note that bDdUpdateLinksAndSynchronize
  2946. // will check for failure of DdHmgLock (the pointer will be NULL):
  2947. for (i = 0; i < cAutoflipVideo; i++)
  2948. {
  2949. apeSurfaceVideo[i] = (EDD_SURFACE*)
  2950. DdHmgLock((HDD_OBJ) ahSurfaceVideo[i], DD_SURFACE_TYPE, FALSE);
  2951. }
  2952. for (i = 0; i < cAutoflipVbi; i++)
  2953. {
  2954. apeSurfaceVbi[i] = (EDD_SURFACE*)
  2955. DdHmgLock((HDD_OBJ) ahSurfaceVbi[i], DD_SURFACE_TYPE, FALSE);
  2956. }
  2957. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  2958. if ((!peDirectDrawGlobal->bSuspended) &&
  2959. (peDirectDrawGlobal->VideoPortCallBacks.UpdateVideoPort) &&
  2960. (bUpdateOK = bDdUpdateLinksAndSynchronize(
  2961. peVideoPort,
  2962. TRUE, // Update video
  2963. apeSurfaceVideo,
  2964. cAutoflipVideo,
  2965. TRUE, // Update VBI
  2966. apeSurfaceVbi,
  2967. cAutoflipVbi)))
  2968. {
  2969. UpdateVPortData.lpDD = peDirectDrawGlobal;
  2970. UpdateVPortData.lpVideoPort = peVideoPort;
  2971. UpdateVPortData.lplpDDSurface = NULL;
  2972. UpdateVPortData.lplpDDVBISurface = NULL;
  2973. UpdateVPortData.dwNumAutoflip = cAutoflipVideo;
  2974. UpdateVPortData.dwNumVBIAutoflip = cAutoflipVbi;
  2975. UpdateVPortData.lpVideoInfo
  2976. = (UpdateVPortData.dwFlags == DDRAWI_VPORTSTOP)
  2977. ? NULL
  2978. : &VideoPortInfo;
  2979. if (cAutoflipVideo != 0)
  2980. {
  2981. for (i = 0; i < cAutoflipVideo; i++)
  2982. {
  2983. apDDSurfaceVideo[i] = apeSurfaceVideo[i];
  2984. }
  2985. UpdateVPortData.lplpDDSurface = apDDSurfaceVideo;
  2986. }
  2987. if (cAutoflipVbi != 0)
  2988. {
  2989. for (i = 0; i < cAutoflipVbi; i++)
  2990. {
  2991. apDDSurfaceVbi[i] = apeSurfaceVbi[i];
  2992. }
  2993. UpdateVPortData.lplpDDVBISurface = apDDSurfaceVbi;
  2994. }
  2995. // Turn off software autoflipping if necessary:
  2996. if (UpdateVPortData.dwFlags == DDRAWI_VPORTSTOP)
  2997. {
  2998. peDxVideoPort->bSoftwareAutoflip = FALSE;
  2999. peDxVideoPort->flFlags &= ~(DD_DXVIDEOPORT_FLAG_AUTOFLIP|DD_DXVIDEOPORT_FLAG_AUTOFLIP_VBI);
  3000. // Disable the video port VSYNC IRQ now
  3001. if( peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_ON )
  3002. {
  3003. peDxVideoPort->flFlags &= ~DD_DXVIDEOPORT_FLAG_ON;
  3004. peDirectDrawGlobal->pfnEnableIRQ(peDxVideoPort, FALSE );
  3005. }
  3006. }
  3007. // We don't allow switching back to hardware once software
  3008. // autoflipping has started (for various reasons, among
  3009. // them being how do we synchronize -- the hardware would
  3010. // start autoflipping before we could turn off the software
  3011. // autoflipping).
  3012. if (peDxVideoPort->bSoftwareAutoflip)
  3013. {
  3014. VideoPortInfo.dwVPFlags &= ~DDVP_AUTOFLIP;
  3015. }
  3016. // Make the HAL call:
  3017. dwRet = peDirectDrawGlobal->
  3018. VideoPortCallBacks.UpdateVideoPort(&UpdateVPortData);
  3019. // If we failed due to a request for hardware autoflipping,
  3020. // try again with software autoflipping.
  3021. if ((dwRet == DDHAL_DRIVER_HANDLED) &&
  3022. (UpdateVPortData.ddRVal != DD_OK) &&
  3023. (peDirectDrawGlobal->DDKernelCaps.dwCaps & DDKERNELCAPS_AUTOFLIP))
  3024. {
  3025. VideoPortInfo.dwVPFlags &= ~DDVP_AUTOFLIP;
  3026. dwRet = peDirectDrawGlobal->
  3027. VideoPortCallBacks.UpdateVideoPort(&UpdateVPortData);
  3028. if ((dwRet == DDHAL_DRIVER_HANDLED) &&
  3029. (UpdateVPortData.ddRVal == DD_OK))
  3030. {
  3031. KdPrint(("DxDvpUpdateVideoPort: Software autoflipping\n"));
  3032. peDxVideoPort->bSoftwareAutoflip = TRUE;
  3033. UpdateVPortData.ddRVal = DD_OK;
  3034. }
  3035. }
  3036. if ((UpdateVPortData.ddRVal == DD_OK) &&
  3037. peDxVideoPort->bSoftwareAutoflip)
  3038. {
  3039. if( cAutoflipVideo > 0 )
  3040. {
  3041. peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_AUTOFLIP;
  3042. }
  3043. if( cAutoflipVbi > 0 )
  3044. {
  3045. peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_AUTOFLIP_VBI;
  3046. }
  3047. }
  3048. }
  3049. if (!bUpdateOK)
  3050. {
  3051. WARNING("DxDvpUpdateVideoPort: failed on bDdUpdateLinksAndSynchronize");
  3052. }
  3053. if ((dwRet == DDHAL_DRIVER_HANDLED) &&
  3054. (UpdateVPortData.ddRVal == DD_OK))
  3055. {
  3056. // Success!
  3057. peVideoPort->dwNumAutoflip = cAutoflipVideo;
  3058. peVideoPort->dwNumVBIAutoflip = cAutoflipVbi;
  3059. if (UpdateVPortData.dwFlags != DDRAWI_VPORTSTOP)
  3060. {
  3061. peVideoPort->ddvpInfo = VideoPortInfo;
  3062. if (VideoPortInfo.lpddpfInputFormat != NULL)
  3063. {
  3064. peVideoPort->ddvpInfo.lpddpfInputFormat
  3065. = &peVideoPort->ddpfInputFormat;
  3066. peVideoPort->ddpfInputFormat = ddpfInputFormat;
  3067. }
  3068. else
  3069. {
  3070. peVideoPort->ddvpInfo.lpddpfInputFormat = NULL;
  3071. }
  3072. }
  3073. }
  3074. // Update various DXAPI state to reflect the changes:
  3075. vDdSynchronizeVideoPort(peVideoPort);
  3076. // If it wasn't previously on, enable the video port VSYNC IRQ now
  3077. //
  3078. // if bDdUpdateLinksAndSynchronize failed, don't enable.
  3079. if( (bUpdateOK) &&
  3080. (UpdateVPortData.dwFlags != DDRAWI_VPORTSTOP) &&
  3081. !(peDxVideoPort->flFlags & DD_DXVIDEOPORT_FLAG_ON) )
  3082. {
  3083. peDxVideoPort->flFlags |= DD_DXVIDEOPORT_FLAG_ON;
  3084. peDirectDrawGlobal->pfnEnableIRQ(peDxVideoPort, TRUE );
  3085. }
  3086. // Unlock the memory that I've locked
  3087. for (i = 0; i < cAutoflipVideo; i++)
  3088. {
  3089. if( apeSurfaceVideo[i] != NULL )
  3090. DEC_EXCLUSIVE_REF_CNT( apeSurfaceVideo[i] );
  3091. }
  3092. for (i = 0; i < cAutoflipVbi; i++)
  3093. {
  3094. if( apeSurfaceVbi[i] != NULL )
  3095. DEC_EXCLUSIVE_REF_CNT( apeSurfaceVbi[i] );
  3096. }
  3097. }
  3098. else
  3099. {
  3100. WARNING("DxDvpUpdateVPortData: Invalid object\n");
  3101. }
  3102. // We have to wrap this in another try-except because the user-mode
  3103. // memory containing the input may have been deallocated by now:
  3104. __try
  3105. {
  3106. ProbeAndWriteRVal(&puUpdateVPortData->ddRVal, UpdateVPortData.ddRVal);
  3107. }
  3108. __except(EXCEPTION_EXECUTE_HANDLER)
  3109. {
  3110. }
  3111. return(dwRet);
  3112. }
  3113. /*****************************Private*Routine******************************\
  3114. * DWORD DxDvpWaitForVideoPortSync
  3115. *
  3116. * Returns at the beginning or end of either the video VSYNC or the specified
  3117. * line. If the sync does not occur before the number of milliseconds
  3118. * specified in dwTimeOut has elapsed, the HAL should return
  3119. * DDERR_VIDEONOTACTIVE.
  3120. *
  3121. * History:
  3122. * 2-Oct-1996 -by- Lingyun Wang [lingyunw]
  3123. * Wrote it.
  3124. \**************************************************************************/
  3125. DWORD
  3126. APIENTRY
  3127. DxDvpWaitForVideoPortSync(
  3128. HANDLE hVideoPort,
  3129. PDD_WAITFORVPORTSYNCDATA puWaitForVPortSyncData
  3130. )
  3131. {
  3132. DWORD dwRet;
  3133. DD_WAITFORVPORTSYNCDATA WaitForVPortSyncData;
  3134. __try
  3135. {
  3136. WaitForVPortSyncData = ProbeAndReadStructure(puWaitForVPortSyncData,
  3137. DD_WAITFORVPORTSYNCDATA);
  3138. }
  3139. __except(EXCEPTION_EXECUTE_HANDLER)
  3140. {
  3141. return(DDHAL_DRIVER_NOTHANDLED);
  3142. }
  3143. dwRet = DDHAL_DRIVER_NOTHANDLED;
  3144. WaitForVPortSyncData.ddRVal = DDERR_GENERIC;
  3145. EDD_VIDEOPORT* peVideoPort;
  3146. EDD_LOCK_VIDEOPORT eLockVideoPort;
  3147. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  3148. peVideoPort = eLockVideoPort.peLock(hVideoPort);
  3149. if (peVideoPort != NULL)
  3150. {
  3151. peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
  3152. WaitForVPortSyncData.lpDD = peDirectDrawGlobal;
  3153. WaitForVPortSyncData.lpVideoPort = peVideoPort;
  3154. // Cap the number of milliseconds to wait to something reasonable:
  3155. if (WaitForVPortSyncData.dwTimeOut
  3156. > 6 * peVideoPort->ddvpDesc.dwMicrosecondsPerField)
  3157. {
  3158. WaitForVPortSyncData.dwTimeOut
  3159. = 6 * peVideoPort->ddvpDesc.dwMicrosecondsPerField;
  3160. }
  3161. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  3162. if ((!peDirectDrawGlobal->bSuspended) &&
  3163. (peDirectDrawGlobal->VideoPortCallBacks.WaitForVideoPortSync))
  3164. {
  3165. dwRet = peDirectDrawGlobal->VideoPortCallBacks.
  3166. WaitForVideoPortSync(&WaitForVPortSyncData);
  3167. }
  3168. }
  3169. else
  3170. {
  3171. WARNING("DxDvpWaitForVPortSyncData: Invalid object\n");
  3172. }
  3173. // We have to wrap this in another try-except because the user-mode
  3174. // memory containing the input may have been deallocated by now:
  3175. __try
  3176. {
  3177. ProbeAndWriteRVal(&puWaitForVPortSyncData->ddRVal,
  3178. WaitForVPortSyncData.ddRVal);
  3179. }
  3180. __except(EXCEPTION_EXECUTE_HANDLER)
  3181. {
  3182. }
  3183. return(dwRet);
  3184. }
  3185. /*****************************Private*Routine******************************\
  3186. * DWORD DxDvpColorControl
  3187. *
  3188. * Gets or sets the current color controls associated with the video port.
  3189. *
  3190. * History:
  3191. * 2-Oct-1996 -by- Lingyun Wang [lingyunw]
  3192. * Wrote it.
  3193. \**************************************************************************/
  3194. DWORD
  3195. APIENTRY
  3196. DxDvpColorControl(
  3197. HANDLE hVideoPort,
  3198. PDD_VPORTCOLORDATA puVPortColorData
  3199. )
  3200. {
  3201. DWORD dwRet;
  3202. DD_VPORTCOLORDATA VPortColorData;
  3203. DDCOLORCONTROL ColorData;
  3204. __try
  3205. {
  3206. VPortColorData = ProbeAndReadStructure(puVPortColorData,
  3207. DD_VPORTCOLORDATA);
  3208. ColorData = ProbeAndReadStructure(VPortColorData.lpColorData,
  3209. DDCOLORCONTROL);
  3210. }
  3211. __except(EXCEPTION_EXECUTE_HANDLER)
  3212. {
  3213. return(DDHAL_DRIVER_NOTHANDLED);
  3214. }
  3215. dwRet = DDHAL_DRIVER_NOTHANDLED;
  3216. VPortColorData.ddRVal = DDERR_GENERIC;
  3217. EDD_VIDEOPORT* peVideoPort;
  3218. EDD_LOCK_VIDEOPORT eLockVideoPort;
  3219. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  3220. peVideoPort = eLockVideoPort.peLock(hVideoPort);
  3221. if (peVideoPort != NULL)
  3222. {
  3223. peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
  3224. VPortColorData.lpDD = peDirectDrawGlobal;
  3225. VPortColorData.lpVideoPort = peVideoPort;
  3226. VPortColorData.lpColorData = &ColorData;
  3227. EDD_DEVLOCK eDevlock(peDirectDrawGlobal);
  3228. if ((!peDirectDrawGlobal->bSuspended) &&
  3229. (peDirectDrawGlobal->VideoPortCallBacks.ColorControl))
  3230. {
  3231. dwRet = peDirectDrawGlobal->
  3232. VideoPortCallBacks.ColorControl(&VPortColorData);
  3233. }
  3234. }
  3235. else
  3236. {
  3237. WARNING("DxDvpColorControl: Invalid object\n");
  3238. }
  3239. // We have to wrap this in another try-except because the user-mode
  3240. // memory containing the input may have been deallocated by now:
  3241. __try
  3242. {
  3243. ProbeAndWriteRVal(&puVPortColorData->ddRVal, VPortColorData.ddRVal);
  3244. }
  3245. __except(EXCEPTION_EXECUTE_HANDLER)
  3246. {
  3247. }
  3248. return(dwRet);
  3249. }
  3250. /*****************************Private*Routine******************************\
  3251. * DWORD DxDvpAcquireNotification
  3252. *
  3253. * Sets up the user mode notification of video port vsyncs.
  3254. *
  3255. * History:
  3256. * 10-Oct-2000 -Scott MacDonald [smac]
  3257. * Wrote it.
  3258. \**************************************************************************/
  3259. DWORD
  3260. APIENTRY
  3261. DxDvpAcquireNotification(
  3262. HANDLE hVideoPort,
  3263. HANDLE * phEvent,
  3264. LPDDVIDEOPORTNOTIFY pNotify
  3265. )
  3266. {
  3267. PKEVENT pEvent = NULL;
  3268. EDD_VIDEOPORT* peVideoPort;
  3269. EDD_LOCK_VIDEOPORT eLockVideoPort;
  3270. EDD_DIRECTDRAW_GLOBAL* peDirectDrawGlobal;
  3271. PMDL mdl;
  3272. LPDDVIDEOPORTNOTIFY pLockedBuffer;
  3273. __try
  3274. {
  3275. ProbeAndWriteHandle(phEvent, NULL);
  3276. }
  3277. __except(EXCEPTION_EXECUTE_HANDLER)
  3278. {
  3279. return DDHAL_DRIVER_NOTHANDLED;
  3280. }
  3281. // First check the caps to see if this device even supports a vport IRQ
  3282. peVideoPort = eLockVideoPort.peLock(hVideoPort);
  3283. if ((peVideoPort != NULL) &&
  3284. (peVideoPort->peDxVideoPort->pNotifyEvent == NULL))
  3285. {
  3286. peDirectDrawGlobal = peVideoPort->peDirectDrawGlobal;
  3287. if (peDirectDrawGlobal->DDKernelCaps.dwIRQCaps & DDIRQ_VPORT0_VSYNC )
  3288. {
  3289. // Now setup the buffer so it can be accessed at DPC level
  3290. mdl = IoAllocateMdl(pNotify,
  3291. sizeof(DDVIDEOPORTNOTIFY),
  3292. FALSE,
  3293. FALSE,
  3294. NULL);
  3295. if (mdl != NULL)
  3296. {
  3297. __try
  3298. {
  3299. MmProbeAndLockPages (mdl,
  3300. KernelMode,
  3301. IoWriteAccess);
  3302. }
  3303. __except(EXCEPTION_EXECUTE_HANDLER)
  3304. {
  3305. IoFreeMdl (mdl);
  3306. mdl = NULL;
  3307. }
  3308. }
  3309. if (mdl != NULL)
  3310. {
  3311. pLockedBuffer = (LPDDVIDEOPORTNOTIFY)
  3312. MmGetSystemAddressForMdlSafe (mdl,
  3313. NormalPagePriority);
  3314. if (pLockedBuffer == NULL)
  3315. {
  3316. MmUnlockPages (mdl);
  3317. IoFreeMdl (mdl);
  3318. }
  3319. else
  3320. {
  3321. // Now set up the event that we trigger
  3322. HANDLE h = NULL;
  3323. ZwCreateEvent( &h,
  3324. EVENT_ALL_ACCESS,
  3325. NULL,
  3326. SynchronizationEvent,
  3327. FALSE );
  3328. if (h != NULL)
  3329. {
  3330. (VOID) ObReferenceObjectByHandle( h,
  3331. 0,
  3332. 0,
  3333. KernelMode,
  3334. (PVOID *) &pEvent,
  3335. NULL );
  3336. }
  3337. if (pEvent != NULL)
  3338. {
  3339. ObDereferenceObject(pEvent);
  3340. peVideoPort->peDxVideoPort->pNotifyBuffer = pLockedBuffer;
  3341. peVideoPort->peDxVideoPort->pNotifyMdl = mdl;
  3342. peVideoPort->peDxVideoPort->pNotifyEvent = pEvent;
  3343. peVideoPort->peDxVideoPort->pNotifyEventHandle = h;
  3344. __try
  3345. {
  3346. ProbeAndWriteHandle(phEvent, h);
  3347. }
  3348. __except(EXCEPTION_EXECUTE_HANDLER)
  3349. {
  3350. }
  3351. }
  3352. else
  3353. {
  3354. MmUnlockPages (mdl);
  3355. IoFreeMdl (mdl);
  3356. }
  3357. }
  3358. // force software autoflipping
  3359. peVideoPort->peDxVideoPort->bSoftwareAutoflip = TRUE;
  3360. }
  3361. }
  3362. }
  3363. return 0;
  3364. }
  3365. /*****************************Private*Routine******************************\
  3366. * DWORD DxDvpReleaseNotification
  3367. *
  3368. * Stops up the user mode notification of video port vsyncs.
  3369. *
  3370. * History:
  3371. * 10-Oct-2000 -Scott MacDonald [smac]
  3372. * Wrote it.
  3373. \**************************************************************************/
  3374. DWORD
  3375. APIENTRY
  3376. DxDvpReleaseNotification(
  3377. HANDLE hVideoPort,
  3378. HANDLE pEvent
  3379. )
  3380. {
  3381. EDD_VIDEOPORT* peVideoPort;
  3382. EDD_LOCK_VIDEOPORT eLockVideoPort;
  3383. peVideoPort = eLockVideoPort.peLock(hVideoPort);
  3384. if ((peVideoPort != NULL) &&
  3385. (peVideoPort->peDxVideoPort->pNotifyEventHandle == pEvent) &&
  3386. (pEvent != NULL))
  3387. {
  3388. PKEVENT pTemp = NULL;
  3389. NTSTATUS Status;
  3390. peVideoPort->peDxVideoPort->pNotifyEvent = NULL;
  3391. peVideoPort->peDxVideoPort->pNotifyEventHandle = NULL;
  3392. // Make sure that the handle hasn't been freed by the OS already
  3393. Status = ObReferenceObjectByHandle( pEvent,
  3394. 0,
  3395. 0,
  3396. KernelMode,
  3397. (PVOID *) &pTemp,
  3398. NULL );
  3399. if ((pTemp != NULL) && (Status != STATUS_INVALID_HANDLE))
  3400. {
  3401. ObDereferenceObject(pTemp);
  3402. ZwClose (pEvent);
  3403. }
  3404. peVideoPort->peDxVideoPort->pNotifyBuffer = NULL;
  3405. if (peVideoPort->peDxVideoPort->pNotifyMdl != NULL)
  3406. {
  3407. MmUnlockPages (peVideoPort->peDxVideoPort->pNotifyMdl);
  3408. IoFreeMdl (peVideoPort->peDxVideoPort->pNotifyMdl);
  3409. peVideoPort->peDxVideoPort->pNotifyMdl = NULL;
  3410. }
  3411. }
  3412. return 0;
  3413. }