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.

851 lines
22 KiB

  1. /*++
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. umpd.cxx
  5. Abstract:
  6. User-mode printer driver support
  7. Environment:
  8. Windows NT 5.0
  9. Revision History:
  10. 07/8/97 -lingyunw-
  11. Created it.
  12. --*/
  13. #include "precomp.hxx"
  14. #if !defined(_GDIPLUS_)
  15. extern PFN gpUMDriverFunc[];
  16. static const ULONG aiFuncRequired[] =
  17. {
  18. INDEX_DrvEnablePDEV,
  19. INDEX_DrvCompletePDEV,
  20. INDEX_DrvDisablePDEV,
  21. };
  22. //
  23. // ()---()
  24. // / o o \
  25. // ___-( )-___
  26. // --------------(,,,----\_/----,,,)--------------------------------------
  27. // O
  28. //
  29. // BOOL UMPD_ldevFillTable
  30. // Fill the ldev function dispatch table for user mode printer drivers
  31. //
  32. // Returns
  33. // BOOLEAN
  34. //
  35. // History:
  36. // 7/17/97 -- Lingyun Wang [lingyunw] -- Wrote it.
  37. //
  38. // -----------------------------------------------------------------------
  39. // | |---| |
  40. // _-+ | | +-_
  41. // (,,,/ \,,,)
  42. UMPD_ldevFillTable(
  43. PLDEV pldev,
  44. BOOL * pbDrvFn)
  45. {
  46. //
  47. // Put the UMPD kernel stubs in the function table.
  48. //
  49. ULONG i;
  50. PFN *ppfnTable = pldev->apfn;
  51. BOOL bRet = TRUE;
  52. //
  53. // fill with zero pointers to avoid possibility of accessing
  54. // incorrect fields later
  55. //
  56. RtlZeroMemory(ppfnTable, INDEX_LAST*sizeof(PFN));
  57. //
  58. // Set UMPD thunk pointers in pldev->apfn.
  59. //
  60. for (i = 0; i < INDEX_LAST; i++)
  61. {
  62. if (pbDrvFn[i])
  63. {
  64. ppfnTable[i] = gpUMDriverFunc[i];
  65. }
  66. }
  67. if (bRet)
  68. {
  69. //
  70. // Check for required driver functions.
  71. //
  72. i = sizeof(aiFuncRequired) / sizeof(ULONG);
  73. while (i--)
  74. {
  75. if (ppfnTable[aiFuncRequired[i]] == (PFN) NULL)
  76. {
  77. ASSERTGDI(FALSE,"UMPDldevFillTable: a required function is missing from driver\n");
  78. return(FALSE);
  79. }
  80. }
  81. }
  82. //
  83. // Always hook up UMPDDRVFREE so we can free our kernel copies
  84. //
  85. ppfnTable[INDEX_DrvFree] = gpUMDriverFunc[INDEX_DrvFree];
  86. return(bRet);
  87. }
  88. //
  89. // ()---()
  90. // / o o \
  91. // ___-( )-___
  92. // --------------(,,,----\_/----,,,)--------------------------------------
  93. // O
  94. //
  95. // BOOL UMPD_ldevLoadDriver
  96. // User mode printer drivers load driver routine. Create a ldev and
  97. // fill up the function table.
  98. //
  99. // Returns
  100. // BOOLEAN
  101. //
  102. // History:
  103. // 7/17/97 -- Lingyun Wang [lingyunw] -- Wrote it.
  104. //
  105. // -----------------------------------------------------------------------
  106. // | |---| |
  107. // _-+ | | +-_
  108. // (,,,/ \,,,)
  109. PLDEV
  110. UMPD_ldevLoadDriver(
  111. LPWSTR pwszDriver,
  112. LDEVTYPE ldt)
  113. {
  114. PLDEV pldev;
  115. PFN *ppdrvfn;
  116. TRACE_INIT(("ldevLoadInternal ENTERING\n"));
  117. //
  118. // Allocate memory for the LDEV.
  119. //
  120. pldev = (PLDEV) EngAllocMem(FL_ZERO_MEMORY, sizeof(LDEV), UMPD_MEMORY_TAG);
  121. if (pldev)
  122. {
  123. //
  124. // Call the Enable entry point.
  125. //
  126. PVOID umpdCookie;
  127. BOOL bRet = FALSE;
  128. bRet = UMPDDrvEnableDriver (pwszDriver, &umpdCookie);
  129. if (bRet)
  130. {
  131. //
  132. // fill info and apfn into pldev
  133. //
  134. pldev->pldevNext = NULL;
  135. pldev->pldevPrev = NULL;
  136. pldev->ldevType = ldt;
  137. pldev->cldevRefs = 1;
  138. pldev->pGdiDriverInfo = NULL;
  139. pldev->umpdCookie = umpdCookie;
  140. pldev->pid = (PW32PROCESS)W32GetCurrentProcess();
  141. BOOL bDrvfn[INDEX_LAST];
  142. if(!UMPDDrvDriverFn(umpdCookie, bDrvfn))
  143. {
  144. WARNING("UMPD -- unable to get driver fn support\n");
  145. bRet = FALSE;
  146. }
  147. if(bRet)
  148. {
  149. bRet = UMPD_ldevFillTable(pldev, bDrvfn);
  150. }
  151. }
  152. if (!bRet)
  153. {
  154. EngFreeMem(pldev);
  155. pldev = NULL;
  156. }
  157. }
  158. return pldev;
  159. }
  160. PPORT_MESSAGE
  161. PROXYPORT::InitMsg(
  162. PPROXYMSG Msg,
  163. UM64_PVOID pvIn,
  164. ULONG cjIn,
  165. UM64_PVOID pvOut,
  166. ULONG cjOut
  167. )
  168. {
  169. Msg->h.u1.s1.DataLength = (short) (sizeof(*Msg) - sizeof(Msg->h));
  170. Msg->h.u1.s1.TotalLength = (short) (sizeof(*Msg));
  171. Msg->h.u2.ZeroInit = 0;
  172. if(pvOut == NULL) cjOut = 0;
  173. Msg->cjIn = cjIn;
  174. Msg->pvIn = pvIn;
  175. Msg->cjOut = cjOut;
  176. Msg->pvOut = pvOut;
  177. return( (PPORT_MESSAGE)Msg );
  178. }
  179. BOOL
  180. PROXYPORT::CheckMsg(
  181. NTSTATUS Status,
  182. PPROXYMSG Msg,
  183. UM64_PVOID pvOut,
  184. ULONG cjOut
  185. )
  186. {
  187. ULONG cbData = Msg->h.u1.s1.DataLength;
  188. if (cbData == (sizeof(*Msg) - sizeof(Msg->h)))
  189. {
  190. if(pvOut != Msg->pvOut)
  191. {
  192. return(FALSE);
  193. }
  194. if(cjOut != Msg->cjOut)
  195. {
  196. return(FALSE);
  197. }
  198. }
  199. else
  200. {
  201. return(FALSE);
  202. }
  203. return( TRUE );
  204. }
  205. NTSTATUS
  206. PROXYPORT::SendRequest(
  207. UM64_PVOID pvIn,
  208. ULONG cjIn,
  209. UM64_PVOID pvOut,
  210. ULONG cjOut
  211. )
  212. {
  213. NTSTATUS Status;
  214. PROXYMSG Request;
  215. PROXYMSG Reply;
  216. InitMsg( &Request, pvIn, cjIn, pvOut, cjOut );
  217. Status = ZwRequestWaitReplyPort( pp->PortHandle,
  218. (PPORT_MESSAGE)&Request,
  219. (PPORT_MESSAGE)&Reply
  220. );
  221. if (!NT_SUCCESS( Status ))
  222. {
  223. return( Status );
  224. }
  225. if (Reply.h.u2.s2.Type == LPC_REPLY)
  226. {
  227. if (!CheckMsg( Status, &Reply, pvOut, cjOut ))
  228. {
  229. return(STATUS_UNSUCCESSFUL);
  230. }
  231. }
  232. else
  233. {
  234. return(STATUS_UNSUCCESSFUL);
  235. }
  236. return( Status );
  237. }
  238. UM64_PVOID
  239. PROXYPORT::HeapAlloc(ULONG inSize)
  240. {
  241. SSIZE_T ptr;
  242. if(pp->ClientMemoryAllocSize + inSize > pp->ClientMemorySize)
  243. return NULL;
  244. ptr = pp->ClientMemoryBase + (SSIZE_T)pp->ClientMemoryAllocSize + pp->ServerMemoryDelta;
  245. pp->ClientMemoryAllocSize += inSize;
  246. return (UM64_PVOID)ptr;
  247. }
  248. PROXYPORT::PROXYPORT(ULONGLONG inMaxSize)
  249. {
  250. NTSTATUS Status;
  251. PORT_VIEW ClientView;
  252. ULONG MaxMessageLength;
  253. LARGE_INTEGER MaximumSize;
  254. UNICODE_STRING PortName;
  255. SECURITY_QUALITY_OF_SERVICE DynamicQos;
  256. PROCESS_SESSION_INFORMATION Info;
  257. WCHAR awcPortName[MAX_PATH] = {0};
  258. DWORD CurrSessionId;
  259. OBJECT_ATTRIBUTES ObjectAttributes;
  260. pp = NULL;
  261. if (NT_SUCCESS(Status = ZwQueryInformationProcess(NtCurrentProcess(),
  262. ProcessSessionInformation,
  263. &Info,
  264. sizeof(Info),
  265. NULL)))
  266. {
  267. CurrSessionId = Info.SessionId;
  268. swprintf(awcPortName, L"%s_%x",L"\\RPC Control\\UmpdProxy", CurrSessionId);
  269. DynamicQos.Length = 0;
  270. DynamicQos.ImpersonationLevel = SecurityImpersonation;
  271. DynamicQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
  272. DynamicQos.EffectiveOnly = TRUE;
  273. pp = (ProxyPort *) PALLOCMEM(sizeof(ProxyPort), 'tppG');
  274. if(pp != NULL)
  275. {
  276. pp->ClientMemoryBase = 0;
  277. pp->ClientMemorySize = 0;
  278. pp->ClientMemoryAllocSize = 0;
  279. pp->PortHandle = NULL;
  280. pp->ServerMemoryBase = 0;
  281. pp->ServerMemoryDelta = 0;
  282. pp->hSecure = 0;
  283. Status = STATUS_SUCCESS;
  284. RtlInitUnicodeString( &PortName, awcPortName );
  285. MaximumSize.QuadPart = inMaxSize;
  286. ClientView.SectionHandle = 0;
  287. InitializeObjectAttributes(&ObjectAttributes,
  288. 0,
  289. OBJ_KERNEL_HANDLE,
  290. 0,
  291. 0);
  292. Status = ZwCreateSection( &ClientView.SectionHandle,
  293. SECTION_MAP_READ | SECTION_MAP_WRITE,
  294. &ObjectAttributes,
  295. &MaximumSize,
  296. PAGE_READWRITE,
  297. SEC_COMMIT,
  298. NULL
  299. );
  300. if (NT_SUCCESS( Status ))
  301. {
  302. ClientView.Length = sizeof( ClientView );
  303. ClientView.SectionOffset = 0;
  304. ClientView.ViewSize = (LPC_SIZE_T) inMaxSize;
  305. ClientView.ViewBase = 0;
  306. ClientView.ViewRemoteBase = 0;
  307. Status = ZwConnectPort( &pp->PortHandle,
  308. &PortName,
  309. &DynamicQos,
  310. &ClientView,
  311. NULL,
  312. (PULONG)&MaxMessageLength,
  313. NULL,
  314. 0
  315. );
  316. if (NT_SUCCESS( Status ))
  317. {
  318. pp->hSecure = MmSecureVirtualMemory(ClientView.ViewBase, ClientView.ViewSize, PAGE_READWRITE);
  319. if (pp->hSecure)
  320. {
  321. pp->SectionHandle = ClientView.SectionHandle;
  322. pp->ClientMemoryBase = (SSIZE_T)ClientView.ViewBase;
  323. pp->ClientMemorySize = ClientView.ViewSize;
  324. pp->ServerMemoryBase = (SSIZE_T)ClientView.ViewRemoteBase;
  325. pp->ServerMemoryDelta = pp->ServerMemoryBase - pp->ClientMemoryBase;
  326. }
  327. }
  328. else
  329. {
  330. WARNING("PROXYPORT::PROXYPORT failed to connect lpc port\n");
  331. }
  332. }
  333. else
  334. {
  335. WARNING("PROXYPORT::PROXYPORT failed to create section\n");
  336. }
  337. if(!NT_SUCCESS( Status ) || pp->hSecure == 0)
  338. {
  339. if (ClientView.SectionHandle)
  340. {
  341. ZwClose(ClientView.SectionHandle);
  342. }
  343. if (pp->PortHandle)
  344. {
  345. ZwClose( pp->PortHandle );
  346. }
  347. VFREEMEM(pp);
  348. pp = NULL;
  349. }
  350. }
  351. }
  352. }
  353. VOID
  354. PROXYPORT::Close()
  355. {
  356. ASSERTGDI(pp->PortHandle, "PROXYPORT::Close() invalid port handle\n");
  357. ASSERTGDI(pp->SectionHandle, "PROXYPORT::Close() invalid shared section handle\n");
  358. ASSERTGDI(pp->hSecure, "PROXYPORT::Close() invalid hSecure handle\n");
  359. if (pp->hSecure)
  360. {
  361. MmUnsecureVirtualMemory(pp->hSecure);
  362. }
  363. if (pp->SectionHandle)
  364. {
  365. if (!ZwClose(pp->SectionHandle))
  366. {
  367. WARNING("ZwClose failed to close the shred section handle in PROXYPORT::Close\n");
  368. }
  369. }
  370. if (pp->PortHandle != NULL)
  371. {
  372. if (!ZwClose( pp->PortHandle ))
  373. {
  374. WARNING("ZwClose failed to close the lpc port handle in PROXYPORT::Close\n");
  375. }
  376. }
  377. VFREEMEM(pp);
  378. }
  379. /*
  380. BOOL UMPDReleaseRFONTSem()
  381. Used by umpd printing, releasing RFONT caching semaphores
  382. */
  383. BOOL UMPDReleaseRFONTSem(
  384. RFONTOBJ& rfo,
  385. PUMPDOBJ pumpdobj,
  386. ULONG* pfl,
  387. ULONG* pnumLinks,
  388. BOOL** ppFaceLink
  389. )
  390. {
  391. BOOL bUMPDOBJ, *pFaceLink = NULL;
  392. ULONG numLinks = 0;
  393. if (!rfo.bValid())
  394. return FALSE;
  395. if (pumpdobj && pfl == NULL && pnumLinks == NULL && ppFaceLink == NULL)
  396. {
  397. bUMPDOBJ = TRUE;
  398. }
  399. else if (pumpdobj == NULL && pfl && pnumLinks && ppFaceLink)
  400. {
  401. bUMPDOBJ = FALSE;
  402. *pfl = 0;
  403. *pnumLinks = 0;
  404. }
  405. else
  406. {
  407. ASSERTGDI(0, "UMPD_ReleaseRFONTSem: it neither umpdobj nor TextOutDrvBitBlt\n");
  408. return FALSE;
  409. }
  410. if (rfo.prfnt->hsemEUDC)
  411. {
  412. GreAcquireSemaphore(rfo.prfnt->hsemEUDC);
  413. if (rfo.prfnt->prfntSystemTT && rfo.prfnt->prfntSystemTT->hsemCache &&
  414. GreIsSemaphoreOwnedByCurrentThread(rfo.prfnt->prfntSystemTT->hsemCache))
  415. {
  416. GreReleaseSemaphore(rfo.prfnt->prfntSystemTT->hsemCache);
  417. if (bUMPDOBJ)
  418. pumpdobj->vSetFlags(RELEASE_SYSTTFONT);
  419. else
  420. *pfl |= RELEASE_SYSTTFONT;
  421. }
  422. if (rfo.prfnt->prfntSysEUDC && rfo.prfnt->prfntSysEUDC->hsemCache &&
  423. GreIsSemaphoreOwnedByCurrentThread(rfo.prfnt->prfntSysEUDC->hsemCache))
  424. {
  425. GreReleaseSemaphore(rfo.prfnt->prfntSysEUDC->hsemCache);
  426. if (bUMPDOBJ)
  427. pumpdobj->vSetFlags(RELEASE_SYSEUDCFONT);
  428. else
  429. *pfl |= RELEASE_SYSEUDCFONT;
  430. }
  431. if (rfo.prfnt->prfntDefEUDC && rfo.prfnt->prfntDefEUDC->hsemCache &&
  432. GreIsSemaphoreOwnedByCurrentThread(rfo.prfnt->prfntDefEUDC->hsemCache))
  433. {
  434. GreReleaseSemaphore(rfo.prfnt->prfntDefEUDC->hsemCache);
  435. if(bUMPDOBJ)
  436. pumpdobj->vSetFlags(RELEASE_DEFEUDCFONT);
  437. else
  438. *pfl |= RELEASE_DEFEUDCFONT;
  439. }
  440. if (numLinks = rfo.uiNumFaceNameLinks())
  441. {
  442. BOOL bContinue = FALSE;
  443. if (bUMPDOBJ)
  444. {
  445. bContinue = pumpdobj->bAllocFontLinks(numLinks);
  446. }
  447. else
  448. {
  449. pFaceLink = numLinks > UMPD_MAX_FONTFACELINK ?
  450. (BOOL*)PALLOCNOZ(sizeof(BOOL) * numLinks, UMPD_MEMORY_TAG) :
  451. *ppFaceLink;
  452. *ppFaceLink = pFaceLink;
  453. if (pFaceLink)
  454. {
  455. bContinue = TRUE;
  456. *pnumLinks = numLinks;
  457. RtlZeroMemory(pFaceLink, sizeof(BOOL) * numLinks);
  458. }
  459. }
  460. if (bContinue)
  461. {
  462. for(ULONG ii = 0; ii < numLinks; ii++)
  463. {
  464. if(rfo.prfnt->paprfntFaceName[ii] &&
  465. rfo.prfnt->paprfntFaceName[ii]->hsemCache &&
  466. GreIsSemaphoreOwnedByCurrentThread(rfo.prfnt->paprfntFaceName[ii]->hsemCache))
  467. {
  468. GreReleaseSemaphore(rfo.prfnt->paprfntFaceName[ii]->hsemCache);
  469. if (bUMPDOBJ)
  470. pumpdobj->vSetFontLink(ii);
  471. else
  472. pFaceLink[ii] = TRUE;
  473. }
  474. }
  475. }
  476. }
  477. GreReleaseSemaphore(rfo.prfnt->hsemEUDC);
  478. }
  479. if (rfo.prfnt->hsemCache != NULL &&
  480. GreIsSemaphoreOwnedByCurrentThread(rfo.prfnt->hsemCache))
  481. {
  482. GreReleaseSemaphore(rfo.prfnt->hsemCache);
  483. if (bUMPDOBJ)
  484. pumpdobj->vSetFlags(RELEASE_BASEFONT);
  485. else
  486. *pfl |= RELEASE_BASEFONT;
  487. }
  488. return TRUE;
  489. }
  490. /*
  491. VOID UMPDAcquireRFONTSem()
  492. Used by umpd printing, acquire all the RFONT caching semaphores.
  493. */
  494. VOID UMPDAcquireRFONTSem(
  495. RFONTOBJ& rfo,
  496. PUMPDOBJ pumpdobj,
  497. ULONG fl,
  498. ULONG numLinks,
  499. BOOL* pFaceLink
  500. )
  501. {
  502. BOOL bUMPDOBJ = FALSE;
  503. if (!rfo.bValid())
  504. return;
  505. if (pumpdobj)
  506. {
  507. bUMPDOBJ = TRUE;
  508. fl = pumpdobj->GetFlags();
  509. numLinks = pumpdobj->bLinkedFonts() ? pumpdobj->numLinkedFonts() : 0;
  510. }
  511. if ((fl & RELEASE_BASEFONT) && rfo.prfnt->hsemCache != NULL)
  512. {
  513. GreAcquireSemaphore(rfo.prfnt->hsemCache);
  514. if (bUMPDOBJ)
  515. pumpdobj->vClearFlags(RELEASE_BASEFONT);
  516. }
  517. if (rfo.prfnt->hsemEUDC)
  518. {
  519. GreAcquireSemaphore(rfo.prfnt->hsemEUDC);
  520. if ((fl & RELEASE_SYSTTFONT) && rfo.prfnt->prfntSystemTT)
  521. {
  522. GreAcquireSemaphore(rfo.prfnt->prfntSystemTT->hsemCache);
  523. if (bUMPDOBJ)
  524. pumpdobj->vClearFlags(RELEASE_SYSTTFONT);
  525. }
  526. if ((fl & RELEASE_SYSEUDCFONT) && rfo.prfnt->prfntSysEUDC)
  527. {
  528. GreAcquireSemaphore(rfo.prfnt->prfntSysEUDC->hsemCache);
  529. if (bUMPDOBJ)
  530. pumpdobj->vClearFlags(RELEASE_SYSEUDCFONT);
  531. }
  532. if ((fl & RELEASE_DEFEUDCFONT) && rfo.prfnt->prfntDefEUDC)
  533. {
  534. GreAcquireSemaphore(rfo.prfnt->prfntDefEUDC->hsemCache);
  535. if (bUMPDOBJ)
  536. pumpdobj->vClearFlags(RELEASE_DEFEUDCFONT);
  537. }
  538. if (numLinks)
  539. {
  540. BOOL bAcquire;
  541. numLinks =(numLinks > rfo.uiNumFaceNameLinks()) ? rfo.uiNumFaceNameLinks() : numLinks;
  542. for (ULONG ii = 0; ii < numLinks; ii++)
  543. {
  544. bAcquire = rfo.prfnt->paprfntFaceName[ii] &&
  545. (bUMPDOBJ ? pumpdobj->bLinkedFont(ii) : pFaceLink[ii]);
  546. if (bAcquire)
  547. {
  548. GreAcquireSemaphore(rfo.prfnt->paprfntFaceName[ii]->hsemCache);
  549. if (bUMPDOBJ)
  550. pumpdobj->vClearFontLink(ii);
  551. }
  552. }
  553. }
  554. GreReleaseSemaphore(rfo.prfnt->hsemEUDC);
  555. }
  556. }
  557. VOID TextOutBitBlt(
  558. SURFACE *pSurf,
  559. RFONTOBJ& rfo,
  560. SURFOBJ *psoSrc,
  561. SURFOBJ *psoMask,
  562. CLIPOBJ *pco,
  563. XLATEOBJ *pxlo,
  564. RECTL *prclTrg,
  565. POINTL *pptlSrc,
  566. POINTL *pptlMask,
  567. BRUSHOBJ *pbo,
  568. POINTL *pptlBrush,
  569. ROP4 rop4
  570. )
  571. {
  572. BOOL bSem = FALSE;
  573. ULONG fl = 0, numLinks = 0;
  574. BOOL aFaceLink[UMPD_MAX_FONTFACELINK], *pFaceLink = aFaceLink;
  575. //
  576. // Release rfont semaphores, otherwise holding rfont semaphores can
  577. // disable APC queue while calling to the user mode.
  578. //
  579. //
  580. // WINBUG #214225 tessiew 10-27-2000 Blackcomb: re-visit the RFONT.hsemCache acquiring/releasing issue
  581. // Need to revisit the font semaphore problem in Blackcomb
  582. // It seems that a thread doesn't need to hold the font caching semaphore
  583. // during the whole GreExtTextOutWLocked call.
  584. //
  585. PDEVOBJ po(pSurf->hdev());
  586. if (po.bPrinter() && po.bUMPD() && rfo.bValid())
  587. {
  588. bSem = UMPDReleaseRFONTSem(rfo, NULL, &fl, &numLinks, &pFaceLink);
  589. }
  590. // call driver BitBlt
  591. (*(pSurf->pfnBitBlt())) (pSurf->pSurfobj(),
  592. psoSrc,
  593. psoMask,
  594. pco,
  595. pxlo,
  596. prclTrg,
  597. pptlSrc,
  598. pptlMask,
  599. pbo,
  600. pptlBrush,
  601. rop4);
  602. // acquire the font semaphore(s)
  603. if (bSem)
  604. {
  605. UMPDAcquireRFONTSem(rfo, NULL, fl, numLinks, pFaceLink);
  606. if (pFaceLink && pFaceLink != aFaceLink)
  607. {
  608. VFREEMEM(pFaceLink);
  609. }
  610. }
  611. }
  612. BOOL GetETMFontManagement(
  613. RFONTOBJ& rfo,
  614. PDEVOBJ pdo,
  615. SURFOBJ *pso,
  616. FONTOBJ *pfo,
  617. ULONG iEsc,
  618. ULONG cjIn,
  619. PVOID pvIn,
  620. ULONG cjOut,
  621. PVOID pvOut
  622. )
  623. {
  624. BOOL bRet;
  625. BOOL bSem = FALSE;
  626. ULONG fl = 0, numLinks = 0;
  627. BOOL aFaceLink[UMPD_MAX_FONTFACELINK], *pFaceLink = aFaceLink;
  628. //
  629. // Release rfont semaphores, otherwise holding rfont semaphores can
  630. // disable APC queue while calling to the user mode.
  631. //
  632. //
  633. // WINBUG #214225 tessiew 10-27-2000 Blackcomb: re-visit the RFONT.hsemCache acquiring/releasing issue
  634. // Need to revisit the font semaphore problem in Blackcomb
  635. // It seems that a thread doesn't need to hold the font caching semaphore
  636. // during the whole GreExtTextOutWLocked call.
  637. if (pdo.bPrinter() && pdo.bUMPD() && rfo.bValid())
  638. {
  639. bSem = UMPDReleaseRFONTSem(rfo, NULL, &fl, &numLinks, &pFaceLink);
  640. }
  641. bRet = pdo.FontManagement(pso,
  642. pfo,
  643. iEsc,
  644. cjIn,
  645. pvIn,
  646. cjOut,
  647. pvOut);
  648. // acquire the font semaphore(s)
  649. if (bSem)
  650. {
  651. UMPDAcquireRFONTSem(rfo, NULL, fl, numLinks, pFaceLink);
  652. if (pFaceLink && pFaceLink != aFaceLink)
  653. {
  654. VFREEMEM(pFaceLink);
  655. }
  656. }
  657. return bRet;
  658. }
  659. #else // _GDIPLUS_
  660. extern "C" PUMPD UMPDDrvEnableDriver(PWSTR, ULONG);
  661. PLDEV
  662. UMPD_ldevLoadDriver(
  663. PWSTR pwszDriver,
  664. LDEVTYPE ldt
  665. )
  666. {
  667. PLDEV pldev = NULL;
  668. PUMPD pUMPD;
  669. if ((pUMPD = UMPDDrvEnableDriver(pwszDriver, DDI_DRIVER_VERSION_NT5_01_SP1)) &&
  670. (pldev = (PLDEV) PALLOCMEM(sizeof(LDEV), UMPD_MEMORY_TAG)))
  671. {
  672. pldev->pldevNext = (PLDEV)pUMPD;
  673. pldev->pldevPrev = NULL;
  674. pldev->ldevType = ldt;
  675. pldev->cldevRefs = 1;
  676. pldev->pGdiDriverInfo = NULL;
  677. RtlCopyMemory(pldev->apfn, pUMPD->apfn, sizeof(pldev->apfn));
  678. return pldev;
  679. }
  680. else
  681. {
  682. if (pldev)
  683. VFREEMEM(pldev);
  684. return NULL;
  685. }
  686. }
  687. #endif // _GDIPLUS_
  688. VOID UMPD_ldevUnloadImage(PLDEV pldev)
  689. {
  690. if (pldev)
  691. EngFreeMem(pldev);
  692. return;
  693. }