|
|
/*++
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.
09/17/97 -davidx- Clean up km-um thunking.
--*/
#include "umpd.h"
//
// LPC
//
#ifdef __cplusplus
extern "C" { #endif
typedef struct ProxyPort { HANDLE PortHandle; HANDLE SectionHandle; SSIZE_T ClientMemoryBase; SIZE_T ClientMemorySize; SSIZE_T ServerMemoryBase; SSIZE_T ServerMemoryDelta; ULONG ClientMemoryAllocSize; HANDLE hSecure; } ProxyPort;
typedef KERNEL_PVOID UM64_PVOID; typedef ULONG SERVEROFF;
typedef struct _PROXYMSG { PORT_MESSAGE h; ULONG cjIn; UM64_PVOID pvIn; ULONG cjOut; UM64_PVOID pvOut; } PROXYMSG, *PPROXYMSG;
#ifdef __cplusplus
} // extern "C"
#endif
#define UMPD_MAX_FONTFACELINK 10
class PROXYPORT { private: ProxyPort *pp;
public: PROXYPORT (ProxyPort* pIn) { pp = pIn; } PROXYPORT (ULONGLONG inMaxSize); ~PROXYPORT () {} BOOL bValid() { return (pp != NULL); } ProxyPort* GetProxyPort() { return (pp); } VOID HeapInit() { pp->ClientMemoryAllocSize = 0; }
UM64_PVOID HeapAlloc(ULONG inSize); KERNEL_PVOID GetKernelPtr(UM64_PVOID pv) { return (KERNEL_PVOID) (pv ? ((PBYTE) pv - pp->ServerMemoryDelta) : NULL); } PPORT_MESSAGE InitMsg(PPROXYMSG Msg, UM64_PVOID pvIn, ULONG cjIn, UM64_PVOID pvOut, ULONG cjOut);
BOOL CheckMsg(NTSTATUS Status, PPROXYMSG Msg, UM64_PVOID pvOut, ULONG cjOut); NTSTATUS SendRequest(UM64_PVOID pvIn, ULONG cjIn, UM64_PVOID pvOut, ULONG cjOut); VOID Close(); };
PLDEV UMPD_ldevLoadDriver( LPWSTR pwszDriver, LDEVTYPE ldt );
VOID UMPD_ldevUnloadImage(PLDEV pldev);
//
// Special flag passed to EngCreateDeviceSurface and EngCreateDeviceBitmap
// to indicate the call is a user mode printer driver
//
#define UMPD_FLAG 0x8000
//
// User-mode printer driver support - memory tag
//
#define UMPD_MEMORY_TAG 'pmuG'
//
// private structure to make N-UP printing work on DrawPatRect
//
typedef struct _DRAWPATRECTP { DRAWPATRECT DrawPatRect; XFORMOBJ *pXformObj; } DRAWPATRECTP, *PDRAWPATRECTP;
#if !defined(_GDIPLUS_)
BOOL UMPDDrvEnableDriver( LPWSTR pwszDriver, PVOID *pCookie );
BOOL UMPDDrvDriverFn( PVOID cookie, BOOL * pbDrvFn );
VOID UMPDDrvDeleteDeviceBitmap( DHPDEV dhpdev, DHSURF dhsurf );
CLIPOBJ *CaptureAndMungeCLIPOBJ(CLIPOBJ *pcoUm, CLIPOBJ *pcoKm, SIZEL *szLimit);
//
// Align UMPD buffer on double-word boundary
//
//
// Change it to sizeof(PVOID) aligned, bug 101774
//
#define ALIGN_UMPD_BUFFER(cj) (((cj) + (sizeof(PVOID) -1)) & ~(sizeof(PVOID)-1))
#define ROUNDUP_MULTIPLE(n, m) ((((n) + (m) - 1) / (m)) * (m))
//
// UMPD memory manager
//
typedef struct _UMPDHEAP { PVOID pAddress; // starting heap address
HANDLE hSecure; // secured handle
SIZE_T CommitSize; // committed heap size
ULONG AllocSize; // allocated heap size
} UMPDHEAP, *PUMPDHEAP;
VOID DestroyUMPDHeap( PUMPDHEAP pHeap );
//
// Data structure for mapping between kernel-mode DDI objects
// and user-mode DDI objects.
//
typedef struct _DDIOBJMAP { KERNEL_PVOID kmobj; // pointer to kernel mode object
UM64_PVOID umobj; // user mode object memory object
} DDIOBJMAP, *PDDIOBJMAP;
//
// flags used by m_flags in UMPDOBJ
//
#define UMPDOBJ_ENGCALL 0x1
#define RELEASE_BASEFONT 0x10
#define RELEASE_SYSTTFONT 0x20
#define RELEASE_SYSEUDCFONT 0x40
#define RELEASE_DEFEUDCFONT 0x80
//
// UMPDOBJ is used to push saved kernel object pointers on to thread
// we allocate a UMPDOBJ on the stack for each Drv-call, push it onto
// the thread, and release it when the Drv-call is finished.
//
// The reason that we can't keep a one layer UMPDOBJ is that
// some Drv-call may call back to the Engine and Engine makes another
// Drv-call with totally different parameters
//
typedef class UMPDOBJ *PUMPDOBJ;
class UMPDOBJ : public OBJECT {
private:
//
// Constructor and destructor
//
UMPDOBJ() { // do nothing -- only here to ensure nobody tries to use constructor
}
~UMPDOBJ() { // do nothing -- only here to ensure nobody tries to use destructor
}
public:
BOOL Init(VOID); VOID Term(VOID) { //
// Back-propogate pvConsumer field from user-mode
// FONTOBJ to kernel-mode FONTOBJ, if necessary
//
if (m_fo.umobj != NULL) { ((FONTOBJ *) m_fo.kmobj)->pvConsumer = ((FONTOBJ *) GetKernelPtr(m_fo.umobj))->pvConsumer; }
Cleanup(); }
//
// Allocate user mode memory out of the UMPD heap
//
KERNEL_PVOID AllocUserMem(ULONG ulSize) { return _AllocUserMem(ulSize, FALSE); } KERNEL_PVOID AllocUserMemZ(ULONG ulSize) { return _AllocUserMem(ulSize, TRUE); }
//
// Cleanup when this object is destroyed
//
VOID Cleanup();
//
// Proxy support
//
BOOL bWOW64() { return m_proxyPort != NULL; } BOOL bWOW64Client() { return ((m_proxyPort != NULL) && (!(m_flags & UMPDOBJ_ENGCALL))); } BOOL bNeedThunk(PVOID pvIn) { return (bWOW64() || IS_SYSTEM_ADDRESS(pvIn)); } PW32THREAD clientTid() { return (m_clientTid); } W32PID clientPid() { return (m_clientPid); } VOID vSetFlags(ULONG f) { m_flags |= f; } VOID vClearFlags(ULONG f) { m_flags &= ~f; } BOOL bAllocFontLinks(UINT numLinks) { if (m_pfontLinks = (BOOL*)PALLOCMEM(sizeof(BOOL) * numLinks, UMPD_MEMORY_TAG)) m_fontLinks = numLinks; return (m_pfontLinks != NULL); } VOID vFreeFontLinks() { if (m_pfontLinks) VFREEMEM(m_pfontLinks); } ULONG GetFlags() { return (m_flags); } BOOL bLinkedFonts() { return (m_pfontLinks != NULL); } UINT numLinkedFonts() { return (m_fontLinks); } BOOL bLinkedFont(UINT i) { return (i < m_fontLinks && m_pfontLinks[i]); } VOID vSetFontLink(UINT i) { if (i < m_fontLinks && m_pfontLinks) m_pfontLinks[i] = TRUE; }
VOID vClearFontLink(UINT i) { if (i < m_fontLinks && m_pfontLinks) m_pfontLinks[i] = FALSE; } ULONG ulAllocSize() { ASSERTGDI(m_proxyPort,"proxyport is NULL\n"); return (m_proxyPort->ClientMemoryAllocSize); } ULONG ulGetMaxSize() { if (m_proxyPort && (m_proxyPort->ClientMemorySize > m_proxyPort->ClientMemoryAllocSize)) return (ULONG)(m_proxyPort->ClientMemorySize - m_proxyPort->ClientMemoryAllocSize); else return 0; } //
// Used only by WOW64 printing while the bitmap in SURFOBJ is bigger than 4MB
//
KERNEL_PVOID UMPDAllocUserMem(ULONG cjSize); //
// Make a copy of the bitmap on wow64 printing
//
BOOL bSendLargeBitmap(SURFOBJ *pso, BOOL *pbLargeBitmap); BOOL bThunkLargeBitmap(SURFOBJ *pso,PVOID *ppvBits, PVOID *ppvScan0, BOOL *pbSavePtr, BOOL *pbLargeBitmap, PULONG pcjSize); BOOL bThunkLargeBitmaps(SURFOBJ *psoTrg, SURFOBJ *psoSrc, SURFOBJ *psoMsk, PVOID *ppvBitTrg, PVOID *ppvScanTrg, PVOID *ppvBitSrc, PVOID *ppvScanSrc, PVOID *ppvBitMsk, PVOID *ppvScanMsk, BOOL *pbSaveTrg, BOOL *pbLargeTrg, BOOL *pbSaveSrc, BOOL *pbLargeSrc, BOOL *pbSaveMsk, BOOL *pbLargeMsk, PULONG pcjSize); BOOL bDeleteLargeBitmaps(SURFOBJ *psoTrg, SURFOBJ *psoSrc, SURFOBJ *psoMsk); VOID RestoreBitmap(SURFOBJ *pso, PVOID pvBits, PVOID pvScan0, BOOL bSavePtr, BOOL bLargeBitmap); VOID RestoreBitmaps(SURFOBJ *psoTrg, SURFOBJ *psoSrc, SURFOBJ *psoMsk, PVOID pvBitTrg, PVOID pvScanTrg, PVOID pvBitSrc, PVOID pvScanSrc, PVOID pvBitMsk, PVOID pvScanMsk, BOOL bSaveTrg, BOOL bLargeTrg, BOOL bSaveSrc, BOOL bLargeSrc, BOOL bSaveMsk, BOOL bLargeMsk); //
// functions for packing kernel mode objects
// before thunking out to the user mode
//
BOOL psoDest(SURFOBJ **ppso, BOOL bLargeBitmap) { return pso(&m_soDest, ppso, bLargeBitmap); }
BOOL psoSrc(SURFOBJ **ppso, BOOL bLargeBitmap) { return pso(&m_soSrc, ppso, bLargeBitmap); }
BOOL psoMask(SURFOBJ **ppso, BOOL bLargeBitmap) { return pso(&m_soMask, ppso, bLargeBitmap); }
BOOL pco(CLIPOBJ **ppco) { return ThunkDDIOBJ(&m_co, (KERNEL_PVOID *) ppco, sizeof(CLIPOBJ)); }
BOOL pcoCreated(CLIPOBJ **ppco) { return ThunkDDIOBJ(&m_coCreated, (KERNEL_PVOID *) ppco, sizeof(CLIPOBJ)); }
BOOL pbo(BRUSHOBJ **ppbo) { return ThunkDDIOBJ(&m_bo, (KERNEL_PVOID *)ppbo, sizeof(BRUSHOBJ)); }
BOOL pboFill(BRUSHOBJ **ppbo) { return ThunkDDIOBJ(&m_boFill, (KERNEL_PVOID *)ppbo, sizeof(BRUSHOBJ)); }
BOOL pfo(FONTOBJ **ppfo) { return ThunkDDIOBJ(&m_fo, (KERNEL_PVOID *) ppfo, sizeof(FONTOBJ)); }
BOOL pstro(STROBJ **ppstro); BOOL pxlo(XLATEOBJ **ppxlo);
BOOL ppo(PATHOBJ **pppo) { return ThunkDDIOBJ(&m_po, (KERNEL_PVOID *) pppo, sizeof(PATHOBJ)); }
BOOL ppoClip(PATHOBJ **pppo) { return ThunkDDIOBJ(&m_poClip, (KERNEL_PVOID *) pppo, sizeof(PATHOBJ)); }
BOOL ppoGlyph(PATHOBJ **pppo) { return ThunkDDIOBJ(&m_poGlyph, (KERNEL_PVOID *) pppo, sizeof(PATHOBJ)); }
BOOL pxo(XFORMOBJ **ppxo) { return ThunkDDIOBJ(&m_xo, (KERNEL_PVOID *) ppxo, sizeof(XFORMOBJ)); }
BOOL pxoFont(XFORMOBJ **ppxo) { return ThunkDDIOBJ(&m_xoFont, (KERNEL_PVOID *) ppxo, sizeof(XFORMOBJ)); }
BOOL ThunkBLENDOBJ(PBLENDOBJ *ppblendobj) { return ThunkDDIOBJ(&m_blendObj, (KERNEL_PVOID *) ppblendobj, sizeof(BLENDOBJ)); }
BOOL ThunkLINEATTRS(LINEATTRS **pplineattrs); BOOL ThunkMemBlock(PVOID *ppInput, ULONG ulSize);
BOOL ThunkStringW(PWSTR *ppwstr) { return (*ppwstr == NULL) ? TRUE : ThunkMemBlock((PVOID *) ppwstr, (wcslen(*ppwstr) + 1) * sizeof(WCHAR)); }
BOOL ThunkRECTL(PRECTL *pprcl) { return ThunkMemBlock((PVOID *) pprcl, sizeof(RECTL)); }
BOOL ThunkPOINTL(PPOINTL *pptl) { return ThunkMemBlock((PVOID *) pptl, sizeof(POINTL)); }
BOOL ThunkPOINTFIX(PPOINTFIX *pptfx) { return ThunkMemBlock((PVOID *) pptfx, sizeof(POINTFIX)); }
BOOL ThunkCOLORADJUSTMENT(PCOLORADJUSTMENT *ppca) { return ThunkMemBlock((PVOID *) ppca, sizeof(COLORADJUSTMENT)); }
//
// Functions for mapping user mode objects to kernel mode
// objects during Eng-callbacks
//
CLIPOBJ *GetDDIOBJ(CLIPOBJ *pco) { return (pco == m_co.umobj) ? (CLIPOBJ *) m_co.kmobj : NULL; }
CLIPOBJ *GetDDIOBJ(CLIPOBJ *pco, SIZEL *szLimit) { return (pco == m_co.umobj) ? (CLIPOBJ *) m_co.kmobj : (pco == m_coCreated.umobj) ? CaptureAndMungeCLIPOBJ(pco, (CLIPOBJ *) m_coCreated.kmobj, szLimit) : NULL; }
BRUSHOBJ *GetDDIOBJ(BRUSHOBJ *pbo) { return (BRUSHOBJ *) ((pbo == m_bo.umobj) ? m_bo.kmobj : (pbo == m_boFill.umobj) ? m_boFill.kmobj : NULL); }
FONTOBJ *GetDDIOBJ(FONTOBJ *pfo) { return (FONTOBJ *) ((pfo == m_fo.umobj) ? m_fo.kmobj : NULL); }
STROBJ *GetDDIOBJ(STROBJ *pstro) { return (STROBJ *) ((pstro == m_stro.umobj) ? m_stro.kmobj : NULL); }
XLATEOBJ *GetDDIOBJ(XLATEOBJ *pxlo) { return (XLATEOBJ *) ((pxlo == m_xlo.umobj) ? m_xlo.kmobj : NULL); }
PATHOBJ *GetDDIOBJ(PATHOBJ *ppo) { return (PATHOBJ *) ((ppo == m_po.umobj) ? m_po.kmobj : (ppo == m_poClip.umobj) ? m_poClip.kmobj : (ppo == m_poGlyph.umobj) ? m_poGlyph.kmobj : NULL); }
XFORMOBJ *GetDDIOBJ(XFORMOBJ *pxo) { return (XFORMOBJ *) ((pxo == m_xo.umobj) ? m_xo.kmobj : (pxo == m_xoFont.umobj) ? m_xoFont.kmobj : NULL); }
BLENDOBJ *GetDDIOBJ(BLENDOBJ *pBlendObj) { return (BLENDOBJ *) ((pBlendObj == m_blendObj.umobj) ? m_blendObj.kmobj : NULL); }
SURFOBJ *GetSURFOBJ(SURFOBJ *pso) { return (SURFOBJ *) ((pso == m_soDest.umobj) ? (m_soDest.kmobj) : (pso == m_soSrc.umobj) ? (m_soSrc.kmobj) : (pso == m_soMask.umobj) ? (m_soMask.kmobj) : NULL); }
SURFOBJ *LockSurface(HSURF hsurf); VOID UnlockSurface(SURFOBJ *pso);
PATHOBJ *GetCLIPOBJPath(CLIPOBJ *pco); VOID DeleteCLIPOBJPath(PATHOBJ *ppo);
CLIPOBJ *CreateCLIPOBJ(); VOID DeleteCLIPOBJ(CLIPOBJ *pco);
GLYPHBITS *CacheGlyphBits(GLYPHBITS *pgb); PATHOBJ *CacheGlyphPath(PATHOBJ *ppo);
XFORMOBJ *GetFONTOBJXform(FONTOBJ *pfo);
PIFIMETRICS pifi() { return m_pifi; } VOID pifi(PIFIMETRICS pifi) { m_pifi = pifi; }
PFD_GLYPHSET pfdg() { return m_pfdg; } VOID pfdg(PFD_GLYPHSET pfdg) { m_pfdg = pfdg; }
PFD_GLYPHATTR pfdga() { return m_pfdga; } VOID pfdga(PFD_GLYPHATTR pfdga) { m_pfdga = pfdga; }
PVOID pvFontFile(ULONG *size) { *size = m_size; return m_pvFontFile; } VOID pvFontFile(PVOID pvFontFile, PVOID pvFontBase, ULONG size) { m_pFontProcess = PsGetCurrentProcess(); m_pvFontFile = pvFontFile; m_pvFontBase = pvFontBase; m_size = size; }
KERNEL_PVOID GetKernelPtr(UM64_PVOID pv); VOID ResetHeap();
DWORD Thunk(PVOID pvIn, ULONG cjIn, PVOID pvOut, ULONG cjOut);
private:
//
// Data members
//
ULONG m_magic; // data structure signature
PUMPDOBJ m_pNext; // link-list pointer
PUMPDHEAP m_pHeap; // pointer to user mode memory heap
DDIOBJMAP m_soDest; // SURFOBJ
DDIOBJMAP m_soSrc; // SURFOBJ
DDIOBJMAP m_soMask; // SURFOBJ
DDIOBJMAP m_co; // CLIPOBJ
DDIOBJMAP m_coCreated; // CLIPOBJ via EngCreateClip
DDIOBJMAP m_bo; // BRUSHOBJ
DDIOBJMAP m_boFill; // BRUSHOBJ
DDIOBJMAP m_fo; // FONTOBJ
DDIOBJMAP m_stro; // STROBJ
DDIOBJMAP m_xlo; // XLATEOBJ
DDIOBJMAP m_po; // PATHOBJ
DDIOBJMAP m_poClip; // PATHOBJ
DDIOBJMAP m_poGlyph; // PATHOBJ
DDIOBJMAP m_xo; // XFORMOBJ
DDIOBJMAP m_xoFont; // XFORMOBJ
DDIOBJMAP m_blendObj; // BLENDOBJ
PIFIMETRICS m_pifi; // pointer to temporary pifi buffer
PFD_GLYPHSET m_pfdg; // pointer to temporary pfdg buffer
PFD_GLYPHATTR m_pfdga; // pointer to temporary pfdga buffer
GLYPHBITS *m_pgb; // pointer to temporary GLYPHBITS buffer
ULONG m_gbSize; // GLYPHBITS buffer size
PVOID m_pvFontBase; // cached info for FONTOBJ_pvTrueTypeFontFile
PVOID m_pvFontFile; //
ULONG m_size; //
PEPROCESS m_pFontProcess; //
struct ProxyPort * m_proxyPort; // Proxy server if needed
PW32THREAD m_clientTid; // Printing client tid
W32PID m_clientPid; // Printing client pid
ULONG m_flags; UINT m_fontLinks; // Number of linked fonts
BOOL *m_pfontLinks; // Keep track of the linked font semaphores
//
// Internal helper functions
//
UM64_PVOID _AllocUserMem(ULONG ulSize, BOOL bZeroInit);
BOOL ThunkDDIOBJ(PDDIOBJMAP pMap, KERNEL_PVOID *ppObj, ULONG objSize); BOOL pso(PDDIOBJMAP pMap, SURFOBJ **ppso, BOOL bLargeBitmap);
// Internal UMPD heap functions
PUMPDHEAP CreateUMPDHeap(void); PUMPDHEAP InitUMPDHeap(PUMPDHEAP pHeap); BOOL GrowUMPDHeap(PUMPDHEAP pHeap, ULONG ulBytesNeeded);
};
typedef class XUMPDOBJ *PXUMPDOBJ;
class XUMPDOBJ { public:
XUMPDOBJ() { PUMPDOBJ pumpdobj = (PUMPDOBJ) PALLOCMEM(sizeof(UMPDOBJ), 'dpxG');
m_pumpdobj = NULL; if(pumpdobj) { if(pumpdobj->Init()) m_pumpdobj = pumpdobj; else VFREEMEM(pumpdobj); } }
BOOL bValid(void) { return m_pumpdobj != NULL; } PUMPDOBJ pumpdobj(VOID) { return m_pumpdobj; } HUMPD hUMPD() { return (HUMPD)m_pumpdobj->hGet(); }
~XUMPDOBJ() { if(m_pumpdobj) { m_pumpdobj->Term(); VFREEMEM(m_pumpdobj); } }
private:
UMPDOBJ * m_pumpdobj; };
class UMPDREF { public:
UMPDREF(HUMPD humpd) { m_pumpd = humpd ? (PUMPDOBJ)HmgShareLock((HOBJ)humpd, UMPD_TYPE) : NULL; }
BOOL bWOW64() { return m_pumpd->bWOW64(); } PW32THREAD clientTid() { return m_pumpd->clientTid(); } W32PID clientPid() { return m_pumpd->clientPid(); } UMPDOBJ* pumpdGet() { return m_pumpd; } ~UMPDREF() { if(m_pumpd) DEC_SHARE_REF_CNT(m_pumpd); } private: UMPDOBJ* m_pumpd; };
//
// Inline function to thunk a block of memory from kernel mode to user mode
//
__inline BOOL UMPDOBJ::ThunkMemBlock( PVOID *ppInput, ULONG ulSize )
{ PVOID pvIn;
if ((pvIn = *ppInput) == NULL || ulSize == 0) return TRUE;
UM64_PVOID pv;
if ((pv = AllocUserMem(ulSize)) == NULL) return FALSE;
RtlCopyMemory(GetKernelPtr(pv), pvIn, ulSize);
*ppInput = pv;
return TRUE; }
//
// Inline function to thunk a kernel mode object to user mode
//
__inline BOOL UMPDOBJ::ThunkDDIOBJ( PDDIOBJMAP pMap, KERNEL_PVOID *ppObj, ULONG objSize )
{ KERNEL_PVOID kmobj; UM64_PVOID umobj;
if ((kmobj = *ppObj) == NULL) return TRUE;
if ((umobj = AllocUserMem(objSize)) == NULL) return FALSE;
RtlCopyMemory(GetKernelPtr(umobj), kmobj, objSize);
pMap->kmobj = kmobj; *ppObj = pMap->umobj = umobj;
return TRUE; }
//
// Inline function to allocate a block of user mode memory
//
__inline KERNEL_PVOID UMPDOBJ::GetKernelPtr(UM64_PVOID pv) { if(bWOW64Client()) { PROXYPORT proxyport(m_proxyPort); return proxyport.GetKernelPtr(pv); } else return pv; }
__inline UM64_PVOID UMPDOBJ::_AllocUserMem( ULONG ulSize, BOOL bZeroInit )
{ UM64_PVOID pv;
if(bWOW64()) { PROXYPORT proxyport(m_proxyPort); pv = proxyport.HeapAlloc(ALIGN_UMPD_BUFFER(ulSize)); } else { if (m_pHeap == NULL || m_pHeap->pAddress == NULL || ulSize > m_pHeap->CommitSize - m_pHeap->AllocSize && !GrowUMPDHeap(m_pHeap, ulSize)) { return NULL; } else { pv = (PBYTE) m_pHeap->pAddress + m_pHeap->AllocSize; m_pHeap->AllocSize += ALIGN_UMPD_BUFFER(ulSize); }
}
if (pv && bZeroInit) RtlZeroMemory(GetKernelPtr(pv), ulSize);
return pv; }
//
// Wrapper class for mapping user mode SURFOBJ pointers
// to their kernel mode counterparts
//
class UMPDSURFOBJ { public:
UMPDSURFOBJ(SURFOBJ *pso, PUMPDOBJ pUMObjs) { m_bLocked = (m_pso = pso) != NULL && (m_pso = pUMObjs->GetSURFOBJ(pso)) == NULL && (m_pso = GetLockedSURFOBJ(pso)) != NULL; }
~UMPDSURFOBJ() { if (m_bLocked) EngUnlockSurface(m_pso); }
SURFOBJ *pso() { return m_pso; }
private:
SURFOBJ *m_pso; BOOL m_bLocked;
SURFOBJ *GetLockedSURFOBJ(SURFOBJ *pso); };
//
// A few DDI callbacks which are implemented differently for UMPD
//
PVOID FONTOBJ_pvTrueTypeFontFileUMPD(FONTOBJ *pfo, ULONG *pcjFile, PVOID *ppBase); PVOID BRUSHOBJ_pvAllocRbrushUMPD(BRUSHOBJ *pbo, ULONG cj); PVOID BRUSHOBJ_pvGetRbrushUMPD(BRUSHOBJ *pbo);
typedef struct _PRINTCLIENTID { PW32THREAD clientTid; W32PID clientPid; } PRINTCLIENTID, PPRINTCLIENTID;
BOOL UMPDEngFreeUserMem(KERNEL_PVOID pv);
BOOL UMPDReleaseRFONTSem( RFONTOBJ& rfo, PUMPDOBJ pumpdobj, ULONG* pfl, ULONG* pnumLinks, BOOL** ppFaceLink );
VOID UMPDAcquireRFONTSem( RFONTOBJ& rfo, PUMPDOBJ pumpdobj, ULONG fl, ULONG numLinks, BOOL* pFaceLink );
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 GetETMFontManagement( RFONTOBJ& rfo, PDEVOBJ pdo, SURFOBJ *pso, FONTOBJ *pfo, ULONG iEsc, ULONG cjIn, PVOID pvIn, ULONG cjOut, PVOID pvOut );
#endif // !_GDIPLUS_
|