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.
945 lines
22 KiB
945 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.
|
|
|
|
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_
|
|
|