diff options
| author | Dave Wilson <[email protected]> | 2015-03-17 19:50:07 -0700 |
|---|---|---|
| committer | Dave Wilson <[email protected]> | 2015-03-17 19:50:07 -0700 |
| commit | 97cf5197cf5b882b2c689d8dc2b555f2edf8f418 (patch) | |
| tree | 46f3701832d70b420eb0fc0eb93261f9da45db3f /print/SimplePipelineFilter | |
| parent | ef1905bf1e8825bb31120dfb27e0daf3154d859a (diff) | |
Initial publish
Diffstat (limited to 'print/SimplePipelineFilter')
| -rw-r--r-- | print/SimplePipelineFilter/FilterSample.def | 8 | ||||
| -rw-r--r-- | print/SimplePipelineFilter/FilterSample.rc | 10 | ||||
| -rw-r--r-- | print/SimplePipelineFilter/ReadMe.md | 9 | ||||
| -rw-r--r-- | print/SimplePipelineFilter/SimplePipelineFilter.sln | 28 | ||||
| -rw-r--r-- | print/SimplePipelineFilter/StreamFilter.cxx | 263 | ||||
| -rw-r--r-- | print/SimplePipelineFilter/StreamFilter.hxx | 99 | ||||
| -rw-r--r-- | print/SimplePipelineFilter/WdkPipelineFilter.vcxproj | 294 | ||||
| -rw-r--r-- | print/SimplePipelineFilter/WdkPipelineFilter.vcxproj.Filters | 39 | ||||
| -rw-r--r-- | print/SimplePipelineFilter/XpsFilter.cxx | 785 | ||||
| -rw-r--r-- | print/SimplePipelineFilter/XpsFilter.hxx | 126 | ||||
| -rw-r--r-- | print/SimplePipelineFilter/main.cxx | 172 | ||||
| -rw-r--r-- | print/SimplePipelineFilter/main.hxx | 51 | ||||
| -rw-r--r-- | print/SimplePipelineFilter/precomp.hxx | 26 | ||||
| -rw-r--r-- | print/SimplePipelineFilter/precompsrc.cpp | 1 | ||||
| -rw-r--r-- | print/SimplePipelineFilter/smartptr.hxx | 233 | ||||
| -rw-r--r-- | print/SimplePipelineFilter/trace.hxx | 51 |
16 files changed, 2195 insertions, 0 deletions
diff --git a/print/SimplePipelineFilter/FilterSample.def b/print/SimplePipelineFilter/FilterSample.def new file mode 100644 index 00000000..f6a38ef5 --- /dev/null +++ b/print/SimplePipelineFilter/FilterSample.def @@ -0,0 +1,8 @@ +LIBRARY "FilterSample.DLL" + +EXPORTS + DllGetClassObject PRIVATE + DllCanUnloadNow PRIVATE + + + diff --git a/print/SimplePipelineFilter/FilterSample.rc b/print/SimplePipelineFilter/FilterSample.rc new file mode 100644 index 00000000..caf78af0 --- /dev/null +++ b/print/SimplePipelineFilter/FilterSample.rc @@ -0,0 +1,10 @@ +#include <windows.h> +#include <ntverp.h> + +#define VER_FILETYPE VFT_DLL +#define VER_FILESUBTYPE VFT2_UNKNOWN +#define VER_FILEDESCRIPTION_STR "Print Pipeline WDK Filter Sample" +#define VER_INTERNALNAME_STR "WdkPipelineFilter.dll" +#define VER_ORIGINALFILENAME_STR "WdkPipelineFilter.dll" + +#include "common.ver" diff --git a/print/SimplePipelineFilter/ReadMe.md b/print/SimplePipelineFilter/ReadMe.md new file mode 100644 index 00000000..06f17b61 --- /dev/null +++ b/print/SimplePipelineFilter/ReadMe.md @@ -0,0 +1,9 @@ +Print Pipeline Simple Filter +============================ + +The printing system supports a print filter pipeline. The pipeline is run when a print job is consumed by the print spooler and sent to the device. + +This sample shows how to use the print pipeline's filter interfaces. + +The filters in the print pipeline consume a certain data type and produce a certain data type. This information is specified in the pipeline configuration file on a per printer driver basis. The WDK print filter sample contains two filter samples: one that consumes and produces XPS data type, and the other one consumes and produces opaque byte stream. For more information, see the [XpsDrv](http://msdn.microsoft.com/en-us/windows/hardware/gg463364) whitepaper. + diff --git a/print/SimplePipelineFilter/SimplePipelineFilter.sln b/print/SimplePipelineFilter/SimplePipelineFilter.sln new file mode 100644 index 00000000..c7863beb --- /dev/null +++ b/print/SimplePipelineFilter/SimplePipelineFilter.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0 +MinimumVisualStudioVersion = 12.0 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WdkPipelineFilter", "WdkPipelineFilter.vcxproj", "{D3CE825A-F33C-4DF0-AA6D-F7BC0463164D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D3CE825A-F33C-4DF0-AA6D-F7BC0463164D}.Debug|Win32.ActiveCfg = Debug|Win32 + {D3CE825A-F33C-4DF0-AA6D-F7BC0463164D}.Debug|Win32.Build.0 = Debug|Win32 + {D3CE825A-F33C-4DF0-AA6D-F7BC0463164D}.Release|Win32.ActiveCfg = Release|Win32 + {D3CE825A-F33C-4DF0-AA6D-F7BC0463164D}.Release|Win32.Build.0 = Release|Win32 + {D3CE825A-F33C-4DF0-AA6D-F7BC0463164D}.Debug|x64.ActiveCfg = Debug|x64 + {D3CE825A-F33C-4DF0-AA6D-F7BC0463164D}.Debug|x64.Build.0 = Debug|x64 + {D3CE825A-F33C-4DF0-AA6D-F7BC0463164D}.Release|x64.ActiveCfg = Release|x64 + {D3CE825A-F33C-4DF0-AA6D-F7BC0463164D}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/print/SimplePipelineFilter/StreamFilter.cxx b/print/SimplePipelineFilter/StreamFilter.cxx new file mode 100644 index 00000000..a03aafe0 --- /dev/null +++ b/print/SimplePipelineFilter/StreamFilter.cxx @@ -0,0 +1,263 @@ +//+-------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// This source code is intended only as a supplement to Microsoft +// Development Tools and/or on-line documentation. See these other +// materials for detailed information regarding Microsoft code samples. +// +// THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY +// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. +// +// Abstract: +// WDK print filter sample. +// This is the C file for the stream filter sample. +// +//---------------------------------------------------------------------------- + +#include "precomp.hxx" +#include "main.hxx" +#include "StreamFilter.tmh" +#include "StreamFilter.hxx" + +#include "winddiui.h" +#include "compstui.h" +#include "printoem.h" + +#include "initguid.h" +#include "prcomoem.h" + +_Analysis_mode_(_Analysis_code_type_user_driver_) + +// +// 5f5460d2-b313-44ca-82e4-37f83d793999 - generate a guid, do not use this one in your code +// +const GUID StreamFilterGuid = {0x5f5460d2, 0xb313, 0x44ca, {0x82, 0xe4, 0x37, 0xf8, 0x3d, 0x79, 0x39, 0x99}}; + +const GUID& +StreamFilter:: +FilterClsid( + void + ) +{ + return StreamFilterGuid; +} + +StreamFilter:: +StreamFilter() : + m_bShutdown(false), + m_cRef(1) +{ +} + +// +// IUnknown methods +// +__override +STDMETHODIMP +StreamFilter:: +QueryInterface( + _In_ REFIID riid, + _Out_ void **ppv + ) +{ + HRESULT hRes = E_POINTER; + + if (ppv) + { + hRes = E_NOINTERFACE; + + *ppv = NULL; + + if (riid == IID_IPrintPipelineFilter) + { + *ppv = static_cast<IPrintPipelineFilter *>(this); + } + else if (riid == IID_IUnknown) + { + *ppv = static_cast<IUnknown *>(this); + } + + if (*ppv) + { + AddRef(); + + hRes = S_OK; + } + } + + return hRes; +} + +__override +STDMETHODIMP_(ULONG) +StreamFilter:: +AddRef( + void + ) +{ + return InterlockedIncrement(&m_cRef); +} + +__override +STDMETHODIMP_(ULONG) +StreamFilter:: +Release( + void + ) +{ + ULONG cRefCount = InterlockedDecrement(&m_cRef); + + if (cRefCount) + { + return cRefCount; + } + + delete this; + + return 0; +} + +// +// IPrintPipelineFilter +// +__override +STDMETHODIMP +StreamFilter:: +ShutdownOperation( + void + ) +{ + m_bShutdown = true; + + return S_OK; +} + +__override +STDMETHODIMP +StreamFilter:: +InitializeFilter( + _In_ IInterFilterCommunicator *pIFilterCommunicator, + _In_ IPrintPipelinePropertyBag *pIPropertyBag, + _In_ IPrintPipelineManagerControl *pIPipelineControl + ) +{ + HRESULT hr = S_OK; + VARIANT varHelper; + PCSTR *pFeatures = NULL; + DWORD dwFeatures = 0; + Tools::SmartPtr<IPrintCoreHelper> pHelper; + + VariantInit(&varHelper); + + // + // StreamAccessSequential, IID_IPrintReadStream + // + hr = pIFilterCommunicator->RequestReader(reinterpret_cast<void **>(&m_pIRead)); + + if (SUCCEEDED(hr)) + { + // + // StreamAccessSequential, StreamModify, IID_IPrintWriteStream + // + hr = pIFilterCommunicator->RequestWriter(reinterpret_cast<void **>(&m_pIWrite)); + } + + if (SUCCEEDED(hr)) + { + m_pIPipelineControl = pIPipelineControl; + } + + // + // This shows how to use the helper interface to read information + // from a UnidrvUI based configuration module. + // + + if (SUCCEEDED(hr)) + { + hr = pIPropertyBag->GetProperty(L"IPrintCoreHelper", &varHelper); + } + + if (SUCCEEDED(hr) && V_UNKNOWN(&varHelper)) + { + hr = (V_UNKNOWN(&varHelper))->QueryInterface(IID_IPrintCoreHelper, (VOID**)(&pHelper)); + } + + // + // No need to release buffers provided by the helper. Their + // lifetime matches that of the helper. + // + if (SUCCEEDED(hr) && pHelper) + { + hr = pHelper->EnumFeatures(&pFeatures, &dwFeatures); + } + + if (SUCCEEDED(hr) && dwFeatures > 0) + { + for (DWORD i = 0; i < dwFeatures; i++) + { + DoTraceMessage(WS_TRACE, L"StreamFilter::InitializeFilter: Feature found: %s", pFeatures[i]); + } + } + + VariantClear(&varHelper); + + return hr; +} + +__override +STDMETHODIMP +StreamFilter:: +StartOperation( + void + ) +{ + HRESULT hr = S_OK; + Tools::SmartPtr<IImgErrorInfo> pIErrorInfo; + DWORD cbRead; + BYTE *pReadBuf; + BOOL bEof = FALSE; + + pReadBuf = new BYTE[kBufferSize]; + + if (!pReadBuf) + { + hr = E_OUTOFMEMORY; + } + + while (SUCCEEDED(hr) && !bEof && !m_bShutdown) + { + hr = m_pIRead->ReadBytes(pReadBuf, kBufferSize, &cbRead, &bEof); + + if (SUCCEEDED(hr) && cbRead) + { + ULONG cbWritten; + + hr = m_pIWrite->WriteBytes(pReadBuf, cbRead, &cbWritten); + + if (SUCCEEDED(hr)) + { + DoTraceMessage(WS_TRACE, "StreamFilter::StartOperation read and wrote %u bytes", cbRead); + } + } + } + + m_pIWrite->Close(); + + if (FAILED(hr)) + { + m_pIPipelineControl->RequestShutdown(hr, pIErrorInfo); + } + + if (m_pIPipelineControl) + { + m_pIPipelineControl->FilterFinished(); + } + + delete [] pReadBuf; + + return hr; +} + + diff --git a/print/SimplePipelineFilter/StreamFilter.hxx b/print/SimplePipelineFilter/StreamFilter.hxx new file mode 100644 index 00000000..c23f5fb2 --- /dev/null +++ b/print/SimplePipelineFilter/StreamFilter.hxx @@ -0,0 +1,99 @@ +//+-------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// This source code is intended only as a supplement to Microsoft +// Development Tools and/or on-line documentation. See these other +// materials for detailed information regarding Microsoft code samples. +// +// THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY +// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. +// +// Abstract: +// WDK print filter sample. +// This is the header file for the stream filter sample. +// +//---------------------------------------------------------------------------- + +#ifndef _STREAM_FILTER_SAMPLE_HXX_ +#define _STREAM_FILTER_SAMPLE_HXX_ + +class StreamFilter : + public IPrintPipelineFilter, + private DllLockManager +{ +public: + + StreamFilter(); + + // + // IUnknown methods + // + __override + STDMETHODIMP + QueryInterface( + _In_ REFIID riid, + _Out_ void **ppv + ); + + __override + STDMETHODIMP_(ULONG) + AddRef( + void + ); + + __override + STDMETHODIMP_(ULONG) + Release( + void + ); + + // + // IPrintPipelineFilter + // + __override + STDMETHODIMP + ShutdownOperation( + void + ); + + __override + STDMETHODIMP + InitializeFilter( + _In_ IInterFilterCommunicator *pINegotiation, + _In_ IPrintPipelinePropertyBag *pIPropertyBag, + _In_ IPrintPipelineManagerControl *pIPipelineControl + ); + + __override + STDMETHODIMP + StartOperation( + void + ); + + // + // Other methods + // + static + const GUID& + FilterClsid( + void + ); + +private: + + enum + { + kBufferSize = 0x10000 + }; + + Tools::SmartPtr<IPrintReadStream> m_pIRead; + Tools::SmartPtr<IPrintWriteStream> m_pIWrite; + Tools::SmartPtr<IPrintPipelineManagerControl> m_pIPipelineControl; + Tools::SmartPtr<IPrintPipelineProgressReport> m_pProgressReport; + bool m_bShutdown; + LONG m_cRef; +}; + +#endif // _STREAM_FILTER_SAMPLE_HXX_ diff --git a/print/SimplePipelineFilter/WdkPipelineFilter.vcxproj b/print/SimplePipelineFilter/WdkPipelineFilter.vcxproj new file mode 100644 index 00000000..3af320ac --- /dev/null +++ b/print/SimplePipelineFilter/WdkPipelineFilter.vcxproj @@ -0,0 +1,294 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{D3CE825A-F33C-4DF0-AA6D-F7BC0463164D}</ProjectGuid> + <RootNamespace>$(MSBuildProjectName)</RootNamespace> + <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> + <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <SampleGuid>{5BC5D9DA-A9ED-4BE2-8DD9-33853EFC148A}</SampleGuid> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <PropertyGroup> + <OutDir>$(IntDir)</OutDir> + </PropertyGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ItemGroup Label="WrappedTaskItems"> + <ClCompile Include="main.cxx"> + <WppEnabled>true</WppEnabled> + <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreCompiledHeaderFile>precomp.hxx</PreCompiledHeaderFile> + <PreCompiledHeader>Use</PreCompiledHeader> + <PreCompiledHeaderOutputFile>$(IntDir)\precomp.hxx.pch</PreCompiledHeaderOutputFile> + </ClCompile> + <ClCompile Include="StreamFilter.cxx"> + <WppEnabled>true</WppEnabled> + <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreCompiledHeaderFile>precomp.hxx</PreCompiledHeaderFile> + <PreCompiledHeader>Use</PreCompiledHeader> + <PreCompiledHeaderOutputFile>$(IntDir)\precomp.hxx.pch</PreCompiledHeaderOutputFile> + </ClCompile> + <ClCompile Include="XpsFilter.cxx"> + <WppEnabled>true</WppEnabled> + <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreCompiledHeaderFile>precomp.hxx</PreCompiledHeaderFile> + <PreCompiledHeader>Use</PreCompiledHeader> + <PreCompiledHeaderOutputFile>$(IntDir)\precomp.hxx.pch</PreCompiledHeaderOutputFile> + </ClCompile> + <OtherWpp Include="FilterSample.rc"> + <WppEnabled>true</WppEnabled> + </OtherWpp> + </ItemGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetName>WdkPipelineFilter</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetName>WdkPipelineFilter</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetName>WdkPipelineFilter</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetName>WdkPipelineFilter</TargetName> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);user32.lib;kernel32.lib;oleaut32.lib;ole32.lib;uuid.lib;advapi32.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);user32.lib;kernel32.lib;oleaut32.lib;ole32.lib;uuid.lib;advapi32.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);user32.lib;kernel32.lib;oleaut32.lib;ole32.lib;uuid.lib;advapi32.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);user32.lib;kernel32.lib;oleaut32.lib;ole32.lib;uuid.lib;advapi32.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Link> + <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> + <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Link> + <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> + <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Link> + <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> + <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Link> + <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> + <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='false'">MultiThreaded</RuntimeLibrary> + <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='true'">MultiThreadedDebug</RuntimeLibrary> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </ResourceCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='false'">MultiThreaded</RuntimeLibrary> + <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='true'">MultiThreadedDebug</RuntimeLibrary> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </ResourceCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='false'">MultiThreaded</RuntimeLibrary> + <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='true'">MultiThreadedDebug</RuntimeLibrary> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </ResourceCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='false'">MultiThreaded</RuntimeLibrary> + <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='true'">MultiThreadedDebug</RuntimeLibrary> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </ResourceCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Link> + <AdditionalOptions>%(AdditionalOptions) /ignore:4070</AdditionalOptions> + <ModuleDefinitionFile>FilterSample.def</ModuleDefinitionFile> + </Link> + <ClCompile> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Link> + <AdditionalOptions>%(AdditionalOptions) /ignore:4070</AdditionalOptions> + <ModuleDefinitionFile>FilterSample.def</ModuleDefinitionFile> + </Link> + <ClCompile> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Link> + <AdditionalOptions>%(AdditionalOptions) /ignore:4070</AdditionalOptions> + <ModuleDefinitionFile>FilterSample.def</ModuleDefinitionFile> + </Link> + <ClCompile> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Link> + <AdditionalOptions>%(AdditionalOptions) /ignore:4070</AdditionalOptions> + <ModuleDefinitionFile>FilterSample.def</ModuleDefinitionFile> + </Link> + <ClCompile> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="precompsrc.cpp"> + <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreCompiledHeaderFile>precomp.hxx</PreCompiledHeaderFile> + <PreCompiledHeader>Create</PreCompiledHeader> + <PreCompiledHeaderOutputFile>$(IntDir)\precomp.hxx.pch</PreCompiledHeaderOutputFile> + </ClCompile> + <ResourceCompile Include="FilterSample.rc" /> + </ItemGroup> + <ItemGroup> + <Inf Exclude="@(Inf)" Include="*.inf" /> + <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" /> + <FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" /> + </ItemGroup> + <ItemGroup> + <None Exclude="@(None)" Include="*.txt;*.htm;*.html" /> + <None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" /> + <None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" /> + </ItemGroup> + <ItemGroup> + <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> +</Project>
\ No newline at end of file diff --git a/print/SimplePipelineFilter/WdkPipelineFilter.vcxproj.Filters b/print/SimplePipelineFilter/WdkPipelineFilter.vcxproj.Filters new file mode 100644 index 00000000..65c4c551 --- /dev/null +++ b/print/SimplePipelineFilter/WdkPipelineFilter.vcxproj.Filters @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions> + <UniqueIdentifier>{9E97BFB7-9C77-4223-A684-83194A1A1C59}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files"> + <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> + <UniqueIdentifier>{ED009CED-C036-41C0-96C7-B993C7F42ECD}</UniqueIdentifier> + </Filter> + <Filter Include="Resource Files"> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions> + <UniqueIdentifier>{F44E5BC1-1970-4C43-A39A-30A1F28A6E42}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="main.cxx"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="precompsrc.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="StreamFilter.cxx"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="XpsFilter.cxx"> + <Filter>Source Files</Filter> + </ClCompile> + <None Include="FilterSample.def"> + <Filter>Source Files</Filter> + </None> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="FilterSample.rc"> + <Filter>Resource Files</Filter> + </ResourceCompile> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/print/SimplePipelineFilter/XpsFilter.cxx b/print/SimplePipelineFilter/XpsFilter.cxx new file mode 100644 index 00000000..fe4945d0 --- /dev/null +++ b/print/SimplePipelineFilter/XpsFilter.cxx @@ -0,0 +1,785 @@ +//+-------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// This source code is intended only as a supplement to Microsoft +// Development Tools and/or on-line documentation. See these other +// materials for detailed information regarding Microsoft code samples. +// +// THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY +// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. +// +// Abstract: +// WDK print filter sample. +// This is the C file for the stream filter sample. +// +//---------------------------------------------------------------------------- + +#include "precomp.hxx" +#include "main.hxx" +#include "XpsFilter.tmh" +#include "XpsFilter.hxx" + +_Analysis_mode_(_Analysis_code_type_user_driver_) + +// +// 8267d291-6ddd-4972-a94e-3ce88149a1fa - generate a guid, do not use this one in your code +// +const GUID ClsidXpsFilter = {0x8267d291, 0x6ddd, 0x4972, {0xa9, 0x4e, 0x3c, 0xe8, 0x81, 0x49, 0xa1, 0xfa}}; + +const GUID& +XpsFilter:: +FilterClsid( + void + ) +{ + return ClsidXpsFilter; +} + +#define COUNTOF(x) (sizeof(x)/sizeof(*x)) + +HRESULT +GetLastErrorAsHResult( + void + ) +{ + DWORD dwError = GetLastError(); + + return HRESULT_FROM_WIN32(dwError); +} + +HRESULT +ProcessTicket( + _In_ IPartPrintTicket *pIPrintTicket + ) +{ + Tools::SmartBSTR bstr; + + HRESULT hRes = pIPrintTicket->GetUri(&bstr); + + if (SUCCEEDED(hRes)) + { + Tools::SmartPtr<IPrintReadStream> pIStream; + + hRes = pIPrintTicket->GetStream(&pIStream); + + if (SUCCEEDED(hRes)) + { + ULONG cbRead = 0; + BOOL bEof = FALSE; + + DoTraceMessage(WS_TRACE, "ProcessTicket print ticket follows."); + + do + { + BYTE buf[200] = {0}; + + // + // Save one byte to ensure null termination + // + if (SUCCEEDED(hRes = pIStream->ReadBytes(buf, COUNTOF(buf) - 1, &cbRead, &bEof)) && cbRead) + { + // + // use PT data + // + DoTraceMessage(WS_TRACE, "%s", reinterpret_cast<PCSTR>(buf)); + } + } + while (!bEof && cbRead && SUCCEEDED(hRes)); + } + } + + return hRes; +} + +HRESULT +AddFontToPage( + _In_ IPartFont *pNewFont, + _In_ IPrintWriteStream *pFontStream, + _In_ IFixedPage *pNewPage + ) +{ + WCHAR szFont[MAX_PATH]; + HRESULT hRes = S_OK; + + if (!GetWindowsDirectory(szFont, MAX_PATH)) + { + hRes = GetLastErrorAsHResult(); + } + + if (SUCCEEDED(hRes)) + { + hRes = StringCchCat(szFont, MAX_PATH, L"\\fonts\\verdana.TTF"); + } + + if (SUCCEEDED(hRes)) + { + HANDLE hFile = CreateFile(szFont, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + 0, + NULL); + + if (hFile != INVALID_HANDLE_VALUE) + { + BYTE buf[400]; + ULONG cbBuf = 400; + ULONG cbRead, cbWritten; + + do + { + if (ReadFile(hFile, buf, cbBuf, &cbRead, NULL)) + { + hRes = pFontStream->WriteBytes(buf, cbRead, &cbWritten); + } + else + { + hRes = GetLastErrorAsHResult(); + } + } + while (SUCCEEDED(hRes) && cbRead); + + CloseHandle(hFile); + } + else + { + hRes = GetLastErrorAsHResult(); + } + + pFontStream->Close(); + } + + if (SUCCEEDED(hRes)) + { + hRes = pNewPage->SetPagePart(pNewFont); + } + + return hRes; +} + +HRESULT +AddTextToPage( + _In_ PCWSTR pszReferencedFont, + _In_ IPrintWriteStream *pPageMarkupStream + ) +{ + HRESULT hRes; + ULONG cb; + CHAR buf[500]; + + // + // Mark up for page generated on the fly: "hello world" + // + CHAR sz[] = "<FixedPage Width=\"816\" Height=\"1056\" xmlns=\"http://schemas.microsoft.com/xps/2005/06\" xml:lang=\"en-US\">" + "<Glyphs Fill=\"#ff000000\" FontUri=\"%ws\" FontRenderingEmSize=\"15\" StyleSimulations=\"None\" OriginX=\"172\"" + " OriginY=\"129.68\" Indices=\"75;72;79;79;82;3;90;82;85;79;71\" UnicodeString=\"hello world\" />" + "</FixedPage>"; + + // + // Insert the URI of the font we added to the document + // + hRes = StringCchPrintfA(buf, COUNTOF(buf), sz, pszReferencedFont); + + // + // Write markup for page + // + if (SUCCEEDED(hRes) && + SUCCEEDED(hRes = pPageMarkupStream->WriteBytes(buf, static_cast<ULONG>(strlen(buf)), &cb))) + { + pPageMarkupStream->Close(); + } + + return hRes; +} + +// +// This function reads the page content and writes it back. Can be extended +// to do useful work +// +HRESULT +ModifyContent( + _In_ IPrintReadStream *pRead, + _In_ IPrintWriteStream *pWrite + ) +{ + CHAR buf[100] = {0}; + HRESULT hRes; + ULONG cbr, cbw; + BOOL bEof = FALSE; + + do + { + hRes = pRead->ReadBytes(buf, sizeof(buf), &cbr, &bEof); + + if (SUCCEEDED(hRes) && cbr) + { + // + // do something with buffer + // + cbw = cbr; + + hRes = pWrite->WriteBytes(buf, cbr, &cbw); + } + } + while (!bEof && cbr && SUCCEEDED(hRes)); + + return hRes; +} + +HRESULT +XpsFilter:: +ProcessImagePart( + _In_ IPartImage *pIPartImage + ) +{ + Tools::SmartBSTR bstr; + + HRESULT hRes = pIPartImage->GetUri(&bstr); + + DoTraceMessage(WS_TRACE, "ProcessImagePart uri %ws", static_cast<PCWSTR>(bstr)); + + if (SUCCEEDED(hRes)) + { + Tools::SmartPtr<IPrintReadStream> pRead; + + if (SUCCEEDED(hRes = pIPartImage->GetStream(&pRead))) + { + // + // do something with image + // + } + } + + return hRes; +} + +// +// Non-static members +// +XpsFilter:: +XpsFilter() : + m_bShutdown(false), + m_cRef(1), + m_cIdCount(0) +{ +} + +HRESULT +XpsFilter:: +ProcessFixedPage( + _In_ void *pVoid + ) +{ + Tools::SmartPtr<IFixedPage> pIFixedPage; + + // + // XpsFilter::ProcessPart already incremented the reference count for the object. This + // function is taking ownership of the object, there is no need for another AddRef call + // (hence the Attach) + // + pIFixedPage.Attach(static_cast<IFixedPage *>(pVoid)); + + HRESULT hRes; + Tools::SmartBSTR bstr; + + if (SUCCEEDED(pIFixedPage->GetUri(&bstr))) + { + DoTraceMessage(WS_TRACE, "ProcessFixedPage uri %ws", static_cast<PCWSTR>(bstr)); + } + + Tools::SmartPtr<IPartPrintTicket> pIPrintTicket; + + hRes = pIFixedPage->GetPrintTicket(&pIPrintTicket); + + if (SUCCEEDED(hRes)) + { + hRes = ProcessTicket(pIPrintTicket); + } + else if (hRes == E_ELEMENT_NOT_FOUND) + { + // + // No ticket. Benign. + // + hRes = S_OK; + + DoTraceMessage(WS_WARNING, "ProcessFixedPage uri %ws. Page print ticket not present.", static_cast<PCWSTR>(bstr)); + } + + pIFixedPage->SetPartCompression(Compression_Small); + + // + // modify content for page, optional + // + Tools::SmartPtr<IPrintReadStream> pRead; + Tools::SmartPtr<IPrintWriteStream> pWrite; + + if (SUCCEEDED(hRes = pIFixedPage->GetStream(&pRead)) && + SUCCEEDED(hRes = pIFixedPage->GetWriteStream(&pWrite))) + { + hRes = ModifyContent(pRead, pWrite); + + pWrite->Close(); + } + + // + // Send page to next filter + // + if (SUCCEEDED(hRes)) + { + hRes = m_pReachConsumer->SendFixedPage(pIFixedPage); + } + + // + // Add a new page + // + if (SUCCEEDED(hRes)) + { + Tools::SmartPtr<IFixedPage> pNewPage; + Tools::SmartPtr<IPrintWriteStream> pNewPageMarkupStream; + Tools::SmartPtr<IPartFont> pNewFont; + Tools::SmartPtr<IPrintWriteStream> pNewFontStream; + + WCHAR szName[MAX_PATH]; + + // + // Generate unique page name + // + if (SUCCEEDED(hRes = StringCchPrintf(szName, MAX_PATH, L"/pages/newaddedpage%u.xaml", m_cIdCount++))) + { + // + // Create new fixed page + // + hRes = m_pReachConsumer->GetNewEmptyPart(szName, + IID_IFixedPage, + reinterpret_cast<void **>(&pNewPage), + &pNewPageMarkupStream); + + DoTraceMessage(WS_TRACE, "ProcessFixedPage new page %ws", szName); + } + + // + // Generate unique font name, this can, of course, be optimized so we don't include + // the same font multiple times. But this code is supposed to just to show how to + // add a font + // + if (SUCCEEDED(hRes = StringCchPrintf(szName, MAX_PATH, L"/font_%u.ttf", m_cIdCount++))) + { + // + // Create new font resource + // + hRes = m_pReachConsumer->GetNewEmptyPart(szName, + IID_IPartFont, + reinterpret_cast<void **>(&pNewFont), + &pNewFontStream); + + DoTraceMessage(WS_TRACE, "ProcessFixedPage new font %ws", szName); + } + + if (SUCCEEDED(hRes) && + SUCCEEDED(hRes = AddFontToPage(pNewFont, pNewFontStream, pNewPage)) && + SUCCEEDED(hRes = AddTextToPage(szName, pNewPageMarkupStream))) + { + // + // Send page to next filter + // + hRes = m_pReachConsumer->SendFixedPage(pNewPage); + } + } + + return hRes; +} + + + +struct Pair_t +{ + typedef HRESULT (XpsFilter::*PFN)(void *); + + Pair_t(REFIID d, PFN n) : iid(d), pfn(n) {} + + REFIID iid; + PFN pfn; + +private: + + Pair_t& operator=(const Pair_t&); +}; + + +HRESULT +XpsFilter:: +ProcessPart( + _In_ IUnknown *pUnk + ) +{ + HRESULT hRes = S_OK; + + Pair_t pairs[] = + { + Pair_t(IID_IXpsDocument, &XpsFilter::ProcessXpsDoc), + Pair_t(IID_IFixedDocumentSequence, &XpsFilter::ProcessFixedDocSequence), + Pair_t(IID_IFixedDocument, &XpsFilter::ProcessFixedDoc), + Pair_t(IID_IFixedPage, &XpsFilter::ProcessFixedPage), + }; + + // + // Detect what part we got + // + for (ULONG i = 0; i < sizeof(pairs)/sizeof(*pairs); i++) + { + void *pvoid = NULL; + + if (SUCCEEDED(hRes = pUnk->QueryInterface(pairs[i].iid, &pvoid))) + { + // + // QueryInterface increments the reference count for the object it returns + // + hRes = (this->*pairs[i].pfn)(pvoid); + + break; + } + else if (hRes != E_NOINTERFACE) + { + break; + } + } + + // + // IPartDiscardControl objects may float through the pipeline. The code above does not check for IPartDiscardControl. + // So, for maximum compatibility, the filter forwards parts that it doesn't understand. + // + if (hRes == E_NOINTERFACE) + { + hRes = m_pReachConsumer->SendXpsUnknown(pUnk); + } + + return hRes; +} + +HRESULT +XpsFilter:: +ProcessXpsDoc( + _In_ void *pVoid + ) +{ + Tools::SmartPtr<IXpsDocument> pIXpsDoc; + + pIXpsDoc.Attach(static_cast<IXpsDocument *>(pVoid)); + + DoTraceMessage(WS_TRACE, L"ProcessXpsDoc"); + + return m_pReachConsumer->SendXpsDocument(pIXpsDoc); +} + +HRESULT +XpsFilter:: +ProcessFixedDocSequence( + _In_ void *pVoid + ) +{ + Tools::SmartPtr<IFixedDocumentSequence> pIFixedDocumentSequence; + + // + // XpsFilter::ProcessPart already incremented the reference count for the object. This + // function is taking ownership of the object, there is no need for another AddRef call + // (hence the Attach) + // + pIFixedDocumentSequence.Attach(static_cast<IFixedDocumentSequence *>(pVoid)); + + Tools::SmartBSTR bstr; + + if (SUCCEEDED(pIFixedDocumentSequence->GetUri(&bstr))) + { + DoTraceMessage(WS_TRACE, "ProcessFixedDocSequence uri %ws", static_cast<PCWSTR>(bstr)); + } + + Tools::SmartPtr<IPartPrintTicket> pIPrintTicket; + + HRESULT hRes = pIFixedDocumentSequence->GetPrintTicket(&pIPrintTicket); + + if (SUCCEEDED(hRes)) + { + hRes = ProcessTicket(pIPrintTicket); + } + else if (hRes == E_ELEMENT_NOT_FOUND) + { + // + // No ticket. Benign. + // + hRes = S_OK; + + DoTraceMessage(WS_WARNING, "ProcessFixedDocSequence uri %ws. Page print ticket not present.", static_cast<PCWSTR>(bstr)); + } + + return m_pReachConsumer->SendFixedDocumentSequence(pIFixedDocumentSequence); +} + +HRESULT +XpsFilter:: +ProcessFixedDoc( + _In_ void *pVoid + ) +{ + Tools::SmartPtr<IFixedDocument> pIFixedDocument; + + // + // XpsFilter::ProcessPart already incremented the reference count for the object. This + // function is taking ownership of the object, there is not need for another AddRef call + // (hence the Attach) + // + pIFixedDocument.Attach(static_cast<IFixedDocument *>(pVoid)); + + Tools::SmartBSTR bstr; + + if (SUCCEEDED(pIFixedDocument->GetUri(&bstr))) + { + DoTraceMessage(WS_TRACE, "ProcessFixedDoc uri %ws", static_cast<PCWSTR>(bstr)); + } + + Tools::SmartPtr<IPartPrintTicket> pIPrintTicket; + + HRESULT hRes = pIFixedDocument->GetPrintTicket(&pIPrintTicket); + + if (SUCCEEDED(hRes)) + { + hRes = ProcessTicket(pIPrintTicket); + } + else if (hRes == E_ELEMENT_NOT_FOUND) + { + // + // No ticket. Benign. + // + hRes = S_OK; + + DoTraceMessage(WS_WARNING, "ProcessFixedDoc uri %ws. Page print ticket not present.", static_cast<PCWSTR>(bstr)); + } + + return m_pReachConsumer->SendFixedDocument(pIFixedDocument); +} + +// +// IPrintPipelineFilter +// +__override +STDMETHODIMP +XpsFilter:: +ShutdownOperation( + void + ) +{ + m_bShutdown = true; + + return S_OK; +} + +__override +STDMETHODIMP +XpsFilter:: +InitializeFilter( + _In_ IInterFilterCommunicator *pIfc, + _In_ IPrintPipelinePropertyBag *pIPropertyBag, + _In_ IPrintPipelineManagerControl *pIPipelineControl + ) +{ + HRESULT hRes = S_OK; + + // + // IID_IReachPackageProvider must be specified in the config file + // + hRes = pIfc->RequestReader(reinterpret_cast<void **>(&m_pReachProvider)); + + if (SUCCEEDED(hRes)) + { + // + // IID_IReachPackageConsumer must be specified in the config file + // + hRes = pIfc->RequestWriter(reinterpret_cast<void **>(&m_pReachConsumer)); + + m_pIPipelineControl = pIPipelineControl; + } + + VARIANT var, var2, var3, var4; + + VariantInit(&var); + VariantInit(&var2); + VariantInit(&var3); + VariantInit(&var4); + + if (SUCCEEDED(hRes) && + SUCCEEDED(hRes = pIPropertyBag->GetProperty(XPS_FP_PRINTER_NAME, &var)) && + SUCCEEDED(hRes = pIPropertyBag->GetProperty(XPS_FP_PRINTER_HANDLE, &var2)) && + SUCCEEDED(hRes = pIPropertyBag->GetProperty(XPS_FP_JOB_ID, &var3)) && + SUCCEEDED(hRes = pIPropertyBag->GetProperty(XPS_FP_USER_TOKEN, &var4))) + { + PWSTR pszName = var.bstrVal; + HANDLE hPrinter = var2.byref; + ULONG jobId = var3.ulVal; + HANDLE hUserSecurityToken = var4.byref; + + // + // Filter can use devmode, hPrinter and pszName. byref value should not be freed/deleted + // in any way. bstrVal must be deleted by clearing the variant. + // + + // + // Do not free any byref resource. Ex: do not call CloseHandle on the security token + // + + // + // Remove these if you use the variables. This is in order to build clean with /W4 + // + UNREFERENCED_PARAMETER(jobId); + UNREFERENCED_PARAMETER(hPrinter); + UNREFERENCED_PARAMETER(pszName); + + // + // Sample code to show how to impersonate in order to access resources on behalf of the + // user who submitted the job + // + if (SetThreadToken(NULL, hUserSecurityToken)) + { + // + // now revert back to the original security context + // + if (!SetThreadToken(NULL, NULL)) + { + hRes = GetLastErrorAsHResult(); + } + } + else + { + hRes = GetLastErrorAsHResult(); + } + } + + VariantClear(&var); + VariantClear(&var2); + VariantClear(&var3); + VariantClear(&var4); + + // + // Example of how to add and delete a property from the bag + // + var.vt = VT_I4; + var.lVal = 5; + + if (SUCCEEDED(hRes) && + SUCCEEDED(hRes = pIPropertyBag->AddProperty(L"TestProperty", &var))) + { + hRes = pIPropertyBag->DeleteProperty(L"TestProperty") ? S_OK : E_FAIL; + } + + + return hRes; +} + +__override +STDMETHODIMP +XpsFilter:: +StartOperation( + void + ) +{ + HRESULT hRes = S_OK; + + while (SUCCEEDED(hRes) && !m_bShutdown) + { + Tools::SmartPtr<IUnknown> pUnk; + + hRes = m_pReachProvider->GetXpsPart(&pUnk); + + if (SUCCEEDED(hRes)) + { + if (!pUnk) + { + // + // End of objects + // + break; + } + + hRes = ProcessPart(pUnk); + } + } + + m_pReachConsumer->CloseSender(); + + if (FAILED(hRes)) + { +#pragma prefast(suppress:__WARNING_INVALID_PARAM_VALUE_1, "MSDN requires that pReason be NULL.") + m_pIPipelineControl->RequestShutdown(hRes, NULL); + } + + m_pIPipelineControl->FilterFinished(); + + return hRes; +} + +// +// IUnknown +// +STDMETHODIMP_(ULONG) +XpsFilter:: +AddRef( + VOID + ) +{ + return InterlockedIncrement(&m_cRef); +} + +STDMETHODIMP_(ULONG) +XpsFilter:: +Release( + VOID + ) +{ + ULONG cRefCount = InterlockedDecrement(&m_cRef); + + if (cRefCount) + { + return cRefCount; + } + + delete this; + + return 0; +} + +STDMETHODIMP +XpsFilter:: +QueryInterface( + _In_ REFIID riid, + _Out_ VOID **ppv + ) +{ + HRESULT hRes = E_POINTER; + + if (ppv) + { + hRes = E_NOINTERFACE; + + *ppv = NULL; + + if (riid == IID_IPrintPipelineFilter) + { + *ppv = static_cast<IPrintPipelineFilter *>(this); + } + else if (riid == IID_IUnknown) + { + *ppv = static_cast<IUnknown *>(this); + } + + if (*ppv) + { + AddRef(); + + hRes = S_OK; + } + } + + return hRes; +} + diff --git a/print/SimplePipelineFilter/XpsFilter.hxx b/print/SimplePipelineFilter/XpsFilter.hxx new file mode 100644 index 00000000..003650a6 --- /dev/null +++ b/print/SimplePipelineFilter/XpsFilter.hxx @@ -0,0 +1,126 @@ +//+-------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// This source code is intended only as a supplement to Microsoft +// Development Tools and/or on-line documentation. See these other +// materials for detailed information regarding Microsoft code samples. +// +// THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY +// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. +// +// Abstract: +// WDK print filter sample. +// This is the header file for the XPS sample. +// +//---------------------------------------------------------------------------- + +#ifndef _XPS_FILTER_SAMPLE_HXX_ +#define _XPS_FILTER_SAMPLE_HXX_ + +class XpsFilter : + public IPrintPipelineFilter, + private DllLockManager +{ +public: + + XpsFilter(); + + // + // IUnknown methods + // + __override + STDMETHODIMP + QueryInterface( + _In_ REFIID riid, + _Out_ void **ppv + ); + + __override + STDMETHODIMP_(ULONG) + AddRef( + void + ); + + __override + STDMETHODIMP_(ULONG) + Release( + void + ); + + // + // IPrintPipelineFilter + // + __override + STDMETHODIMP + ShutdownOperation( + void + ); + + __override + STDMETHODIMP + InitializeFilter( + _In_ IInterFilterCommunicator *pINegotiation, + _In_ IPrintPipelinePropertyBag *pIPropertyBag, + _In_ IPrintPipelineManagerControl *pIPipelineControl + ); + + __override + STDMETHODIMP + StartOperation( + void + ); + + // + // Other methods + // + static + const GUID& + FilterClsid( + void + ); + +private: + + HRESULT + ProcessFixedPage( + _In_ void *pVoid + ); + + HRESULT + ProcessXpsDoc( + _In_ void *pVoid + ); + + HRESULT + ProcessFixedDocSequence( + _In_ void *pVoid + ); + + HRESULT + ProcessFixedDoc( + _In_ void *pVoid + ); + + HRESULT + ProcessPart( + _In_ IUnknown *pUnk + ); + + static + HRESULT + ProcessImagePart( + _In_ IPartImage *pIPartImage + ); + + Tools::SmartPtr<IPrintPipelineManagerControl> m_pIPipelineControl; + Tools::SmartPtr<IXpsDocumentProvider> m_pReachProvider; + Tools::SmartPtr<IXpsDocumentConsumer> m_pReachConsumer; + bool m_bShutdown; + LONG m_cRef; + LONG m_cIdCount; +}; + +#endif // _XPS_FILTER_SAMPLE_HXX_ + diff --git a/print/SimplePipelineFilter/main.cxx b/print/SimplePipelineFilter/main.cxx new file mode 100644 index 00000000..180fb4c6 --- /dev/null +++ b/print/SimplePipelineFilter/main.cxx @@ -0,0 +1,172 @@ +//+-------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// This source code is intended only as a supplement to Microsoft +// Development Tools and/or on-line documentation. See these other +// materials for detailed information regarding Microsoft code samples. +// +// THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY +// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. +// +// Abstract: +// WDK print filter sample. This file contains the implementation for +// DllGetClassObject and DllMain +// +//---------------------------------------------------------------------------- + +#include "precomp.hxx" +#include "main.hxx" +#include "XpsFilter.hxx" +#include "StreamFilter.hxx" +#include "main.tmh" + +_Analysis_mode_(_Analysis_code_type_user_driver_) + +LONG DllLockManager::m_cGlobalRef = 0; + +HRESULT +WINAPI +DllCanUnloadNow(void) throw() +{ + return 0 == DllLockManager::GetGlobalRef() ? S_OK : S_FALSE; +} + +HRESULT +WINAPI +DllGetClassObject( + _In_ REFCLSID rclsid, + _In_ REFIID riid, + _Outptr_ PVOID *ppv + ) throw() +{ + HRESULT hRetval = E_POINTER; + + if (ppv) + { + *ppv = NULL; + + if (rclsid == XpsFilter::FilterClsid()) + { + Tools::SmartPtr<XpsFilter> pFilter; + + pFilter.Attach(new XpsFilter()); + + if (pFilter) + { + hRetval = pFilter->QueryInterface(riid, ppv); + } + else + { + hRetval = E_OUTOFMEMORY; + } + } + else if (rclsid == StreamFilter::FilterClsid()) + { + Tools::SmartPtr<StreamFilter> pFilter; + + pFilter.Attach(new StreamFilter()); + + if (pFilter) + { + hRetval = pFilter->QueryInterface(riid, ppv); + } + else + { + hRetval = E_OUTOFMEMORY; + } + } + else + { + hRetval = CLASS_E_CLASSNOTAVAILABLE; + } + } + + return hRetval; +} + +BOOL WINAPI +DllMain( + _In_ HINSTANCE hInst, + _In_ DWORD dwReason, + _In_opt_ PVOID pReserved + ) +{ + if (dwReason == DLL_PROCESS_ATTACH) + { + DisableThreadLibraryCalls(hInst); + + WPP_INIT_TRACING(L"WdkPipelineFilter"); + } + else if (dwReason == DLL_PROCESS_DETACH) + { + WPP_CLEANUP(); + } + + UNREFERENCED_PARAMETER(dwReason); + UNREFERENCED_PARAMETER(pReserved); + + return TRUE; +} + +void +WppTraceDebugOut( + _In_z_ const WCHAR *pszFmt, + ... + ) +{ + va_list pArgs; + + va_start(pArgs, pszFmt); + + WCHAR buf[MAX_PATH]; + + if (SUCCEEDED(StringCchVPrintf(buf, + MAX_PATH, + pszFmt, + pArgs)) && + SUCCEEDED(StringCchCat(buf, + MAX_PATH, + L"\n"))) + { + OutputDebugString(buf); + } + + va_end(pArgs); +} + +void +WppTraceDebugOut( + _In_z_ const CHAR *pszFmt, + ... + ) +{ + va_list pArgs; + + va_start(pArgs, pszFmt); + + CHAR buf[MAX_PATH]; + + if (SUCCEEDED(StringCchVPrintfA(buf, + MAX_PATH, + pszFmt, + pArgs)) && + SUCCEEDED(StringCchCatA(buf, + MAX_PATH, + "\n"))) + { + OutputDebugStringA(buf); + } + + va_end(pArgs); +} + + + + + + + + + diff --git a/print/SimplePipelineFilter/main.hxx b/print/SimplePipelineFilter/main.hxx new file mode 100644 index 00000000..88d8c052 --- /dev/null +++ b/print/SimplePipelineFilter/main.hxx @@ -0,0 +1,51 @@ +//+-------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// This source code is intended only as a supplement to Microsoft +// Development Tools and/or on-line documentation. See these other +// materials for detailed information regarding Microsoft code samples. +// +// THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY +// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. +// +// Abstract: +// WDK print filter sample. +// The filters need to derive from DllLockManager. Thus the filter constructor and +// destructor call the DllLockManager constructor and destructor, respectively. +// +//---------------------------------------------------------------------------- + +#ifndef _FILTER_MAIN_HXX_ +#define _FILTER_MAIN_HXX_ + +class DllLockManager +{ +public: + + DllLockManager() + { + InterlockedIncrement(&m_cGlobalRef); + } + + ~DllLockManager() + { + InterlockedDecrement(&m_cGlobalRef); + } + + static + LONG + GetGlobalRef() + { + return InterlockedCompareExchange(&m_cGlobalRef, 0, 0); + } + +private: + + static LONG m_cGlobalRef; +}; + +#endif + + diff --git a/print/SimplePipelineFilter/precomp.hxx b/print/SimplePipelineFilter/precomp.hxx new file mode 100644 index 00000000..4ca7012d --- /dev/null +++ b/print/SimplePipelineFilter/precomp.hxx @@ -0,0 +1,26 @@ +//+-------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// This source code is intended only as a supplement to Microsoft +// Development Tools and/or on-line documentation. See these other +// materials for detailed information regarding Microsoft code samples. +// +// THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY +// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. +// +// Abstract: +// WDK print filter sample. +// This is the precompiled header file. +// +//---------------------------------------------------------------------------- + +#include <windows.h> +#include <common.ver> +#include <filterpipeline.h> +#include <strsafe.h> +#include "smartptr.hxx" +#include "trace.hxx" + +_Analysis_mode_(_Analysis_code_type_user_driver_) diff --git a/print/SimplePipelineFilter/precompsrc.cpp b/print/SimplePipelineFilter/precompsrc.cpp new file mode 100644 index 00000000..5d84a122 --- /dev/null +++ b/print/SimplePipelineFilter/precompsrc.cpp @@ -0,0 +1 @@ +#include "precomp.hxx"
\ No newline at end of file diff --git a/print/SimplePipelineFilter/smartptr.hxx b/print/SimplePipelineFilter/smartptr.hxx new file mode 100644 index 00000000..7f20c530 --- /dev/null +++ b/print/SimplePipelineFilter/smartptr.hxx @@ -0,0 +1,233 @@ +//+-------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// This source code is intended only as a supplement to Microsoft +// Development Tools and/or on-line documentation. See these other +// materials for detailed information regarding Microsoft code samples. +// +// THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY +// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. +// +// Abstract: +// WDK print filter sample. +// This file contains a smart pointer implementation. +// +//---------------------------------------------------------------------------- + +#ifndef __SAMPLE_SMART_PTR_HXX__ +#define __SAMPLE_SMART_PTR_HXX__ + +namespace Tools +{ + +template<class T> +inline +void +SmartAddRef( + T *pInterface + ) throw() +{ + if (pInterface) + { + pInterface->AddRef(); + } +} + +template<class T> +inline +void +SmartRelease( + T **ppInterface + ) throw() +{ + if (*ppInterface) + { + (*ppInterface)->Release(); + *ppInterface = NULL; + } +} + +template<class T> +class SmartPtr +{ +public: + + inline + SmartPtr( + void + ) throw() : m_Pointer(NULL) + { + } + + inline + SmartPtr( + _In_opt_ T *pointer + ) throw() + : m_Pointer(pointer) + { + SmartAddRef(m_Pointer); + } + + inline + SmartPtr( + _In_ const SmartPtr © + ) throw() + { + m_Pointer = copy.m_Pointer; + SmartAddRef(m_Pointer); + } + + inline + ~SmartPtr( + void + ) throw() + { + SmartRelease(&m_Pointer); + } + + inline + SmartPtr & + operator=( + _In_opt_ T *pointer + ) throw() + { + T *temp = m_Pointer; + + m_Pointer = pointer; + SmartAddRef(m_Pointer); + SmartRelease(&temp); + + return *this; + } + + inline + SmartPtr & + operator=( + _In_ const SmartPtr © + ) throw() + { + T *temp = m_Pointer; + + m_Pointer = copy.m_Pointer; + SmartAddRef(m_Pointer); + SmartRelease(&temp); + + return *this; + } + + inline + operator T *() throw() + { + return m_Pointer; + } + + inline + operator const T *() const throw() + { + return m_Pointer; + } + + inline + T ** + operator&() throw() + { + return &m_Pointer; + } + + inline + const T ** + operator&() const throw() + { + return &m_Pointer; + } + + inline + T * + operator->() throw() + { + return m_Pointer; + } + + inline + const T * + operator->( + ) const throw() + { + return m_Pointer; + } + + inline + void + Attach( + _In_opt_ T *pointer + ) throw() + { + T *temp = m_Pointer; + m_Pointer = pointer; + + SmartRelease(&temp); + } + + inline + T * + Detach( + void + ) throw() + { + T *pTemp = m_Pointer; + m_Pointer = NULL; + + return pTemp; + } + + inline + void + Clear( + void + ) throw() + { + SmartRelease(&m_Pointer); + } + +private: + + T *m_Pointer; +}; + +/////////////////////////////////////////////////////////////////////////////// + +class SmartBSTR +{ +public: + + SmartBSTR() throw() + : m_bstr (NULL) + { + } + + ~SmartBSTR() throw() + { + ::SysFreeString(m_bstr); + } + + operator BSTR() const throw() + { + return m_bstr; + } + + BSTR* + operator&() throw() + { + return &m_bstr; + } + +private: + + BSTR m_bstr; +}; + +}; // namespace tools + +#endif diff --git a/print/SimplePipelineFilter/trace.hxx b/print/SimplePipelineFilter/trace.hxx new file mode 100644 index 00000000..8b905c49 --- /dev/null +++ b/print/SimplePipelineFilter/trace.hxx @@ -0,0 +1,51 @@ +//+-------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// This source code is intended only as a supplement to Microsoft +// Development Tools and/or on-line documentation. See these other +// materials for detailed information regarding Microsoft code samples. +// +// THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY +// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. +// +// Abstract: +// WDK print filter sample. +// Declares what is needed to Event Tracing. +// +//---------------------------------------------------------------------------- + +#ifndef __WDK_SAMPLE_TRACE_HXX__ +#define __WDK_SAMPLE_TRACE_HXX__ + +// +// Generate your own guid. Feel free to add more flags, as needed. +// +#define WPP_CONTROL_GUIDS \ + WPP_DEFINE_CONTROL_GUID(WdkSample, (79ad6dce, adad, 47ae, b49e, 41bcdccf9ed8), \ + WPP_DEFINE_BIT(WS_ERROR) \ + WPP_DEFINE_BIT(WS_WARNING) \ + WPP_DEFINE_BIT(WS_TRACE) \ + ) + +void +WppTraceDebugOut( + _In_z_ const WCHAR *pszFmt, + ... + ); + +void +WppTraceDebugOut( + _In_z_ const CHAR *pszFmt, + ... + ); + +// +// For checked builds, send output to debugger rather than to file +// +#ifdef DBG +#define WPP_DEBUG(x) WppTraceDebugOut x +#endif + +#endif |
