生成基本的 v4 打印机驱动程序-RenderFilter.cpp
- RenderFilter.cpp
//
// File Name:
//
// RenderFilter.cpp
//
// Abstract:
//
// XPS Rendering filter implementation.
//
#include "precomp.h"
#include "WppTrace.h"
#include "CustomWppCommands.h"
#include "Exception.h"
#include "filtertypes.h"
#include "UnknownBase.h"
#include "OMConvertor.h"
#include "PThandler.h"
#include "RenderFilter.h"
#include "RenderFilter.tmh"
namespace MyV4PrintDriver_Render_Filter
{
long RenderFilter::ms_numObjects = 0; // Initialize static object count
//
//Routine Name:
//
// RenderFilter::RenderFilter
//
//Routine Description:
//
// XPS Rendering filter default constructor.
//
//Arguments:
//
// None
//
//Return Value:
//
// None
//
RenderFilter::RenderFilter()
{
//
// Take ownership with no AddRef
//
m_pLiveness.Attach(new FilterLiveness());
::InterlockedIncrement(&ms_numObjects);
}
//
//Routine Name:
//
// RenderFilter::~RenderFilter
//
//Routine Description:
//
// XPS Rendering sample filter destructor.
//
//Arguments:
//
// None
//
//Return Value:
//
// None
//
RenderFilter::~RenderFilter()
{
::InterlockedDecrement(&ms_numObjects);
}
//
//Routine Name:
//
// RenderFilter::InitializeFilter
//
//Routine Description:
//
// Exception boundary wrapper for IPrintPipelineFilter initialization.
//
//Arguments:
//
// pICommunicator - interface to interfilter communicator
// pIPropertyBag - interface to pipeline property bag
// pIPipelineControl - interface to pipeline control methods
//
//Return Value:
//
// ULONG
// New reference count
//
_Check_return_
HRESULT STDMETHODCALLTYPE
RenderFilter::InitializeFilter(
_In_ IInterFilterCommunicator *pICommunicator,
_In_ IPrintPipelinePropertyBag *pIPropertyBag,
_In_ IPrintPipelineManagerControl *pIPipelineControl
)
{
DoTraceMessage(RENDERFILTER_TRACE_INFO, L"Initializing Filter");
if (pICommunicator == NULL ||
pIPropertyBag == NULL ||
pIPipelineControl == NULL)
{
WPP_LOG_ON_FAILED_HRESULT(E_POINTER);
return E_POINTER;
}
HRESULT hr = S_OK;
try
{
InitializeFilter_throws(
pICommunicator,
pIPropertyBag
);
}
CATCH_VARIOUS(hr);
return hr;
}
//
//Routine Name:
//
// RenderFilter::InitializeFilter_throws
//
//Routine Description:
//
// Implements IPrintPipelineFilter initialization. Gets
// all necessary communication interfaces.
//
//Arguments:
//
// pICommunicator - interface to interfilter communicator
// pIPropertyBag - interface to pipeline property bag
//
VOID
RenderFilter::InitializeFilter_throws(
const IInterFilterCommunicator_t &pICommunicator,
const IPrintPipelinePropertyBag_t &pIPropertyBag
)
{
//
// Get the pipeline communication interfaces
//
THROW_ON_FAILED_HRESULT(
pICommunicator->RequestReader(reinterpret_cast<void**>(&m_pReader))
);
THROW_ON_FAILED_HRESULT(
pICommunicator->RequestWriter(reinterpret_cast<void**>(&m_pWriter))
);
{
//
// Check to ensure that the provided interfaces are as expected.
// That is, that the GUIDs were correctly listed in the
// pipeline configuration file
//
IXpsDocumentProvider_t pReaderCheck;
IPrintWriteStream_t pWriterCheck;
THROW_ON_FAILED_HRESULT(
m_pReader.QueryInterface(&pReaderCheck)
);
THROW_ON_FAILED_HRESULT(
m_pWriter.QueryInterface(&pWriterCheck)
);
}
//
// Save a pointer to the Property Bag for further
// initialization, later.
//
m_pIPropertyBag = pIPropertyBag;
}
//
//Routine Name:
//
// RenderFilter::ShutdownOperation
//
//Routine Description:
//
// Called asynchronously by the pipeline manager
// to shutdown filter operation.
//
//Arguments:
//
// None
//
//Return Value:
//
// HRESULT
// S_OK - On success
//
_Check_return_
HRESULT
RenderFilter::ShutdownOperation()
{
DoTraceMessage(RENDERFILTER_TRACE_INFO, L"Shutting Down Operation");
m_pLiveness->Cancel();
return S_OK;
}
//
//Routine Name:
//
// RenderFilter::StartOperation
//
//Routine Description:
//
// Called by the pipeline manager to start processing
// a document. Exception boundary for page processing.
//
//Arguments:
//
// None
//
//Return Value:
//
// HRESULT
// S_OK - On success
// Otherwise - Failure
//
_Check_return_
HRESULT
RenderFilter::StartOperation()
{
HRESULT hr = S_OK;
DoTraceMessage(RENDERFILTER_TRACE_INFO, L"Starting Operation");
//
// Process the Xps Package
//
try {
StartOperation_throws();
}
CATCH_VARIOUS(hr);
m_pWriter->Close();
return hr;
}
//
//Routine Name:
//
// RenderFilter::StartOperation_throws
//
//Routine Description:
//
// Iterates over the 'trunk' parts of the document
// and calls appropriate processing methods.
//
//Arguments:
//
// None
//
void
RenderFilter::StartOperation_throws()
{
//
// CoInitialize/CoUninitialize RAII object.
// COM is inititalized for the lifetime of this method.
//
SafeCoInit coInit;
IXpsOMObjectFactory_t pOMFactory;
//
// Create Xps Object Model Object Factory instance
//
THROW_ON_FAILED_HRESULT(
::CoCreateInstance(
__uuidof(XpsOMObjectFactory),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IXpsOMObjectFactory),
reinterpret_cast<LPVOID*>(&pOMFactory)
)
);
IOpcFactory_t pOpcFactory;
//
// Create Opc Object Factory instance
//
THROW_ON_FAILED_HRESULT(
::CoCreateInstance(
__uuidof(OpcFactory),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IOpcFactory),
reinterpret_cast<LPVOID*>(&pOpcFactory)
)
);
//
// Create the Print Ticket Handler
//
PrintTicketHandler_t pPrintTicketHandler =
PrintTicketHandler::CreatePrintTicketHandler(
m_pIPropertyBag
);
IUnknown_t pUnk;
//
// Get first part
//
THROW_ON_FAILED_HRESULT(m_pReader->GetXpsPart(&pUnk));
while (m_pLiveness->IsAlive() &&
pUnk != NULL)
{
IXpsDocument_t pDoc;
IFixedDocumentSequence_t pFDS;
IFixedDocument_t pFD;
IFixedPage_t pFP;
if (SUCCEEDED(pUnk.QueryInterface(&pFP)))
{
DoTraceMessage(RENDERFILTER_TRACE_VERBOSE, L"Handling a Page");
pPrintTicketHandler->ProcessPart(pFP);
}
else if (SUCCEEDED(pUnk.QueryInterface(&pFD)))
{
pPrintTicketHandler->ProcessPart(pFD);
}
else if (SUCCEEDED(pUnk.QueryInterface(&pFDS)))
{
pPrintTicketHandler->ProcessPart(pFDS);
}
else if (SUCCEEDED(pUnk.QueryInterface(&pDoc)))
{
//
// Do nothing with the XML Document part
//
}
else
{
DoTraceMessage(RENDERFILTER_TRACE_INFO, L"Unhandled Document Part");
}
pUnk.Release();
//
// Get Next Part
//
THROW_ON_FAILED_HRESULT(m_pReader->GetXpsPart(&pUnk));
}
}
} // namespace MyV4PrintDriver_Render_Filter
文件概述
- 功能:实现
RenderFilter类,作为打印管道中的一个过滤器,负责处理 XPS 文档的部件(如固定文档序列、固定文档、固定页面),调用打印票据处理和对象模型转换逻辑。 - 主要内容:
定义了RenderFilter类的构造函数、析构函数和核心方法(如InitializeFilter和StartOperation)。
通过 COM 接口与打印管道交互,处理 XPS 文档的部件并协调打印票据处理。
使用 WPP(Windows 软件跟踪预处理器)记录日志,结合异常处理确保代码健壮性。 - 命名空间:
MyV4PrintDriver_Render_Filter,用于组织代码并避免符号冲突。
代码结构与功能详解
- 头文件与预处理器
- 作用:
包含必要的头文件,提供预编译宏、WPP 跟踪、自定义 WPP 命令、异常处理(Exception.h)、过滤器类型(filtertypes.h)、COM 基类(UnknownBase.h)、对象模型转换(OMConvertor.h)、打印票据处理(PThandler.h)和渲染过滤器声明(RenderFilter.h)。
RenderFilter.tmh是 WPP 跟踪生成的头文件,用于日志记录。
- 命名空间
namespace MyV4PrintDriver_Render_Filter
- 作用: 使用命名空间
MyV4PrintDriver_Render_Filter组织代码,避免符号冲突。
- 类
RenderFilter及成员
静态成员 ms_numObjects
long RenderFilter::ms_numObjects = 0;
- 功能: 静态变量,跟踪
RenderFilter对象的活跃实例数量,用于DllCanUnloadNow(在dllentry.cpp中)判断 DLL 是否可卸载。 - 初始化: 在文件开头初始化为 0。
构造函数 RenderFilter
RenderFilter::RenderFilter()
{
m_pLiveness.Attach(new FilterLiveness());
::InterlockedIncrement(&ms_numObjects);
}
- 功能: 默认构造函数,初始化
RenderFilter对象。 - 逻辑:
1.创建FilterLiveness对象(用于控制过滤器操作的存活状态),并通过Attach绑定到智能指针m_pLiveness(不增加引用计数)。
2.使用InterlockedIncrement增加ms_numObjects,记录活跃对象数。 - 作用: 始化过滤器,准备处理 XPS 文档。
析构函数 ~RenderFilter
RenderFilter::~RenderFilter()
{
::InterlockedDecrement(&ms_numObjects);
}
- 功能: 析构函数,清理资源并减少活跃对象计数。
- 逻辑:使用
InterlockedDecrement减少ms_numObjects。 - 作用: 确保对象销毁时更新全局计数,便于 DLL 卸载检查。
方法 InitializeFilter
HRESULT RenderFilter::InitializeFilter(
IInterFilterCommunicator *pICommunicator,
IPrintPipelinePropertyBag *pIPropertyBag,
IPrintPipelineManagerControl *pIPipelineControl
)
- 功能: 初始化打印管道过滤器,设置通信接口和属性包。
- 参数:
pICommunicator: 过滤器间通信接口(IInterFilterCommunicator),用于获取读写接口。
pIPropertyBag: 打印管道属性包(IPrintPipelinePropertyBag),包含打印票据等配置。
pIPipelineControl: 管道控制接口(IPrintPipelineManagerControl),用于控制过滤器操作。 - 逻辑:
1.检查输入参数是否为NULL,若为空则返回E_POINTER并记录日志。
2.调用InitializeFilter_throws执行初始化逻辑,捕获可能的异常(通过CATCH_VARIOUS)。
3.返回HRESULT表示成功(S_OK)或失败。 - WPP 日志: 使用
DoTraceMessage记录初始化开始,使用WPP_LOG_ON_FAILED_HRESULT记录错误。 - 异常处理: 使用
CATCH_VARIOUS捕获异常并转换为 HRESULT。 - 作用: 设置过滤器的通信接口和属性包,准备处理 XPS 文档。
方法 InitializeFilter_throws
VOID RenderFilter::InitializeFilter_throws(
const IInterFilterCommunicator_t &pICommunicator,
const IPrintPipelinePropertyBag_t &pIPropertyBag
)
- 功能: 执行过滤器初始化的具体逻辑,获取并验证通信接口。
- 参数:
pICommunicator: 智能指针形式的通信接口。
pIPropertyBag: 智能指针形式的属性包。 - 逻辑:
1.调用pICommunicator->RequestReader和RequestWriter获取 XPS 文档读取器(m_pReader)和写入器(m_pWriter)。
2.验证接口类型,确保m_pReader支持IXpsDocumentProvider接口,m_pWriter支持IPrintWriteStream接口。
3.保存属性包(m_pIPropertyBag)以供后续使用(如创建打印票据处理对象)。 - 异常处理:使用 THROW_ON_FAILED_HRESULT(调用 ThrowHRException)抛出异常。
- 作用: 确保过滤器获得正确的读写接口,并存储属性包以支持后续操作。
方法 ShutdownOperation
HRESULT RenderFilter::ShutdownOperation()
- 功能: 由管道管理器异步调用,关闭过滤器操作。
- 逻辑:
1.记录日志表示关闭操作。
2.调用m_pLiveness->Cancel()取消过滤器的存活状态,停止处理。
3.返回S_OK。 - WPP 日志: 使用
DoTraceMessage记录关闭信息。 - 作用: 响应管道管理器的关闭请求,停止过滤器处理。
方法 StartOperation
HRESULT RenderFilter::StartOperation()
- 功能: 由管道管理器调用,开始处理 XPS 文档,包含异常处理边界。
- 逻辑:
1.记录日志表示关闭操作。
2.调用StartOperation_throws执行文档处理逻辑,捕获异常(通过CATCH_VARIOUS)。
3.关闭写入器(m_pWriter->Close())。
3.返回HRESULT表示成功或失败。 - WPP 日志: 使用
DoTraceMessage记录关闭信息。 - 异常处理: 使用
CATCH_VARIOUS捕获异常。 - 作用: 启动过滤器的主要处理流程,处理整个 XPS 文档。
方法 StartOperation_throws
void RenderFilter::StartOperation_throws()
- 功能: 执行 XPS 文档的处理逻辑,遍历文档部件并调用相应的处理方法。
- 逻辑:
1.初始化 COM:
使用SafeCoInit(RAII 对象)初始化 COM 环境,确保方法执行期间 COM 可用。
2.创建对象工厂:
使用CoCreateInstance创建 XPS 对象模型工厂(IXpsOMObjectFactory)和 OPC 工厂(IOpcFactory)。
3.创建打印票据处理对象:
调用PrintTicketHandler::CreatePrintTicketHandler(定义在PThandler.cpp中),传入属性包,创建PrintTicketHandler。
4.遍历 XPS 部件:
调用m_pReader->GetXpsPart获取第一个部件(IUnknown)。
在m_pLiveness->IsAlive()为真且部件非空时,循环处理:
尝试将部件转换为IFixedPage、IFixedDocument、IFixedDocumentSequence或IXpsDocument。
如果是页面(IFixedPage)、文档(IFixedDocument)或文档序列\(IFixedDocumentSequence),调用pPrintTicketHandler->ProcessPart处理打印票据。
如果是 XML 文档(IXpsDocument),不做处理。
如果是未知部件,记录日志(Unhandled Document Part)。
释放当前部件(pUnk.Release())。
获取下一个部件。 - 异常处理: 使用
THROW_ON_FAILED_HRESULT。 - WPP 日志: 使用
DoTraceMessage记录处理页面或未知部件的信息。 - 作用: 遍历 XPS 文档的“主干”部件(文档序列、文档、页面),调用打印票据处理逻辑。
代码总结
- 主要功能:
RenderFilter类是 XPS 渲染过滤器的核心实现,负责初始化过滤器、处理 XPS 文档部件和协调打印票据处理。- 通过 COM 接口(
IInterFilterCommunicator、IXpsDocumentProvider等)与打印管道交互。 - 调用
PrintTicketHandler处理打印票据,可能为后续对象模型转换(OMConvertor)提供设置。
- 关键点:
- 使用
ms_numObjects跟踪活跃对象,配合dllentry.cpp中的DllCanUnloadNow。 FilterLiveness控制过滤器操作的存活状态,支持异步取消。- 智能指针(如
IXpsOMObjectFactory_t)简化 COM 对象管理。 - 异常处理(
CATCH_VARIOUS和THROW_ON_FAILED_HRESULT)和 WPP 日志(DoTraceMessage)确保健壮性和可调试性。
- 应用场景:
- 该类是 Windows 打印管道中的一个过滤器,处理 XPS 文档的渲染流程。
- 与
PThandler.cpp协作处理打印票据,与OMConvertor.cpp协作转换对象模型。
- 处理流程:
- 初始化过滤器,获取读写接口和属性包。
- 启动操作,遍历 XPS 文档部件(文档序列、文档、页面)。
- 对每个部件调用
PrintTicketHandler::ProcessPart处理打印票据。 - (未在代码中实现)可能调用
OMConvertor的函数将部件转换为 XPS 对象模型。
原始资料地址:
生成基本的 v4 打印机驱动程序
如有侵权联系删除 仅供学习交流使用