/*++ Copyright (c) 1996-1999 Microsoft Corporation Module Name: intfuni.cpp Abstract: Interface implementation of Windows NT unidriver OEM rendering plugins Environment: Windows NT Unidriver. Revision History: 01/18/98 -ganeshp- Initial framework. --*/ #define INITGUID #include "unidrv.h" #ifdef WINNT_40 #include "cppfunc.h" #undef InterlockedIncrement #undef InterlockedDecrement #define InterlockedIncrement(x) DrvInterlockedIncrement(x) #define InterlockedDecrement(x) DrvInterlockedDecrement(x) int __cdecl _purecall (void) { return FALSE; } #endif // WINNT_40 #pragma hdrstop("unidrv.h") #include "prcomoem.h" // // List all of the supported OEM plugin interface IIDs from the // latest to the oldest, that's the order our driver will QI OEM // plugin for its supported interface. // // DON"T remove the last NULL terminator. // static const GUID *PrintOemUni_IIDs[] = { &IID_IPrintOemUni2, &IID_IPrintOemUni, NULL }; // // Component // class CPrintOemDriver : public IPrintOemDriverUni { // // IUnknown implementation // STDMETHODIMP QueryInterface(const IID& iid, void** ppv); STDMETHODIMP_(ULONG) AddRef(); STDMETHODIMP_(ULONG) Release(); // // Interface IPrintOemDriverUni implementation // STDMETHODIMP DrvGetDriverSetting(PVOID pdriverobj, PCSTR Feature, PVOID pOutput, DWORD cbSize, PDWORD pcbNeeded, PDWORD pdwOptionsReturned); STDMETHODIMP DrvWriteSpoolBuf(PDEVOBJ pdevobj, PVOID pBuffer, DWORD cbSize, OUT DWORD *pdwResult); // // Cursor movement helper functions. // STDMETHODIMP DrvXMoveTo(PDEVOBJ pdevobj, INT x, DWORD dwFlags, OUT INT *piResult); STDMETHODIMP DrvYMoveTo(PDEVOBJ pdevobj, INT y, DWORD dwFlags, OUT INT *piResult); // // Unidrv specific. To get the standard variable value. // STDMETHODIMP DrvGetStandardVariable(PDEVOBJ pdevobj, DWORD dwIndex, PVOID pBuffer, DWORD cbSize, PDWORD pcbNeeded); // // Unidrv specific. To Provide OEM plugins access to GPD data. // STDMETHODIMP DrvGetGPDData(PDEVOBJ pdevobj, DWORD dwType, // Type of the data PVOID pInputData, // reserved. Should be set to 0 PVOID pBuffer, // Caller allocated Buffer to be copied DWORD cbSize, // Size of the buffer PDWORD pcbNeeded // New Size of the buffer if needed. ); // // Unidrv specific. To do the TextOut. // STDMETHODIMP DrvUniTextOut(SURFOBJ *pso, STROBJ *pstro, FONTOBJ *pfo, CLIPOBJ *pco, RECTL *prclExtra, RECTL *prclOpaque, BRUSHOBJ *pboFore, BRUSHOBJ *pboOpaque, POINTL *pptlBrushOrg, MIX mix); STDMETHODIMP DrvWriteAbortBuf(PDEVOBJ pdevobj, PVOID pBuffer, DWORD cbSize, DWORD dwWait); public: // // Constructor // CPrintOemDriver() : m_cRef(0) {} private: long m_cRef; }; STDMETHODIMP CPrintOemDriver::QueryInterface(const IID& iid, void** ppv) { if (iid == IID_IUnknown || iid == IID_IPrintOemDriverUni) { *ppv = static_cast(this); } else { *ppv = NULL; return E_NOINTERFACE; } reinterpret_cast(*ppv)->AddRef(); return S_OK; } STDMETHODIMP_(ULONG) CPrintOemDriver::AddRef() { return InterlockedIncrement(&m_cRef); } STDMETHODIMP_(ULONG) CPrintOemDriver::Release() { if (InterlockedDecrement(&m_cRef) == 0) { delete this; return 0; } return m_cRef; } STDMETHODIMP CPrintOemDriver::DrvGetDriverSetting(PVOID pdriverobj, PCSTR Feature, PVOID pOutput, DWORD cbSize, PDWORD pcbNeeded, PDWORD pdwOptionsReturned) { if (BGetDriverSettingForOEM((PDEV *)pdriverobj, Feature, pOutput, cbSize, pcbNeeded, pdwOptionsReturned)) return S_OK; return E_FAIL; } STDMETHODIMP CPrintOemDriver::DrvWriteSpoolBuf(PDEVOBJ pdevobj, PVOID pBuffer, DWORD cbSize, OUT DWORD *pdwResult) { DWORD dwI; POEM_PLUGIN_ENTRY pOemEntry; // // OEM plug-ins may not call back to DrvWriteSpoolBuf during the // WritePrinter hook. // if (((PDEV*)pdevobj)->fMode2 & PF2_CALLING_OEM_WRITE_PRINTER) return E_FAIL; if (*pdwResult = WriteSpoolBuf((PDEV *)pdevobj, (PBYTE)pBuffer, cbSize)) { return S_OK; } *pdwResult = 0; return E_FAIL; } STDMETHODIMP CPrintOemDriver::DrvWriteAbortBuf(PDEVOBJ pdevobj, PVOID pBuffer, DWORD cbSize, DWORD dwWait) { DWORD dwI; POEM_PLUGIN_ENTRY pOemEntry; // // OEM Plug-ins may not call back to DrvWriteAbortBuf during the // WritePrinter hook. // if (((PDEV*)pdevobj)->fMode2 & PF2_CALLING_OEM_WRITE_PRINTER) return E_FAIL; WriteAbortBuf((PDEV *)pdevobj, (PBYTE)pBuffer, cbSize, dwWait) ; return S_OK; // no failure condition } // // Cursor movement helper functions. // STDMETHODIMP CPrintOemDriver::DrvXMoveTo(PDEVOBJ pdevobj, INT x, DWORD dwFlags, OUT INT *piResult) { *piResult = XMoveTo((PDEV *)pdevobj, x, dwFlags); return S_OK; } STDMETHODIMP CPrintOemDriver::DrvYMoveTo(PDEVOBJ pdevobj, INT y, DWORD dwFlags, OUT INT *piResult) { *piResult = YMoveTo((PDEV *)pdevobj, y, dwFlags); return S_OK; } // // Unidrv specific. To get the standard variable value. // STDMETHODIMP CPrintOemDriver::DrvGetStandardVariable(PDEVOBJ pdevobj, DWORD dwIndex, PVOID pBuffer, DWORD cbSize, PDWORD pcbNeeded) { if (BGetStandardVariable((PDEV *)pdevobj, dwIndex, pBuffer, cbSize, pcbNeeded)) return S_OK; return E_FAIL; } // // Unidrv specific. To Provide OEM plugins access to GPD data. // STDMETHODIMP CPrintOemDriver::DrvGetGPDData(PDEVOBJ pdevobj, DWORD dwType, // Type of the data PVOID pInputData, // reserved. Should be set to 0 PVOID pBuffer, // Caller allocated Buffer to be copied DWORD cbSize, // Size of the buffer PDWORD pcbNeeded // New Size of the buffer if needed. ) { if (BGetGPDData((PDEV *)pdevobj, dwType, pInputData, pBuffer, cbSize, pcbNeeded )) return S_OK; return E_FAIL; } // // Unidrv specific. To do the TextOut. // STDMETHODIMP CPrintOemDriver::DrvUniTextOut(SURFOBJ *pso, STROBJ *pstro, FONTOBJ *pfo, CLIPOBJ *pco, RECTL *prclExtra, RECTL *prclOpaque, BRUSHOBJ *pboFore, BRUSHOBJ *pboOpaque, POINTL *pptlBrushOrg, MIX mix) { if (FMTextOut(pso, pstro, pfo,pco, prclExtra, prclOpaque, pboFore, pboOpaque, pptlBrushOrg, mix)) { return S_OK; } return E_FAIL; } // // Creation function // extern "C" IUnknown* DriverCreateInstance() { IUnknown* pI = static_cast(new CPrintOemDriver); if (pI != NULL) pI->AddRef(); return pI; } extern "C" HRESULT HDriver_CoCreateInstance( IN REFCLSID rclsid, IN LPUNKNOWN pUnknownOuter, IN DWORD dwClsContext, IN REFIID riid, IN LPVOID *ppv, IN HANDLE hInstance ); // // Get OEM plugin interface and publish driver helper interface // extern "C" BOOL BGetOemInterface(POEM_PLUGIN_ENTRY pOemEntry) { IUnknown *pIDriverHelper = NULL; HRESULT hr; // // QI to retrieve the latest interface OEM plugin supports // if (!BQILatestOemInterface(pOemEntry->hInstance, CLSID_OEMRENDER, PrintOemUni_IIDs, &(pOemEntry->pIntfOem), &(pOemEntry->iidIntfOem))) { ERR(("BQILatestOemInterface failed\n")); return FALSE; } // // If QI succeeded, pOemEntry->pIntfOem will have the OEM plugin // interface pointer with ref count 1. // // // Publish driver's helper function interface // if ((pIDriverHelper = DriverCreateInstance()) == NULL) { ERR(("DriverCreateInstance failed\n")); goto fail_cleanup; } // // As long as we define new OEM plugin interface by inheriting old ones, // we can always cast pIntfOem into pointer of the oldest plugin interface // (the base class) and call PublishDriverInterface method. // // Otherwise, this code needs to be modified when new interface is added. // hr = ((IPrintOemUni *)(pOemEntry->pIntfOem))->PublishDriverInterface(pIDriverHelper); // // OEM plugin should do QI in their PublishDriverInterface, so we need to release // our ref count of pIDriverHelper. // pIDriverHelper->Release(); if (FAILED(hr)) { ERR(("PublishDriverInterface failed\n")); goto fail_cleanup; } return TRUE; fail_cleanup: // // If failed, we need to release the ref count we hold on pOemEntry->pIntfOem, // and set pIntfOem to NULL to indicate no COM interface is available. // ((IUnknown *)(pOemEntry->pIntfOem))->Release(); pOemEntry->pIntfOem = NULL; return FALSE; } // // CALL_INTRFACE macros // #define CALL_INTRFACE(MethodName, pOemEntry, args) \ if (IsEqualGUID(&(pOemEntry)->iidIntfOem, &IID_IPrintOemUni)) \ { \ return ((IPrintOemUni *)(pOemEntry)->pIntfOem)->MethodName args; \ } \ else if (IsEqualGUID(&(pOemEntry)->iidIntfOem, &IID_IPrintOemUni2)) \ { \ return ((IPrintOemUni2 *)(pOemEntry)->pIntfOem)->MethodName args; \ } \ return E_NOINTERFACE; #define CALL_INTRFACE2(MethodName, pOemEntry, args) \ if (IsEqualGUID(&(pOemEntry)->iidIntfOem, &IID_IPrintOemUni2)) \ { \ return ((IPrintOemUni2 *)(pOemEntry)->pIntfOem)->MethodName args; \ } \ return E_NOINTERFACE; // add additional else if (IsEqualGUID(&pOemEntry->iidIntfOem, &IID_IPrintOemUni2))\ // sections as needed as more interfaces are defined to CALL_INTRFACE macro. extern "C" HRESULT HComOEMGetInfo(POEM_PLUGIN_ENTRY pOemEntry, DWORD dwMode, PVOID pBuffer, DWORD cbSize, PDWORD pcbNeeded) { CALL_INTRFACE(GetInfo, pOemEntry, (dwMode, pBuffer, cbSize, pcbNeeded)); } extern "C" HRESULT HComOEMDevMode(POEM_PLUGIN_ENTRY pOemEntry, DWORD dwMode, POEMDMPARAM pOemDMParam) { CALL_INTRFACE(DevMode, pOemEntry, (dwMode, pOemDMParam)); } extern "C" HRESULT HComOEMEnableDriver(POEM_PLUGIN_ENTRY pOemEntry, DWORD DriverVersion, DWORD cbSize, PDRVENABLEDATA pded) { CALL_INTRFACE(EnableDriver, pOemEntry, (DriverVersion, cbSize, pded)); } extern "C" HRESULT HComOEMDisableDriver(POEM_PLUGIN_ENTRY pOemEntry) { CALL_INTRFACE(DisableDriver, pOemEntry, ()); } extern "C" HRESULT HComOEMEnablePDEV(POEM_PLUGIN_ENTRY pOemEntry, PDEVOBJ pdevobj, PWSTR pPrinterName, ULONG cPatterns, HSURF *phsurfPatterns, ULONG cjGdiInfo, GDIINFO *pGdiInfo, ULONG cjDevInfo, DEVINFO *pDevInfo, DRVENABLEDATA *pded, PDEVOEM *pDevOem) { CALL_INTRFACE(EnablePDEV, pOemEntry, (pdevobj, pPrinterName, cPatterns, phsurfPatterns, cjGdiInfo, pGdiInfo, cjDevInfo, pDevInfo, pded, pDevOem)); } extern "C" HRESULT HComOEMDisablePDEV( POEM_PLUGIN_ENTRY pOemEntry, PDEVOBJ pdevobj ) { CALL_INTRFACE(DisablePDEV, pOemEntry, (pdevobj)); } extern "C" HRESULT HComOEMResetPDEV( POEM_PLUGIN_ENTRY pOemEntry, PDEVOBJ pdevobjOld, PDEVOBJ pdevobjNew ) { CALL_INTRFACE(ResetPDEV, pOemEntry, (pdevobjOld, pdevobjNew)); } extern "C" HRESULT HComGetImplementedMethod( POEM_PLUGIN_ENTRY pOemEntry, PSTR pMethodName ) { CALL_INTRFACE(GetImplementedMethod, pOemEntry, (pMethodName)); } // // OEMDriverDMS - UNIDRV only, // extern "C" HRESULT HComDriverDMS( POEM_PLUGIN_ENTRY pOemEntry, PVOID pDevObj, PVOID pBuffer, WORD cbSize, PDWORD pcbNeeded ) { CALL_INTRFACE(DriverDMS, pOemEntry, (pDevObj, pBuffer, cbSize, pcbNeeded)); } // // OEMCommandCallback - UNIDRV only, // extern "C" HRESULT HComCommandCallback( POEM_PLUGIN_ENTRY pOemEntry, PDEVOBJ pdevobj, DWORD dwCallbackID, DWORD dwCount, PDWORD pdwParams, OUT INT *piResult ) { CALL_INTRFACE(CommandCallback, pOemEntry, (pdevobj, dwCallbackID, dwCount, pdwParams, piResult)); } // // OEMImageProcessing - UNIDRV only, // extern "C" HRESULT HComImageProcessing( POEM_PLUGIN_ENTRY pOemEntry, PDEVOBJ pdevobj, PBYTE pSrcBitmap, PBITMAPINFOHEADER pBitmapInfoHeader, PBYTE pColorTable, DWORD dwCallbackID, PIPPARAMS pIPParams, OUT PBYTE *ppbResult ) { CALL_INTRFACE(ImageProcessing, pOemEntry, (pdevobj, pSrcBitmap, pBitmapInfoHeader, pColorTable, dwCallbackID, pIPParams, ppbResult)); } // // OEMFilterGraphics - UNIDRV only, // extern "C" HRESULT HComFilterGraphics( POEM_PLUGIN_ENTRY pOemEntry, PDEVOBJ pdevobj, PBYTE pBuf, DWORD dwLen ) { CALL_INTRFACE(FilterGraphics, pOemEntry, (pdevobj, pBuf, dwLen)); } // // OEMCompression - UNIDRV only, // extern "C" HRESULT HComCompression( POEM_PLUGIN_ENTRY pOemEntry, PDEVOBJ pdevobj, PBYTE pInBuf, PBYTE pOutBuf, DWORD dwInLen, DWORD dwOutLen, OUT INT *piResult ) { CALL_INTRFACE(Compression, pOemEntry, (pdevobj, pInBuf, pOutBuf, dwInLen, dwOutLen, piResult)); } // // OEMHalftone - UNIDRV only // extern "C" HRESULT HComHalftonePattern( POEM_PLUGIN_ENTRY pOemEntry, PDEVOBJ pdevobj, PBYTE pHTPattern, DWORD dwHTPatternX, DWORD dwHTPatternY, DWORD dwHTNumPatterns, DWORD dwCallbackID, PBYTE pResource, DWORD dwResourceSize ) { CALL_INTRFACE(HalftonePattern, pOemEntry, (pdevobj, pHTPattern, dwHTPatternX, dwHTPatternY, dwHTNumPatterns, dwCallbackID, pResource, dwResourceSize)); } // // OEMMemoryUsage - UNIDRV only, // extern "C" HRESULT HComMemoryUsage( POEM_PLUGIN_ENTRY pOemEntry, PDEVOBJ pdevobj, POEMMEMORYUSAGE pMemoryUsage ) { CALL_INTRFACE(MemoryUsage, pOemEntry, (pdevobj, pMemoryUsage)); } // // OEMTTYGetInfo - UNIDRV only // extern "C" HRESULT HComTTYGetInfo( POEM_PLUGIN_ENTRY pOemEntry, PDEVOBJ pdevobj, DWORD dwInfoIndex, PVOID pOutputBuf, DWORD dwSize, DWORD *pcbcNeeded ) { CALL_INTRFACE(TTYGetInfo, pOemEntry, (pdevobj, dwInfoIndex, pOutputBuf, dwSize, pcbcNeeded)); } // // OEMDownloadFontheader - UNIDRV only // extern "C" HRESULT HComDownloadFontHeader( POEM_PLUGIN_ENTRY pOemEntry, PDEVOBJ pdevobj, PUNIFONTOBJ pUFObj, OUT DWORD *pdwResult ) { CALL_INTRFACE(DownloadFontHeader, pOemEntry, (pdevobj, pUFObj, pdwResult)); } // // OEMDownloadCharGlyph - UNIDRV only // extern "C" HRESULT HComDownloadCharGlyph( POEM_PLUGIN_ENTRY pOemEntry, PDEVOBJ pdevobj, PUNIFONTOBJ pUFObj, HGLYPH hGlyph, PDWORD pdwWidth, OUT DWORD *pdwResult ) { CALL_INTRFACE(DownloadCharGlyph, pOemEntry, (pdevobj, pUFObj, hGlyph, pdwWidth, pdwResult)); } // // OEMTTDownloadMethod - UNIDRV only // extern "C"HRESULT HComTTDownloadMethod( POEM_PLUGIN_ENTRY pOemEntry, PDEVOBJ pdevobj, PUNIFONTOBJ pUFObj, OUT DWORD *pdwResult ) { CALL_INTRFACE(TTDownloadMethod, pOemEntry, (pdevobj, pUFObj, pdwResult)); } // // OEMOutputCharStr - UNIDRV only // extern "C" HRESULT HComOutputCharStr( POEM_PLUGIN_ENTRY pOemEntry, PDEVOBJ pdevobj, PUNIFONTOBJ pUFObj, DWORD dwType, DWORD dwCount, PVOID pGlyph ) { CALL_INTRFACE(OutputCharStr, pOemEntry, (pdevobj, pUFObj, dwType, dwCount, pGlyph)); } // // OEMSendFontCmd - UNIDRV only // extern "C" HRESULT HComSendFontCmd( POEM_PLUGIN_ENTRY pOemEntry, PDEVOBJ pdevobj, PUNIFONTOBJ pUFObj, PFINVOCATION pFInv ) { CALL_INTRFACE(SendFontCmd, pOemEntry, (pdevobj, pUFObj, pFInv)); } // // OEMTextOutAsBitmap - UNIDRV only // HRESULT HComTextOutAsBitmap( POEM_PLUGIN_ENTRY pOemEntry, SURFOBJ *pso, STROBJ *pstro, FONTOBJ *pfo, CLIPOBJ *pco, RECTL *prclExtra, RECTL *prclOpaque, BRUSHOBJ *pboFore, BRUSHOBJ *pboOpaque, POINTL *pptlOrg, MIX mix ) { CALL_INTRFACE(TextOutAsBitmap, pOemEntry, (pso, pstro, pfo, pco, prclExtra, prclOpaque, pboFore, pboOpaque, pptlOrg, mix )); } extern "C" HRESULT HComWritePrinter(POEM_PLUGIN_ENTRY pOemEntry, PDEVOBJ pdevobj, PVOID pBuf, DWORD cbBuffer, PDWORD pcbWritten) { CALL_INTRFACE2(WritePrinter, pOemEntry, (pdevobj, pBuf, cbBuffer, pcbWritten)); } extern "C" ULONG ReleaseOemInterface(POEM_PLUGIN_ENTRY pOemEntry) { #ifdef WINNT_40 HRESULT hr; if (IsEqualGUID(&pOemEntry->iidIntfOem, &IID_IPrintOemUni)) \ { hr = ((IPrintOemUni *)(pOemEntry)->pIntfOem)->Release(); } #else // WINNT_40 CALL_INTRFACE(Release, pOemEntry, ()); #endif // WINNT_40 return 0; } #if CODE_COMPLETE #endif