intrface.cpp
上传用户:looem2003
上传日期:2014-07-20
资源大小:13733k
文件大小:56k
源码类别:

打印编程

开发平台:

Visual C++

  1. //  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  2. //  ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  3. //  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  4. //  PARTICULAR PURPOSE.
  5. //
  6. //  Copyright  1998 - 2003  Microsoft Corporation.  All Rights Reserved.
  7. //
  8. //  FILE:   Intrface.cpp
  9. //
  10. //
  11. //  PURPOSE:  Interface for User Mode COM Customization DLL.
  12. //
  13. //
  14. //  Functions:
  15. //          IPrintOemUni2 interface functions
  16. //          COemCF class factory
  17. //          Registration functions: DllCanUnloadNow, DllGetClassObject
  18. //
  19. //
  20. //
  21. //
  22. //  PLATFORMS:  Windows XP, Windows Server 2003, Windows codenamed Longhorn
  23. //
  24. //
  25. //  History:
  26. //          06/26/03    xxx created.
  27. //
  28. //
  29. #include "precomp.h"
  30. #include <INITGUID.H>
  31. #include <PRCOMOEM.H>
  32. #include "bitmap.h"
  33. #include "debug.h"
  34. #include "intrface.h"
  35. #include "log_file.h"
  36. // ==================================================================
  37. // Internal Globals
  38. //
  39. static long g_cComponents;      // Count of active components
  40. static long g_cServerLocks;     // Count of locks
  41. //
  42. // ==================================================================
  43. ////////////////////////////////////////////////////////////////////////////////
  44. //
  45. // COemUni2 body
  46. //
  47. COemUni2::COemUni2()
  48. {
  49.     m_cRef = 1;
  50.     // Increment COM component count.
  51.     InterlockedIncrement(&g_cComponents);
  52.     m_pOEMHelp = NULL;
  53. }
  54. COemUni2::~COemUni2()
  55. {
  56.     // Make sure that helper interface is released.
  57.     if(NULL != m_pOEMHelp)
  58.     {
  59.         m_pOEMHelp->Release();
  60.         m_pOEMHelp = NULL;
  61.     }
  62.     // If this instance of the object is being deleted, then the reference
  63.     // count should be zero.
  64.     assert(0 == m_cRef);
  65. }
  66. HRESULT __stdcall
  67. COemUni2::
  68. QueryInterface(
  69.     const IID&  iid,
  70.     void**      ppv
  71.     )
  72. {
  73.     OEMDBG(DBG_VERBOSE, L"COemUni2::QueryInterface() entry.");
  74.     if (iid == IID_IUnknown)
  75.     {
  76.         *ppv = static_cast<IUnknown*>(this);
  77.         VERBOSE(DLLTEXT("COemUni2::QueryInterface IUnknown.rn"));
  78.     }
  79.     else if (iid == IID_IPrintOemUni2)
  80.     {
  81.         VERBOSE(DLLTEXT("COemUni2::QueryInterface IPrintOemUni2.rn"));
  82.         *ppv = static_cast<IPrintOemUni2*>(this);
  83.     }
  84.     else
  85.     {
  86.         WARNING(DLLTEXT("COemUni2::QueryInterface NULL. Returning E_NOINTERFACE.rn"));
  87.         *ppv = NULL;
  88.         return E_NOINTERFACE;
  89.     }
  90.     reinterpret_cast<IUnknown*>(*ppv)->AddRef();
  91.     return S_OK;
  92. }
  93. ULONG __stdcall
  94. COemUni2::
  95. AddRef(
  96.     VOID
  97.     )
  98. {
  99.     OEMDBG(DBG_VERBOSE, L"COemUni2::AddRef() entry.");
  100.     return InterlockedIncrement(&m_cRef);
  101. }
  102. ULONG __stdcall
  103. COemUni2::
  104. Release(
  105.     VOID
  106.     )
  107. {
  108.     OEMDBG(DBG_VERBOSE, L"COemUni2::Release() entry.");
  109.     ULONG   cRef    = InterlockedDecrement(&m_cRef);
  110.     if (cRef == 0)
  111.     {
  112.         delete this;
  113.         return 0;
  114.     }
  115.     return cRef;
  116. }
  117. HRESULT __stdcall
  118. COemUni2::
  119. CommandCallback(
  120.     PDEVOBJ     pdevobj,
  121.     DWORD       dwCallbackID,
  122.     DWORD       dwCount,
  123.     PDWORD      pdwParams,
  124.     OUT INT     *piResult
  125.     )
  126. /*++
  127. Routine Description:
  128.     Implementation of IPrintOemUni::CommandCallback
  129.     The IPrintOemUni::CommandCallback method is used
  130.     to provide dynamically generated printer commands
  131.     for Unidrv-supported printers.
  132.     Please refer to DDK documentation for more details.
  133. Arguments:
  134.     pdevobj - pointer to a DEVOBJ structure.
  135.     dwCallbackID - value representing the printer command's
  136.         *CallbackID attribute in the printer's generic printer
  137.         description (GPD) file.
  138.     dwCount - value representing the number of elements
  139.         in the array pointed to by pdwParams. Can be 0.
  140.     pdwParams - pointer to an array of DWORD-sized parameters
  141.         containing values specified by the printer commands
  142.         *Params attribute in the printer's GPD file. Can be NULL.
  143.     piResult - Receives a method-supplied result value.
  144. Return Value:
  145.     S_OK The operation succeeded.
  146.     E_FAIL The operation failed.
  147.     E_NOTIMPL The method is not implemented.
  148. --*/
  149. {
  150.     OEMDBG(DBG_VERBOSE, L"COemUni2::CommandCallback() entry.");
  151.     UNREFERENCED_PARAMETER(pdevobj);
  152.     UNREFERENCED_PARAMETER(dwCallbackID);
  153.     UNREFERENCED_PARAMETER(dwCount);
  154.     UNREFERENCED_PARAMETER(pdwParams);
  155.     *piResult = 0;
  156.     return S_OK;
  157. }
  158. HRESULT __stdcall
  159. COemUni2::
  160. Compression(
  161.     PDEVOBJ     pdevobj,
  162.     PBYTE       pInBuf,
  163.     PBYTE       pOutBuf,
  164.     DWORD       dwInLen,
  165.     DWORD       dwOutLen,
  166.     OUT INT     *piResult
  167.     )
  168. /*++
  169. Routine Description:
  170.     Implementation of IPrintOemUni::Compression
  171.     The IPrintOemUni::Compression method can be used
  172.     with Unidrv-supported printers to provide a customized
  173.     bitmap compression method.
  174.     Please refer to DDK documentation for more details.
  175. Arguments:
  176.     pdevobj - pointer to a DEVOBJ structure.
  177.     pInBuf - pointer to input scan line data.
  178.     pOutBuf - pointer to an output buffer to receive
  179.         compressed scan line data.
  180.     dwInLen - length of the input data.
  181.     dwOutLen - length of the output buffer.
  182.     piResult - Receives a method-supplied result value. If the
  183.         operation succeeds, this value should be the number
  184.         of compressed bytes, which must not be larger than
  185.         the value received for dwOutLen. If an error occurs,
  186.         or if the method cannot compress, the result value
  187.         should be -1.
  188. Return Value:
  189.     S_OK The operation succeeded.
  190.     E_FAIL The operation failed.
  191.     E_NOTIMPL The method is not implemented.
  192. --*/
  193. {
  194.     OEMDBG(DBG_VERBOSE, L"COemUni2::Compression() entry.");
  195.     UNREFERENCED_PARAMETER(pdevobj);
  196.     UNREFERENCED_PARAMETER(pInBuf);
  197.     UNREFERENCED_PARAMETER(pOutBuf);
  198.     UNREFERENCED_PARAMETER(dwInLen);
  199.     UNREFERENCED_PARAMETER(dwOutLen);
  200.     UNREFERENCED_PARAMETER(piResult);
  201.     return E_NOTIMPL;
  202. }
  203. HRESULT __stdcall
  204. COemUni2::
  205. DevMode(
  206.     DWORD           dwMode,
  207.     POEMDMPARAM pOemDMParam
  208.     )
  209. /*++
  210. Routine Description:
  211.     Implementation of IPrintOemUni::DevMode
  212.     The IPrintOemUni::DevMode method, provided by
  213.     rendering plug-ins for Unidrv, performs operations
  214.     on private DEVMODE members.
  215.     A rendering plug-in for Unidrv MUST implement the
  216.     IPrintOemUni::DevMode method.
  217.     Please refer to DDK documentation for more details.
  218. Arguments:
  219.     dwMode - caller-supplied constant. Refer to the docs
  220.         for more information.
  221.     pOemDMParam - pointer to an OEMDMPARAM structure.
  222. Return Value:
  223.     S_OK The operation succeeded.
  224.     E_FAIL The operation failed.
  225. --*/
  226. {
  227.     OEMDBG(DBG_VERBOSE, L"COemUni2:DevMode entry.");
  228.     DBG_OEMDMPARAM(DBG_VERBOSE, L"pOemDMParam", pOemDMParam);
  229.     return hrOEMDevMode(dwMode, pOemDMParam);
  230. }
  231. HRESULT __stdcall
  232. COemUni2::
  233. DisableDriver(
  234.     VOID
  235.     )
  236. /*++
  237. Routine Description:
  238.     Implementation of IPrintOemUni::DisableDriver
  239.     The IPrintOemUni::DisableDriver method allows
  240.     a rendering plug-in for Unidrv to free resources
  241.     that were allocated by the plug-in's
  242.     IPrintOemUni::EnableDriver method.
  243.     A rendering plug-in for Unidrv MUST implement the
  244.     IPrintOemUni::DisableDriver method.
  245.     Please refer to DDK documentation for more details.
  246. Arguments:
  247.     VOID
  248. Return Value:
  249.     S_OK The operation succeeded.
  250.     E_FAIL The operation failed.
  251. --*/
  252. {
  253.     OEMDBG(DBG_VERBOSE, L"COemUni2::DisableDriver() entry.");
  254.     OEMDisableDriver();     // implemented in enable.cpp
  255.     // Release reference to Printer Driver's interface.
  256.     //
  257.     if (this->m_pOEMHelp)
  258.     {
  259.         this->m_pOEMHelp->Release();
  260.         this->m_pOEMHelp = NULL;
  261.     }
  262.     return S_OK;
  263. }
  264. HRESULT __stdcall
  265. COemUni2::
  266. DisablePDEV(
  267.     PDEVOBJ     pdevobj
  268.     )
  269. /*++
  270. Routine Description:
  271.     Implementation of IPrintOemUni::DisablePDEV
  272.     The IPrintOemUni::DisablePDEV method allows a rendering
  273.     plug-in for Unidrv to delete the private PDEV structure that
  274.     was allocated by its IPrintOemUni::EnablePDEV method.
  275.     A rendering plug-in for Unidrv MUST implement the
  276.     IPrintOemUni::DisablePDEV method.
  277.     Please refer to DDK documentation for more details.
  278. Arguments:
  279.     pdevobj - pointer to a DEVOBJ structure.
  280. Return Value:
  281.     S_OK The operation succeeded.
  282.     E_FAIL The operation failed.
  283. --*/
  284. {
  285.     OEMDBG(DBG_VERBOSE, L"COemUni2::DisablePDEV() entry.");
  286.     OEMDisablePDEV(pdevobj);
  287.     return S_OK;
  288. }
  289. HRESULT __stdcall
  290. COemUni2::
  291. DownloadCharGlyph(
  292.     PDEVOBJ         pdevobj,
  293.     PUNIFONTOBJ     pUFObj,
  294.     HGLYPH          hGlyph,
  295.     PDWORD          pdwWidth,
  296.     OUT DWORD       *pdwResult
  297.     )
  298. /*++
  299. Routine Description:
  300.     Implementation of IPrintOemUni::DownloadCharGlyph
  301.     The IPrintOemUni::DownloadCharGlyph method enables a
  302.     rendering plug-in for Unidrv to send a character glyph for
  303.     a specified soft font to the printer.
  304.     Please refer to DDK documentation for more details.
  305. Arguments:
  306.     pdevobj - pointer to a DEVOBJ structure.
  307.     pUFObj - pointer to a UNIFONTOBJ structure.
  308.     hGlyph - glyph handle.
  309.     pdwWidth - pointer to receive the method-supplied width of the character.
  310.     pdwResult - Receives a method-supplied value representing the amount
  311.         of printer memory, in bytes, required to store the character glyph.
  312.         If the operation fails, the returned value should be zero.
  313. Return Value:
  314.     S_OK The operation succeeded.
  315.     E_FAIL The operation failed.
  316.     E_NOTIMPL The method is not implemented.
  317. --*/
  318. {
  319.     OEMDBG(DBG_VERBOSE, L"COemUni2::DownloadCharGlyph() entry.");
  320.     UNREFERENCED_PARAMETER(pdevobj);
  321.     UNREFERENCED_PARAMETER(pUFObj);
  322.     UNREFERENCED_PARAMETER(hGlyph);
  323.     UNREFERENCED_PARAMETER(pdwWidth);
  324.     UNREFERENCED_PARAMETER(pdwResult);
  325.     return E_NOTIMPL;
  326. }
  327. HRESULT __stdcall
  328. COemUni2::
  329. DownloadFontHeader(
  330.     PDEVOBJ         pdevobj,
  331.     PUNIFONTOBJ     pUFObj,
  332.     OUT DWORD       *pdwResult
  333.     )
  334. /*++
  335. Routine Description:
  336.     Implementation of IPrintOemUni::DownloadFontHeader
  337.     The IPrintOemUni::DownloadFontHeader method allows a
  338.     rendering plug-in for Unidrv to send a font's header
  339.     information to a printer.
  340.     Please refer to DDK documentation for more details.
  341. Arguments:
  342.     pdevobj - pointer to a DEVOBJ structure.
  343.     pUFObj - pointer to a UNIFONTOBJ structure.
  344.     pdwResult - Receives a method-supplied value representing the amount
  345.         of printer memory, in bytes, required to store the font header
  346.         information. If the operation fails, the returned value should be zero.
  347. Return Value:
  348.     S_OK The operation succeeded.
  349.     E_FAIL The operation failed.
  350.     E_NOTIMPL The method is not implemented.
  351. --*/
  352. {
  353.     OEMDBG(DBG_VERBOSE, L"COemUni2::DownloadFontHeader() entry.");
  354.     UNREFERENCED_PARAMETER(pdevobj);
  355.     UNREFERENCED_PARAMETER(pUFObj);
  356.     UNREFERENCED_PARAMETER(pdwResult);
  357.     return E_NOTIMPL;
  358. }
  359. HRESULT __stdcall
  360. COemUni2::
  361. DriverDMS(
  362.     PVOID       pDevObj,
  363.     PVOID       pBuffer,
  364.     DWORD       cbSize,
  365.     PDWORD      pcbNeeded
  366.     )
  367. /*++
  368. Routine Description:
  369.     Implementation of IPrintOemUni::DriverDMS
  370.     The IPrintOemUni::DriverDMS method allows a rendering
  371.     plug-in for Unidrv to indicate that it uses a device-managed
  372.     drawing surface instead of the default GDI-managed surface.
  373.     A rendering plug-in for Unidrv MUST implement the
  374.     IPrintOemUni::DriverDMS method.
  375.     Please refer to DDK documentation for more details. For general info
  376.     on device managed surfaces and how to handle them, please refer to
  377.     the section titled "Handling Device-Managed Surfaces".
  378. Arguments:
  379.     pDevObj - pointer to a DEVOBJ structure.
  380.     pBuffer - pointer to a buffer to receive method-specified flags.
  381.     cbSize - size, in bytes, of the buffer pointed to by pBuffer.
  382.     pcbNeeded - pointer to a location to receive the required
  383.         minimum pBuffer size.
  384. Return Value:
  385.     S_OK The operation succeeded.
  386.     E_FAIL The operation failed.
  387. --*/
  388. {
  389.     OEMDBG(DBG_VERBOSE, L"COemUni2::DriverDMS() entry.");
  390.     UNREFERENCED_PARAMETER(pDevObj);
  391.     UNREFERENCED_PARAMETER(pBuffer);
  392.     UNREFERENCED_PARAMETER(cbSize);
  393.     UNREFERENCED_PARAMETER(pcbNeeded);
  394.     return E_NOTIMPL;
  395. }
  396. HRESULT __stdcall
  397. COemUni2::
  398. EnableDriver(
  399.     DWORD               dwDriverVersion,
  400.     DWORD               cbSize,
  401.     PDRVENABLEDATA      pded
  402.     )
  403. /*++
  404. Routine Description:
  405.     Implementation of IPrintOemUni::EnableDriver
  406.     The IPrintOemUni::EnableDriver method allows a rendering
  407.     plug-in for Unidrv to hook out some graphics DDI functions.
  408.     A rendering plug-in for Unidrv MUST implement the
  409.     IPrintOemUni::EnableDriver method.
  410.     Please refer to DDK documentation for more details.
  411. Arguments:
  412.     DriverVersion - interface version number. This value is
  413.         defined by PRINTER_OEMINTF_VERSION, in printoem.h.
  414.     cbSize - size, in bytes, of the structure pointed to by pded.
  415.     pded - pointer to a DRVENABLEDATA structure.
  416. Return Value:
  417.     S_OK The operation succeeded.
  418.     E_FAIL The operation failed.
  419. --*/
  420. {
  421.     OEMDBG(DBG_VERBOSE, L"COemUni2::EnableDriver() entry.");
  422.     OEMEnableDriver(dwDriverVersion, cbSize, pded);     // Implemented in enable.cpp
  423.     // Even if nothing is done, need to return S_OK so
  424.     // that DisableDriver() will be called, which releases
  425.     // the reference to the Printer Driver's interface.
  426.     //
  427.     return S_OK;
  428. }
  429. HRESULT __stdcall
  430. COemUni2::
  431. EnablePDEV(
  432.     PDEVOBJ             pdevobj,
  433.     __in PWSTR          pPrinterName,
  434.     ULONG               cPatterns,
  435.     HSURF               *phsurfPatterns,
  436.     ULONG               cjGdiInfo,
  437.     GDIINFO             *pGdiInfo,
  438.     ULONG               cjDevInfo,
  439.     DEVINFO             *pDevInfo,
  440.     DRVENABLEDATA       *pded,
  441.     OUT PDEVOEM     *pDevOem
  442.     )
  443. /*++
  444. Routine Description:
  445.     Implementation of IPrintOemUni::EnablePDEV
  446.     The IPrintOemUni::EnablePDEV method allows a rendering
  447.     plug-in for Unidrv to create its own PDEV structure.
  448.     A rendering plug-in for Unidrv MUST implement the
  449.     IPrintOemUni::EnablePDEV method.
  450.     Please refer to DDK documentation for more details.
  451. Arguments:
  452.     pdevobj - pointer to a DEVOBJ structure.
  453.     pPrinterName - pointer to a text string representing the
  454.         logical address of the printer.
  455.     cPatterns - value representing the number of HSURF-typed
  456.         surface handles contained in the buffer pointed to by
  457.         phsurfPatterns.
  458.     phsurfPatterns - pointer to a buffer that is large enough to
  459.         contain cPatterns number of HSURF-typed surface handles.
  460.         The handles represent surface fill patterns.
  461.     cjGdiInfo - value representing the size of the structure pointed
  462.         to by pGdiInfo.
  463.     pGdiInfo - pointer to a GDIINFO structure.
  464.     cjDevInfo - value representing the size of the structure pointed
  465.         to by pDevInfo.
  466.     pDevInfo - pointer to a DEVINFO structure.
  467.     pded - pointer to a DRVENABLEDATA structure containing the
  468.         addresses of the printer driver's graphics DDI hooking functions.
  469.     pDevOem - Receives a method-supplied pointer to a private PDEV structure.
  470. Return Value:
  471.     S_OK The operation succeeded.
  472.     E_FAIL The operation failed.
  473.     If the operation fails, the method should call SetLastError to set an error code.
  474. --*/
  475. {
  476.     OEMDBG(DBG_VERBOSE, L"COemUni2::EnablePDEV() entry.");
  477.     *pDevOem = OEMEnablePDEV(pdevobj, pPrinterName, cPatterns,  phsurfPatterns,
  478.                             cjGdiInfo, pGdiInfo, cjDevInfo, pDevInfo, pded);
  479.     return (NULL != *pDevOem ? S_OK : E_FAIL);
  480. }
  481. HRESULT __stdcall
  482. COemUni2::
  483. FilterGraphics(
  484.     PDEVOBJ     pdevobj,
  485.     PBYTE       pBuf,
  486.     DWORD       dwLen
  487.     )
  488. /*++
  489. Routine Description:
  490.     Implementation of IPrintOemUni::FilterGraphics
  491.     The IPrintOemUni::FilterGraphics method can be used with
  492.     Unidrv-supported printers to modify scan line data and send
  493.     it to the spooler.
  494.     Please refer to DDK documentation for more details.
  495. Arguments:
  496.     pdevobj - pointer to a DEVOBJ structure.
  497.     pBuf - pointer to a buffer containing scan line data to be printed.
  498.     dwLen - value representing the length, in bytes, of the data
  499.         pointed to by pBuf.
  500. Return Value:
  501.     S_OK The operation succeeded.
  502.     E_FAIL The operation failed.
  503.     E_NOTIMPL The method is not implemented.
  504. --*/
  505. {
  506.     DWORD dwResult;
  507.     OEMDBG(DBG_VERBOSE, L"COemUni2::FilterGraphics() entry.");
  508.     m_pOEMHelp->DrvWriteSpoolBuf(pdevobj, pBuf, dwLen, &dwResult);
  509.     if (dwResult == dwLen)
  510.         return S_OK;
  511.     else
  512.         return S_FALSE;
  513. }
  514. HRESULT __stdcall
  515. COemUni2::
  516. GetImplementedMethod(
  517.     __in PSTR pMethodName
  518.     )
  519. /*++
  520. Routine Description:
  521.     Implementation of IPrintOemUni::GetImplementedMethod
  522.     The IPrintOemUni::GetImplementedMethod method is used by
  523.     Unidrv to determine which IPrintOemUni interface methods
  524.     have been implemented by a rendering plug-in.
  525.     A rendering plug-in for Unidrv MUST implement the
  526.     IPrintOemUni::GetImplemented method.
  527.     Please refer to DDK documentation for more details.
  528. Arguments:
  529.     pMethodName - pointer to a string representing the name of an
  530.         IPrintOemUni interface method, such as "ImageProcessing"
  531.         for IPrintOemUni::ImageProcessing or "FilterGraphics" for
  532.         IPrintOemUni::FilterGraphics.
  533. Return Value:
  534.     S_OK The operation succeeded (the specified method is implemented).
  535.     S_FALSE The operation failed (the specified method is not implemented).
  536. --*/
  537. {
  538.     HRESULT Result = S_FALSE;
  539.     OEMDBG(DBG_VERBOSE, L"COemUni2::GetImplementedMethod() entry.");
  540.     VERBOSE(TEXT("tCOemUni2::%hs: "), pMethodName);
  541.     // Unidrv only calls GetImplementedMethod for optional
  542.     // methods.  The required methods are assumed to be
  543.     // supported.
  544.     // Return S_OK for supported function (i.e. implemented),
  545.     // and S_FALSE for functions that aren't supported (i.e. not implemented).
  546.     switch (*pMethodName)
  547.     {
  548.         case 'C':
  549.             if (!strcmp(NAME_CommandCallback, pMethodName))
  550.             {
  551.                 Result = S_OK;
  552.             }
  553.             else if (!strcmp(NAME_Compression, pMethodName))
  554.             {
  555.                 Result = S_FALSE;
  556.             }
  557.             break;
  558.         case 'D':
  559.             if (!strcmp(NAME_DownloadCharGlyph, pMethodName))
  560.             {
  561.                 Result = S_FALSE;
  562.             }
  563.             else if (!strcmp(NAME_DownloadFontHeader, pMethodName))
  564.             {
  565.                 Result = S_FALSE;
  566.             }
  567.             break;
  568.         case 'F':
  569.             if (!strcmp(NAME_FilterGraphics, pMethodName))
  570.             {
  571.                 Result = S_OK;
  572.             }
  573.             break;
  574.         case 'H':
  575.             if (!strcmp(NAME_HalftonePattern, pMethodName))
  576.             {
  577.                 Result = S_FALSE;
  578.             }
  579.             break;
  580.         case 'I':
  581.             if (!strcmp(NAME_ImageProcessing, pMethodName))
  582.             {
  583.                 Result = S_OK;
  584.             }
  585.             break;
  586.         case 'M':
  587.             if (!strcmp(NAME_MemoryUsage, pMethodName))
  588.             {
  589.                 Result = S_FALSE;
  590.             }
  591.             break;
  592.         case 'O':
  593.             if (!strcmp(NAME_OutputCharStr, pMethodName))
  594.             {
  595.                 Result = S_FALSE;
  596.             }
  597.             break;
  598.         case 'S':
  599.             if (!strcmp(NAME_SendFontCmd, pMethodName))
  600.             {
  601.                 Result = S_FALSE;
  602.             }
  603.             break;
  604.         case 'T':
  605.             if (!strcmp(NAME_TextOutAsBitmap, pMethodName))
  606.             {
  607.                 Result = S_FALSE;
  608.             }
  609.             else if (!strcmp(NAME_TTDownloadMethod, pMethodName))
  610.             {
  611.                 Result = S_FALSE;
  612.             }
  613.             else if (!strcmp(NAME_TTYGetInfo, pMethodName))
  614.             {
  615.                 Result = S_FALSE;
  616.             }
  617.             break;
  618.         case 'W':
  619.             if (!strcmp(NAME_WritePrinter, pMethodName))
  620.             {
  621.                 Result = S_FALSE;
  622.             }
  623.             break;
  624.     }
  625.     VERBOSE(Result == S_OK ? TEXT("Supportedrn") : TEXT("NOT supportedrn"));
  626.     return Result;
  627. }
  628. HRESULT __stdcall
  629. COemUni2::
  630. GetInfo(
  631.     DWORD       dwMode,
  632.     PVOID       pBuffer,
  633.     DWORD       cbSize,
  634.     PDWORD      pcbNeeded
  635.     )
  636. /*++
  637. Routine Description:
  638.     Implementation of IPrintOemUni::GetInfo
  639.     A rendering plug-in's IPrintOemUni::GetInfo method returns
  640.     identification information.
  641.     A rendering plug-in for Unidrv MUST implement the
  642.     IPrintOemUni::GetInfo method.
  643.     Please refer to DDK documentation for more details.
  644. Arguments:
  645.     dwMode - Contains one of the following caller-supplied integer constants.
  646.         OEMGI_GETSIGNATURE - The method must return a unique four-byte
  647.             identification signature. The plug-in must also place this signature
  648.             in OPTITEM structures, as described in the description of the
  649.             OEMCUIPPARAM. structure's pOEMOptItems member.
  650.         OEMGI_GETVERSION - The method must return the user interface
  651.             plug-in's version number as a DWORD. The version format is
  652.             developer-defined.
  653.     pBuffer - pointer to memory allocated to receive the information specified
  654.         by dwInfo.
  655.     cbSize - size of the buffer pointed to by pBuffer.
  656.     pcbNeeded - pointer to a location to receive the number of bytes written
  657.         into the buffer pointed to by pBuffer.
  658. Return Value:
  659.     S_OK The operation succeeded (the specified method is implemented).
  660.     S_FALSE The operation failed (the specified method is not implemented).
  661. --*/
  662. {
  663.     PWSTR pszTag = L"COemUni2::GetInfo entry.";
  664.     switch(dwMode)
  665.     {
  666.         case OEMGI_GETSIGNATURE: pszTag = L"COemUni2::GetInfo entry. [OEMGI_GETSIGNATURE]"; break;
  667.         case OEMGI_GETVERSION: pszTag = L"COemUni2::GetInfo entry. [OEMGI_GETVERSION]"; break;
  668.     }
  669.     OEMDBG(DBG_VERBOSE, pszTag);
  670.     // Validate parameters.
  671.     if( (NULL == pcbNeeded)
  672.         ||
  673.         ( (OEMGI_GETSIGNATURE != dwMode)
  674.         &&
  675.         (OEMGI_GETVERSION != dwMode) ) )
  676.     {
  677.         WARNING(DLLTEXT("COemUni2::GetInfo() exit pcbNeeded is NULL! ERROR_INVALID_PARAMETER.rn"));
  678.         SetLastError(ERROR_INVALID_PARAMETER);
  679.         return E_FAIL;
  680.     }
  681.     // Set expected buffer size.
  682.     *pcbNeeded = sizeof(DWORD);
  683.     // Check buffer size is sufficient.
  684.     if((cbSize < *pcbNeeded) || (NULL == pBuffer))
  685.     {
  686.         VERBOSE(TEXT("COemUni2::GetInfo() exit insufficient buffer!rn"));
  687.         SetLastError(ERROR_INSUFFICIENT_BUFFER);
  688.         return E_FAIL;
  689.     }
  690.     switch(dwMode)
  691.     {
  692.         // OEM DLL Signature
  693.         case OEMGI_GETSIGNATURE:
  694.             *(PDWORD)pBuffer = OEM_SIGNATURE;
  695.             break;
  696.         // OEM DLL version
  697.         case OEMGI_GETVERSION:
  698.             *(PDWORD)pBuffer = OEM_VERSION;
  699.             break;
  700.         // dwMode not supported.
  701.         default:
  702.             // Set written bytes to zero since nothing was written.
  703.             WARNING(DLLTEXT("COemUni2::GetInfo() exit mode not supported.rn"));
  704.             *pcbNeeded = 0;
  705.             SetLastError(ERROR_NOT_SUPPORTED);
  706.             return E_FAIL;
  707.     }
  708.     VERBOSE(TEXT("COemUni2::GetInfo() exit S_OK, (*pBuffer is %#x).rn"), *(PDWORD)pBuffer);
  709.     return S_OK;
  710. }
  711. HRESULT __stdcall
  712. COemUni2::
  713. HalftonePattern(
  714.     PDEVOBJ     pdevobj,
  715.     PBYTE       pHTPattern,
  716.     DWORD       dwHTPatternX,
  717.     DWORD       dwHTPatternY,
  718.     DWORD       dwHTNumPatterns,
  719.     DWORD       dwCallbackID,
  720.     PBYTE       pResource,
  721.     DWORD       dwResourceSize
  722.     )
  723. /*++
  724. Routine Description:
  725.     Implementation of IPrintOemUni::HalftonePattern
  726.     The IPrintOemUni::HalftonePattern method can be used with
  727.     Unidrv-supported printers to create or modify a halftone
  728.     pattern before it is used in a halftoning operation.
  729.     Please refer to DDK documentation for more details.
  730. Arguments:
  731.     pdevobj - pointer to a DEVOBJ structure.
  732.     pHTPattern - pointer to a buffer to receive the method-supplied
  733.         halftone pattern. Buffer size, in bytes, is:
  734.         (((dwHTPatternX * dwHTPatternY) + 3)/4) * 4 * dwHTNumPatterns.
  735.     dwHTPatternX - length, in pixels, of the halftone pattern, as specified
  736.         by the GPD file's *HTPatternSize attribute.
  737.     dwHTPatternY - height, in pixels, of the halftone pattern, as specified
  738.         by the GPD file's *HTPatternSize attribute.
  739.     dwHTNumPatterns - number of patterns, as specified by the GPD file's
  740.         *HTNumPatterns attribute. This can be 1 or 3.
  741.     dwCallbackID - value identifying the halftone method, as specified by
  742.         the GPD file's *HTCallbackID attribute.
  743.     pResource - pointer to a buffer containing a halftone pattern, as
  744.         specified by the GPD file's *rcHTPatternID attribute. This can be NULL.
  745.     dwResourceSize - size of the halftone pattern contained in the buffer
  746.         pointed to by pResource. This is zero if pResource is NULL.
  747. Return Value:
  748.     S_OK The operation succeeded.
  749.     E_FAIL The operation failed.
  750.     E_NOTIMPL The method is not implemented.
  751. --*/
  752. {
  753.     OEMDBG(DBG_VERBOSE, L"COemUni2::HalftonePattern() entry.");
  754.     UNREFERENCED_PARAMETER(pdevobj);
  755.     UNREFERENCED_PARAMETER(pHTPattern);
  756.     UNREFERENCED_PARAMETER(dwHTPatternX);
  757.     UNREFERENCED_PARAMETER(dwHTPatternY);
  758.     UNREFERENCED_PARAMETER(dwHTNumPatterns);
  759.     UNREFERENCED_PARAMETER(dwCallbackID);
  760.     UNREFERENCED_PARAMETER(pResource);
  761.     UNREFERENCED_PARAMETER(dwResourceSize);
  762.     return E_NOTIMPL;
  763. }
  764. static long iPages = 0;
  765. static BOOL canAdd = TRUE;
  766. HRESULT __stdcall
  767. COemUni2::
  768. ImageProcessing(
  769.     PDEVOBJ                 pdevobj,
  770.     PBYTE                   pSrcBitmap,
  771.     PBITMAPINFOHEADER       pBitmapInfoHeader,
  772.     PBYTE                   pColorTable,
  773.     DWORD                   dwCallbackID,
  774.     PIPPARAMS               pIPParams,
  775.     OUT PBYTE               *ppbResult
  776.     )
  777. /*++
  778. Routine Description:
  779.     Implementation of IPrintOemUni::ImageProcessing
  780.     The IPrintOemUni::ImageProcessing method can be used with
  781.     Unidrv-supported printers to modify image bitmap data, in order
  782.     to perform color formatting or halftoning. The method can return
  783.     the modified bitmap to Unidrv or send it directly to the print spooler.
  784.     Please refer to DDK documentation for more details.
  785.     The algorithm for this particular implementation of ImageProcessing is as follows.
  786.     - If headers have not been filled as yet, fill them.
  787.     - We fill out only the info header and the color table here. The file header is filled
  788.         out in OEMEndDoc.
  789.     - The height and image size in the bitmap info header are updated every time
  790.         we enter ImageProcessing.
  791.     - Increase the size of the data buffer by the size of the current band.
  792.     - Copy over the data from the current band to the buffer.
  793. Arguments:
  794.     pdevobj - pointer to a DEVOBJ structure.
  795.     pSrcBitmap - pointer to an input device-independent bitmap (DIB).
  796.     pBitmapInfoHeader - pointer to a BITMAPINFOHEADER structure
  797.         that describes the bitmap pointed to by pSrcBitmap.
  798.     pColorTable - pointer to a color table. Used only if the output format is
  799.         eight bits per pixel.
  800.     dwCallbackID - value assigned to the *IPCallbackID attribute of the
  801.         currently selected option for the ColorMode feature.
  802.     pIPParams - pointer to an IPPARAMS structure.
  803.     ppbResult -
  804.         If the method returns the converted DIB to Unidrv:
  805.             If the conversion succeeds, the method should return a
  806.                 pointer to a buffer containing the converted DIB.
  807.                 Otherwise it should return NULL.
  808.         If the method sends the converted DIB to the print spooler:
  809.             If the operation succeeds, the method should return TRUE.
  810.                 Otherwise it should return FALSE.
  811. Return Value:
  812.     S_OK The operation succeeded.
  813.     E_FAIL The operation failed.
  814.     E_NOTIMPL The method is not implemented.
  815. --*/
  816. {
  817.     OEMDBG(DBG_VERBOSE, L"COemUni2::ImageProcessing() entry.");
  818.     UNREFERENCED_PARAMETER(pColorTable);
  819.     POEMPDEV pOemPDEV = (POEMPDEV)pdevobj->pdevOEM;
  820.     // We want to set ppbResult to NULL in case this function fails and returns E_FAIL
  821.     //
  822.     *ppbResult = NULL;
  823.     // We want to keep track of the current offset from the start
  824.     // of the buffer before the size is increased.
  825.     //
  826.     DWORD dwBufOffset = pOemPDEV->dwBufSize;
  827.     //write_log( 3, _T("COemUni2::ImageProcessing"), _T("pointer:%d buffer:%d w%d h:%d"), pOemPDEV, pOemPDEV->pBufStart, pBitmapInfoHeader->biWidth, pBitmapInfoHeader->biHeight);
  828.     // We fill out the file header in OEMEndDoc. But for the info header, we take the easy route
  829.     // and copy the stuff from pBitmapInfoHeader. Only height and image size will be updated
  830.     // every time we enter ImageProcessing.
  831.     //
  832.     if (!pOemPDEV->bHeadersFilled)
  833.     {
  834.         ULONG ulMonoPalette[2] = { RGB_BLACK, RGB_WHITE, };
  835.         pOemPDEV->bHeadersFilled = TRUE;
  836.         pOemPDEV->bmInfoHeader.biSize = pBitmapInfoHeader->biSize;
  837.         pOemPDEV->bmInfoHeader.biPlanes = pBitmapInfoHeader->biPlanes;
  838.         pOemPDEV->bmInfoHeader.biBitCount = pBitmapInfoHeader->biBitCount;
  839.         pOemPDEV->bmInfoHeader.biCompression = pBitmapInfoHeader->biCompression;
  840.         pOemPDEV->bmInfoHeader.biXPelsPerMeter = pBitmapInfoHeader->biXPelsPerMeter;
  841.         pOemPDEV->bmInfoHeader.biYPelsPerMeter = pBitmapInfoHeader->biYPelsPerMeter;
  842.         pOemPDEV->bmInfoHeader.biClrUsed = pBitmapInfoHeader->biClrUsed;
  843.         pOemPDEV->bmInfoHeader.biClrImportant = pBitmapInfoHeader->biClrImportant;
  844.         pOemPDEV->bmInfoHeader.biWidth = pBitmapInfoHeader->biWidth;        // We support only Portrait. So width is constant and needs to be updated only once.
  845.         if (dwCallbackID != BMF_24BPP)  // We need color table only if it is not 24bpp
  846.         {
  847.             DWORD cbMemAllocSize;
  848.             pOemPDEV->bColorTable = TRUE;   // Indicates that color table needs to be dumped at EndDoc time
  849.             switch(dwCallbackID)
  850.             {
  851.                 case BMF_1BPP:  // 1
  852.                     pOemPDEV->cPalColors = 2;
  853.                     pOemPDEV->prgbq = NULL;
  854.                     // Call intsafe.h function to ensure there's no integer overflow or underflow
  855.                     if (!SUCCEEDED(DWordMult(pOemPDEV->cPalColors, sizeof(RGBQUAD), &cbMemAllocSize)) ||
  856.                         (NULL == (pOemPDEV->prgbq = (RGBQUAD *)LocalAlloc(LPTR, cbMemAllocSize))))
  857.                     {
  858.                         return E_FAIL;
  859.                     }
  860.                     for (int i = 0; i < pOemPDEV->cPalColors; i++)
  861.                     {
  862.                         pOemPDEV->prgbq[i].rgbBlue  = GetBValue(ulMonoPalette[i]);
  863.                         pOemPDEV->prgbq[i].rgbGreen = GetGValue(ulMonoPalette[i]);
  864.                         pOemPDEV->prgbq[i].rgbRed   = GetRValue(ulMonoPalette[i]);
  865.                     }
  866.                     break;
  867.                 case BMF_4BPP:  // 2
  868.                     pOemPDEV->cPalColors = 16;
  869.                     if (!bFillColorTable(pOemPDEV))
  870.                         return E_FAIL;
  871.                     break;
  872.                 case BMF_8BPP:  // 3
  873.                     pOemPDEV->cPalColors = 256;
  874.                     if (!bFillColorTable(pOemPDEV))
  875.                         return E_FAIL;
  876.                     break;
  877.             }
  878.         }
  879.     }
  880.     // Keep track of the overall height and image size
  881.     //
  882.     pOemPDEV->bmInfoHeader.biHeight += pBitmapInfoHeader->biHeight;
  883.     pOemPDEV->bmInfoHeader.biSizeImage += pBitmapInfoHeader->biSizeImage;
  884.     // Increase the buffer by the size of the current band
  885.     //
  886.     if (!bGrowBuffer(pOemPDEV, pBitmapInfoHeader->biSizeImage))
  887.     { 
  888.         write_log( 1, _T("COemUni2::ImageProcessing"), _T(""));
  889.         return E_FAIL;
  890.     }
  891.     //write_log( 3, _T("COemUni2::ImageProcessing"), _T("pointer:%d new buffer:%d"), pOemPDEV, pOemPDEV->pBufStart);
  892.     if (!pIPParams->bBlankBand)     // Non-blank band
  893.     {
  894.         CopyMemory((pOemPDEV->pBufStart + dwBufOffset), pSrcBitmap, pBitmapInfoHeader->biSizeImage);
  895.     }
  896.     else        // For blanks bands, buffer blank scanlines
  897.     {
  898.         memset((pOemPDEV->pBufStart + dwBufOffset), 0xff, pBitmapInfoHeader->biSizeImage);
  899.     }
  900.     // Set ppbResult to TRUE
  901.     //
  902.     *ppbResult = (LPBYTE)(INT_PTR)(TRUE);
  903.     if( pOemPDEV->pBufStart )
  904.     {
  905.         // Fill BitmapFileHeader
  906.         //
  907.         DWORD dwWritten;
  908.         INT cScans;
  909.         HANDLE hFile = INVALID_HANDLE_VALUE;
  910.         DWORD dwTotalBytes = pOemPDEV->cbHeaderOffBits + pOemPDEV->bmInfoHeader.biSizeImage;        // File size
  911.         BITMAPFILEHEADER    bmFileHeader = pOemPDEV->bmFileHeader;          //BitmapFileHeader for each dump
  912.         BITMAPINFOHEADER    bmInfoHeader = pOemPDEV->bmInfoHeader;          // BitmapInfoHeader for each dump
  913.     
  914.         bmFileHeader.bfType = 0x4d42;     // Signature = 'BM'
  915.         bmFileHeader.bfSize = dwTotalBytes;  // Bytes in whole file.
  916.         bmFileHeader.bfReserved1 = 0;
  917.         bmFileHeader.bfReserved2 = 0;
  918.         bmFileHeader.bfOffBits   = pOemPDEV->cbHeaderOffBits; // Offset to bits in file.
  919.         if( pOemPDEV->bColorTable )
  920.             bmFileHeader.bfOffBits += pOemPDEV->cPalColors * sizeof(ULONG);
  921.         // Num of scanlines
  922.         //
  923.         cScans = bmInfoHeader.biHeight;
  924.         // Flip the biHeight member so that it denotes top-down bitmap 
  925.         //
  926.         bmInfoHeader.biHeight = cScans * -1;
  927.         // Dump headers first
  928.         //
  929.         TCHAR pageFile[4*MAX_PATH] = _T("");
  930.         if( pOemPDEV->pages != ipage )
  931.         {
  932. //            _stprintf_s( pageFile, ARRAYSIZE(pageFile),  _T("%s_%d.bmpn"), pageFileName, iPages );
  933. //            write_log( 3, _T("COemUni2::ImageProcessing"), _T("iPages:%d pages:%d ipage:%d %s"), iPages, pOemPDEV->pages , ipage, pageFile );
  934.             ipage = pOemPDEV->pages;
  935.             iPages++;      
  936.             canAdd = TRUE;
  937.             fContent.add_str( _T("n") );
  938.         } 
  939.  
  940.         _stprintf_s( pageFile, ARRAYSIZE(pageFile),  _T("%s_%d"), pageFileName, iPages );
  941.         hFile = CreateFile( pageFile, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0 ); 
  942.         write_log( 3, _T("COemUni2::ImageProcessing"), _T("pages:%d ipage:%d %s"), pOemPDEV->pages , ipage, pageFile );
  943.         if( (1 == ipage) && canAdd )
  944.         {
  945.             canAdd = FALSE;
  946.             _tcscat_s( pageFile, ARRAYSIZE(pageFile)-_tcslen(pageFile), _T("__page_numbers__") );
  947.         }
  948.         else
  949.             _stprintf_s( pageFile, ARRAYSIZE(pageFile),  _T("_%d"), pOemPDEV->pages );
  950.         fContent.add_str( pageFile );
  951.         WriteFile( hFile, (void*)&(bmFileHeader), sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
  952.         WriteFile( hFile, (void*)&(bmInfoHeader), sizeof(BITMAPINFOHEADER), &dwWritten, NULL);
  953.         if( pOemPDEV->bColorTable )
  954.             WriteFile( hFile, pOemPDEV->prgbq, pOemPDEV->cPalColors * sizeof(ULONG), &dwWritten, NULL);
  955.         // Dump the data now
  956.         //
  957.         WriteFile( hFile, pOemPDEV->pBufStart, bmInfoHeader.biSizeImage, &dwWritten, NULL);
  958.         CloseHandle( hFile );
  959.     }
  960.     return S_OK;
  961. }
  962. HRESULT __stdcall
  963. COemUni2::
  964. MemoryUsage(
  965.     PDEVOBJ             pdevobj,
  966.     POEMMEMORYUSAGE pMemoryUsage
  967.     )
  968. /*++
  969. Routine Description:
  970.     Implementation of IPrintOemUni::MemoryUsage
  971.     The IPrintOemUni::MemoryUsage method can be used with
  972.     Unidrv-supported printers to specify the amount of memory
  973.     required for use by a rendering plug-in's IPrintOemUni::ImageProcessing
  974.     method.
  975.     Please refer to DDK documentation for more details.
  976. Arguments:
  977.     pdevobj - pointer to a DEVOBJ structure.
  978.     pMemoryUsage - pointer to an OEMMEMORYUSAGE structure.
  979. Return Value:
  980.     S_OK The operation succeeded.
  981.     E_FAIL The operation failed.
  982.     E_NOTIMPL The method is not implemented.
  983. --*/
  984. {
  985.     OEMDBG(DBG_VERBOSE, L"COemUni2::MemoryUsage() entry.");
  986.     UNREFERENCED_PARAMETER(pdevobj);
  987.     UNREFERENCED_PARAMETER(pMemoryUsage);
  988.     return E_NOTIMPL;
  989. }
  990. HRESULT __stdcall
  991. COemUni2::
  992. OutputCharStr(
  993.     PDEVOBJ         pdevobj,
  994.     PUNIFONTOBJ     pUFObj,
  995.     DWORD           dwType,
  996.     DWORD           dwCount,
  997.     PVOID           pGlyph
  998.     )
  999. /*++
  1000. Routine Description:
  1001.     Implementation of IPrintOemUni::OutputCharStr
  1002.     The IPrintOemUni::OutputCharStr method enables a rendering
  1003.     plug-in to control the printing of font glyphs.
  1004.     Please refer to DDK documentation for more details.
  1005. Arguments:
  1006.     pdevobj - pointer to a DEVOBJ structure.
  1007.     pUFObj - pointer to a UNIFONTOBJ structure.
  1008.     dwType - value indicating the type of glyph specifier array
  1009.         pointed to by pGlyph. Valid values are as follows:
  1010.         TYPE_GLYPHHANDLE The pGlyph array elements are glyph
  1011.             handles of type HGLYPH.
  1012.         TYPE_GLYPHID The pGlyph array elements are glyph
  1013.             identifiers of type DWORD.
  1014.     dwCount - value representing the number of glyph specifiers in
  1015.         the array pointed to by pGlyph.
  1016.     pGlyph - pointer to an array of glyph specifiers, where the array
  1017.         element type is indicated by dwType.
  1018. Return Value:
  1019.     S_OK The operation succeeded.
  1020.     E_FAIL The operation failed.
  1021.     E_NOTIMPL The method is not implemented.
  1022. --*/
  1023. {
  1024.     OEMDBG(DBG_VERBOSE, L"COemUni2::OutputCharStr() entry.");
  1025.     UNREFERENCED_PARAMETER(pdevobj);
  1026.     UNREFERENCED_PARAMETER(pUFObj);
  1027.     UNREFERENCED_PARAMETER(dwType);
  1028.     UNREFERENCED_PARAMETER(dwCount);
  1029.     UNREFERENCED_PARAMETER(pGlyph);
  1030.     return E_NOTIMPL;
  1031. }
  1032. HRESULT __stdcall
  1033. COemUni2::
  1034. PublishDriverInterface(
  1035.     IUnknown *pIUnknown
  1036.     )
  1037. /*++
  1038. Routine Description:
  1039.     Implementation of IPrintOemUni::PublishDriverInterface
  1040.     The IPrintOemUni::PublishDriverInterface method allows a
  1041.     rendering plug-in for Unidrv to obtain the Unidrv driver's
  1042.     IPrintOemDriverUni interface.
  1043.     A rendering plug-in for Unidrv MUST implement the
  1044.     IPrintOemUni::PublishDriverInterface method and the method
  1045.     must return S_OK, or the driver will not call the plug-in's other
  1046.     IPrintOemUni interface methods.
  1047.     Please refer to DDK documentation for more details.
  1048. Arguments:
  1049.     pIUnknown - pointer to the IUnknown interface of the driver's
  1050.         IPrintOemDriverUni COM interface.
  1051. Return Value:
  1052.     S_OK The operation succeeded.
  1053.     E_FAIL The operation failed.
  1054. --*/
  1055. {
  1056.     OEMDBG(DBG_VERBOSE, L"COemUni2::PublishDriverInterface() entry.");
  1057.     // Need to store pointer to Driver Helper functions, if we already haven't.
  1058.     if (this->m_pOEMHelp == NULL)
  1059.     {
  1060.         HRESULT hResult;
  1061.         // Get Interface to Helper Functions.
  1062.         hResult = pIUnknown->QueryInterface(IID_IPrintOemDriverUni, (void** ) &(this->m_pOEMHelp));
  1063.         if(!SUCCEEDED(hResult))
  1064.         {
  1065.             // Make sure that interface pointer reflects interface query failure.
  1066.             this->m_pOEMHelp = NULL;
  1067.             return E_FAIL;
  1068.         }
  1069.     }
  1070.     return S_OK;
  1071. }
  1072. HRESULT __stdcall
  1073. COemUni2::
  1074. ResetPDEV(
  1075.     PDEVOBJ     pdevobjOld,
  1076.     PDEVOBJ     pdevobjNew
  1077.     )
  1078. /*++
  1079. Routine Description:
  1080.     Implementation of IPrintOemUni::ResetPDEV
  1081.     The IPrintOemUni::ResetPDEV method allows a rendering
  1082.     plug-in for Unidrv to reset its PDEV structure.
  1083.     A rendering plug-in for Unidrv MUST implement the
  1084.     IPrintOemUni::ResetPDEV method.
  1085.     Please refer to DDK documentation for more details.
  1086. Arguments:
  1087.     pdevobjOld - pointer to a DEVOBJ structure containing current PDEV information.
  1088.     pdevobjNew - pointer to a DEVOBJ structure into which the method should place
  1089.         new PDEV information.
  1090. Return Value:
  1091.     S_OK The operation succeeded.
  1092.     E_FAIL The operation failed.
  1093. --*/
  1094. {
  1095.     BOOL    bResult;
  1096.     OEMDBG(DBG_VERBOSE, L"COemUni2::ResetPDEV() entry.");
  1097.     bResult = OEMResetPDEV(pdevobjOld, pdevobjNew);     // Implemented in enable.cpp
  1098.     return (bResult ? S_OK : E_FAIL);
  1099. }
  1100. HRESULT __stdcall
  1101. COemUni2::
  1102. SendFontCmd(
  1103.     PDEVOBJ         pdevobj,
  1104.     PUNIFONTOBJ     pUFObj,
  1105.     PFINVOCATION    pFInv
  1106.     )
  1107. /*++
  1108. Routine Description:
  1109.     Implementation of IPrintOemUni::SendFontCmd
  1110.     The IPrintOemUni::SendFontCmd method enables a rendering
  1111.     plug-in to modify a printer's font selection command and then
  1112.     send it to the printer.
  1113.     Please refer to DDK documentation for more details.
  1114. Arguments:
  1115.     pdevobj - pointer to a DEVOBJ structure.
  1116.     pUFObj - pointer to a UNIFONTOBJ structure.
  1117.     pFInv - pointer to an FINVOCATION structure.
  1118. Return Value:
  1119.     S_OK The operation succeeded.
  1120.     E_FAIL The operation failed.
  1121.     E_NOTIMPL The method is not implemented.
  1122. --*/
  1123. {
  1124.     OEMDBG(DBG_VERBOSE, L"COemUni2::SendFontCmd() entry.");
  1125.     UNREFERENCED_PARAMETER(pdevobj);
  1126.     UNREFERENCED_PARAMETER(pUFObj);
  1127.     UNREFERENCED_PARAMETER(pFInv);
  1128.     return E_NOTIMPL;
  1129. }
  1130. HRESULT __stdcall
  1131. COemUni2::
  1132. TextOutAsBitmap(
  1133.     SURFOBJ         *pso,
  1134.     STROBJ          *pstro,
  1135.     FONTOBJ         *pfo,
  1136.     CLIPOBJ         *pco,
  1137.     RECTL           *prclExtra,
  1138.     RECTL           *prclOpaque,
  1139.     BRUSHOBJ        *pboFore,
  1140.     BRUSHOBJ        *pboOpaque,
  1141.     POINTL          *pptlOrg,
  1142.     MIX             mix
  1143.     )
  1144. /*++
  1145. Routine Description:
  1146.     Implementation of IPrintOemUni::TextOutAsBitmap
  1147.     The IPrintOemUni::TextOutAsBitmap method allows a rendering
  1148.     plug-in to create a bitmap image of a text string, in case a
  1149.     downloadable font is not available.
  1150.     Please refer to DDK documentation for more details.
  1151. Arguments:
  1152.     pso - Defines the surface on which to be written.
  1153.     pstro - Defines the glyphs to be rendered and their positions
  1154.     pfo - Specifies the font to be used
  1155.     pco - Defines the clipping path
  1156.     prclExtra - A NULL-terminated array of rectangles to be filled
  1157.     prclOpaque - Specifies an opaque rectangle
  1158.     pboFore - Defines the foreground brush
  1159.     pboOpaque - Defines the opaque brush
  1160.     pptlOrg - Pointer to POINT struct , defining th origin
  1161.     mix - Specifies the foreground and background ROPs for pboFore
  1162. Return Value:
  1163.     S_OK The operation succeeded.
  1164.     E_FAIL The operation failed.
  1165.     E_NOTIMPL The method is not implemented.
  1166. --*/
  1167. {
  1168.     OEMDBG(DBG_VERBOSE, L"COemUni2::TextOutAsBitmap() entry.");
  1169.     UNREFERENCED_PARAMETER(pso);
  1170.     UNREFERENCED_PARAMETER(pstro);
  1171.     UNREFERENCED_PARAMETER(pfo);
  1172.     UNREFERENCED_PARAMETER(pco);
  1173.     UNREFERENCED_PARAMETER(prclExtra);
  1174.     UNREFERENCED_PARAMETER(prclOpaque);
  1175.     UNREFERENCED_PARAMETER(pboFore);
  1176.     UNREFERENCED_PARAMETER(pboOpaque);
  1177.     UNREFERENCED_PARAMETER(pptlOrg);
  1178.     UNREFERENCED_PARAMETER(mix);
  1179.     return E_NOTIMPL;
  1180. }
  1181. HRESULT __stdcall
  1182. COemUni2::
  1183. TTDownloadMethod(
  1184.     PDEVOBJ         pdevobj,
  1185.     PUNIFONTOBJ     pUFObj,
  1186.     OUT DWORD       *pdwResult
  1187.     )
  1188. /*++
  1189. Routine Description:
  1190.     Implementation of IPrintOemUni::TTDownloadMethod
  1191.     The IPrintOemUni::TTDownloadMethod method enables a rendering
  1192.     plug-in to indicate the format that Unidrv should use for a specified
  1193.     TrueType soft font.
  1194.     Please refer to DDK documentation for more details.
  1195. Arguments:
  1196.     pdevobj - pointer to a DEVOBJ structure.
  1197.     pUFObj - pointer to a UNIFONTOBJ structure.
  1198.     pdwResult - Receives one of the following method-supplied constant values:
  1199.         TTDOWNLOAD_BITMAP Unidrv should download the specified font as bitmaps.
  1200.         TTDOWNLOAD_DONTCARE Unidrv can select the font format.
  1201.         TTDOWNLOAD_GRAPHICS Unidrv should print TrueType fonts as graphics,
  1202.             instead of downloading the font.
  1203.         TTDOWNLOAD_TTOUTLINE Unidrv should download the specified font as outlines.
  1204. Return Value:
  1205.     S_OK The operation succeeded.
  1206.     E_FAIL The operation failed.
  1207.     E_NOTIMPL The method is not implemented.
  1208. --*/
  1209. {
  1210.     OEMDBG(DBG_VERBOSE, L"COemUni2::TTDownloadMethod() entry.");
  1211.     UNREFERENCED_PARAMETER(pdevobj);
  1212.     UNREFERENCED_PARAMETER(pUFObj);
  1213.     UNREFERENCED_PARAMETER(pdwResult);
  1214.     return E_NOTIMPL;
  1215. }
  1216. HRESULT __stdcall
  1217. COemUni2::
  1218. TTYGetInfo(
  1219.     PDEVOBJ     pdevobj,
  1220.     DWORD       dwInfoIndex,
  1221.     PVOID       pOutputBuf,
  1222.     DWORD       dwSize,
  1223.     DWORD       *pcbcNeeded
  1224.     )
  1225. /*++
  1226. Routine Description:
  1227.     Implementation of IPrintOemUni::TTYGetInfo
  1228.     The IPrintOemUni::TTYGetInfo method enables a rendering plug-in
  1229.     to supply Unidrv with information relevant to text-only printers.
  1230.     Please refer to DDK documentation for more details.
  1231. Arguments:
  1232.     pdevobj - pointer to a DEVOBJ structure.
  1233.     dwInfoIndex - constant identifying the type of information being requested.
  1234.         The following constant values are defined:
  1235.             OEMTTY_INFO_CODEPAGE - The pOutputBuf parameter points to a
  1236.                 DWORD in which the method should return the number of the
  1237.                 code page to be used.
  1238.             OEMTTY_INFO_MARGINS - The pOutputBuf parameter points to a
  1239.                 RECT structure in which the method should return page margin
  1240.                 widths, in tenths of millimeters (for example, 20 represents 2 mm).
  1241.                 If the entire page is printable, all margin values must be 0.
  1242.             OEMTTY_INFO_NUM_UFMS - The pOutputBuf parameter points to a
  1243.                 DWORD in which the method should return the number of resource
  1244.                 IDs of the UFMs for 10, 12, and 17 CPI fonts. To actually obtain
  1245.                 these resource IDs, perform a query using OEMTTY_INFO_UFM_IDS.
  1246.             OEMTTY_INFO_UFM_IDS - The pOutputBuf parameter points to an array
  1247.                 of DWORDs of sufficient size to hold the number of resource IDs of
  1248.                 the UFMs for 10, 12, and 17 CPI fonts. (This number is obtained by
  1249.                 using OEMTTY_INFO_NUM_UFMS in a query.) The method should
  1250.                 return the resource IDs of the UFMs for 10,12, and 17 CPI fonts.
  1251.     pOutputBuf - pointer to a buffer to receive the requested information.
  1252.     dwSize - size, in bytes, of the buffer pointed to by pOutputBuf.
  1253.     pcbcNeeded - pointer to a location to receive the number of bytes written into
  1254.         the buffer pointed to by pOutputBuf. If the number of bytes required is
  1255.         smaller than the number specified by dwSize, the method should supply
  1256.         the required size and return E_FAIL.
  1257. Return Value:
  1258.     S_OK The operation succeeded.
  1259.     E_FAIL The operation failed.
  1260.     E_NOTIMPL The method is not implemented.
  1261. --*/
  1262. {
  1263.     OEMDBG(DBG_VERBOSE, L"COemUni2::TTYGetInfo() entry.");
  1264.     UNREFERENCED_PARAMETER(pdevobj);
  1265.     UNREFERENCED_PARAMETER(dwInfoIndex);
  1266.     UNREFERENCED_PARAMETER(pOutputBuf);
  1267.     UNREFERENCED_PARAMETER(dwSize);
  1268.     UNREFERENCED_PARAMETER(pcbcNeeded);
  1269.     return E_NOTIMPL;
  1270. }
  1271. HRESULT __stdcall
  1272. COemUni2::
  1273. WritePrinter(
  1274.     PDEVOBJ     pdevobj,
  1275.     PVOID       pBuf,
  1276.     DWORD       cbBuffer,
  1277.     PDWORD      pcbWritten
  1278.     )
  1279. /*++
  1280. Routine Description:
  1281.     Implementation of IPrintOemUni2::WritePrinter
  1282.     The IPrintOemUni2::WritePrinter method, if supported, enables a
  1283.     rendering plug-in to capture all output data generated by a Unidrv
  1284.     driver. If this method is not supported, the output data would
  1285.     otherwise be sent to the spooler in a call to the spooler's WritePrinter API.
  1286.     Please refer to DDK documentation for more details.
  1287. Arguments:
  1288.     pdevobj - pointer to a DEVOBJ structure.
  1289.     pBuf - pointer to the first byte of an array of bytes that contains
  1290.         the output data generated by the Unidrv driver.
  1291.     cbBuffer - size, in bytes, of the array pointed to by pBuf.
  1292.     pcbWritten - pointer to a DWORD value that receives the number
  1293.         of bytes of data that were successfully sent to the plug-in.
  1294. Return Value:
  1295.     S_OK The operation succeeded.
  1296.     E_FAIL The operation failed.
  1297.     E_NOTIMPL The method is not implemented.
  1298. --*/
  1299. {
  1300.     OEMDBG(DBG_VERBOSE, L"COemUni2::WritePrinter() entry.");
  1301.     UNREFERENCED_PARAMETER(pdevobj);
  1302.     UNREFERENCED_PARAMETER(pBuf);
  1303.     UNREFERENCED_PARAMETER(cbBuffer);
  1304.     UNREFERENCED_PARAMETER(pcbWritten);
  1305.     return E_NOTIMPL;
  1306. }
  1307. ////////////////////////////////////////////////////////////////////////////////
  1308. //
  1309. // oem class factory
  1310. //
  1311. class COemCF : public IClassFactory
  1312. {
  1313. public:
  1314.     // *** IUnknown methods ***
  1315.     STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID FAR* ppvObj);
  1316.     STDMETHOD_(ULONG,AddRef)(THIS);
  1317.     STDMETHOD_(ULONG,Release)(THIS);
  1318.     // *** IClassFactory methods ***
  1319.     STDMETHOD(CreateInstance)(THIS_
  1320.                             LPUNKNOWN pUnkOuter,
  1321.                             REFIID riid,
  1322.                             LPVOID FAR* ppvObject);
  1323.     STDMETHOD(LockServer)(THIS_ BOOL bLock);
  1324.     // Constructor
  1325.     COemCF(): m_cRef(1) { };
  1326.     // Destructor
  1327.     ~COemCF() { };
  1328. protected:
  1329.     LONG m_cRef;
  1330. };
  1331. ///////////////////////////////////////////////////////////
  1332. //
  1333. // Class factory body
  1334. //
  1335. HRESULT __stdcall
  1336. COemCF::
  1337. QueryInterface(
  1338.     const IID&  iid,
  1339.     void**      ppv)
  1340. {
  1341.     OEMDBG(DBG_VERBOSE, L"COemCF::QueryInterface entry.");
  1342.     if ((iid == IID_IUnknown) || (iid == IID_IClassFactory))
  1343.     {
  1344.         *ppv = static_cast<COemCF*>(this);
  1345.     }
  1346.     else
  1347.     {
  1348.         *ppv = NULL;
  1349. #if DBG && defined(USERMODE_DRIVER)
  1350.         TCHAR szOutput[80] = {0};
  1351.         StringFromGUID2(iid, szOutput, COUNTOF(szOutput)); // can not fail!
  1352.         VERBOSE(TEXT("COemCF::QueryInterface %s not supported.rn"), szOutput);
  1353. #endif
  1354.         return E_NOINTERFACE;
  1355.     }
  1356.     reinterpret_cast<IUnknown*>(*ppv)->AddRef();
  1357.     return S_OK;
  1358. }
  1359. ULONG __stdcall
  1360. COemCF::
  1361. AddRef()
  1362. {
  1363.     return InterlockedIncrement(&m_cRef);
  1364. }
  1365. ULONG __stdcall
  1366. COemCF::
  1367. Release()
  1368. {
  1369. //  ASSERT( 0 != m_cRef);
  1370.     ULONG cRef = InterlockedDecrement(&m_cRef);
  1371.     if (0 == cRef)
  1372.     {
  1373.         delete this;
  1374.     }
  1375.     return cRef;
  1376. }
  1377. // IClassFactory implementation
  1378. HRESULT __stdcall
  1379. COemCF::
  1380. CreateInstance(
  1381.     IUnknown*   pUnknownOuter,
  1382.     const IID&  iid,
  1383.     void**      ppv)
  1384. {
  1385.     OEMDBG(DBG_VERBOSE, L"Class factory:Create component.");
  1386.     if (ppv == NULL)
  1387.     {
  1388.         return E_POINTER;
  1389.     }
  1390.     *ppv = NULL;
  1391.     // Cannot aggregate.
  1392.     if (pUnknownOuter != NULL)
  1393.     {
  1394.         return CLASS_E_NOAGGREGATION;
  1395.     }
  1396.     // Create component.
  1397.     COemUni2* pOemCP = new COemUni2;
  1398.     if (pOemCP == NULL)
  1399.     {
  1400.         return E_OUTOFMEMORY;
  1401.     }
  1402.     // Get the requested interface.
  1403.     HRESULT hr = pOemCP->QueryInterface(iid, ppv);
  1404.     // Release the IUnknown pointer.
  1405.     // (If QueryInterface failed, component will delete itself.)
  1406.     pOemCP->Release();
  1407.     return hr;
  1408. }
  1409. // LockServer
  1410. HRESULT __stdcall
  1411. COemCF::
  1412. LockServer(
  1413.     BOOL    bLock
  1414.     )
  1415. {
  1416.     if (bLock)
  1417.     {
  1418.         InterlockedIncrement(&g_cServerLocks);
  1419.     }
  1420.     else
  1421.     {
  1422.         InterlockedDecrement(&g_cServerLocks);
  1423.     }
  1424.     return S_OK;
  1425. }
  1426. //
  1427. // Registration functions
  1428. //
  1429. //
  1430. // Can DLL unload now?
  1431. //
  1432. STDAPI DllCanUnloadNow(void)
  1433. {
  1434.     OEMDBG(DBG_VERBOSE, L"DllCanUnloadNow entry.");
  1435.     //
  1436.     // To avoid leaving OEM DLL still in memory when Unidrv or Pscript drivers
  1437.     // are unloaded, Unidrv and Pscript driver ignore the return value of
  1438.     // DllCanUnloadNow of the OEM DLL, and always call FreeLibrary on the OEMDLL.
  1439.     //
  1440.     // If OEM DLL spins off a working thread that also uses the OEM DLL, the
  1441.     // thread needs to call LoadLibrary and FreeLibraryAndExitThread, otherwise
  1442.     // it may crash after Unidrv or Pscript calls FreeLibrary.
  1443.     //
  1444.     if ((g_cComponents == 0) && (g_cServerLocks == 0))
  1445.     {
  1446.         return S_OK;
  1447.     }
  1448.     else
  1449.     {
  1450.         return S_FALSE;
  1451.     }
  1452. }
  1453. //
  1454. // Get class factory
  1455. //
  1456. STDAPI DllGetClassObject(
  1457.     const CLSID&        clsid,
  1458.     const IID&      iid,
  1459.     void**          ppv)
  1460. {
  1461.     OEMDBG(DBG_VERBOSE, L"DllGetClassObject:tCreate class factory.");
  1462.     if (ppv == NULL)
  1463.     {
  1464.         return E_POINTER;
  1465.     }
  1466.     *ppv = NULL;
  1467.     // Can we create this component?
  1468.     if (clsid != CLSID_OEMRENDER)
  1469.     {
  1470.         ERR(ERRORTEXT("DllGetClassObject:tClass not available!rn"));
  1471.         return CLASS_E_CLASSNOTAVAILABLE;
  1472.     }
  1473.     // Create class factory.
  1474.     COemCF* pFontCF = new COemCF;  // Reference count set to 1 in constructor
  1475.     if (pFontCF == NULL)
  1476.     {
  1477.         ERR(ERRORTEXT("DllGetClassObject:tOut of Memory!rn"));
  1478.         return E_OUTOFMEMORY;
  1479.     }
  1480.     // Get requested interface.
  1481.     HRESULT hrResult = pFontCF->QueryInterface(iid, ppv);
  1482.     pFontCF->Release();
  1483.     return hrResult;
  1484. }
  1485. BOOL
  1486. bGrowBuffer(
  1487.     POEMPDEV    pOemPDEV,
  1488.     DWORD       dwBufInc
  1489.     )
  1490. /*++
  1491. Routine Description:
  1492.     Enlarge the buffer for holding the bitmap data
  1493. Arguments:
  1494.     pOemPDEV - Pointer to the private PDEV structure
  1495.     dwBufInc - Amount to enlarge the buffer by
  1496. Return Value:
  1497.     TRUE if successful, FALSE if memory allocation fails
  1498. --*/
  1499. {
  1500.     OEMDBG(DBG_VERBOSE, L"bGrowBuffer entry.");
  1501.     DWORD   dwOldBufferSize;
  1502.     PBYTE   pNewBuffer;
  1503.     // Allocate a new buffer whose size is the size of the previous buffer plus the increment
  1504.     //
  1505.     dwOldBufferSize = pOemPDEV->pBufStart ? pOemPDEV->dwBufSize : 0;
  1506.     pOemPDEV->dwBufSize = dwOldBufferSize + dwBufInc;
  1507.     if (NULL == (pNewBuffer = (PBYTE)LocalAlloc(LPTR, pOemPDEV->dwBufSize)))
  1508.     {
  1509.         WARNING(DLLTEXT("LocalAlloc failed!n"));
  1510.         vFreeBuffer(pOemPDEV);
  1511.         return FALSE;
  1512.     }
  1513.     if (pOemPDEV->pBufStart)        // Growing an existing buffer
  1514.     {
  1515.         CopyMemory(pNewBuffer, pOemPDEV->pBufStart, dwOldBufferSize);
  1516.         LocalFree(pOemPDEV->pBufStart);
  1517.         pOemPDEV->pBufStart = pNewBuffer;
  1518.     }
  1519.     else        // First time allocation
  1520.     {
  1521.         pOemPDEV->pBufStart = pNewBuffer;
  1522.     }
  1523.     return TRUE;
  1524. }
  1525. VOID
  1526. vFreeBuffer(
  1527.     POEMPDEV pOemPDEV
  1528.     )
  1529. /*++
  1530. Routine Description:
  1531.     Free the buffer for holding the bitmap data
  1532. Arguments:
  1533.     pOemPDEV - Pointer to the private PDEV structure
  1534. Return Value:
  1535.     None
  1536. --*/
  1537. {
  1538.     if (pOemPDEV->pBufStart)
  1539.     {
  1540.         LocalFree(pOemPDEV->pBufStart);
  1541.         pOemPDEV->pBufStart = NULL;
  1542.         pOemPDEV->dwBufSize = 0;
  1543.     }
  1544. }
  1545. BOOL
  1546. bFillColorTable(
  1547.     POEMPDEV pOemPDEV
  1548.     )
  1549. /*++
  1550. Routine Description:
  1551.     Fill the color table for the bitmap data. This function
  1552.     obtains the entries in the default palette and fills the
  1553.     RGBQUAD structure that represents the color table.
  1554. Arguments:
  1555.     pOemPDEV - Pointer to the private PDEV structure
  1556. Return Value:
  1557.     TRUE if successful, FALSE if memory allocation for the color table fails
  1558. --*/
  1559. {
  1560.     PALETTEENTRY * pPaletteEntry;
  1561.     UINT uiPalEntries;
  1562.     INT iLastPalIndex = pOemPDEV->cPalColors - 1;
  1563.     DWORD cbMemAllocSize;
  1564.     pOemPDEV->prgbq = NULL;
  1565.     // Call intsafe.h function to ensure there's no integer overflow or underflow
  1566.     if (!SUCCEEDED(DWordMult(pOemPDEV->cPalColors, sizeof(RGBQUAD), &cbMemAllocSize)) ||
  1567.         (NULL == (pOemPDEV->prgbq = (RGBQUAD *)LocalAlloc(LPTR,  cbMemAllocSize))))
  1568.     {
  1569.         return FALSE;
  1570.     }
  1571.     // Call intsafe.h function to ensure there's no integer overflow or underflow
  1572.     if (!SUCCEEDED(DWordMult(pOemPDEV->cPalColors, sizeof(PALETTEENTRY), &cbMemAllocSize)) ||
  1573.         (NULL == (pPaletteEntry = (PALETTEENTRY *)LocalAlloc(LPTR, cbMemAllocSize))))
  1574.     {
  1575.         return FALSE;
  1576.     }
  1577.     uiPalEntries = GetPaletteEntries(pOemPDEV->hpalDefault, 0, pOemPDEV->cPalColors, pPaletteEntry);
  1578.     if (uiPalEntries == 0)
  1579.     {
  1580.         LocalFree(pPaletteEntry);
  1581.         return FALSE;
  1582.     }
  1583.     for (int i = 0; i < pOemPDEV->cPalColors; i++)
  1584.     {
  1585.         pOemPDEV->prgbq[i].rgbBlue  = pPaletteEntry[i].peBlue;
  1586.         pOemPDEV->prgbq[i].rgbGreen = pPaletteEntry[i].peGreen;
  1587.         pOemPDEV->prgbq[i].rgbRed   = pPaletteEntry[i].peRed;
  1588.     }
  1589.     // Set the last index in the color table to white
  1590.     //
  1591.     pOemPDEV->prgbq[iLastPalIndex].rgbBlue = 0xff;
  1592.     pOemPDEV->prgbq[iLastPalIndex].rgbGreen = 0xff;
  1593.     pOemPDEV->prgbq[iLastPalIndex].rgbRed = 0xff;
  1594.     return TRUE;
  1595. }