/*++ Copyright (c) 1997-1999 Microsoft Corporation Module Name: umpddrv.c Abstract: User-mode printer driver stubs for Drv callback functions Environment: Windows NT 5.0 Revision History: 09/30/97 -lingyunw- Created it by moving GdiPrinterThunk out of umpd.c. --*/ #include "precomp.h" #pragma hdrstop RTL_CRITICAL_SECTION semUMPD; // Critical section for user-mode printer driver #if !defined(_GDIPLUS_) #include "winddi.h" #include "proxyport.h" /* #if DBG #define DBG_TRACE(x) DbgPrint("UMPD: "#x"\n") #else #define DBG_TRACE(x) #endif */ // // Adjust user mode printer driver DHPDEV field in a SURFOBJ // __inline PUMDHPDEV AdjustUMdhpdev( SURFOBJ *pso ) { PUMDHPDEV pUMdhpdev = (PUMDHPDEV) pso->dhpdev; pso->dhpdev = pUMdhpdev->dhpdev; return pUMdhpdev; } BOOL GdiCopyFD_GLYPHSET( FD_GLYPHSET *dst, FD_GLYPHSET *src, ULONG cjSize ) { ULONG index, offset, size; PBYTE phg, pbMax; size = offsetof(FD_GLYPHSET, awcrun) + src->cRuns * sizeof(WCRUN); RtlCopyMemory(dst, src, size); dst->cjThis = cjSize; pbMax = (PBYTE)dst + cjSize; phg = (PBYTE)dst + size; // // Patch up memory pointers in each WCRUN structure // for (index=0; index < src->cRuns; index++) { if (src->awcrun[index].phg != NULL) { size = src->awcrun[index].cGlyphs * sizeof(HGLYPH); if (phg + size <= pbMax) { RtlCopyMemory(phg, src->awcrun[index].phg, size); dst->awcrun[index].phg = (HGLYPH*) phg; phg += size; } else return FALSE; } } return TRUE; } BOOL bAddPrinterHandle(PUMPD pUMPD, DWORD clientPid, DWORD hPrinter32, HANDLE hPrinter64) { PHPRINTERLIST pPtrList; BOOL bRet = FALSE; if (pPtrList = LOCALALLOC(sizeof(HPRINTERLIST))) { pPtrList->clientPid = clientPid; pPtrList->hPrinter32 = hPrinter32; pPtrList->hPrinter64 = hPrinter64; ENTERCRITICALSECTION(&semUMPD); pPtrList->pNext = pUMPD->pHandleList; pUMPD->pHandleList = pPtrList; bRet = TRUE; LEAVECRITICALSECTION(&semUMPD); } return bRet; } PHPRINTERLIST FindPrinterHandle(PUMPD pUMPD, DWORD clientPid, DWORD hPrinter32) { PHPRINTERLIST pList; ENTERCRITICALSECTION(&semUMPD); pList = pUMPD->pHandleList; while(pList) { if (pList->clientPid == clientPid && pList->hPrinter32 == hPrinter32) { break; } pList = pList->pNext; } LEAVECRITICALSECTION(&semUMPD); return pList; } VOID DeletePrinterHandle(PUMPD pUMPD, PHPRINTERLIST pNode) { PHPRINTERLIST pList; ENTERCRITICALSECTION(&semUMPD); pList = pUMPD->pHandleList; if (pList == pNode) { pUMPD->pHandleList = pNode->pNext; } else { while(pList && pList->pNext != pNode) { pList = pList->pNext; } if (pList) { pList->pNext = pNode->pNext; } } LEAVECRITICALSECTION(&semUMPD); if (pList) { LOCALFREE(pNode); } } // // KERNEL_PVOID UMPDAllocUserMem // // WOW64 printing only // KERNEL_PVOID UMPDAllocUserMem(ULONG cjSize) { return ((KERNEL_PVOID) LOCALALLOC(cjSize)); } // // KERNEL_PVOID UMPDCopyMemory // // WOW64 printing only // // pvSrc // source // // pvDest // dest // // cjBits // size to copy // KERNEL_PVOID UMPDCopyMemory( KERNEL_PVOID pvSrc, KERNEL_PVOID pvDest, ULONG cjBits ) { if (pvDest != NULL) RtlCopyMemory(pvDest, pvSrc, cjBits); return pvDest; } // // BOOL UMPDFreeMemory // // WOW64 only // BOOL UMPDFreeMemory( KERNEL_PVOID pv1, KERNEL_PVOID pv2, KERNEL_PVOID pv3 ) { if (pv1) LOCALFREE(pv1); if (pv2) LOCALFREE(pv2); if (pv3) LOCALFREE(pv3); return TRUE; } /******************************Public*Routine******************************\ * GdiPrinterThunk function * * GDI callback for user-mode printer drivers. * * Parameters pumth * Pointer to input buffer. Buffer has UMTHDR at * beginning. * * pvOut * Output buffer. * * cjOut * Size of output buffer. * * Return Value * * The function returns GPT_ERROR if an error occurs. Otherwise, the * return value is dependent on the command specified by pumth->ulType. * * History: * 7/17/97 -by- Lingyun Wang [lingyunw] Added giant body to * Make it do the real work * 30-Jun-1997 -by- Gilman Wong [gilmanw] * Wrote it. \**************************************************************************/ extern PUMPD FindUserModePrinterDriver( PCWSTR pDriverDllName, DWORD dwDriverVersion, BOOL bUseVersion ); WINGDIAPI ULONG WINAPI GdiPrinterThunk ( UMTHDR * pvIn, PVOID pvOut, ULONG cjOut ) { INT iRet = 1; UMPDTHDR * pumpdthdr = (UMPDTHDR *) pvIn; HUMPD hSaved; BOOL bWOW64 = FALSE, bSetPUMPD = FALSE; ULONG ulType = pvIn->ulType; // // Call NtGdiSetPUMPDOBJ to set the W32THREAD.pUMPDObj pointer // only if this is a DDI thunk // if (ulType <= INDEX_LAST+1) { if (!(bSetPUMPD = NtGdiSetPUMPDOBJ(pumpdthdr->humpd, TRUE, &hSaved, &bWOW64))) { WARNING ("NtGdiSetPUMPDOBJ failed\n"); return GPT_ERROR; } } switch (ulType) { case INDEX_LoadUMPrinterDrv: { PLOADDRIVERINPUT pInput = (PLOADDRIVERINPUT) pvIn; PUMPD pUMPD = NULL; HANDLE hPrinter = NULL; *((PUMPD *)pvOut) = NULL; if(BLOADSPOOLER) { (*fpOpenPrinterW)(pInput->pPrinterName, &hPrinter, (LPPRINTER_DEFAULTSW)&pInput->defaults); if(hPrinter) { if(LoadUserModePrinterDriverEx((PDRIVER_INFO_5W)&pInput->driverInfo, NULL, &pUMPD, NULL, 0) && bAddPrinterHandle(pUMPD, pInput->clientPid, pInput->hPrinter32, hPrinter)) { *((PUMPD *) pvOut) = pUMPD; } else { if (pUMPD) UnloadUserModePrinterDriver(pUMPD, TRUE, 0); (*fpClosePrinter)(hPrinter); WARNING("GdiPrinterThunk: failed to load umpd or add printer handles\n"); } } else { WARNING(("failed opening printer '%ls' on proxy\n", (PCH)pInput->pPrinterName)); } } else { WARNING("GdiPrinterThunk: failed loading spooler\n"); } } break; case INDEX_UnloadUMPrinterDrv: { PUNLOADDRIVERINPUT pInput = (PUNLOADDRIVERINPUT) pvIn; PUMPD pUMPD = (PUMPD) pInput->umpdCookie; PHPRINTERLIST pList; if (pInput->hPrinter32 && (pList = FindPrinterHandle(pUMPD, pInput->clientPid, pInput->hPrinter32))) { (*fpClosePrinter)(pList->hPrinter64); DeletePrinterHandle(pUMPD, pList); } UnloadUserModePrinterDriver(pUMPD, pInput->bNotifySpooler, 0); } break; case INDEX_UMDriverFN: { PDRVDRIVERFNINPUT pInput = (PDRVDRIVERFNINPUT) pvIn; PUMPD pUMPD = (PUMPD) pInput->cookie; BOOL * pbDrvFn = (BOOL *) pvOut; int index; if(pUMPD) { for(index = 0; index < INDEX_LAST; index++) pbDrvFn[index] = (pUMPD->apfn[index] != NULL ? TRUE : FALSE); } else { RtlZeroMemory(pvOut, sizeof(BOOL) * INDEX_LAST); } } break; case INDEX_DocumentEvent: { PDOCUMENTEVENTINPUT pInput = (PDOCUMENTEVENTINPUT) pvIn; PHPRINTERLIST pList = FindPrinterHandle((PUMPD)pInput->umpdCookie, pInput->clientPid, pInput->hPrinter32); if (pList) { *((int*)pvOut) = (*fpDocumentEvent)(pList->hPrinter64, pInput->hdc, pInput->iEsc, pInput->cjIn, (PVOID)pInput->pvIn, pInput->cjOut, (PVOID)pInput->pvOut); if (pInput->iEsc == DOCUMENTEVENT_CREATEDCPRE || pInput->iEsc == DOCUMENTEVENT_RESETDCPRE) { if ((*((int*)pvOut) != DOCUMENTEVENT_FAILURE) && *((DEVMODEW**)pInput->pvOut)) { RtlCopyMemory(pInput->pdmCopy, *((DEVMODEW**)pInput->pvOut), sizeof(DEVMODEW)); } } } else *((int*)pvOut) = DOCUMENTEVENT_FAILURE; } break; case INDEX_StartDocPrinterW: { PSTARTDOCPRINTERWINPUT pInput = (PSTARTDOCPRINTERWINPUT) pvIn; PHPRINTERLIST pList = FindPrinterHandle((PUMPD)pInput->umpdCookie, pInput->clientPid, pInput->hPrinter32); if (pList) { *((DWORD*)pvOut) = (*fpStartDocPrinterW)(pList->hPrinter64, pInput->level, (LPBYTE)&pInput->docInfo); pInput->lastError = GetLastError(); } else *((DWORD*)pvOut) = 0; } break; case INDEX_StartPagePrinter: { PUMPDSIMPLEINPUT pInput = (PUMPDSIMPLEINPUT) pvIn; PHPRINTERLIST pList = FindPrinterHandle((PUMPD)pInput->umpdCookie, pInput->clientPid, pInput->hPrinter32); if (pList) *((BOOL*)pvOut) = (*fpStartPagePrinter)(pList->hPrinter64); else *((BOOL*)pvOut) = FALSE; } break; case INDEX_EndPagePrinter: { PUMPDSIMPLEINPUT pInput = (PUMPDSIMPLEINPUT) pvIn; PHPRINTERLIST pList = FindPrinterHandle((PUMPD)pInput->umpdCookie, pInput->clientPid, pInput->hPrinter32); if (pList) { *((BOOL*)pvOut) = (*fpEndPagePrinter)(pList->hPrinter64); } else { *((BOOL*)pvOut) = FALSE; } } break; case INDEX_EndDocPrinter: { PUMPDSIMPLEINPUT pInput = (PUMPDSIMPLEINPUT) pvIn; PHPRINTERLIST pList = FindPrinterHandle((PUMPD)pInput->umpdCookie, pInput->clientPid, pInput->hPrinter32); if (pList) *((BOOL*)pvOut) = (*fpEndDocPrinter)(pList->hPrinter64); else *((BOOL*)pvOut) = FALSE; } break; case INDEX_AbortPrinter: { PUMPDSIMPLEINPUT pInput = (PUMPDSIMPLEINPUT) pvIn; PHPRINTERLIST pList = FindPrinterHandle((PUMPD)pInput->umpdCookie, pInput->clientPid, pInput->hPrinter32); if (pList) *((BOOL*)pvOut) = (*fpAbortPrinter)(pList->hPrinter64); else *((BOOL*)pvOut) = FALSE; } break; case INDEX_ResetPrinterW: { PRESETPRINTERWINPUT pInput = (PRESETPRINTERWINPUT) pvIn; PHPRINTERLIST pList = FindPrinterHandle((PUMPD)pInput->umpdCookie, pInput->clientPid, pInput->hPrinter32); if (pList) { *((BOOL*)pvOut) = (*fpResetPrinterW)(pList->hPrinter64, (PRINTER_DEFAULTSW*)&pInput->ptrDef); } else *((BOOL*)pvOut) = FALSE; } break; case INDEX_QueryColorProfile: { PQUERYCOLORPROFILEINPUT pInput = (PQUERYCOLORPROFILEINPUT) pvIn; ULONG cjProfileSizeOld = pInput->cjProfileSize; PHPRINTERLIST pList = FindPrinterHandle((PUMPD)pInput->umpdCookie, pInput->clientPid, pInput->hPrinter32); if (pList) { *((BOOL*)pvOut) = (*fpQueryColorProfile)(pList->hPrinter64, pInput->pDevMode, pInput->ulQueryMode, pInput->pvProfileData, &pInput->cjProfileSize, &pInput->flProfileFlag); if ((*(INT*)pvOut) == 0 && pInput->cjProfileSize > cjProfileSizeOld && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) { pInput->lastError = GetLastError(); } } else *((BOOL*)pvOut) = FALSE; } break; case INDEX_UMPDDrvEnableDriver: // special index for DrvEnableDriver { PDRVENABLEDRIVERINPUT pInput = (PDRVENABLEDRIVERINPUT) pvIn; *((PUMPD *) pvOut) = UMPDDrvEnableDriver(pInput->pwszDriver, DDI_DRIVER_VERSION_NT5_01_SP1); } break; case INDEX_DrvEnablePDEV: { PDRVENABLEPDEVINPUT pInput = (PDRVENABLEPDEVINPUT) pvIn; PUMPD pUMPD = (PUMPD) pInput->umpdCookie; PFN pfn = pUMPD->apfn[INDEX_DrvEnablePDEV]; PUMDHPDEV pUMdhpdev; HANDLE hPrinter = NULL; PHPRINTERLIST pList; // If we have a local hPrinter use it if (pInput->bWOW64 && (pList = FindPrinterHandle((PUMPD)pInput->umpdCookie, pInput->clientPid, HandleToUlong(pInput->hPrinter)))) { hPrinter = pList->hPrinter64; } else { hPrinter = pInput->hPrinter; } if (pUMdhpdev = (PUMDHPDEV) LOCALALLOC(sizeof(UMDHPDEV))) { ZeroMemory(pUMdhpdev, sizeof(UMDHPDEV)); pUMdhpdev->pUMPD = pUMPD; pUMdhpdev->dhpdev = (DHPDEV) pfn( pInput->pdm, pInput->pLogAddress, pInput->cPatterns, pInput->phsurfPatterns, pInput->cjCaps, pInput->pdevcaps, pInput->cjDevInfo, pInput->pDevInfo, pInput->hdev, pInput->pDeviceName, hPrinter); if (pUMdhpdev->dhpdev == NULL) { WARNING ("Driver's DrvEnablePDEV failed\n"); LOCALFREE(pUMdhpdev); pUMdhpdev = NULL; } #if defined(_WIN64) else { if (pInput->bWOW64 && pInput->pdevcaps) { GDIINFO *pGdiInfo = (GDIINFO*)pInput->pdevcaps; if (pGdiInfo->ulHTPatternSize == HT_PATSIZE_USER && pGdiInfo->cxHTPat <= HT_USERPAT_CX_MAX && pGdiInfo->cyHTPat <= HT_USERPAT_CY_MAX) { pInput->cxHTPat = pGdiInfo->cxHTPat; pInput->cyHTPat = pGdiInfo->cyHTPat; pInput->bHTPatA = pGdiInfo->pHTPatA ? TRUE : FALSE; pInput->bHTPatB = pGdiInfo->pHTPatB ? TRUE : FALSE; pInput->bHTPatC = pGdiInfo->pHTPatC ? TRUE : FALSE; if (pInput->bHTPatA) { RtlCopyMemory(pInput->pHTPatA, pGdiInfo->pHTPatA, pInput->cxHTPat* pInput->cyHTPat); } if (pInput->bHTPatB) { RtlCopyMemory(pInput->pHTPatB, pGdiInfo->pHTPatB, pInput->cxHTPat* pInput->cyHTPat); } if (pInput->bHTPatC) { RtlCopyMemory(pInput->pHTPatC, pGdiInfo->pHTPatC, pInput->cxHTPat* pInput->cyHTPat); } } } } #endif } else { WARNING ("umEnablePDEV failed memory allocation \n"); } *((DHPDEV *) pvOut) = (DHPDEV) pUMdhpdev; } break; case INDEX_DrvCompletePDEV: { PDRVCOMPLETEPDEVINPUT pInput = (PDRVCOMPLETEPDEVINPUT) pvIn; PUMDHPDEV pUMdhpdev = (PUMDHPDEV) pInput->dhpdev; PUMPD pUMPD = pUMdhpdev->pUMPD; PFN pfn = pUMPD->apfn[INDEX_DrvCompletePDEV]; pfn(pUMdhpdev->dhpdev, pInput->hdev); } break; case INDEX_DrvFree: { PDRVFREEINPUT pInput = (PDRVFREEINPUT) pvIn; PUMDHPDEV pUMdhpdev = (PUMDHPDEV) pInput->dhpdev; PUMPD pUMPD = pUMdhpdev->pUMPD; PFN pfn = pUMPD->apfn[INDEX_DrvFree]; if (pfn) pfn(pInput->pv, pInput->id); } break; case INDEX_DrvResetPDEV: { PDRVRESETPDEVINPUT pInput = (PDRVRESETPDEVINPUT) pvIn; PUMDHPDEV pUMdhpdevOld= (PUMDHPDEV) pInput->dhpdevOld; PUMDHPDEV pUMdhpdevNew= (PUMDHPDEV) pInput->dhpdevNew; PUMPD pUMPDNew = pUMdhpdevNew->pUMPD; PFN pfn = pUMPDNew->apfn[INDEX_DrvResetPDEV]; *((BOOL *) pvOut) = (BOOL)pfn(pUMdhpdevOld->dhpdev, pUMdhpdevNew->dhpdev); } break; case INDEX_DrvDisablePDEV: { PUMDHPDEV pUMdhpdev = (PUMDHPDEV)((PDHPDEVINPUT)pvIn)->dhpdev; PUMPD pUMPD = pUMdhpdev->pUMPD; PFN pfn = pUMPD->apfn[INDEX_DrvDisablePDEV]; pfn(pUMdhpdev->dhpdev); // free up memory allocated for user mode printer drivers if (pUMdhpdev) { LOCALFREE (pUMdhpdev); } } break; case INDEX_DrvEnableSurface: { PUMDHPDEV pUMdhpdev = (PUMDHPDEV)((PDHPDEVINPUT)pvIn)->dhpdev; PUMPD pUMPD = pUMdhpdev->pUMPD; PFN pfn = pUMPD->apfn[INDEX_DrvEnableSurface]; *((HSURF *) pvOut) = (HSURF) pfn(pUMdhpdev->dhpdev); } break; case INDEX_DrvDisableSurface: { PUMDHPDEV pUMdhpdev = (PUMDHPDEV)((PDHPDEVINPUT)pvIn)->dhpdev; PUMPD pUMPD = pUMdhpdev->pUMPD; PFN pfn = pUMPD->apfn[INDEX_DrvDisableSurface]; pfn(pUMdhpdev->dhpdev); } break; case INDEX_DrvStartDoc: { PDRVSTARTDOCINPUT pInput = (PDRVSTARTDOCINPUT)pvIn; PUMDHPDEV pUMdhpdev = AdjustUMdhpdev(pInput->pso); // // check to make sure we have a dhpdev in the surface // neither Unidrv or Pscript checks if EngAssociateSurface is // successful or not // if (pUMdhpdev) { PUMPD pUMPD = pUMdhpdev->pUMPD; PFN pfn = pUMPD->apfn[INDEX_DrvStartDoc]; *((BOOL *) pvOut) = (BOOL)pfn(pInput->pso, pInput->pwszDocName, pInput->dwJobId); } else *(BOOL *)pvOut = FALSE; } break; case INDEX_DrvEndDoc: { PDRVENDDOCINPUT pInput = (PDRVENDDOCINPUT)pvIn; PUMDHPDEV pUMdhpdev = AdjustUMdhpdev(pInput->pso); PUMPD pUMPD = pUMdhpdev->pUMPD; PFN pfn = pUMPD->apfn[INDEX_DrvEndDoc]; *((BOOL *) pvOut) = (BOOL)pfn(pInput->pso, pInput->fl ); } break; case INDEX_DrvStartPage: { PSURFOBJINPUT pInput = (PSURFOBJINPUT)pvIn; PUMDHPDEV pUMdhpdev = AdjustUMdhpdev(pInput->pso); PUMPD pUMPD = pUMdhpdev->pUMPD; PFN pfn = pUMPD->apfn[INDEX_DrvStartPage]; *((BOOL *) pvOut) = (BOOL)pfn(pInput->pso); } break; case INDEX_DrvSendPage: { PSURFOBJINPUT pInput = (PSURFOBJINPUT)pvIn; PUMDHPDEV pUMdhpdev = AdjustUMdhpdev(pInput->pso); PUMPD pUMPD = pUMdhpdev->pUMPD; PFN pfn = pUMPD->apfn[INDEX_DrvSendPage]; *((BOOL *) pvOut) = (BOOL)pfn(pInput->pso); } break; case INDEX_DrvEscape: { PDRVESCAPEINPUT pInput = (PDRVESCAPEINPUT) pvIn; PUMDHPDEV pUMdhpdev = AdjustUMdhpdev(pInput->pso); PUMPD pUMPD = pUMdhpdev->pUMPD; PFN pfn = pUMPD->apfn[INDEX_DrvEscape]; *((ULONG *) pvOut) = (ULONG) pfn(pInput->pso, pInput->iEsc, pInput->cjIn, pInput->pvIn, pInput->cjOut, pInput->pvOut); } break; case INDEX_DrvDrawEscape: { PDRVDRAWESCAPEINPUT pInput = (PDRVDRAWESCAPEINPUT) pvIn; PUMDHPDEV pUMdhpdev = AdjustUMdhpdev(pInput->pso); PUMPD pUMPD = pUMdhpdev->pUMPD; PFN pfn = pUMPD->apfn[INDEX_DrvDrawEscape]; *((ULONG *) pvOut) = (ULONG) pfn(pInput->pso, pInput->iEsc, pInput->pco, pInput->prcl, pInput->cjIn, pInput->pvIn); } break; case INDEX_DrvStartBanding: { PDRVBANDINGINPUT pInput = (PDRVBANDINGINPUT)pvIn; PUMDHPDEV pUMdhpdev = AdjustUMdhpdev(pInput->pso); PUMPD pUMPD = pUMdhpdev->pUMPD; PFN pfn = pUMPD->apfn[INDEX_DrvStartBanding]; *((BOOL *) pvOut) = (BOOL)pfn(pInput->pso, pInput->pptl); } break; case INDEX_DrvQueryPerBandInfo: { PDRVPERBANDINPUT pInput = (PDRVPERBANDINPUT)pvIn; PUMDHPDEV pUMdhpdev = AdjustUMdhpdev(pInput->pso); PUMPD pUMPD = pUMdhpdev->pUMPD; PFN pfn = pUMPD->apfn[INDEX_DrvQueryPerBandInfo]; *((BOOL *) pvOut) = (BOOL) pfn(pInput->pso, pInput->pbi); } break; case INDEX_DrvNextBand: { PDRVBANDINGINPUT pInput = (PDRVBANDINGINPUT)pvIn; PUMDHPDEV pUMdhpdev = AdjustUMdhpdev(pInput->pso); PUMPD pUMPD = pUMdhpdev->pUMPD; PFN pfn = pUMPD->apfn[INDEX_DrvNextBand]; *((BOOL *) pvOut) = (BOOL)pfn(pInput->pso, pInput->pptl); } break; case INDEX_DrvBitBlt: { PDRVBITBLTINPUT pInput = (PDRVBITBLTINPUT)pvIn; PUMDHPDEV pUMdhpdev = AdjustUMdhpdev(pInput->psoTrg); PUMPD pUMPD = pUMdhpdev->pUMPD; PFN pfn = pUMPD->apfn[INDEX_DrvBitBlt]; *((BOOL *) pvOut) = (BOOL) pfn(pInput->psoTrg, pInput->psoSrc, pInput->psoMask, pInput->pco, pInput->pxlo, pInput->prclTrg, pInput->pptlSrc, pInput->pptlMask, pInput->pbo, pInput->pptlBrush, pInput->rop4); if (bWOW64 && pInput->pbo) { NtGdiBRUSHOBJ_DeleteRbrush(pInput->pbo, NULL); } } break; case INDEX_DrvStretchBlt: { PDRVSTRETCHBLTINPUT pInput = (PDRVSTRETCHBLTINPUT)pvIn; PUMDHPDEV pUMdhpdev = AdjustUMdhpdev(pInput->psoTrg); PUMPD pUMPD = pUMdhpdev->pUMPD; PFN pfn = pUMPD->apfn[INDEX_DrvStretchBlt]; *((BOOL *) pvOut) = (BOOL) pfn (pInput->psoTrg, pInput->psoSrc, pInput->psoMask, pInput->pco, pInput->pxlo, pInput->pca, pInput->pptlHTOrg, pInput->prclTrg, pInput->prclSrc, pInput->pptlMask, pInput->iMode); } break; case INDEX_DrvStretchBltROP: { PDRVSTRETCHBLTINPUT pInput = (PDRVSTRETCHBLTINPUT)pvIn; PUMDHPDEV pUMdhpdev = AdjustUMdhpdev(pInput->psoTrg); PUMPD pUMPD = pUMdhpdev->pUMPD; PFN pfn = pUMPD->apfn[INDEX_DrvStretchBltROP]; *((BOOL *) pvOut) = (BOOL) pfn (pInput->psoTrg, pInput->psoSrc, pInput->psoMask, pInput->pco, pInput->pxlo, pInput->pca, pInput->pptlHTOrg, pInput->prclTrg, pInput->prclSrc, pInput->pptlMask, pInput->iMode, pInput->pbo, pInput->rop4); if (bWOW64 && pInput->pbo) { NtGdiBRUSHOBJ_DeleteRbrush(pInput->pbo, NULL); } } break; case INDEX_DrvPlgBlt: { PDRVPLGBLTINPUT pInput = (PDRVPLGBLTINPUT)pvIn; PUMDHPDEV pUMdhpdev = AdjustUMdhpdev(pInput->psoTrg); PUMPD pUMPD = pUMdhpdev->pUMPD; PFN pfn = pUMPD->apfn[INDEX_DrvPlgBlt]; *((BOOL *) pvOut) = (BOOL) pfn(pInput->psoTrg, pInput->psoSrc, pInput->psoMask, pInput->pco, pInput->pxlo, pInput->pca, pInput->pptlBrushOrg, pInput->pptfx, pInput->prcl, pInput->pptl, pInput->iMode); } break; case INDEX_DrvCopyBits: { PDRVCOPYBITSINPUT pInput = (PDRVCOPYBITSINPUT) pvIn; PUMDHPDEV pUMdhpdev; PUMPD pUMPD; PFN pfn; SURFOBJ *pso; // // Special case when psoSrc is a device surface and // psoTrg is a bitmap surface. This is used by the engine // during simulation of certain drawing calls. // pso = (pInput->psoTrg->iType == STYPE_BITMAP && pInput->psoTrg->dhpdev == NULL) ? pInput->psoSrc : pInput->psoTrg; if (pso && (pUMdhpdev = AdjustUMdhpdev(pso))) { pUMPD = pUMdhpdev->pUMPD; pfn = pUMPD->apfn[INDEX_DrvCopyBits]; *((BOOL *) pvOut) = (BOOL) pfn(pInput->psoTrg, pInput->psoSrc, pInput->pco, pInput->pxlo, pInput->prclTrg, pInput->pptlSrc); } else { *((BOOL *) pvOut) = FALSE; } } break; case INDEX_DrvRealizeBrush: { PDRVREALIZEBRUSHINPUT pInput = (PDRVREALIZEBRUSHINPUT)pvIn; PUMDHPDEV pUMdhpdev = AdjustUMdhpdev(pInput->psoTrg); PUMPD pUMPD = pUMdhpdev->pUMPD; PFN pfn = pUMPD->apfn[INDEX_DrvRealizeBrush]; *((BOOL *) pvOut) = (BOOL) pfn(pInput->pbo, pInput->psoTrg, pInput->psoPat, pInput->psoMsk, pInput->pxlo, pInput->iHatch); } break; case INDEX_DrvLineTo: { PDRVLINETOINPUT pInput = (PDRVLINETOINPUT)pvIn; PUMDHPDEV pUMdhpdev = AdjustUMdhpdev(pInput->pso); PUMPD pUMPD = pUMdhpdev->pUMPD; PFN pfn = pUMPD->apfn[INDEX_DrvLineTo]; *((BOOL *) pvOut) = (BOOL) pfn (pInput->pso, pInput->pco, pInput->pbo, pInput->x1, pInput->y1, pInput->x2, pInput->y2, pInput->prclBounds, pInput->mix); if (bWOW64 && pInput->pbo) { NtGdiBRUSHOBJ_DeleteRbrush(pInput->pbo, NULL); } } break; case INDEX_DrvStrokePath: { PSTROKEANDFILLINPUT pInput = (PSTROKEANDFILLINPUT)pvIn; PUMDHPDEV pUMdhpdev = AdjustUMdhpdev(pInput->pso); PUMPD pUMPD = pUMdhpdev->pUMPD; PFN pfn = pUMPD->apfn[INDEX_DrvStrokePath]; *((BOOL *) pvOut) = (BOOL) pfn(pInput->pso, pInput->ppo, pInput->pco, pInput->pxo, pInput->pbo, pInput->pptlBrushOrg, pInput->plineattrs, pInput->mix); if (bWOW64 && pInput->pbo) { NtGdiBRUSHOBJ_DeleteRbrush(pInput->pbo, NULL); } } break; case INDEX_DrvFillPath: { PSTROKEANDFILLINPUT pInput = (PSTROKEANDFILLINPUT)pvIn; PUMDHPDEV pUMdhpdev = AdjustUMdhpdev(pInput->pso); PUMPD pUMPD = pUMdhpdev->pUMPD; PFN pfn = pUMPD->apfn[INDEX_DrvFillPath]; *((BOOL *) pvOut) = (BOOL) pfn(pInput->pso, pInput->ppo, pInput->pco, pInput->pbo, pInput->pptlBrushOrg, pInput->mix, pInput->flOptions); if (bWOW64 && pInput->pbo) { NtGdiBRUSHOBJ_DeleteRbrush(pInput->pbo, NULL); } } break; case INDEX_DrvStrokeAndFillPath: { PSTROKEANDFILLINPUT pInput = (PSTROKEANDFILLINPUT)pvIn; PUMDHPDEV pUMdhpdev = AdjustUMdhpdev(pInput->pso); PUMPD pUMPD = pUMdhpdev->pUMPD; PFN pfn = pUMPD->apfn[INDEX_DrvStrokeAndFillPath]; *((BOOL *) pvOut) = (BOOL) pfn(pInput->pso, pInput->ppo, pInput->pco, pInput->pxo, pInput->pbo, pInput->plineattrs, pInput->pboFill, pInput->pptlBrushOrg, pInput->mix, pInput->flOptions); if (bWOW64 && (pInput->pbo || pInput->pboFill)) { NtGdiBRUSHOBJ_DeleteRbrush(pInput->pbo, pInput->pboFill); } } break; case INDEX_DrvPaint: { PSTROKEANDFILLINPUT pInput = (PSTROKEANDFILLINPUT)pvIn; PUMDHPDEV pUMdhpdev = AdjustUMdhpdev(pInput->pso); PUMPD pUMPD = pUMdhpdev->pUMPD; PFN pfn = pUMPD->apfn[INDEX_DrvPaint]; *((BOOL *) pvOut) = (BOOL) pfn(pInput->pso, pInput->pco, pInput->pbo, pInput->pptlBrushOrg, pInput->mix); if (bWOW64 && pInput->pbo) { NtGdiBRUSHOBJ_DeleteRbrush(pInput->pbo, NULL); } } break; case INDEX_DrvGradientFill: { PGRADIENTINPUT pInput = (PGRADIENTINPUT)pvIn; PUMDHPDEV pUMdhpdev = AdjustUMdhpdev(pInput->psoTrg); PUMPD pUMPD = pUMdhpdev->pUMPD; PFN pfn = pUMPD->apfn[INDEX_DrvGradientFill]; *((BOOL *) pvOut) = (BOOL) pfn(pInput->psoTrg, pInput->pco, pInput->pxlo, pInput->pVertex, pInput->nVertex, pInput->pMesh, pInput->nMesh, pInput->prclExtents, pInput->pptlDitherOrg, pInput->ulMode); } break; case INDEX_DrvAlphaBlend: { PALPHAINPUT pInput = (PALPHAINPUT)pvIn; PUMDHPDEV pUMdhpdev = AdjustUMdhpdev(pInput->psoTrg); PUMPD pUMPD = pUMdhpdev->pUMPD; PFN pfn = pUMPD->apfn[INDEX_DrvAlphaBlend]; *((BOOL *) pvOut) = (BOOL) pfn(pInput->psoTrg, pInput->psoSrc, pInput->pco, pInput->pxlo, pInput->prclDest, pInput->prclSrc, pInput->pBlendObj); } break; case INDEX_DrvTransparentBlt: { PTRANSPARENTINPUT pInput = (PTRANSPARENTINPUT)pvIn; PUMDHPDEV pUMdhpdev = AdjustUMdhpdev(pInput->psoTrg); PUMPD pUMPD = pUMdhpdev->pUMPD; PFN pfn = pUMPD->apfn[INDEX_DrvTransparentBlt]; *((BOOL *) pvOut) = (BOOL) pfn(pInput->psoTrg, pInput->psoSrc, pInput->pco, pInput->pxlo, pInput->prclDst, pInput->prclSrc, pInput->TransColor, pInput->ulReserved); } break; case INDEX_DrvTextOut: { PTEXTOUTINPUT pInput = (PTEXTOUTINPUT)pvIn; PUMDHPDEV pUMdhpdev = AdjustUMdhpdev(pInput->pso); PUMPD pUMPD = pUMdhpdev->pUMPD; PFN pfn = pUMPD->apfn[INDEX_DrvTextOut]; *((BOOL *) pvOut) = (BOOL) pfn(pInput->pso, pInput->pstro, pInput->pfo, pInput->pco, pInput->prclExtra, pInput->prclOpaque, pInput->pboFore, pInput->pboOpaque, pInput->pptlOrg, pInput->mix); if (bWOW64 && (pInput->pboFore || pInput->pboOpaque)) { NtGdiBRUSHOBJ_DeleteRbrush(pInput->pboFore, pInput->pboOpaque); } } break; case INDEX_DrvQueryFont: { PQUERYFONTINPUT pInput = (PQUERYFONTINPUT)pvIn; PUMDHPDEV pUMdhpdev = (PUMDHPDEV)(pInput->dhpdev); PUMPD pUMPD = pUMdhpdev->pUMPD; PFN pfn = pUMPD->apfn[INDEX_DrvQueryFont]; *((PIFIMETRICS *) pvOut) = (PIFIMETRICS) pfn( pUMdhpdev->dhpdev, pInput->iFile, pInput->iFace, pInput->pid); if (pInput->iFace && *((PIFIMETRICS*)pvOut) && pInput->pv) { ASSERTGDI(pInput->cjMaxData >= (*(PIFIMETRICS*)pvOut)->cjThis, "gdi32!GdiPrinterThunk: not enough buffer for ifimetrics\n"); if (pInput->cjMaxData >= (*(PIFIMETRICS*)pvOut)->cjThis) { RtlCopyMemory(pInput->pv, (PBYTE)(*(PIFIMETRICS*)pvOut), (*(PIFIMETRICS*)pvOut)->cjThis); } else { iRet = -1; WARNING(("Not enough buffer for ifimetrics cjMaxData: 0x%lx cjSize: 0x%lx pInput.pv %lp pvOut %lp\n", pInput->cjMaxData, (*(PIFIMETRICS*)pvOut)->cjThis, pInput->pv, pvOut)); pInput->cjMaxData = 0; } } } break; case INDEX_DrvQueryFontTree: { PQUERYFONTINPUT pInput = (PQUERYFONTINPUT)pvIn; PUMDHPDEV pUMdhpdev = (PUMDHPDEV)(pInput->dhpdev); PUMPD pUMPD = pUMdhpdev->pUMPD; PFN pfn = pUMPD->apfn[INDEX_DrvQueryFontTree]; ULONG cjSize = 0; FD_GLYPHSET* pfdg; *((PVOID *) pvOut) = (PVOID) pfn (pUMdhpdev->dhpdev, pInput->iFile, pInput->iFace, pInput->iMode, pInput->pid); if (pInput->iMode == QFT_GLYPHSET && *((FD_GLYPHSET**)pvOut) && pInput->pv) { pfdg = *((FD_GLYPHSET**)pvOut); cjSize = offsetof(FD_GLYPHSET, awcrun) + pfdg->cRuns * sizeof(WCRUN) + pfdg->cGlyphsSupported * sizeof(HGLYPH); ASSERTGDI(pInput->cjMaxData >= cjSize, "gdi32!GdiPrinterThunk: not enough buffer for glyphset\n"); if ((pInput->cjMaxData < cjSize) || !GdiCopyFD_GLYPHSET((FD_GLYPHSET*)pInput->pv, pfdg, cjSize)) { WARNING("GDI32: Not enough bufer or error copying FD_GLYPHSET\n"); pInput->cjMaxData = 0; iRet = -1; } } else if (pInput->iMode == QFT_KERNPAIRS && *(FD_KERNINGPAIR **)pvOut && pInput->pv) { FD_KERNINGPAIR *pkpEnd = *(FD_KERNINGPAIR **)pvOut; while ((pkpEnd->wcFirst) || (pkpEnd->wcSecond) || (pkpEnd->fwdKern)) { pkpEnd += 1; cjSize++; } cjSize = (cjSize + 1) * sizeof(FD_KERNINGPAIR); ASSERTGDI(pInput->cjMaxData >= cjSize, "gdi32!GdiPrinterThunk: not enough buffer for Kerningpairs\n"); if (pInput->cjMaxData >= cjSize) { RtlCopyMemory(pInput->pv, (PBYTE)(*(FD_KERNINGPAIR **)pvOut), cjSize); } else { WARNING(("Not enough buffer forkerningpair cjMaxData: 0x%lx cjSize: 0x%lx pInput.pv %lp pvOut %lp\n", pInput->cjMaxData, cjSize, pInput->pv, pvOut)); pInput->cjMaxData = 0; iRet = -1; } } } break; case INDEX_DrvQueryFontData: { PQUERYFONTDATAINPUT pInput = (PQUERYFONTDATAINPUT)pvIn; PUMDHPDEV pUMdhpdev = (PUMDHPDEV)(pInput->dhpdev); PUMPD pUMPD = pUMdhpdev->pUMPD; PFN pfn = pUMPD->apfn[INDEX_DrvQueryFontData]; *((ULONG *) pvOut) = (ULONG)pfn (pUMdhpdev->dhpdev, pInput->pfo, pInput->iMode, pInput->hg, pInput->pgd, pInput->pv, pInput->cjSize); } break; case INDEX_DrvQueryAdvanceWidths: { PQUERYADVWIDTHSINPUT pInput = (PQUERYADVWIDTHSINPUT)pvIn; PUMDHPDEV pUMdhpdev = (PUMDHPDEV)(pInput->dhpdev); PUMPD pUMPD = pUMdhpdev->pUMPD; PFN pfn = pUMPD->apfn[INDEX_DrvQueryAdvanceWidths]; *((BOOL *) pvOut) = (BOOL)pfn (pUMdhpdev->dhpdev, pInput->pfo, pInput->iMode, pInput->phg, pInput->pvWidths, pInput->cGlyphs); } break; case INDEX_DrvGetGlyphMode: { PQUERYFONTDATAINPUT pInput = (PQUERYFONTDATAINPUT)pvIn; PUMDHPDEV pUMdhpdev = (PUMDHPDEV)(pInput->dhpdev); PUMPD pUMPD = pUMdhpdev->pUMPD; PFN pfn = pUMPD->apfn[INDEX_DrvGetGlyphMode]; *((ULONG *) pvOut) = (ULONG) pfn (pUMdhpdev->dhpdev, pInput->pfo); } break; case INDEX_DrvFontManagement: { PFONTMANAGEMENTINPUT pInput = (PFONTMANAGEMENTINPUT)pvIn; PUMDHPDEV pUMdhpdev; PUMPD pUMPD; PFN pfn; if (pInput->iMode == QUERYESCSUPPORT) pUMdhpdev = (PUMDHPDEV) pInput->dhpdev; else pUMdhpdev = AdjustUMdhpdev(pInput->pso); pUMPD = pUMdhpdev->pUMPD; pfn = pUMPD->apfn[INDEX_DrvFontManagement]; *((ULONG *) pvOut) = (ULONG)pfn(pInput->pso, pInput->pfo, pInput->iMode, pInput->cjIn, pInput->pvIn, pInput->cjOut, pInput->pvOut); } break; case INDEX_DrvDitherColor: { PDRVDITHERCOLORINPUT pInput = (PDRVDITHERCOLORINPUT)pvIn; PUMDHPDEV pUMdhpdev = (PUMDHPDEV)pInput->dhpdev; PUMPD pUMPD = pUMdhpdev->pUMPD; PFN pfn = pUMPD->apfn[INDEX_DrvDitherColor]; *((ULONG *) pvOut) = (ULONG)pfn(pUMdhpdev->dhpdev, pInput->iMode, pInput->rgb, pInput->pul); } break; case INDEX_DrvDeleteDeviceBitmap: { PDRVDELETEDEVBITMAP pInput = (PDRVDELETEDEVBITMAP) pvIn; PUMDHPDEV pUMdhpdev = (PUMDHPDEV) pInput->dhpdev; PUMPD pUMPD = pUMdhpdev->pUMPD; PFN pfn = pUMPD->apfn[INDEX_DrvDeleteDeviceBitmap]; pfn(pUMdhpdev->dhpdev, pInput->dhsurf); } break; case INDEX_DrvIcmDeleteColorTransform: { PDRVICMDELETECOLOR pInput = (PDRVICMDELETECOLOR)pvIn; PUMDHPDEV pUMdhpdev = (PUMDHPDEV) pInput->dhpdev; PUMPD pUMPD = pUMdhpdev->pUMPD; PFN pfn = pUMPD->apfn[INDEX_DrvIcmDeleteColorTransform]; *((BOOL *) pvOut) = (BOOL)pfn(pUMdhpdev->dhpdev, pInput->hcmXform); } break; case INDEX_DrvIcmCreateColorTransform: { PDRVICMCREATECOLORINPUT pInput = (PDRVICMCREATECOLORINPUT) pvIn; PUMDHPDEV pUMdhpdev = (PUMDHPDEV) pInput->dhpdev; PUMPD pUMPD = pUMdhpdev->pUMPD; PFN pfn = pUMPD->apfn[INDEX_DrvIcmCreateColorTransform]; *((HANDLE *) pvOut) = (HANDLE)pfn(pUMdhpdev->dhpdev, pInput->pLogColorSpace, pInput->pvSourceProfile, pInput->cjSourceProfile, pInput->pvDestProfile, pInput->cjDestProfile, pInput->pvTargetProfile, pInput->cjTargetProfile, pInput->dwReserved); } break; case INDEX_DrvIcmCheckBitmapBits: { PDRVICMCHECKBITMAPINPUT pInput = (PDRVICMCHECKBITMAPINPUT) pvIn; PUMDHPDEV pUMdhpdev = (PUMDHPDEV) pInput->dhpdev; PUMPD pUMPD = pUMdhpdev->pUMPD; PFN pfn = pUMPD->apfn[INDEX_DrvIcmCheckBitmapBits]; pfn(pUMdhpdev->dhpdev, pInput->hColorTransform, pInput->pso, pInput->paResults); } break; case INDEX_DrvQueryDeviceSupport: { PDRVQUERYDEVICEINPUT pInput = (PDRVQUERYDEVICEINPUT) pvIn; PUMDHPDEV pUMdhpdev = AdjustUMdhpdev(pInput->pso); PUMPD pUMPD = pUMdhpdev->pUMPD; PFN pfn = pUMPD->apfn[INDEX_DrvQueryDeviceSupport]; *((ULONG *) pvOut) = (ULONG) pfn(pInput->pso, pInput->pxlo, pInput->pxo, pInput->iType, pInput->cjIn, pInput->pvIn, pInput->cjOut, pInput->pvOut); } break; case INDEX_UMPDAllocUserMem: { PUMPDALLOCUSERMEMINPUT pInput = (PUMPDALLOCUSERMEMINPUT) pvIn; ASSERTGDI(bWOW64, "Calling INDEX_UMPDAllocUserMem during NONE wow64 printing\n"); *((KERNEL_PVOID*)pvOut) = UMPDAllocUserMem(pInput->cjSize); } break; case INDEX_UMPDCopyMemory: { PUMPDCOPYMEMINPUT pInput = (PUMPDCOPYMEMINPUT) pvIn; ASSERTGDI(bWOW64, "Calling INDEX_UMPDCopyMemory during NONE wow64 printing\n"); *((KERNEL_PVOID*)pvOut) = UMPDCopyMemory(pInput->pvSrc, pInput->pvDest, pInput->cjSize); } break; case INDEX_UMPDFreeMemory: { PUMPDFREEMEMINPUT pInput = (PUMPDFREEMEMINPUT) pvIn; ASSERTGDI(bWOW64, "Calling INDEX_UMPDFreeMemory during NONE wow64 printing\n"); *((BOOL*)pvOut) = UMPDFreeMemory(pInput->pvTrg, pInput->pvSrc, pInput->pvMsk); } break; case INDEX_UMPDEngFreeUserMem: { PUMPDFREEMEMINPUT pInput = (PUMPDFREEMEMINPUT) pvIn; if (bWOW64) { *((BOOL*)pvOut) = NtGdiUMPDEngFreeUserMem(&pInput->pvTrg); } } break; default: WARNING ("Drv call is not supported\n"); iRet = GPT_ERROR; break; } if (bSetPUMPD) { NtGdiSetPUMPDOBJ(hSaved, FALSE, &pumpdthdr->humpd, NULL); } return (iRet); } #endif // !_GDIPLUS_