summaryrefslogtreecommitdiff
path: root/print/SimplePipelineFilter
diff options
context:
space:
mode:
authorDave Wilson <[email protected]>2015-03-17 19:50:07 -0700
committerDave Wilson <[email protected]>2015-03-17 19:50:07 -0700
commit97cf5197cf5b882b2c689d8dc2b555f2edf8f418 (patch)
tree46f3701832d70b420eb0fc0eb93261f9da45db3f /print/SimplePipelineFilter
parentef1905bf1e8825bb31120dfb27e0daf3154d859a (diff)
Initial publish
Diffstat (limited to 'print/SimplePipelineFilter')
-rw-r--r--print/SimplePipelineFilter/FilterSample.def8
-rw-r--r--print/SimplePipelineFilter/FilterSample.rc10
-rw-r--r--print/SimplePipelineFilter/ReadMe.md9
-rw-r--r--print/SimplePipelineFilter/SimplePipelineFilter.sln28
-rw-r--r--print/SimplePipelineFilter/StreamFilter.cxx263
-rw-r--r--print/SimplePipelineFilter/StreamFilter.hxx99
-rw-r--r--print/SimplePipelineFilter/WdkPipelineFilter.vcxproj294
-rw-r--r--print/SimplePipelineFilter/WdkPipelineFilter.vcxproj.Filters39
-rw-r--r--print/SimplePipelineFilter/XpsFilter.cxx785
-rw-r--r--print/SimplePipelineFilter/XpsFilter.hxx126
-rw-r--r--print/SimplePipelineFilter/main.cxx172
-rw-r--r--print/SimplePipelineFilter/main.hxx51
-rw-r--r--print/SimplePipelineFilter/precomp.hxx26
-rw-r--r--print/SimplePipelineFilter/precompsrc.cpp1
-rw-r--r--print/SimplePipelineFilter/smartptr.hxx233
-rw-r--r--print/SimplePipelineFilter/trace.hxx51
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 &copy
+ ) 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 &copy
+ ) 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