summaryrefslogtreecommitdiff
path: root/print/XpsRasFilter/src
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/XpsRasFilter/src
parentef1905bf1e8825bb31120dfb27e0daf3154d859a (diff)
Initial publish
Diffstat (limited to 'print/XpsRasFilter/src')
-rw-r--r--print/XpsRasFilter/src/BitmapHandler.cpp361
-rw-r--r--print/XpsRasFilter/src/BitmapHandler.h64
-rw-r--r--print/XpsRasFilter/src/Exception.cpp43
-rw-r--r--print/XpsRasFilter/src/Exception.h86
-rw-r--r--print/XpsRasFilter/src/OMConvertor.cpp774
-rw-r--r--print/XpsRasFilter/src/OMConvertor.h90
-rw-r--r--print/XpsRasFilter/src/PThandler.cpp781
-rw-r--r--print/XpsRasFilter/src/PThandler.h112
-rw-r--r--print/XpsRasFilter/src/UnknownBase.h158
-rw-r--r--print/XpsRasFilter/src/WppTrace.cpp41
-rw-r--r--print/XpsRasFilter/src/WppTrace.h58
-rw-r--r--print/XpsRasFilter/src/dllentry.cpp326
-rw-r--r--print/XpsRasFilter/src/filtertypes.h497
-rw-r--r--print/XpsRasFilter/src/precomp.h86
-rw-r--r--print/XpsRasFilter/src/precompsrc.cpp1
-rw-r--r--print/XpsRasFilter/src/rasinterface.cpp412
-rw-r--r--print/XpsRasFilter/src/rasinterface.h107
-rw-r--r--print/XpsRasFilter/src/xpsrasfilter.cpp396
-rw-r--r--print/XpsRasFilter/src/xpsrasfilter.def22
-rw-r--r--print/XpsRasFilter/src/xpsrasfilter.h141
-rw-r--r--print/XpsRasFilter/src/xpsrasfilter.rc28
-rw-r--r--print/XpsRasFilter/src/xpsrasfilter.vcxproj349
-rw-r--r--print/XpsRasFilter/src/xpsrasfilter.vcxproj.Filters54
23 files changed, 4987 insertions, 0 deletions
diff --git a/print/XpsRasFilter/src/BitmapHandler.cpp b/print/XpsRasFilter/src/BitmapHandler.cpp
new file mode 100644
index 00000000..d887ddab
--- /dev/null
+++ b/print/XpsRasFilter/src/BitmapHandler.cpp
@@ -0,0 +1,361 @@
+// THIS CODE AND INFORMATION IS 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.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved
+//
+// File Name:
+//
+// BitmapHandler.cpp
+//
+// Abstract:
+//
+// Abstract class that encapsulates the processing done to each
+// individual band bitmap, as well as the concrete implemention
+// that streams the bands as Tiffs to the output stream.
+//
+
+#include "precomp.h"
+#include "WppTrace.h"
+#include "Exception.h"
+#include "filtertypes.h"
+#include "UnknownBase.h"
+#include "xpsrasfilter.h"
+#include "OMConvertor.h"
+#include "rasinterface.h"
+#include "BitmapHandler.h"
+
+#include "BitmapHandler.tmh"
+
+namespace xpsrasfilter
+{
+
+//
+//Routine Name:
+//
+// TiffStreamBitmapHandler::CreateTiffStreamBitmapHandler
+//
+//Routine Description:
+//
+// Static factory method that creates an instance of
+// TiffStreamBitmapHandler.
+//
+//Arguments:
+//
+// pStream - Filter output stream (IPrintWriteStream)
+//
+//Return Value:
+//
+// TiffStreamBitmapHandler_t (smart ptr)
+// The new TiffStreamBitmapHandler.
+//
+TiffStreamBitmapHandler_t
+TiffStreamBitmapHandler::CreateTiffStreamBitmapHandler(
+ const IPrintWriteStream_t &pStream
+ )
+{
+ IWICImagingFactory_t pWICFactory;
+
+ //
+ // Create an instance of a WIC Imaging Factory
+ //
+ THROW_ON_FAILED_HRESULT(
+ ::CoCreateInstance(
+ CLSID_WICImagingFactory,
+ NULL,
+ CLSCTX_INPROC_SERVER,
+ __uuidof(IWICImagingFactory),
+ reinterpret_cast<LPVOID*>(&pWICFactory)
+ )
+ );
+
+ //
+ // Construct the TiffStreamBitmapHandler and return it
+ //
+ TiffStreamBitmapHandler_t toReturn(
+ new TiffStreamBitmapHandler(
+ pWICFactory,
+ pStream
+ )
+ );
+
+ return toReturn;
+}
+
+//
+//Routine Name:
+//
+// TiffStreamBitmapHandler::TiffStreamBitmapHandler
+//
+//Routine Description:
+//
+// Construct the bitmap handler with the WIC factory
+// and filter output stream.
+//
+//Arguments:
+//
+// pWICFactory - Windows Imaging Components object factory
+// pStream - Output stream
+// pHG - Encoder cache HGLOBAL
+//
+TiffStreamBitmapHandler::TiffStreamBitmapHandler(
+ const IWICImagingFactory_t &pWICFactory,
+ const IPrintWriteStream_t &pStream
+ ) : m_pWICFactory(pWICFactory),
+ m_pWriter(pStream),
+ m_nextTiffStart(0),
+ m_numTiffs(0),
+ m_tiffStarts(0)
+{
+}
+
+//
+//Routine Name:
+//
+// TiffStreamBitmapHandler::ProcessBitmap
+//
+//Routine Description:
+//
+// Encode the bitmap as a TIFF and stream out of the filter.
+//
+//Arguments:
+//
+// bitmap - bitmap of a single band, to stream
+//
+void
+TiffStreamBitmapHandler::ProcessBitmap(
+ const IWICBitmap_t &bitmap
+ )
+{
+
+ //
+ // Create an empty HGLOBAL to hold the encode cache
+ //
+ SafeHGlobal_t pHG(
+ new SafeHGlobal(GMEM_SHARE | GMEM_MOVEABLE, 0)
+ );
+
+ //
+ // Create a stream to the encode buffer so that WIC can
+ // encode the TIFF in-memory
+ //
+ IStream_t pIStream;
+
+ THROW_ON_FAILED_HRESULT(
+ ::CreateStreamOnHGlobal(
+ *pHG,
+ FALSE, // Do NOT Free the HGLOBAL on Release of the stream
+ &pIStream
+ )
+ );
+
+ //
+ // Create a WIC TIFF Encoder on the stream
+ //
+ IWICBitmapEncoder_t pWICEncoder;
+ THROW_ON_FAILED_HRESULT(
+ m_pWICFactory->CreateEncoder(GUID_ContainerFormatTiff, NULL, &pWICEncoder)
+ );
+ THROW_ON_FAILED_HRESULT(
+ pWICEncoder->Initialize(pIStream, WICBitmapEncoderNoCache)
+ );
+
+ //
+ // Create a new frame for the band and configure it
+ //
+ IWICBitmapFrameEncode_t pWICFrame;
+ IPropertyBag2_t pFramePropertyBag;
+
+ THROW_ON_FAILED_HRESULT(
+ pWICEncoder->CreateNewFrame(&pWICFrame, &pFramePropertyBag)
+ );
+
+ {
+ //
+ // Write the compression method to the frame's property bag
+ //
+ PROPBAG2 option = { 0 };
+ option.pstrName = L"TiffCompressionMethod";
+
+ VARIANT varValue;
+ VariantInit(&varValue);
+ varValue.vt = VT_UI1;
+ varValue.bVal = WICTiffCompressionLZW;
+
+ THROW_ON_FAILED_HRESULT(
+ pFramePropertyBag->Write(
+ 1, // number of properties being set
+ &option,
+ &varValue
+ )
+ );
+ }
+
+ THROW_ON_FAILED_HRESULT(
+ pWICFrame->Initialize(pFramePropertyBag)
+ );
+
+ //
+ // Set the frame's size
+ //
+ UINT bitmapWidth, bitmapHeight;
+ THROW_ON_FAILED_HRESULT(
+ bitmap->GetSize(&bitmapWidth, &bitmapHeight)
+ );
+ THROW_ON_FAILED_HRESULT(
+ pWICFrame->SetSize(bitmapWidth, bitmapHeight)
+ );
+
+ //
+ // Set the frame's resolution
+ //
+ DOUBLE xDPI, yDPI;
+ THROW_ON_FAILED_HRESULT(
+ bitmap->GetResolution(&xDPI, &yDPI)
+ );
+ THROW_ON_FAILED_HRESULT(
+ pWICFrame->SetResolution(xDPI, yDPI)
+ );
+
+ //
+ // Set the frame's pixel format
+ //
+ WICPixelFormatGUID format;
+ THROW_ON_FAILED_HRESULT(
+ bitmap->GetPixelFormat(&format)
+ );
+ THROW_ON_FAILED_HRESULT(
+ pWICFrame->SetPixelFormat(&format)
+ );
+
+ //
+ // Write the bitmap data to the frame
+ //
+ WICRect rect = {0, 0, 0, 0};
+ rect.Width = bitmapWidth;
+ rect.Height = bitmapHeight;
+ THROW_ON_FAILED_HRESULT(
+ pWICFrame->WriteSource(bitmap, &rect)
+ );
+
+ //
+ // Commit the frame and encoder
+ //
+ THROW_ON_FAILED_HRESULT(
+ pWICFrame->Commit()
+ );
+ THROW_ON_FAILED_HRESULT(
+ pWICEncoder->Commit()
+ );
+
+ //
+ // Get the size of the TIFF from the stream position
+ //
+ ULARGE_INTEGER tiffSize;
+ LARGE_INTEGER zero;
+ zero.QuadPart = 0;
+
+ THROW_ON_FAILED_HRESULT(
+ pIStream->Seek(zero, SEEK_CUR, &tiffSize)
+ );
+
+ ULONG cb;
+
+ THROW_ON_FAILED_HRESULT(
+ ::ULongLongToULong(tiffSize.QuadPart, &cb)
+ );
+
+ //
+ // Update the list of Tiff locations so that it can be written to
+ // the end of the Tiff stream.
+ //
+ m_tiffStarts.push_back(m_nextTiffStart);
+ m_nextTiffStart += tiffSize.QuadPart;
+ m_numTiffs++;
+
+ {
+ //
+ // Get a pointer to the HGLOBAL memory
+ //
+ HGlobalLock_t lock = pHG->Lock();
+ BYTE *pCache = lock->GetAddress();
+
+ //
+ // Write the encoded Tiff to the output stream
+ //
+ ULONG written;
+
+ THROW_ON_FAILED_HRESULT(
+ m_pWriter->WriteBytes(pCache, cb, &written)
+ );
+ }
+}
+
+//
+//Routine Name:
+//
+// TiffStreamBitmapHandler::WriteFooter
+//
+//Routine Description:
+//
+// Write the footer to the stream, making it easier
+// to decode the individual TIFFs later. The footer
+// looks like this:
+//
+// |<--8 bytes--->|
+//
+// +--------------+
+// | Tiff 1 start |
+// +--------------+
+// | Tiff 2 start |
+// +--------------+
+// | ... |
+// +--------------+
+// | Tiff N start |
+// +--------------+
+// | N |
+// +--------------+
+//
+void
+TiffStreamBitmapHandler::WriteFooter()
+{
+ ULONG written;
+
+ //
+ // Write the vector of Tiff starts to the stream, if any Tiffs
+ // have been written to the stream.
+ //
+ if (m_numTiffs > 0)
+ {
+ ULONG toWrite;
+
+ THROW_ON_FAILED_HRESULT(
+ SizeTToULong(
+ sizeof(ULONGLONG) * m_tiffStarts.size(),
+ &toWrite
+ )
+ );
+
+ THROW_ON_FAILED_HRESULT(
+ m_pWriter->WriteBytes(
+ reinterpret_cast<BYTE *>(&m_tiffStarts[0]),
+ toWrite,
+ &written
+ )
+ );
+ }
+
+ //
+ // Write the number of Tiffs to the stream
+ //
+ THROW_ON_FAILED_HRESULT(
+ m_pWriter->WriteBytes(
+ reinterpret_cast<BYTE *>(&m_numTiffs),
+ sizeof(m_numTiffs),
+ &written
+ )
+ );
+}
+
+} // namespace xpsrasfilter
diff --git a/print/XpsRasFilter/src/BitmapHandler.h b/print/XpsRasFilter/src/BitmapHandler.h
new file mode 100644
index 00000000..3f78dc30
--- /dev/null
+++ b/print/XpsRasFilter/src/BitmapHandler.h
@@ -0,0 +1,64 @@
+// THIS CODE AND INFORMATION IS 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.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved
+//
+// File Name:
+//
+// BitmapHandler.h
+//
+// Abstract:
+//
+// Abstract class that encapsulates the processing done to each
+// individual band bitmap, as well as the concrete implemention
+// that streams the bands as Tiffs to the output stream.
+//
+
+#pragma once
+
+namespace xpsrasfilter
+{
+
+class TiffStreamBitmapHandler
+{
+public:
+
+ static
+ TiffStreamBitmapHandler_t
+ CreateTiffStreamBitmapHandler(
+ const IPrintWriteStream_t &pStream
+ );
+
+ void
+ ProcessBitmap(
+ const IWICBitmap_t &bitmap
+ );
+
+ void
+ WriteFooter();
+
+private:
+ IWICImagingFactory_t m_pWICFactory;
+ IPrintWriteStream_t m_pWriter; // output stream
+
+ //
+ // Members to keep track of where each Tiff
+ // starts in the output stream
+ //
+ ULONGLONG m_nextTiffStart;
+ ULONGLONG m_numTiffs;
+ std::vector<ULONGLONG> m_tiffStarts;
+
+ //
+ // Constructor is private; use CreateTiffStreamBitmapHandler
+ // to create instances
+ //
+ TiffStreamBitmapHandler(
+ const IWICImagingFactory_t &pWICFactory,
+ const IPrintWriteStream_t &pStream
+ );
+};
+
+} // namespace xpsrasfilter
diff --git a/print/XpsRasFilter/src/Exception.cpp b/print/XpsRasFilter/src/Exception.cpp
new file mode 100644
index 00000000..141c1ac3
--- /dev/null
+++ b/print/XpsRasFilter/src/Exception.cpp
@@ -0,0 +1,43 @@
+// THIS CODE AND INFORMATION IS 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.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved
+//
+// File Name:
+//
+// Exception.cpp
+//
+// Abstract:
+//
+// Exception routine definitions.
+//
+
+#include "precomp.h"
+#include "WppTrace.h"
+#include "Exception.h"
+
+#include "Exception.tmh"
+
+namespace xpsrasfilter
+{
+
+void ThrowHRException(
+ HRESULT hr,
+ char const *fileName,
+ int lineNum
+ )
+{
+ DoTraceMessage(
+ XPSRASFILTER_TRACE_ERROR,
+ L"Throwing HRESULT Exception from %s:%d (HRESULT=%!HRESULT!)",
+ fileName,
+ lineNum,
+ hr
+ );
+
+ throw hr_error(hr);
+}
+
+} // namespace xpsrasfilter
diff --git a/print/XpsRasFilter/src/Exception.h b/print/XpsRasFilter/src/Exception.h
new file mode 100644
index 00000000..887bfbc4
--- /dev/null
+++ b/print/XpsRasFilter/src/Exception.h
@@ -0,0 +1,86 @@
+// THIS CODE AND INFORMATION IS 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.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved
+//
+// File Name:
+//
+// Exception.h
+//
+// Abstract:
+//
+// Exception macro and class declarations.
+//
+
+#pragma once
+
+//
+// Macro to convert HRESULT into an exception throw
+//
+#ifndef THROW_ON_FAILED_HRESULT
+#define THROW_ON_FAILED_HRESULT(func_) \
+{ \
+ HRESULT hr_ = func_; \
+ if (FAILED(hr_)) { xpsrasfilter::ThrowHRException(hr_, __FILE__, __LINE__); } \
+}
+#endif // THROW_ON_FAILED_HRESULT
+
+#ifndef THROW_LAST_ERROR
+#define THROW_LAST_ERROR() \
+{ \
+ HRESULT errhr_ = HRESULT_FROM_WIN32(::GetLastError()); \
+ THROW_ON_FAILED_HRESULT(errhr_); \
+}
+#endif // THROW_LAST_ERROR
+
+//
+// Macro to catch various exceptions, including
+// HRESULT-turned-exceptions.
+//
+// Because we have defined USE_NATIVE_EH=1, the
+// catch(...) block will not catch structural
+// exceptions.
+//
+#ifndef CATCH_VARIOUS
+#define CATCH_VARIOUS(hr_) \
+ catch(std::bad_alloc const& ) \
+ { \
+ hr_ = E_OUTOFMEMORY; \
+ } \
+ catch(xpsrasfilter::hr_error const& e) \
+ { \
+ hr_ = e.hr; \
+ } \
+ catch(std::exception const& ) \
+ { \
+ hr_ = E_FAIL; \
+ } \
+ catch(...) \
+ { \
+ hr_ = E_UNEXPECTED; \
+ }
+#endif // CATCH_VARIOUS
+
+namespace xpsrasfilter
+{
+
+//
+// HRESULT exception
+//
+struct hr_error
+{
+ HRESULT hr;
+
+ hr_error(HRESULT hr_in) : hr(hr_in)
+ { }
+};
+
+void ThrowHRException(
+ HRESULT hr,
+ char const *fileName,
+ int lineNum
+ );
+
+} // namespace xpsrasfilter
diff --git a/print/XpsRasFilter/src/OMConvertor.cpp b/print/XpsRasFilter/src/OMConvertor.cpp
new file mode 100644
index 00000000..2cd478c2
--- /dev/null
+++ b/print/XpsRasFilter/src/OMConvertor.cpp
@@ -0,0 +1,774 @@
+// THIS CODE AND INFORMATION IS 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.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved
+//
+// File Name:
+//
+// omconvertor.cpp
+//
+// Abstract:
+//
+// Object model conversion routines. This class provides routines
+// to convert from filter pipeline objects into Xps Object Model
+// objects.
+//
+
+#include "precomp.h"
+#include "WppTrace.h"
+#include "Exception.h"
+#include "filtertypes.h"
+#include "UnknownBase.h"
+#include "OMConvertor.h"
+
+#include "OMConvertor.tmh"
+
+namespace xpsrasfilter
+{
+
+//
+//Routine Name:
+//
+// CreateXpsOMPageFromIFixedPage
+//
+//Routine Description:
+//
+// This is the main method called by the filter. It
+// proceeds to call the remaining Create* methods
+// to convert from the print pipeline Object Model
+// to the Xps Object Model.
+//
+// Takes an IFixedPage (print pipeline Object Model)
+// and converts it to an IXpsOMPage (Xps Object Model).
+//
+//Arguments:
+//
+// pPageIn - IFixedPage to convert
+// pOMFactory - Xps Object Model Object Factory
+// pOpcFactory - Opc Object Factory
+//
+//Return Value:
+//
+// IXpsOMPage_t (smart pointer)
+// Result IXpsOMPage
+//
+IXpsOMPage_t
+CreateXpsOMPageFromIFixedPage(
+ const IFixedPage_t &pPageIn,
+ const IXpsOMObjectFactory_t &pOMFactory,
+ const IOpcFactory_t &pOpcFactory
+ )
+{
+ //
+ // Get additional page parameters (uri and stream)
+ //
+ IOpcPartUri_t pPartUri;
+ IStream_t pPartStream;
+
+ pPartStream = GetStreamFromPart(
+ static_cast<IPartBase_t>(pPageIn)
+ );
+ pPartUri = CreateOpcPartUriFromPart(
+ static_cast<IPartBase_t>(pPageIn),
+ pOpcFactory
+ );
+
+ //
+ // Call Xps Object Model to create the page resource
+ //
+ IXpsOMPage_t pPageOut;
+
+ THROW_ON_FAILED_HRESULT(
+ pOMFactory->CreatePageFromStream(
+ pPartStream,
+ pPartUri,
+ CollectPageResources(pPageIn, pOMFactory, pOpcFactory),
+ FALSE, // Do not reuse objects
+ &pPageOut
+ )
+ );
+
+ return pPageOut;
+}
+
+//
+//Routine Name:
+//
+// CreateImageFromIPartImage
+//
+//Routine Description:
+//
+// Takes an IPartImage (print pipeline Object Model)
+// and converts it to an IXpsOMImageResource (Xps Object Model).
+//
+//Arguments:
+//
+// pImageIn - IPartImage to convert
+// pOMFactory - Xps Object Model Object Factory
+// pOpcFactory - Opc Object Factory
+//
+//Return Value:
+//
+// IXpsOMImageResource_t (smart pointer)
+// Result IXpsOMImageResource
+//
+IXpsOMImageResource_t
+CreateImageFromIPartImage(
+ const IPartImage_t &pImageIn,
+ const IXpsOMObjectFactory_t &pOMFactory,
+ const IOpcFactory_t &pOpcFactory
+ )
+{
+ //
+ // Get IPartBase parameters (stream and uri)
+ //
+ IStream_t pPartStream;
+ IOpcPartUri_t pPartUri;
+
+ pPartStream = GetStreamFromPart(
+ static_cast<IPartBase_t>(pImageIn)
+ );
+ pPartUri = CreateOpcPartUriFromPart(
+ static_cast<IPartBase_t>(pImageIn),
+ pOpcFactory
+ );
+
+ //
+ // Get the image type and convert it to the corresponding enum
+ //
+ BSTR_t strContentType;
+ XPS_IMAGE_TYPE type = XPS_IMAGE_TYPE_WDP;
+
+ THROW_ON_FAILED_HRESULT(
+ pImageIn->GetImageProperties(&strContentType)
+ );
+
+ if (0 == _wcsicmp(strContentType, L"image/jpeg"))
+ {
+ type = XPS_IMAGE_TYPE_JPEG;
+ }
+ else if (0 == _wcsicmp(strContentType, L"image/png"))
+ {
+ type = XPS_IMAGE_TYPE_PNG;
+ }
+ else if (0 == _wcsicmp(strContentType, L"image/tiff"))
+ {
+ type = XPS_IMAGE_TYPE_TIFF;
+ }
+ else if (0 == _wcsicmp(strContentType, L"image/vnd.ms-photo"))
+ {
+ type = XPS_IMAGE_TYPE_WDP;
+ }
+ else
+ {
+ //
+ // unknown content type
+ //
+ THROW_ON_FAILED_HRESULT(E_INVALIDARG);
+ }
+
+ //
+ // Call Xps Object Model to create the image resource
+ //
+ IXpsOMImageResource_t pImageOut;
+
+ THROW_ON_FAILED_HRESULT(
+ pOMFactory->CreateImageResource(
+ pPartStream,
+ type,
+ pPartUri,
+ &pImageOut
+ )
+ );
+
+ return pImageOut;
+}
+
+//
+//Routine Name:
+//
+// CreateProfileFromIPartColorProfile
+//
+//Routine Description:
+//
+// Takes an IPartColorProfile (print pipeline Object Model)
+// and converts it to an IXpsOMColorProfileResource (Xps Object Model).
+//
+//Arguments:
+//
+// pProfileIn - IPartColorProfile to convert
+// pOMFactory - Xps Object Model Object Factory
+// pOpcFactory - Opc Object Factory
+//
+//Return Value:
+//
+// IXpsOMColorProfileResource_t (smart pointer)
+// Result IXpsOMColorProfileResource
+//
+IXpsOMColorProfileResource_t
+CreateProfileFromIPartColorProfile(
+ const IPartColorProfile_t &pProfileIn,
+ const IXpsOMObjectFactory_t &pOMFactory,
+ const IOpcFactory_t &pOpcFactory
+ )
+{
+ //
+ // Get IPartBase parameters (stream and uri)
+ //
+ IStream_t pPartStream;
+ IOpcPartUri_t pPartUri;
+
+ pPartStream = GetStreamFromPart(
+ static_cast<IPartBase_t>(pProfileIn)
+ );
+ pPartUri = CreateOpcPartUriFromPart(
+ static_cast<IPartBase_t>(pProfileIn),
+ pOpcFactory
+ );
+
+ //
+ // Call Xps Object Model to create the color profile resource
+ //
+ IXpsOMColorProfileResource_t pProfileOut;
+
+ THROW_ON_FAILED_HRESULT(
+ pOMFactory->CreateColorProfileResource(
+ pPartStream,
+ pPartUri,
+ &pProfileOut
+ )
+ );
+
+ return pProfileOut;
+}
+
+//
+//Routine Name:
+//
+// CreateDictionaryFromIPartResourceDictionary
+//
+//Routine Description:
+//
+// Takes an IPartResourceDictionary (print pipeline Object Model)
+// and converts it to an IXpsOMRemoteDictionaryResource (Xps Object Model).
+//
+//Arguments:
+//
+// pDictionaryIn - IPartResourceDictionary to convert
+// pOMFactory - Xps Object Model Object Factory
+// pOpcFactory - Opc Object Factory
+// pResources - The resources of the fixed page
+//
+//Return Value:
+//
+// IXpsOMRemoteDictionaryResource_t (smart pointer)
+// Result IXpsOMRemoteDictionaryResource
+//
+IXpsOMRemoteDictionaryResource_t
+CreateDictionaryFromIPartResourceDictionary(
+ const IPartResourceDictionary_t &pDictionaryIn,
+ const IXpsOMObjectFactory_t &pOMFactory,
+ const IOpcFactory_t &pOpcFactory,
+ const IXpsOMPartResources_t &pResources
+ )
+{
+ //
+ // Get IPartBase parameters (stream and uri)
+ //
+ IStream_t pPartStream;
+ IOpcPartUri_t pPartUri;
+
+ pPartStream = GetStreamFromPart(
+ static_cast<IPartBase_t>(pDictionaryIn)
+ );
+ pPartUri = CreateOpcPartUriFromPart(
+ static_cast<IPartBase_t>(pDictionaryIn),
+ pOpcFactory
+ );
+
+ //
+ // Call Xps Object Model to create the remote dictionary resource
+ //
+ IXpsOMRemoteDictionaryResource_t pDictionaryOut;
+
+ THROW_ON_FAILED_HRESULT(
+ pOMFactory->CreateRemoteDictionaryResourceFromStream(
+ pPartStream,
+ pPartUri,
+ pResources,
+ &pDictionaryOut)
+ );
+
+ return pDictionaryOut;
+}
+
+//
+//Routine Name:
+//
+// CreateFontFromIPartFont
+//
+//Routine Description:
+//
+// Takes an IPartFont (print pipeline Object Model)
+// and converts it to an IXpsOMFontResource (Xps Object Model).
+//
+//Arguments:
+//
+// pFontIn - IPartFont to convert
+// pFactory - Xps Object Model Object Factory
+// pOpcFactory - Opc Object Factory
+//
+//Return Value:
+//
+// IXpsOMFontResource_t (smart pointer)
+// Result IXpsOMFontResource
+//
+IXpsOMFontResource_t
+CreateFontFromIPartFont(
+ const IPartFont_t &pFontIn,
+ const IXpsOMObjectFactory_t &pOMFactory,
+ const IOpcFactory_t &pOpcFactory
+ )
+{
+ //
+ // Get IPartBase parameters (stream and uri)
+ //
+ IStream_t pPartStream;
+ IOpcPartUri_t pPartUri;
+
+ pPartStream = GetStreamFromPart(
+ static_cast<IPartBase_t>(pFontIn)
+ );
+ pPartUri = CreateOpcPartUriFromPart(
+ static_cast<IPartBase_t>(pFontIn),
+ pOpcFactory
+ );
+
+ //
+ // Get the font restriction
+ //
+ EXpsFontRestriction eFontRestriction = Xps_Restricted_Font_Installable;
+
+ {
+ IPartFont2_t pFont2In;
+
+ if (SUCCEEDED(pFontIn->QueryInterface(__uuidof(IPartFont2), reinterpret_cast<void **>(&pFont2In))))
+ {
+ pFont2In->GetFontRestriction(&eFontRestriction);
+ }
+ }
+
+ //
+ // Get the font obfuscation
+ //
+ EXpsFontOptions eFontOptions;
+
+ {
+ BSTR_t contentType;
+
+ THROW_ON_FAILED_HRESULT(
+ pFontIn->GetFontProperties(&contentType, &eFontOptions)
+ );
+ }
+
+ //
+ // It is necessary to combine the obfuscation and restriction
+ // attributes from the print pipeline into the one parameter that
+ // the Xps Object Model consumes.
+ //
+
+ XPS_FONT_EMBEDDING omEmbedding;
+
+ if (eFontOptions == Font_Normal)
+ {
+ omEmbedding = XPS_FONT_EMBEDDING_NORMAL;
+ }
+ else if (eFontOptions == Font_Obfusticate &&
+ (eFontRestriction &
+ (Xps_Restricted_Font_PreviewPrint |
+ Xps_Restricted_Font_NoEmbedding)))
+ {
+ //
+ // If the font is obfuscated, and either the PreviewPrint or
+ // NoEmbedding restriction flags are set, then create a
+ // Restricted font
+ //
+ omEmbedding = XPS_FONT_EMBEDDING_RESTRICTED;
+ }
+ else
+ {
+ omEmbedding = XPS_FONT_EMBEDDING_OBFUSCATED;
+ }
+
+ //
+ // Call Xps Object Model to create the font resource
+ //
+ IXpsOMFontResource_t pFontOut;
+
+ THROW_ON_FAILED_HRESULT(
+ pOMFactory->CreateFontResource(
+ pPartStream,
+ omEmbedding,
+ pPartUri,
+ FALSE, // fonts received from the pipeline are already de-obfuscated
+ &pFontOut
+ )
+ );
+
+ return pFontOut;
+}
+
+//
+//Routine Name:
+//
+// CollectPageResources
+//
+//Routine Description:
+//
+// Iterates over all of the resources related to
+// a fixed page and adds them to a resource
+// collection.
+//
+//Arguments:
+//
+// pPage - The page to query for resources
+// pOMFactory - Xps Object Model Object Factory
+// pOpcFactory - Opc Object Factory
+//
+//Return Value:
+//
+// IXpsOMPartResources_t (smart pointer)
+// The resource collection of all of the resources of the page
+//
+IXpsOMPartResources_t
+CollectPageResources(
+ const IFixedPage_t &pPage,
+ const IXpsOMObjectFactory_t &pOMFactory,
+ const IOpcFactory_t &pOpcFactory
+ )
+{
+ IXpsOMPartResources_t pResources;
+
+ IXpsOMFontResourceCollection_t pFonts;
+ IXpsOMImageResourceCollection_t pImages;
+ IXpsOMColorProfileResourceCollection_t pProfiles;
+ IXpsOMRemoteDictionaryResourceCollection_t pDictionaries;
+
+ //
+ // collection of resource dictionaries saved for later processing.
+ //
+ ResourceDictionaryList_t dictionaryList;
+
+ //
+ // Create the resource collection and get all of the
+ // resource-specific sub-collections.
+ //
+ THROW_ON_FAILED_HRESULT(
+ pOMFactory->CreatePartResources(&pResources)
+ );
+ THROW_ON_FAILED_HRESULT(
+ pResources->GetFontResources(&pFonts)
+ );
+ THROW_ON_FAILED_HRESULT(
+ pResources->GetImageResources(&pImages)
+ );
+ THROW_ON_FAILED_HRESULT(
+ pResources->GetColorProfileResources(&pProfiles)
+ );
+ THROW_ON_FAILED_HRESULT(
+ pResources->GetRemoteDictionaryResources(&pDictionaries)
+ );
+ //
+ // Get the XpsPartIterator and iterate through all of the parts
+ // related to this fixed page.
+ //
+ IXpsPartIterator_t itPart;
+
+ THROW_ON_FAILED_HRESULT(
+ pPage->GetXpsPartIterator(&itPart)
+ );
+
+ for (; !itPart->IsDone(); itPart->Next())
+ {
+ BSTR_t uri;
+ IUnknown_t pUnkPart;
+
+ THROW_ON_FAILED_HRESULT(
+ itPart->Current(&uri, &pUnkPart)
+ );
+
+ IPartFont_t pFontPart;
+ IPartImage_t pImagePart;
+ IPartColorProfile_t pProfilePart;
+ IPartResourceDictionary_t pDictionaryPart;
+
+ if (SUCCEEDED(pUnkPart.QueryInterface(&pFontPart)))
+ {
+ //
+ // Convert the font part to Xps Object Model and add it to the
+ // font resource collection
+ //
+ THROW_ON_FAILED_HRESULT(
+ pFonts->Append(
+ CreateFontFromIPartFont(
+ pFontPart,
+ pOMFactory,
+ pOpcFactory
+ )
+ )
+ );
+ }
+ else if (SUCCEEDED(pUnkPart.QueryInterface(&pImagePart)))
+ {
+ //
+ // Convert the image part to Xps Object Model and add it to the
+ // image resource collection
+ //
+ THROW_ON_FAILED_HRESULT(
+ pImages->Append(
+ CreateImageFromIPartImage(
+ pImagePart,
+ pOMFactory,
+ pOpcFactory
+ )
+ )
+ );
+ }
+ else if (SUCCEEDED(pUnkPart.QueryInterface(&pProfilePart)))
+ {
+ //
+ // Convert the color profile part to Xps Object Model and add it
+ // to the color profile resource collection
+ //
+ THROW_ON_FAILED_HRESULT(
+ pProfiles->Append(
+ CreateProfileFromIPartColorProfile(
+ pProfilePart,
+ pOMFactory,
+ pOpcFactory
+ )
+ )
+ );
+ }
+ else if (SUCCEEDED(pUnkPart.QueryInterface(&pDictionaryPart)))
+ {
+ //
+ // In order to process the remote resource dictionary, all of
+ // its linked resources must be present in pResources. To ensure
+ // this, we delay the conversion of the remote resource
+ // dictionaries until all of the other resources have been converted.
+ //
+ dictionaryList.push_back(pDictionaryPart);
+ }
+ else
+ {
+ //
+ // Any other page resources are ignored
+ //
+ }
+ }
+
+ for (ResourceDictionaryList_t::const_iterator it = dictionaryList.begin();
+ it != dictionaryList.end();
+ ++it)
+ {
+ //
+ // Convert the remote dictionary to Xps Object Model and add it
+ // to the remote dictionary collection
+ //
+ THROW_ON_FAILED_HRESULT(
+ pDictionaries->Append(
+ CreateDictionaryFromIPartResourceDictionary(
+ *it,
+ pOMFactory,
+ pOpcFactory,
+ pResources
+ )
+ )
+ );
+ }
+
+ return pResources;
+}
+
+//
+//Routine Name:
+//
+// GetStreamFromPart
+//
+//Routine Description:
+//
+// Gets the IStream from this part.
+//
+//Arguments:
+//
+// pPart - An Xps Part
+//
+//Return Value:
+//
+// IStream_t (smart pointer)
+// The stream of the part's content
+//
+IStream_t
+GetStreamFromPart(
+ const IPartBase_t &pPart
+ )
+{
+ //
+ // Get the IPrintReadStream for the part from the pipeline Object Model
+ //
+ IPrintReadStream_t pStream;
+ THROW_ON_FAILED_HRESULT(
+ pPart->GetStream(&pStream)
+ );
+
+ return CreateIStreamFromIPrintReadStream(pStream);
+}
+
+//
+//Routine Name:
+//
+// CreateIStreamFromIPrintReadStream
+//
+//Routine Description:
+//
+// Creates an IStream from an IPrintReadStream.
+//
+//Arguments:
+//
+// pReadStream - A Print Pipeline IPrintReadStream
+//
+//Return Value:
+//
+// IStream_t (smart pointer)
+// A stream with the same content as the argument stream.
+//
+IStream_t
+CreateIStreamFromIPrintReadStream(
+ const IPrintReadStream_t &pReadStream
+ )
+{
+ //
+ // Get the size of the stream
+ //
+ ULONGLONG tmpPos;
+ size_t partSize;
+
+ THROW_ON_FAILED_HRESULT(
+ pReadStream->Seek(0, SEEK_END, &tmpPos)
+ );
+
+ //
+ // GlobalAlloc can only allocate size_t bytes, so
+ // throw if the part is larger than that
+ //
+ THROW_ON_FAILED_HRESULT(
+ ULongLongToSizeT(tmpPos, &partSize)
+ );
+
+ THROW_ON_FAILED_HRESULT(
+ pReadStream->Seek(0, SEEK_SET, &tmpPos)
+ );
+
+ //
+ // Allocate an HGLOBAL for the part cache
+ //
+ SafeHGlobal_t pHBuf(
+ new SafeHGlobal(GMEM_FIXED, partSize)
+ );
+
+ //
+ // Read the part into the cache
+ //
+ {
+ //
+ // Lock the HGLOBAL and get the address of the buffer
+ // from the RAII lock object
+ //
+ HGlobalLock_t lock = pHBuf->Lock();
+ BYTE *pBuffer = lock->GetAddress();
+
+ //
+ // Allow the number of bytes to read to be clipped to max ULONG
+ // and then spin on fEOF until the stream is exhausted
+ //
+ ULONG numToRead;
+
+ if (FAILED(SizeTToULong(partSize, &numToRead)))
+ {
+ numToRead = MAXUINT;
+ }
+
+ BOOL fEOF;
+ ULONG numRead;
+ size_t pos = 0;
+
+ //
+ // Iterate until all bytes from the stream
+ // have been read into the buffer
+ //
+ do
+ {
+ THROW_ON_FAILED_HRESULT(
+ pReadStream->ReadBytes(pBuffer + pos, numToRead, &numRead, &fEOF)
+ );
+
+ pos += numRead;
+ } while (!fEOF && numRead);
+ }
+
+ //
+ // Create an IStream from the part cache
+ //
+ IStream_t pIStream = pHBuf->ConvertToIStream();
+
+ LARGE_INTEGER zero = {0};
+ THROW_ON_FAILED_HRESULT(
+ pIStream->Seek(zero, SEEK_SET, NULL)
+ );
+
+ return pIStream;
+}
+
+//
+//Routine Name:
+//
+// CreateOpcPartUriFromPart
+//
+//Routine Description:
+//
+// Gets the Opc Uri from the Xps Part.
+//
+//Arguments:
+//
+// pPart - An Xps Part
+// pFactory - Opc Factory
+//
+//Return Value:
+//
+// IOpcPartUri_t (smart pointer)
+// The Uri of the part
+//
+IOpcPartUri_t
+CreateOpcPartUriFromPart(
+ const IPartBase_t &pPart,
+ const IOpcFactory_t &pFactory
+ )
+{
+ BSTR_t strPartUri;
+
+ THROW_ON_FAILED_HRESULT(
+ pPart->GetUri(&strPartUri)
+ );
+
+ IOpcPartUri_t pPartUri;
+ THROW_ON_FAILED_HRESULT(
+ pFactory->CreatePartUri(strPartUri, &pPartUri)
+ );
+ return pPartUri;
+}
+
+} // namespace xpsrasfilter
+
diff --git a/print/XpsRasFilter/src/OMConvertor.h b/print/XpsRasFilter/src/OMConvertor.h
new file mode 100644
index 00000000..7257da3b
--- /dev/null
+++ b/print/XpsRasFilter/src/OMConvertor.h
@@ -0,0 +1,90 @@
+// THIS CODE AND INFORMATION IS 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.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved
+//
+// File Name:
+//
+// omconvertor.h
+//
+// Abstract:
+//
+// Object model conversion routines.
+//
+
+#pragma once
+
+namespace xpsrasfilter
+{
+
+//
+// Top-level Create Page routine
+//
+IXpsOMPage_t
+CreateXpsOMPageFromIFixedPage(
+ const IFixedPage_t &pPageIn,
+ const IXpsOMObjectFactory_t &pFactory,
+ const IOpcFactory_t &pOpcFactory
+ );
+
+//
+// Individual Part conversion routines
+//
+IXpsOMImageResource_t
+CreateImageFromIPartImage(
+ const IPartImage_t &pImageIn,
+ const IXpsOMObjectFactory_t &pFactory,
+ const IOpcFactory_t &pOpcFactory
+ );
+
+IXpsOMColorProfileResource_t
+CreateProfileFromIPartColorProfile(
+ const IPartColorProfile_t &pProfileIn,
+ const IXpsOMObjectFactory_t &pFactory,
+ const IOpcFactory_t &pOpcFactory
+ );
+
+IXpsOMRemoteDictionaryResource_t
+CreateDictionaryFromIPartResourceDictionary(
+ const IPartResourceDictionary_t &pDictionaryIn,
+ const IXpsOMObjectFactory_t &pFactory,
+ const IOpcFactory_t &pOpcFactory,
+ const IXpsOMPartResources_t &pResources
+ );
+
+IXpsOMFontResource_t
+CreateFontFromIPartFont(
+ const IPartFont_t &pFontIn,
+ const IXpsOMObjectFactory_t &pFactory,
+ const IOpcFactory_t &pOpcFactory
+ );
+
+//
+// Utility Routines
+//
+IStream_t
+GetStreamFromPart(
+ const IPartBase_t &pPart
+ );
+
+IOpcPartUri_t
+CreateOpcPartUriFromPart(
+ const IPartBase_t &pPart,
+ const IOpcFactory_t &pOpcFactory
+ );
+
+IXpsOMPartResources_t
+CollectPageResources(
+ const IFixedPage_t &pPage,
+ const IXpsOMObjectFactory_t &pFactory,
+ const IOpcFactory_t &pOpcFactory
+ );
+
+IStream_t
+CreateIStreamFromIPrintReadStream(
+ const IPrintReadStream_t &pReadStream
+ );
+
+} // namespace xpsrasfilter
diff --git a/print/XpsRasFilter/src/PThandler.cpp b/print/XpsRasFilter/src/PThandler.cpp
new file mode 100644
index 00000000..6b158032
--- /dev/null
+++ b/print/XpsRasFilter/src/PThandler.cpp
@@ -0,0 +1,781 @@
+// THIS CODE AND INFORMATION IS 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.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved
+//
+// File Name:
+//
+// PThandler.cpp
+//
+// Abstract:
+//
+// Print Ticket Handler class definition.
+//
+
+#include "precomp.h"
+#include "WppTrace.h"
+#include "Exception.h"
+#include "filtertypes.h"
+#include "UnknownBase.h"
+#include "OMConvertor.h"
+#include "rasinterface.h"
+#include "xpsrasfilter.h"
+#include "PTHandler.h"
+
+#include "PThandler.tmh"
+
+namespace xpsrasfilter
+{
+
+//
+// This is an arbitrary page margin that is used to simulate
+// an imageable area for scaling calculations.
+//
+const FLOAT g_pageMargin = 0.25f;
+
+//
+//Routine Name:
+//
+// PrintTicketHandler::CreatePrintTicketHandler
+//
+//Routine Description:
+//
+// Static factory method that creates an instance of
+// PrintTicketHandler.
+//
+//Arguments:
+//
+// pPropertyBag - Property Bag
+//
+//Return Value:
+//
+// PrintTicketHandler_t (smart ptr)
+// The new PrintTicketHandler.
+//
+PrintTicketHandler_t
+PrintTicketHandler::CreatePrintTicketHandler(
+ const IPrintPipelinePropertyBag_t &pPropertyBag
+ )
+{
+ //
+ // Create MSXML DOM document
+ //
+ IXMLDOMDocument2_t pDOMDoc;
+
+ THROW_ON_FAILED_HRESULT(
+ ::CoCreateInstance(
+ __uuidof(DOMDocument60),
+ NULL,
+ CLSCTX_INPROC_SERVER,
+ __uuidof(IXMLDOMDocument2),
+ reinterpret_cast<LPVOID*>(&pDOMDoc)
+ )
+ );
+
+ //
+ // Get the default user Print Ticket Stream Factory
+ //
+ Variant_t varUserPrintTicket;
+ THROW_ON_FAILED_HRESULT(
+ pPropertyBag->GetProperty(
+ XPS_FP_USER_PRINT_TICKET,
+ &varUserPrintTicket
+ )
+ );
+ IUnknown_t pUnk = varUserPrintTicket.punkVal;
+
+ IPrintReadStreamFactory_t pStreamFactory;
+
+ THROW_ON_FAILED_HRESULT(
+ pUnk.QueryInterface(&pStreamFactory)
+ );
+
+ //
+ // Get the default user Print Ticket stream
+ // and wrap it in an IStream
+ //
+
+ IPrintReadStream_t pUserPrintTicketStream;
+
+ THROW_ON_FAILED_HRESULT(
+ pStreamFactory->GetStream(&pUserPrintTicketStream)
+ );
+
+ IStream_t pUserPrintTicket =
+ CreateIStreamFromIPrintReadStream(pUserPrintTicketStream);
+
+ //
+ // Get the Printer Name
+ //
+ Variant_t varPrinterName;
+ THROW_ON_FAILED_HRESULT(
+ pPropertyBag->GetProperty(
+ XPS_FP_PRINTER_NAME,
+ &varPrinterName
+ )
+ );
+
+ BSTR_t pPrinterName(varPrinterName.bstrVal);
+
+ //
+ // Get the User Security Token
+ // Avoid CComVariant if getting the XPS_FP_USER_TOKEN property.
+ // Please refer to http://go.microsoft.com/fwlink/?LinkID=255534 for detailed information.
+ //
+ SafeVariant varUserSecurityToken;
+ THROW_ON_FAILED_HRESULT(
+ pPropertyBag->GetProperty(
+ XPS_FP_USER_TOKEN,
+ &varUserSecurityToken
+ )
+ );
+
+ //
+ // Open the Print Ticket Provider
+ //
+ SafeHPTProvider_t pHProvider(
+ new SafeHPTProvider(
+ pPrinterName,
+ varUserSecurityToken.byref
+ )
+ );
+
+ PrintTicketHandler_t toReturn(
+ new PrintTicketHandler(
+ pDOMDoc,
+ pHProvider,
+ pUserPrintTicket
+ )
+ );
+
+ return toReturn;
+}
+
+//
+//Routine Name:
+//
+// PrintTicketHandler::PrintTicketHandler
+//
+//Routine Description:
+//
+// Constructor for the Print Ticket Handler.
+//
+//Arguments:
+//
+// pDoc - initialized MSXML DOM document
+// pHProvider - handle to the Print Ticket Provider
+//
+PrintTicketHandler::PrintTicketHandler(
+ const IXMLDOMDocument2_t &pDoc,
+ SafeHPTProvider_t pHProvider,
+ const IStream_t &pUserPrintTicket
+ ) : m_pDOMDoc(pDoc),
+ m_pHProvider(pHProvider),
+ m_pDefaultUserPrintTicket(pUserPrintTicket)
+{
+}
+
+//
+//Routine Name:
+//
+// PrintTicketHandler::ProcessPrintTicket
+//
+//Routine Description:
+//
+// Gets the print ticket from the part, merges with
+// the base ticket, and returns the result.
+//
+//Arguments:
+//
+// pBasePrintTicket - Base Print Ticket
+// pDeltaPrintTicketPart - Delta Print Pipeline Print Ticket Part
+// scope - Scope of the merged Print Ticket
+//
+//Return Value:
+//
+// IStream_t (smart pointer)
+// Merged stream
+//
+IStream_t
+PrintTicketHandler::ProcessPrintTicket(
+ const IStream_t &pBasePrintTicket,
+ const IPartPrintTicket_t &pDeltaPrintTicketPart,
+ EPrintTicketScope scope
+ )
+{
+ IStream_t pMergedPrintTicket;
+ IStream_t pDeltaPrintTicket;
+
+ pDeltaPrintTicket = GetStreamFromPart(
+ static_cast<IPartBase_t>(pDeltaPrintTicketPart)
+ );
+
+ //
+ // Before calling PTMergeAndValidatePrintTicket, both input
+ // Print Ticket streams MUST be at position 0. The temp Print
+ // Ticket stream is already at position 0, but the Base Print
+ // Ticket may not be. Seek it to 0 to be sure.
+ //
+ LARGE_INTEGER zero;
+ zero.QuadPart = 0;
+ THROW_ON_FAILED_HRESULT(
+ pBasePrintTicket->Seek(zero, SEEK_SET, NULL)
+ );
+
+ //
+ // Merge the delta Print Ticket with the
+ // base Print Ticket
+ //
+ THROW_ON_FAILED_HRESULT(
+ ::CreateStreamOnHGlobal(
+ NULL,
+ TRUE, // delete on release
+ &pMergedPrintTicket
+ )
+ );
+
+ m_pHProvider->PTMergeAndValidatePrintTicket(
+ pBasePrintTicket,
+ pDeltaPrintTicket,
+ scope,
+ pMergedPrintTicket
+ );
+
+ return pMergedPrintTicket;
+}
+
+//
+//Routine Name:
+//
+// PrintTicketHandler::ProcessPart
+//
+//Routine Description:
+//
+// Merges the Fixed Document Sequence Print Ticket with
+// the default user Print Ticket and caches the result.
+//
+//Arguments:
+//
+// pFDS - Fixed Document Sequence part
+//
+void
+PrintTicketHandler::ProcessPart(
+ const IFixedDocumentSequence_t &pFDS
+ )
+{
+ IPartPrintTicket_t pPrintTicket;
+
+ HRESULT hr = pFDS->GetPrintTicket(&pPrintTicket);
+
+ //
+ // E_ELEMENT_NOT_FOUND means that this Fixed Document Sequence
+ // does not have a Print Ticket. Propagate the Default User
+ // Print Ticket.
+ // All other failed HRESULTs should be thrown.
+ //
+ if (hr == E_ELEMENT_NOT_FOUND)
+ {
+ m_pJobPrintTicket = m_pDefaultUserPrintTicket;
+ return;
+ }
+
+ THROW_ON_FAILED_HRESULT(hr);
+
+ m_pDocumentPrintTicket = NULL;
+ m_pPagePrintTicket = NULL;
+
+ m_pJobPrintTicket = ProcessPrintTicket(
+ m_pDefaultUserPrintTicket,
+ pPrintTicket,
+ kPTJobScope
+ );
+}
+
+//
+//Routine Name:
+//
+// PrintTicketHandler::ProcessPart
+//
+//Routine Description:
+//
+// Merges the Fixed Document Print Ticket with the
+// Fixed Document Sequence Print Ticket and caches
+// the result. The tickets are merged at the Document
+// scope, so the result contains no job-level features.
+//
+//Arguments:
+//
+// pFD - Fixed Document part
+//
+void
+PrintTicketHandler::ProcessPart(
+ const IFixedDocument_t &pFD
+ )
+{
+ IPartPrintTicket_t pPrintTicket;
+
+ HRESULT hr = pFD->GetPrintTicket(&pPrintTicket);
+
+ //
+ // E_ELEMENT_NOT_FOUND means that this Fixed Document
+ // does not have a Print Ticket. Propagate the Job
+ // Print Ticket.
+ // All other failed HRESULTs should be thrown.
+ //
+ if (hr == E_ELEMENT_NOT_FOUND)
+ {
+ m_pDocumentPrintTicket = m_pJobPrintTicket;
+ return;
+ }
+
+ THROW_ON_FAILED_HRESULT(hr);
+
+ m_pPagePrintTicket = NULL;
+
+ m_pDocumentPrintTicket = ProcessPrintTicket(
+ m_pJobPrintTicket,
+ pPrintTicket,
+ kPTDocumentScope
+ );
+}
+
+//
+//Routine Name:
+//
+// PrintTicketHandler::ProcessPart
+//
+//Routine Description:
+//
+// Merges the Fixed Page Print Ticket with the
+// Fixed Document Print Ticket and caches the result.
+// The tickets are merged at the Page scope, so the
+// result contains no job-level or document-level features.
+//
+//Arguments:
+//
+// pFP - Fixed Page part
+//
+void
+PrintTicketHandler::ProcessPart(
+ const IFixedPage_t &pFP
+ )
+{
+ IPartPrintTicket_t pPrintTicket;
+
+ HRESULT hr = pFP->GetPrintTicket(&pPrintTicket);
+
+ //
+ // E_ELEMENT_NOT_FOUND means that this Fixed Page
+ // does not have a Print Ticket. Propagate the Document
+ // Print Ticket.
+ // All other failed HRESULTs should be thrown.
+ //
+ if (hr == E_ELEMENT_NOT_FOUND)
+ {
+ m_pPagePrintTicket = m_pDocumentPrintTicket;
+ return;
+ }
+
+ THROW_ON_FAILED_HRESULT(hr);
+
+ m_pPagePrintTicket = ProcessPrintTicket(
+ m_pDocumentPrintTicket,
+ pPrintTicket,
+ kPTPageScope
+ );
+}
+
+//
+//Routine Name:
+//
+// PrintTicketHandler::GetMergedPrintTicketParams
+//
+//Routine Description:
+//
+// Queries a set of parameters from the merged print ticket.
+//
+// NOTE: Relies on successful calls to all three PrintTicket
+// processing methods.
+//
+//Return Value:
+//
+// ParametersFromPrintTicket
+// The set of parameters queried from the merged
+// Print Ticket.
+//
+ParametersFromPrintTicket
+PrintTicketHandler::GetMergedPrintTicketParams()
+{
+ DoTraceMessage(XPSRASFILTER_TRACE_VERBOSE, L"Getting Print Ticket parameters");
+
+ if (!m_pPagePrintTicket)
+ {
+ DoTraceMessage(XPSRASFILTER_TRACE_ERROR, L"GetMergedPrintTicketParams called before ProcessPagePrintTicket");
+ THROW_ON_FAILED_HRESULT(E_FAIL);
+ }
+
+ ParametersFromPrintTicket params;
+
+ //
+ // Seek the Page-level Print Ticket to 0
+ //
+ LARGE_INTEGER zero;
+ zero.QuadPart = 0;
+ THROW_ON_FAILED_HRESULT(
+ m_pPagePrintTicket->Seek(zero, SEEK_SET, NULL)
+ );
+
+ //
+ // Load the print ticket stream into a DOM document
+ //
+ // NOTE: We are only looking for features at the Page scope for this sample,
+ // so we only extract features from the effective page-level PrintTicket.
+ //
+ Variant_t varStream(m_pPagePrintTicket);
+ VARIANT_BOOL success;
+
+ THROW_ON_FAILED_HRESULT(
+ m_pDOMDoc->load(varStream, &success)
+ );
+ if (!success)
+ {
+ WPP_LOG_ON_FAILED_HRESULT(E_FAIL);
+ THROW_ON_FAILED_HRESULT(E_FAIL);
+ }
+
+ //
+ // Set the DOM Selection namespace to simplify queries
+ //
+ BSTR_t ns(L"xmlns:psf='http://schemas.microsoft.com/windows/2003/08/printing/printschemaframework'");
+ Variant_t nsProp(ns);
+ THROW_ON_FAILED_HRESULT(
+ m_pDOMDoc->setProperty(L"SelectionNamespaces", nsProp)
+ );
+
+ //
+ // Query the print ticket for parameters of interest
+ //
+ params.destDPI = QueryDPI();
+ params.scaling = QueryScaling();
+ params.physicalPageSize = QueryPhysicalPageSize();
+
+ //
+ // We simulate imageable area by assuming a constant margin of
+ // around the entire page
+ //
+ params.imageableArea.x = g_pageMargin * xpsDPI;
+ params.imageableArea.y = g_pageMargin * xpsDPI;
+ params.imageableArea.height = params.physicalPageSize.height
+ - 2 * g_pageMargin * xpsDPI;
+ params.imageableArea.width = params.physicalPageSize.width
+ - 2 * g_pageMargin * xpsDPI;
+
+ return params;
+}
+
+//
+//Routine Name:
+//
+// PrintTicketHandler::QueryDPI
+//
+//Routine Description:
+//
+// Queries the DPI from the Print Ticket using an XPath query.
+//
+//Return Value:
+//
+// FLOAT
+// DPI from the Print Ticket.
+//
+FLOAT
+PrintTicketHandler::QueryDPI()
+{
+ //
+ // Default DPI: 96 DPI
+ //
+ FLOAT dpi = 96.0;
+
+ //
+ // Perform the page resolution query on the print ticket
+ //
+ IXMLDOMNodeList_t pNodes;
+
+ //
+ // The following XPath query is fairly straightforward, except for the
+ // predicate attached to Feature. This is necessary to match both the
+ // keyword AND the namespace of the "name" of the Feature as in:
+ //
+ // <psf:Feature name="psk:PageResolution">
+ //
+ // In order to match the keyword, we match the substring after the colon:
+ //
+ // [substring-after(@name,':')='PageResolution']
+ //
+ // We also need to ensure that the namespace refers to the correct
+ // printschemakeywords namespace. Thus we get:
+ //
+ // [name(namespace::*[.=PRINTSCHEMAKEYWORDNS])=substring-before(@name,':')]
+ //
+ // where PRINTSCHEMAKEYWORDNS is:
+ //
+ // http://schemas.microsoft.com/windows/2003/08/printing/printschemakeywords
+ //
+ BSTR_t query(L"psf:PrintTicket/psf:Feature[substring-after(@name,':')='PageResolution']"
+ L"[name(namespace::*[.='http://schemas.microsoft.com/windows/2003/08/printing/printschemakeywords'])=substring-before(@name,':')]"
+ L"/*/*/psf:Value");
+
+ THROW_ON_FAILED_HRESULT(
+ m_pDOMDoc->selectNodes(query, &pNodes)
+ );
+
+ if (pNodes)
+ {
+ //
+ // The Print Ticket may have both X and Y resolutions defined, but
+ // the Xps Rasterization Service only accepts a single resolution.
+ // We query for both X and Y resolutions and take the larger of the
+ // two as the destination DPI. The resultant raster data could then
+ // be scaled down in the other dimension to achieve the non-square
+ // pixels.
+ //
+
+ LONG numResolutions;
+
+ THROW_ON_FAILED_HRESULT(
+ pNodes->get_length(&numResolutions)
+ );
+
+ if (numResolutions != 0 &&
+ numResolutions != 1 &&
+ numResolutions != 2)
+ {
+ //
+ // We expect 0, 1, or 2 resolutions to be set in the Print Ticket.
+ // Throw if this is not the case.
+ //
+ THROW_ON_FAILED_HRESULT(E_UNEXPECTED);
+ }
+
+ LONG maxResolution = 0;
+
+ for (INT i = 0; i < numResolutions; i++)
+ {
+ IXMLDOMNode_t pCurrentNode;
+
+ THROW_ON_FAILED_HRESULT(
+ pNodes->get_item(i, &pCurrentNode)
+ );
+
+ BSTR_t strResolution;
+
+ THROW_ON_FAILED_HRESULT(
+ pCurrentNode->get_text(&strResolution)
+ );
+
+ LONG resolution;
+
+ THROW_ON_FAILED_HRESULT(
+ ::VarI4FromStr(
+ strResolution,
+ LOCALE_USER_DEFAULT,
+ 0, // no custom flags
+ &resolution
+ )
+ );
+
+ if (resolution > maxResolution)
+ {
+ maxResolution = resolution;
+ }
+ }
+
+ dpi = static_cast<FLOAT>(maxResolution);
+ }
+
+ DoTraceMessage(XPSRASFILTER_TRACE_VERBOSE, L"Got DPI: %f", dpi);
+
+ return dpi;
+}
+
+//
+//Routine Name:
+//
+// PrintTicketHandler::QueryPhysicalPageSize
+//
+//Routine Description:
+//
+// Queries the physical page size from the
+// Print Ticket using an XPath query.
+//
+//Return Value:
+//
+// XPS_SIZE
+// Physical page size from the Print Ticket (in XPS units).
+//
+XPS_SIZE
+PrintTicketHandler::QueryPhysicalPageSize()
+{
+ //
+ // Default page size: 8.5" x 11" at Xps DPI
+ //
+ XPS_SIZE pageSize = {11.0f * xpsDPI,
+ 8.5f * xpsDPI};
+
+ {
+ //
+ // Perform the page width query on the print ticket
+ //
+ IXMLDOMNode_t pNode;
+
+ //
+ // See the comment in PrintTicketHandler::QueryDPI() for details
+ // about this XPath query.
+ //
+ BSTR_t query(L"psf:PrintTicket/psf:Feature[substring-after(@name,':')='PageMediaSize']"
+ L"[name(namespace::*[.='http://schemas.microsoft.com/windows/2003/08/printing/printschemakeywords'])=substring-before(@name,':')]"
+ L"/*/psf:ScoredProperty[substring-after(@name,':')='MediaSizeWidth']"
+ L"[name(namespace::*[.='http://schemas.microsoft.com/windows/2003/08/printing/printschemakeywords'])=substring-before(@name,':')]"
+ L"/psf:Value");
+
+ THROW_ON_FAILED_HRESULT(
+ m_pDOMDoc->selectSingleNode(query, &pNode)
+ );
+
+ if (pNode)
+ {
+ BSTR_t strWidth;
+ THROW_ON_FAILED_HRESULT(
+ pNode->get_text(&strWidth)
+ );
+
+ LONG width;
+ THROW_ON_FAILED_HRESULT(
+ ::VarI4FromStr(
+ strWidth,
+ LOCALE_USER_DEFAULT,
+ 0, // no custom flags
+ &width
+ )
+ );
+
+ //
+ // the page dimensions are in microns; convert to Xps units
+ //
+ pageSize.width = MicronsToXpsUnits(width);
+ }
+ }
+
+ {
+ //
+ // Perform the page height query on the print ticket
+ //
+ IXMLDOMNode_t pNode;
+
+ //
+ // See the comment in PrintTicketHandler::QueryDPI() for details
+ // about this XPath query.
+ //
+ BSTR_t query(L"psf:PrintTicket/psf:Feature[substring-after(@name,':')='PageMediaSize']"
+ L"[name(namespace::*[.='http://schemas.microsoft.com/windows/2003/08/printing/printschemakeywords'])=substring-before(@name,':')]"
+ L"/*/psf:ScoredProperty[substring-after(@name,':')='MediaSizeHeight']"
+ L"[name(namespace::*[.='http://schemas.microsoft.com/windows/2003/08/printing/printschemakeywords'])=substring-before(@name,':')]"
+ L"/psf:Value");
+
+ THROW_ON_FAILED_HRESULT(
+ m_pDOMDoc->selectSingleNode(query, &pNode)
+ );
+
+ if (pNode)
+ {
+ BSTR_t strHeight;
+ THROW_ON_FAILED_HRESULT(
+ pNode->get_text(&strHeight)
+ );
+
+ LONG height;
+ THROW_ON_FAILED_HRESULT(
+ ::VarI4FromStr(
+ strHeight,
+ LOCALE_USER_DEFAULT,
+ 0, // no custom flags
+ &height
+ )
+ );
+
+ //
+ // the page dimensions are in microns; convert to Xps unit
+ //
+ pageSize.height = MicronsToXpsUnits(height);
+ }
+ }
+
+ {
+ //
+ // Perform the landscape query on the print ticket
+ //
+ IXMLDOMNode_t pNode;
+
+ //
+ // See the comment in PrintTicketHandler::QueryDPI() for details
+ // about this XPath query.
+ //
+ BSTR_t query(L"psf:PrintTicket/psf:Feature[substring-after(@name,':')='PageOrientation']"
+ L"[name(namespace::*[.='http://schemas.microsoft.com/windows/2003/08/printing/printschemakeywords'])=substring-before(@name,':')]"
+ L"/psf:Option[substring-after(@name,':')='Landscape']"
+ L"[name(namespace::*[.='http://schemas.microsoft.com/windows/2003/08/printing/printschemakeywords'])=substring-before(@name,':')]");
+
+ THROW_ON_FAILED_HRESULT(
+ m_pDOMDoc->selectSingleNode(query, &pNode)
+ );
+
+ if (pNode)
+ {
+ //
+ // landscape. swap height and width.
+ //
+ FLOAT tmp;
+
+ tmp = pageSize.height;
+ pageSize.height = pageSize.width;
+ pageSize.width = tmp;
+ }
+
+ DoTraceMessage(XPSRASFILTER_TRACE_VERBOSE, L"Physical Page Size: %f x %f", pageSize.width, pageSize.height);
+ }
+
+ return pageSize;
+}
+
+//
+//Routine Name:
+//
+// PrintTicketHandler::QueryScaling
+//
+//Routine Description:
+//
+// Queries the desired type of scaling from the
+// Print Ticket using an XPath query.
+//
+//Return Value:
+//
+// PrintTicketScaling
+// Scaling type from the Print Ticket.
+//
+PrintTicketScaling
+PrintTicketHandler::QueryScaling()
+{
+ //
+ // Default Scaling: FitApplicationBleedSizeToPageImageableSize
+ //
+ PrintTicketScaling scaling = SCALE_BLEEDTOIMAGEABLE;
+
+ //
+ // We do not query for media scaling. Rather, we always return
+ // the equivalent of FitApplicationBleedSizeToPageImageableSize
+ //
+ return scaling;
+}
+
+} // namespace xpsrasfilter
diff --git a/print/XpsRasFilter/src/PThandler.h b/print/XpsRasFilter/src/PThandler.h
new file mode 100644
index 00000000..103e5d78
--- /dev/null
+++ b/print/XpsRasFilter/src/PThandler.h
@@ -0,0 +1,112 @@
+// THIS CODE AND INFORMATION IS 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.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved
+//
+// File Name:
+//
+// PThandler.h
+//
+// Abstract:
+//
+// Print Ticket Handler class declaration.
+//
+
+#pragma once
+
+namespace xpsrasfilter
+{
+
+class PrintTicketHandler
+{
+public:
+ static
+ PrintTicketHandler_t
+ CreatePrintTicketHandler(
+ const IPrintPipelinePropertyBag_t &pPropertyBag
+ );
+
+ void
+ ProcessPart(
+ const IFixedDocumentSequence_t &pFDS
+ );
+
+ void
+ ProcessPart(
+ const IFixedDocument_t &pFD
+ );
+
+ void
+ ProcessPart(
+ const IFixedPage_t &pFP
+ );
+
+ ParametersFromPrintTicket
+ GetMergedPrintTicketParams();
+
+private:
+ //
+ // Constructor is private; use CreatePrintTicketHandler
+ // to create instances.
+ //
+ PrintTicketHandler(
+ const IXMLDOMDocument2_t &pDoc,
+ SafeHPTProvider_t pHProvider,
+ const IStream_t &pUserPrintTicket
+ );
+
+ IStream_t
+ ProcessPrintTicket(
+ const IStream_t &pBasePrintTicket,
+ const IPartPrintTicket_t &pDeltaPrintTicketPart,
+ EPrintTicketScope scope
+ );
+
+ //
+ // Inline function to convert from microns to Xps Units
+ //
+ inline
+ FLOAT
+ MicronsToXpsUnits(
+ long dimensionInMicrons
+ )
+ {
+ const FLOAT micronsPerInch = 25400.0f; // 2.54 cm/in --> 25400 um/in
+
+ return ((static_cast<FLOAT>(dimensionInMicrons) / micronsPerInch) * xpsDPI);
+ }
+
+ //
+ // Routines to query parameters from the DOM document
+ //
+ FLOAT
+ QueryDPI();
+
+ XPS_SIZE
+ QueryPhysicalPageSize();
+
+ PrintTicketScaling
+ QueryScaling();
+
+ //
+ // MSXML DOM document
+ //
+ IXMLDOMDocument2_t m_pDOMDoc;
+
+ //
+ // Handle to the Print Ticket Provider
+ //
+ SafeHPTProvider_t m_pHProvider;
+
+ //
+ // Cached Print Tickets
+ //
+ IStream_t m_pDefaultUserPrintTicket;
+ IStream_t m_pJobPrintTicket;
+ IStream_t m_pDocumentPrintTicket;
+ IStream_t m_pPagePrintTicket;
+};
+
+} // namespace xpsrasfilter
diff --git a/print/XpsRasFilter/src/UnknownBase.h b/print/XpsRasFilter/src/UnknownBase.h
new file mode 100644
index 00000000..5ecd2487
--- /dev/null
+++ b/print/XpsRasFilter/src/UnknownBase.h
@@ -0,0 +1,158 @@
+// THIS CODE AND INFORMATION IS 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.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved
+//
+// File Name:
+//
+// UnknownBase.h
+//
+// Abstract:
+//
+// IUnknown implementation common to filter components derived from
+// IUnknown.
+//
+
+#pragma once
+
+namespace xpsrasfilter
+{
+
+template <class Interface>
+class UnknownBase : public Interface
+{
+public:
+ UnknownBase() : m_cRef(1) { }
+ virtual ~UnknownBase() { };
+
+ //
+ //Routine Name:
+ //
+ // UnknownBase::QueryInterface
+ //
+ //Routine Description:
+ //
+ // Implements IUnknown QueryInterface.
+ //
+ //Arguments:
+ //
+ // riid - id of the interface
+ // ppv - void pointer to the requested interface
+ //
+ //Return Value:
+ //
+ // HRESULT
+ // S_OK - On success
+ // E_NOINTERFACE - Invalid interface
+ //
+ _Must_inspect_result_
+ HRESULT STDMETHODCALLTYPE
+ QueryInterface(
+ _In_ REFIID riid,
+ _Outptr_ PVOID *ppv
+ )
+ {
+ HRESULT hr = S_OK;
+
+ if (ppv == NULL)
+ {
+ WPP_LOG_ON_FAILED_HRESULT(E_POINTER);
+
+ return E_POINTER;
+ }
+
+ if (riid == IID_IUnknown)
+ {
+ *ppv = static_cast<IUnknown *>(this);
+ }
+ else if (riid == __uuidof(Interface))
+ {
+ *ppv = static_cast<Interface *>(this);
+ }
+ else
+ {
+ *ppv = NULL;
+ WPP_LOG_ON_FAILED_HRESULT(
+ hr = E_NOINTERFACE
+ );
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ AddRef();
+ }
+
+ return hr;
+ }
+
+ //
+ //Routine Name:
+ //
+ // UnknownBase::AddRef
+ //
+ //Routine Description:
+ //
+ // Implements IUnknown reference count increment
+ // on the current interface.
+ //
+ //Arguments:
+ //
+ // None
+ //
+ //Return Value:
+ //
+ // ULONG
+ // New reference count
+ //
+ ULONG STDMETHODCALLTYPE
+ AddRef()
+ {
+ return ::InterlockedIncrement(&m_cRef);
+ }
+
+ //
+ //Routine Name:
+ //
+ // UnknownBase::Release
+ //
+ //Routine Description:
+ //
+ // Implements IUnknown reference count decrement
+ // on the current interface.
+ //
+ //Arguments:
+ //
+ // None
+ //
+ //Return Value:
+ //
+ // ULONG
+ // New reference count
+ //
+ //Note:
+ //
+ // The drv_at annotation tells Prefast to consider this object's memory
+ // freed after Release has been called.
+ //
+ _At_(this, __drv_freesMem(object))
+ ULONG STDMETHODCALLTYPE
+ Release()
+ {
+ ULONG cRef = ::InterlockedDecrement(&m_cRef);
+
+ if (0 == cRef)
+ {
+ delete this;
+ }
+
+ return cRef;
+ }
+
+private:
+ volatile ULONG m_cRef; // interface reference count
+};
+
+} // namespace xpsrasfilter
+
diff --git a/print/XpsRasFilter/src/WppTrace.cpp b/print/XpsRasFilter/src/WppTrace.cpp
new file mode 100644
index 00000000..b788c461
--- /dev/null
+++ b/print/XpsRasFilter/src/WppTrace.cpp
@@ -0,0 +1,41 @@
+// THIS CODE AND INFORMATION IS 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.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved
+//
+// File Name:
+//
+// WppTrace.h
+//
+// Abstract:
+//
+// WPP tracing definitions.
+//
+
+#include "precomp.h"
+#include "WppTrace.h"
+
+#include "WppTrace.tmh"
+
+namespace xpsrasfilter
+{
+
+void TraceFailedHRESULT(
+ HRESULT hr,
+ char const *fileName,
+ int lineNum,
+ wchar_t const *extraText
+ )
+{
+ DoTraceMessage(XPSRASFILTER_TRACE_ERROR,
+ "Failed HRESULT (%!HRESULT!) at %s:%d (%S)",
+ hr,
+ fileName,
+ lineNum,
+ extraText
+ );
+}
+
+} // namespace xpsrasfilter
diff --git a/print/XpsRasFilter/src/WppTrace.h b/print/XpsRasFilter/src/WppTrace.h
new file mode 100644
index 00000000..4f33db3b
--- /dev/null
+++ b/print/XpsRasFilter/src/WppTrace.h
@@ -0,0 +1,58 @@
+// THIS CODE AND INFORMATION IS 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.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved
+//
+// File Name:
+//
+// WppTrace.h
+//
+// Abstract:
+//
+// WPP tracing definitions.
+//
+
+#pragma once
+
+#define WPP_CONTROL_GUIDS WPP_DEFINE_CONTROL_GUID( \
+ XpsRasFilter, \
+ (EB4C6075, 0B67, 4a79, A0A3, 7CD9DF881194), \
+ WPP_DEFINE_BIT(XPSRASFILTER_TRACE_ERROR) \
+ WPP_DEFINE_BIT(XPSRASFILTER_TRACE_WARNING) \
+ WPP_DEFINE_BIT(XPSRASFILTER_TRACE_INFO) \
+ WPP_DEFINE_BIT(XPSRASFILTER_TRACE_VERBOSE) \
+ )
+
+#define WPP_LOG_ON_FAILED_HRESULT_WITH_TEXT(func_,text_) \
+ { \
+ HRESULT hr_ = func_; \
+ if (FAILED(hr_)) \
+ { \
+ xpsrasfilter::TraceFailedHRESULT( \
+ hr_, \
+ __FILE__, \
+ __LINE__, \
+ text_ \
+ ); \
+ } \
+ }
+
+#define WPP_LOG_ON_FAILED_HRESULT(func_) \
+ { \
+ WPP_LOG_ON_FAILED_HRESULT_WITH_TEXT(func_, L"") \
+ }
+
+namespace xpsrasfilter
+{
+
+void
+TraceFailedHRESULT(
+ HRESULT hr,
+ char const *fileName,
+ int lineNum,
+ wchar_t const *extraText
+ );
+
+} // namespace xpsrasfilter
diff --git a/print/XpsRasFilter/src/dllentry.cpp b/print/XpsRasFilter/src/dllentry.cpp
new file mode 100644
index 00000000..8e19ae16
--- /dev/null
+++ b/print/XpsRasFilter/src/dllentry.cpp
@@ -0,0 +1,326 @@
+// THIS CODE AND INFORMATION IS 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.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved
+//
+// File Name:
+//
+// dllentry.cpp
+//
+// Abstract:
+//
+// Xps Rasterization Service filter DLL entry points.
+//
+
+#include "precomp.h"
+#include "WppTrace.h"
+#include "Exception.h"
+#include "filtertypes.h"
+#include "UnknownBase.h"
+#include "xpsrasfilter.h"
+
+#include "dllentry.tmh"
+
+namespace xpsrasfilter
+{
+
+//
+// Class Factory returned by DllGetClassObject()
+//
+class __declspec( uuid("CFF7BE69-E62D-403b-BE4F-48EC73F5DA1A") ) XPSRasFilterFactory : public UnknownBase<IClassFactory>
+{
+public:
+ XPSRasFilterFactory() :
+ m_serverLocks(0)
+ {
+ ::InterlockedIncrement(&XPSRasFilter::ms_numObjects);
+ }
+
+ ~XPSRasFilterFactory()
+ {
+ ::InterlockedDecrement(&XPSRasFilter::ms_numObjects);
+ }
+
+ //
+ //Routine Name:
+ //
+ // XPSRasFilterFactory::CreateInstance
+ //
+ //Routine Description:
+ //
+ // Returns an instance of XPSRasFilter.
+ //
+ //Arguments:
+ //
+ // pUnkOuter - Outer class (must be NULL)
+ // riid - Requested interface (IPrintPipelineFilter)
+ // ppvObject - Pointer to the requested interface
+ //
+ //Return Value:
+ //
+ // HRESULT
+ // S_OK - On success
+ // Otherwise - Failure
+ //
+ HRESULT
+ STDMETHODCALLTYPE
+ CreateInstance(
+ IUnknown *pUnkOuter,
+ REFIID riid,
+ void **ppvObject
+ )
+ {
+ HRESULT hr = S_OK;
+
+ if (pUnkOuter != NULL)
+ {
+ WPP_LOG_ON_FAILED_HRESULT(CLASS_E_NOAGGREGATION);
+
+ return CLASS_E_NOAGGREGATION;
+ }
+
+ if (ppvObject == NULL)
+ {
+ WPP_LOG_ON_FAILED_HRESULT(E_POINTER);
+
+ return E_POINTER;
+ }
+
+ *ppvObject = NULL;
+
+ xpsrasfilter::XPSRasFilter *pFilter = NULL;
+
+ //
+ // XpsRasFilter::XpsRasFilter() can throw, as can new
+ //
+ try
+ {
+ DoTraceMessage(XPSRASFILTER_TRACE_INFO, L"Instantiating filter");
+ pFilter = new xpsrasfilter::XPSRasFilter();
+ }
+ CATCH_VARIOUS(hr)
+
+ if (SUCCEEDED(hr))
+ {
+ WPP_LOG_ON_FAILED_HRESULT(
+ hr = pFilter->QueryInterface(riid, ppvObject)
+ );
+
+ pFilter->Release();
+ }
+
+ return hr;
+ }
+
+ //
+ //Routine Name:
+ //
+ // XPSRasFilterFactory::LockServer
+ //
+ //Routine Description:
+ //
+ // Allows clients to lock the filter factory in
+ // memory.
+ //
+ //Arguments:
+ //
+ // fLock - TRUE - lock; FALSE - unlock
+ //
+ //Return Value:
+ //
+ // HRESULT
+ // S_OK - On success
+ //
+ HRESULT
+ STDMETHODCALLTYPE
+ LockServer(
+ BOOL fLock
+ )
+ {
+ LONG result;
+
+ if (fLock) // lock
+ {
+ result = ::InterlockedIncrement(&m_serverLocks);
+
+ if (result == 1)
+ {
+ //
+ // This was the first 'lock' call; increment the
+ // global numObjects
+ //
+ ::InterlockedIncrement(&XPSRasFilter::ms_numObjects);
+ }
+ }
+ else // unlock
+ {
+ result = ::InterlockedDecrement(&m_serverLocks);
+
+ if (result == 0)
+ {
+ //
+ // All locks have been unlocked; decrement the
+ // global numObjects
+ //
+ ::InterlockedDecrement(&XPSRasFilter::ms_numObjects);
+ }
+ }
+
+ return S_OK;
+ }
+
+private:
+ volatile LONG m_serverLocks;
+};
+
+} // namespace xpsrasfilter
+
+//
+//Routine Name:
+//
+// DllGetClassObject
+//
+//Routine Description:
+//
+// Returns an instance of XPSRasFilterFactory.
+//
+//Arguments:
+//
+// rclsid - Requested class (XPSRasFilter)
+// riid - Requested interface (IClassFactory)
+// ppv - Pointer to the requested interface
+//
+//Return Value:
+//
+// HRESULT
+// S_OK - On success
+// Otherwise - Failure
+//
+STDAPI
+DllGetClassObject(
+ _In_ REFCLSID rclsid,
+ _In_ REFIID riid,
+ _Outptr_ LPVOID *ppv
+ )
+{
+ HRESULT hr = S_OK;
+
+ if (ppv == NULL)
+ {
+ WPP_LOG_ON_FAILED_HRESULT(E_POINTER);
+
+ return E_POINTER;
+ }
+
+ *ppv = NULL;
+
+ if (rclsid != __uuidof(xpsrasfilter::XPSRasFilterFactory))
+ {
+ WPP_LOG_ON_FAILED_HRESULT(CLASS_E_CLASSNOTAVAILABLE);
+
+ return CLASS_E_CLASSNOTAVAILABLE;
+ }
+
+ DoTraceMessage(XPSRASFILTER_TRACE_INFO, L"Instantiating class factory");
+
+ xpsrasfilter::XPSRasFilterFactory *pFactory = NULL;
+ pFactory = new(std::nothrow) xpsrasfilter::XPSRasFilterFactory();
+
+ if (pFactory == NULL)
+ {
+ WPP_LOG_ON_FAILED_HRESULT(E_OUTOFMEMORY);
+
+ hr = E_OUTOFMEMORY;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ WPP_LOG_ON_FAILED_HRESULT(
+ hr = pFactory->QueryInterface(riid, ppv)
+ );
+
+ pFactory->Release();
+ }
+
+ return hr;
+}
+
+//
+//Routine Name:
+//
+// DllCanUnloadNow
+//
+//Routine Description:
+//
+// Checks whether the DLL can be unloaded. That is,
+// whether there are any instances of XPSRasFilter.
+//
+//Arguments:
+//
+// None
+//
+//Return Value:
+//
+// HRESULT
+// S_OK - Can unload.
+// Otherwise - Cannot unload.
+//
+STDAPI
+DllCanUnloadNow()
+{
+ return (0 == xpsrasfilter::XPSRasFilter::ms_numObjects) ? S_OK : S_FALSE;
+}
+
+//
+//Routine Name:
+//
+// DllMain
+//
+//Routine Description:
+//
+// Initializes WPP tracing when the DLL is loaded
+// and cleans up WPP tracing when the DLL is unloaded.
+//
+//Arguments:
+//
+// None
+//
+//Return Value:
+//
+// HRESULT
+// S_OK - On success.
+// Otherwise - Otherwise.
+//
+extern "C"
+BOOL
+WINAPI
+DllMain(
+ _In_ HINSTANCE hinstDLL,
+ _In_ DWORD fdwReason,
+ _In_opt_ LPVOID /*lpvReserved*/
+ )
+{
+ switch(fdwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+
+ ::DisableThreadLibraryCalls(hinstDLL);
+
+ WPP_INIT_TRACING(L"XpsRasFilter");
+ DoTraceMessage(XPSRASFILTER_TRACE_INFO, L"DLL_PROCESS_ATTACH");
+
+ break;
+
+ case DLL_PROCESS_DETACH:
+
+ DoTraceMessage(XPSRASFILTER_TRACE_INFO, L"DLL_PROCESS_DETACH");
+ WPP_CLEANUP();
+
+ break;
+ }
+
+ return TRUE;
+}
+
diff --git a/print/XpsRasFilter/src/filtertypes.h b/print/XpsRasFilter/src/filtertypes.h
new file mode 100644
index 00000000..6b5c35e6
--- /dev/null
+++ b/print/XpsRasFilter/src/filtertypes.h
@@ -0,0 +1,497 @@
+// THIS CODE AND INFORMATION IS 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.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved
+//
+// File Name:
+//
+// filtertypes.h
+//
+// Abstract:
+//
+// Smart pointer types. Shared structures and enums.
+//
+
+#pragma once
+
+//
+// XpsDrv Print Pipeline types
+//
+typedef CComPtr<IXpsDocument> IXpsDocument_t;
+typedef CComPtr<IFixedDocumentSequence> IFixedDocumentSequence_t;
+typedef CComPtr<IFixedDocument> IFixedDocument_t;
+typedef CComPtr<IFixedPage> IFixedPage_t;
+typedef CComPtr<IPrintReadStreamFactory> IPrintReadStreamFactory_t;
+typedef CComPtr<IPrintReadStream> IPrintReadStream_t;
+typedef CComPtr<IPrintWriteStream> IPrintWriteStream_t;
+typedef CComPtr<IInterFilterCommunicator> IInterFilterCommunicator_t;
+typedef CComPtr<IPrintPipelinePropertyBag> IPrintPipelinePropertyBag_t;
+typedef CComPtr<IPrintPipelineManagerControl> IPrintPipelineManagerControl_t;
+typedef CComPtr<IXpsDocumentProvider> IXpsDocumentProvider_t;
+typedef CComPtr<IXpsDocumentConsumer> IXpsDocumentConsumer_t;
+typedef CComPtr<IXpsPartIterator> IXpsPartIterator_t;
+typedef CComPtr<IPartBase> IPartBase_t;
+typedef CComPtr<IPartFont2> IPartFont2_t;
+typedef CComPtr<IPartFont> IPartFont_t;
+typedef CComPtr<IPartImage> IPartImage_t;
+typedef CComPtr<IPartColorProfile> IPartColorProfile_t;
+typedef CComPtr<IPartResourceDictionary> IPartResourceDictionary_t;
+typedef std::vector<CAdapt<IPartResourceDictionary_t>> ResourceDictionaryList_t;
+typedef CComPtr<IPartPrintTicket> IPartPrintTicket_t;
+
+//
+// Xps Object Model types
+//
+typedef CComPtr<IXpsOMObjectFactory> IXpsOMObjectFactory_t;
+typedef CComPtr<IXpsOMPartResources> IXpsOMPartResources_t;
+typedef CComPtr<IXpsOMFontResourceCollection> IXpsOMFontResourceCollection_t;
+typedef CComPtr<IXpsOMImageResourceCollection> IXpsOMImageResourceCollection_t;
+typedef CComPtr<IXpsOMColorProfileResourceCollection> IXpsOMColorProfileResourceCollection_t;
+typedef CComPtr<IXpsOMRemoteDictionaryResourceCollection> IXpsOMRemoteDictionaryResourceCollection_t;
+typedef CComPtr<IXpsOMFontResource> IXpsOMFontResource_t;
+typedef CComPtr<IXpsOMImageResource> IXpsOMImageResource_t;
+typedef CComPtr<IXpsOMColorProfileResource> IXpsOMColorProfileResource_t;
+typedef CComPtr<IXpsOMRemoteDictionaryResource> IXpsOMRemoteDictionaryResource_t;
+typedef CComPtr<IXpsOMPage> IXpsOMPage_t;
+
+//
+// Opc Types
+//
+typedef CComPtr<IOpcFactory> IOpcFactory_t;
+typedef CComPtr<IOpcPartUri> IOpcPartUri_t;
+
+//
+// Common types
+//
+typedef CComPtr<IStream> IStream_t;
+typedef CComPtr<IUnknown> IUnknown_t;
+typedef CComBSTR BSTR_t;
+typedef CComVariant Variant_t;
+typedef CComPtr<IPropertyBag2> IPropertyBag2_t;
+
+//
+// WIC types
+//
+typedef CComPtr<IWICImagingFactory> IWICImagingFactory_t;
+typedef CComPtr<IWICBitmap> IWICBitmap_t;
+typedef CComPtr<IWICStream> IWICStream_t;
+typedef CComPtr<IWICBitmapEncoder> IWICBitmapEncoder_t;
+typedef CComPtr<IWICBitmapFrameEncode> IWICBitmapFrameEncode_t;
+
+//
+// Xps Rasterization Service types
+//
+typedef CComPtr<IXpsRasterizationFactory> IXpsRasterizationFactory_t;
+typedef CComPtr<IXpsRasterizer> IXpsRasterizer_t;
+
+//
+// MSXML DOM types
+//
+typedef CComPtr<IXMLDOMDocument2> IXMLDOMDocument2_t;
+typedef CComPtr<IXMLDOMNode> IXMLDOMNode_t;
+typedef CComPtr<IXMLDOMNodeList> IXMLDOMNodeList_t;
+
+namespace xpsrasfilter
+{
+
+//
+// Supported types of print ticket scaling
+//
+enum PrintTicketScaling
+{
+ SCALE_NONE,
+ SCALE_BLEEDTOIMAGEABLE,
+ SCALE_CONTENTTOIMAGEABLE,
+ SCALE_MEDIASIZETOIMAGEABLE,
+ SCALE_MEDIASIZETOMEDIASIZE
+};
+
+//
+// Parameters that can be read from the Print Ticket
+// to feed into rasterization calculations.
+//
+struct ParametersFromPrintTicket
+{
+ XPS_SIZE physicalPageSize; // in XPS units
+ PrintTicketScaling scaling; // scaling type
+ FLOAT destDPI; // target rasterization dpi
+ XPS_RECT imageableArea; // in XPS units
+};
+
+//
+// Parameters read from the FixedPage
+// to feed into rasterization calculations.
+//
+struct ParametersFromFixedPage
+{
+ XPS_SIZE fixedPageSize; // in XPS units
+ XPS_RECT bleedBoxRect; // in XPS units
+ XPS_RECT contentBoxRect; // in XPS units
+};
+
+//
+// Forward Declarations
+//
+class RasterizationInterface;
+class PrintTicketHandler;
+class TiffStreamBitmapHandler;
+class FilterLiveness;
+
+} // namespace xpsrasfilter
+
+//
+// This class handles setting and clearing the security
+// context, based on a token. This token is retrieved from
+// the filter pipeline, and we do not want to free it.
+//
+class ScopeImpersonation
+{
+public:
+ ScopeImpersonation(
+ HANDLE token
+ )
+ {
+ if (
+ !SetThreadToken(
+ NULL, // set the current thread's token
+ token
+ )
+ )
+ {
+ THROW_LAST_ERROR();
+ }
+ }
+
+ ~ScopeImpersonation()
+ {
+ if (
+ !SetThreadToken(
+ NULL, // set the current thread's token
+ NULL // revert to default security context
+ )
+ )
+ {
+ //
+ // We couldn't revert the security context. The filter pipeline
+ // manager will clean up the thread when operation is complete,
+ // when it is determined that the security context was not
+ // reverted. Since there are no security implications with
+ // running this filter in an elevated context, we can log the
+ // error and continue to run.
+ //
+ DWORD error = ::GetLastError();
+
+ WPP_LOG_ON_FAILED_HRESULT_WITH_TEXT(
+ HRESULT_FROM_WIN32(error),
+ L"Failed to revert thread security context."
+ );
+ }
+ }
+
+private:
+ ScopeImpersonation(ScopeImpersonation const&);
+ ScopeImpersonation& operator=(ScopeImpersonation const&);
+};
+
+//
+// RAII object to make HGLOBAL locks exception-safe. This requires
+// unlocking during unwind.
+//
+class HGlobalLock
+{
+public:
+ HGlobalLock(
+ HGLOBAL hG
+ ) :
+ m_hGlobal(hG)
+ {
+ m_pAddress = static_cast<BYTE *>(
+ ::GlobalLock(m_hGlobal)
+ );
+
+ if (!m_pAddress)
+ {
+ THROW_LAST_ERROR();
+ }
+ }
+
+ ~HGlobalLock()
+ {
+ if (!::GlobalUnlock(m_hGlobal))
+ {
+ WPP_LOG_ON_FAILED_HRESULT(
+ HRESULT_FROM_WIN32(::GetLastError())
+ );
+ }
+ }
+
+ BYTE*
+ GetAddress()
+ {
+ return m_pAddress;
+ }
+private:
+ HGLOBAL m_hGlobal;
+ BYTE *m_pAddress;
+
+ HGlobalLock(HGlobalLock const&);
+ HGlobalLock& operator=(HGlobalLock const&);
+
+};
+
+typedef std::auto_ptr<HGlobalLock> HGlobalLock_t;
+
+//
+// Safe handle to make HGLOBAL exception-safe. This requires both
+// freeing and unlocking during unwind.
+//
+class SafeHGlobal
+{
+public:
+
+ SafeHGlobal(
+ UINT flags,
+ SIZE_T size
+ )
+ {
+ m_hGlobal = ::GlobalAlloc(flags, size);
+
+ if (!m_hGlobal)
+ {
+ THROW_ON_FAILED_HRESULT(E_OUTOFMEMORY);
+ }
+ }
+
+ virtual
+ ~SafeHGlobal()
+ {
+ if (m_hGlobal)
+ {
+ //
+ // Free the HGLOBAL
+ //
+ ::GlobalFree(m_hGlobal);
+ }
+ }
+
+ operator HGLOBAL()
+ {
+ return m_hGlobal;
+ }
+
+ //
+ // Passes ownership of the HGLOBAL from this safe handle
+ // to a new IStream.
+ //
+ IStream_t
+ ConvertToIStream()
+ {
+ IStream_t pStream;
+
+ THROW_ON_FAILED_HRESULT(
+ ::CreateStreamOnHGlobal(
+ m_hGlobal,
+ TRUE, // Free the HGLOBAL on Release of the stream
+ &pStream
+ )
+ );
+
+ m_hGlobal = NULL;
+
+ return pStream;
+ }
+
+ HGlobalLock_t
+ Lock()
+ {
+ HGlobalLock_t toReturn(
+ new HGlobalLock(m_hGlobal)
+ );
+ return toReturn;
+ }
+
+private:
+
+ HGLOBAL m_hGlobal;
+
+ SafeHGlobal(SafeHGlobal const&);
+ SafeHGlobal& operator=(SafeHGlobal const&);
+
+};
+
+//
+// Safe handle to make HPTPROVIDER exception safe. This
+// requires closing the provider during unwind.
+//
+class SafeHPTProvider
+{
+public:
+ SafeHPTProvider(
+ const wchar_t *printerName,
+ HANDLE userSecurityToken
+ ) :
+ m_token(userSecurityToken)
+ {
+ //
+ // We impersonate the user while we call PTQuerySchemaVersionSupport
+ // and PTOpenProviderEx.
+ //
+ ScopeImpersonation impersonate(m_token);
+
+ DWORD maxVersion,
+ tempVersion;
+
+ THROW_ON_FAILED_HRESULT(
+ ::PTQuerySchemaVersionSupport(
+ printerName,
+ &maxVersion
+ )
+ );
+
+ THROW_ON_FAILED_HRESULT(
+ ::PTOpenProviderEx(
+ printerName,
+ maxVersion, // maximum version
+ maxVersion, // preferred version
+ &m_hProvider,
+ &tempVersion // version used by the provider
+ )
+ );
+ }
+
+ virtual
+ ~SafeHPTProvider()
+ {
+ WPP_LOG_ON_FAILED_HRESULT(
+ ::PTCloseProvider(m_hProvider)
+ );
+ }
+
+ void
+ PTMergeAndValidatePrintTicket(
+ const IStream_t &pBasePrintTicket,
+ const IStream_t &pDeltaPrintTicket,
+ EPrintTicketScope scope,
+ _Inout_ IStream_t &pMergedPrintTicket
+ )
+ {
+ //
+ // We impersonate the user while we call PTMergeAndValidatePrintTicket.
+ //
+ ScopeImpersonation impersonate(m_token);
+
+ BSTR_t error;
+
+ HRESULT hr = ::PTMergeAndValidatePrintTicket(
+ m_hProvider,
+ pBasePrintTicket,
+ pDeltaPrintTicket,
+ scope,
+ pMergedPrintTicket,
+ &error
+ );
+
+ WPP_LOG_ON_FAILED_HRESULT_WITH_TEXT(
+ hr,
+ error
+ );
+
+ THROW_ON_FAILED_HRESULT(hr);
+ }
+
+private:
+
+ HPTPROVIDER m_hProvider;
+ HANDLE m_token;
+
+ SafeHPTProvider(SafeHPTProvider const&);
+ SafeHPTProvider& operator=(SafeHPTProvider const&);
+};
+
+//
+// CoInitialize/CoUninitialize RAII object
+//
+// This object ensures that COM is initialized for the duration
+// of the XpsRasFilter's lifetime, and then uninitialized after
+// all of the COM objects, regardless of how the filter exits
+//
+class SafeCoInit
+{
+public:
+ SafeCoInit() :
+ m_doCoUninitialize(FALSE)
+ {
+ //
+ // Initialize COM
+ //
+ HRESULT hr = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);
+
+ if (FAILED(hr) &&
+ hr != RPC_E_CHANGED_MODE)
+ {
+ //
+ // RPC_E_CHANGED_MODE indicates that we attempted to change the
+ // threading model. It is safe to ignore since we do not *require*
+ // multi-threading. Throw on any other errors.
+ //
+
+ THROW_ON_FAILED_HRESULT(hr);
+ }
+ else if (SUCCEEDED(hr))
+ {
+ //
+ // It is important that we only call CoUninitialize() if we
+ // succeeded in setting the threading model.
+ //
+
+ m_doCoUninitialize = TRUE;
+ }
+ }
+
+ ~SafeCoInit()
+ {
+ if (m_doCoUninitialize)
+ {
+ ::CoUninitialize();
+ }
+ }
+private:
+ SafeCoInit(SafeCoInit const&);
+ SafeCoInit& operator=(SafeCoInit const&);
+
+ BOOL m_doCoUninitialize;
+};
+
+//
+// RAII object to make VARIANT exception-safe. This requires
+// VariantClear during unwind.
+//
+class SafeVariant : public VARIANT
+{
+public:
+ SafeVariant()
+ {
+ ::VariantInit(this);
+ }
+
+ ~SafeVariant()
+ {
+ ::VariantClear(this);
+ }
+private:
+ SafeVariant(SafeVariant const&);
+ SafeVariant& operator=(SafeVariant const&);
+};
+
+//
+// Internal Types
+//
+typedef std::auto_ptr<xpsrasfilter::RasterizationInterface> RasterizationInterface_t;
+typedef std::auto_ptr<xpsrasfilter::PrintTicketHandler> PrintTicketHandler_t;
+typedef std::auto_ptr<xpsrasfilter::TiffStreamBitmapHandler> TiffStreamBitmapHandler_t;
+typedef std::auto_ptr<SafeHGlobal> SafeHGlobal_t;
+typedef std::auto_ptr<SafeHPTProvider> SafeHPTProvider_t;
+typedef CComPtr<xpsrasfilter::FilterLiveness> FilterLiveness_t;
+
diff --git a/print/XpsRasFilter/src/precomp.h b/print/XpsRasFilter/src/precomp.h
new file mode 100644
index 00000000..97e8f4ee
--- /dev/null
+++ b/print/XpsRasFilter/src/precomp.h
@@ -0,0 +1,86 @@
+// THIS CODE AND INFORMATION IS 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.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved
+//
+// File Name:
+//
+// precomp.h
+//
+// Abstract:
+//
+// Precompiled header for the Xps Rasterization Service sample filter.
+//
+
+#pragma once
+
+//
+// Define this as a usermode driver for analysis purposes
+//
+#include <DriverSpecs.h>
+__user_driver
+
+//
+// Standard Annotation Language include
+//
+#include <sal.h>
+
+//
+// Windows includes
+//
+#include <windows.h>
+
+// Standard includes
+#include <cstring>
+#include <intsafe.h>
+#include <new>
+
+// STL
+#include <vector>
+
+//
+// COM includes
+//
+#include <objbase.h>
+#include <oleauto.h>
+
+//
+// Filter pipeline includes
+//
+#include <winspool.h>
+#include <filterpipeline.h>
+#include <filterpipelineutil.h>
+#include <prntvpt.h>
+
+//
+// ATL
+//
+#include <atlbase.h>
+
+//
+// WIC
+//
+#include <wincodec.h>
+
+//
+// MSXML
+//
+#include <msxml6.h>
+
+//
+// OPC Layer
+//
+#include <msopc.h>
+
+//
+// Xps Object Model
+//
+#include <XpsObjectModel.h>
+
+//
+// Xps Rasterization Service
+//
+#include <xpsrassvc.h>
+
diff --git a/print/XpsRasFilter/src/precompsrc.cpp b/print/XpsRasFilter/src/precompsrc.cpp
new file mode 100644
index 00000000..5944cf51
--- /dev/null
+++ b/print/XpsRasFilter/src/precompsrc.cpp
@@ -0,0 +1 @@
+#include "precomp.h" \ No newline at end of file
diff --git a/print/XpsRasFilter/src/rasinterface.cpp b/print/XpsRasFilter/src/rasinterface.cpp
new file mode 100644
index 00000000..adbf73e4
--- /dev/null
+++ b/print/XpsRasFilter/src/rasinterface.cpp
@@ -0,0 +1,412 @@
+// THIS CODE AND INFORMATION IS 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.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved
+//
+// File Name:
+//
+// rasinterface.cpp
+//
+// Abstract:
+//
+// Class to wrap rasterization-related calculations, interactions with
+// the Xps Rasterization Service, Xps Rasterization Service Callback,
+// and eventual raster output (i.e. TIFF encoding)
+//
+
+#include "precomp.h"
+#include "WppTrace.h"
+#include "Exception.h"
+#include "filtertypes.h"
+#include "UnknownBase.h"
+#include "xpsrasfilter.h"
+#include "OMConvertor.h"
+#include "rasinterface.h"
+#include "BitmapHandler.h"
+
+#include "rasinterface.tmh"
+
+namespace xpsrasfilter
+{
+
+//
+//Routine Name:
+//
+// RasterizationInterface::CreateRasterizationInterface
+//
+//Routine Description:
+//
+// Static factory method that creates an instance of
+// RasterizationInterface.
+//
+//Arguments:
+//
+// pPropertyBag - Property Bag
+// pStream - Filter output stream (IPrintWriteStream)
+//
+//Return Value:
+//
+// RasterizationInterface_t (smart ptr)
+// The new RasterizationInterface.
+//
+RasterizationInterface_t
+RasterizationInterface::CreateRasterizationInterface(
+ const IPrintPipelinePropertyBag_t &pPropertyBag,
+ const IPrintWriteStream_t &pStream
+ )
+{
+ Variant_t varRasFactory;
+ IXpsRasterizationFactory_t pXPSRasFactory;
+
+ //
+ // Get the Xps Rasterization Service factory. Since XpsRasterService.dll
+ // is specified as an OptionalFilterServiceProvider in the filter pipeline
+ // configuration file, the factory may not be available in the property bag
+ // (e.g. when running on Windows Vista, Windows XP, etc). In this case,
+ // this call will fail and the filter could fail, as we do here, or could
+ // default to some other behavior.
+ //
+ THROW_ON_FAILED_HRESULT(
+ pPropertyBag->GetProperty(
+ L"MS_IXpsRasterizationFactory",
+ &varRasFactory
+ )
+ );
+
+ IUnknown_t pUnk(varRasFactory.punkVal);
+
+ THROW_ON_FAILED_HRESULT(
+ pUnk.QueryInterface(&pXPSRasFactory)
+ );
+
+ //
+ // Prepare the rasterization/encode/stream interface
+ //
+ TiffStreamBitmapHandler_t pBitmapHandler(
+ TiffStreamBitmapHandler::CreateTiffStreamBitmapHandler(pStream)
+ );
+
+ RasterizationInterface_t pReturnInterface(
+ new RasterizationInterface(
+ pXPSRasFactory,
+ pBitmapHandler
+ )
+ );
+
+ return pReturnInterface;
+}
+
+//
+//Routine Name:
+//
+// RasterizationInterface::RasterizationInterface
+//
+//Routine Description:
+//
+// Construct the Rasterization Interface with the
+// IXpsRasterizationFactory interface and bitmap
+// handler.
+//
+//Arguments:
+//
+// pRasFactory - Xps Rasterization Service object factory
+// pBitmapHandler - Class to handle band bitmaps
+//
+RasterizationInterface::RasterizationInterface(
+ const IXpsRasterizationFactory_t &pRasFactory,
+ TiffStreamBitmapHandler_t pBitmapHandler
+ ) : m_pXPSRasFactory(pRasFactory),
+ m_pBitmapHandler(pBitmapHandler)
+{
+}
+
+//
+//Routine Name:
+//
+// RasterizationInterface::FinishRasterization
+//
+//Routine Description:
+//
+// Tell the Rasterization Interface that the last
+// page has been rasterized.
+//
+//Arguments:
+//
+// None
+//
+void
+RasterizationInterface::FinishRasterization()
+{
+ m_pBitmapHandler->WriteFooter();
+}
+
+
+//
+//Routine Name:
+//
+// RasterizationInterface::RasterizeAndStreamPage
+//
+//Routine Description:
+//
+// Given an IXpsOMPage and a set of Print Ticket
+// parameters, this method invokes the Xps Rasterization
+// Service for each band of the page, and outputs the
+// resultant raster data.
+//
+//Arguments:
+//
+// pPage - page to rasterize
+// printTicketparams - raw parameters from the print ticket(s)
+//
+void
+RasterizationInterface::RasterizePage(
+ const IXpsOMPage_t &pPage,
+ const ParametersFromPrintTicket &printTicketParams,
+ const FilterLiveness_t &pLiveness
+ )
+{
+ //
+ // Calculate rasterization parameters
+ //
+ ParametersFromFixedPage fixedPageParams;
+ THROW_ON_FAILED_HRESULT(
+ pPage->GetPageDimensions(&fixedPageParams.fixedPageSize)
+ );
+ THROW_ON_FAILED_HRESULT(
+ pPage->GetBleedBox(&fixedPageParams.bleedBoxRect)
+ );
+ THROW_ON_FAILED_HRESULT(
+ pPage->GetContentBox(&fixedPageParams.contentBoxRect)
+ );
+
+ RasterizationParameters rastParams(
+ printTicketParams,
+ fixedPageParams
+ );
+
+ //
+ // Create the Rasterizer
+ //
+ IXpsRasterizer_t rasterizer;
+ THROW_ON_FAILED_HRESULT(
+ m_pXPSRasFactory->CreateRasterizer(
+ pPage,
+ rastParams.rasterizationDPI,
+ XPSRAS_RENDERING_MODE_ANTIALIASED,
+ XPSRAS_RENDERING_MODE_ANTIALIASED,
+ &rasterizer
+ )
+ );
+
+ //
+ // Set the minimal line width to 1 pixel
+ //
+ THROW_ON_FAILED_HRESULT(
+ rasterizer->SetMinimalLineWidth(1)
+ );
+
+ //
+ // Loop over bands
+ //
+ INT bandOriginY = 0;
+
+ while (pLiveness->IsAlive() &&
+ bandOriginY < rastParams.rasterHeight)
+ {
+ DoTraceMessage(XPSRASFILTER_TRACE_VERBOSE, L"Rasterizing Band");
+
+ IWICBitmap_t bitmap;
+
+ //
+ // Calculate the height of this band
+ //
+ INT bandHeight = rastParams.bandHeight;
+ if (bandOriginY + rastParams.bandHeight >= rastParams.rasterHeight)
+ {
+ bandHeight = rastParams.rasterHeight - bandOriginY;
+ }
+
+ //
+ // Rasterize this band
+ //
+ {
+ HRESULT hr = rasterizer->RasterizeRect(
+ rastParams.originX,
+ bandOriginY + rastParams.originY,
+ rastParams.rasterWidth,
+ bandHeight,
+ static_cast<IXpsRasterizerNotificationCallback *>(pLiveness),
+ &bitmap
+ );
+
+ //
+ // Do not throw if we have cancelled rasterization
+ //
+ if (hr == HRESULT_FROM_WIN32(ERROR_PRINT_CANCELLED))
+ {
+ DoTraceMessage(XPSRASFILTER_TRACE_VERBOSE, L"Rasterization Cancelled");
+ return;
+ }
+
+ THROW_ON_FAILED_HRESULT(hr);
+ }
+
+ bandOriginY += bandHeight;
+
+ //
+ // The resolution of the bitmap defaults to the
+ // rasterization DPI, which includes the scaling factor.
+ // We want the output bitmap to reflect the destination DPI.
+ //
+ THROW_ON_FAILED_HRESULT(
+ bitmap->SetResolution(
+ printTicketParams.destDPI,
+ printTicketParams.destDPI
+ )
+ );
+
+ //
+ // Encode the raster data as TIFF and stream out
+ //
+ m_pBitmapHandler->ProcessBitmap(bitmap);
+ }
+}
+
+//
+//Routine Name:
+//
+// RasterizationParameters::RasterizationParameters
+//
+//Routine Description:
+//
+// Given a set of fixed page parameters and a set of Print Ticket
+// parameters, this constructor calculates the parameters necessary to
+// invoke the Xps Rasterization Service.
+//
+//Arguments:
+//
+// printTicketparams - raw parameters from the print ticket(s)
+// fixedPageParams - raw parameters from the fixed page
+//
+RasterizationParameters::RasterizationParameters(
+ const ParametersFromPrintTicket &printTicketParams,
+ const ParametersFromFixedPage &fixedPageParams
+ )
+{
+ //
+ // Rasterize the entire physical page at the desired resolution. The fixed page
+ // is scaled and traslated to place it correctly witin the physical page.
+ //
+ rasterHeight = static_cast<INT>(
+ printTicketParams.physicalPageSize.height
+ * (printTicketParams.destDPI / xpsDPI)
+ + 0.5
+ );
+ rasterWidth = static_cast<INT>(
+ printTicketParams.physicalPageSize.width
+ * (printTicketParams.destDPI / xpsDPI)
+ + 0.5
+ );
+
+ //
+ // Determine the source rectangle for the scale operation
+ //
+ XPS_RECT srcRect = {0,0,0,0};
+
+ switch(printTicketParams.scaling)
+ {
+ case SCALE_BLEEDTOIMAGEABLE:
+
+ srcRect = fixedPageParams.bleedBoxRect;
+
+ break;
+ default:
+ DoTraceMessage(XPSRASFILTER_TRACE_ERROR, L"Unknown scaling type");
+ THROW_ON_FAILED_HRESULT(E_UNEXPECTED);
+ break;
+ }
+
+ //
+ // Determine the destination rectangle for the scale operation
+ //
+ XPS_RECT destRect = {0,0,0,0};
+
+ switch(printTicketParams.scaling)
+ {
+ case SCALE_BLEEDTOIMAGEABLE:
+
+ destRect = printTicketParams.imageableArea;
+
+ break;
+ default:
+ DoTraceMessage(XPSRASFILTER_TRACE_ERROR, L"Unknown scaling type");
+ THROW_ON_FAILED_HRESULT(E_UNEXPECTED);
+ break;
+ }
+
+
+ //
+ // Because we want to fit the fixed page into a physical page of
+ // potentially different aspect ratio, it is necessary to calculate
+ // the scaling factor assuming either the height or width constrains
+ // the operation; the rasterization dpi is then the smaller of the two.
+ //
+ //
+ // The basic calculation for scaling factor is:
+ //
+ // Scaling Factor = (Destination Dimension / Source Dimension)
+ //
+ // Multiplying by desired Destination DPI we get the DPI at which to
+ // rasterize the source content in order to get the desired size
+ //
+ // Rasterization DPI = Scaling Factor * Desired Destination DPI
+ //
+ {
+ FLOAT heightScalingFactor = destRect.height / srcRect.height;
+ FLOAT widthScalingFactor = destRect.width / srcRect.width;
+
+ FLOAT heightRastDPI = heightScalingFactor * printTicketParams.destDPI;
+ FLOAT widthRastDPI = widthScalingFactor * printTicketParams.destDPI;
+
+ rasterizationDPI = min(heightRastDPI, widthRastDPI);
+ }
+
+ //
+ // To determine the rasterization origin, subtract the translation
+ // due to the destination rectangle (e.g. imageable area) from the
+ // translation due to the choice of scale (e.g. bleed box origin)
+ //
+ {
+ FLOAT srcOffsetX = srcRect.x * rasterizationDPI / xpsDPI;
+ FLOAT srcOffsetY = srcRect.y * rasterizationDPI / xpsDPI;
+
+ FLOAT destOffsetX = destRect.x * printTicketParams.destDPI / xpsDPI;
+ FLOAT destOffsetY = destRect.y * printTicketParams.destDPI / xpsDPI;
+
+ originX = static_cast<INT>(srcOffsetX - destOffsetX - 0.5);
+ originY = static_cast<INT>(srcOffsetY - destOffsetY - 0.5);
+ }
+
+ //
+ // The height of each band is determined by the maximum band size (in bytes)
+ // divided by 4 bytes per pixel to get the total pixels, and then divided by
+ // the width of the raster data. This results in a band bitmap that is close
+ // to the target band size.
+ //
+ bandHeight = (RasterizationInterface::ms_targetBandSize / 4) / rasterWidth;
+
+ if (bandHeight == 0)
+ {
+ //
+ // The physical page is too wide to rasterize at this
+ // maximum band size and dpi. Throw.
+ //
+ THROW_ON_FAILED_HRESULT(
+ E_OUTOFMEMORY
+ );
+ }
+}
+
+} // namespace xpsrasfilter
diff --git a/print/XpsRasFilter/src/rasinterface.h b/print/XpsRasFilter/src/rasinterface.h
new file mode 100644
index 00000000..3fae74cf
--- /dev/null
+++ b/print/XpsRasFilter/src/rasinterface.h
@@ -0,0 +1,107 @@
+// THIS CODE AND INFORMATION IS 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.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved
+//
+// File Name:
+//
+// rasinterface.h
+//
+// Abstract:
+//
+// Class to wrap rasterization-related calculations, interactions with
+// the Xps Rasterization Service, Xps Rasterization Service Callback,
+// and eventual raster output (i.e. TIFF encoding)
+//
+
+#pragma once
+
+namespace xpsrasfilter
+{
+
+class RasterizationInterface
+{
+public:
+ static
+ RasterizationInterface_t
+ CreateRasterizationInterface(
+ const IPrintPipelinePropertyBag_t &pPropertyBag,
+ const IPrintWriteStream_t &pStream
+ );
+
+ RasterizationInterface();
+
+ void
+ RasterizePage(
+ const IXpsOMPage_t &pPage,
+ const ParametersFromPrintTicket &printTicketParams,
+ const FilterLiveness_t &pLiveness
+ );
+
+ void
+ CancelRasterization();
+
+ void
+ FinishRasterization();
+
+ //
+ // Target band size; 16MB
+ //
+ const static LONG ms_targetBandSize = 1024 * 1024 * 16;
+
+private:
+
+ //
+ // Constructor is private; use CreateRasterizationInterface
+ // to create instances
+ //
+ RasterizationInterface(
+ const IXpsRasterizationFactory_t &pRasFactory,
+ TiffStreamBitmapHandler_t pBitmapHandler
+ );
+
+ //
+ // prevent copy semantics
+ //
+ RasterizationInterface(const RasterizationInterface&);
+ RasterizationInterface& operator=(const RasterizationInterface&);
+
+ //
+ // Internal data members
+ //
+
+ //
+ // Xps Rasterization Service Factory
+ //
+ IXpsRasterizationFactory_t m_pXPSRasFactory;
+
+ //
+ // Bitmap Handler
+ //
+ TiffStreamBitmapHandler_t m_pBitmapHandler;
+};
+
+//
+// Parameters that determine how a page is rasterized, in the
+// units that the Rasterization Service expects
+//
+struct RasterizationParameters
+{
+ FLOAT rasterizationDPI; // dpi (scaling factor)
+ INT rasterHeight; // total size of raster
+ INT rasterWidth;
+ INT originX; // origin of the rasterization (translation)
+ INT originY;
+ INT bandHeight; // height of individual bands
+
+ RasterizationParameters(
+ const ParametersFromPrintTicket &printTicketParams,
+ const ParametersFromFixedPage &fixedPageParams
+ );
+};
+
+const FLOAT xpsDPI = 96.0f;
+
+} // namespace xpsrasfilter
diff --git a/print/XpsRasFilter/src/xpsrasfilter.cpp b/print/XpsRasFilter/src/xpsrasfilter.cpp
new file mode 100644
index 00000000..1199a540
--- /dev/null
+++ b/print/XpsRasFilter/src/xpsrasfilter.cpp
@@ -0,0 +1,396 @@
+// THIS CODE AND INFORMATION IS 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.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved
+//
+// File Name:
+//
+// xpsrasfilter.cpp
+//
+// Abstract:
+//
+// Xps Rasterization Service filter implementation.
+//
+
+#include "precomp.h"
+#include "WppTrace.h"
+#include "Exception.h"
+#include "filtertypes.h"
+#include "UnknownBase.h"
+#include "OMConvertor.h"
+#include "rasinterface.h"
+#include "BitmapHandler.h"
+#include "PThandler.h"
+#include "xpsrasfilter.h"
+
+#include "xpsrasfilter.tmh"
+
+namespace xpsrasfilter
+{
+
+long XPSRasFilter::ms_numObjects = 0; // Initialize static object count
+
+//
+//Routine Name:
+//
+// XPSRasFilter::XPSRasFilter
+//
+//Routine Description:
+//
+// Xps Rasterization Service sample filter default constructor.
+//
+//Arguments:
+//
+// None
+//
+//Return Value:
+//
+// None
+//
+XPSRasFilter::XPSRasFilter()
+{
+ //
+ // Take ownership with no AddRef
+ //
+ m_pLiveness.Attach(new FilterLiveness());
+
+ ::InterlockedIncrement(&ms_numObjects);
+}
+
+//
+//Routine Name:
+//
+// XPSRasFilter::~XPSRasFilter
+//
+//Routine Description:
+//
+// Xps Rasterization Service sample filter destructor.
+//
+//Arguments:
+//
+// None
+//
+//Return Value:
+//
+// None
+//
+XPSRasFilter::~XPSRasFilter()
+{
+ ::InterlockedDecrement(&ms_numObjects);
+}
+
+//
+//Routine Name:
+//
+// XPSRasFilter::InitializeFilter
+//
+//Routine Description:
+//
+// Exception boundary wrapper for IPrintPipelineFilter initialization.
+//
+//Arguments:
+//
+// pICommunicator - interface to interfilter communicator
+// pIPropertyBag - interface to pipeline property bag
+// pIPipelineControl - interface to pipeline control methods
+//
+//Return Value:
+//
+// ULONG
+// New reference count
+//
+_Must_inspect_result_
+HRESULT STDMETHODCALLTYPE
+XPSRasFilter::InitializeFilter(
+ _In_ IInterFilterCommunicator *pICommunicator,
+ _In_ IPrintPipelinePropertyBag *pIPropertyBag,
+ _In_ IPrintPipelineManagerControl *pIPipelineControl
+ )
+{
+ DoTraceMessage(XPSRASFILTER_TRACE_INFO, L"Initializing Filter");
+
+ if (pICommunicator == NULL ||
+ pIPropertyBag == NULL ||
+ pIPipelineControl == NULL)
+ {
+ WPP_LOG_ON_FAILED_HRESULT(E_POINTER);
+
+ return E_POINTER;
+ }
+
+ HRESULT hr = S_OK;
+
+ try
+ {
+ InitializeFilter_throws(
+ pICommunicator,
+ pIPropertyBag
+ );
+ }
+ CATCH_VARIOUS(hr);
+
+ return hr;
+}
+
+//
+//Routine Name:
+//
+// XPSRasFilter::InitializeFilter_throws
+//
+//Routine Description:
+//
+// Implements IPrintPipelineFilter initialization. Gets
+// all necessary communication interfaces.
+//
+//Arguments:
+//
+// pICommunicator - interface to interfilter communicator
+// pIPropertyBag - interface to pipeline property bag
+//
+VOID
+XPSRasFilter::InitializeFilter_throws(
+ const IInterFilterCommunicator_t &pICommunicator,
+ const IPrintPipelinePropertyBag_t &pIPropertyBag
+ )
+{
+ //
+ // Get the pipeline communication interfaces
+ //
+ THROW_ON_FAILED_HRESULT(
+ pICommunicator->RequestReader(reinterpret_cast<void**>(&m_pReader))
+ );
+ THROW_ON_FAILED_HRESULT(
+ pICommunicator->RequestWriter(reinterpret_cast<void**>(&m_pWriter))
+ );
+
+ {
+ //
+ // Check to ensure that the provided interfaces are as expected.
+ // That is, that the GUIDs were correctly listed in the
+ // pipeline configuration file
+ //
+ IXpsDocumentProvider_t pReaderCheck;
+ IPrintWriteStream_t pWriterCheck;
+
+ THROW_ON_FAILED_HRESULT(
+ m_pReader.QueryInterface(&pReaderCheck)
+ );
+ THROW_ON_FAILED_HRESULT(
+ m_pWriter.QueryInterface(&pWriterCheck)
+ );
+ }
+
+ //
+ // Save a pointer to the Property Bag for further
+ // initialization, later.
+ //
+ m_pIPropertyBag = pIPropertyBag;
+}
+
+//
+//Routine Name:
+//
+// XPSRasFilter::ShutdownOperation
+//
+//Routine Description:
+//
+// Called asynchronously by the pipeline manager
+// to shutdown filter operation.
+//
+//Arguments:
+//
+// None
+//
+//Return Value:
+//
+// HRESULT
+// S_OK - On success
+//
+_Must_inspect_result_
+HRESULT
+XPSRasFilter::ShutdownOperation()
+{
+ DoTraceMessage(XPSRASFILTER_TRACE_INFO, L"Shutting Down Operation");
+
+ m_pLiveness->Cancel();
+
+ return S_OK;
+}
+
+//
+//Routine Name:
+//
+// XPSRasFilter::StartOperation
+//
+//Routine Description:
+//
+// Called by the pipeline manager to start processing
+// a document. Exception boundary for page processing.
+//
+//Arguments:
+//
+// None
+//
+//Return Value:
+//
+// HRESULT
+// S_OK - On success
+// Otherwise - Failure
+//
+_Must_inspect_result_
+HRESULT
+XPSRasFilter::StartOperation()
+{
+ HRESULT hr = S_OK;
+
+ DoTraceMessage(XPSRASFILTER_TRACE_INFO, L"Starting Operation");
+
+ //
+ // Process the Xps Package
+ //
+ try {
+ StartOperation_throws();
+ }
+ CATCH_VARIOUS(hr);
+
+ m_pWriter->Close();
+
+ return hr;
+}
+
+//
+//Routine Name:
+//
+// XPSRasFilter::StartOperation_throws
+//
+//Routine Description:
+//
+// Iterates over the 'trunk' parts of the document
+// and calls appropriate processing methods.
+//
+//Arguments:
+//
+// None
+//
+void
+XPSRasFilter::StartOperation_throws()
+{
+ //
+ // CoInitialize/CoUninitialize RAII object.
+ // COM is inititalized for the lifetime of this method.
+ //
+ SafeCoInit coInit;
+
+ IXpsOMObjectFactory_t pOMFactory;
+
+ //
+ // Create Xps Object Model Object Factory instance
+ //
+ THROW_ON_FAILED_HRESULT(
+ ::CoCreateInstance(
+ __uuidof(XpsOMObjectFactory),
+ NULL,
+ CLSCTX_INPROC_SERVER,
+ __uuidof(IXpsOMObjectFactory),
+ reinterpret_cast<LPVOID*>(&pOMFactory)
+ )
+ );
+
+ IOpcFactory_t pOpcFactory;
+
+ //
+ // Create Opc Object Factory instance
+ //
+ THROW_ON_FAILED_HRESULT(
+ ::CoCreateInstance(
+ __uuidof(OpcFactory),
+ NULL,
+ CLSCTX_INPROC_SERVER,
+ __uuidof(IOpcFactory),
+ reinterpret_cast<LPVOID*>(&pOpcFactory)
+ )
+ );
+
+ //
+ // Create the rasterization interface
+ //
+ RasterizationInterface_t pRasInterface =
+ RasterizationInterface::CreateRasterizationInterface(
+ m_pIPropertyBag,
+ m_pWriter
+ );
+
+ //
+ // Create the Print Ticket Handler
+ //
+ PrintTicketHandler_t pPrintTicketHandler =
+ PrintTicketHandler::CreatePrintTicketHandler(
+ m_pIPropertyBag
+ );
+
+ IUnknown_t pUnk;
+
+ //
+ // Get first part
+ //
+ THROW_ON_FAILED_HRESULT(m_pReader->GetXpsPart(&pUnk));
+
+ while (m_pLiveness->IsAlive() &&
+ pUnk != NULL)
+ {
+ IXpsDocument_t pDoc;
+ IFixedDocumentSequence_t pFDS;
+ IFixedDocument_t pFD;
+ IFixedPage_t pFP;
+
+ if (SUCCEEDED(pUnk.QueryInterface(&pFP)))
+ {
+ DoTraceMessage(XPSRASFILTER_TRACE_VERBOSE, L"Handling a Page");
+
+ pPrintTicketHandler->ProcessPart(pFP);
+
+ ParametersFromPrintTicket printTicketParams =
+ pPrintTicketHandler->GetMergedPrintTicketParams();
+
+ pRasInterface->RasterizePage(
+ CreateXpsOMPageFromIFixedPage(pFP, pOMFactory, pOpcFactory),
+ printTicketParams,
+ m_pLiveness
+ );
+ }
+ else if (SUCCEEDED(pUnk.QueryInterface(&pFD)))
+ {
+ pPrintTicketHandler->ProcessPart(pFD);
+ }
+ else if (SUCCEEDED(pUnk.QueryInterface(&pFDS)))
+ {
+ pPrintTicketHandler->ProcessPart(pFDS);
+ }
+ else if (SUCCEEDED(pUnk.QueryInterface(&pDoc)))
+ {
+ //
+ // Do nothing with the XML Document part
+ //
+ }
+ else
+ {
+ //
+ // Any other document 'trunk' parts are ignored.
+ //
+ }
+
+ pUnk.Release();
+
+ //
+ // Get Next Part
+ //
+ THROW_ON_FAILED_HRESULT(m_pReader->GetXpsPart(&pUnk));
+ }
+
+ pRasInterface->FinishRasterization();
+}
+
+} // namespace xpsrasfilter
+
diff --git a/print/XpsRasFilter/src/xpsrasfilter.def b/print/XpsRasFilter/src/xpsrasfilter.def
new file mode 100644
index 00000000..a3dac1cc
--- /dev/null
+++ b/print/XpsRasFilter/src/xpsrasfilter.def
@@ -0,0 +1,22 @@
+; THIS CODE AND INFORMATION IS 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.
+;
+; Copyright (c) Microsoft Corporation. All rights reserved
+;
+; File Name:
+;
+; xpsrasfilter.def
+;
+; Abstract:
+;
+; Defines DLL exports for xpsrasfilter.dll
+;
+
+LIBRARY "xpsrasfilter.dll"
+
+EXPORTS
+ DllGetClassObject PRIVATE
+ DllCanUnloadNow PRIVATE
+
diff --git a/print/XpsRasFilter/src/xpsrasfilter.h b/print/XpsRasFilter/src/xpsrasfilter.h
new file mode 100644
index 00000000..2ad3a4f9
--- /dev/null
+++ b/print/XpsRasFilter/src/xpsrasfilter.h
@@ -0,0 +1,141 @@
+// THIS CODE AND INFORMATION IS 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.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved
+//
+// File Name:
+//
+// xpsrasfilter.h
+//
+// Abstract:
+//
+// Xps Rasterization Service sample filter definition. The
+// XPSRasFilter provides the interface to the filter pipeline manager.
+//
+
+#pragma once
+
+namespace xpsrasfilter
+{
+
+//
+// Class to maintain the shared state of operation between multiple components
+// of the filter. Also provides the callback for the Xps Rasterization Service.
+//
+class FilterLiveness : public UnknownBase<IXpsRasterizerNotificationCallback>
+{
+public:
+
+ FilterLiveness() :
+ m_isAlive(TRUE)
+ {}
+
+ virtual
+ ~FilterLiveness() {}
+
+ BOOL
+ IsAlive()
+ {
+ return m_isAlive;
+ }
+
+ void
+ Cancel()
+ {
+ //
+ // May be called from a different thread
+ //
+ m_isAlive = FALSE;
+ }
+
+ //
+ // IXpsRasterizerNotificationCallback Method
+ //
+ virtual _Must_inspect_result_
+ HRESULT STDMETHODCALLTYPE
+ Continue()
+ {
+ return (m_isAlive) ? (S_OK) : (HRESULT_FROM_WIN32(ERROR_PRINT_CANCELLED));
+ }
+
+private:
+ volatile BOOL m_isAlive;
+
+ //
+ // prevent copy semantics
+ //
+ FilterLiveness(const FilterLiveness&);
+ FilterLiveness& operator=(const FilterLiveness&);
+};
+
+class XPSRasFilter : public UnknownBase<IPrintPipelineFilter>
+{
+
+public:
+
+ static LONG ms_numObjects; // Number of instances of XPSRasFilter
+
+ XPSRasFilter();
+
+ virtual
+ ~XPSRasFilter();
+
+ //
+ // IPrintPipelineFilter Methods
+ //
+ virtual _Must_inspect_result_
+ HRESULT STDMETHODCALLTYPE
+ InitializeFilter(
+ _In_ IInterFilterCommunicator *pICommunicator,
+ _In_ IPrintPipelinePropertyBag *pIPropertyBag,
+ _In_ IPrintPipelineManagerControl *pIPipelineControl
+ );
+
+ virtual _Must_inspect_result_
+ HRESULT STDMETHODCALLTYPE
+ ShutdownOperation();
+
+ virtual _Must_inspect_result_
+ HRESULT STDMETHODCALLTYPE
+ StartOperation();
+
+private:
+ //
+ // prevent copy semantics
+ //
+ XPSRasFilter(const XPSRasFilter&);
+ XPSRasFilter& operator=(const XPSRasFilter&);
+
+ //
+ // Xps package part reader
+ //
+ IXpsDocumentProvider_t m_pReader;
+ IPrintWriteStream_t m_pWriter;
+
+ //
+ // Pipeline Property Bag
+ //
+ IPrintPipelinePropertyBag_t m_pIPropertyBag;
+
+ //
+ // IPrintPipelineFilter Methods (throwing)
+ //
+ VOID
+ StartOperation_throws();
+
+ VOID
+ InitializeFilter_throws(
+ const IInterFilterCommunicator_t &pICommunicator,
+ const IPrintPipelinePropertyBag_t &pIPropertyBag
+ );
+
+ //
+ // Keeps track of whether the operation has been cancelled
+ //
+ FilterLiveness_t m_pLiveness;
+};
+
+} // namespace xpsrasfilter
+
diff --git a/print/XpsRasFilter/src/xpsrasfilter.rc b/print/XpsRasFilter/src/xpsrasfilter.rc
new file mode 100644
index 00000000..d7f2fc40
--- /dev/null
+++ b/print/XpsRasFilter/src/xpsrasfilter.rc
@@ -0,0 +1,28 @@
+// THIS CODE AND INFORMATION IS 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.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved
+//
+// File Name:
+//
+// xpsrasfilter.rc
+//
+// Abstract:
+//
+// Xps Rasterization Service filter resource file.
+//
+
+#include <windows.h>
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "XPS Rasterization Service WDK Sample Filter"
+#define VER_INTERNALNAME_STR "xpsrasfilter.dll"
+#define VER_ORIGINALFILENAME_STR "xpsrasfilter.dll"
+#define VER_FILEVERSION 0, 3, VER_PRODUCTBUILD, VER_PRODUCTBUILD_QFE
+
+#include "common.ver"
+
diff --git a/print/XpsRasFilter/src/xpsrasfilter.vcxproj b/print/XpsRasFilter/src/xpsrasfilter.vcxproj
new file mode 100644
index 00000000..48f9b603
--- /dev/null
+++ b/print/XpsRasFilter/src/xpsrasfilter.vcxproj
@@ -0,0 +1,349 @@
+<?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>{41965435-F4B0-495B-B669-2291F27F56B5}</ProjectGuid>
+ <RootNamespace>$(MSBuildProjectName)</RootNamespace>
+ <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
+ <Platform Condition="'$(Platform)' == ''">Win32</Platform>
+ <SampleGuid>{47DD7292-F334-4FEC-B539-B5D84A74585B}</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="dllentry.cpp">
+ <WppEnabled>true</WppEnabled>
+ <WppFileExtensions>.cpp.cxx.h.hxx.inl</WppFileExtensions>
+ <WppPreserveExtensions>.h.hxx.inl</WppPreserveExtensions>
+ <WppModuleName>XpsRasFilter</WppModuleName>
+ <WppDllMacro>true</WppDllMacro>
+ <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreCompiledHeaderFile>precomp.h</PreCompiledHeaderFile>
+ <PreCompiledHeader>Use</PreCompiledHeader>
+ <PreCompiledHeaderOutputFile>$(IntDir)\precomp.h.pch</PreCompiledHeaderOutputFile>
+ </ClCompile>
+ <ClCompile Include="xpsrasfilter.cpp">
+ <WppEnabled>true</WppEnabled>
+ <WppFileExtensions>.cpp.cxx.h.hxx.inl</WppFileExtensions>
+ <WppPreserveExtensions>.h.hxx.inl</WppPreserveExtensions>
+ <WppModuleName>XpsRasFilter</WppModuleName>
+ <WppDllMacro>true</WppDllMacro>
+ <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreCompiledHeaderFile>precomp.h</PreCompiledHeaderFile>
+ <PreCompiledHeader>Use</PreCompiledHeader>
+ <PreCompiledHeaderOutputFile>$(IntDir)\precomp.h.pch</PreCompiledHeaderOutputFile>
+ </ClCompile>
+ <ClCompile Include="omconvertor.cpp">
+ <WppEnabled>true</WppEnabled>
+ <WppFileExtensions>.cpp.cxx.h.hxx.inl</WppFileExtensions>
+ <WppPreserveExtensions>.h.hxx.inl</WppPreserveExtensions>
+ <WppModuleName>XpsRasFilter</WppModuleName>
+ <WppDllMacro>true</WppDllMacro>
+ <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreCompiledHeaderFile>precomp.h</PreCompiledHeaderFile>
+ <PreCompiledHeader>Use</PreCompiledHeader>
+ <PreCompiledHeaderOutputFile>$(IntDir)\precomp.h.pch</PreCompiledHeaderOutputFile>
+ </ClCompile>
+ <ClCompile Include="Exception.cpp">
+ <WppEnabled>true</WppEnabled>
+ <WppFileExtensions>.cpp.cxx.h.hxx.inl</WppFileExtensions>
+ <WppPreserveExtensions>.h.hxx.inl</WppPreserveExtensions>
+ <WppModuleName>XpsRasFilter</WppModuleName>
+ <WppDllMacro>true</WppDllMacro>
+ <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreCompiledHeaderFile>precomp.h</PreCompiledHeaderFile>
+ <PreCompiledHeader>Use</PreCompiledHeader>
+ <PreCompiledHeaderOutputFile>$(IntDir)\precomp.h.pch</PreCompiledHeaderOutputFile>
+ </ClCompile>
+ <ClCompile Include="WppTrace.cpp">
+ <WppEnabled>true</WppEnabled>
+ <WppFileExtensions>.cpp.cxx.h.hxx.inl</WppFileExtensions>
+ <WppPreserveExtensions>.h.hxx.inl</WppPreserveExtensions>
+ <WppModuleName>XpsRasFilter</WppModuleName>
+ <WppDllMacro>true</WppDllMacro>
+ <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreCompiledHeaderFile>precomp.h</PreCompiledHeaderFile>
+ <PreCompiledHeader>Use</PreCompiledHeader>
+ <PreCompiledHeaderOutputFile>$(IntDir)\precomp.h.pch</PreCompiledHeaderOutputFile>
+ </ClCompile>
+ <ClCompile Include="rasinterface.cpp">
+ <WppEnabled>true</WppEnabled>
+ <WppFileExtensions>.cpp.cxx.h.hxx.inl</WppFileExtensions>
+ <WppPreserveExtensions>.h.hxx.inl</WppPreserveExtensions>
+ <WppModuleName>XpsRasFilter</WppModuleName>
+ <WppDllMacro>true</WppDllMacro>
+ <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreCompiledHeaderFile>precomp.h</PreCompiledHeaderFile>
+ <PreCompiledHeader>Use</PreCompiledHeader>
+ <PreCompiledHeaderOutputFile>$(IntDir)\precomp.h.pch</PreCompiledHeaderOutputFile>
+ </ClCompile>
+ <ClCompile Include="PThandler.cpp">
+ <WppEnabled>true</WppEnabled>
+ <WppFileExtensions>.cpp.cxx.h.hxx.inl</WppFileExtensions>
+ <WppPreserveExtensions>.h.hxx.inl</WppPreserveExtensions>
+ <WppModuleName>XpsRasFilter</WppModuleName>
+ <WppDllMacro>true</WppDllMacro>
+ <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreCompiledHeaderFile>precomp.h</PreCompiledHeaderFile>
+ <PreCompiledHeader>Use</PreCompiledHeader>
+ <PreCompiledHeaderOutputFile>$(IntDir)\precomp.h.pch</PreCompiledHeaderOutputFile>
+ </ClCompile>
+ <ClCompile Include="BitmapHandler.cpp">
+ <WppEnabled>true</WppEnabled>
+ <WppFileExtensions>.cpp.cxx.h.hxx.inl</WppFileExtensions>
+ <WppPreserveExtensions>.h.hxx.inl</WppPreserveExtensions>
+ <WppModuleName>XpsRasFilter</WppModuleName>
+ <WppDllMacro>true</WppDllMacro>
+ <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreCompiledHeaderFile>precomp.h</PreCompiledHeaderFile>
+ <PreCompiledHeader>Use</PreCompiledHeader>
+ <PreCompiledHeaderOutputFile>$(IntDir)\precomp.h.pch</PreCompiledHeaderOutputFile>
+ </ClCompile>
+ <OtherWpp Include="xpsrasfilter.rc">
+ <WppEnabled>true</WppEnabled>
+ <WppFileExtensions>.cpp.cxx.h.hxx.inl</WppFileExtensions>
+ <WppPreserveExtensions>.h.hxx.inl</WppPreserveExtensions>
+ <WppModuleName>XpsRasFilter</WppModuleName>
+ <WppDllMacro>true</WppDllMacro>
+ </OtherWpp>
+ </ItemGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TargetName>xpsrasfilter</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetName>xpsrasfilter</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetName>xpsrasfilter</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetName>xpsrasfilter</TargetName>
+ </PropertyGroup>
+ <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'">
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories>
+ </Midl>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);uuid.lib;prntvpt.lib;Kernel32.lib;winspool.lib;ole32.lib;oleaut32.lib;Advapi32.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories>
+ </Midl>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);uuid.lib;prntvpt.lib;Kernel32.lib;winspool.lib;ole32.lib;oleaut32.lib;Advapi32.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories>
+ </Midl>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);uuid.lib;prntvpt.lib;Kernel32.lib;winspool.lib;ole32.lib;oleaut32.lib;Advapi32.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories>
+ </Midl>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);uuid.lib;prntvpt.lib;Kernel32.lib;winspool.lib;ole32.lib;oleaut32.lib;Advapi32.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <UseOfAtl>Dynamic</UseOfAtl>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <UseOfAtl>Dynamic</UseOfAtl>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <UseOfAtl>Dynamic</UseOfAtl>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <UseOfAtl>Dynamic</UseOfAtl>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Link>
+ <ModuleDefinitionFile>xpsrasfilter.def</ModuleDefinitionFile>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Link>
+ <ModuleDefinitionFile>xpsrasfilter.def</ModuleDefinitionFile>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Link>
+ <ModuleDefinitionFile>xpsrasfilter.def</ModuleDefinitionFile>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Link>
+ <ModuleDefinitionFile>xpsrasfilter.def</ModuleDefinitionFile>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="precompsrc.cpp">
+ <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreCompiledHeaderFile>precomp.h</PreCompiledHeaderFile>
+ <PreCompiledHeader>Create</PreCompiledHeader>
+ <PreCompiledHeaderOutputFile>$(IntDir)\precomp.h.pch</PreCompiledHeaderOutputFile>
+ </ClCompile>
+ <ResourceCompile Include="xpsrasfilter.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/XpsRasFilter/src/xpsrasfilter.vcxproj.Filters b/print/XpsRasFilter/src/xpsrasfilter.vcxproj.Filters
new file mode 100644
index 00000000..fdfc8758
--- /dev/null
+++ b/print/XpsRasFilter/src/xpsrasfilter.vcxproj.Filters
@@ -0,0 +1,54 @@
+<?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>{10F00C97-F803-43B8-994A-022AE3AA52E4}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ <UniqueIdentifier>{0422AF40-0146-47B2-BF48-C80A11C4F7F2}</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>{1F07CF73-346E-4FF4-80B6-BC92C1A72B62}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="BitmapHandler.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="dllentry.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="Exception.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="omconvertor.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="precompsrc.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="PThandler.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="rasinterface.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="WppTrace.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="xpsrasfilter.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <None Include="xpsrasfilter.def">
+ <Filter>Source Files</Filter>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="xpsrasfilter.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file