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
851 lines
22 KiB
/*++
|
|
|
|
Copyright (c) 1997-1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
umpd.cxx
|
|
|
|
Abstract:
|
|
|
|
User-mode printer driver support
|
|
|
|
Environment:
|
|
|
|
Windows NT 5.0
|
|
|
|
Revision History:
|
|
|
|
07/8/97 -lingyunw-
|
|
Created it.
|
|
|
|
|
|
--*/
|
|
|
|
#include "precomp.hxx"
|
|
|
|
|
|
#if !defined(_GDIPLUS_)
|
|
|
|
extern PFN gpUMDriverFunc[];
|
|
|
|
static const ULONG aiFuncRequired[] =
|
|
{
|
|
INDEX_DrvEnablePDEV,
|
|
INDEX_DrvCompletePDEV,
|
|
INDEX_DrvDisablePDEV,
|
|
};
|
|
|
|
|
|
//
|
|
// ()---()
|
|
// / o o \
|
|
// ___-( )-___
|
|
// --------------(,,,----\_/----,,,)--------------------------------------
|
|
// O
|
|
//
|
|
// BOOL UMPD_ldevFillTable
|
|
// Fill the ldev function dispatch table for user mode printer drivers
|
|
//
|
|
// Returns
|
|
// BOOLEAN
|
|
//
|
|
// History:
|
|
// 7/17/97 -- Lingyun Wang [lingyunw] -- Wrote it.
|
|
//
|
|
// -----------------------------------------------------------------------
|
|
// | |---| |
|
|
// _-+ | | +-_
|
|
// (,,,/ \,,,)
|
|
|
|
UMPD_ldevFillTable(
|
|
PLDEV pldev,
|
|
BOOL * pbDrvFn)
|
|
{
|
|
//
|
|
// Put the UMPD kernel stubs in the function table.
|
|
//
|
|
|
|
ULONG i;
|
|
PFN *ppfnTable = pldev->apfn;
|
|
BOOL bRet = TRUE;
|
|
|
|
//
|
|
// fill with zero pointers to avoid possibility of accessing
|
|
// incorrect fields later
|
|
//
|
|
|
|
RtlZeroMemory(ppfnTable, INDEX_LAST*sizeof(PFN));
|
|
|
|
//
|
|
// Set UMPD thunk pointers in pldev->apfn.
|
|
//
|
|
|
|
for (i = 0; i < INDEX_LAST; i++)
|
|
{
|
|
if (pbDrvFn[i])
|
|
{
|
|
ppfnTable[i] = gpUMDriverFunc[i];
|
|
}
|
|
}
|
|
|
|
if (bRet)
|
|
{
|
|
//
|
|
// Check for required driver functions.
|
|
//
|
|
|
|
i = sizeof(aiFuncRequired) / sizeof(ULONG);
|
|
while (i--)
|
|
{
|
|
if (ppfnTable[aiFuncRequired[i]] == (PFN) NULL)
|
|
{
|
|
ASSERTGDI(FALSE,"UMPDldevFillTable: a required function is missing from driver\n");
|
|
return(FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Always hook up UMPDDRVFREE so we can free our kernel copies
|
|
//
|
|
ppfnTable[INDEX_DrvFree] = gpUMDriverFunc[INDEX_DrvFree];
|
|
|
|
return(bRet);
|
|
}
|
|
|
|
//
|
|
// ()---()
|
|
// / o o \
|
|
// ___-( )-___
|
|
// --------------(,,,----\_/----,,,)--------------------------------------
|
|
// O
|
|
//
|
|
// BOOL UMPD_ldevLoadDriver
|
|
// User mode printer drivers load driver routine. Create a ldev and
|
|
// fill up the function table.
|
|
//
|
|
// Returns
|
|
// BOOLEAN
|
|
//
|
|
// History:
|
|
// 7/17/97 -- Lingyun Wang [lingyunw] -- Wrote it.
|
|
//
|
|
// -----------------------------------------------------------------------
|
|
// | |---| |
|
|
// _-+ | | +-_
|
|
// (,,,/ \,,,)
|
|
|
|
PLDEV
|
|
UMPD_ldevLoadDriver(
|
|
LPWSTR pwszDriver,
|
|
LDEVTYPE ldt)
|
|
{
|
|
PLDEV pldev;
|
|
PFN *ppdrvfn;
|
|
|
|
TRACE_INIT(("ldevLoadInternal ENTERING\n"));
|
|
|
|
//
|
|
// Allocate memory for the LDEV.
|
|
//
|
|
|
|
pldev = (PLDEV) EngAllocMem(FL_ZERO_MEMORY, sizeof(LDEV), UMPD_MEMORY_TAG);
|
|
|
|
if (pldev)
|
|
{
|
|
//
|
|
// Call the Enable entry point.
|
|
//
|
|
PVOID umpdCookie;
|
|
BOOL bRet = FALSE;
|
|
|
|
bRet = UMPDDrvEnableDriver (pwszDriver, &umpdCookie);
|
|
|
|
if (bRet)
|
|
{
|
|
//
|
|
// fill info and apfn into pldev
|
|
//
|
|
pldev->pldevNext = NULL;
|
|
pldev->pldevPrev = NULL;
|
|
pldev->ldevType = ldt;
|
|
pldev->cldevRefs = 1;
|
|
pldev->pGdiDriverInfo = NULL;
|
|
pldev->umpdCookie = umpdCookie;
|
|
pldev->pid = (PW32PROCESS)W32GetCurrentProcess();
|
|
|
|
BOOL bDrvfn[INDEX_LAST];
|
|
|
|
if(!UMPDDrvDriverFn(umpdCookie, bDrvfn))
|
|
{
|
|
WARNING("UMPD -- unable to get driver fn support\n");
|
|
bRet = FALSE;
|
|
}
|
|
|
|
if(bRet)
|
|
{
|
|
bRet = UMPD_ldevFillTable(pldev, bDrvfn);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
if (!bRet)
|
|
{
|
|
EngFreeMem(pldev);
|
|
pldev = NULL;
|
|
}
|
|
}
|
|
|
|
return pldev;
|
|
}
|
|
|
|
PPORT_MESSAGE
|
|
PROXYPORT::InitMsg(
|
|
PPROXYMSG Msg,
|
|
UM64_PVOID pvIn,
|
|
ULONG cjIn,
|
|
UM64_PVOID pvOut,
|
|
ULONG cjOut
|
|
)
|
|
{
|
|
Msg->h.u1.s1.DataLength = (short) (sizeof(*Msg) - sizeof(Msg->h));
|
|
Msg->h.u1.s1.TotalLength = (short) (sizeof(*Msg));
|
|
|
|
Msg->h.u2.ZeroInit = 0;
|
|
|
|
if(pvOut == NULL) cjOut = 0;
|
|
|
|
Msg->cjIn = cjIn;
|
|
Msg->pvIn = pvIn;
|
|
|
|
Msg->cjOut = cjOut;
|
|
Msg->pvOut = pvOut;
|
|
|
|
return( (PPORT_MESSAGE)Msg );
|
|
}
|
|
|
|
BOOL
|
|
PROXYPORT::CheckMsg(
|
|
NTSTATUS Status,
|
|
PPROXYMSG Msg,
|
|
UM64_PVOID pvOut,
|
|
ULONG cjOut
|
|
)
|
|
{
|
|
ULONG cbData = Msg->h.u1.s1.DataLength;
|
|
|
|
if (cbData == (sizeof(*Msg) - sizeof(Msg->h)))
|
|
{
|
|
if(pvOut != Msg->pvOut)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
if(cjOut != Msg->cjOut)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
NTSTATUS
|
|
PROXYPORT::SendRequest(
|
|
UM64_PVOID pvIn,
|
|
ULONG cjIn,
|
|
UM64_PVOID pvOut,
|
|
ULONG cjOut
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
PROXYMSG Request;
|
|
PROXYMSG Reply;
|
|
|
|
InitMsg( &Request, pvIn, cjIn, pvOut, cjOut );
|
|
|
|
Status = ZwRequestWaitReplyPort( pp->PortHandle,
|
|
(PPORT_MESSAGE)&Request,
|
|
(PPORT_MESSAGE)&Reply
|
|
);
|
|
|
|
if (!NT_SUCCESS( Status ))
|
|
{
|
|
return( Status );
|
|
}
|
|
|
|
if (Reply.h.u2.s2.Type == LPC_REPLY)
|
|
{
|
|
if (!CheckMsg( Status, &Reply, pvOut, cjOut ))
|
|
{
|
|
return(STATUS_UNSUCCESSFUL);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return(STATUS_UNSUCCESSFUL);
|
|
}
|
|
|
|
return( Status );
|
|
}
|
|
|
|
UM64_PVOID
|
|
PROXYPORT::HeapAlloc(ULONG inSize)
|
|
{
|
|
SSIZE_T ptr;
|
|
|
|
if(pp->ClientMemoryAllocSize + inSize > pp->ClientMemorySize)
|
|
return NULL;
|
|
|
|
ptr = pp->ClientMemoryBase + (SSIZE_T)pp->ClientMemoryAllocSize + pp->ServerMemoryDelta;
|
|
|
|
pp->ClientMemoryAllocSize += inSize;
|
|
|
|
return (UM64_PVOID)ptr;
|
|
}
|
|
|
|
|
|
PROXYPORT::PROXYPORT(ULONGLONG inMaxSize)
|
|
{
|
|
NTSTATUS Status;
|
|
PORT_VIEW ClientView;
|
|
ULONG MaxMessageLength;
|
|
LARGE_INTEGER MaximumSize;
|
|
UNICODE_STRING PortName;
|
|
SECURITY_QUALITY_OF_SERVICE DynamicQos;
|
|
PROCESS_SESSION_INFORMATION Info;
|
|
WCHAR awcPortName[MAX_PATH] = {0};
|
|
DWORD CurrSessionId;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
pp = NULL;
|
|
|
|
if (NT_SUCCESS(Status = ZwQueryInformationProcess(NtCurrentProcess(),
|
|
ProcessSessionInformation,
|
|
&Info,
|
|
sizeof(Info),
|
|
NULL)))
|
|
{
|
|
CurrSessionId = Info.SessionId;
|
|
swprintf(awcPortName, L"%s_%x",L"\\RPC Control\\UmpdProxy", CurrSessionId);
|
|
|
|
DynamicQos.Length = 0;
|
|
DynamicQos.ImpersonationLevel = SecurityImpersonation;
|
|
DynamicQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
|
|
DynamicQos.EffectiveOnly = TRUE;
|
|
|
|
pp = (ProxyPort *) PALLOCMEM(sizeof(ProxyPort), 'tppG');
|
|
|
|
if(pp != NULL)
|
|
{
|
|
pp->ClientMemoryBase = 0;
|
|
pp->ClientMemorySize = 0;
|
|
pp->ClientMemoryAllocSize = 0;
|
|
pp->PortHandle = NULL;
|
|
pp->ServerMemoryBase = 0;
|
|
pp->ServerMemoryDelta = 0;
|
|
pp->hSecure = 0;
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
RtlInitUnicodeString( &PortName, awcPortName );
|
|
|
|
MaximumSize.QuadPart = inMaxSize;
|
|
ClientView.SectionHandle = 0;
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
0,
|
|
OBJ_KERNEL_HANDLE,
|
|
0,
|
|
0);
|
|
|
|
Status = ZwCreateSection( &ClientView.SectionHandle,
|
|
SECTION_MAP_READ | SECTION_MAP_WRITE,
|
|
&ObjectAttributes,
|
|
&MaximumSize,
|
|
PAGE_READWRITE,
|
|
SEC_COMMIT,
|
|
NULL
|
|
);
|
|
|
|
if (NT_SUCCESS( Status ))
|
|
{
|
|
ClientView.Length = sizeof( ClientView );
|
|
ClientView.SectionOffset = 0;
|
|
ClientView.ViewSize = (LPC_SIZE_T) inMaxSize;
|
|
ClientView.ViewBase = 0;
|
|
ClientView.ViewRemoteBase = 0;
|
|
|
|
Status = ZwConnectPort( &pp->PortHandle,
|
|
&PortName,
|
|
&DynamicQos,
|
|
&ClientView,
|
|
NULL,
|
|
(PULONG)&MaxMessageLength,
|
|
NULL,
|
|
0
|
|
);
|
|
|
|
if (NT_SUCCESS( Status ))
|
|
{
|
|
|
|
pp->hSecure = MmSecureVirtualMemory(ClientView.ViewBase, ClientView.ViewSize, PAGE_READWRITE);
|
|
|
|
if (pp->hSecure)
|
|
{
|
|
pp->SectionHandle = ClientView.SectionHandle;
|
|
pp->ClientMemoryBase = (SSIZE_T)ClientView.ViewBase;
|
|
pp->ClientMemorySize = ClientView.ViewSize;
|
|
pp->ServerMemoryBase = (SSIZE_T)ClientView.ViewRemoteBase;
|
|
pp->ServerMemoryDelta = pp->ServerMemoryBase - pp->ClientMemoryBase;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
WARNING("PROXYPORT::PROXYPORT failed to connect lpc port\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WARNING("PROXYPORT::PROXYPORT failed to create section\n");
|
|
}
|
|
|
|
if(!NT_SUCCESS( Status ) || pp->hSecure == 0)
|
|
{
|
|
if (ClientView.SectionHandle)
|
|
{
|
|
ZwClose(ClientView.SectionHandle);
|
|
}
|
|
|
|
if (pp->PortHandle)
|
|
{
|
|
ZwClose( pp->PortHandle );
|
|
}
|
|
|
|
VFREEMEM(pp);
|
|
pp = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
VOID
|
|
PROXYPORT::Close()
|
|
{
|
|
ASSERTGDI(pp->PortHandle, "PROXYPORT::Close() invalid port handle\n");
|
|
ASSERTGDI(pp->SectionHandle, "PROXYPORT::Close() invalid shared section handle\n");
|
|
ASSERTGDI(pp->hSecure, "PROXYPORT::Close() invalid hSecure handle\n");
|
|
|
|
if (pp->hSecure)
|
|
{
|
|
MmUnsecureVirtualMemory(pp->hSecure);
|
|
}
|
|
|
|
if (pp->SectionHandle)
|
|
{
|
|
if (!ZwClose(pp->SectionHandle))
|
|
{
|
|
WARNING("ZwClose failed to close the shred section handle in PROXYPORT::Close\n");
|
|
}
|
|
}
|
|
|
|
if (pp->PortHandle != NULL)
|
|
{
|
|
if (!ZwClose( pp->PortHandle ))
|
|
{
|
|
WARNING("ZwClose failed to close the lpc port handle in PROXYPORT::Close\n");
|
|
}
|
|
}
|
|
|
|
VFREEMEM(pp);
|
|
}
|
|
|
|
/*
|
|
BOOL UMPDReleaseRFONTSem()
|
|
Used by umpd printing, releasing RFONT caching semaphores
|
|
*/
|
|
|
|
BOOL UMPDReleaseRFONTSem(
|
|
RFONTOBJ& rfo,
|
|
PUMPDOBJ pumpdobj,
|
|
ULONG* pfl,
|
|
ULONG* pnumLinks,
|
|
BOOL** ppFaceLink
|
|
)
|
|
{
|
|
BOOL bUMPDOBJ, *pFaceLink = NULL;
|
|
ULONG numLinks = 0;
|
|
|
|
if (!rfo.bValid())
|
|
return FALSE;
|
|
|
|
if (pumpdobj && pfl == NULL && pnumLinks == NULL && ppFaceLink == NULL)
|
|
{
|
|
bUMPDOBJ = TRUE;
|
|
}
|
|
else if (pumpdobj == NULL && pfl && pnumLinks && ppFaceLink)
|
|
{
|
|
bUMPDOBJ = FALSE;
|
|
*pfl = 0;
|
|
*pnumLinks = 0;
|
|
}
|
|
else
|
|
{
|
|
ASSERTGDI(0, "UMPD_ReleaseRFONTSem: it neither umpdobj nor TextOutDrvBitBlt\n");
|
|
return FALSE;
|
|
}
|
|
|
|
if (rfo.prfnt->hsemEUDC)
|
|
{
|
|
GreAcquireSemaphore(rfo.prfnt->hsemEUDC);
|
|
|
|
if (rfo.prfnt->prfntSystemTT && rfo.prfnt->prfntSystemTT->hsemCache &&
|
|
GreIsSemaphoreOwnedByCurrentThread(rfo.prfnt->prfntSystemTT->hsemCache))
|
|
{
|
|
GreReleaseSemaphore(rfo.prfnt->prfntSystemTT->hsemCache);
|
|
|
|
if (bUMPDOBJ)
|
|
pumpdobj->vSetFlags(RELEASE_SYSTTFONT);
|
|
else
|
|
*pfl |= RELEASE_SYSTTFONT;
|
|
}
|
|
|
|
if (rfo.prfnt->prfntSysEUDC && rfo.prfnt->prfntSysEUDC->hsemCache &&
|
|
GreIsSemaphoreOwnedByCurrentThread(rfo.prfnt->prfntSysEUDC->hsemCache))
|
|
{
|
|
GreReleaseSemaphore(rfo.prfnt->prfntSysEUDC->hsemCache);
|
|
|
|
if (bUMPDOBJ)
|
|
pumpdobj->vSetFlags(RELEASE_SYSEUDCFONT);
|
|
else
|
|
*pfl |= RELEASE_SYSEUDCFONT;
|
|
}
|
|
|
|
if (rfo.prfnt->prfntDefEUDC && rfo.prfnt->prfntDefEUDC->hsemCache &&
|
|
GreIsSemaphoreOwnedByCurrentThread(rfo.prfnt->prfntDefEUDC->hsemCache))
|
|
{
|
|
GreReleaseSemaphore(rfo.prfnt->prfntDefEUDC->hsemCache);
|
|
|
|
if(bUMPDOBJ)
|
|
pumpdobj->vSetFlags(RELEASE_DEFEUDCFONT);
|
|
else
|
|
*pfl |= RELEASE_DEFEUDCFONT;
|
|
}
|
|
|
|
if (numLinks = rfo.uiNumFaceNameLinks())
|
|
{
|
|
BOOL bContinue = FALSE;
|
|
|
|
if (bUMPDOBJ)
|
|
{
|
|
bContinue = pumpdobj->bAllocFontLinks(numLinks);
|
|
}
|
|
else
|
|
{
|
|
pFaceLink = numLinks > UMPD_MAX_FONTFACELINK ?
|
|
(BOOL*)PALLOCNOZ(sizeof(BOOL) * numLinks, UMPD_MEMORY_TAG) :
|
|
*ppFaceLink;
|
|
*ppFaceLink = pFaceLink;
|
|
|
|
if (pFaceLink)
|
|
{
|
|
bContinue = TRUE;
|
|
*pnumLinks = numLinks;
|
|
RtlZeroMemory(pFaceLink, sizeof(BOOL) * numLinks);
|
|
}
|
|
}
|
|
|
|
if (bContinue)
|
|
{
|
|
for(ULONG ii = 0; ii < numLinks; ii++)
|
|
{
|
|
if(rfo.prfnt->paprfntFaceName[ii] &&
|
|
rfo.prfnt->paprfntFaceName[ii]->hsemCache &&
|
|
GreIsSemaphoreOwnedByCurrentThread(rfo.prfnt->paprfntFaceName[ii]->hsemCache))
|
|
{
|
|
GreReleaseSemaphore(rfo.prfnt->paprfntFaceName[ii]->hsemCache);
|
|
|
|
if (bUMPDOBJ)
|
|
pumpdobj->vSetFontLink(ii);
|
|
else
|
|
pFaceLink[ii] = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
GreReleaseSemaphore(rfo.prfnt->hsemEUDC);
|
|
}
|
|
|
|
if (rfo.prfnt->hsemCache != NULL &&
|
|
GreIsSemaphoreOwnedByCurrentThread(rfo.prfnt->hsemCache))
|
|
{
|
|
GreReleaseSemaphore(rfo.prfnt->hsemCache);
|
|
|
|
if (bUMPDOBJ)
|
|
pumpdobj->vSetFlags(RELEASE_BASEFONT);
|
|
else
|
|
*pfl |= RELEASE_BASEFONT;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
VOID UMPDAcquireRFONTSem()
|
|
Used by umpd printing, acquire all the RFONT caching semaphores.
|
|
*/
|
|
|
|
VOID UMPDAcquireRFONTSem(
|
|
RFONTOBJ& rfo,
|
|
PUMPDOBJ pumpdobj,
|
|
ULONG fl,
|
|
ULONG numLinks,
|
|
BOOL* pFaceLink
|
|
)
|
|
{
|
|
BOOL bUMPDOBJ = FALSE;
|
|
|
|
if (!rfo.bValid())
|
|
return;
|
|
|
|
if (pumpdobj)
|
|
{
|
|
bUMPDOBJ = TRUE;
|
|
fl = pumpdobj->GetFlags();
|
|
numLinks = pumpdobj->bLinkedFonts() ? pumpdobj->numLinkedFonts() : 0;
|
|
}
|
|
|
|
if ((fl & RELEASE_BASEFONT) && rfo.prfnt->hsemCache != NULL)
|
|
{
|
|
GreAcquireSemaphore(rfo.prfnt->hsemCache);
|
|
if (bUMPDOBJ)
|
|
pumpdobj->vClearFlags(RELEASE_BASEFONT);
|
|
}
|
|
|
|
if (rfo.prfnt->hsemEUDC)
|
|
{
|
|
GreAcquireSemaphore(rfo.prfnt->hsemEUDC);
|
|
|
|
if ((fl & RELEASE_SYSTTFONT) && rfo.prfnt->prfntSystemTT)
|
|
{
|
|
GreAcquireSemaphore(rfo.prfnt->prfntSystemTT->hsemCache);
|
|
if (bUMPDOBJ)
|
|
pumpdobj->vClearFlags(RELEASE_SYSTTFONT);
|
|
}
|
|
|
|
if ((fl & RELEASE_SYSEUDCFONT) && rfo.prfnt->prfntSysEUDC)
|
|
{
|
|
GreAcquireSemaphore(rfo.prfnt->prfntSysEUDC->hsemCache);
|
|
if (bUMPDOBJ)
|
|
pumpdobj->vClearFlags(RELEASE_SYSEUDCFONT);
|
|
}
|
|
|
|
if ((fl & RELEASE_DEFEUDCFONT) && rfo.prfnt->prfntDefEUDC)
|
|
{
|
|
GreAcquireSemaphore(rfo.prfnt->prfntDefEUDC->hsemCache);
|
|
if (bUMPDOBJ)
|
|
pumpdobj->vClearFlags(RELEASE_DEFEUDCFONT);
|
|
}
|
|
|
|
if (numLinks)
|
|
{
|
|
BOOL bAcquire;
|
|
|
|
numLinks =(numLinks > rfo.uiNumFaceNameLinks()) ? rfo.uiNumFaceNameLinks() : numLinks;
|
|
|
|
for (ULONG ii = 0; ii < numLinks; ii++)
|
|
{
|
|
bAcquire = rfo.prfnt->paprfntFaceName[ii] &&
|
|
(bUMPDOBJ ? pumpdobj->bLinkedFont(ii) : pFaceLink[ii]);
|
|
|
|
if (bAcquire)
|
|
{
|
|
GreAcquireSemaphore(rfo.prfnt->paprfntFaceName[ii]->hsemCache);
|
|
if (bUMPDOBJ)
|
|
pumpdobj->vClearFontLink(ii);
|
|
}
|
|
}
|
|
}
|
|
|
|
GreReleaseSemaphore(rfo.prfnt->hsemEUDC);
|
|
}
|
|
}
|
|
|
|
|
|
VOID TextOutBitBlt(
|
|
SURFACE *pSurf,
|
|
RFONTOBJ& rfo,
|
|
SURFOBJ *psoSrc,
|
|
SURFOBJ *psoMask,
|
|
CLIPOBJ *pco,
|
|
XLATEOBJ *pxlo,
|
|
RECTL *prclTrg,
|
|
POINTL *pptlSrc,
|
|
POINTL *pptlMask,
|
|
BRUSHOBJ *pbo,
|
|
POINTL *pptlBrush,
|
|
ROP4 rop4
|
|
)
|
|
{
|
|
BOOL bSem = FALSE;
|
|
ULONG fl = 0, numLinks = 0;
|
|
BOOL aFaceLink[UMPD_MAX_FONTFACELINK], *pFaceLink = aFaceLink;
|
|
|
|
//
|
|
// Release rfont semaphores, otherwise holding rfont semaphores can
|
|
// disable APC queue while calling to the user mode.
|
|
//
|
|
|
|
//
|
|
// WINBUG #214225 tessiew 10-27-2000 Blackcomb: re-visit the RFONT.hsemCache acquiring/releasing issue
|
|
// Need to revisit the font semaphore problem in Blackcomb
|
|
// It seems that a thread doesn't need to hold the font caching semaphore
|
|
// during the whole GreExtTextOutWLocked call.
|
|
//
|
|
|
|
PDEVOBJ po(pSurf->hdev());
|
|
|
|
if (po.bPrinter() && po.bUMPD() && rfo.bValid())
|
|
{
|
|
bSem = UMPDReleaseRFONTSem(rfo, NULL, &fl, &numLinks, &pFaceLink);
|
|
}
|
|
|
|
// call driver BitBlt
|
|
|
|
(*(pSurf->pfnBitBlt())) (pSurf->pSurfobj(),
|
|
psoSrc,
|
|
psoMask,
|
|
pco,
|
|
pxlo,
|
|
prclTrg,
|
|
pptlSrc,
|
|
pptlMask,
|
|
pbo,
|
|
pptlBrush,
|
|
rop4);
|
|
|
|
// acquire the font semaphore(s)
|
|
|
|
if (bSem)
|
|
{
|
|
UMPDAcquireRFONTSem(rfo, NULL, fl, numLinks, pFaceLink);
|
|
|
|
if (pFaceLink && pFaceLink != aFaceLink)
|
|
{
|
|
VFREEMEM(pFaceLink);
|
|
}
|
|
}
|
|
}
|
|
|
|
BOOL GetETMFontManagement(
|
|
RFONTOBJ& rfo,
|
|
PDEVOBJ pdo,
|
|
SURFOBJ *pso,
|
|
FONTOBJ *pfo,
|
|
ULONG iEsc,
|
|
ULONG cjIn,
|
|
PVOID pvIn,
|
|
ULONG cjOut,
|
|
PVOID pvOut
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
BOOL bSem = FALSE;
|
|
|
|
ULONG fl = 0, numLinks = 0;
|
|
BOOL aFaceLink[UMPD_MAX_FONTFACELINK], *pFaceLink = aFaceLink;
|
|
|
|
//
|
|
// Release rfont semaphores, otherwise holding rfont semaphores can
|
|
// disable APC queue while calling to the user mode.
|
|
//
|
|
|
|
//
|
|
// WINBUG #214225 tessiew 10-27-2000 Blackcomb: re-visit the RFONT.hsemCache acquiring/releasing issue
|
|
// Need to revisit the font semaphore problem in Blackcomb
|
|
// It seems that a thread doesn't need to hold the font caching semaphore
|
|
// during the whole GreExtTextOutWLocked call.
|
|
|
|
if (pdo.bPrinter() && pdo.bUMPD() && rfo.bValid())
|
|
{
|
|
bSem = UMPDReleaseRFONTSem(rfo, NULL, &fl, &numLinks, &pFaceLink);
|
|
}
|
|
|
|
bRet = pdo.FontManagement(pso,
|
|
pfo,
|
|
iEsc,
|
|
cjIn,
|
|
pvIn,
|
|
cjOut,
|
|
pvOut);
|
|
|
|
// acquire the font semaphore(s)
|
|
|
|
if (bSem)
|
|
{
|
|
UMPDAcquireRFONTSem(rfo, NULL, fl, numLinks, pFaceLink);
|
|
|
|
if (pFaceLink && pFaceLink != aFaceLink)
|
|
{
|
|
VFREEMEM(pFaceLink);
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
#else // _GDIPLUS_
|
|
|
|
extern "C" PUMPD UMPDDrvEnableDriver(PWSTR, ULONG);
|
|
|
|
PLDEV
|
|
UMPD_ldevLoadDriver(
|
|
PWSTR pwszDriver,
|
|
LDEVTYPE ldt
|
|
)
|
|
|
|
{
|
|
PLDEV pldev = NULL;
|
|
PUMPD pUMPD;
|
|
|
|
if ((pUMPD = UMPDDrvEnableDriver(pwszDriver, DDI_DRIVER_VERSION_NT5_01_SP1)) &&
|
|
(pldev = (PLDEV) PALLOCMEM(sizeof(LDEV), UMPD_MEMORY_TAG)))
|
|
{
|
|
pldev->pldevNext = (PLDEV)pUMPD;
|
|
pldev->pldevPrev = NULL;
|
|
pldev->ldevType = ldt;
|
|
pldev->cldevRefs = 1;
|
|
pldev->pGdiDriverInfo = NULL;
|
|
|
|
RtlCopyMemory(pldev->apfn, pUMPD->apfn, sizeof(pldev->apfn));
|
|
|
|
return pldev;
|
|
}
|
|
else
|
|
{
|
|
if (pldev)
|
|
VFREEMEM(pldev);
|
|
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
#endif // _GDIPLUS_
|
|
|
|
|
|
VOID UMPD_ldevUnloadImage(PLDEV pldev)
|
|
{
|
|
if (pldev)
|
|
EngFreeMem(pldev);
|
|
|
|
return;
|
|
}
|
|
|