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.

2266 lines
74 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: OPENDC.CXX
  3. *
  4. * Handles DC creation and driver loading.
  5. *
  6. * Copyright (c) 1990-1999 Microsoft Corporation
  7. \**************************************************************************/
  8. #include "precomp.hxx"
  9. extern FLONG flRaster(ULONG, FLONG);
  10. /******************************Exported*Routine****************************\
  11. * GreCreateDisplayDC
  12. *
  13. * Opens a DC on the specified display PDEV.
  14. * Allocates space for a DC, fills in the defaults.
  15. * If successfull, increments the PDEV reference count.
  16. *
  17. \**************************************************************************/
  18. HDC
  19. GreCreateDisplayDC(
  20. HDEV hdev,
  21. ULONG iType,
  22. BOOL bAltType)
  23. {
  24. GDIFunctionID(GreCreateDisplayDC);
  25. HDC hdc = (HDC) NULL;
  26. //
  27. // We hold the devlock to protect against dynamic mode changes
  28. // while we're copying mode specific information to the DC.
  29. //
  30. PDEVOBJ pdo(hdev);
  31. DEVLOCKOBJ dlo(pdo);
  32. DCMEMOBJ dcmo(iType, bAltType);
  33. if (dcmo.bValid())
  34. {
  35. //
  36. // Copy info from the PDEV into the DC.
  37. //
  38. dcmo.pdc->ppdev((PDEV *) pdo.hdev());
  39. dcmo.pdc->flGraphicsCaps(pdo.flGraphicsCaps()); // cache it for later use by graphics output functions
  40. dcmo.pdc->flGraphicsCaps2(pdo.flGraphicsCaps2()); // cache it for later use by graphics output functions
  41. dcmo.pdc->dhpdev(pdo.dhpdev());
  42. dcmo.hsemDcDevLock(pdo.hsemDevLock());
  43. if (iType == DCTYPE_MEMORY)
  44. {
  45. SIZEL sizlTemp;
  46. sizlTemp.cx = 1;
  47. sizlTemp.cy = 1;
  48. dcmo.pdc->sizl(sizlTemp);
  49. }
  50. else
  51. {
  52. dcmo.pdc->sizl(pdo.sizl());
  53. //
  54. // The info and direct DC's for the screen need to grab
  55. // the semaphore before doing output, the memory DC's will
  56. // grab the semaphore only if a DFB is selected.
  57. //
  58. if (iType == DCTYPE_DIRECT)
  59. {
  60. dcmo.bSynchronizeAccess(pdo.bDisplayPDEV());
  61. dcmo.pdc->vDisplay(pdo.bDisplayPDEV());
  62. //
  63. // If this DC is created against with disabled PDEV,
  64. // mark it as full screen mode. All hdc on disbaled
  65. // PDEV should be marked as 'in fullscreen'.
  66. // (see PDEVOBJ::bDisabled(BOOL bDisable))
  67. //
  68. dcmo.pdc->bInFullScreen(pdo.bDisabled());
  69. if (!pdo.bPrinter())
  70. dcmo.pdc->pSurface(pdo.pSurface());
  71. }
  72. }
  73. //
  74. // Call the region code to set a default clip region.
  75. //
  76. if (dcmo.pdc->bSetDefaultRegion())
  77. {
  78. // If display PDEV, select in the System stock font.
  79. dcmo.vSetDefaultFont(pdo.bDisplayPDEV());
  80. // set user mode VisRect
  81. dcmo.pdc->vUpdate_VisRect(dcmo.pdc->prgnVis());
  82. if (GreSetupDCAttributes((HDC)(dcmo.pdc->hGet())))
  83. {
  84. // Mark the DC as permanent, hold the PDEV reference.
  85. dcmo.vKeepIt();
  86. // This will permanently increase the ref count to indicate
  87. // a new DC has been created.
  88. pdo.vReferencePdev();
  89. // turn on the DC_PRIMARY_DISPLAY flag for primary dc's
  90. if (hdev == UserGetHDEV())
  91. {
  92. dcmo.pdc->ulDirtyAdd(DC_PRIMARY_DISPLAY);
  93. }
  94. // finish initializing the DC.
  95. hdc = dcmo.hdc();
  96. }
  97. else
  98. {
  99. // DCMEMOBJ will be freed, delete vis region
  100. dcmo.pdc->vReleaseVis();
  101. // delete LOGFONT in DC which set by dcmo.vSetDefaultFont() in above.
  102. DEC_SHARE_REF_CNT_LAZY_DEL_LOGFONT(dcmo.pdc->plfntNew());
  103. }
  104. }
  105. if (hdc == NULL)
  106. {
  107. // dec reference counts on brush, pen and others
  108. // (which incremented in DCOBJ::DCOBJ())
  109. DEC_SHARE_REF_CNT_LAZY0(dcmo.pdc->pbrushFill());
  110. DEC_SHARE_REF_CNT_LAZY0(dcmo.pdc->pbrushLine());
  111. DEC_SHARE_REF_CNT_LAZY_DEL_COLORSPACE(dcmo.pdc->pColorSpace());
  112. }
  113. #if DBG
  114. else
  115. {
  116. // Enable visrgn validation from this point
  117. GreValidateVisrgn(hdc, TRUE);
  118. }
  119. #endif
  120. }
  121. return hdc;
  122. }
  123. /******************************Public*Routine******************************\
  124. * NtGdiCreateMetafileDC()
  125. *
  126. * History:
  127. * 01-Jun-1995 -by- Andre Vachon [andreva]
  128. * Wrote it.
  129. \**************************************************************************/
  130. HDC
  131. APIENTRY
  132. NtGdiCreateMetafileDC(
  133. HDC hdc
  134. )
  135. {
  136. HDC hdcNew = NULL;
  137. if (hdc)
  138. {
  139. //
  140. // Lock down the given DC.
  141. //
  142. DCOBJ dco(hdc);
  143. if (dco.bValid())
  144. {
  145. //
  146. // Allocate the DC, fill it with defaults.
  147. //
  148. hdcNew = GreCreateDisplayDC((HDEV) dco.pdc->ppdev(), DCTYPE_INFO, TRUE);
  149. }
  150. }
  151. else
  152. {
  153. //
  154. // We must call USER to get the current PDEV\HDEV for this thread
  155. // This should end up right back in GreCreateDisplayDC
  156. //
  157. hdcNew = UserGetDesktopDC(DCTYPE_INFO, TRUE, FALSE);
  158. }
  159. return hdcNew;
  160. }
  161. /******************************Public*Routine******************************\
  162. * NtGdiCreateCompatibleDC()
  163. *
  164. * History:
  165. * 01-Nov-1994 -by- Eric Kutter [erick]
  166. * Wrote it.
  167. \**************************************************************************/
  168. HDC
  169. APIENTRY
  170. NtGdiCreateCompatibleDC(
  171. HDC hdc
  172. )
  173. {
  174. HDC hdcRet = GreCreateCompatibleDC(hdc);
  175. //
  176. // Make sure user attributes are added to this dc
  177. //
  178. #if DBG
  179. if (hdcRet)
  180. {
  181. DCOBJ dco(hdcRet);
  182. if (dco.bValid())
  183. {
  184. ASSERTGDI((PENTRY_FROM_POBJ((POBJ)dco.pdc))->pUser != NULL,"NtGdiCreateCompatibleDC: pUser == NULL");
  185. }
  186. }
  187. #endif
  188. return(hdcRet);
  189. }
  190. /******************************Public*Routine******************************\
  191. * HDC GreCreateCompatibleDC(hdc)
  192. *
  193. * History:
  194. * 01-Jun-1995 -by- Andre Vachon [andreva]
  195. * Wrote it.
  196. *
  197. \**************************************************************************/
  198. HDC APIENTRY GreCreateCompatibleDC(HDC hdc)
  199. {
  200. HDC hdcNew = NULL;
  201. if (hdc)
  202. {
  203. //
  204. // Lock down the given DC.
  205. //
  206. DCOBJ dco(hdc);
  207. if (dco.bValid())
  208. {
  209. //
  210. // Allocate the DC, fill it with defaults.
  211. //
  212. hdcNew = GreCreateDisplayDC((HDEV) dco.pdc->ppdev(),
  213. DCTYPE_MEMORY,
  214. FALSE);
  215. //
  216. // If the compatible DC for a mirrored DC then mirror it.
  217. //
  218. if (hdcNew)
  219. {
  220. DWORD dwLayout = dco.pdc->dwLayout();
  221. if (dwLayout & LAYOUT_ORIENTATIONMASK)
  222. {
  223. GreSetLayout(hdcNew, -1, dwLayout);
  224. }
  225. }
  226. }
  227. }
  228. else
  229. {
  230. hdcNew = UserGetDesktopDC(DCTYPE_MEMORY, FALSE, FALSE);
  231. }
  232. return hdcNew;
  233. }
  234. /******************************Public*Routine******************************\
  235. * BOOL GreSelectRedirectionBitmap
  236. *
  237. * This routine selects a redirection bitmap into a redirection DC. A single
  238. * redirection bitmap can be selected into multiple redirection DCs.
  239. * Note: The caller needs to hold the devlock.
  240. * Note: The redirection bitmap must be in system memory because GDI may
  241. * attempt to convert it to a memory bitmap in the future (mode change,
  242. * speed optimizations in some code paths, etc.) and we cannot do that
  243. * here because there's no easy way of getting the list of redirection
  244. * DCs on that surface.
  245. *
  246. * Arguments:
  247. *
  248. * hdc -- The redirection DC as created by GreCreateRedirectionDC.
  249. *
  250. * hbitmap -- The redirection bitmap to be selected into hdc. This needs
  251. * to be a memory bitmap (but not DIB-section) which is compatible with
  252. * the display pdev.
  253. *
  254. * Return Value:
  255. *
  256. * True upon success
  257. *
  258. * History:
  259. * 21-Sep-1998 -by- Ori Gershony [orig]
  260. * Wrote it.
  261. *
  262. \**************************************************************************/
  263. BOOL
  264. APIENTRY
  265. GreSelectRedirectionBitmap(
  266. HDC hdc,
  267. HBITMAP hBitmap
  268. )
  269. {
  270. ULONG ulRet=TRUE;
  271. DCOBJA dco(hdc);
  272. if (dco.bValid())
  273. {
  274. SURFACE* pSurface = NULL;
  275. PDEVOBJ po(dco.hdev());
  276. #if DBG
  277. po.vAssertDevLock();
  278. #endif
  279. if (hBitmap == NULL)
  280. {
  281. dco.pdc->bRedirection(FALSE);
  282. pSurface = po.pSurface();
  283. }
  284. else
  285. {
  286. dco.pdc->bRedirection(TRUE);
  287. SURFREF surfref((HSURF) hBitmap);
  288. if (surfref.bValid())
  289. {
  290. pSurface = surfref.ps;
  291. ASSERTGDI((pSurface->iType() == STYPE_BITMAP) && (!(pSurface->fjBitmap() & BMF_NOTSYSMEM)),
  292. "GreSelectRedirectionBitmap: bitmap must be in system memory");
  293. ASSERTGDI(!pSurface->hDIBSection(),
  294. "GreSelectRedirectionBitmap: cannot select DIB-section into a redirection DC");
  295. PPALETTE ppalReference;
  296. ASSERTGDI(bIsCompatible(&ppalReference, NULL, pSurface, dco.hdev()),
  297. "GreSelectRedirectionBitmap: hBitmap not compatible with display hdev");
  298. //
  299. // Mark bitmap as redirection bitmap if not one already
  300. //
  301. if (!pSurface->bRedirection())
  302. {
  303. pSurface->vSetRedirection();
  304. }
  305. }
  306. }
  307. if (pSurface != NULL)
  308. {
  309. //
  310. // Replace the surface in all the saved DCs too.
  311. //
  312. if (dco.lSaveDepth() > 1)
  313. {
  314. ulRet = GreSelectRedirectionBitmap (dco.hdcSave(), hBitmap);
  315. //
  316. // The recursive call above should never fail, and we are not
  317. // setup to deal with failure correctly (need to undo change
  318. // to DC redirection flag, etc.). We can add code to do that,
  319. // but user (who calls us) cannot deal with failure either. So
  320. // instead we assert that this call succeeded.
  321. //
  322. ASSERTGDI(ulRet == TRUE,
  323. "GreSelectRedirectionBitmap: Recursive call on hdcSave failed");
  324. }
  325. if (ulRet)
  326. {
  327. //
  328. // Replace the pSurf reference in the DCLEVEL
  329. //
  330. dco.pdc->pSurface(pSurface);
  331. //
  332. // Set the size to that of the new surface
  333. //
  334. dco.pdc->sizl(pSurface->sizl());
  335. //
  336. // Make sure that the surface pointers in any EBRUSHOBJ's get
  337. // updated, by ensuring that vInitBrush() gets called the next
  338. // time any brush is used in this DC.
  339. //
  340. dco.pdc->flbrushAdd(DIRTY_BRUSHES);
  341. //
  342. // Note: we don't set the visrgn so that if user wants to reuse this dc over
  343. // the same redirection bitmap it won't have to recompute the visrgn (though it
  344. // will have to recompute it if it will be reused for a different redirection
  345. // bitmap).
  346. //
  347. }
  348. }
  349. else
  350. {
  351. ulRet = FALSE;
  352. }
  353. }
  354. else
  355. {
  356. ulRet = FALSE;
  357. }
  358. return ulRet;
  359. }
  360. /******************************Exported*Routine****************************\
  361. * hdcOpenDCW
  362. *
  363. * Opens a DC for a device which is not a display. GDI should call this
  364. * function from within DevOpenDC, in the case that an hdc is not passed
  365. * in. This call locates the device and creates a new PDEV. The physical
  366. * surface associated with this PDEV will be distinct from all other
  367. * physical surfaces.
  368. *
  369. * The window manager should not call this routine unless it is providing
  370. * printing services for an application.
  371. *
  372. * pwszDriver
  373. *
  374. * This points to a string which identifies the device driver.
  375. * The given string must be a fully qualified path name.
  376. *
  377. * pdriv
  378. *
  379. * This is a pointer to the DEVMODEW block.
  380. *
  381. * Since a single driver, like PSCRIPT.DRV, may support multiple
  382. * different devices, the szDeviceName field defines which device to
  383. * use.
  384. *
  385. * This structure also contains device specific data in abGeneralData.
  386. * This data is set by the device driver in bPostDeviceModes.
  387. *
  388. * If the pdriv pointer is NULL, the device driver assumes some default
  389. * configuration.
  390. *
  391. * iType
  392. *
  393. * Identifies the type of the DC. Must be one of DCTYPE_DIRECT,
  394. * DCTYPE_INFO, or DCTYPE_MEMORY.
  395. *
  396. * Returns:
  397. *
  398. * HDC - A handle to the DC.
  399. *
  400. \**************************************************************************/
  401. class PRINTER
  402. {
  403. public:
  404. HANDLE hSpooler_;
  405. BOOL bKeep;
  406. public:
  407. PRINTER(PWSZ pwszDevice,DEVMODEW *pdriv,HANDLE hspool );
  408. ~PRINTER()
  409. {
  410. if (!bKeep && (hSpooler_ != (HANDLE) NULL))
  411. ClosePrinter(hSpooler_);
  412. }
  413. BOOL bValid() {return(hSpooler_ != (HANDLE) NULL);}
  414. VOID vKeepIt() {bKeep = TRUE;}
  415. HANDLE hSpooler() {return(hSpooler_);}
  416. };
  417. // PRINTER constructor -- Attempts to open a spooler connection to the
  418. // printer.
  419. PRINTER::PRINTER(
  420. PWSZ pwszDevice,
  421. DEVMODEW *pdriv,
  422. HANDLE hspool )
  423. {
  424. bKeep = FALSE;
  425. PRINTER_DEFAULTSW defaults;
  426. defaults.pDevMode = pdriv;
  427. defaults.DesiredAccess = PRINTER_ACCESS_USE;
  428. //
  429. // Attempt to open the printer for spooling journal files.
  430. // NOTE: For debugging, a global flag disables journaling.
  431. //
  432. defaults.pDatatype = (LPWSTR) L"RAW";
  433. if (hspool)
  434. {
  435. hSpooler_ = hspool;
  436. }
  437. else
  438. {
  439. if (!OpenPrinterW(pwszDevice,&hSpooler_,&defaults))
  440. {
  441. //
  442. // It's not a printer. OpenPrinterW doesn't guarantee the value
  443. // of hSpooler in this case, so we have to clear it.
  444. //
  445. hSpooler_ = (HANDLE) NULL;
  446. }
  447. }
  448. return;
  449. }
  450. /******************************Public*Routine******************************\
  451. * See comments above.
  452. *
  453. * History:
  454. * Andre Vachon [andreva]
  455. *
  456. \**************************************************************************/
  457. HDC hdcOpenDCW(
  458. PWSZ pwszDevice, // The device driver name.
  459. DEVMODEW *pdriv, // Driver data.
  460. ULONG iType, // Identifies the type of DC to create.
  461. HANDLE hspool, // do we already have a spooler handle?
  462. PREMOTETYPEONENODE prton,
  463. DRIVER_INFO_2W *pDriverInfo2, // we pass in pDriverInfo for UMPD, NULL otherwise
  464. PVOID pUMdhpdev
  465. )
  466. {
  467. HDC hdc = (HDC) 0; // Prepare for the worst.
  468. DWORD cbNeeded = 0;
  469. PVOID mDriverInfo;
  470. BOOL bUMPD = pDriverInfo2 ? TRUE: FALSE; // TRUE if User Mode driver
  471. TRACE_INIT(("\nhdcOpenDCW: ENTERING\n"));
  472. //
  473. // Attempt to open a display DC.
  474. //
  475. if (pwszDevice && !bUMPD)
  476. {
  477. PMDEV pmdev = NULL;
  478. HDEV hdev = NULL;
  479. UNICODE_STRING usDevice;
  480. RtlInitUnicodeString(&usDevice,
  481. pwszDevice);
  482. if (pdriv == NULL)
  483. {
  484. //
  485. // If no DEVMODE is present, then we just want to create a DC on
  486. // the specific device.
  487. // This will allow an application to make some escape calls to a
  488. // specific device\driver.
  489. //
  490. hdev = DrvGetHDEV(&usDevice);
  491. }
  492. else
  493. {
  494. //
  495. // We have to acquire the USER lock to synchronize with
  496. // ChangeDisplaySettings.
  497. //
  498. UserEnterUserCritSec();
  499. TRACE_INIT(("hdcOpenDCW: Trying to open as a second display device\n"));
  500. //
  501. // Only let the user do this if the device is not part of the
  502. // desktop.
  503. //
  504. pmdev = DrvCreateMDEV(&usDevice,
  505. pdriv,
  506. (PVOID) (ULONG_PTR)0xFFFFFFFF,
  507. GRE_DISP_CREATE_NODISABLE |
  508. GRE_DISP_NOT_APARTOF_DESKTOP,
  509. NULL,
  510. KernelMode,
  511. GRE_RAWMODE,
  512. FALSE); // buffer is captured in NtGdiOpenDCW()
  513. if (!pmdev)
  514. {
  515. DWORD dwDesktopId;
  516. if (UserGetCurrentDesktopId(&dwDesktopId))
  517. {
  518. //
  519. // Try match from current desktop display.
  520. // but don't create new display instance.
  521. //
  522. pmdev = DrvCreateMDEV(&usDevice,
  523. pdriv,
  524. (PVOID) (ULONG_PTR) dwDesktopId,
  525. GRE_DISP_CREATE_NODISABLE |
  526. GRE_DISP_NOT_APARTOF_DESKTOP,
  527. NULL,
  528. KernelMode,
  529. GRE_RAWMODE,
  530. FALSE);
  531. }
  532. }
  533. UserLeaveUserCritSec();
  534. if (pmdev)
  535. {
  536. TRACE_INIT(("Drv_Trace: CreateExclusiveDC: We have an hdev\n"));
  537. ASSERTGDI(pmdev->chdev == 1,"hdcOpenDCW(): pmdev->chdev != 1");
  538. hdev = pmdev->Dev[0].hdev;
  539. }
  540. }
  541. if (hdev)
  542. {
  543. hdc = GreCreateDisplayDC(hdev, DCTYPE_DIRECT, FALSE);
  544. if (hdc)
  545. {
  546. if (pmdev || hdev)
  547. {
  548. DCOBJ dco(hdc);
  549. PDEVOBJ po(dco.hdev());
  550. //
  551. // Dereference the object since we want DeleteDC
  552. // to automatically destroy the PDEV.
  553. //
  554. // This basically counteracts the extra reference that it done
  555. // by DrvCreateMDEV(), or DrvGetHDEV().
  556. //
  557. po.vUnreferencePdev();
  558. }
  559. }
  560. else
  561. {
  562. TRACE_INIT(("hdcOpenDCW: Failed to get DC\n"));
  563. if (pmdev)
  564. {
  565. DrvDestroyMDEV(pmdev);
  566. }
  567. else
  568. {
  569. PDEVOBJ po(hdev);
  570. po.vUnreferencePdev();
  571. }
  572. }
  573. }
  574. if (pmdev)
  575. {
  576. VFREEMEM(pmdev);
  577. }
  578. }
  579. //
  580. // Attempt to open a new printer DC.
  581. //
  582. if (hdc == NULL)
  583. {
  584. //
  585. // Open the spooler connection to the printer.
  586. // Allocate space for DRIVER_INFO.
  587. //
  588. PRINTER print(pwszDevice, pdriv, hspool);
  589. if (print.bValid())
  590. {
  591. if (!bUMPD)
  592. {
  593. if (mDriverInfo = PALLOCMEM(512, 'pmtG'))
  594. {
  595. //
  596. // Fill the DRIVER_INFO.
  597. //
  598. if (!GetPrinterDriverW(
  599. print.hSpooler(),
  600. NULL,
  601. 2,
  602. (LPBYTE) mDriverInfo,
  603. 512,
  604. &cbNeeded))
  605. {
  606. //
  607. // Call failed - free the memory.
  608. //
  609. VFREEMEM(mDriverInfo);
  610. mDriverInfo = NULL;
  611. //
  612. // Get more space if we need it.
  613. //
  614. if ((EngGetLastError() == ERROR_INSUFFICIENT_BUFFER) &&
  615. (cbNeeded > 0))
  616. {
  617. if (mDriverInfo = PALLOCMEM(cbNeeded, 'pmtG'))
  618. {
  619. if (!GetPrinterDriverW(print.hSpooler(),
  620. NULL,
  621. 2,
  622. (LPBYTE) mDriverInfo,
  623. cbNeeded,
  624. &cbNeeded))
  625. {
  626. VFREEMEM(mDriverInfo);
  627. mDriverInfo = NULL;
  628. }
  629. }
  630. }
  631. }
  632. }
  633. }
  634. else
  635. {
  636. //
  637. // we have a pDriverInfo2 passed in for UMPD
  638. //
  639. mDriverInfo = pDriverInfo2;
  640. }
  641. if (mDriverInfo != (PVOID) NULL)
  642. {
  643. PLDEV pldev;
  644. if ( bUMPD)
  645. {
  646. //
  647. // we fake a pldev for each LoadDriver call.
  648. // the real driver list is kept at the client side as a pUMPD list
  649. //
  650. pldev = UMPD_ldevLoadDriver(((DRIVER_INFO_2W *)mDriverInfo)->pDriverPath,
  651. LDEV_DEVICE_PRINTER);
  652. }
  653. else
  654. {
  655. pldev = ldevLoadDriver(((DRIVER_INFO_2W *)mDriverInfo)->pDriverPath,
  656. LDEV_DEVICE_PRINTER);
  657. }
  658. if (pldev == NULL)
  659. {
  660. SAVE_ERROR_CODE(ERROR_BAD_DRIVER_LEVEL);
  661. }
  662. else
  663. {
  664. //
  665. // Create a PDEV. If no DEVMODEW passed in from above,
  666. // use the default from the printer structure.
  667. //
  668. PDEVOBJ po(pldev,
  669. (PDEVMODEW) pdriv,
  670. pwszDevice,
  671. ((DRIVER_INFO_2W *)mDriverInfo)->pDataFile,
  672. ((DRIVER_INFO_2W *)mDriverInfo)->pName,
  673. print.hSpooler(),
  674. prton,
  675. NULL,
  676. NULL,
  677. bUMPD);
  678. if (po.bValid())
  679. {
  680. //
  681. // Make a note that this is a printer.
  682. //
  683. po.bPrinter(TRUE);
  684. //
  685. // Allocate the DC, fill it with defaults.
  686. //
  687. hdc = GreCreateDisplayDC(po.hdev(),
  688. iType,
  689. TRUE);
  690. //
  691. // If the DC was properly create, keep the printer
  692. // object so the printer stays open
  693. if (hdc)
  694. {
  695. print.vKeepIt();
  696. if (bUMPD && pUMdhpdev)
  697. {
  698. __try
  699. {
  700. ProbeForWritePointer(pUMdhpdev);
  701. *(PUMDHPDEV *)pUMdhpdev = (PUMDHPDEV)po.dhpdev();
  702. }
  703. __except(EXCEPTION_EXECUTE_HANDLER)
  704. {
  705. bDeleteDCInternal(hdc, FALSE, FALSE);
  706. hdc = 0;
  707. }
  708. }
  709. }
  710. //
  711. // Always delete the PEV reference count.
  712. // If the DC was created, the DC keeps the ref count
  713. // at 1, and the PDEV will get destroyed when the
  714. // DC gets destroyed.
  715. // If the DC was not created properly, this will cause
  716. // the PDEV to get destroyed immediately.
  717. //
  718. po.vUnreferencePdev();
  719. }
  720. else
  721. {
  722. if (!bUMPD)
  723. {
  724. ldevUnloadImage(pldev);
  725. }
  726. else
  727. {
  728. UMPD_ldevUnloadImage(pldev);
  729. }
  730. }
  731. }
  732. if (!bUMPD)
  733. {
  734. VFREEMEM(mDriverInfo);
  735. }
  736. }
  737. }
  738. }
  739. if (hdc == (HDC) NULL)
  740. {
  741. WARNING("opendc.cxx: failed to create DC in hdcOpenDCW\n");
  742. }
  743. return(hdc);
  744. }
  745. /******************************Public*Routine******************************\
  746. * GreResetDCInternal
  747. *
  748. * Reset the mode of a DC. The DC returned will be a different DC than
  749. * the original. The only common piece between the original DC and the
  750. * new one is the hSpooler.
  751. *
  752. * There are a number of intresting problems to be carefull of. The
  753. * original DC can be an info DC. The new one will always be a direct DC.
  754. *
  755. * Also, it is important to be carefull of the state of the DC when this
  756. * function is called and the effects of journaling vs non journaling.
  757. * In the case of journaling, the spooler is responsible for doing a CreateDC
  758. * to play the journal file to. For this reason, the spooler must have the
  759. * current DEVMODE. For this reason, ResetDC must call ResetPrinter for
  760. * spooled DC's.
  761. *
  762. * ResetDC can happen at any time other than between StartPage-EndPage, even
  763. * before StartDoc.
  764. *
  765. *
  766. * History:
  767. * 13-Jan-1994 -by- Eric Kutter [erick]
  768. * Wrote it.
  769. \**************************************************************************/
  770. extern "C" BOOL GreResetDCInternal(
  771. HDC hdc,
  772. DEVMODEW *pdmw, // Driver data.
  773. BOOL *pbBanding,
  774. DRIVER_INFO_2W *pDriverInfo2,
  775. PVOID ppUMdhpdev)
  776. {
  777. BOOL bSurf;
  778. BOOL bTempInfoDC = FALSE;
  779. HDC hdcNew;
  780. BOOL bRet = FALSE;
  781. // we need this set of brackets so the DC's get unlocked before we try to delete
  782. // the dc>
  783. {
  784. DCOBJ dco(hdc);
  785. if (!dco.bValid())
  786. {
  787. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  788. }
  789. else
  790. {
  791. // if this has been made into a TempInfoDC for printing, undo it now
  792. bTempInfoDC = dco.pdc->bTempInfoDC();
  793. if (bTempInfoDC)
  794. dco.pdc->bMakeInfoDC(FALSE);
  795. PDEVOBJ po(dco.hdev());
  796. // get list of Type1 remote type one fonts if there is one and transfer
  797. // it accross PDEV's.
  798. PREMOTETYPEONENODE prton = po.RemoteTypeOneGet();
  799. po.RemoteTypeOneSet(NULL);
  800. // This call only makes sense on RASTER technology printers.
  801. if (!dco.bKillReset() &&
  802. !(dco.dctp() == DCTYPE_MEMORY) &&
  803. (po.bPrinter()))
  804. {
  805. // First, remember if a surface needs to be created
  806. bSurf = dco.bHasSurface();
  807. // Now, clean up the DC
  808. if (dco.bCleanDC())
  809. {
  810. // If there are any outstanding references to this PDEV, fail.
  811. if (((PDEV *) po.hdev())->cPdevRefs == 1)
  812. {
  813. // create the new DC
  814. hdcNew = hdcOpenDCW(L"",
  815. pdmw,
  816. DCTYPE_DIRECT,
  817. po.hSpooler(),
  818. prton,
  819. pDriverInfo2,
  820. ppUMdhpdev);
  821. if (hdcNew)
  822. {
  823. // don't want to delete the spooler handle since it
  824. // is in the new DC
  825. po.hSpooler(NULL);
  826. // lock down the new DC and PDEV
  827. DCOBJ dcoNew(hdcNew);
  828. if (!dcoNew.bValid())
  829. {
  830. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  831. }
  832. else
  833. {
  834. // Transfer any remote fonts
  835. dcoNew.PFFListSet(dco.PFFListGet());
  836. dco.PFFListSet(NULL);
  837. // Transfer any color transform
  838. dcoNew.CXFListSet(dco.CXFListGet());
  839. dco.CXFListSet(NULL);
  840. PDEVOBJ poNew((HDEV) dcoNew.pdc->ppdev());
  841. // let the driver know
  842. PFN_DrvResetPDEV rfn = PPFNDRV(po,ResetPDEV);
  843. if (rfn != NULL)
  844. {
  845. (*rfn)(po.dhpdev(),poNew.dhpdev());
  846. }
  847. // now swap the two handles
  848. {
  849. MLOCKFAST mlo;
  850. BOOL bRes = HmgSwapLockedHandleContents((HOBJ)hdc,0,(HOBJ)hdcNew,0,DC_TYPE);
  851. ASSERTGDI(bRes,"GreResetDC - SwapHandleContents failed\n");
  852. }
  853. bRet = TRUE;
  854. }
  855. }
  856. }
  857. }
  858. }
  859. }
  860. // DON'T DO ANYTHING HERE, the dcobj's don't match the handles, so
  861. // unlock them first
  862. }
  863. if (bRet)
  864. {
  865. // got a new dc, get rid of the old one (remember the handles have
  866. // been swapped)
  867. bDeleteDCInternal(hdcNew,TRUE,FALSE);
  868. // now deal with the new one
  869. DCOBJ newdco(hdc);
  870. if (!newdco.bValid())
  871. {
  872. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  873. bRet = FALSE;
  874. }
  875. else
  876. {
  877. PDEVOBJ newpo(newdco.hdev());
  878. // Create a new surface for the DC.
  879. if (bSurf)
  880. {
  881. if (!newpo.bMakeSurface())
  882. {
  883. bRet = FALSE;
  884. }
  885. else
  886. {
  887. newdco.pdc->pSurface(newpo.pSurface());
  888. *pbBanding = newpo.pSurface()->bBanding();
  889. if( *pbBanding )
  890. {
  891. // if banding set Clip rectangle to size of band
  892. newdco.pdc->sizl((newpo.pSurface())->sizl());
  893. newdco.pdc->bSetDefaultRegion();
  894. }
  895. PFN_DrvStartDoc pfnDrvStartDoc = PPFNDRV(newpo, StartDoc);
  896. (*pfnDrvStartDoc)(newpo.pSurface()->pSurfobj(),NULL,0);
  897. }
  898. }
  899. else
  900. {
  901. // important to set this to FALSE is a surface has not yet been created
  902. // ie StartDoc has not yet been called.
  903. *pbBanding = FALSE;
  904. }
  905. // if the original was a tempinfo dc for printing, this one needs to be too.
  906. if (bRet && bTempInfoDC)
  907. {
  908. newdco.pdc->bMakeInfoDC(TRUE);
  909. }
  910. }
  911. }
  912. return(bRet);
  913. }
  914. /******************************Public*Routine******************************\
  915. * bDynamicMatchEnoughForModeChange
  916. *
  917. * We can dynamically change modes only if the new mode matches the old
  918. * in certain respects. This is because, for example, we don't have code
  919. * written to track down all the places where flGraphicsCaps has been copied,
  920. * and then change it asynchronously.
  921. *
  922. * History:
  923. * 8-Feb-1996 -by- J. Andrew Goossen [andrewgo]
  924. * Wrote it.
  925. \**************************************************************************/
  926. BOOL
  927. bDynamicMatchEnoughForModeChange(
  928. HDEV hdevOld,
  929. HDEV hdevNew
  930. )
  931. {
  932. PDEVOBJ poOld(hdevOld);
  933. PDEVOBJ poNew(hdevNew);
  934. BOOL b = TRUE;
  935. // We would get quite confused with converting monochrome bitmaps if
  936. // we were to handle 1bpp:
  937. if ((poOld.iDitherFormat() == BMF_1BPP) ||
  938. (poNew.iDitherFormat() == BMF_1BPP))
  939. {
  940. WARNING("bDynamicMatchEnoughForModeChange: Can't handle 1bpp");
  941. b = FALSE;
  942. }
  943. // Some random stuff must be the same between the old instance and
  944. // the new:
  945. //
  946. // We impose the restriction that some flGraphicsCaps flags must stay
  947. // the same with the new mode. Specifically, we can't allow the
  948. // following to change:
  949. //
  950. // o We don't allow GCAPS_HIGHRESTEXT to change because ESTROBJ::
  951. // vInit needs to look at it sometimes without acquiring a lock,
  952. // and it's pretty much a printer specific feature anyway.
  953. // o We don't allow GCAPS_FORCEDITHER to change because vInitBrush
  954. // needs to look for this flag without holding a lock, and because
  955. // this flag is intended to be used only by printer drivers.
  956. if ((poNew.flGraphicsCaps() ^ poOld.flGraphicsCaps())
  957. & (GCAPS_HIGHRESTEXT | GCAPS_FORCEDITHER))
  958. {
  959. WARNING("bDynamicMatchEnoughForModeChange: Driver's flGraphicsCaps did");
  960. WARNING(" not match for GCAPS_HIGHRESTEXT and GCAPS_FORCEDITHER\n");
  961. b = FALSE;
  962. }
  963. if ((poNew.ulLogPixelsX() != poOld.ulLogPixelsX()) ||
  964. (poNew.ulLogPixelsY() != poOld.ulLogPixelsY()))
  965. {
  966. WARNING("bDynamicMatchEnoughForModeChange: Driver's ulLogPixels did not match\n");
  967. b = FALSE;
  968. }
  969. // We can't handle font producers because I haven't bothered with
  970. // code to traverse the font code's producer lists and Do The Right
  971. // Thing (appropriate locks are the biggest pain). Fortunately,
  972. // font producing video drivers should be extremely rare.
  973. if (PPFNDRV(poNew, QueryFont) ||
  974. PPFNDRV(poNew, QueryFontCaps) ||
  975. PPFNDRV(poNew, LoadFontFile) ||
  976. PPFNDRV(poNew, QueryFontFile) ||
  977. PPFNDRV(poNew, GetGlyphMode))
  978. {
  979. WARNING("bDynamicMatchEnoughForModeChange: New driver can't be a font provider\n");
  980. b = FALSE;
  981. }
  982. if (PPFNDRV(poOld, QueryFont) ||
  983. PPFNDRV(poOld, QueryFontCaps) ||
  984. PPFNDRV(poOld, LoadFontFile) ||
  985. PPFNDRV(poOld, QueryFontFile) ||
  986. PPFNDRV(poOld, GetGlyphMode))
  987. {
  988. WARNING("bDynamicMatchEnoughForModeChange: Old driver can't be a font provider\n");
  989. b = FALSE;
  990. }
  991. ASSERTGDI((poNew.ulTechnology() == DT_RASDISPLAY) &&
  992. (poOld.ulTechnology() == DT_RASDISPLAY),
  993. "Display drivers must specify DT_RASDISPLAY for ulTechnology");
  994. ASSERTGDI((poNew.flTextCaps() & ~TC_SCROLLBLT) ==
  995. (poOld.flTextCaps() & ~TC_SCROLLBLT),
  996. "Display drivers should set only TC_RA_ABLE in flTextCaps");
  997. return(b);
  998. }
  999. /******************************Public*Routine******************************\
  1000. * vAssertPaletteRefCountCorrect
  1001. *
  1002. * Validates the reference count for a palette by counting all the surfaces
  1003. * that use it.
  1004. *
  1005. * History:
  1006. * 14-Oct-1996 -by- J. Andrew Goossen [andrewgo]
  1007. * Wrote it.
  1008. \**************************************************************************/
  1009. #if DBG
  1010. VOID
  1011. vAssertPaletteRefCountCorrect(
  1012. PALETTE* ppalOld
  1013. )
  1014. {
  1015. LONG cAltLocks;
  1016. LONG cSurfaces;
  1017. HOBJ hobj;
  1018. SURFACE* pSurface;
  1019. PALETTE* ppalSurface;
  1020. MLOCKFAST mo;
  1021. cSurfaces = 0;
  1022. hobj = 0;
  1023. while (pSurface = (SURFACE*) HmgSafeNextObjt(hobj, SURF_TYPE))
  1024. {
  1025. hobj = (HOBJ) pSurface->hGet();
  1026. ppalSurface = pSurface->ppal();
  1027. if (ppalSurface == ppalOld)
  1028. {
  1029. cSurfaces++;
  1030. }
  1031. else if ((ppalSurface != NULL) && (ppalSurface->ppalColor == ppalOld))
  1032. {
  1033. cSurfaces++;
  1034. }
  1035. }
  1036. cAltLocks = ((POBJ) ppalOld)->ulShareCount;
  1037. // The PDEV keeps a reference count on the palette, as does the
  1038. // EngCreatePalette call. So the number of Alt-locks should be
  1039. // two more than the number of surfaces with this palette:
  1040. if (cAltLocks < cSurfaces + 2)
  1041. {
  1042. KdPrint(("vAssertPaletteRefCountCorrect cAltLocks: %li != cSurfaces: %li.\n",
  1043. cAltLocks - 2, cSurfaces));
  1044. hobj = 0;
  1045. while (pSurface = (SURFACE*) HmgSafeNextObjt(hobj, SURF_TYPE))
  1046. {
  1047. hobj = (HOBJ) pSurface->hGet();
  1048. ppalSurface = pSurface->ppal();
  1049. if (ppalSurface == ppalOld)
  1050. {
  1051. KdPrint((" %p\n", pSurface));
  1052. }
  1053. else if ((ppalSurface != NULL) && (ppalSurface->ppalColor == ppalOld))
  1054. {
  1055. KdPrint((" -%p\n", pSurface));
  1056. }
  1057. }
  1058. RIP("Breaking to debugger...");
  1059. }
  1060. }
  1061. #else
  1062. #define vAssertPaletteRefCountCorrect(ppalOld)
  1063. #endif
  1064. /******************************Public*Routine******************************\
  1065. * bDynamicRemoveAllDriverRealizations
  1066. *
  1067. * Cleanses a PDEV of all state that is specific to the device, such as
  1068. * device format bitmaps, and brush and font realizations.
  1069. *
  1070. * NOTE: The following locks must be held:
  1071. *
  1072. * 1. Devlock;
  1073. * 2. RFont list lock;
  1074. * 3. Handle manager lock.
  1075. *
  1076. * History:
  1077. * 8-Feb-1996 -by- J. Andrew Goossen [andrewgo]
  1078. * Wrote it.
  1079. \**************************************************************************/
  1080. BOOL
  1081. bDynamicRemoveAllDriverRealizations(
  1082. HDEV hdev
  1083. )
  1084. {
  1085. BOOL bConversionSuccessful;
  1086. HOBJ hobj; // Temporary object handle
  1087. SURFACE* pSurface; // Temporary surface pointer
  1088. RFONT* prfnt; // Temporary RFONT pointer
  1089. FONTOBJ* pfo; // Temporary FONTOBJ pointer
  1090. BRUSH* pbrush; // Temporary BRUSH pointer
  1091. PFN_DrvDestroyFont pfnDrvDestroyFont;
  1092. PDEV* ppdev;
  1093. PDEVOBJ po(hdev);
  1094. ppdev = po.ppdev;
  1095. // Now traverse all the device bitmaps associated with this device,
  1096. // and convert any driver-owned bitmaps to DIBs.
  1097. bConversionSuccessful = TRUE;
  1098. hobj = 0;
  1099. while (pSurface = (SURFACE*) HmgSafeNextObjt(hobj, SURF_TYPE))
  1100. {
  1101. // Retrieve the handle to the next surface before we delete
  1102. // the current one:
  1103. hobj = (HOBJ) pSurface->hGet();
  1104. // Note that the sprite code handles mode changes for sprite
  1105. // surfaces.
  1106. if ((pSurface->hdev() == hdev) &&
  1107. (pSurface->bDeviceDependentBitmap()) &&
  1108. (pSurface->dhpdev() != NULL))
  1109. {
  1110. // The surface cannot be converted if there is any
  1111. // outstanding lock other than those done to select
  1112. // a bitmap into a DC. We can't very well go and de-
  1113. // allocate 'pSurface' while someone is looking at it.
  1114. //
  1115. // However, we really shouldn't fail a dynamic mode
  1116. // change if some thread somewhere in the system should
  1117. // happen to be doing a bitmap operation with a DFB.
  1118. // For that reason, wherever a surface is locked,
  1119. // we endeavour to hold either the dynamic mode change
  1120. // lock or the devlock -- and since at this very moment
  1121. // we have both, that should mean that these conversions
  1122. // will never fail due to lock issues.
  1123. if (pSurface->hdc() != 0)
  1124. {
  1125. // WinBug #242572 3-13-2001 jasonha Surface not selected by DC it thinks it is
  1126. //
  1127. // When a DC is saved while a DFB is selected, but then another
  1128. // surface or no surface is selected, bConvertDfbDcToDib will
  1129. // try to convert the top-level DC's surface to a DIB.
  1130. //
  1131. // Walk the saved DC chain until the first DC actually referencing
  1132. // this surface is found.
  1133. //
  1134. HDC hdc = pSurface->hdc();
  1135. while (1)
  1136. {
  1137. MDCOBJA dco(hdc); // Alt-lock
  1138. ASSERTGDI(dco.bValid(), "Surface DC is invalid");
  1139. if (dco.pSurface() == pSurface)
  1140. {
  1141. if (!bConvertDfbDcToDib(&dco))
  1142. {
  1143. WARNING("Failed DC surface conversion (possibly from low memory)\n");
  1144. bConversionSuccessful = FALSE;
  1145. }
  1146. break;
  1147. }
  1148. ASSERTGDI(dco.lSaveDepth() > 1, "DC selected surface not found in DC stack.");
  1149. hdc = dco.hdcSave();
  1150. }
  1151. }
  1152. else
  1153. {
  1154. // Handle Compatible Stock Surfaces
  1155. if (pSurface->bStockSurface())
  1156. {
  1157. if (!pConvertDfbSurfaceToDib(hdev, pSurface, pSurface->cRef()))
  1158. {
  1159. WARNING("Failed stock surface conversion in bConvertStockDfbToDib()\n");
  1160. bConversionSuccessful = FALSE;
  1161. }
  1162. }
  1163. else
  1164. {
  1165. // No-one should have a lock on the bitmap:
  1166. if (!pConvertDfbSurfaceToDib(hdev, pSurface, 0))
  1167. {
  1168. WARNING("Failed surface conversion (possibly from low memory)\n");
  1169. bConversionSuccessful = FALSE;
  1170. }
  1171. }
  1172. }
  1173. }
  1174. }
  1175. // We are safe from new DFBs being created right now because we're
  1176. // holding the devlock.
  1177. if (bConversionSuccessful)
  1178. {
  1179. // Now get rid of any font caches that the old instance
  1180. // of the driver may have.
  1181. //
  1182. // We're protected against having bDeleteRFONT call the
  1183. // driver at the same time because it has to grab the
  1184. // Devlock, and we're already holding it.
  1185. pfnDrvDestroyFont = PPFNDRV(po, DestroyFont);
  1186. if (pfnDrvDestroyFont != NULL)
  1187. {
  1188. // We must hold the RFONT list semaphore while we traverse the
  1189. // RFONT list!
  1190. for (prfnt = ppdev->prfntInactive;
  1191. prfnt != NULL;
  1192. prfnt = prfnt->rflPDEV.prfntNext)
  1193. {
  1194. pfo = &prfnt->fobj;
  1195. pfnDrvDestroyFont(pfo);
  1196. pfo->pvConsumer = NULL;
  1197. }
  1198. for (prfnt = ppdev->prfntActive;
  1199. prfnt != NULL;
  1200. prfnt = prfnt->rflPDEV.prfntNext)
  1201. {
  1202. pfo = &prfnt->fobj;
  1203. pfnDrvDestroyFont(pfo);
  1204. pfo->pvConsumer = NULL;
  1205. }
  1206. }
  1207. // Make it so that any brush realizations are invalidated, because
  1208. // we don't want a new instance of the driver trying to use old
  1209. // instance 'pvRbrush' data.
  1210. //
  1211. // This also takes care of invalidating the brushes for all the
  1212. // DDB to DIB conversions.
  1213. //
  1214. // Note that we're actually invalidating the caches of all brushes
  1215. // in the system, because we don't store any 'hdevOld' information
  1216. // with the brush. Because dynamic mode changes should be relatively
  1217. // infrequent, and because realizations are reasonably cheap, I don't
  1218. // expect this to be a big hit.
  1219. hobj = 0;
  1220. while (pbrush = (BRUSH*) HmgSafeNextObjt(hobj, BRUSH_TYPE))
  1221. {
  1222. hobj = (HOBJ) pbrush->hGet();
  1223. // Mark as dirty by setting the cache ID to
  1224. // an invalid state.
  1225. pbrush->ulSurfTime((ULONG) -1);
  1226. // Set the uniqueness so the are-you-really-
  1227. // dirty check in vInitBrush will not think
  1228. // an old realization is still valid.
  1229. pbrush->ulBrushUnique(pbrush->ulGlobalBrushUnique());
  1230. }
  1231. // We must disable the halftone device information when changing
  1232. // colour depths because the GDIINFO data it was constructed with
  1233. // are no longer valid. It is always enabled lazily, so there's no
  1234. // need to reenable it here:
  1235. if (ppdev->pDevHTInfo != NULL)
  1236. {
  1237. po.bDisableHalftone();
  1238. }
  1239. }
  1240. return(bConversionSuccessful);
  1241. }
  1242. /******************************Public*Routine******************************\
  1243. * bDynamicIntersectVisRect
  1244. *
  1245. * It is critical that we must be able to update all VisRgns if the new
  1246. * mode is smaller than the old. If this did not happen, we could allow
  1247. * GDI calls to the driver that are outside the bounds of the visible
  1248. * display, and as a result the driver would quite likely fall over.
  1249. *
  1250. * We don't entrust USER to always take care of this case because it
  1251. * updates the VisRgns after it knows that bDynamicModeChange was
  1252. * successful -- which is too late if the VisRgn change should fail
  1253. * because of low memory. It's acceptable in low memory situations to
  1254. * temporarily draw incorrectly as a result of a wrong VisRgn, but it
  1255. * is *not* acceptable to crash.
  1256. *
  1257. * Doing this here also means that USER doesn't have to call
  1258. * us while holding the Devlock.
  1259. *
  1260. * History:
  1261. * 8-Feb-1996 -by- J. Andrew Goossen [andrewgo]
  1262. * Wrote it.
  1263. \**************************************************************************/
  1264. BOOL
  1265. bDynamicIntersectVisRect(
  1266. SURFACE* pSurfaceOld,
  1267. SIZEL sizlNew
  1268. )
  1269. {
  1270. HOBJ hobj;
  1271. DC* pdc;
  1272. hobj = 0;
  1273. while (pdc = (DC*) HmgSafeNextObjt(hobj, DC_TYPE))
  1274. {
  1275. hobj = (HOBJ) pdc->hGet();
  1276. if ((!(pdc->fs() & DC_IN_CLONEPDEV)) &&
  1277. (pdc->pSurface() == pSurfaceOld) &&
  1278. (pdc->prgnVis() != NULL))
  1279. {
  1280. if (!GreIntersectVisRect((HDC) hobj, 0, 0,
  1281. sizlNew.cx, sizlNew.cy))
  1282. {
  1283. WARNING("bDynamicModeChange: Failed reseting VisRect!\n");
  1284. // Note that if we fail here, we may have already
  1285. // shrunk some VisRgn's. However, we should have only
  1286. // failed in a very low-memory situation, in which case
  1287. // there will be plenty of other drawing problems. The
  1288. // regions will likely all be reset back to the correct
  1289. // dimensions by the owning applications, eventually.
  1290. return(FALSE);
  1291. }
  1292. }
  1293. }
  1294. return(TRUE);
  1295. }
  1296. /******************************Public*Routine******************************\
  1297. * vDynamicSwitchPalettes
  1298. *
  1299. * Device Independent Bitmaps (DIBs) are great when switching colour
  1300. * depths because, by virtue of their attached colour table (also known
  1301. * as a 'palette'), they Just Work at any colour depth.
  1302. *
  1303. * Device Dependent Bitmaps (DDBs) are more problematic. They implicitly
  1304. * share their palette with the display -- meaning that if the display's
  1305. * palette is dynamically changed, the old DDBs will not work. We get
  1306. * around this by dynamically creating palettes to convert them to DIBs.
  1307. * Unfortunately, at palettized 8bpp we sometimes have to guess at what
  1308. * the appropriate palette would be. For this reason, whenever we switch
  1309. * back to 8bpp we make sure we convert them back to DDBs by removing their
  1310. * palettes.
  1311. *
  1312. * History:
  1313. * 8-Feb-1996 -by- J. Andrew Goossen [andrewgo]
  1314. * Wrote it.
  1315. \**************************************************************************/
  1316. VOID
  1317. vDynamicSwitchPalettes(
  1318. SURFACE* pSurface,
  1319. PDEV* ppdevOld,
  1320. PDEV* ppdevNew
  1321. )
  1322. {
  1323. PALETTE* ppalOld;
  1324. HOBJ hobj;
  1325. BOOL bHintCreated;
  1326. ASSERTGDI(pSurface->iType() == STYPE_BITMAP,
  1327. "Unexpected bitmap type");
  1328. ASSERTGDI(pSurface->iFormat() == ppdevOld->devinfo.iDitherFormat,
  1329. "Unexpected bitmap format");
  1330. // Device Format Bitmaps (DFBs) are DDBs that are created via
  1331. // CreateCompatibleBitmap, and so we know what device they're
  1332. // associated with.
  1333. //
  1334. // Unfortunately, non-DFB DDBs (created via CreateBitmap or
  1335. // CreateDiscardableBitmap) have no device assocation -- so we
  1336. // don't know whether or not they're really associated with the
  1337. // display.
  1338. //
  1339. // If a non-DFB DDB is currently selected into a DC owned by the
  1340. // display, we will add a palette to it. If a non-DFB DDB is
  1341. // not currently selected into a DC owned by the display (implied
  1342. // by having its surface 'hdev' as zero), we will not convert it.
  1343. // SelectBitmap will refuse to load it into a DC. (In 4.0 we used
  1344. // to always assume that any such bitmap was intended for the
  1345. // display, but that's not always a valid assumption, and doesn't
  1346. // make much sense in a multiple-monitor or multi-user environment
  1347. // anyway.) Fortunately, non-DFB DDBs are increasingly rare.
  1348. //
  1349. // Note that DFBs are synchronized by the Devlock, and we don't
  1350. // need a lock to change the palette for a non-DFB DDB (see
  1351. // PALETTE_SELECT_SET logic).
  1352. ppalOld = ppdevOld->ppalSurf;
  1353. if (pSurface->ppal() == NULL)
  1354. {
  1355. // Mark the surface to note that we added a palette:
  1356. pSurface->vSetDynamicModePalette();
  1357. if (ppdevOld->GdiInfo.flRaster & RC_PALETTE)
  1358. {
  1359. bHintCreated = FALSE;
  1360. if (pSurface->hpalHint() != 0)
  1361. {
  1362. EPALOBJ palDC(pSurface->hpalHint());
  1363. if ((palDC.bValid()) &&
  1364. (palDC.bIsPalDC()) &&
  1365. (!palDC.bIsPalDefault()) &&
  1366. (palDC.ptransFore() != NULL))
  1367. {
  1368. PALMEMOBJ palPerm;
  1369. XEPALOBJ palSurf(ppalOld);
  1370. if (palPerm.bCreatePalette(PAL_INDEXED,
  1371. 256,
  1372. (ULONG*) palSurf.apalColorGet(),
  1373. 0,
  1374. 0,
  1375. 0,
  1376. PAL_FREE))
  1377. {
  1378. ULONG nPhysChanged = 0;
  1379. ULONG nTransChanged = 0;
  1380. palPerm.ulNumReserved(palSurf.ulNumReserved());
  1381. bHintCreated = TRUE;
  1382. vMatchAPal(NULL,
  1383. palPerm,
  1384. palDC,
  1385. &nPhysChanged,
  1386. &nTransChanged);
  1387. palPerm.vKeepIt();
  1388. pSurface->ppal(palPerm.ppalGet());
  1389. // Keep a reference active:
  1390. palPerm.ppalSet(NULL);
  1391. }
  1392. }
  1393. }
  1394. if (!bHintCreated)
  1395. {
  1396. INC_SHARE_REF_CNT(ppalDefaultSurface8bpp);
  1397. pSurface->ppal(ppalDefaultSurface8bpp);
  1398. }
  1399. }
  1400. else
  1401. {
  1402. INC_SHARE_REF_CNT(ppalOld);
  1403. pSurface->ppal(ppalOld);
  1404. }
  1405. }
  1406. else if ((pSurface->ppal() == ppalOld) &&
  1407. (pSurface->flags() & PALETTE_SELECT_SET))
  1408. {
  1409. ASSERTGDI((pSurface->hdc() != 0) &&
  1410. (pSurface->cRef() != 0),
  1411. "Expected bitmap to be selected into a DC");
  1412. INC_SHARE_REF_CNT(pSurface->ppal());
  1413. pSurface->flags(pSurface->flags() & ~PALETTE_SELECT_SET);
  1414. }
  1415. // When switching back to palettized 8bpp, remove any palettes we
  1416. // had to add to 8bpp DDBs:
  1417. if (ppdevNew->GdiInfo.flRaster & RC_PALETTE)
  1418. {
  1419. if (pSurface->bDynamicModePalette())
  1420. {
  1421. ASSERTGDI(pSurface->ppal() != NULL,
  1422. "Should be a palette here");
  1423. XEPALOBJ pal(pSurface->ppal());
  1424. pal.vUnrefPalette();
  1425. pSurface->vClearDynamicModePalette();
  1426. pSurface->ppal(NULL);
  1427. }
  1428. }
  1429. }
  1430. /******************************Public*Routine******************************\
  1431. * bDynamicModeChange
  1432. *
  1433. * USER callable function that switches driver instances between two PDEVs.
  1434. *
  1435. * GDI's 'HDEV' and 'PDEV' stay the same; only the device's 'pSurface',
  1436. * 'dhpdev', GDIINFO, DEVINFO, and palette information change.
  1437. *
  1438. * The caller is ChangeDisplaySettings in USER, which is reponsible for:
  1439. *
  1440. * o Calling us with a valid devmode;
  1441. * o Ensuring that the device is not currently in full-screen mode;
  1442. * o Invalidating all of its SaveScreenBits buffers;
  1443. * o Changing the VisRgn's on all DCs;
  1444. * o Resetting the pointer shape;
  1445. * o Sending the appropriate messages to everyone;
  1446. * o Redrawing the desktop.
  1447. *
  1448. * Since CreateDC("DISPLAY") always gets mapped to GetDC(NULL), there are
  1449. * no DC's for which GDI is responsible for updating the VisRgn.
  1450. *
  1451. * Dynamically changes a display driver or mode.
  1452. *
  1453. * Rules of This Routine
  1454. * ---------------------
  1455. *
  1456. * o An important precept is that no drawing by any threads to any
  1457. * application's bitmaps should be affected by this routine. This means,
  1458. * for example, that we cannot exclusive lock any DCs.
  1459. *
  1460. * o While we keep GDI's 'HDEV' and 'PDEV' in place, we do have to modify
  1461. * fields like 'dhpdev' and 'pSurface'. Because we also have to update
  1462. * copies of these fields that are stashed in DC's, it means that *all*
  1463. * accesses to mode-dependent fields such as 'dhpdev,' 'pSurface,' and
  1464. * 'sizl' must be protected by holding a resource that this routine
  1465. * acquires -- such as the devlock or handle-manager lock.
  1466. *
  1467. * o If the function fails for whatever reason, the mode MUST be restored
  1468. * back to its original state.
  1469. *
  1470. * Returns: TRUE if successful, FALSE if the two PDEVs didn't match enough,
  1471. * or if we're out of memory.
  1472. *
  1473. * History:
  1474. * 8-Feb-1996 -by- J. Andrew Goossen [andrewgo]
  1475. * Wrote it.
  1476. *
  1477. * 27-Aug-1996 -by- J. Andrew Goossen [andrewgo]
  1478. * Added support for dynamic display driver changes.
  1479. *
  1480. \**************************************************************************/
  1481. ULONG gcModeChanges; // # of mode changes, for debugging even on free builds
  1482. #define SWAP(x, y, tmp) { (tmp) = (x); (x) = (y); (y) = (tmp); }
  1483. typedef union {
  1484. GDIINFO GdiInfo;
  1485. DEVINFO devinfo;
  1486. PFN apfn[INDEX_LAST];
  1487. LDEV* pldev;
  1488. HANDLE hSpooler;
  1489. PVOID pDesktopId;
  1490. PGRAPHICS_DEVICE pGraphicsDevice;
  1491. POINTL ptlOrigin;
  1492. PDEVMODEW ppdevDevmode;
  1493. PFN_DrvSetPointerShape pfnSet;
  1494. PFN_DrvMovePointer pfnMove;
  1495. PFN_DrvSynchronize pfnSync;
  1496. PFN_DrvSynchronizeSurface pfnSyncSurface;
  1497. PFN_DrvSetPalette pfnSetPalette;
  1498. PFN_DrvBitBlt pfnUnfilteredBitBlt;
  1499. PFN_DrvNotify pfnNotify;
  1500. BYTE dc[sizeof(DC)];
  1501. SIZEL sizlMeta;
  1502. HSURF ahsurf[HS_DDI_MAX];
  1503. HLFONT hlfnt;
  1504. DWORD dwDriverAccelerationLevel;
  1505. DWORD dwDriverCapableOverride;
  1506. #ifdef DDI_WATCHDOG
  1507. PWATCHDOG_DATA pWatchdogData;
  1508. #endif
  1509. } SWAPBUFFER;
  1510. BOOL
  1511. bDynamicModeChange(
  1512. HDEV hdevOld,
  1513. HDEV hdevNew
  1514. )
  1515. {
  1516. BOOL bRet;
  1517. BOOL bFormatChange;
  1518. PDEV* ppdevOld;
  1519. PDEV* ppdevNew;
  1520. DHPDEV dhpdevOld;
  1521. DHPDEV dhpdevNew;
  1522. SURFACE* pSurfaceOld;
  1523. SURFACE* pSurfaceNew;
  1524. PALETTE* ppalOld;
  1525. PALETTE* ppalNew;
  1526. ULONG cBppOld;
  1527. ULONG cBppNew;
  1528. SIZEL sizlOld;
  1529. SIZEL sizlNew;
  1530. SURFACE* pSurface; // Temporary surface pointer
  1531. DC* pdc; // Temporary DC pointer
  1532. DRVOBJ* pdo; // Temporary DRVOBJ pointer
  1533. HOBJ hobj; // Temporary object handle
  1534. BOOL bPermitModeChange;
  1535. BRUSH* pbrGrayPattern;
  1536. DC* pdcBuffer; // Points to temporary DC buffer
  1537. SWAPBUFFER* pswap;
  1538. BOOL bDisabledOld;
  1539. BOOL bDisabledNew;
  1540. PFN_DrvResetPDEV pfnDrvResetPDEV;
  1541. bRet = FALSE; // Assume failure
  1542. // We impose some restrictions upon what capabilities may change
  1543. // between drivers:
  1544. if (bDynamicMatchEnoughForModeChange(hdevOld, hdevNew))
  1545. {
  1546. ASSERTGDI(GreIsSemaphoreOwnedByCurrentThread(ghsemShareDevLock),
  1547. "ShareDevlock must held be before calling bDynamicModeChange");
  1548. // Allocate a temporary buffer for use swapping data:
  1549. pswap = (SWAPBUFFER*) PALLOCNOZ(sizeof(SWAPBUFFER), 'pmtG');
  1550. if (pswap)
  1551. {
  1552. PDEVOBJ poOld(hdevOld);
  1553. PDEVOBJ poNew(hdevNew);
  1554. bDisabledNew = poNew.bDisabled();
  1555. bDisabledOld = poOld.bDisabled();
  1556. // Disable timer-based synchronization for these PDEVs for now.
  1557. // This is mainly so that the PDEV_SYNCHRONIZE_ENABLED is set
  1558. // correctly.
  1559. vDisableSynchronize(hdevNew);
  1560. vDisableSynchronize(hdevOld);
  1561. cBppOld = poOld.GdiInfo()->cBitsPixel * poOld.GdiInfo()->cPlanes;
  1562. cBppNew = poNew.GdiInfo()->cBitsPixel * poNew.GdiInfo()->cPlanes;
  1563. // Ideally, we would check the palettes here, too:
  1564. bFormatChange = (cBppOld != cBppNew);
  1565. ppdevOld = (PDEV*) hdevOld;
  1566. ppdevNew = (PDEV*) hdevNew;
  1567. // PDEV shouldn't be clone
  1568. ASSERTGDI(!poOld.bCloneDriver(),"pdevOld is clone!");
  1569. ASSERTGDI(!poNew.bCloneDriver(),"pdevNew is clone!");
  1570. // The following lock rules must be abided, otherwise deadlocks may
  1571. // arise:
  1572. //
  1573. // o Pointer lock must be acquired after Devlock (GreSetPointer);
  1574. //
  1575. // And see drvsup.cxx, too.
  1576. //
  1577. // So we acquire locks in the following order (note that the
  1578. // vAssertDynaLock() routines should be modified if this list ever
  1579. // changes):
  1580. ASSERTGDI(GreIsSemaphoreOwnedByCurrentThread(poOld.hsemDevLock()),
  1581. "Devlock must be held before acquiring the pointer semaphore");
  1582. SEMOBJ soPointer(poOld.hsemPointer()); // No asynchronous pointer moves
  1583. ASSERTGDI(ppdevOld->pSurface != NULL, "Must be called on a completed PDEV");
  1584. ASSERTGDI(poOld.bDisplayPDEV(), "Must be called on a display PDEV");
  1585. ASSERTGDI((prgnDefault->cScans == 1) && (prgnDefault->rcl.right == 0),
  1586. "Someone changed prgnDefault; could cause driver access violations");
  1587. // Free all PDEV state that is dependent on or cached by the driver:
  1588. if (bDynamicRemoveAllDriverRealizations(hdevOld) &&
  1589. bDynamicRemoveAllDriverRealizations(hdevNew))
  1590. {
  1591. bPermitModeChange = TRUE;
  1592. sizlOld = poOld.sizl();
  1593. pSurfaceOld = ppdevOld->pSurface;
  1594. ppalOld = ppdevOld->ppalSurf;
  1595. dhpdevOld = ppdevOld->dhpdev;
  1596. sizlNew = poNew.sizl();
  1597. pSurfaceNew = ppdevNew->pSurface;
  1598. ppalNew = ppdevNew->ppalSurf;
  1599. dhpdevNew = ppdevNew->dhpdev;
  1600. // Make sure the VisRgns are immediately shrunk if necessary:
  1601. if ((sizlNew.cx < sizlOld.cx) || (sizlNew.cy < sizlOld.cy))
  1602. {
  1603. bPermitModeChange &= bDynamicIntersectVisRect(pSurfaceOld, sizlNew);
  1604. }
  1605. if ((sizlOld.cx < sizlNew.cx) || (sizlOld.cy < sizlNew.cy))
  1606. {
  1607. bPermitModeChange &= bDynamicIntersectVisRect(pSurfaceNew, sizlOld);
  1608. }
  1609. // Finally, if we're not switching drivers then let the driver know
  1610. // about the mode switch. This has to be the last step because we
  1611. // are implicitly telling the driver that it can transfer data from
  1612. // the old instance to the new instance with the assurance that the
  1613. // new instance won't later be abandoned.
  1614. pfnDrvResetPDEV = PPFNDRV(poNew, ResetPDEV);
  1615. if ((pfnDrvResetPDEV != NULL) &&
  1616. (pfnDrvResetPDEV == PPFNDRV(poOld, ResetPDEV)) &&
  1617. (poNew.pldev() == poOld.pldev()))
  1618. {
  1619. // The driver can refuse the mode switch if it wants:
  1620. if (bPermitModeChange)
  1621. {
  1622. GreEnterMonitoredSection(poOld.ppdev, WD_DEVLOCK);
  1623. bPermitModeChange = pfnDrvResetPDEV(dhpdevOld, dhpdevNew);
  1624. GreExitMonitoredSection(poOld.ppdev, WD_DEVLOCK);
  1625. }
  1626. }
  1627. if (bPermitModeChange)
  1628. {
  1629. /////////////////////////////////////////////////////////////
  1630. // At this point, we're committed to the mode change.
  1631. // Nothing below this point can be allowed to fail.
  1632. /////////////////////////////////////////////////////////////
  1633. // Traverse all DC's and update their surface information if
  1634. // they're associated with this device.
  1635. //
  1636. // Note that bDeleteDCInternal wipes some fields in the DC via
  1637. // bCleanDC before freeing the DC, but this is okay since the
  1638. // worst we'll do is update some fields just before the DC gets
  1639. // deleted.
  1640. hobj = 0;
  1641. while (pdc = (DC*) HmgSafeNextObjt(hobj, DC_TYPE))
  1642. {
  1643. hobj = (HOBJ) pdc->hGet();
  1644. if (!(pdc->fs() & DC_IN_CLONEPDEV))
  1645. {
  1646. // Note that we don't check that pdc->hdevOld() == hdevOld
  1647. // because the SaveDC stuff doesn't bother copying the hdevOld,
  1648. // but DOES copy the dclevel.
  1649. //
  1650. // Note that 'flbrushAdd()' is not an atomic operation.
  1651. // However, since we're holding the devlock and the palette
  1652. // lock, there shouldn't be any other threads alt-locking our
  1653. // DC and modifying these fields at the same time:
  1654. if (pdc->pSurface() == pSurfaceOld)
  1655. {
  1656. pdc->pSurface(pSurfaceNew);
  1657. pdc->sizl(sizlNew);
  1658. pdc->flbrushAdd(DIRTY_BRUSHES);
  1659. }
  1660. else if (pdc->pSurface() == pSurfaceNew)
  1661. {
  1662. pdc->pSurface(pSurfaceOld);
  1663. pdc->sizl(sizlOld);
  1664. pdc->flbrushAdd(DIRTY_BRUSHES);
  1665. }
  1666. if (pdc->dhpdev() == dhpdevOld)
  1667. {
  1668. pdc->dhpdev(dhpdevNew);
  1669. pdc->flGraphicsCaps(poNew.flGraphicsCaps());
  1670. pdc->flGraphicsCaps2(poNew.flGraphicsCaps2());
  1671. }
  1672. else if (pdc->dhpdev() == dhpdevNew)
  1673. {
  1674. pdc->dhpdev(dhpdevOld);
  1675. pdc->flGraphicsCaps(poOld.flGraphicsCaps());
  1676. pdc->flGraphicsCaps2(poOld.flGraphicsCaps2());
  1677. }
  1678. }
  1679. }
  1680. // Compatible bitmap palettes may have to be changed if the
  1681. // mode changes. Note that the sprite code handles any
  1682. // sprite surfaces:
  1683. hobj = 0;
  1684. while (pSurface = (SURFACE*) HmgSafeNextObjt(hobj, SURF_TYPE))
  1685. {
  1686. hobj = (HOBJ) pSurface->hGet();
  1687. if (pSurface->hdev() == hdevOld)
  1688. {
  1689. if (pSurface->bApiBitmap())
  1690. {
  1691. if ((bFormatChange) &&
  1692. (pSurface->iFormat() == pSurfaceOld->iFormat()))
  1693. {
  1694. vDynamicSwitchPalettes(pSurface, ppdevOld, ppdevNew);
  1695. }
  1696. }
  1697. // Surfaces private to the driver should be transferred
  1698. // along with the driver instance.
  1699. else if (pSurface->bDriverCreated() && !pSurface->bDirectDraw())
  1700. {
  1701. pSurface->hdev(hdevNew);
  1702. }
  1703. }
  1704. else if (pSurface->hdev() == hdevNew)
  1705. {
  1706. if (pSurface->bApiBitmap())
  1707. {
  1708. if ((bFormatChange) &&
  1709. (pSurface->iFormat() == pSurfaceNew->iFormat()))
  1710. {
  1711. vDynamicSwitchPalettes(pSurface, ppdevNew, ppdevOld);
  1712. }
  1713. }
  1714. // Surfaces private to the driver should be transferred
  1715. // along with the driver instance.
  1716. else if (pSurface->bDriverCreated() && !pSurface->bDirectDraw())
  1717. {
  1718. pSurface->hdev(hdevOld);
  1719. }
  1720. }
  1721. }
  1722. // DRIVEROBJs are transferred with the driver to the new PDEV:
  1723. hobj = 0;
  1724. while (pdo = (DRVOBJ*) HmgSafeNextObjt(hobj, DRVOBJ_TYPE))
  1725. {
  1726. hobj = (HOBJ) pdo->hGet();
  1727. if (pdo->hdev == hdevOld)
  1728. {
  1729. pdo->hdev = hdevNew;
  1730. poNew.vReferencePdev();
  1731. poOld.vUnreferencePdev();
  1732. }
  1733. else if (pdo->hdev == hdevNew)
  1734. {
  1735. pdo->hdev = hdevOld;
  1736. poOld.vReferencePdev();
  1737. poNew.vUnreferencePdev();
  1738. }
  1739. }
  1740. // Same with WNDOBJs:
  1741. vChangeWndObjs(pSurfaceOld, hdevOld, pSurfaceNew, hdevNew);
  1742. // Re-realize the gray pattern brush which is used for drag
  1743. // rectangles:
  1744. pbrGrayPattern = (BRUSH*) HmgShareLock((HOBJ)ghbrGrayPattern,
  1745. BRUSH_TYPE);
  1746. pdcBuffer = (DC*) &pswap->dc;
  1747. pdcBuffer->pDCAttr = &pdcBuffer->dcattr;
  1748. pdcBuffer->crTextClr(0x00000000);
  1749. pdcBuffer->crBackClr(0x00FFFFFF);
  1750. pdcBuffer->lIcmMode(DC_ICM_OFF);
  1751. pdcBuffer->hcmXform(NULL);
  1752. poOld.pbo()->vInitBrush(pdcBuffer,
  1753. pbrGrayPattern,
  1754. (XEPALOBJ) ppalDefault,
  1755. (XEPALOBJ) ppalNew,
  1756. pSurfaceNew);
  1757. poNew.pbo()->vInitBrush(pdcBuffer,
  1758. pbrGrayPattern,
  1759. (XEPALOBJ) ppalDefault,
  1760. (XEPALOBJ) ppalOld,
  1761. pSurfaceOld);
  1762. DEC_SHARE_REF_CNT(pbrGrayPattern);
  1763. /////////////////////////////////////////////////////////////
  1764. // Update all our PDEV fields:
  1765. /////////////////////////////////////////////////////////////
  1766. // Swap surface data between the two PDEVs:
  1767. ppdevNew->pSurface = pSurfaceOld;
  1768. ppdevNew->ppalSurf = ppalOld;
  1769. ppdevNew->dhpdev = dhpdevOld;
  1770. ppdevOld->pSurface = pSurfaceNew;
  1771. ppdevOld->ppalSurf = ppalNew;
  1772. ppdevOld->dhpdev = dhpdevNew;
  1773. if (!pSurfaceOld->bReadable())
  1774. {
  1775. pSurfaceNew->flags(pSurfaceNew->flags() | UNREADABLE_SURFACE);
  1776. SPRITESTATE *pStateOld = poOld.pSpriteState();
  1777. if (pStateOld)
  1778. {
  1779. if (pStateOld->flOriginalSurfFlags & UNREADABLE_SURFACE ||
  1780. pStateOld->flSpriteSurfFlags & UNREADABLE_SURFACE)
  1781. {
  1782. SPRITESTATE *pStateNew = poNew.pSpriteState();
  1783. if (pStateNew)
  1784. {
  1785. pStateNew->flOriginalSurfFlags |= UNREADABLE_SURFACE;
  1786. pStateNew->flSpriteSurfFlags |= UNREADABLE_SURFACE;
  1787. }
  1788. }
  1789. }
  1790. }
  1791. else if (!pSurfaceNew->bReadable())
  1792. {
  1793. pSurfaceOld->flags(pSurfaceOld->flags() | UNREADABLE_SURFACE);
  1794. SPRITESTATE *pStateNew = poNew.pSpriteState();
  1795. if (pStateNew)
  1796. {
  1797. if (pStateNew->flOriginalSurfFlags & UNREADABLE_SURFACE ||
  1798. pStateNew->flSpriteSurfFlags & UNREADABLE_SURFACE)
  1799. {
  1800. SPRITESTATE *pStateOld = poOld.pSpriteState();
  1801. if (pStateOld)
  1802. {
  1803. pStateOld->flOriginalSurfFlags |= UNREADABLE_SURFACE;
  1804. pStateOld->flSpriteSurfFlags |= UNREADABLE_SURFACE;
  1805. }
  1806. }
  1807. }
  1808. }
  1809. // WINBUG #365395 4-10-2001 jasonha Need to investigate old comments in bDynamicModeChange
  1810. //
  1811. // Old Comments:
  1812. // - vUnrefPalette of old palette for mirrored drivers?
  1813. // - Secondary palette fix?
  1814. SWAP(ppdevNew->pldev ,ppdevOld->pldev ,pswap->pldev );
  1815. SWAP(ppdevNew->devinfo ,ppdevOld->devinfo ,pswap->devinfo );
  1816. SWAP(ppdevNew->GdiInfo ,ppdevOld->GdiInfo ,pswap->GdiInfo );
  1817. SWAP(ppdevNew->hSpooler ,ppdevOld->hSpooler ,pswap->hSpooler );
  1818. SWAP(ppdevNew->pDesktopId ,ppdevOld->pDesktopId ,pswap->pDesktopId );
  1819. SWAP(ppdevNew->pGraphicsDevice,ppdevOld->pGraphicsDevice,pswap->pGraphicsDevice);
  1820. SWAP(ppdevNew->ptlOrigin ,ppdevOld->ptlOrigin ,pswap->ptlOrigin );
  1821. SWAP(ppdevNew->ppdevDevmode ,ppdevOld->ppdevDevmode ,pswap->ppdevDevmode );
  1822. SWAP(ppdevNew->pfnUnfilteredBitBlt,
  1823. ppdevOld->pfnUnfilteredBitBlt,
  1824. pswap->pfnUnfilteredBitBlt);
  1825. SWAP(ppdevNew->dwDriverCapableOverride,
  1826. ppdevOld->dwDriverCapableOverride,
  1827. pswap->dwDriverCapableOverride);
  1828. SWAP(ppdevNew->dwDriverAccelerationLevel,
  1829. ppdevOld->dwDriverAccelerationLevel,
  1830. pswap->dwDriverAccelerationLevel);
  1831. // Swap multimon data between the two PDEVs:
  1832. if (poOld.bMetaDriver() != poNew.bMetaDriver())
  1833. {
  1834. BOOL bMetaDriver = poOld.bMetaDriver();
  1835. poOld.bMetaDriver(poNew.bMetaDriver());
  1836. poNew.bMetaDriver(bMetaDriver);
  1837. }
  1838. SWAP(ppdevNew->sizlMeta, ppdevOld->sizlMeta, pswap->sizlMeta);
  1839. // Swap pattern brushes
  1840. RtlCopyMemory(pswap->ahsurf, ppdevNew->ahsurf, sizeof(HSURF)*HS_DDI_MAX);
  1841. RtlCopyMemory(ppdevNew->ahsurf, ppdevOld->ahsurf, sizeof(HSURF)*HS_DDI_MAX);
  1842. RtlCopyMemory(ppdevOld->ahsurf, pswap->ahsurf, sizeof(HSURF)*HS_DDI_MAX);
  1843. // Swap log fonts.
  1844. SWAP(ppdevNew->hlfntDefault, ppdevOld->hlfntDefault, pswap->hlfnt);
  1845. SWAP(ppdevNew->hlfntAnsiVariable, ppdevOld->hlfntAnsiVariable, pswap->hlfnt);
  1846. SWAP(ppdevNew->hlfntAnsiFixed, ppdevOld->hlfntAnsiFixed, pswap->hlfnt);
  1847. // Swap the dispatch tables and accelerators:
  1848. RtlCopyMemory(pswap->apfn, ppdevNew->apfn, sizeof(PFN)*INDEX_LAST);
  1849. RtlCopyMemory(ppdevNew->apfn, ppdevOld->apfn, sizeof(PFN)*INDEX_LAST);
  1850. RtlCopyMemory(ppdevOld->apfn, pswap->apfn, sizeof(PFN)*INDEX_LAST);
  1851. SWAP(ppdevNew->pfnDrvSetPointerShape, ppdevOld->pfnDrvSetPointerShape, pswap->pfnSet);
  1852. SWAP(ppdevNew->pfnDrvMovePointer, ppdevOld->pfnDrvMovePointer, pswap->pfnMove);
  1853. SWAP(ppdevNew->pfnSync, ppdevOld->pfnSync, pswap->pfnSync);
  1854. SWAP(ppdevNew->pfnSyncSurface, ppdevOld->pfnSyncSurface, pswap->pfnSyncSurface);
  1855. SWAP(ppdevNew->pfnSetPalette, ppdevOld->pfnSetPalette, pswap->pfnSetPalette);
  1856. SWAP(ppdevNew->pfnNotify, ppdevOld->pfnNotify, pswap->pfnNotify);
  1857. #ifdef DDI_WATCHDOG
  1858. SWAP(ppdevNew->pWatchdogData, ppdevOld->pWatchdogData, pswap->pWatchdogData);
  1859. #endif
  1860. // Inform the drivers of their new PDEVs:
  1861. (*PPFNDRV(poNew, CompletePDEV))(poNew.dhpdev(), poNew.hdev());
  1862. (*PPFNDRV(poOld, CompletePDEV))(poOld.dhpdev(), poOld.hdev());
  1863. // Transfer all the DirectDraw state:
  1864. DxDdDynamicModeChange(hdevOld, hdevNew, 0);
  1865. // Transfer the disabled state:
  1866. poOld.bDisabled(bDisabledNew);
  1867. poNew.bDisabled(bDisabledOld);
  1868. // Update the magic colours in the surface palette:
  1869. vResetSurfacePalette(hdevOld);
  1870. vResetSurfacePalette(hdevNew);
  1871. // Transfer all the sprites between the two PDEVs:
  1872. vSpDynamicModeChange(hdevOld, hdevNew);
  1873. // Update the gamma-ramp on the device only if a gamma-ramp
  1874. // existed in the old (but at this moment, old is "new") PDEV:
  1875. UpdateGammaRampOnDevice(hdevOld, FALSE);
  1876. // Update some handy debug information:
  1877. gcModeChanges++;
  1878. bRet = TRUE;
  1879. }
  1880. }
  1881. VFREEMEM(pswap);
  1882. vEnableSynchronize(hdevNew);
  1883. vEnableSynchronize(hdevOld);
  1884. }
  1885. }
  1886. return(bRet);
  1887. }