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.

4410 lines
132 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: print.cxx
  3. *
  4. * Printer support routines.
  5. *
  6. * Copyright (c) 1991-1999 Microsoft Corporation
  7. \**************************************************************************/
  8. #include "precomp.hxx"
  9. extern "C"
  10. {
  11. #include <gl\gl.h>
  12. #include <gldrv.h>
  13. #include <dciddi.h>
  14. };
  15. extern "C"
  16. {
  17. extern HFASTMUTEX ghfmMemory;
  18. }
  19. #define TYPE1_KEY L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Type 1 Installer\\Type 1 Fonts"
  20. PTYPEONEINFO gpTypeOneInfo = NULL;
  21. PTYPEONEINFO GetTypeOneFontList();
  22. BOOL GetFontPathName( WCHAR *pFullPath, WCHAR *pFileName );
  23. extern "C" ULONG ComputeFileviewCheckSum(PVOID, ULONG);
  24. extern "C" void vUnmapRemoteFonts(FONTFILEVIEW *pFontFileView);
  25. extern PW32PROCESS gpidSpool;
  26. /******************************Public*Routine******************************\
  27. * DoFontManagement *
  28. * *
  29. * Gives us access to the driver entry point DrvFontManagement. This is *
  30. * very much an Escape function, except that it needs a font realization. *
  31. * *
  32. * Fri 07-May-1993 14:56:12 -by- Charles Whitmer [chuckwh] *
  33. * Wrote it. *
  34. \**************************************************************************/
  35. ULONG DoFontManagement(
  36. DCOBJ &dco,
  37. ULONG iMode,
  38. ULONG cjIn,
  39. PVOID pvIn,
  40. ULONG cjOut,
  41. PVOID pvOut
  42. )
  43. {
  44. ULONG ulRet = 0;
  45. PVOID pvExtra = NULL;
  46. PDEVOBJ pdo(dco.hdev());
  47. PFN_DrvFontManagement pfnF = PPFNDRV(pdo,FontManagement);
  48. if (pfnF == (PFN_DrvFontManagement) NULL)
  49. return(ulRet);
  50. if (iMode == QUERYESCSUPPORT)
  51. {
  52. // Pass it to the device.
  53. return ((*pfnF)
  54. (
  55. pdo.bUMPD() ? (SURFOBJ *)pdo.dhpdev() : NULL, //overload pso with dhpdev for UMPD
  56. NULL,
  57. iMode,
  58. cjIn,
  59. pvIn,
  60. 0,
  61. NULL
  62. ));
  63. }
  64. RFONTOBJ rfo(dco,FALSE);
  65. if (!rfo.bValid())
  66. {
  67. WARNING("gdisrv!DoFontManagement(): could not lock HRFONT\n");
  68. return(ulRet);
  69. }
  70. // See if we need some extra RAM and translation work.
  71. if (iMode == DOWNLOADFACE)
  72. {
  73. // How many 16 bit values are there now?
  74. int cWords = (int)cjIn / sizeof(WCHAR);
  75. // Try to get a buffer of 32 bit entries, since HGLYPHs are bigger.
  76. pvExtra = (BALLOC_OVERFLOW1(cWords,HGLYPH)) ? NULL
  77. : PALLOCMEM(cWords * sizeof(HGLYPH),'mfdG');
  78. if (pvExtra == NULL)
  79. return(ulRet);
  80. // Translate the UNICODE to HGYLPHs.
  81. if (cWords > 1)
  82. {
  83. rfo.vXlatGlyphArray
  84. (
  85. ((WCHAR *) pvIn) + 1,
  86. (UINT) (cWords-1),
  87. ((HGLYPH *) pvExtra) + 1
  88. );
  89. }
  90. // Copy the control word from the app over.
  91. *(HGLYPH *) pvExtra = *(WORD *) pvIn;
  92. // Adjust the pvIn and cjIn.
  93. pvIn = pvExtra;
  94. cjIn = cWords * sizeof(HGLYPH);
  95. }
  96. // It is unfortunate that apps call some printing escapes before
  97. // doing a StartDoc, so there is no real surface in the DC.
  98. // We fake up a rather poor one here if we need it. The device
  99. // driver may only dereference the dhpdev from this!
  100. SURFOBJ soFake;
  101. SURFOBJ *pso = dco.pSurface()->pSurfobj();
  102. if (pso == (SURFOBJ *) NULL)
  103. {
  104. RtlFillMemory((BYTE *) &soFake,sizeof(SURFOBJ),0);
  105. soFake.dhpdev = dco.dhpdev();
  106. soFake.hdev = dco.hdev();
  107. soFake.iType = (USHORT)STYPE_DEVICE;
  108. pso = &soFake;
  109. }
  110. // Pass it to the device.
  111. ulRet = (*pfnF)
  112. (
  113. pso,
  114. rfo.pfo(),
  115. iMode,
  116. cjIn,
  117. pvIn,
  118. cjOut,
  119. pvOut
  120. );
  121. // Free any extra RAM.
  122. if (pvExtra != NULL)
  123. {
  124. VFREEMEM(pvExtra);
  125. }
  126. return(ulRet);
  127. }
  128. /******************************Public*Routine******************************\
  129. *
  130. * LockMcdHdrSurfaces
  131. *
  132. * Locks kernel-mode handles for DirectDraw surfaces described in the
  133. * given header.
  134. *
  135. * History:
  136. * Fri Sep 20 14:18:31 1996 -by- Drew Bliss [drewb]
  137. * Created
  138. *
  139. \**************************************************************************/
  140. BOOL LockMcdHdrSurfaces(MCDESC_HEADER *pmeh,
  141. PDD_SURFACE_LOCAL *ppslColor,
  142. PDD_SURFACE_LOCAL *ppslDepth)
  143. {
  144. PDD_SURFACE_LOCAL psl;
  145. PDD_SURFACE_GLOBAL psg;
  146. *ppslColor = *ppslDepth = NULL;
  147. if (pmeh->msrfColor.hSurf != NULL)
  148. {
  149. *ppslColor = psl = EngLockDirectDrawSurface(pmeh->msrfColor.hSurf);
  150. if (psl == NULL)
  151. {
  152. return FALSE;
  153. }
  154. psg = psl->lpGbl;
  155. // Update information with trusted values
  156. pmeh->msrfColor.hSurf = (HANDLE)psl;
  157. pmeh->msrfColor.lOffset = (ULONG)psg->fpVidMem;
  158. pmeh->msrfColor.lStride = psg->lPitch;
  159. pmeh->msrfColor.rclPos.left = psg->xHint;
  160. pmeh->msrfColor.rclPos.top = psg->yHint;
  161. pmeh->msrfColor.rclPos.right = psg->xHint+psg->wWidth;
  162. pmeh->msrfColor.rclPos.bottom = psg->yHint+psg->wHeight;
  163. }
  164. if (pmeh->msrfDepth.hSurf != NULL)
  165. {
  166. *ppslDepth = psl = EngLockDirectDrawSurface(pmeh->msrfDepth.hSurf);
  167. if (psl == NULL)
  168. {
  169. if (*ppslColor)
  170. {
  171. EngUnlockDirectDrawSurface(*ppslColor);
  172. *ppslColor = NULL;
  173. }
  174. return FALSE;
  175. }
  176. psg = psl->lpGbl;
  177. // Update information with trusted values
  178. pmeh->msrfDepth.hSurf = (HANDLE)psl;
  179. pmeh->msrfDepth.lOffset = (ULONG)psg->fpVidMem;
  180. pmeh->msrfDepth.lStride = psg->lPitch;
  181. pmeh->msrfDepth.rclPos.left = psg->xHint;
  182. pmeh->msrfDepth.rclPos.top = psg->yHint;
  183. pmeh->msrfDepth.rclPos.right = psg->xHint+psg->wWidth;
  184. pmeh->msrfDepth.rclPos.bottom = psg->yHint+psg->wHeight;
  185. }
  186. return TRUE;
  187. }
  188. /******************************Public*Routine******************************\
  189. * iMcdSetupExtEscape
  190. *
  191. * MCD CreateContext ExtEscape. This special escape allows WNDOBJ to be
  192. * created in DrvEscape. This is one of the three places where WNDOBJ can
  193. * be created (the other two are iWndObjSetupExtEscape and DrvSetPixelFormat).
  194. *
  195. * See also iWndObjSetupExtEscape().
  196. *
  197. * History:
  198. * Tue Jun 21 17:24:12 1994 -by- Hock San Lee [hockl]
  199. * Wrote it.
  200. \**************************************************************************/
  201. int iMcdSetupExtEscape(
  202. DCOBJ &dco, // DC user object
  203. int nEscape, // Specifies the escape function to be performed.
  204. int cjIn, // Number of bytes of data pointed to by pvIn
  205. PVOID pvIn, // Points to the input structure required
  206. int cjOut, // Number of bytes of data pointed to by pvOut
  207. PVOID pvOut // Points to the output structure
  208. )
  209. {
  210. KFLOATING_SAVE fsFpState;
  211. MCDESC_HEADER *pmeh = (MCDESC_HEADER *)pvIn;
  212. MCDESC_HEADER_NTPRIVATE *pmehPriv =
  213. (MCDESC_HEADER_NTPRIVATE *)((PBYTE)pvIn + sizeof(MCDESC_HEADER));
  214. // This command may not be in shared memory. Also, make sure
  215. // we have entire command structure.
  216. if ((!pmehPriv->pBuffer) ||
  217. (pmehPriv->bufferSize < sizeof(MCDESC_CREATE_CONTEXT)))
  218. {
  219. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  220. return 0;
  221. }
  222. MCDESC_CREATE_CONTEXT *pmccCreate =
  223. (MCDESC_CREATE_CONTEXT *)(pmehPriv->pBuffer);
  224. ASSERTGDI(nEscape == MCDFUNCS,
  225. "iMcdSetupExtEscape(): not a CreateContext escape\n");
  226. // Validate DC surface. Info DC is not allowed.
  227. if (!dco.bHasSurface())
  228. {
  229. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  230. return(0);
  231. }
  232. // Make sure that we don't have devlock before entering user critical section.
  233. // Otherwise, it can cause deadlock.
  234. if (dco.bDisplay())
  235. {
  236. ASSERTGDI(dco.dctp() == DCTYPE_DIRECT,"ERROR it has to be direct");
  237. CHECKDEVLOCKOUT(dco);
  238. }
  239. // Enter user critical section.
  240. USERCRIT usercrit;
  241. // Grab the devlock.
  242. // We don't need to validate the devlock since we do not care if it is full screen.
  243. DEVLOCKOBJ dlo(dco);
  244. // Redirection DCs should not support escapes. This is actually a tricky
  245. // case because the dc is DCTYPE_DIRECT but the redirection surface may
  246. // not be owned by the driver (and in fact the driver may crash if we
  247. // pass it a redirection surface). So it's best to quit here.
  248. if (dco.pdc->bRedirection())
  249. {
  250. return(0);
  251. }
  252. // Assume no WNDOBJ on this call
  253. pmehPriv->pwo = (WNDOBJ *)NULL;
  254. HWND hwnd = NULL;
  255. PEWNDOBJ pwo = NULL;
  256. if (pmccCreate->flags & MCDESC_SURFACE_HWND)
  257. {
  258. // If it is a display DC, get the hwnd that the hdc is associated with.
  259. // If it is a printer or memory DC, hwnd is NULL.
  260. if (dco.bDisplay() && dco.dctp() == DCTYPE_DIRECT)
  261. {
  262. ASSERTGDI(dco.dctp() == DCTYPE_DIRECT,"ERROR it has to be direct really");
  263. if (!UserGetHwnd(dco.hdc(), &hwnd, (PVOID *) &pwo, FALSE))
  264. {
  265. SAVE_ERROR_CODE(ERROR_INVALID_WINDOW_STYLE);
  266. return(FALSE);
  267. }
  268. if (pwo)
  269. {
  270. // If the WNDOBJ is owned by a different surface (as can happen with
  271. // dynamic mode changes, where the old driver instance lives as long
  272. // as the WNDOBJ is alive), simply fail the call.
  273. if (pwo->pto->pSurface != dco.pSurface())
  274. {
  275. #ifdef OPENGL_MM
  276. // Under multi-mon the DCOBJ may have the meta-surface while
  277. // the pto was created with the actual hardware surface.
  278. // So if the parent hdev of hdev in WNDOBJ is same as hdev in
  279. // DCOBJ, we will allow to continue since we have replaced
  280. // meta-PDEV with hardware PDEV. so it's fine.
  281. PDEVOBJ pdoOfPwo(pwo->pto->pSurface->hdev());
  282. if (pdoOfPwo.hdevParent() != dco.hdev())
  283. {
  284. WARNING("iMcdSetupExtEscape: pwo->pto->pSurface != dco.pSurface, so bailing out\n");
  285. return(FALSE);
  286. }
  287. #else
  288. return(FALSE);
  289. #endif // OPENGL_MM
  290. }
  291. if (!(pwo->fl & WO_GENERIC_WNDOBJ))
  292. pmehPriv->pwo = (WNDOBJ *)pwo;
  293. }
  294. }
  295. // Make sure that DC hwnd matches MCDESC_CREATE_CONTEXT hwnd.
  296. if (hwnd != pmccCreate->hwnd)
  297. {
  298. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  299. return(0);
  300. }
  301. }
  302. // Dispatch the call.
  303. PDEVOBJ pdo(dco.hdev());
  304. SURFOBJ *pso = dco.pSurface()->pSurfobj();
  305. #ifdef OPENGL_MM
  306. if (pdo.bMetaDriver())
  307. {
  308. // We need to change the meta-PDEV into a hardware specific PDEV
  309. HDEV hdevDevice = hdevFindDeviceHdev(
  310. dco.hdev(), (RECTL)dco.erclWindow(), pwo);
  311. if (hdevDevice)
  312. {
  313. // If the surface is pdev's primary surface, we will replace it with
  314. // new device pdev's surface.
  315. if (pdo.bPrimary(dco.pSurface()))
  316. {
  317. PDEVOBJ pdoDevice(hdevDevice);
  318. pso = pdoDevice.pSurface()->pSurfobj();
  319. }
  320. // replace meta pdevobj with device specific hdev.
  321. pdo.vInit(hdevDevice);
  322. }
  323. }
  324. #endif // OPENGL_MM
  325. if ( !PPFNDRV( pdo, Escape ))
  326. return(0);
  327. // Handle any surfaces
  328. // This escape doesn't expect any extra locks
  329. ASSERTGDI((pmeh->flags & MCDESC_FL_LOCK_SURFACES) == 0,
  330. "iMcdSetupExtEscape: MCDESC_FL_LOCK_SURFACES set\n");
  331. PDD_SURFACE_LOCAL psl[2] = { NULL, NULL };
  332. if (pmeh->flags & MCDESC_FL_SURFACES)
  333. {
  334. if (!LockMcdHdrSurfaces(pmeh, &psl[0], &psl[1]))
  335. {
  336. return 0;
  337. }
  338. }
  339. // Save floating point state
  340. // This allows client drivers to do floating point operations
  341. // If the state were not preserved then we would be corrupting the
  342. // thread's user-mode FP state
  343. int iRet;
  344. if (!NT_SUCCESS(KeSaveFloatingPointState(&fsFpState)))
  345. {
  346. WARNING("iMcdSetupExtEscape: Unable to save FP state\n");
  347. iRet = 0;
  348. goto iMcdSetupExtEscape_Unlock_And_Exit;
  349. }
  350. iRet = (int) pdo.Escape(pso,
  351. (ULONG)nEscape,
  352. (ULONG)cjIn,
  353. pvIn,
  354. (ULONG)cjOut,
  355. pvOut);
  356. // Restore floating point state
  357. KeRestoreFloatingPointState(&fsFpState);
  358. // If a new WNDOBJ is created, we need to update the window client regions
  359. // in the driver.
  360. if (gbWndobjUpdate)
  361. {
  362. gbWndobjUpdate = FALSE;
  363. vForceClientRgnUpdate();
  364. }
  365. iMcdSetupExtEscape_Unlock_And_Exit:
  366. if (pmeh->flags & MCDESC_FL_SURFACES)
  367. {
  368. if (psl[0])
  369. {
  370. EngUnlockDirectDrawSurface(psl[0]);
  371. }
  372. if (psl[1])
  373. {
  374. EngUnlockDirectDrawSurface(psl[1]);
  375. }
  376. }
  377. return(iRet);
  378. }
  379. /******************************Public*Routine******************************\
  380. * iWndObjSetupExtEscape
  381. *
  382. * Live video ExtEscape. This special escape allows WNDOBJ to be created
  383. * in DrvEscape. This is one of the three places where WNDOBJ can be created
  384. * (the other two are iMcdSetupExtEscape and DrvSetPixelFormat).
  385. *
  386. * See also iMcdSetupExtEscape().
  387. *
  388. * History:
  389. * Fri Feb 18 13:25:13 1994 -by- Hock San Lee [hockl]
  390. * Wrote it.
  391. \**************************************************************************/
  392. int iWndObjSetupExtEscape
  393. (
  394. DCOBJ &dco, // DC user object
  395. int nEscape, // Specifies the escape function to be performed.
  396. int cjIn, // Number of bytes of data pointed to by pvIn
  397. PVOID pvIn, // Points to the input structure required
  398. int cjOut, // Number of bytes of data pointed to by pvOut
  399. PVOID pvOut // Points to the output structure
  400. )
  401. {
  402. ASSERTGDI(nEscape == WNDOBJ_SETUP,
  403. "iWndObjSetupExtEscape(): not a WndObjSetup escape\n");
  404. // Validate DC surface. Info DC is not allowed.
  405. if (!dco.bHasSurface())
  406. {
  407. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  408. return(0);
  409. }
  410. // Make sure that we don't have devlock before entering user critical section.
  411. // Otherwise, it can cause deadlock.
  412. if (dco.bDisplay())
  413. {
  414. ASSERTGDI(dco.dctp() == DCTYPE_DIRECT,"ERROR it has to be direct");
  415. CHECKDEVLOCKOUT(dco);
  416. }
  417. // Enter user critical section.
  418. USERCRIT usercrit;
  419. // Grab the devlock.
  420. // We don't need to validate the devlock since we do not care if it is full screen.
  421. DEVLOCKOBJ dlo(dco);
  422. // Redirection DCs should not support escapes. This is actually a tricky
  423. // case because the dc is DCTYPE_DIRECT but the redirection surface may
  424. // not be owned by the driver (and in fact the driver may crash if we
  425. // pass it a redirection surface). So it's best to quit here.
  426. if (dco.pdc->bRedirection())
  427. {
  428. return(0);
  429. }
  430. // Dispatch the call.
  431. PDEVOBJ pdo(dco.hdev());
  432. SURFOBJ *pso = dco.pSurface()->pSurfobj();
  433. #ifdef OPENGL_MM
  434. if (pdo.bMetaDriver())
  435. {
  436. // We need to change the meta-PDEV into a hardware specific PDEV
  437. HDEV hdevDevice = hdevFindDeviceHdev(
  438. dco.hdev(), (RECTL)dco.erclWindow(), NULL);
  439. if (hdevDevice)
  440. {
  441. // If the surface is pdev's primary surface, we will replace it with
  442. // new device pdev's surface.
  443. if (pdo.bPrimary(dco.pSurface()))
  444. {
  445. PDEVOBJ pdoDevice(hdevDevice);
  446. pso = pdoDevice.pSurface()->pSurfobj();
  447. }
  448. // replace meta pdevobj with device specific hdev.
  449. pdo.vInit(hdevDevice);
  450. }
  451. }
  452. #endif // OPENGL_MM
  453. if ( !PPFNDRV( pdo, Escape ))
  454. return(0);
  455. int iRet = (int) pdo.Escape(pso,
  456. (ULONG)nEscape,
  457. (ULONG)cjIn,
  458. pvIn,
  459. (ULONG)cjOut,
  460. pvOut);
  461. // If a new WNDOBJ is created, we need to update the window client regions
  462. // in the driver.
  463. if (gbWndobjUpdate)
  464. {
  465. gbWndobjUpdate = FALSE;
  466. vForceClientRgnUpdate();
  467. }
  468. return(iRet);
  469. }
  470. /******************************Public*Routine******************************\
  471. *
  472. * LookUpWndobjs
  473. *
  474. * Looks up WNDOBJs for a list of HDCs. Only performs lookups for
  475. * HDCs which are for the same device as that given. Returns negative
  476. * if error, otherwise it returns a bitmask of the HDCs
  477. * that had a lookup.
  478. *
  479. * Fills in DCOBJ table with locked DCs for tested HDCs.
  480. * Overwrites HDC table with WNDOBJ pointers.
  481. *
  482. * History:
  483. * Mon Oct 14 16:48:13 1996 -by- Drew Bliss [drewb]
  484. * Created
  485. *
  486. \**************************************************************************/
  487. int LookUpWndobjs(DCOBJ *pdcoMatch, DCOBJ *pdcoFill, HDC *phdc, int n)
  488. {
  489. int iMask;
  490. HDEV hdevMatch;
  491. int i;
  492. CHECKUSERCRITIN;
  493. hdevMatch = pdcoMatch->hdev();
  494. iMask = 0;
  495. for (i = 0; i < n; i++)
  496. {
  497. pdcoFill->vLock(*phdc);
  498. if (!pdcoFill->bValid())
  499. {
  500. return -1;
  501. }
  502. if (pdcoFill->hdev() != hdevMatch)
  503. {
  504. pdcoFill->vUnlock();
  505. *phdc = NULL;
  506. }
  507. else
  508. {
  509. HWND hwnd;
  510. if (!UserGetHwnd(*phdc, &hwnd, (PVOID *)phdc, FALSE))
  511. {
  512. return -1;
  513. }
  514. else
  515. {
  516. iMask |= 1 << i;
  517. }
  518. }
  519. phdc++;
  520. pdcoFill++;
  521. }
  522. return iMask;
  523. }
  524. /******************************Public*Routine******************************\
  525. * iMcdExtEscape
  526. *
  527. * Take the MCD special case ExtEscape out of line to minimize the
  528. * impact on other ExtEscapes. We need to stick special data into the
  529. * input buffer. No CLIPOBJ is given to the driver here.
  530. *
  531. * History:
  532. * Tue Jun 21 17:24:12 1994 -by- Hock San Lee [hockl]
  533. * Wrote it.
  534. \**************************************************************************/
  535. int iMcdExtEscape(
  536. DCOBJ &dco, // DC user object
  537. int nEscape, // Specifies the escape function to be performed.
  538. int cjIn, // Number of bytes of data pointed to by pvIn
  539. PVOID pvIn, // Points to the input structure required
  540. int cjOut, // Number of bytes of data pointed to by pvOut
  541. PVOID pvOut // Points to the output structure
  542. )
  543. {
  544. BOOL bSaveSwapEnable;
  545. KFLOATING_SAVE fsFpState;
  546. ULONG i;
  547. int iRet = 0;
  548. int iMultiMask;
  549. DCOBJ dcoMulti[MCDESC_MAX_EXTRA_WNDOBJ];
  550. ASSERTGDI(nEscape == MCDFUNCS, "iMcdExtEscape(): not an MCD escape\n");
  551. // Validate DC surface. Info DC is not allowed.
  552. if (!dco.bHasSurface())
  553. {
  554. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  555. return iRet;
  556. }
  557. // Special processing for 3D-DDI escape.
  558. //
  559. // The escape requires that the server fill in the pwo engine object pointer
  560. // before it is passed to the display driver. The client side simply
  561. // doesn't have a clue what this might be.
  562. // CAUTION: These object are defined here so that they will live long enough
  563. // to be valid when control is passed to the driver!
  564. // Grab the devlock and lock down wndobj.
  565. DEVLOCKOBJ_WNDOBJ dlo(dco);
  566. // Redirection DCs should not support escapes. This is actually a tricky
  567. // case because the dc is DCTYPE_DIRECT but the redirection surface may
  568. // not be owned by the driver (and in fact the driver may crash if we
  569. // pass it a redirection surface). So it's best to quit here.
  570. if (dco.pdc->bRedirection())
  571. {
  572. return(0);
  573. }
  574. if (!dlo.bValidDevlock())
  575. {
  576. if (!dco.bFullScreen())
  577. {
  578. WARNING("iMcdExtEscape(): devlock failed\n");
  579. return iRet;
  580. }
  581. }
  582. PDEVOBJ pdo(dco.hdev());
  583. SURFOBJ *pso = dco.pSurface()->pSurfobj();
  584. #ifdef OPENGL_MM
  585. if (pdo.bMetaDriver())
  586. {
  587. // We need to change the meta-PDEV into a hardware specific PDEV
  588. HDEV hdevDevice = hdevFindDeviceHdev(
  589. dco.hdev(),
  590. (RECTL)dco.erclWindow(),
  591. (dlo.bValidWndobj() ? dlo.pwo() : NULL));
  592. if (hdevDevice)
  593. {
  594. // If the surface is pdev's primary surface, we will replace it with
  595. // new device pdev's surface.
  596. if (pdo.bPrimary(dco.pSurface()))
  597. {
  598. PDEVOBJ pdoDevice(hdevDevice);
  599. pso = pdoDevice.pSurface()->pSurfobj();
  600. }
  601. // replace meta pdevobj with device specific hdev.
  602. pdo.vInit(hdevDevice);
  603. }
  604. }
  605. #endif // OPENGL_MM
  606. // Locate the driver entry point.
  607. if ( !PPFNDRV( pdo, Escape ))
  608. return( iRet );
  609. if (pdo.bUMPD())
  610. return (iRet);
  611. // If surfaces are passed through the MCDESC_HEADER then lock them
  612. MCDESC_HEADER *pmeh = (MCDESC_HEADER *)pvIn;
  613. MCDESC_HEADER_NTPRIVATE *pmehPriv = (MCDESC_HEADER_NTPRIVATE *)(pmeh+1);
  614. PDD_SURFACE_LOCAL psl[2+MCDESC_MAX_LOCK_SURFACES];
  615. RtlZeroMemory(psl, (2+MCDESC_MAX_LOCK_SURFACES) * sizeof(PDD_SURFACE_LOCAL));
  616. // First lock standard surfaces
  617. if (pmeh->flags & MCDESC_FL_SURFACES)
  618. {
  619. if (!LockMcdHdrSurfaces(pmeh, &psl[0], &psl[1]))
  620. {
  621. return iRet;
  622. }
  623. }
  624. // Now check for extra surfaces
  625. if (pmeh->flags & MCDESC_FL_LOCK_SURFACES)
  626. {
  627. HANDLE *phSurf;
  628. phSurf = pmehPriv->pLockSurfaces;
  629. for (i = 0; i < pmeh->cLockSurfaces; i++)
  630. {
  631. if ((psl[i+2] = EngLockDirectDrawSurface(*phSurf++)) == NULL)
  632. {
  633. goto iMcdExtEscape_Unlock_And_Exit;
  634. }
  635. }
  636. }
  637. // Look up any extra WNDOBJs that need to be looked up
  638. if (pmeh->flags & MCDESC_FL_EXTRA_WNDOBJ)
  639. {
  640. iMultiMask = LookUpWndobjs(&dco, dcoMulti, pmehPriv->pExtraWndobj,
  641. pmeh->cExtraWndobj);
  642. if (iMultiMask < 0)
  643. {
  644. goto iMcdExtEscape_Unlock_And_Exit;
  645. }
  646. }
  647. // Grow the kernel stack so that OpenGL drivers can use more
  648. // stack than is provided by default. The call attempts to
  649. // grow the stack to the maximum possible size
  650. // The stack will shrink back automatically so there's no cleanup
  651. // necessary
  652. if (!NT_SUCCESS(MmGrowKernelStack((BYTE *)PsGetCurrentThreadStackBase()-
  653. KERNEL_LARGE_STACK_SIZE+
  654. KERNEL_LARGE_STACK_COMMIT)))
  655. {
  656. WARNING("iMcdExtEscape: Unable to grow stack\n");
  657. goto iMcdExtEscape_Unlock_And_Exit;
  658. }
  659. // Ensure that the stack does not shrink back until we release it.
  660. bSaveSwapEnable = KeSetKernelStackSwapEnable(FALSE);
  661. // We need to get the WNDOBJ for the driver. Note that we pass calls
  662. // through to the driver even if we don't yet have a WNDOBJ to allow
  663. // query functions to succeed (before context-creation). Cursor exclusion
  664. // is not performed in this case, since no drawing is done.
  665. {
  666. DEVEXCLUDEWNDOBJ dxoWnd;
  667. if (dlo.bValidWndobj())
  668. {
  669. // Put the DDI pwo pointer in the input buffer.
  670. PEWNDOBJ pwo;
  671. pwo = dlo.pwo();
  672. // If the WNDOBJ is owned by a different surface (as can happen with
  673. // dynamic mode changes, where the old driver instance lives as long
  674. // as the WNDOBJ is alive), simply fail the call.
  675. if (pwo->pto->pSurface != dco.pSurface())
  676. {
  677. #ifdef OPENGL_MM
  678. // Under multi-mon the DCOBJ may have the meta-surface while
  679. // the pto was created with the actual hardware surface.
  680. // So if the parent hdev of hdev in WNDOBJ is same as hdev in
  681. // DCOBJ, we will allow to continue since we have replaced
  682. // meta-PDEV with hardware PDEV. so it's fine.
  683. PDEVOBJ pdoOfPwo(pwo->pto->pSurface->hdev());
  684. if (pdoOfPwo.hdevParent() != dco.hdev())
  685. {
  686. WARNING("iMcdExtEscape: pwo->pto->pSurface != dco.pSurface, so bailing out\n");
  687. goto iMcdExtEscape_RestoreSwap;
  688. }
  689. #else
  690. goto iMcdExtEscape_RestoreSwap;
  691. #endif // OPENGL_MM
  692. }
  693. if (pwo->fl & WO_GENERIC_WNDOBJ)
  694. pwo = (PEWNDOBJ) NULL;
  695. pmehPriv->pwo = (WNDOBJ *) pwo;
  696. // Cursor exclusion.
  697. // Note that we do not early out for empty clip rectangle.
  698. if (pwo)
  699. {
  700. dxoWnd.vExclude(pwo);
  701. INC_SURF_UNIQ(dco.pSurface());
  702. }
  703. }
  704. else
  705. pmehPriv->pwo = (WNDOBJ *) NULL;
  706. }
  707. // Save floating point state
  708. // This allows client drivers to do floating point operations
  709. // If the state were not preserved then we would be corrupting the
  710. // thread's user-mode FP state
  711. if (!NT_SUCCESS(KeSaveFloatingPointState(&fsFpState)))
  712. {
  713. WARNING("iMcdExtEscape: Unable to save FP state\n");
  714. goto iMcdExtEscape_RestoreSwap;
  715. }
  716. // Call the driver escape.
  717. iRet = (int) pdo.Escape(pso,
  718. (ULONG)nEscape,
  719. (ULONG)cjIn,
  720. pvIn,
  721. (ULONG)cjOut,
  722. pvOut);
  723. if (pmeh->flags & MCDESC_FL_EXTRA_WNDOBJ)
  724. {
  725. iRet = (iRet & (0xffffffff >> MCDESC_MAX_EXTRA_WNDOBJ)) |
  726. (iMultiMask << (32-MCDESC_MAX_EXTRA_WNDOBJ));
  727. }
  728. // Restore floating point state and stack swap enable state
  729. KeRestoreFloatingPointState(&fsFpState);
  730. iMcdExtEscape_RestoreSwap:
  731. KeSetKernelStackSwapEnable((BOOLEAN)bSaveSwapEnable);
  732. iMcdExtEscape_Unlock_And_Exit:
  733. if (pmeh->flags & MCDESC_FL_SURFACES)
  734. {
  735. if (psl[0])
  736. {
  737. EngUnlockDirectDrawSurface(psl[0]);
  738. }
  739. if (psl[1])
  740. {
  741. EngUnlockDirectDrawSurface(psl[1]);
  742. }
  743. }
  744. if (pmeh->flags & MCDESC_FL_LOCK_SURFACES)
  745. {
  746. for (i = 0; i < pmeh->cLockSurfaces; i++)
  747. {
  748. if (psl[i+2])
  749. {
  750. EngUnlockDirectDrawSurface(psl[i+2]);
  751. }
  752. }
  753. }
  754. return iRet;
  755. }
  756. /******************************Public*Routine******************************\
  757. * iOpenGLExtEscape
  758. *
  759. * Take the OpenGL special case ExtEscape out of line to minimize the
  760. * impact on non-OpenGL ExtEscapes. We need to stick special data into the
  761. * input buffer. No CLIPOBJ is given to the driver here.
  762. *
  763. * History:
  764. * 20-Jan-1994 -by- Gilman Wong [gilmanw]
  765. * Wrote it.
  766. \**************************************************************************/
  767. int iOpenGLExtEscape(
  768. DCOBJ &dco, // DC user object
  769. int nEscape, // Specifies the escape function to be performed.
  770. int cjIn, // Number of bytes of data pointed to by pvIn
  771. PVOID pvIn, // Points to the input structure required
  772. int cjOut, // Number of bytes of data pointed to by pvOut
  773. PVOID pvOut // Points to the output structure
  774. )
  775. {
  776. BOOL bSaveSwapEnable;
  777. KFLOATING_SAVE fsFpState;
  778. int iRet = 0;
  779. int iMultiMask;
  780. DCOBJ dcoMulti[OPENGLCMD_MAXMULTI];
  781. ASSERTGDI(
  782. (nEscape == OPENGL_CMD) || (nEscape == OPENGL_GETINFO),
  783. "iOpenGLExtEscape(): not an OpenGL escape\n");
  784. // Validate DC surface. Info DC is not allowed.
  785. if (!dco.bHasSurface())
  786. {
  787. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  788. return(0);
  789. }
  790. // Special processing for OPENGL_CMD escape.
  791. //
  792. // The OPENGL_CMD escape may require that the server fill in the pxo and
  793. // pwo engine object pointers before it is passed to the display driver.
  794. // The client side simply doesn't have a clue what these might be.
  795. // CAUTION: These object are defined here so that they will live long enough
  796. // to be valid when control is passed to the driver!
  797. EXLATEOBJ xlo;
  798. XLATEOBJ *pxlo = (XLATEOBJ *) NULL;
  799. PDEVOBJ po(dco.hdev());
  800. ASSERTGDI(po.bValid(), "iOpenGLExtEscape(): bad hdev in DC\n");
  801. // Grab the devlock and user crit section
  802. DEVLOCKOBJ_WNDOBJ dlo(dco);
  803. // Redirection DCs should not support escapes. This is actually a tricky
  804. // case because the dc is DCTYPE_DIRECT but the redirection surface may
  805. // not be owned by the driver (and in fact the driver may crash if we
  806. // pass it a redirection surface). So it's best to quit here.
  807. if (dco.pdc->bRedirection())
  808. {
  809. return(0);
  810. }
  811. if (!dlo.bValidDevlock())
  812. {
  813. if (!dco.bFullScreen())
  814. {
  815. WARNING("iOpenGLExtEscape(): devlock failed\n");
  816. return 0;
  817. }
  818. }
  819. // Find a target surface, if DDML.
  820. PSURFACE pSurface = dco.pSurfaceEff();
  821. #ifdef OPENGL_MM
  822. if (po.bMetaDriver())
  823. {
  824. // We need to change the meta-PDEV into a hardware specific PDEV
  825. HDEV hdevDevice = hdevFindDeviceHdev(
  826. dco.hdev(),
  827. (RECTL)dco.erclWindow(),
  828. (dlo.bValidWndobj() ? dlo.pwo() : NULL));
  829. if (hdevDevice)
  830. {
  831. // If the surface is pdev's primary surface, we will replace it with
  832. // new device pdev's surface.
  833. if (po.bPrimary(dco.pSurface()))
  834. {
  835. PDEVOBJ poDevice(hdevDevice);
  836. pSurface = poDevice.pSurface();
  837. }
  838. // replace meta pdevobj with device specific hdev.
  839. po.vInit(hdevDevice);
  840. }
  841. }
  842. #endif // OPENGL_MM
  843. SURFOBJ *pso = pSurface->pSurfobj();
  844. // Locate the driver entry point.
  845. if (!PPFNDRV(po, Escape))
  846. return(0);
  847. if (po.bUMPD())
  848. return (0);
  849. // Create a sprite exclusion object. Actual exclusion is performed elsewhere
  850. // as needed.
  851. DEVEXCLUDEWNDOBJ dxoWnd;
  852. DEVEXCLUDERECT dxoRect;
  853. // Grow the kernel stack so that OpenGL drivers can use more
  854. // stack than is provided by default. The call attempts to
  855. // grow the stack to the maximum possible size
  856. // The stack will shrink back automatically so there's no cleanup
  857. // necessary
  858. if (!NT_SUCCESS(MmGrowKernelStack((BYTE *)PsGetCurrentThreadStackBase()-
  859. KERNEL_LARGE_STACK_SIZE+
  860. KERNEL_LARGE_STACK_COMMIT)))
  861. {
  862. WARNING("iOpenGLExtEscape: Unable to grow stack\n");
  863. return 0;
  864. }
  865. // Ensure that the stack does not shrink back until we release it.
  866. bSaveSwapEnable = KeSetKernelStackSwapEnable(FALSE);
  867. // Save floating point state
  868. // This allows client drivers to do floating point operations
  869. // If the state were not preserved then we would be corrupting the
  870. // thread's user-mode FP state
  871. if (!NT_SUCCESS(KeSaveFloatingPointState(&fsFpState)))
  872. {
  873. WARNING("iOpenGLExtEscape: Unable to save FP state\n");
  874. goto iOpenGLExtEscape_RestoreSwap;
  875. }
  876. // Handle OPENGL_CMD processing.
  877. if ( nEscape == OPENGL_CMD )
  878. {
  879. ASSERTGDI(sizeof(OPENGLCMD) == sizeof(OPENGLCMDMULTI),
  880. "OPENGLCMD doesn't match OPENGLCMDMULTI\n");
  881. // Better check input size. We don't want to access violate.
  882. if (cjIn < sizeof(OPENGLCMD))
  883. {
  884. WARNING("iOpenGLExtEscape(): buffer too small\n");
  885. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  886. goto iOpenGLExtEscape_RestoreState;
  887. }
  888. DWORD inBuffer[(sizeof(OPENGLCMD) + 128) / sizeof(DWORD)];
  889. POPENGLCMD poglcmd;
  890. POPENGLCMDMULTI pomcmd;
  891. // Copy pvIn to a private buffer to prevent client process from trashing
  892. // pwo and pxlo.
  893. if (cjIn <= sizeof(inBuffer))
  894. {
  895. poglcmd = (POPENGLCMD) inBuffer;
  896. }
  897. else
  898. {
  899. // may affect performance
  900. WARNING("iOpenGLExtEscape(): big input buffer\n");
  901. poglcmd = (POPENGLCMD) PALLOCNOZ(cjIn,'lgoG');
  902. if (!poglcmd)
  903. {
  904. SAVE_ERROR_CODE(ERROR_NOT_ENOUGH_MEMORY);
  905. goto iOpenGLExtEscape_RestoreState;
  906. }
  907. }
  908. RtlCopyMemory((PBYTE) poglcmd, (PBYTE) pvIn, cjIn);
  909. if (poglcmd->fl & OGLCMD_MULTIWNDOBJ)
  910. {
  911. pomcmd = (POPENGLCMDMULTI)poglcmd;
  912. if (pomcmd->cMulti > OPENGLCMD_MAXMULTI ||
  913. (DWORD)cjIn < sizeof(OPENGLCMDMULTI)+pomcmd->cMulti*
  914. sizeof(HDC))
  915. {
  916. SAVE_ERROR_CODE(ERROR_NOT_ENOUGH_MEMORY);
  917. goto oglcmd_cleanup;
  918. }
  919. iMultiMask = LookUpWndobjs(&dco, dcoMulti, (HDC *)(poglcmd+1),
  920. pomcmd->cMulti);
  921. if (iMultiMask < 0)
  922. {
  923. goto oglcmd_cleanup;
  924. }
  925. }
  926. if ( poglcmd->fl & OGLCMD_NEEDXLATEOBJ )
  927. {
  928. switch (po.iDitherFormat())
  929. {
  930. case BMF_4BPP:
  931. case BMF_8BPP:
  932. {
  933. XEPALOBJ pal(dco.ppal());
  934. if ( pal.bValid() )
  935. {
  936. COUNT cColors = (po.iDitherFormat() == BMF_4BPP) ? 16 : 256;
  937. USHORT aus[256];
  938. for (COUNT ii = 0; ii < cColors; ii++)
  939. aus[ii] = (USHORT) ii;
  940. #ifdef OPENGL_MM
  941. if ( xlo.bMakeXlate(aus, pal, pSurface, cColors, cColors) )
  942. #else
  943. if ( xlo.bMakeXlate(aus, pal, dco.pSurfaceEff(), cColors, cColors) )
  944. #endif // OPENGL_MM
  945. pxlo = (XLATEOBJ *) xlo.pxlo();
  946. }
  947. if (!pxlo)
  948. pxlo = &xloIdent;
  949. }
  950. break;
  951. default:
  952. pxlo = &xloIdent;
  953. break;
  954. }
  955. }
  956. // Write the XLATOBJ into the correct places in the input structure.
  957. poglcmd->pxo = pxlo;
  958. // May need to get the WNDOBJ for the driver.
  959. if ((poglcmd->fl & OGLCMD_MULTIWNDOBJ) == 0)
  960. {
  961. if (poglcmd->fl & OGLCMD_NEEDWNDOBJ)
  962. {
  963. if (!dlo.bValidWndobj() || dlo.pwo()->fl & WO_GENERIC_WNDOBJ)
  964. {
  965. WARNING("iOpenGLExtEscape(): invalid WNDOBJ\n");
  966. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  967. goto oglcmd_cleanup;
  968. }
  969. // If the WNDOBJ is owned by a different surface (as can happen with
  970. // dynamic mode changes, where the old driver instance lives as long
  971. // as the WNDOBJ is alive), simply fail the call.
  972. if (dlo.pwo()->pto->pSurface != dco.pSurface())
  973. {
  974. #ifdef OPENGL_MM
  975. // Under multi-mon the DCOBJ may have the meta-surface while
  976. // the pto was created with the actual hardware surface.
  977. // So if the parent hdev of hdev in WNDOBJ is same as hdev in
  978. // DCOBJ, we will allow to continue since we have replaced
  979. // meta-PDEV with hardware PDEV. so it's fine.
  980. PDEVOBJ pdoOfPwo(dlo.pwo()->pto->pSurface->hdev());
  981. if (pdoOfPwo.hdevParent() != dco.hdev())
  982. {
  983. WARNING("iOpenGLExtEscape: pwo->pto->pSurface != dco.pSurface, so bailing out\n");
  984. goto oglcmd_cleanup;
  985. }
  986. #else
  987. goto oglcmd_cleanup;
  988. #endif // OPENGL_MM
  989. }
  990. poglcmd->pwo = (WNDOBJ *)dlo.pwo();
  991. }
  992. else
  993. {
  994. poglcmd->pwo = (WNDOBJ *)NULL;
  995. }
  996. }
  997. // Cursor exclusion.
  998. if (dlo.bValidWndobj())
  999. {
  1000. // If the driver's WNDOBJ knows about sprites, we assume the driver
  1001. // will take of exclusion.
  1002. if (!(dlo.pwo()->fl & WO_SPRITE_NOTIFY))
  1003. {
  1004. dxoWnd.vExclude(dlo.pwo());
  1005. }
  1006. INC_SURF_UNIQ(dco.pSurface());
  1007. }
  1008. else
  1009. {
  1010. ERECTL ercl(dco.prgnEffRao()->rcl);
  1011. ECLIPOBJ co(dco.prgnEffRao(), ercl, FALSE);
  1012. dxoRect.vExclude(dco.hdev(), &co.erclExclude());
  1013. INC_SURF_UNIQ(dco.pSurface());
  1014. }
  1015. iRet = (int) po.Escape(pso,
  1016. (ULONG)nEscape,
  1017. (ULONG)cjIn,
  1018. (PVOID)poglcmd,
  1019. (ULONG)cjOut,
  1020. pvOut);
  1021. if (poglcmd->fl & OGLCMD_MULTIWNDOBJ)
  1022. {
  1023. iRet = (iRet & (0xffffffff >> OPENGLCMD_MAXMULTI)) |
  1024. (iMultiMask << (32-OPENGLCMD_MAXMULTI));
  1025. }
  1026. oglcmd_cleanup:
  1027. if (cjIn > sizeof(inBuffer))
  1028. VFREEMEM(poglcmd);
  1029. } // if ( nEscape == OPENGL_CMD )
  1030. else
  1031. {
  1032. // Handle OPENGL_GETINFO processing.
  1033. iRet = ((int) po.Escape(pso,
  1034. (ULONG)nEscape,
  1035. (ULONG)cjIn,
  1036. pvIn,
  1037. (ULONG)cjOut,
  1038. pvOut));
  1039. }
  1040. // Restore floating point state
  1041. iOpenGLExtEscape_RestoreState:
  1042. KeRestoreFloatingPointState(&fsFpState);
  1043. iOpenGLExtEscape_RestoreSwap:
  1044. KeSetKernelStackSwapEnable((BOOLEAN)bSaveSwapEnable);
  1045. return iRet;
  1046. }
  1047. /******************************Public*Routine******************************\
  1048. * iCheckPassthroughImage
  1049. *
  1050. * Implements the CHECKJPEGFORMAT and CHECKPNGFORMAT escapes on behalf of
  1051. * the driver. Converts the escape into a call to DrvQueryDriverSupport
  1052. * which can pass objects such as XLATEOBJ to the driver that DrvEscape
  1053. * does not have.
  1054. *
  1055. * These escapes are used to validate images with the device so that
  1056. * they can later be sent directly (passthrough) to the device.
  1057. *
  1058. * Returns:
  1059. * QUERYESCSUPPORT returns 1 if escape supported, 0 otherwise.
  1060. * CHECKJPEGFORMAT/CHECKPNGFORMAT returns 1 if image supported, 0 if not
  1061. * supported, and -1 if error.
  1062. *
  1063. * History:
  1064. * 14-Oct-1997 -by- Gilman Wong [gilmanw]
  1065. * Wrote it.
  1066. \**************************************************************************/
  1067. int iCheckPassthroughImage(
  1068. DCOBJ &dco, // DC user object
  1069. PDEVOBJ &pdo, // PDEV user object
  1070. int nEscape, // Specifies the escape function to be performed.
  1071. int cjIn, // Number of bytes of data pointed to by pvIn
  1072. PVOID pvIn, // Points to the input structure required
  1073. int cjOut, // Number of bytes of data pointed to by pvOut
  1074. PVOID pvOut // Points to the output structure
  1075. )
  1076. {
  1077. int iRet = 0; // not supported
  1078. if (nEscape == QUERYESCSUPPORT)
  1079. {
  1080. ASSERTGDI((*(ULONG*)pvIn == CHECKJPEGFORMAT) ||
  1081. (*(ULONG*)pvIn == CHECKPNGFORMAT),
  1082. "iCheckPassthroughImage: unknown escape\n");
  1083. if (*(ULONG*)pvIn == CHECKJPEGFORMAT)
  1084. {
  1085. // Escape is supported if driver has JPEG support.
  1086. if (dco.bSupportsJPEG() &&
  1087. (PPFNVALID(pdo, QueryDeviceSupport)))
  1088. {
  1089. iRet = 1;
  1090. }
  1091. }
  1092. else
  1093. {
  1094. // Escape is supported if driver has PNG support.
  1095. if (dco.bSupportsPNG() &&
  1096. (PPFNVALID(pdo, QueryDeviceSupport)))
  1097. {
  1098. iRet = 1;
  1099. }
  1100. }
  1101. }
  1102. else if (PPFNVALID(pdo, QueryDeviceSupport))
  1103. {
  1104. ASSERTGDI((nEscape == CHECKJPEGFORMAT) || (nEscape == CHECKPNGFORMAT),
  1105. "iCheckPassthroughImage: unknown escape\n");
  1106. if ((cjOut >= sizeof(ULONG)) && pvOut)
  1107. {
  1108. // There is no surface in metafile DCs. In addition, some
  1109. // apps call printing escape before the StartDoc, also
  1110. // resulting in no real surface in DC.
  1111. //
  1112. // The XLATEOBJ generated in this way may not be valid except
  1113. // for the ICM information (which is all this escape cares
  1114. // about in the XLATEOBJ anyway).
  1115. XEPALOBJ palDest(dco.pSurface() ? dco.pSurface()->ppal() : NULL);
  1116. XEPALOBJ palDestDC(dco.ppal());
  1117. PALMEMOBJ palTemp;
  1118. XLATEOBJ *pxlo = NULL;
  1119. EXLATEOBJ xlo;
  1120. // Create the XLATEOBJ so driver can determine the ICM state.
  1121. if (((nEscape == CHECKJPEGFORMAT) && dco.bSupportsJPEG()) ||
  1122. ((nEscape == CHECKPNGFORMAT ) && dco.bSupportsPNG()))
  1123. {
  1124. if (palTemp.bCreatePalette(PAL_BGR, 0, (PULONG) NULL,
  1125. 0, 0, 0, PAL_FIXED))
  1126. {
  1127. if (xlo.pInitXlateNoCache(dco.pdc->hcmXform(),
  1128. dco.pdc->lIcmMode(),
  1129. palTemp,
  1130. palDest,
  1131. palDestDC,
  1132. 0,
  1133. 0,
  1134. 0x00FFFFFF))
  1135. {
  1136. pxlo = xlo.pxlo();
  1137. }
  1138. else
  1139. {
  1140. WARNING("ExtEscape(CHECKJPEGFORMAT/CHECKPNGFORMAT): "
  1141. "failed pxlo creation\n");
  1142. iRet = -1; // error
  1143. }
  1144. }
  1145. }
  1146. // If XLATEOBJ created, call DrvQueryDriverSupport to validate
  1147. // the image.
  1148. if (pxlo)
  1149. {
  1150. // There is no surface in metafile DCs. In addition, some
  1151. // apps call printing escape before the StartDoc, also
  1152. // resulting in no real surface in DC.
  1153. //
  1154. // We fake up a rather poor one here if we need it. The
  1155. // device driver may only dereference the dhpdev from this!
  1156. SURFOBJ soFake;
  1157. SURFOBJ *pso = dco.pSurface()->pSurfobj();
  1158. if (pso == (SURFOBJ *) NULL)
  1159. {
  1160. RtlFillMemory((BYTE *) &soFake,sizeof(SURFOBJ),0);
  1161. soFake.dhpdev = dco.dhpdev();
  1162. soFake.hdev = dco.hdev();
  1163. soFake.iType = (USHORT)STYPE_DEVICE;
  1164. pso = &soFake;
  1165. }
  1166. // Call the Driver.
  1167. *(ULONG *)pvOut = PPFNDRV(pdo,QueryDeviceSupport)
  1168. (pso,
  1169. pxlo,
  1170. (XFORMOBJ *) NULL,
  1171. (nEscape == CHECKJPEGFORMAT)
  1172. ? QDS_CHECKJPEGFORMAT
  1173. : QDS_CHECKPNGFORMAT,
  1174. (ULONG) cjIn,
  1175. pvIn,
  1176. (ULONG) cjOut,
  1177. pvOut) ? 1 : 0;
  1178. iRet = 1;
  1179. }
  1180. }
  1181. else
  1182. {
  1183. WARNING("ExtEscape(CHECKJPEGFORMAT/CHECKPNGFORMAT): "
  1184. "invalid output buffer\n");
  1185. iRet = -1; // error
  1186. }
  1187. }
  1188. return iRet;
  1189. }
  1190. /******************************Public*Routine******************************\
  1191. * GreExtEscape *
  1192. * *
  1193. * GreExtEscape() allows applications to access facilities of a particular *
  1194. * device that are not directly available through GDI. GreExtEscape calls *
  1195. * made by an application are translated and sent to the device driver. *
  1196. * *
  1197. * Returns *
  1198. * *
  1199. * The return value specifies the outcome of the function. It is *
  1200. * positive if the function is successful except for the *
  1201. * QUERYESCSUPPORT escape, which only checks for implementation. *
  1202. * The return value is zero if the escape is not implemented. *
  1203. * A negative value indicates an error. *
  1204. * The following list shows common error values: *
  1205. * *
  1206. * *
  1207. * Value Meaning *
  1208. * *
  1209. * SP_ERROR General error. *
  1210. * *
  1211. * SP_OUTOFDISK Not enough disk space is currently *
  1212. * available for spooling, and no more *
  1213. * space will become available. *
  1214. * *
  1215. * *
  1216. * SP_OUTOFMEMORY Not enough memory is available for *
  1217. * spooling. *
  1218. * *
  1219. * *
  1220. * SP_USERABORT User terminated the job through the *
  1221. * Print Manager. *
  1222. * *
  1223. * *
  1224. * COMMENTS *
  1225. * *
  1226. * [1] I assume that if we pass to the driver an Escape number that *
  1227. * it does not support, the driver will handle it gracefully. *
  1228. * No checks are done in the Engine. *
  1229. * [koo 02/13/91]. *
  1230. * [2] The cast on pso may seem redundant. However if you *
  1231. * try it without the (PSURFOBJ) cast, you will find *
  1232. * that cFront objects. The reason for this is beyond *
  1233. * my understanding of C++. *
  1234. * *
  1235. * History: *
  1236. * Fri 07-May-1993 14:58:39 -by- Charles Whitmer [chuckwh] *
  1237. * Added the font management escapes. Made it copy the ATTRCACHE. *
  1238. * *
  1239. * Fri 03-Apr-1992 Wendy Wu [wendywu] *
  1240. * Old escapes are now mapped to GDI functions on the client side. *
  1241. * *
  1242. * Fri 14-Feb-1992 Dave Snipp *
  1243. * Added output buffer size. This is calculated on the client and passed to *
  1244. * us in the message *
  1245. * *
  1246. * Wed 13-Feb-1991 09:17:51 by Kirk Olynyk [kirko] *
  1247. * Wrote it. *
  1248. \**************************************************************************/
  1249. int APIENTRY GreExtEscape(
  1250. HDC hDC, // Identifies the device context.
  1251. int iEscape, // Specifies the escape function to be performed.
  1252. int cjIn, // Number of bytes of data pointed to by pvIn.
  1253. LPSTR pvIn, // Points to the input data.
  1254. int cjOut, // Number of bytes of data pointed to by pvOut.
  1255. LPSTR pvOut // Points to the structure to receive output.
  1256. )
  1257. {
  1258. // Locate the surface.
  1259. DCOBJ dco(hDC);
  1260. if (!dco.bValid())
  1261. return(0);
  1262. // PDEVs that have been marked by USER for deletion cannot have escapes
  1263. // going down to them.
  1264. PDEVOBJ pdo(dco.hdev());
  1265. if (pdo.bDeleted())
  1266. return(0);
  1267. #if TEXTURE_DEMO
  1268. if (iEscape == 0x031898)
  1269. {
  1270. return(TexTexture(pvIn, cjIn));
  1271. }
  1272. if ((cjIn >= 4) && (pvIn != NULL) && (iEscape == 0x031899))
  1273. {
  1274. return((int) hdcTexture(*(ULONG*) pvIn));
  1275. }
  1276. #endif
  1277. // We are responsible for not faulting on any call that we handle.
  1278. // (As are all drivers below us!) Since we handle QUERYESCSUPPORT, we'd
  1279. // better verify the length. [chuckwh]
  1280. ////////////////////////////////////////////////////////////////////////
  1281. // NOTE: If you add more private escape routines, you MUST acquire the
  1282. // DEVLOCK before calling the driver's DrvEscape routine, to allow
  1283. // for dynamic mode changing.
  1284. // First, get the driver capable override info
  1285. DWORD dwOverride = pdo.dwDriverCapableOverride();
  1286. if ((iEscape == QUERYESCSUPPORT) && (((ULONG)cjIn) < 4))
  1287. {
  1288. return(0);
  1289. }
  1290. else if ( (iEscape == QUERYESCSUPPORT)
  1291. &&( (*(ULONG*)pvIn == OPENGL_GETINFO)
  1292. ||(*(ULONG*)pvIn == OPENGL_CMD)
  1293. ||(*(ULONG*)pvIn == MCDFUNCS) )
  1294. &&(dwOverride & DRIVER_NOT_CAPABLE_OPENGL) )
  1295. {
  1296. return (0);
  1297. }
  1298. else if ( (iEscape == OPENGL_CMD) || (iEscape == OPENGL_GETINFO) )
  1299. {
  1300. // If the driver is not capable of doing OpenGL, just return
  1301. if ( (dwOverride & DRIVER_NOT_CAPABLE_OPENGL)
  1302. || (dco.dctp() != DCTYPE_DIRECT) )
  1303. return 0;
  1304. return iOpenGLExtEscape(dco, iEscape, cjIn, pvIn, cjOut, pvOut);
  1305. }
  1306. else if (iEscape == MCDFUNCS)
  1307. {
  1308. // Don't allow the MCD to be started up on device bitmaps.
  1309. // If the driver is not capable of doing OpenGL, just return
  1310. if ( (dwOverride & DRIVER_NOT_CAPABLE_OPENGL)
  1311. || (dco.dctp() != DCTYPE_DIRECT) )
  1312. return 0;
  1313. DWORD inBuffer[((sizeof(MCDESC_HEADER) +
  1314. sizeof(MCDESC_HEADER_NTPRIVATE)) /
  1315. sizeof(DWORD))];
  1316. HANDLE hLockSurfaces[MCDESC_MAX_LOCK_SURFACES];
  1317. HDC hdcExtraWndobj[MCDESC_MAX_EXTRA_WNDOBJ];
  1318. MCDESC_HEADER *pmeh = (MCDESC_HEADER *)inBuffer;
  1319. MCDESC_HEADER_NTPRIVATE *pmehPriv;
  1320. BYTE *pbCmd;
  1321. // MCD escape protocol involves an
  1322. // MCDESC_HEADER + MCDESC_HEADER_NTPRIVATE structure sent via
  1323. // the escape.
  1324. //
  1325. // If there is shared memory, then the entire command is described
  1326. // in the MCDESC_HEADER. Otherwise, the pBuffer field of the
  1327. // MCDESC_HEADER_NTPRIVATE
  1328. // structure is set to point to the command structure.
  1329. if (cjIn >= sizeof(MCDESC_HEADER))
  1330. {
  1331. RtlCopyMemory(pmeh,pvIn,sizeof(*pmeh));
  1332. pbCmd = (BYTE *)pvIn+sizeof(MCDESC_HEADER);
  1333. cjIn -= sizeof(MCDESC_HEADER);
  1334. }
  1335. else
  1336. {
  1337. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  1338. return 0;
  1339. }
  1340. pmehPriv = (MCDESC_HEADER_NTPRIVATE *)(pmeh+1);
  1341. // If MCDESC_FL_LOCK_SURFACES is set, the cLockSurfaces field indicates
  1342. // the number of trailing surface handles for locking
  1343. if (pmeh->flags & MCDESC_FL_LOCK_SURFACES)
  1344. {
  1345. int cb;
  1346. if ((pmeh->cLockSurfaces <= MCDESC_MAX_LOCK_SURFACES) &&
  1347. ((cb = sizeof(HANDLE)*pmeh->cLockSurfaces) <= cjIn))
  1348. {
  1349. RtlCopyMemory(hLockSurfaces, pbCmd, cb);
  1350. pmehPriv->pLockSurfaces = hLockSurfaces;
  1351. pbCmd += cb;
  1352. cjIn -= cb;
  1353. }
  1354. else
  1355. {
  1356. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  1357. return 0;
  1358. }
  1359. }
  1360. else
  1361. {
  1362. pmehPriv->pLockSurfaces = NULL;
  1363. }
  1364. // If MCDESC_FL_EXTRA_WNDOBJ is set, the cExtraWndobj field indicates
  1365. // the number of trailing HDCs to find WNDOBJs for.
  1366. if (pmeh->flags & MCDESC_FL_EXTRA_WNDOBJ)
  1367. {
  1368. int cb;
  1369. if ((pmeh->cExtraWndobj <= MCDESC_MAX_EXTRA_WNDOBJ) &&
  1370. ((cb = sizeof(HDC)*pmeh->cExtraWndobj) <= cjIn))
  1371. {
  1372. RtlCopyMemory(hdcExtraWndobj, pbCmd, cb);
  1373. pmehPriv->pExtraWndobj = hdcExtraWndobj;
  1374. pbCmd += cb;
  1375. cjIn -= cb;
  1376. }
  1377. else
  1378. {
  1379. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  1380. return 0;
  1381. }
  1382. }
  1383. else
  1384. {
  1385. pmehPriv->pExtraWndobj = NULL;
  1386. }
  1387. if (!pmeh->hSharedMem)
  1388. {
  1389. pmehPriv->pBuffer = (VOID *)pbCmd;
  1390. pmehPriv->bufferSize = cjIn;
  1391. }
  1392. else
  1393. {
  1394. pmehPriv->pBuffer = (VOID *)NULL;
  1395. pmehPriv->bufferSize = 0;
  1396. }
  1397. if (pmeh->flags & MCDESC_FL_CREATE_CONTEXT)
  1398. {
  1399. return iMcdSetupExtEscape(dco, iEscape, sizeof(inBuffer), inBuffer,
  1400. cjOut, pvOut);
  1401. }
  1402. else
  1403. {
  1404. return iMcdExtEscape(dco, iEscape, sizeof(inBuffer), inBuffer,
  1405. cjOut, pvOut);
  1406. }
  1407. }
  1408. else if (iEscape == WNDOBJ_SETUP)
  1409. {
  1410. if (dco.dctp() != DCTYPE_DIRECT)
  1411. return 0;
  1412. return iWndObjSetupExtEscape(dco, iEscape, cjIn, pvIn, cjOut, pvOut);
  1413. }
  1414. else if (iEscape == DCICOMMAND)
  1415. {
  1416. return (0);
  1417. }
  1418. // Acquire the DEVLOCK to protect against dynamic mode changes. We still
  1419. // let escapes down if we're in full-screen mode, though.
  1420. DEVLOCKOBJ dlo;
  1421. dlo.vLockNoDrawing(dco);
  1422. // Redirection DCs should not support escapes. This is actually a tricky
  1423. // case because the dc is DCTYPE_DIRECT but the redirection surface may
  1424. // not be owned by the driver (and in fact the driver may crash if we
  1425. // pass it a redirection surface). So it's best to quit here.
  1426. if (dco.pdc->bRedirection())
  1427. {
  1428. return(0);
  1429. }
  1430. // Make sure that a driver can't be called with an escape on a DIB bitmap
  1431. // that it obviously won't own.
  1432. if (dco.dctp() != DCTYPE_DIRECT)
  1433. {
  1434. if (!dco.bPrinter())
  1435. {
  1436. if ((dco.pSurface() == NULL) ||
  1437. (dco.pSurface()->iType() != STYPE_DEVBITMAP))
  1438. {
  1439. return(0);
  1440. }
  1441. }
  1442. else
  1443. {
  1444. // Have to be careful with the printer case since there is no
  1445. // surface if metafile or escape called before StartDoc. Only
  1446. // reject if surface exists and does not match device.
  1447. if ((dco.pSurface() != NULL) &&
  1448. (dco.pSurface()->dhpdev() != pdo.dhpdev())
  1449. )
  1450. {
  1451. return(0);
  1452. }
  1453. }
  1454. }
  1455. DRAWPATRECTP PatternRect;
  1456. EXFORMOBJ exo;
  1457. // Adjust DRAWPATTERNRECT for banding
  1458. if (iEscape == DRAWPATTERNRECT)
  1459. {
  1460. if (pdo.flGraphicsCaps() & GCAPS_NUP)
  1461. {
  1462. exo.vQuickInit(dco, WORLD_TO_DEVICE);
  1463. //
  1464. // If app passes us the wrong size return failure.
  1465. // Note: wow always fix up 16bit DRAWPATRECT to 32bit
  1466. // version.
  1467. //
  1468. if (cjIn != sizeof(DRAWPATRECT))
  1469. {
  1470. WARNING(" we are passed in a bad cjIn for DRAWPATTERNRECT\n");
  1471. return (0);
  1472. }
  1473. else
  1474. {
  1475. PatternRect.DrawPatRect = *(DRAWPATRECT *) pvIn;
  1476. PatternRect.pXformObj = (XFORMOBJ *) (PVOID) &exo;
  1477. pvIn = (LPSTR)&PatternRect;
  1478. cjIn = sizeof(DRAWPATRECTP);
  1479. }
  1480. }
  1481. if (dco.pSurface() && (dco.pSurface())->bBanding())
  1482. {
  1483. if ((cjIn == sizeof(DRAWPATRECT)) || (pdo.flGraphicsCaps() & GCAPS_NUP))
  1484. {
  1485. DRAWPATRECT *pPatternRect = (DRAWPATRECT *) pvIn;
  1486. // convert position to band coords from page coords.
  1487. pPatternRect->ptPosition.x -= (dco.ptlPrintBandPos().x);
  1488. pPatternRect->ptPosition.y -= (dco.ptlPrintBandPos().y);
  1489. }
  1490. else
  1491. {
  1492. WARNING("GreExtEscape():DRAWPATRECT - cjIn != sizeof(DRAWPATRECT)\n");
  1493. // we don't fail, let driver effort for this.
  1494. }
  1495. }
  1496. }
  1497. // Pass the calls that require a FONTOBJ off to DoFontManagement.
  1498. if ( ((iEscape >= 0x100) && (iEscape < 0x3FF)) ||
  1499. ((iEscape == QUERYESCSUPPORT) &&
  1500. ((*(ULONG*)pvIn >= 0x100) && (*(ULONG*)pvIn < 0x3FF))) )
  1501. {
  1502. return ( (int) DoFontManagement(dco,
  1503. iEscape,
  1504. (ULONG) cjIn,
  1505. (PVOID) pvIn,
  1506. (ULONG) cjOut,
  1507. (PVOID) pvOut));
  1508. }
  1509. // Handle device compressed image passthrough support (JPEG or PNG images)
  1510. if ( (iEscape == CHECKJPEGFORMAT) || (iEscape == CHECKPNGFORMAT) ||
  1511. ((iEscape == QUERYESCSUPPORT) &&
  1512. ((*(ULONG*)pvIn == CHECKJPEGFORMAT) ||
  1513. (*(ULONG*)pvIn == CHECKPNGFORMAT ))
  1514. )
  1515. )
  1516. {
  1517. return ( iCheckPassthroughImage(dco,
  1518. pdo,
  1519. iEscape,
  1520. (ULONG) cjIn,
  1521. (PVOID) pvIn,
  1522. (ULONG) cjOut,
  1523. (PVOID) pvOut));
  1524. }
  1525. // Inc the target surface for output calls with a valid surface.
  1526. if (dco.bValidSurf() && (pvOut == (LPSTR) NULL))
  1527. {
  1528. INC_SURF_UNIQ(dco.pSurface());
  1529. }
  1530. SURFOBJ *pso = dco.pSurface()->pSurfobj();
  1531. // Handle OpenGL - QUERYSUPPORT escape with multimon system
  1532. #ifdef OPENGL_MM
  1533. if (pdo.bMetaDriver())
  1534. {
  1535. if ( (iEscape == QUERYESCSUPPORT) &&
  1536. ((*(ULONG *) pvIn == OPENGL_GETINFO) ||
  1537. (*(ULONG *) pvIn == OPENGL_CMD) ||
  1538. (*(ULONG *) pvIn == MCDFUNCS)
  1539. )
  1540. )
  1541. {
  1542. // We need to change the meta-PDEV into a hardware specific PDEV
  1543. HDEV hdevDevice = hdevFindDeviceHdev(
  1544. dco.hdev(),
  1545. (RECTL)dco.erclWindow(),
  1546. NULL);
  1547. if (hdevDevice)
  1548. {
  1549. // If the surface is pdev's primary surface, we will replace it with
  1550. // new device pdev's surface.
  1551. if (pdo.bPrimary(dco.pSurface()))
  1552. {
  1553. PDEVOBJ pdoDevice(hdevDevice);
  1554. pso = pdoDevice.pSurface()->pSurfobj();
  1555. }
  1556. // replace meta pdevobj with device specific hdev.
  1557. pdo.vInit(hdevDevice);
  1558. }
  1559. }
  1560. }
  1561. #endif // OPENGL_MM
  1562. // Locate the driver entry point.
  1563. if (!PPFNDRV(pdo, Escape))
  1564. return(0);
  1565. // There is no surface in metafile DCs. In addition,
  1566. // it is unfortunate that apps call some printing escapes before
  1567. // doing a StartDoc, so there is no real surface in the DC.
  1568. // We fake up a rather poor one here if we need it. The device
  1569. // driver may only dereference the dhpdev from this!
  1570. SURFOBJ soFake;
  1571. if (pso == (SURFOBJ *) NULL)
  1572. {
  1573. RtlFillMemory((BYTE *) &soFake,sizeof(SURFOBJ),0);
  1574. soFake.dhpdev = dco.dhpdev();
  1575. soFake.hdev = dco.hdev();
  1576. soFake.iType = (USHORT)STYPE_DEVICE;
  1577. pso = &soFake;
  1578. // Special case SETCOPYCOUNT if we havn't done a startdoc yet
  1579. if ((iEscape == SETCOPYCOUNT) && (cjIn >= sizeof(USHORT)))
  1580. {
  1581. // let's remember the call in the dc and wait for start doc
  1582. // since if there is no hardware support, we can simulate it
  1583. // when EMF spooling case.
  1584. dco.ulCopyCount((ULONG)(*(PUSHORT)pvIn));
  1585. // check if the driver supports it and let him fill in the actual
  1586. // size in the return buffer.
  1587. pdo.Escape(pso,iEscape,cjIn,pvIn,cjOut,pvOut);
  1588. // always behaves as success, since EMF spooling can simulate it.
  1589. return(1);
  1590. }
  1591. // Special case post scripts EPS_PRINTING if we havn't done a startdoc yet
  1592. if ((iEscape == EPSPRINTING) && (cjIn >= sizeof(USHORT)))
  1593. {
  1594. // yes, lets remember the call in the dc and wait for start doc
  1595. if ((BOOL)*(PUSHORT)pvIn)
  1596. dco.vSetEpsPrintingEscape();
  1597. else
  1598. dco.vClearEpsPrintingEscape();
  1599. return(1);
  1600. }
  1601. }
  1602. // Call the Driver.
  1603. int iRes;
  1604. iRes = (int) pdo.Escape(pso,
  1605. (ULONG) iEscape,
  1606. (ULONG) cjIn,
  1607. pvIn,
  1608. (ULONG) cjOut,
  1609. pvOut);
  1610. return(iRes);
  1611. }
  1612. /******************************Public*Routine******************************\
  1613. * GreDrawEscape
  1614. *
  1615. * History:
  1616. * 07-Apr-1992 -by- Wendy Wu [wendywu]
  1617. * Wrote it.
  1618. \**************************************************************************/
  1619. int APIENTRY GreDrawEscape(
  1620. HDC hdc, // Identifies the device context.
  1621. int nEscape, // Specifies the escape function to be performed.
  1622. int cjIn, // Number of bytes of data pointed to by lpIn
  1623. PSTR pstrIn // Points to the input structure required
  1624. )
  1625. {
  1626. LONG lRet = 0;
  1627. DCOBJ dco(hdc);
  1628. //
  1629. // The DC must be valid and also the surface must be valid in order
  1630. // for the driver to be called
  1631. //
  1632. if ((dco.bValid()) && (dco.bHasSurface()) && (!dco.pdc->bDIBSection()))
  1633. {
  1634. //
  1635. // We are responsible for not faulting on any call that we handle.
  1636. // (As are all drivers below us!) Since we handle QUERYESCSUPPORT, we'd
  1637. // better verify the length.
  1638. //
  1639. if ((nEscape == QUERYESCSUPPORT) && (((ULONG) cjIn) < 4))
  1640. {
  1641. return(0);
  1642. }
  1643. //
  1644. // see if the device supports it
  1645. //
  1646. PDEVOBJ pdo(dco.hdev());
  1647. //
  1648. // Lock the surface and the Rao region, ensure VisRgn up to date.
  1649. //
  1650. DEVLOCKOBJ dlo(dco);
  1651. PFN_DrvDrawEscape pfnDrvDrawEscape = PPFNDRV(pdo, DrawEscape);
  1652. if (pfnDrvDrawEscape != NULL)
  1653. {
  1654. //
  1655. // if it is query escape support, get out early
  1656. //
  1657. if (nEscape == QUERYESCSUPPORT)
  1658. {
  1659. lRet = (int)(*pfnDrvDrawEscape)(dco.pSurface()->pSurfobj(),
  1660. (ULONG)nEscape,
  1661. (CLIPOBJ *)NULL,
  1662. (RECTL *)NULL,
  1663. (ULONG)cjIn,
  1664. (PVOID)pstrIn);
  1665. }
  1666. else
  1667. {
  1668. if (!dlo.bValid())
  1669. {
  1670. lRet = (int)dco.bFullScreen();
  1671. }
  1672. else
  1673. {
  1674. ERECTL ercl = dco.erclWindow();
  1675. ECLIPOBJ co(dco.prgnEffRao(), ercl);
  1676. if (co.erclExclude().bEmpty())
  1677. {
  1678. lRet = (int)TRUE;
  1679. }
  1680. else
  1681. {
  1682. //
  1683. // Exclude any sprites.
  1684. //
  1685. DEVEXCLUDERECT dxoRect(dco.hdev(), &ercl);
  1686. //
  1687. // Inc the target surface uniqueness
  1688. //
  1689. INC_SURF_UNIQ(dco.pSurface());
  1690. lRet = (int)(*pfnDrvDrawEscape)(dco.pSurface()->pSurfobj(),
  1691. (ULONG)nEscape,
  1692. (CLIPOBJ *)&co,
  1693. (RECTL *)&ercl,
  1694. (ULONG)cjIn,
  1695. (PVOID)pstrIn);
  1696. }
  1697. }
  1698. }
  1699. }
  1700. }
  1701. return(lRet);
  1702. }
  1703. /******************************Public*Routine******************************\
  1704. * int APIENTRY GreStartDoc(HDC hdc, DOCINFOW *pDocInfo,BOOL *pbBanding)
  1705. *
  1706. * Arguments:
  1707. *
  1708. * hdc - handle to device context
  1709. * pdi - DOCINFO of output names
  1710. * pbBanding - return banding flag
  1711. *
  1712. * Return Value:
  1713. *
  1714. * if successful return job identifier, else SP_ERROR
  1715. *
  1716. * History:
  1717. * Wed 08-Apr-1992 -by- Patrick Haluptzok [patrickh]
  1718. * lazy surface enable, journal support, remove unnecesary validation.
  1719. *
  1720. * Mon 01-Apr-1991 13:50:23 by Kirk Olynyk [kirko]
  1721. * Wrote it.
  1722. \**************************************************************************/
  1723. int APIENTRY GreStartDocInternal(
  1724. HDC hdc,
  1725. DOCINFOW *pDocInfo,
  1726. BOOL *pbBanding,
  1727. INT iDocJob
  1728. )
  1729. {
  1730. int iRet = 0;
  1731. int iJob;
  1732. DCOBJ dco(hdc);
  1733. if (dco.bValid())
  1734. {
  1735. PDEVOBJ po(dco.hdev());
  1736. //
  1737. // Check that this is a printer surface.
  1738. //
  1739. if ((!po.bDisplayPDEV()) &&
  1740. (po.hSpooler()) &&
  1741. (dco.dctp() == DCTYPE_DIRECT) &&
  1742. (!dco.bHasSurface()))
  1743. {
  1744. // We now try and open the printer up in journal mode. If we fail
  1745. // then we try and open it up in raw mode. If that fails we fail call.
  1746. if (!po.bUMPD())
  1747. {
  1748. #define MAX_DOCINFO_DATA_TYPE 80
  1749. DOC_INFO_1W DocInfo;
  1750. WCHAR awchDatatype[MAX_DOCINFO_DATA_TYPE];
  1751. DocInfo.pDocName = (LPWSTR)pDocInfo->lpszDocName;
  1752. DocInfo.pOutputFile = (LPWSTR)pDocInfo->lpszOutput;
  1753. DocInfo.pDatatype = NULL;
  1754. // see if the driver wants to define its own data type. If it does,
  1755. // first fill the buffer in with the type requested by the app
  1756. if (PPFNVALID(po, QuerySpoolType))
  1757. {
  1758. awchDatatype[0] = 0;
  1759. // did the app specify a data type and will it fit in our buffer
  1760. if (pDocInfo->lpszDatatype)
  1761. {
  1762. int cjStr = (wcslen(pDocInfo->lpszDatatype) + 1) * sizeof(WCHAR);
  1763. if (cjStr < (MAX_DOCINFO_DATA_TYPE * sizeof(WCHAR)))
  1764. {
  1765. RtlCopyMemory((PVOID)awchDatatype,(PVOID)pDocInfo->lpszDatatype,cjStr);
  1766. }
  1767. }
  1768. if ((*PPFNDRV(po, QuerySpoolType))(po.dhpdev(), awchDatatype))
  1769. {
  1770. DocInfo.pDatatype = awchDatatype;
  1771. }
  1772. }
  1773. // open up the document
  1774. iJob = (BOOL)StartDocPrinterW(po.hSpooler(), 1, (LPBYTE)&DocInfo);
  1775. if (iJob <= 0)
  1776. {
  1777. WARNING("ERROR GreStartDoc failed StartDocPrinter Raw Mode\n");
  1778. return(iJob);
  1779. }
  1780. }
  1781. else
  1782. {
  1783. // if it is UMPD, StartDocPrinter has been called in user mode already
  1784. iJob = iDocJob;
  1785. }
  1786. // Lazy surface creation happens now.
  1787. if (po.bMakeSurface())
  1788. {
  1789. *pbBanding = (po.pSurface())->bBanding();
  1790. // Put the surface into the DC.
  1791. dco.pdc->pSurface(po.pSurface());
  1792. if ( *pbBanding )
  1793. {
  1794. // if banding set Clip rectangle to size of band
  1795. dco.pdc->sizl((po.pSurface())->sizl());
  1796. dco.pdc->bSetDefaultRegion();
  1797. }
  1798. BOOL bSucceed = FALSE;
  1799. PFN_DrvStartDoc pfnDrvStartDoc = PPFNDRV(po, StartDoc);
  1800. bSucceed = (*pfnDrvStartDoc)(po.pSurface()->pSurfobj(),
  1801. (PWSTR)pDocInfo->lpszDocName,
  1802. iJob);
  1803. // now, if a SETCOPYCOUNT escape has come through, send it down
  1804. if (dco.ulCopyCount() != (ULONG)-1)
  1805. {
  1806. ULONG ulCopyCount = dco.ulCopyCount();
  1807. GreExtEscape(hdc,SETCOPYCOUNT,sizeof(DWORD),
  1808. (LPSTR)&ulCopyCount,0,NULL);
  1809. dco.ulCopyCount((ULONG)-1);
  1810. }
  1811. // now, if a EPSPRINTING escape has come through, send it down
  1812. if (dco.bEpsPrintingEscape())
  1813. {
  1814. SHORT b = 1;
  1815. GreExtEscape(hdc,EPSPRINTING,sizeof(b),(LPSTR)&b,0,NULL);
  1816. dco.vClearEpsPrintingEscape();
  1817. }
  1818. if (bSucceed)
  1819. {
  1820. iRet = iJob;
  1821. dco.vSetSaveDepthStartDoc();
  1822. }
  1823. }
  1824. }
  1825. if (!iRet)
  1826. {
  1827. AbortPrinter(po.hSpooler());
  1828. }
  1829. }
  1830. return iRet;
  1831. }
  1832. /****************************************************************************
  1833. * NtGdiSetLinkedUFIs
  1834. *
  1835. * History:
  1836. * 12/16/1996 by Gerrit van Wingerden [gerritv]
  1837. * Wrote it.
  1838. *****************************************************************************/
  1839. #define QUICK_LINKS 4
  1840. extern "C" BOOL NtGdiSetLinkedUFIs(
  1841. HDC hdc,
  1842. PUNIVERSAL_FONT_ID pufiLinks,
  1843. ULONG uNumUFIs
  1844. )
  1845. {
  1846. BOOL bRet = TRUE;
  1847. UNIVERSAL_FONT_ID pufiQuickLinks[QUICK_LINKS];
  1848. PUNIVERSAL_FONT_ID pufi = NULL;
  1849. if (!pufiLinks && uNumUFIs)
  1850. return FALSE;
  1851. if (uNumUFIs > QUICK_LINKS)
  1852. {
  1853. if (!BALLOC_OVERFLOW1(uNumUFIs,UNIVERSAL_FONT_ID))
  1854. {
  1855. pufi = (PUNIVERSAL_FONT_ID)
  1856. PALLOCNOZ(uNumUFIs * sizeof(UNIVERSAL_FONT_ID),'difG');
  1857. }
  1858. if (pufi == NULL)
  1859. {
  1860. WARNING("NtGdiSetLinkedUFIs: out of memory\n");
  1861. return(FALSE);
  1862. }
  1863. }
  1864. else
  1865. {
  1866. pufi = pufiQuickLinks;
  1867. }
  1868. __try
  1869. {
  1870. if (pufiLinks)
  1871. {
  1872. ProbeForRead(pufiLinks,
  1873. sizeof(UNIVERSAL_FONT_ID)*uNumUFIs,
  1874. sizeof(DWORD) );
  1875. RtlCopyMemory(pufi,pufiLinks,
  1876. sizeof(UNIVERSAL_FONT_ID)*uNumUFIs);
  1877. }
  1878. }
  1879. __except(EXCEPTION_EXECUTE_HANDLER)
  1880. {
  1881. WARNINGX(106);
  1882. bRet = FALSE;
  1883. }
  1884. if (bRet)
  1885. {
  1886. XDCOBJ dco(hdc);
  1887. if (dco.bValid())
  1888. {
  1889. bRet = dco.bSetLinkedUFIs(pufi, uNumUFIs);
  1890. dco.vUnlockFast();
  1891. }
  1892. }
  1893. if (pufi != pufiQuickLinks)
  1894. {
  1895. VFREEMEM(pufi);
  1896. }
  1897. return(bRet);
  1898. }
  1899. int APIENTRY NtGdiStartDoc(
  1900. HDC hdc,
  1901. DOCINFOW *pdi,
  1902. BOOL *pbBanding,
  1903. INT iJob
  1904. )
  1905. {
  1906. int iRet = 0;
  1907. BOOL bkmBanding;
  1908. DOCINFOW kmDocInfo;
  1909. ULONG cjStr;
  1910. BOOL bStatus = TRUE;
  1911. kmDocInfo.cbSize = 0;
  1912. kmDocInfo.lpszDocName = NULL;
  1913. kmDocInfo.lpszOutput = NULL;
  1914. kmDocInfo.lpszDatatype = NULL;
  1915. //DbgPrint ("NtGdiStartDoc\n");
  1916. if (pdi != (DOCINFOW *)NULL)
  1917. {
  1918. __try
  1919. {
  1920. LPCWSTR lpszDocName;
  1921. LPCWSTR lpszOutput;
  1922. LPCWSTR lpszDatatype;
  1923. ProbeForRead(pdi,sizeof(DOCINFOW),sizeof(ULONG));
  1924. kmDocInfo.cbSize = pdi->cbSize;
  1925. lpszDocName = pdi->lpszDocName;
  1926. lpszOutput = pdi->lpszOutput;
  1927. lpszDatatype = pdi->lpszDatatype;
  1928. if (lpszDocName != NULL)
  1929. {
  1930. cjStr = (wcslensafe(lpszDocName) + 1) * sizeof(WCHAR);
  1931. kmDocInfo.lpszDocName = (LPWSTR)PALLOCNOZ(cjStr,'pmtG');
  1932. if (kmDocInfo.lpszDocName == NULL)
  1933. {
  1934. bStatus = FALSE;
  1935. }
  1936. else
  1937. {
  1938. ProbeForRead(lpszDocName,cjStr,sizeof(WCHAR));
  1939. RtlCopyMemory((PVOID)kmDocInfo.lpszDocName,(PVOID)lpszDocName,cjStr);
  1940. // Guarantee NULL termination of string.
  1941. ((WCHAR *)kmDocInfo.lpszDocName)[(cjStr/sizeof(WCHAR)) - 1] = L'\0';
  1942. }
  1943. }
  1944. if (lpszOutput != NULL)
  1945. {
  1946. cjStr = (wcslensafe(lpszOutput) + 1) * sizeof(WCHAR);
  1947. kmDocInfo.lpszOutput = (LPWSTR)PALLOCNOZ(cjStr,'pmtG');
  1948. if (kmDocInfo.lpszOutput == NULL)
  1949. {
  1950. bStatus = FALSE;
  1951. }
  1952. else
  1953. {
  1954. ProbeForRead(lpszOutput,cjStr,sizeof(WCHAR));
  1955. RtlCopyMemory((PVOID)kmDocInfo.lpszOutput,(PVOID)lpszOutput,cjStr);
  1956. // Guarantee NULL termination of string.
  1957. ((WCHAR *)kmDocInfo.lpszOutput)[(cjStr/sizeof(WCHAR)) - 1] = L'\0';
  1958. }
  1959. }
  1960. // does it contain the new Win95 fields
  1961. if ((kmDocInfo.cbSize >= sizeof(DOCINFOW)) && (lpszDatatype != NULL))
  1962. {
  1963. __try
  1964. {
  1965. cjStr = (wcslensafe(lpszDatatype) + 1) * sizeof(WCHAR);
  1966. ProbeForRead(lpszDatatype,cjStr,sizeof(WCHAR));
  1967. kmDocInfo.lpszDatatype = (LPWSTR)PALLOCNOZ(cjStr,'pmtG');
  1968. if (kmDocInfo.lpszDatatype == NULL)
  1969. {
  1970. bStatus = FALSE;
  1971. }
  1972. else
  1973. {
  1974. RtlCopyMemory((PVOID)kmDocInfo.lpszDatatype,(PVOID)lpszDatatype,cjStr);
  1975. // Guarantee NULL termination of string.
  1976. ((WCHAR *)kmDocInfo.lpszDatatype)[(cjStr/sizeof(WCHAR)) - 1] = L'\0';
  1977. }
  1978. }
  1979. __except(EXCEPTION_EXECUTE_HANDLER)
  1980. {
  1981. // apps may have forgotten to initialize this. Don't want to fail
  1982. if (kmDocInfo.lpszDatatype != NULL)
  1983. {
  1984. VFREEMEM(kmDocInfo.lpszDatatype);
  1985. kmDocInfo.lpszDatatype = NULL;
  1986. }
  1987. }
  1988. }
  1989. }
  1990. __except(EXCEPTION_EXECUTE_HANDLER)
  1991. {
  1992. // SetLastError(GetExceptionCode());
  1993. bStatus = FALSE;
  1994. }
  1995. }
  1996. if (bStatus)
  1997. {
  1998. iRet = GreStartDocInternal(hdc,&kmDocInfo,&bkmBanding, iJob);
  1999. if (iRet != 0)
  2000. {
  2001. __try
  2002. {
  2003. ProbeForWrite(pbBanding,sizeof(BOOL),sizeof(BOOL));
  2004. *pbBanding = bkmBanding;
  2005. }
  2006. __except(EXCEPTION_EXECUTE_HANDLER)
  2007. {
  2008. // SetLastError(GetExceptionCode());
  2009. iRet = 0;
  2010. }
  2011. }
  2012. }
  2013. if (kmDocInfo.lpszDocName != NULL)
  2014. {
  2015. VFREEMEM(kmDocInfo.lpszDocName);
  2016. }
  2017. if (kmDocInfo.lpszOutput != NULL)
  2018. {
  2019. VFREEMEM(kmDocInfo.lpszOutput);
  2020. }
  2021. if (kmDocInfo.lpszDatatype != NULL)
  2022. {
  2023. VFREEMEM(kmDocInfo.lpszDatatype);
  2024. }
  2025. return(iRet);
  2026. }
  2027. /******************************Public*Routine******************************\
  2028. * bEndDocInternal
  2029. *
  2030. * History:
  2031. * Tue 22-Sep-1992 -by- Wendy Wu [wendywu]
  2032. * Made it a common routine for EndDoc and AbortDoc.
  2033. *
  2034. * Sun 21-Jun-1992 -by- Patrick Haluptzok [patrickh]
  2035. * surface disable, check for display dc.
  2036. *
  2037. * Mon 01-Apr-1991 13:50:23 by Kirk Olynyk [kirko]
  2038. * Wrote it.
  2039. \**************************************************************************/
  2040. BOOL bEndDocInternal(HDC hdc, FLONG fl)
  2041. {
  2042. BOOL bSucceed;
  2043. BOOL bEndPage;
  2044. ASSERTGDI(((fl & ~ED_ABORTDOC) == 0), "GreEndDoc: invalid fl\n");
  2045. DCOBJ dco(hdc);
  2046. if (!dco.bValidSurf())
  2047. {
  2048. SAVE_ERROR_CODE(ERROR_CAN_NOT_COMPLETE);
  2049. WARNING("GreEndDoc failed - invalid DC\n");
  2050. return(FALSE);
  2051. }
  2052. // before going any futher, restore the DC to it's original level
  2053. if (dco.lSaveDepth() > dco.lSaveDepthStartDoc())
  2054. GreRestoreDC(hdc,dco.lSaveDepthStartDoc());
  2055. PDEVOBJ po(dco.hdev());
  2056. if (po.bDisplayPDEV() || po.hSpooler() == (HANDLE)0)
  2057. {
  2058. SAVE_ERROR_CODE(ERROR_CAN_NOT_COMPLETE);
  2059. WARNING("GreEndDoc: Display PDEV or not spooling yet\n");
  2060. return(FALSE);
  2061. }
  2062. SURFACE *pSurf = dco.pSurface();
  2063. bEndPage = (*PPFNDRV(po,EndDoc))(pSurf->pSurfobj(), fl);
  2064. if (!po.bUMPD())
  2065. {
  2066. if (fl & ED_ABORTDOC)
  2067. bSucceed = AbortPrinter(po.hSpooler());
  2068. else
  2069. bSucceed = EndDocPrinter(po.hSpooler());
  2070. }
  2071. else
  2072. bSucceed = TRUE;
  2073. // Reset pixel format accelerators.
  2074. dco.ipfdDevMax(-1);
  2075. // Remove the surface from the DC.
  2076. dco.pdc->pSurface((SURFACE *) NULL);
  2077. po.vDisableSurface();
  2078. return(bSucceed && bEndPage);
  2079. }
  2080. /******************************Public*Routine******************************\
  2081. * NtGdiEndDoc()
  2082. *
  2083. \**************************************************************************/
  2084. BOOL APIENTRY NtGdiEndDoc( HDC hdc )
  2085. {
  2086. return(bEndDocInternal(hdc, 0));
  2087. }
  2088. /******************************Public*Routine******************************\
  2089. * NtGdiAbortDoc()
  2090. *
  2091. \**************************************************************************/
  2092. BOOL APIENTRY NtGdiAbortDoc( HDC hdc )
  2093. {
  2094. return(bEndDocInternal(hdc, ED_ABORTDOC));
  2095. }
  2096. /******************************Public*Routine******************************\
  2097. * NtGdiStartPage()
  2098. *
  2099. * Mon 01-Apr-1991 13:50:23 by Kirk Olynyk [kirko]
  2100. * Wrote it.
  2101. \**************************************************************************/
  2102. BOOL APIENTRY NtGdiStartPage( HDC hdc )
  2103. {
  2104. DCOBJ dco(hdc);
  2105. BOOL bReturn = FALSE;
  2106. if (dco.bValidSurf())
  2107. {
  2108. if (dco.bHasSurface())
  2109. {
  2110. PDEVOBJ po(dco.hdev());
  2111. //
  2112. // Must be spooling already
  2113. //
  2114. if (po.hSpooler())
  2115. {
  2116. SURFACE *pSurf = dco.pSurface();
  2117. BOOL bStarted;
  2118. //
  2119. // if it is not a User Mode Printer,
  2120. // Call the spooler before calling the printer.
  2121. //
  2122. if (!po.bUMPD())
  2123. {
  2124. bStarted = StartPagePrinter(po.hSpooler());
  2125. }
  2126. else
  2127. {
  2128. bStarted = TRUE;
  2129. }
  2130. if (bStarted)
  2131. {
  2132. if ((*PPFNDRV(po, StartPage))(pSurf->pSurfobj()))
  2133. {
  2134. //
  2135. // Can't ResetDC in an active page
  2136. //
  2137. dco.fsSet(DC_RESET);
  2138. //
  2139. // Reset band position in page (if we are banding)
  2140. //
  2141. dco.vResetPrintBandPos();
  2142. bReturn = TRUE;
  2143. }
  2144. else
  2145. {
  2146. bEndDocInternal(hdc, ED_ABORTDOC);
  2147. }
  2148. }
  2149. }
  2150. }
  2151. }
  2152. else
  2153. {
  2154. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  2155. }
  2156. return (bReturn);
  2157. }
  2158. /******************************Public*Routine******************************\
  2159. * NtGdiEndPage()
  2160. *
  2161. * Mon 01-Apr-1991 13:50:23 by Kirk Olynyk [kirko]
  2162. * Wrote it.
  2163. \**************************************************************************/
  2164. BOOL APIENTRY NtGdiEndPage( HDC hdc )
  2165. {
  2166. BOOL bRet = FALSE;
  2167. DCOBJ dco(hdc);
  2168. if (dco.bValidSurf())
  2169. {
  2170. if (dco.bHasSurface())
  2171. {
  2172. PDEVOBJ po(dco.hdev());
  2173. // Must be spooling already.
  2174. if (!po.bDisplayPDEV() && po.hSpooler())
  2175. {
  2176. SURFACE *pSurf = dco.pSurface();
  2177. if ((*PPFNDRV(po, SendPage))(pSurf->pSurfobj()))
  2178. {
  2179. BOOL bEndPage;
  2180. if (po.bUMPD())
  2181. {
  2182. //
  2183. // all the spooler calls have been made at the user mode
  2184. // for User Mode Printer Drivers
  2185. //
  2186. bEndPage = TRUE;
  2187. }
  2188. else
  2189. {
  2190. bEndPage = EndPagePrinter(po.hSpooler());
  2191. }
  2192. if (bEndPage)
  2193. {
  2194. //
  2195. // Allow ResetDC to function again.
  2196. //
  2197. dco.fsClr(DC_RESET);
  2198. //
  2199. // Delete the wndobj and reset the pixel format.
  2200. // Since we don't allow pixel format to change once it
  2201. // is set, we need to reset it internally here to allow a
  2202. // different pixel format in the next page. This means
  2203. // that applications must make the OpenGL rendering
  2204. // context not current before ending a page or a document.
  2205. // They also need to set the pixel format explicitly in
  2206. // the next page if they need it.
  2207. //
  2208. EWNDOBJ *pwoDelete = pSurf->pwo();
  2209. if (pwoDelete)
  2210. {
  2211. GreDeleteWnd((PVOID) pwoDelete);
  2212. pSurf->pwo((EWNDOBJ *) NULL);
  2213. }
  2214. //
  2215. // Reset pixel format accelerators.
  2216. //
  2217. dco.ipfdDevMax(-1);
  2218. bRet = TRUE;
  2219. }
  2220. }
  2221. }
  2222. }
  2223. }
  2224. return (bRet);
  2225. }
  2226. /******************************Public*Routine******************************\
  2227. * BOOL APIENTRY GreDoBanding(HDC hdc,BOOL bStart,RECTL *prcl)
  2228. *
  2229. *
  2230. * Tue 20-Dec-1994 14:50:45 by Gerrit van Wingerden
  2231. * Wrote it.
  2232. \**************************************************************************/
  2233. BOOL GreDoBanding( HDC hdc, BOOL bStart, POINTL *pptl, PSIZE pSize )
  2234. {
  2235. BOOL bRet = FALSE;
  2236. DCOBJ dco(hdc);
  2237. if (dco.bValidSurf() && (dco.bHasSurface()))
  2238. {
  2239. PDEVOBJ po(dco.hdev());
  2240. // Must be spooling already.
  2241. if (po.hSpooler())
  2242. {
  2243. SURFACE *pSurf = dco.pSurface();
  2244. if (pSurf->SurfFlags & BANDING_SURFACE)
  2245. {
  2246. BOOL bSucceed;
  2247. if ( bStart )
  2248. {
  2249. // DrvStartBanding
  2250. PFN_DrvStartBanding pfnDrvStartBanding = PPFNDRV(po, StartBanding);
  2251. bSucceed = (*pfnDrvStartBanding)(pSurf->pSurfobj(),pptl);
  2252. #if DEBUG_BANDING
  2253. DbgPrint("just called DrvStartBanding which returned %s %d %d\n",
  2254. (bSucceed) ? "TRUE" : "FALSE", pptl->x, pptl->y );
  2255. #endif
  2256. pSize->cx = pSurf->so.sizlBitmap.cx;
  2257. pSize->cy = pSurf->so.sizlBitmap.cy;
  2258. //
  2259. // Set band position in page (if we are banding)
  2260. //
  2261. dco.vSetPrintBandPos(pptl);
  2262. }
  2263. else
  2264. {
  2265. // DrvNextBand
  2266. PFN_DrvNextBand pfnDrvNextBand = PPFNDRV(po, NextBand);
  2267. bSucceed = (*pfnDrvNextBand)(pSurf->pSurfobj(), pptl );
  2268. #if DEBUG_BANDING
  2269. DbgPrint("just called DrvNextBand which returned %s %d %d\n",
  2270. (bSucceed) ? "TRUE" : "FALSE", pptl->x, pptl->y );
  2271. #endif
  2272. if ( (bSucceed) && ( pptl->x == -1 ) )
  2273. {
  2274. // No more bands.
  2275. if (!po.bUMPD())
  2276. {
  2277. //
  2278. // all the spooler calls have been made at the user mode
  2279. // for User Mode Printer Drivers
  2280. //
  2281. bSucceed = EndPagePrinter(po.hSpooler());
  2282. }
  2283. // Allow ResetDC to function again.
  2284. if (bSucceed)
  2285. {
  2286. dco.fsClr(DC_RESET);
  2287. }
  2288. // Delete the wndobj and reset the pixel format.
  2289. // Since we don't allow pixel format to change once it is set, we need
  2290. // to reset it internally here to allow a different pixel format in the
  2291. // next page. This means that applications must make the OpenGL
  2292. // rendering context not current before ending a page or a document.
  2293. // They also need to set the pixel format explicitly in the next page
  2294. // if they need it.
  2295. if (bSucceed)
  2296. {
  2297. EWNDOBJ *pwoDelete = pSurf->pwo();
  2298. if (pwoDelete)
  2299. {
  2300. GreDeleteWnd((PVOID) pwoDelete);
  2301. pSurf->pwo((EWNDOBJ *) NULL);
  2302. }
  2303. // Reset pixel format accelerators.
  2304. dco.ipfdDevMax(0);
  2305. }
  2306. }
  2307. else
  2308. {
  2309. if ( !bSucceed )
  2310. {
  2311. WARNING("GreDoBanding failed DrvNextBand\n");
  2312. }
  2313. else
  2314. {
  2315. //
  2316. // Set band position in page (if we are banding)
  2317. //
  2318. dco.vSetPrintBandPos(pptl);
  2319. }
  2320. }
  2321. }
  2322. return(bSucceed);
  2323. }
  2324. }
  2325. }
  2326. return bRet;
  2327. }
  2328. /******************************Public*Routine******************************\
  2329. * NtGdiDoBanding()
  2330. *
  2331. * History:
  2332. * 11-Jan-1995 -by- Eric Kutter [erick]
  2333. * Wrote it.
  2334. * 01-Mar-1995 -by- Lingyun Wang [lingyunw]
  2335. * Expanded it.
  2336. \**************************************************************************/
  2337. BOOL APIENTRY NtGdiDoBanding(
  2338. HDC hdc,
  2339. BOOL bStart,
  2340. POINTL *pptl,
  2341. PSIZE pSize
  2342. )
  2343. {
  2344. POINTL ptTmp;
  2345. SIZE szTmp;
  2346. BOOL bRet = TRUE;
  2347. bRet = GreDoBanding(hdc,bStart,&ptTmp,&szTmp);
  2348. if (bRet)
  2349. {
  2350. __try
  2351. {
  2352. ProbeForWrite(pptl,sizeof(POINTL), sizeof(DWORD));
  2353. *pptl = ptTmp;
  2354. ProbeForWrite(pSize,sizeof(SIZE), sizeof(DWORD));
  2355. *pSize = szTmp;
  2356. }
  2357. __except(EXCEPTION_EXECUTE_HANDLER)
  2358. {
  2359. // SetLastError(GetExceptionCode());
  2360. bRet = FALSE;
  2361. }
  2362. }
  2363. return(bRet);
  2364. }
  2365. /******************************Public*Routine******************************\
  2366. * BOOL APIENTRY GreGetPerBandInfo()
  2367. *
  2368. * History:
  2369. * 05-Jan-1997 -by- Hideyuki Nagase [hideyukn]
  2370. * Wrote it.
  2371. ***************************************************************************/
  2372. ULONG APIENTRY GreGetPerBandInfo(
  2373. HDC hdc,
  2374. PERBANDINFO *ppbi
  2375. )
  2376. {
  2377. ULONG ulRet = GDI_ERROR;
  2378. //
  2379. // Set default. Assume no repeat, just play one time per one band.
  2380. //
  2381. ppbi->bRepeatThisBand = FALSE;
  2382. DCOBJ dco(hdc);
  2383. if (dco.bValidSurf() && (dco.bHasSurface()))
  2384. {
  2385. PDEVOBJ po(dco.hdev());
  2386. if (po.hSpooler())
  2387. {
  2388. SURFACE *pSurf = dco.pSurface();
  2389. //
  2390. // The surface should be banded.
  2391. //
  2392. if (pSurf->SurfFlags & BANDING_SURFACE)
  2393. {
  2394. PFN_DrvQueryPerBandInfo pfnDrvQueryPerBandInfo = PPFNDRV(po, QueryPerBandInfo);
  2395. //
  2396. // DrvQueryPerBandInfo is optional fucntion, check it is provided.
  2397. //
  2398. if (pfnDrvQueryPerBandInfo)
  2399. {
  2400. //
  2401. // Call driver.
  2402. //
  2403. ulRet = (*pfnDrvQueryPerBandInfo)(pSurf->pSurfobj(), ppbi);
  2404. if (ulRet == DDI_ERROR)
  2405. {
  2406. ulRet = GDI_ERROR;
  2407. }
  2408. }
  2409. else
  2410. {
  2411. //
  2412. // The function is not provided, that means the driver don't
  2413. // want to repeat more than one time for each band. Just return
  2414. // true, and use default that setted above.
  2415. //
  2416. ulRet = 0;
  2417. }
  2418. }
  2419. }
  2420. }
  2421. return (ulRet);
  2422. }
  2423. /******************************Public*Routine******************************\
  2424. * BOOL APIENTRY NtGdiGetPerBandInfo()
  2425. *
  2426. * History:
  2427. * 05-Jan-1997 -by- Hideyuki Nagase [hideyukn]
  2428. * Wrote it.
  2429. ***************************************************************************/
  2430. ULONG APIENTRY NtGdiGetPerBandInfo(
  2431. HDC hdc,
  2432. PERBANDINFO *ppbi
  2433. )
  2434. {
  2435. PERBANDINFO PerBandInfo;
  2436. ULONG ulRet = GDI_ERROR;
  2437. if (ppbi)
  2438. {
  2439. __try
  2440. {
  2441. ProbeForRead(ppbi,sizeof(PERBANDINFO),sizeof(ULONG));
  2442. RtlCopyMemory(&PerBandInfo,ppbi,sizeof(PERBANDINFO));
  2443. }
  2444. __except(EXCEPTION_EXECUTE_HANDLER)
  2445. {
  2446. return (ulRet);
  2447. }
  2448. }
  2449. ulRet = GreGetPerBandInfo(hdc,&PerBandInfo);
  2450. if (ulRet && (ulRet != GDI_ERROR))
  2451. {
  2452. __try
  2453. {
  2454. ProbeForWrite(ppbi,sizeof(PERBANDINFO), sizeof(ULONG));
  2455. RtlCopyMemory(ppbi,&PerBandInfo,sizeof(PERBANDINFO));
  2456. }
  2457. __except(EXCEPTION_EXECUTE_HANDLER)
  2458. {
  2459. ulRet = GDI_ERROR;
  2460. }
  2461. }
  2462. return (ulRet);
  2463. }
  2464. /******************************Public*Routine******************************\
  2465. * BOOL APIENTRY EngCheckAbort
  2466. *
  2467. * History:
  2468. * 01-Apr-1992 -by- Wendy Wu [wendywu]
  2469. * Wrote it.
  2470. \**************************************************************************/
  2471. BOOL APIENTRY EngCheckAbort(SURFOBJ *pso)
  2472. {
  2473. // Return FALSE if it's a faked surfobj.
  2474. PSURFACE pSurf = SURFOBJ_TO_SURFACE(pso);
  2475. if (pSurf == NULL || pSurf->hsurf() == 0)
  2476. {
  2477. return(FALSE);
  2478. }
  2479. return(pSurf->bAbort());
  2480. }
  2481. /******************************Public*Routine******************************\
  2482. * BOOL APIENTRY NtGdiAnyLinkedFonts()
  2483. *
  2484. * Returns TRUE if there are any linked fonts in the system.
  2485. *
  2486. *
  2487. * History:
  2488. * 12-Dec-1996 by Gerrit van Wingerden [gerritv]
  2489. * Wrote it.
  2490. \**************************************************************************/
  2491. extern "C" BOOL NtGdiAnyLinkedFonts()
  2492. {
  2493. return(gbAnyLinkedFonts || IS_SYSTEM_EUDC_PRESENT());
  2494. }
  2495. /******************************Public*Routine******************************\
  2496. * BOOL APIENTRY NtGdiGetLinkedUFIs
  2497. *
  2498. * This API returns UFI's (in order of priority) of all the fonts linked to
  2499. * the font currently in the DC.
  2500. *
  2501. *
  2502. * History:
  2503. * 12-Dec-1996 by Gerrit van Wingerden [gerritv]
  2504. * Wrote it.
  2505. \**************************************************************************/
  2506. extern "C" INT NtGdiGetLinkedUFIs(
  2507. HDC hdc,
  2508. PUNIVERSAL_FONT_ID pufiLinkedUFIs,
  2509. INT BufferSize
  2510. )
  2511. {
  2512. INT iRet = 0;
  2513. PUNIVERSAL_FONT_ID pufi = NULL;
  2514. if (( BufferSize > 0 ) && ( pufiLinkedUFIs != NULL ))
  2515. {
  2516. if (!BALLOC_OVERFLOW1(BufferSize,UNIVERSAL_FONT_ID))
  2517. {
  2518. pufi = (PUNIVERSAL_FONT_ID)
  2519. PALLOCNOZ(BufferSize * sizeof(UNIVERSAL_FONT_ID),'difG');
  2520. }
  2521. if ( pufi == NULL )
  2522. {
  2523. iRet = -1 ;
  2524. }
  2525. }
  2526. else if (BufferSize && pufiLinkedUFIs == NULL)
  2527. {
  2528. iRet = -1;
  2529. }
  2530. if ( iRet != -1 )
  2531. {
  2532. {
  2533. XDCOBJ dco(hdc);
  2534. if (dco.bValid())
  2535. {
  2536. RFONTOBJ rfo(dco,FALSE);
  2537. if (rfo.bValid())
  2538. {
  2539. iRet = rfo.GetLinkedFontUFIs(dco, pufi,BufferSize);
  2540. }
  2541. else
  2542. {
  2543. iRet = -1;
  2544. WARNING("NtGdiGetLinkedUFIS: Invalid RFNTOBJ");
  2545. }
  2546. dco.vUnlockFast();
  2547. }
  2548. else
  2549. {
  2550. WARNING("NtGdiGetLinkedUFIS: Invalid DC");
  2551. iRet = -1;
  2552. }
  2553. }
  2554. if ( iRet > 0 )
  2555. {
  2556. __try
  2557. {
  2558. if (pufiLinkedUFIs)
  2559. {
  2560. ProbeForWrite(pufiLinkedUFIs,
  2561. sizeof(UNIVERSAL_FONT_ID)*BufferSize,
  2562. sizeof(DWORD));
  2563. RtlCopyMemory(pufiLinkedUFIs,
  2564. pufi,sizeof(UNIVERSAL_FONT_ID)*BufferSize);
  2565. }
  2566. }
  2567. __except(EXCEPTION_EXECUTE_HANDLER)
  2568. {
  2569. WARNINGX(62);
  2570. iRet = -1;
  2571. }
  2572. }
  2573. }
  2574. if ( pufi != NULL )
  2575. {
  2576. VFREEMEM( pufi );
  2577. }
  2578. if ( iRet == -1 )
  2579. {
  2580. // We need to set the last error here to something because the spooler
  2581. // code that calls this relies on there being a non-zero error code
  2582. // in the case of failure. Since we really have no idea I will just
  2583. // set this to ERROR_NOT_ENOUGH_MEMORY which would be the most likely
  2584. // reason for a failure
  2585. EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2586. }
  2587. return(iRet);
  2588. }
  2589. ULONG GreGetEmbedFonts()
  2590. {
  2591. PUBLIC_PFTOBJ pfto(gpPFTPrivate);
  2592. if (!pfto.bValid() || pfto.cFiles() == 0) // no embedded fonts
  2593. return 0;
  2594. return (pfto.GetEmbedFonts());
  2595. }
  2596. BOOL GreChangeGhostFont(VOID *fontID, BOOL bLoad)
  2597. {
  2598. PUBLIC_PFTOBJ pfto(gpPFTPrivate);
  2599. if (!pfto.bValid() || !pfto.cFiles()) // somehow the private font table is invalid
  2600. return FALSE;
  2601. return (pfto.ChangeGhostFont(fontID, bLoad));
  2602. }
  2603. extern "C" BOOL NtGdiAddEmbFontToDC(HDC hdc, VOID **pFontID)
  2604. {
  2605. VOID *fontID;
  2606. BOOL bRet = TRUE;
  2607. __try
  2608. {
  2609. ProbeForRead(pFontID, sizeof(VOID *), sizeof(BYTE));
  2610. RtlCopyMemory(&fontID, pFontID, sizeof(VOID *));
  2611. }
  2612. __except(EXCEPTION_EXECUTE_HANDLER)
  2613. {
  2614. bRet = FALSE;
  2615. }
  2616. if (bRet)
  2617. {
  2618. bRet = FALSE;
  2619. XDCOBJ dco(hdc);
  2620. if (dco.bValid())
  2621. {
  2622. PUBLIC_PFTOBJ pfto(gpPFTPrivate);
  2623. // FonID could be a fake value from hacker to crash the system
  2624. if(pfto.bValid() && pfto.VerifyFontID(fontID))
  2625. bRet = dco.bAddRemoteFont((PFF *)fontID);
  2626. }
  2627. }
  2628. return bRet;
  2629. }
  2630. /******************************Public*Routine******************************\
  2631. * BOOL GreGetUFI
  2632. *
  2633. * History:
  2634. * 18-Jan-1995 -by- Gerrit van Wingerden
  2635. * Wrote it.
  2636. \**************************************************************************/
  2637. BOOL GreGetUFI( HDC hdc, PUNIVERSAL_FONT_ID pufi,
  2638. DESIGNVECTOR *pdv, ULONG *pcjDV, ULONG *pulBaseCheckSum,
  2639. FLONG *pfl,
  2640. VOID **pfontID)
  2641. {
  2642. *pfl = 0;
  2643. if (pfontID)
  2644. *pfontID = NULL;
  2645. BOOL bRet = FALSE;
  2646. XDCOBJ dco(hdc);
  2647. if(dco.bValid())
  2648. {
  2649. RFONTOBJ rfo(dco,FALSE);
  2650. if (rfo.bValid())
  2651. {
  2652. rfo.vUFI( pufi );
  2653. // now on to determine if this is private or public font
  2654. PFEOBJ pfeo(rfo.ppfe());
  2655. if (pfeo.bValid())
  2656. {
  2657. PFFOBJ pffo(pfeo.pPFF());
  2658. if (pffo.bValid())
  2659. {
  2660. if (pffo.bInPrivatePFT())
  2661. {
  2662. *pfl |= FL_UFI_PRIVATEFONT;
  2663. if (pfontID)
  2664. *pfontID = (VOID*) pfeo.pPFF();
  2665. }
  2666. if (pffo.bMemFont())
  2667. {
  2668. *pfl |= FL_UFI_MEMORYFONT;
  2669. }
  2670. if (pffo.pdv())
  2671. {
  2672. *pfl |= FL_UFI_DESIGNVECTOR_PFF;
  2673. if (pdv)
  2674. RtlCopyMemory(pdv, pffo.pdv(), pffo.cjDV());
  2675. if (pcjDV)
  2676. *pcjDV = pffo.cjDV();
  2677. if (pulBaseCheckSum)
  2678. {
  2679. // factor out DV check sum. If we endup using algorithm
  2680. // that couples these two numbers, then BaseCheckSum will
  2681. // have to be remembered at the time of computation.
  2682. *pulBaseCheckSum = pffo.ulCheckSum();
  2683. *pulBaseCheckSum -= ComputeFileviewCheckSum(pffo.pdv(), pffo.cjDV());
  2684. }
  2685. }
  2686. bRet = TRUE;
  2687. }
  2688. }
  2689. }
  2690. else
  2691. {
  2692. WARNING("GreGetUFI: Invalid rfo");
  2693. }
  2694. dco.vUnlockFast();
  2695. }
  2696. else
  2697. {
  2698. WARNING("GreGetUFI: Invalid DC");
  2699. }
  2700. return bRet;
  2701. }
  2702. /******************************Public*Routine******************************\
  2703. *
  2704. * ppfeGetPFEFromUFI
  2705. *
  2706. * This is used all over the place
  2707. *
  2708. * History:
  2709. * 11-Aug-1997 -by- Bodin Dresevic [BodinD]
  2710. * Wrote it.
  2711. \**************************************************************************/
  2712. PFE *ppfeGetPFEFromUFIInternal (
  2713. PUNIVERSAL_FONT_ID pufi,
  2714. BOOL bPrivate,
  2715. BOOL bCheckProccess
  2716. )
  2717. {
  2718. PFE *ppfeRet = NULL;
  2719. PFELINK *ppfel;
  2720. BOOL bThreadMatch = FALSE;
  2721. PUBLIC_PFTOBJ pfto(bPrivate ? gpPFTPrivate : gpPFTPublic);
  2722. if (!pfto.bValid())
  2723. return ppfeRet;
  2724. FHOBJ fho(&pfto.pPFT->pfhUFI);
  2725. HASHBUCKET *pbkt;
  2726. pbkt = fho.pbktSearch( NULL, (UINT*)NULL, pufi );
  2727. if (!pbkt)
  2728. {
  2729. WARNING1("ppfeGetPFEFromUFI: pbkt is NULL\n");
  2730. return ppfeRet;
  2731. }
  2732. for(ppfel = pbkt->ppfelEnumHead; ppfel; ppfel = ppfel->ppfelNext)
  2733. {
  2734. PFEOBJ pfeo(ppfel->ppfe);
  2735. if (UFI_SAME_FACE(pfeo.pUFI(),pufi) && (!bCheckProccess || pfeo.SameProccess()))
  2736. {
  2737. if(pfeo.bDead())
  2738. {
  2739. WARNING("ppfeGetPFEFromUFI: get the pathname to a dead PFE\n");
  2740. }
  2741. else
  2742. {
  2743. if (ppfeRet == NULL)
  2744. {
  2745. bThreadMatch = pfeo.SameThread();
  2746. ppfeRet = ppfel->ppfe;
  2747. }
  2748. else
  2749. {
  2750. // if we get here, it means we have multiple face name and process match.
  2751. // Do more extensive matching using thread ID.
  2752. if (!bThreadMatch && pfeo.SameThread())
  2753. {
  2754. // This is a better candidate.
  2755. // Although spooler can be running multiple threads, the same thread for a given
  2756. // port is used by spooler. However, if multiple printers were sharing the same
  2757. // port, we cannot distinguish.
  2758. ppfeRet = ppfel->ppfe;
  2759. bThreadMatch = TRUE;
  2760. break;
  2761. }
  2762. }
  2763. }
  2764. }
  2765. }
  2766. return ppfeRet;
  2767. }
  2768. PFE *ppfeGetPFEFromUFI (
  2769. PUNIVERSAL_FONT_ID pufi,
  2770. BOOL bPrivate,
  2771. BOOL bCheckProccess
  2772. )
  2773. {
  2774. PFE * pfeRet = NULL;
  2775. if (bPrivate)
  2776. pfeRet = ppfeGetPFEFromUFIInternal(pufi, TRUE, bCheckProccess);
  2777. if (!pfeRet)
  2778. pfeRet = ppfeGetPFEFromUFIInternal(pufi, FALSE, bCheckProccess);
  2779. return pfeRet;
  2780. }
  2781. #define SZDLHEADER ALIGN8(offsetof(DOWNLOADFONTHEADER, FileOffsets[1]))
  2782. /*********************************Public*Routine*********************************\
  2783. * BOOL GreGetUFIPathname
  2784. *
  2785. * Get the path name and file counts to a given UFI.
  2786. *
  2787. * History:
  2788. * Feb-04-1997 Xudong Wu [tessiew]
  2789. * Wrote it.
  2790. \********************************************************************************/
  2791. BOOL GreGetUFIPathname(
  2792. PUNIVERSAL_FONT_ID pufi,
  2793. ULONG *pcwc,
  2794. LPWSTR pwszPathname,
  2795. ULONG *pcNumFiles,
  2796. FLONG fl,
  2797. BOOL *pbMemFont,
  2798. ULONG *pcjView,
  2799. PVOID pvView,
  2800. BOOL *pbTTC,
  2801. ULONG *piTTC
  2802. )
  2803. {
  2804. BOOL bRet = TRUE;
  2805. PFE *ppfe = ppfeGetPFEFromUFI(pufi, (BOOL)(fl & (FL_UFI_PRIVATEFONT | FL_UFI_MEMORYFONT)), TRUE);
  2806. if (ppfe == NULL)
  2807. {
  2808. WARNING("GreGetUFIPathname can't find the PFE\n");
  2809. return FALSE;
  2810. }
  2811. PFFOBJ pffo(ppfe->pPFF);
  2812. if (pcNumFiles)
  2813. {
  2814. *pcNumFiles = pffo.cNumFiles();
  2815. }
  2816. if (pcwc)
  2817. {
  2818. *pcwc = pffo.cSizeofPaths();
  2819. }
  2820. if (pwszPathname)
  2821. {
  2822. RtlCopyMemory(pwszPathname, pffo.pwszPathname(), pffo.cSizeofPaths() * sizeof(WCHAR));
  2823. }
  2824. if (pbMemFont)
  2825. {
  2826. *pbMemFont = (BOOL)(ppfe->flPFE & PFE_MEMORYFONT);
  2827. }
  2828. if (ppfe->flPFE & PFE_MEMORYFONT)
  2829. {
  2830. NTSTATUS NtStatus;
  2831. SIZE_T ViewSize = 0;
  2832. ULONG cjView;
  2833. ASSERTGDI((pffo.ppfvGet()[0])->SpoolerPid == (W32PID)W32GetCurrentPID() || // either the current process
  2834. gpidSpool == (PW32PROCESS)W32GetCurrentProcess(), // or the spooler
  2835. "GreGetUFIPathname: wrong process to access memory font\n");
  2836. #if 0
  2837. PVOID pvView1;
  2838. LARGE_INTEGER SectionOffset; SectionOffset.QuadPart = 0;
  2839. NtStatus = MmMapViewOfSection(
  2840. pffo.ppfvGet()[0]->fv.pSection , // SectionToMap,
  2841. PsGetCurrentProcess(), //
  2842. &pvView1 , // CapturedBase,
  2843. 0 , // ZeroBits,
  2844. ViewSize , // CommitSize,
  2845. &SectionOffset , // SectionOffset,
  2846. &ViewSize , // CapturedViewSize,
  2847. ViewUnmap , // InheritDisposition,
  2848. SEC_NO_CHANGE , // AllocationType,
  2849. PAGE_READONLY // Protect
  2850. );
  2851. if (!NT_SUCCESS(NtStatus))
  2852. {
  2853. //WARNING("could not map mem font to the spooler process\n");
  2854. KdPrint(("could not map mem font to the spooler process\n"));
  2855. *pcjView = 0;
  2856. *ppvView = NULL;
  2857. return FALSE;
  2858. }
  2859. // if this is a memory font, preceeding the font image
  2860. // there is going to be the header stuff in the section,
  2861. // so will need to adjust the pointer. cjView will already contain
  2862. // the correct data corresponding to the size without the header
  2863. *pcjView = pffo.ppfvGet()[0]->fv.cjView;
  2864. *ppvView = (PVOID)((BYTE *)pvView1 + SZDLHEADER);
  2865. #endif
  2866. cjView = pffo.ppfvGet()[0]->fv.cjView;
  2867. if (pcjView)
  2868. {
  2869. *pcjView = cjView;
  2870. }
  2871. if (pvView)
  2872. {
  2873. PVOID pvKView;
  2874. #ifdef _HYDRA_
  2875. // MmMapViewInSessionSpace is internally promoted to
  2876. // MmMapViewInSystemSpace on non-Hydra systems.
  2877. NtStatus = Win32MapViewInSessionSpace(
  2878. pffo.ppfvGet()[0]->fv.pSection,
  2879. &pvKView,
  2880. &ViewSize);
  2881. #else
  2882. NtStatus = MmMapViewInSystemSpace(
  2883. pffo.ppfvGet()[0]->fv.pSection,
  2884. &pvKView,
  2885. &ViewSize);
  2886. #endif
  2887. if (!NT_SUCCESS(NtStatus))
  2888. {
  2889. //WARNING("could not map mem font to the system space\n");
  2890. KdPrint(("could not map mem font to the system space\n"));
  2891. return FALSE;
  2892. }
  2893. __try
  2894. {
  2895. // if this is a memory font, preceeding the font image
  2896. // there is going to be the header stuff in the section,
  2897. // so will need to adjust the pointer before copying.
  2898. // cjView already corresponds to the correct data
  2899. // without the header
  2900. ProbeForWrite(pvView, cjView, sizeof(BYTE));
  2901. RtlCopyMemory(pvView, ((BYTE *)pvKView + SZDLHEADER), cjView);
  2902. }
  2903. __except(EXCEPTION_EXECUTE_HANDLER)
  2904. {
  2905. bRet = FALSE;
  2906. }
  2907. #ifdef _HYDRA_
  2908. // MmUnmapViewInSessionSpace is internally promoted to
  2909. // MmUnmapViewInSystemSpace on non-Hydra systems.
  2910. Win32UnmapViewInSessionSpace(pvKView);
  2911. #else
  2912. MmUnmapViewInSystemSpace(pvKView);
  2913. #endif
  2914. }
  2915. }
  2916. if (bRet && pbTTC && piTTC)
  2917. {
  2918. *pbTTC = FALSE;
  2919. *piTTC = 0;
  2920. PFF *pPFF = ppfe->pPFF;
  2921. if (pPFF->hdev == (HDEV) gppdevTrueType)
  2922. {
  2923. COUNT cFonts = pPFF->cFonts;
  2924. // if this is a ttc file we need at least 4 faces, eg.
  2925. // foo1, @foo1, foo2, @foo2 ...
  2926. if ((cFonts >= 4) && !(cFonts & 1))
  2927. {
  2928. ASSERTGDI(ppfe->ufi.Index, "ufi.Index must not be zero\n");
  2929. *piTTC = (ppfe->ufi.Index - 1) / 2;
  2930. *pbTTC = TRUE;
  2931. }
  2932. }
  2933. }
  2934. return bRet;
  2935. }
  2936. /******************************Public*Routine******************************\
  2937. * BOOL GreForceUFIMapping( HDC hdc, PUNIVERSAL_FONT_ID pufi )
  2938. *
  2939. * History:
  2940. * 3-Mar-1995 -by- Gerrit van Wingerden
  2941. * Wrote it.
  2942. \**************************************************************************/
  2943. BOOL GreForceUFIMapping( HDC hdc, PUNIVERSAL_FONT_ID pufi)
  2944. {
  2945. XDCOBJ dco(hdc);
  2946. if (!dco.bValid())
  2947. {
  2948. WARNING("GreForceUFIMapping: Invalid DC");
  2949. return(FALSE);
  2950. }
  2951. dco.pdc->vForceMapping( pufi );
  2952. dco.vUnlockFast();
  2953. return(TRUE);
  2954. }
  2955. /**********************Public*Routine******************************\
  2956. * NtGdiRemoveMergeFont(HDC hdc, UNIVERSAL_FONT_ID *pufi)
  2957. *
  2958. * History:
  2959. * Jan-27-1997 -by- Xudong Wu [tessiew]
  2960. * Wrote it.
  2961. \******************************************************************/
  2962. BOOL
  2963. APIENTRY
  2964. NtGdiRemoveMergeFont(HDC hdc, UNIVERSAL_FONT_ID *pufi)
  2965. {
  2966. BOOL bRet = TRUE;
  2967. UNIVERSAL_FONT_ID ufiTmp;
  2968. XDCOBJ dco(hdc);
  2969. if(!dco.bValid())
  2970. {
  2971. WARNING("NtGdiRemoveMergefont bogus HDC\n" );
  2972. return FALSE;
  2973. }
  2974. else if (dco.bDisplay())
  2975. {
  2976. WARNING("NtGdiRemoveMergefont: display DC\n" );
  2977. bRet = FALSE;
  2978. }
  2979. else
  2980. {
  2981. ASSERTGDI(pufi != NULL, "Try to remove a font wiht pufi == NULL\n");
  2982. __try
  2983. {
  2984. ProbeForRead(pufi, sizeof(UNIVERSAL_FONT_ID), sizeof(DWORD));
  2985. ufiTmp = *pufi;
  2986. }
  2987. __except(EXCEPTION_EXECUTE_HANDLER)
  2988. {
  2989. bRet = FALSE;
  2990. }
  2991. if (bRet)
  2992. {
  2993. if (!(bRet = dco.bRemoveMergeFont(ufiTmp)))
  2994. {
  2995. WARNING("NtGdiRemoveMergeFont failed on dco.bRemoveMergeFont\n");
  2996. }
  2997. }
  2998. }
  2999. dco.vUnlockFast();
  3000. return bRet;
  3001. }
  3002. /****************************************************************************
  3003. * INT GreQueryFonts( PUNIVERSAL_FONT_ID, ULONG, PLARGE_INTEGER )
  3004. *
  3005. * History:
  3006. * 5/24/1995 by Gerrit van Wingerden [gerritv]
  3007. * Wrote it.
  3008. *****************************************************************************/
  3009. INT GreQueryFonts(
  3010. PUNIVERSAL_FONT_ID pufi,
  3011. ULONG nBufferSize,
  3012. PLARGE_INTEGER pTimeStamp
  3013. )
  3014. {
  3015. PUBLIC_PFTOBJ pfto;
  3016. return(pfto.QueryFonts(pufi,nBufferSize,pTimeStamp));
  3017. }
  3018. /*****************************************************************************
  3019. * PTYPEONEINFO GetTypeOneFontList()
  3020. *
  3021. * This function returns a pointer to a TYPEONEINFO structure that contains
  3022. * a list of file mapping handles and checksums for the Type1 fontst that are
  3023. * installed in the system. This structure also has a reference count and a
  3024. * time stamp coresponding to the last time fonts were added or removed from
  3025. * the system. The reference count is 1 biased meaning that even if no PDEV's
  3026. * a referencing it, it is still 1.
  3027. *
  3028. * History
  3029. * 8-10-95 Gerrit van Wingerden [gerritv]
  3030. * Wrote it.
  3031. *
  3032. ****************************************************************************/
  3033. PTYPEONEINFO GetTypeOneFontList()
  3034. {
  3035. UNICODE_STRING UnicodeRoot;
  3036. PTYPEONEINFO InfoReturn = NULL;
  3037. OBJECT_ATTRIBUTES ObjectAttributes;
  3038. BOOL bCloseRegistry = FALSE;
  3039. NTSTATUS NtStatus;
  3040. PKEY_FULL_INFORMATION InfoBuffer = NULL;
  3041. PKEY_VALUE_PARTIAL_INFORMATION PartialInfo = NULL;
  3042. ULONG KeyInfoLength;
  3043. HANDLE KeyRegistry;
  3044. RtlInitUnicodeString(&UnicodeRoot,TYPE1_KEY);
  3045. InitializeObjectAttributes(&ObjectAttributes,
  3046. &UnicodeRoot,
  3047. OBJ_CASE_INSENSITIVE,
  3048. NULL,
  3049. NULL);
  3050. NtStatus = ZwOpenKey(&KeyRegistry,
  3051. GENERIC_READ,
  3052. &ObjectAttributes);
  3053. if (!NT_SUCCESS(NtStatus))
  3054. {
  3055. WARNING("Unable to open TYPE1 key\n");
  3056. goto done;
  3057. }
  3058. bCloseRegistry = TRUE;
  3059. NtStatus = ZwQueryKey(KeyRegistry,
  3060. KeyFullInformation,
  3061. (PVOID) NULL,
  3062. 0,
  3063. &KeyInfoLength );
  3064. if ((NtStatus != STATUS_BUFFER_OVERFLOW) &&
  3065. (NtStatus != STATUS_BUFFER_TOO_SMALL))
  3066. {
  3067. WARNING("Unable to query TYPE1 key\n");
  3068. goto done;
  3069. }
  3070. InfoBuffer = (PKEY_FULL_INFORMATION) PALLOCNOZ(KeyInfoLength,'f1tG');
  3071. if ( !InfoBuffer )
  3072. {
  3073. WARNING("Unable to alloc mem for TYPE1 info\n");
  3074. goto done;
  3075. }
  3076. NtStatus = ZwQueryKey(KeyRegistry,
  3077. KeyFullInformation,
  3078. InfoBuffer,
  3079. KeyInfoLength,
  3080. &KeyInfoLength );
  3081. if (!NT_SUCCESS(NtStatus))
  3082. {
  3083. WARNING("Unable to query TYPE1 key\n");
  3084. goto done;
  3085. }
  3086. // if there aren't any soft TYPE1 fonts installed then just return now.
  3087. if ( !InfoBuffer->Values )
  3088. {
  3089. goto done;
  3090. }
  3091. GreAcquireFastMutex(ghfmMemory);
  3092. if (gpTypeOneInfo != NULL )
  3093. {
  3094. if ((gpTypeOneInfo->LastWriteTime.LowPart == InfoBuffer->LastWriteTime.LowPart)&&
  3095. (gpTypeOneInfo->LastWriteTime.HighPart == InfoBuffer->LastWriteTime.HighPart))
  3096. {
  3097. // If the times match then increment the ref count and return
  3098. InfoReturn = gpTypeOneInfo;
  3099. gpTypeOneInfo->cRef += 1;
  3100. GreReleaseFastMutex(ghfmMemory);
  3101. goto done;
  3102. }
  3103. gpTypeOneInfo->cRef -= 1;
  3104. // At this point if gTypeOneInfo->cRef > 0 then there is a PDEV using this
  3105. // info still. If gTypeOneInfo->cRef = 0 then it is okay to delete it.
  3106. // Note that this behavior means we must initialize gTypeOneInfo->cRef to 1.
  3107. if ( !gpTypeOneInfo->cRef )
  3108. {
  3109. VFREEMEM(gpTypeOneInfo);
  3110. }
  3111. // Whether someone is using it or not, remove pointer to current type one
  3112. // info so that noone else tries to use it.
  3113. gpTypeOneInfo = NULL;
  3114. }
  3115. GreReleaseFastMutex(ghfmMemory);
  3116. ULONG MaxValueName, MaxValueData, TotalData, Values;
  3117. MaxValueData = ALIGN4(InfoBuffer->MaxValueDataLen);
  3118. Values = InfoBuffer->Values;
  3119. TotalData = MaxValueData + sizeof(KEY_VALUE_PARTIAL_INFORMATION);
  3120. if( TotalData < MaxValueData ) // overflow
  3121. {
  3122. TotalData = 0;
  3123. } else {
  3124. unsigned long n = sizeof(ULONG) // checksum
  3125. + (2 * sizeof(WCHAR) * (MAX_PATH+1)) // PFM & PFB paths
  3126. + sizeof(FONTFILEVIEW); // mapping structs
  3127. if( Values > MAXIMUM_POOL_ALLOC/n // multiply would overflow
  3128. || TotalData < (TotalData + Values * n) ) // addition would overflow
  3129. TotalData = 0;
  3130. else
  3131. TotalData += Values * n;
  3132. }
  3133. // now TotalData contains either:
  3134. // MaxValueData + sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
  3135. // (Values * sizeof(ULONG)) + <--- Room for checksums
  3136. // (Values * 2 * sizeof(WCHAR) * (MAX_PATH + 1)) + <--- PFM/PFB paths
  3137. // Values * sizeof(FONTFILEVIEW); <--- room for mapping structs
  3138. // or it contains a zero because of arithmetic overflow in the size
  3139. // calculation
  3140. PartialInfo = (TotalData == 0) ? NULL
  3141. : (PKEY_VALUE_PARTIAL_INFORMATION) PALLOCNOZ(TotalData,'f1tG');
  3142. if ( !PartialInfo )
  3143. {
  3144. WARNING("Unable to allocate memory for TYPE1 info\n");
  3145. goto done;
  3146. }
  3147. BYTE *ValueData;
  3148. PFONTFILEVIEW FontFileViews;
  3149. WCHAR *FullPFM, *FullPFB;
  3150. ULONG *Checksums;
  3151. ULONG SoftFont,Result;
  3152. ValueData = &(PartialInfo->Data[0]);
  3153. FullPFM = (WCHAR*) &ValueData[MaxValueData];
  3154. FullPFB = &FullPFM[(MAX_PATH+1)*Values];
  3155. Checksums = (ULONG*) &FullPFB[Values*(MAX_PATH+1)];
  3156. FontFileViews = (PFONTFILEVIEW) &Checksums[Values];
  3157. for ( SoftFont = 0; SoftFont < Values; SoftFont ++ )
  3158. {
  3159. WCHAR *TmpValueData;
  3160. COUNT SizeOfString;
  3161. NtStatus = ZwEnumerateValueKey(KeyRegistry,
  3162. SoftFont,
  3163. KeyValuePartialInformation,
  3164. PartialInfo,
  3165. MaxValueData +
  3166. sizeof(KEY_VALUE_PARTIAL_INFORMATION),
  3167. &Result );
  3168. if (!NT_SUCCESS(NtStatus))
  3169. {
  3170. WARNING("Unable to enumerate TYPE1 keys\n");
  3171. goto done;
  3172. }
  3173. TmpValueData = (WCHAR*) ValueData;
  3174. TmpValueData = TmpValueData + wcslen(TmpValueData)+1;
  3175. SizeOfString = wcslen(TmpValueData);
  3176. if ( SizeOfString > MAX_PATH )
  3177. {
  3178. WARNING("PFM path too long\n");
  3179. goto done;
  3180. }
  3181. wcscpy(&FullPFM[SoftFont*(MAX_PATH+1)],TmpValueData);
  3182. TmpValueData += SizeOfString+1;
  3183. SizeOfString = wcslen(TmpValueData);
  3184. if ( SizeOfString > MAX_PATH )
  3185. {
  3186. WARNING("PFB path too long\n");
  3187. goto done;
  3188. }
  3189. wcscpy(&FullPFB[SoftFont*(MAX_PATH+1)],TmpValueData);
  3190. }
  3191. // Release key at this point. We are about to call off to the spooler
  3192. // which could take a while and shouldn't be holding the key while we do so.
  3193. ZwCloseKey(KeyRegistry);
  3194. bCloseRegistry = FALSE;
  3195. ULONG i, ValidatedTotal,TotalSize;
  3196. for ( i = 0, ValidatedTotal = TotalSize = 0; i < SoftFont; i++ )
  3197. {
  3198. BOOL bAbleToLoadFont;
  3199. bAbleToLoadFont = FALSE;
  3200. // go through all the PFM's and PFB's and expand them to full paths by
  3201. // calling back to the spooler
  3202. if (GetFontPathName(&FullPFM[i*(MAX_PATH+1)],&FullPFM[i*(MAX_PATH+1)]) &&
  3203. GetFontPathName(&FullPFB[i*(MAX_PATH+1)],&FullPFB[i*(MAX_PATH+1)]))
  3204. {
  3205. // Compute the checksum that we are goine to give to the PSCRIPT
  3206. // driver to stuff into the IFI metrics. We will use the sum
  3207. // of the checksum of both files.
  3208. FILEVIEW fv;
  3209. RtlZeroMemory( &fv, sizeof(fv) );
  3210. // Temporarily map a kernel mode view
  3211. if (bMapFile(&FullPFM[i*(MAX_PATH+1)], &fv, 0, NULL))
  3212. {
  3213. ULONG sum;
  3214. sum = ComputeFileviewCheckSum(fv.pvKView, fv.cjView);
  3215. vUnmapFile( &fv);
  3216. // Temporarily map a kernel mode view
  3217. if (bMapFile(&FullPFB[i*(MAX_PATH+1)], &fv, 0, NULL))
  3218. {
  3219. sum += ComputeFileviewCheckSum(fv.pvKView, fv.cjView);
  3220. vUnmapFile( &fv);
  3221. ValidatedTotal += 2;
  3222. TotalSize += (wcslen(&FullPFM[i*(MAX_PATH+1)]) + 1) * sizeof(WCHAR);
  3223. TotalSize += (wcslen(&FullPFB[i*(MAX_PATH+1)]) + 1) * sizeof(WCHAR);
  3224. Checksums[i] = sum;
  3225. bAbleToLoadFont = TRUE;
  3226. }
  3227. }
  3228. }
  3229. if (!bAbleToLoadFont)
  3230. {
  3231. FullPFM[i*(MAX_PATH+1)] = (WCHAR) 0;
  3232. FullPFB[i*(MAX_PATH+1)] = (WCHAR) 0;
  3233. }
  3234. }
  3235. TotalSize += ValidatedTotal * sizeof(TYPEONEMAP) + sizeof(TYPEONEINFO);
  3236. PTYPEONEINFO TypeOneInfo;
  3237. WCHAR *StringBuffer;
  3238. if (!ValidatedTotal)
  3239. {
  3240. goto done;
  3241. }
  3242. TypeOneInfo = (PTYPEONEINFO) PALLOCMEM(TotalSize,'f1tG');
  3243. StringBuffer = (WCHAR*) &TypeOneInfo->aTypeOneMap[ValidatedTotal];
  3244. if ( !TypeOneInfo )
  3245. {
  3246. goto done;
  3247. }
  3248. TypeOneInfo->cRef = 1; // must be one so PDEV stuff doesn't deallocate it unless
  3249. // we explicitly set it to 0
  3250. TypeOneInfo->cNumFonts = ValidatedTotal/2;
  3251. TypeOneInfo->LastWriteTime = InfoBuffer->LastWriteTime;
  3252. // loop through everything again packing everything tightly together in memory
  3253. // and setting up the FONTFILEVIEW pointers.
  3254. UINT CurrentFont;
  3255. for ( i = 0, CurrentFont = 0; i < SoftFont; i ++ )
  3256. {
  3257. if (FullPFM[i*(MAX_PATH+1)] != (WCHAR) 0)
  3258. {
  3259. wcscpy(StringBuffer,&FullPFM[i*(MAX_PATH+1)]);
  3260. TypeOneInfo->aTypeOneMap[CurrentFont].fv.pwszPath = StringBuffer;
  3261. StringBuffer += wcslen(&FullPFM[i*(MAX_PATH+1)]) + 1;
  3262. wcscpy(StringBuffer,&FullPFB[i*(MAX_PATH+1)]);
  3263. TypeOneInfo->aTypeOneMap[CurrentFont+1].fv.pwszPath = StringBuffer;
  3264. StringBuffer += wcslen(&FullPFB[i*(MAX_PATH+1)]) + 1;
  3265. // Both the PFM and PFB share the same checksum since they represent
  3266. // the same font file.
  3267. TypeOneInfo->aTypeOneMap[CurrentFont].Checksum = Checksums[i];
  3268. TypeOneInfo->aTypeOneMap[CurrentFont+1].Checksum = Checksums[i];
  3269. CurrentFont += 2;
  3270. }
  3271. }
  3272. ASSERTGDI(CurrentFont == ValidatedTotal,
  3273. "GetTypeOneFontList:CurrentFont != ValidatedTotal\n");
  3274. // everything should be set up now just our list into
  3275. GreAcquireFastMutex(ghfmMemory);
  3276. if ( gpTypeOneInfo )
  3277. {
  3278. // looks like someone snuck in before us. that's okay well use their font
  3279. // list and destroy our own
  3280. VFREEMEM(TypeOneInfo);
  3281. }
  3282. else
  3283. {
  3284. gpTypeOneInfo = TypeOneInfo;
  3285. }
  3286. gpTypeOneInfo->cRef += 1;
  3287. InfoReturn = gpTypeOneInfo;
  3288. GreReleaseFastMutex(ghfmMemory);
  3289. done:
  3290. if ( bCloseRegistry )
  3291. {
  3292. ZwCloseKey(KeyRegistry);
  3293. }
  3294. if ( InfoBuffer )
  3295. {
  3296. VFREEMEM(InfoBuffer);
  3297. }
  3298. if ( PartialInfo )
  3299. {
  3300. VFREEMEM(PartialInfo);
  3301. }
  3302. return(InfoReturn);
  3303. }
  3304. /******************************Public*Routine******************************\
  3305. *
  3306. * Routine Name:
  3307. *
  3308. * EngGetType1FontList
  3309. *
  3310. * Routine Description:
  3311. *
  3312. * Arguments:
  3313. *
  3314. * Called by:
  3315. *
  3316. * Return Value:
  3317. *
  3318. \**************************************************************************/
  3319. BOOL APIENTRY EngGetType1FontList(
  3320. HDEV hdev,
  3321. TYPE1_FONT *pType1Buffer,
  3322. ULONG cjType1Buffer,
  3323. PULONG pulLocalFonts,
  3324. PULONG pulRemoteFonts,
  3325. LARGE_INTEGER *pLastModified
  3326. )
  3327. {
  3328. BOOL bRet = FALSE;
  3329. PPDEV ppdev = (PPDEV) hdev;
  3330. if (!ppdev->TypeOneInfo)
  3331. {
  3332. ppdev->TypeOneInfo = GetTypeOneFontList();
  3333. }
  3334. PREMOTETYPEONENODE RemoteTypeOne = ppdev->RemoteTypeOne;
  3335. if (ppdev->TypeOneInfo || RemoteTypeOne )
  3336. {
  3337. *pulRemoteFonts = 0;
  3338. while (RemoteTypeOne)
  3339. {
  3340. *pulRemoteFonts += 1;
  3341. RemoteTypeOne = RemoteTypeOne->pNext;
  3342. }
  3343. if ( ppdev->TypeOneInfo )
  3344. {
  3345. *pulLocalFonts = ppdev->TypeOneInfo->cNumFonts;
  3346. *pLastModified = *(&ppdev->TypeOneInfo->LastWriteTime);
  3347. }
  3348. else
  3349. {
  3350. *pulLocalFonts = 0;
  3351. pLastModified->LowPart = 0;
  3352. pLastModified->HighPart = 0;
  3353. }
  3354. // If buffer is NULL then caller is only querying for time stamp
  3355. // and size of buffer.
  3356. if (pType1Buffer)
  3357. {
  3358. COUNT Font;
  3359. unsigned long buflen =
  3360. (BALLOC_OVERFLOW1((*pulLocalFonts+*pulRemoteFonts),TYPE1_FONT))
  3361. ? 0 : (*pulLocalFonts+*pulRemoteFonts) * sizeof(TYPE1_FONT);
  3362. if (cjType1Buffer >= buflen && buflen != 0)
  3363. {
  3364. TYPEONEMAP *pTypeOneMap = ppdev->TypeOneInfo->aTypeOneMap;
  3365. for (Font = 0;
  3366. ppdev->TypeOneInfo && (Font < ppdev->TypeOneInfo->cNumFonts);
  3367. Font++ )
  3368. {
  3369. pType1Buffer[Font].hPFM = (HANDLE)&pTypeOneMap[Font*2].fv;
  3370. pType1Buffer[Font].hPFB = (HANDLE)&pTypeOneMap[Font*2+1].fv;
  3371. pType1Buffer[Font].ulIdentifier = pTypeOneMap[Font*2+1].Checksum;
  3372. }
  3373. RemoteTypeOne = ppdev->RemoteTypeOne;
  3374. while ( RemoteTypeOne )
  3375. {
  3376. pType1Buffer[Font].hPFM = (HANDLE) &(RemoteTypeOne->fvPFM);
  3377. pType1Buffer[Font].hPFB = (HANDLE) &(RemoteTypeOne->fvPFB);
  3378. pType1Buffer[Font].ulIdentifier =
  3379. RemoteTypeOne->pDownloadHeader->Type1ID;
  3380. Font += 1;
  3381. RemoteTypeOne = RemoteTypeOne->pNext;
  3382. }
  3383. bRet = TRUE;
  3384. }
  3385. else
  3386. {
  3387. WARNING("GDI:EngGetType1FontList:pType1Buffer is too small.\n");
  3388. }
  3389. }
  3390. else
  3391. {
  3392. bRet = TRUE;
  3393. }
  3394. }
  3395. return(bRet);
  3396. }
  3397. /******************************Public*Routine******************************\
  3398. * EngQueryLocalTime()
  3399. *
  3400. * Fill in the ENG_TIME_FIELDS structure with the current local time.
  3401. * Originaly added for postscript
  3402. *
  3403. * History:
  3404. * 07-Feb-1996 -by- Eric Kutter [erick]
  3405. * Wrote it.
  3406. \**************************************************************************/
  3407. VOID EngQueryLocalTime( PENG_TIME_FIELDS ptf )
  3408. {
  3409. TIME_FIELDS tf;
  3410. LARGE_INTEGER li;
  3411. GreQuerySystemTime(&li);
  3412. GreSystemTimeToLocalTime(&li,&li);
  3413. RtlTimeToTimeFields(&li,&tf);
  3414. ptf->usYear = tf.Year;
  3415. ptf->usMonth = tf.Month;
  3416. ptf->usDay = tf.Day;
  3417. ptf->usHour = tf.Hour;
  3418. ptf->usMinute = tf.Minute;
  3419. ptf->usSecond = tf.Second;
  3420. ptf->usMilliseconds = tf.Milliseconds;
  3421. ptf->usWeekday = tf.Weekday;
  3422. }
  3423. /******************************Public*Routine******************************\
  3424. * BOOL GreGetBaseUFIBits(UNIVERSAL_FONT_ID *pufi, FONTFILEVIEW **ppfv)
  3425. *
  3426. * History:
  3427. * 17-Jan-1997 -by- Bodin Dresevic [BodinD]
  3428. * Wrote it.
  3429. \**************************************************************************/
  3430. BOOL GreGetBaseUFIBits(UNIVERSAL_FONT_ID *pufi, FONTFILEVIEW *pfv)
  3431. {
  3432. BOOL bRet = FALSE;
  3433. // base font is not an old fashioned type1 font
  3434. ASSERTGDI(!UFI_TYPE1_FONT(pufi), "Base MM Font is old fashioned device font\n");
  3435. // Stabilize the public PFT for mapping.
  3436. PUBLIC_PFTOBJ pfto(gpPFTPublic);
  3437. // base mm font will always be added to gpPFTPublic (not to gpPFTPrivate)
  3438. // on the print server machine (look at NtGdiAddRemoteFontsToDC).
  3439. // Therefore, we shall only look in the public table for it
  3440. PFE *ppfe = ppfeGetPFEFromUFI(pufi,
  3441. FALSE, // public
  3442. FALSE); // do not check the proccess id
  3443. if (!ppfe)
  3444. return bRet;
  3445. PFFOBJ pffo(ppfe->pPFF);
  3446. #if DBG
  3447. COUNT cNumFiles = pffo.cNumFiles();
  3448. ASSERTGDI(cNumFiles == 1, "GreGetBaseUFIBits cNumFiles != 1\n");
  3449. ASSERTGDI(!wcsncmp(pffo.pwszPathname(), L"REMOTE-", 7), "GreGetBaseUFIBits pathname != REMOTE\n");
  3450. #endif
  3451. // We need to copy this to a buffer since the PFFOBJ could go away after
  3452. // we release the semaphore. TRUE? Not really. The point is that ppfv is
  3453. // only going to be used during a print job while base font is added to DC.
  3454. // That is, only when DC goes away the base font will be removed so that this
  3455. // ppfv will be around for as long as is necessary to service its mm instances
  3456. // that are used in the same job.
  3457. *pfv = *(pffo.ppfvGet()[0]);
  3458. ASSERTGDI(pfv->SpoolerPid == W32GetCurrentPID() || gpidSpool == (PW32PROCESS)W32GetCurrentProcess(),
  3459. "GreGetBaseUFIBits, Pid doesn't match\n");
  3460. return TRUE;
  3461. }
  3462. /******************************Public*Routine******************************\
  3463. *
  3464. * NtGdiAddRemoteMMInstanceToDC(
  3465. *
  3466. * History:
  3467. * 17-Jan-1997 -by- Bodin Dresevic [BodinD]
  3468. * Wrote it.
  3469. \**************************************************************************/
  3470. BOOL NtGdiAddRemoteMMInstanceToDC(
  3471. HDC hdc,
  3472. DOWNLOADDESIGNVECTOR *pddv,
  3473. ULONG cjDDV
  3474. )
  3475. {
  3476. DOWNLOADDESIGNVECTOR ddv;
  3477. BOOL bRet = FALSE;
  3478. FONTFILEVIEW fv;
  3479. XDCOBJ dco(hdc);
  3480. if (!dco.bValid())
  3481. return bRet;
  3482. if (!dco.bDisplay() && (cjDDV <= sizeof(DOWNLOADDESIGNVECTOR)) )
  3483. {
  3484. __try
  3485. {
  3486. ProbeForRead(pddv,cjDDV, sizeof(BYTE));
  3487. RtlCopyMemory(&ddv, pddv, cjDDV);
  3488. }
  3489. __except(EXCEPTION_EXECUTE_HANDLER)
  3490. {
  3491. WARNING("GreAddRemoteMMInstanceToDC, bogus ddv\n");
  3492. }
  3493. // Now get the pointer to the bits of the base mm font.
  3494. // This will only work because the base font has already been installed
  3495. // on the print server. We always first write the bits for the base font
  3496. // to the spool file and then design vectors for all its instances.
  3497. // Consenquently, as we spool, the base font has already been added
  3498. // and its bits live in virtual memory window allocated by
  3499. // NtGdiAddRemoteFontToDC. We now just get the file view for the bits
  3500. if (GreGetBaseUFIBits(&ddv.ufiBase, &fv))
  3501. {
  3502. PUBLIC_PFTOBJ pfto;
  3503. UINT offset = ALIGN8(sizeof(FONTFILEVIEW*));
  3504. FONTFILEVIEW** ppfv = (FONTFILEVIEW**)
  3505. PALLOCMEM( sizeof(FONTFILEVIEW) + offset, 'vffG');
  3506. if (ppfv == NULL)
  3507. {
  3508. WARNING1("NtGdiAddRemoteMMInstanceToDC out of memory\n");
  3509. bRet = FALSE;
  3510. }
  3511. else
  3512. {
  3513. // CAUTION
  3514. //
  3515. // The PFF cleanup code has intimate knowledge of this
  3516. // code so be sure you synchronize changes in here and there.
  3517. //
  3518. // We are about to create a FONTFILEVIEW that corresponds to
  3519. // a pool image of a font downloaded for metafile printing.
  3520. // This case is signified by setting FONTFILEVIEW::pszPath
  3521. // to zero. This corresponds to a image loaded once.
  3522. ppfv[0] = (FONTFILEVIEW*)((BYTE *)ppfv + offset);
  3523. // the following line of code is crucial:
  3524. // since we set ulRegionSize to zero, the code
  3525. // which does unsecure mem will not be executed for instances
  3526. // but only for the base font. However, ppfv will be freed properly.
  3527. fv.ulRegionSize = 0;
  3528. // cRefCountFD should be set to or 1, what should it be?
  3529. // It turns out it does not matter because ulRegionSize
  3530. // is set to zero, so that unmap remote fonts is not called on
  3531. // pdv record, only on the base font.
  3532. fv.cRefCountFD = 0;
  3533. *(ppfv[0]) = fv;
  3534. bRet = pfto.bLoadRemoteFonts(dco, ppfv, 1, &ddv.dv, NULL);
  3535. }
  3536. }
  3537. }
  3538. else
  3539. {
  3540. WARNING("GreAddRemoteMMInstanceToDC bogus HDC,display DC, or cjDDV\n");
  3541. }
  3542. dco.vUnlockFast();
  3543. return (bRet);
  3544. }
  3545. /*************Public**Routine**************\
  3546. * BOOL GreUnmapMemFont
  3547. *
  3548. * History:
  3549. * Jul-03-97 Xudong Wu [TessieW]
  3550. * Wrote it
  3551. \*******************************************/
  3552. #if 0
  3553. BOOL GreUnmapMemFont(PVOID pvView)
  3554. {
  3555. NTSTATUS NtStatus;
  3556. NtStatus = MmUnmapViewOfSection(PsGetCurrentProcess(), (PVOID)((PBYTE)pvView - SZDLHEADER));
  3557. if (!NT_SUCCESS(NtStatus))
  3558. {
  3559. WARNING("Unmapping memory font's view in application's process space failed");
  3560. return FALSE;
  3561. }
  3562. return TRUE;
  3563. }
  3564. #endif