sunpongber

生成基本的 v4 打印机驱动程序-dllentry.cpp

//
// File Name:
//
//    dllentry.cpp
//
// Abstract:
//
//    XPS Rendering Filter DLL entry points.
//

#include "precomp.h"
#include "WppTrace.h"
#include "CustomWppCommands.h"
#include "Exception.h"
#include "filtertypes.h"
#include "UnknownBase.h"
#include "RenderFilter.h"

#include "dllentry.tmh"

namespace MyV4PrintDriver_Render_Filter
{

//
// Class Factory returned by DllGetClassObject()
//
class __declspec(uuid("ccf3dccf-b589-48b9-ab27-fd463caf8855")) RenderFilterFactory : public UnknownBase<IClassFactory>
{
public:
    RenderFilterFactory() :
        m_serverLocks(0)
    {
        ::InterlockedIncrement(&RenderFilter::ms_numObjects);
    }

    ~RenderFilterFactory()
    {
        ::InterlockedDecrement(&RenderFilter::ms_numObjects);
    }

    //
    //Routine Name:
    //
    //    RenderFilterFactory::CreateInstance
    //
    //Routine Description:
    //
    //    Returns an instance of RenderFilter.
    //
    //Arguments:
    //
    //    pUnkOuter - Outer class (must be NULL)
    //    riid      - Requested interface (IPrintPipelineFilter)
    //    ppvObject - Pointer to the requested interface
    //
    //Return Value:
    //
    //    HRESULT
    //    S_OK      - On success
    //    Otherwise - Failure
    //
    HRESULT
    STDMETHODCALLTYPE
    CreateInstance(
        IUnknown    *pUnkOuter,
        REFIID      riid,
        void        **ppvObject
        )
    {
        HRESULT hr = S_OK;

        if (pUnkOuter != NULL)
        {
            WPP_LOG_ON_FAILED_HRESULT(CLASS_E_NOAGGREGATION);

            return CLASS_E_NOAGGREGATION;
        }

        if (ppvObject == NULL)
        {
            WPP_LOG_ON_FAILED_HRESULT(E_POINTER);

            return E_POINTER;
        }

        *ppvObject = NULL;

        MyV4PrintDriver_Render_Filter::RenderFilter *pFilter = NULL;

        //
        // RenderFilter::RenderFilter() can throw, as can new
        //
        try
        {
            DoTraceMessage(RENDERFILTER_TRACE_INFO, L"Instantiating filter");
            pFilter = new MyV4PrintDriver_Render_Filter::RenderFilter();
        }
        CATCH_VARIOUS(hr)

        if (SUCCEEDED(hr))
        {
            WPP_LOG_ON_FAILED_HRESULT(
                hr = pFilter->QueryInterface(riid, ppvObject)
                );

            pFilter->Release();
        }

        return hr;
    }

    //
    //Routine Name:
    //
    //    RenderFilterFactory::LockServer
    //
    //Routine Description:
    //
    //    Allows clients to lock the filter factory in
    //    memory.
    //
    //Arguments:
    //
    //    fLock - TRUE - lock; FALSE - unlock
    //
    //Return Value:
    //
    //    HRESULT
    //    S_OK      - On success
    //
    HRESULT
    STDMETHODCALLTYPE
    LockServer(
        BOOL    fLock
        )
    {
        LONG result;

        if (fLock)  // lock
        {
            result = ::InterlockedIncrement(&m_serverLocks);

            if (result == 1)
            {
                //
                // This was the first 'lock' call; increment the
                // global numObjects
                //
                ::InterlockedIncrement(&RenderFilter::ms_numObjects);
            }
        }
        else // unlock
        {
            result = ::InterlockedDecrement(&m_serverLocks);

            if (result == 0)
            {
                //
                // All locks have been unlocked; decrement the
                // global numObjects
                //
                ::InterlockedDecrement(&RenderFilter::ms_numObjects);
            }
        }

        return S_OK;
    }

private:
    volatile LONG m_serverLocks;
};

} // namespace MyV4PrintDriver_Render_Filter 

//
//Routine Name:
//
//    DllGetClassObject
//
//Routine Description:
//
//    Returns an instance of RenderFilterFactory.
//
//Arguments:
//
//    rclsid  - Requested class (RenderFilter)
//    riid    - Requested interface (IClassFactory)
//    ppv     - Pointer to the requested interface
//
//Return Value:
//
//    HRESULT
//    S_OK      - On success
//    Otherwise - Failure
//
STDAPI
DllGetClassObject(
    _In_ REFCLSID        rclsid,
    _In_ REFIID          riid,
    _Outptr_ LPVOID   *ppv
    )
{
    HRESULT hr = S_OK;

    if (ppv == NULL)
    {
        WPP_LOG_ON_FAILED_HRESULT(E_POINTER);

        return E_POINTER;
    }

    *ppv = NULL;

    if (rclsid != __uuidof(MyV4PrintDriver_Render_Filter::RenderFilterFactory))
    {
        WPP_LOG_ON_FAILED_HRESULT(CLASS_E_CLASSNOTAVAILABLE);

        return CLASS_E_CLASSNOTAVAILABLE;
    }

    DoTraceMessage(RENDERFILTER_TRACE_INFO, L"Instantiating class factory");

    MyV4PrintDriver_Render_Filter::RenderFilterFactory *pFactory = NULL;
    pFactory = new(std::nothrow) MyV4PrintDriver_Render_Filter::RenderFilterFactory();

    if (pFactory == NULL)
    {
        WPP_LOG_ON_FAILED_HRESULT(E_OUTOFMEMORY);

        hr = E_OUTOFMEMORY;
    }

    if (SUCCEEDED(hr))
    {
        WPP_LOG_ON_FAILED_HRESULT(
            hr = pFactory->QueryInterface(riid, ppv)
            );

        pFactory->Release();
    }

    return hr;
}

//
//Routine Name:
//
//    DllCanUnloadNow
//
//Routine Description:
//
//    Checks whether the DLL can be unloaded. That is,
//    whether there are any instances of RenderFilter.
//
//Arguments:
//
//    None
//
//Return Value:
//
//    HRESULT
//    S_OK      - Can unload.
//    Otherwise - Cannot unload.
//
STDAPI
DllCanUnloadNow()
{
    return (0 == MyV4PrintDriver_Render_Filter::RenderFilter::ms_numObjects) ? S_OK : S_FALSE;
}

//
//Routine Name:
//
//    DllMain
//
//Routine Description:
//
//    Initializes WPP tracing when the DLL is loaded
//    and cleans up WPP tracing when the DLL is unloaded.
//
//Arguments:
//
//    None
//
//Return Value:
//
//    HRESULT
//    S_OK      - On success.
//    Otherwise - Otherwise.
//
extern "C"
BOOL
WINAPI
DllMain(
    _In_     HINSTANCE   hinstDLL,
    _In_     DWORD       fdwReason,
    _In_opt_ LPVOID      /*lpvReserved*/
    )
{
    switch(fdwReason)
    {
    case DLL_PROCESS_ATTACH:

        ::DisableThreadLibraryCalls(hinstDLL);

        WPP_INIT_TRACING(L"MyV4PrintDriverRenderFilter");
        DoTraceMessage(RENDERFILTER_TRACE_INFO, L"DLL_PROCESS_ATTACH");
        break;

    case DLL_PROCESS_DETACH:

        DoTraceMessage(RENDERFILTER_TRACE_INFO, L"DLL_PROCESS_DETACH");
        WPP_CLEANUP();

        break;
    }

    return TRUE;
}
  1. 文件定位
    这是渲染过滤器DLL的入口文件。XPS渲染过滤器是V4打印机驱动中用于拦截和处理打印管道中XPS数据流的模块。
  2. 引用的头文件
    WppTrace/CustomWppCommands:用于日志和错误追踪(WPP tracing)。
    Exception/filtertypes/UnknownBase:异常处理、接口类型定义、COM 基类。
    RenderFilter.h:渲染过滤器类,核心逻辑实现。
    dllentry.tmh:WPP tracing 自动生成的文件。
  3. RenderFilterFactory类
class __declspec(uuid("ccf3dccf-b589-48b9-ab27-fd463caf8855")) RenderFilterFactory : public UnknownBase<IClassFactory>

这是一个COM类工厂(Class Factory),用于创建RenderFilter对象。
它继承自UnknownBase<IClassFactory>,提供IUnknownIClassFactory接口的实现。

构造 & 析构

    RenderFilterFactory() :
        m_serverLocks(0)
    {
        ::InterlockedIncrement(&RenderFilter::ms_numObjects);
    }

    ~RenderFilterFactory()
    {
        ::InterlockedDecrement(&RenderFilter::ms_numObjects);
    }

使用InterlockedIncrement/Decrement操作全局静态变量`RenderFilter::ms_numObjects,维护当前活动对象的计数。

CreateInstance

    HRESULT
    STDMETHODCALLTYPE
    CreateInstance(
        IUnknown    *pUnkOuter,
        REFIID      riid,
        void        **ppvObject
        )

检查聚合:如果pUnkOuter != NULL,返回CLASS_E_NOAGGREGATION(不支持聚合)。
检查参数:如果ppvObject == NULL,返回E_POINTER
创建对象:pFilter = new RenderFilter();可能抛异常,所以用try / CATCH_VARIOUS保护。
返回接口:调用QueryInterface获取所需的接口指针。
释放引用:工厂持有的引用释放,交给调用方。

LockServer

    HRESULT
    STDMETHODCALLTYPE
    LockServer(
        BOOL    fLock
        )

允许客户端锁定工厂驻留在内存中。
fLock = TRUE→ 增加锁计数并增加ms_numObjects
fLock = FALSE→ 减少锁计数,并在最后一个锁释放时减少ms_numObjects
返回S_OK

  1. DllGetClassObject
STDAPI
DllGetClassObject(
    _In_ REFCLSID        rclsid,
    _In_ REFIID          riid,
    _Outptr_ LPVOID   *ppv
    )

检查参数:ppv == NULLE_POINTER
检查 CLSID:如果不是RenderFilterFactory的CLSID→CLASS_E_CLASSNOTAVAILABLE
创建工厂对象:new RenderFilterFactory()
查询接口:通过QueryInterface返回IClassFactory指针。
释放工厂引用:保持COM引用计数语义。
这是标准COM DLL必须导出的函数之一,提供类工厂。

  1. DllCanUnloadNow
STDAPI
DllCanUnloadNow()
{
    return (0 == MyV4PrintDriver_Render_Filter::RenderFilter::ms_numObjects) ? S_OK : S_FALSE;
}

如果没有活动对象(ms_numObjects == 0),返回S_OK,DLL可以卸载。
否则返回S_FALSE,表示仍有对象在使用。

  1. DllMain
extern "C"
BOOL
WINAPI
DllMain(
    _In_     HINSTANCE   hinstDLL,
    _In_     DWORD       fdwReason,
    _In_opt_ LPVOID      /*lpvReserved*/
    )

DLL_PROCESS_ATTACH
禁用线程通知(DisableThreadLibraryCalls)。
初始化WPP tracing(WPP_INIT_TRACING)。
打日志:DLL_PROCESS_ATTACH
DLL_PROCESS_DETACH
打日志:DLL_PROCESS_DETACH
清理WPP tracing(WPP_CLEANUP)。
返回TRUE
这是DLL的入口点,负责初始化/清理日志系统

  1. 总结
    这段程序实现了一个XPS渲染过滤器DLL的COM入口模块,主要功能:
    RenderFilterFactory提供IClassFactory,用于生成RenderFilter对象。
    DllGetClassObject导出工厂接口。
    DllCanUnloadNow检查是否可以安全卸载DLL。
    DllMain管理DLL生命周期,初始化/清理WPP tracing。
    作用
    确保驱动中的渲染过滤器作为 COM 组件被系统正确加载、实例化、释放。
    提供调试和错误日志功能,方便诊断问题。
    管理全局对象数量,确保 DLL 不会过早卸载。

原始资料地址:
生成基本的 v4 打印机驱动程序
如有侵权联系删除 仅供学习交流使用