[PATCH v2 01/12] prntvpt: Implement PTConvertDevModeToPrintTicket.
Dmitry Timoshkov
dmitry at baikal.ru
Wed Jun 17 00:21:55 CDT 2020
v2: Split into smaller parts.
Signed-off-by: Dmitry Timoshkov <dmitry at baikal.ru>
---
dlls/prntvpt/prntvpt.spec | 2 +-
dlls/prntvpt/ticket.c | 318 ++++++++++++++++++++++++++++++++++++++
include/prntvpt.h | 1 +
3 files changed, 320 insertions(+), 1 deletion(-)
diff --git a/dlls/prntvpt/prntvpt.spec b/dlls/prntvpt/prntvpt.spec
index ce8a0e591c..bae26fab9d 100644
--- a/dlls/prntvpt/prntvpt.spec
+++ b/dlls/prntvpt/prntvpt.spec
@@ -6,7 +6,7 @@
@ stub PTGetPrintCapabilities
@ stub PTMergeAndValidatePrintTicket
@ stdcall PTConvertPrintTicketToDevMode(ptr ptr long long ptr ptr ptr)
-@ stub PTConvertDevModeToPrintTicket
+@ stdcall PTConvertDevModeToPrintTicket(ptr long ptr long ptr)
@ stdcall PTReleaseMemory(ptr)
@ stub ConvertDevModeToPrintTicketThunk2
@ stub ConvertDevModeToPrintTicketThunk
diff --git a/dlls/prntvpt/ticket.c b/dlls/prntvpt/ticket.c
index 36e343bbf2..548da5977c 100644
--- a/dlls/prntvpt/ticket.c
+++ b/dlls/prntvpt/ticket.c
@@ -102,6 +102,18 @@ static int media_to_paper(const WCHAR *name)
return DMPAPER_A4;
}
+static const WCHAR *paper_to_media(int paper)
+{
+ int i;
+
+ for (i = 0 ; i < ARRAY_SIZE(psk_media); i++)
+ if (psk_media[i].paper == paper)
+ return psk_media[i].name;
+
+ FIXME("%d\n", paper);
+ return psk_media[0].name;
+}
+
static BOOL is_valid_node_name(const WCHAR *name)
{
static const WCHAR * const psf_names[] = { L"psf:ParameterInit", L"psf:Feature" };
@@ -693,3 +705,309 @@ HRESULT WINAPI PTConvertPrintTicketToDevMode(HPTPROVIDER provider, IStream *stre
return S_OK;
}
+
+static void devmode_to_ticket(const DEVMODEW *dm, struct ticket *ticket)
+{
+ if (dm->dmFields & DM_ORIENTATION)
+ ticket->page.orientation = dm->u1.s1.dmOrientation;
+ if (dm->dmFields & DM_PAPERSIZE)
+ ticket->page.media.paper = dm->u1.s1.dmPaperSize;
+ if (dm->dmFields & DM_PAPERLENGTH)
+ ticket->page.media.size.width = dm->u1.s1.dmPaperWidth * 100;
+ if (dm->dmFields & DM_PAPERWIDTH)
+ ticket->page.media.size.height = dm->u1.s1.dmPaperLength * 100;
+ if (dm->dmFields & DM_SCALE)
+ ticket->page.scaling = dm->u1.s1.dmScale;
+ if (dm->dmFields & DM_COPIES)
+ ticket->job.copies = dm->u1.s1.dmCopies;
+ if (dm->dmFields & DM_COLOR)
+ ticket->page.color = dm->dmColor;
+ if (dm->dmFields & DM_PRINTQUALITY)
+ {
+ ticket->page.resolution.x = dm->u1.s1.dmPrintQuality;
+ ticket->page.resolution.y = dm->u1.s1.dmPrintQuality;
+ }
+ if (dm->dmFields & DM_YRESOLUTION)
+ ticket->page.resolution.y = dm->dmYResolution;
+ if (dm->dmFields & DM_LOGPIXELS)
+ {
+ ticket->page.resolution.x = dm->dmLogPixels;
+ ticket->page.resolution.y = dm->dmLogPixels;
+ }
+ if (dm->dmFields & DM_COLLATE)
+ ticket->document.collate = dm->dmCollate;
+}
+
+static HRESULT add_attribute(IXMLDOMElement *element, const WCHAR *attr, const WCHAR *value)
+{
+ VARIANT var;
+ BSTR name;
+ HRESULT hr;
+
+ name = SysAllocString(attr);
+ V_VT(&var) = VT_BSTR;
+ V_BSTR(&var) = SysAllocString(value);
+
+ hr = IXMLDOMElement_setAttribute(element, name, var);
+
+ SysFreeString(name);
+ SysFreeString(V_BSTR(&var));
+
+ return hr;
+}
+
+static HRESULT create_element(IXMLDOMElement *root, const WCHAR *name, IXMLDOMElement **child)
+{
+ IXMLDOMDocument *doc;
+ HRESULT hr;
+
+ hr = IXMLDOMElement_get_ownerDocument(root, &doc);
+ if (hr != S_OK) return hr;
+
+ hr = IXMLDOMDocument_createElement(doc, (BSTR)name, child);
+ if (hr == S_OK)
+ hr = IXMLDOMElement_appendChild(root, (IXMLDOMNode *)*child, NULL);
+
+ IXMLDOMDocument_Release(doc);
+ return hr;
+}
+
+static HRESULT write_int_value(IXMLDOMElement *root, int value)
+{
+ HRESULT hr;
+ IXMLDOMElement *child;
+ VARIANT var;
+
+ hr = create_element(root, L"psf:Value", &child);
+ if (hr != S_OK) return hr;
+
+ hr = add_attribute(child, L"xsi:type", L"xsd:integer");
+ if (hr != S_OK) return hr;
+
+ V_VT(&var) = VT_I4;
+ V_I4(&var) = value;
+ hr = IXMLDOMElement_put_nodeTypedValue(child, var);
+
+ IXMLDOMElement_Release(child);
+ return hr;
+}
+
+static HRESULT create_Feature(IXMLDOMElement *root, const WCHAR *name, IXMLDOMElement **child)
+{
+ HRESULT hr;
+
+ hr = create_element(root, L"psf:Feature", child);
+ if (hr != S_OK) return hr;
+
+ return add_attribute(*child, L"name", name);
+}
+
+static HRESULT create_Option(IXMLDOMElement *root, const WCHAR *name, IXMLDOMElement **child)
+{
+ HRESULT hr;
+
+ hr = create_element(root, L"psf:Option", child);
+ if (hr != S_OK) return hr;
+
+ if (name)
+ hr = add_attribute(*child, L"name", name);
+
+ return hr;
+}
+
+static HRESULT create_ScoredProperty(IXMLDOMElement *root, const WCHAR *name, IXMLDOMElement **child)
+{
+ HRESULT hr;
+
+ hr = create_element(root, L"psf:ScoredProperty", child);
+ if (hr != S_OK) return hr;
+
+ return add_attribute(*child, L"name", name);
+}
+
+static HRESULT write_PageMediaSize(IXMLDOMElement *root, const struct ticket *ticket)
+{
+ IXMLDOMElement *feature, *option = NULL, *property;
+ HRESULT hr;
+
+ hr = create_Feature(root, L"psk:PageMediaSize", &feature);
+ if (hr != S_OK) return hr;
+
+ hr = create_Option(feature, paper_to_media(ticket->page.media.paper), &option);
+ if (hr != S_OK) goto fail;
+
+ hr = create_ScoredProperty(option, L"psk:MediaSizeWidth", &property);
+ if (hr != S_OK) goto fail;
+ hr = write_int_value(property, ticket->page.media.size.width);
+ IXMLDOMElement_Release(property);
+ if (hr != S_OK) goto fail;
+
+ hr = create_ScoredProperty(option, L"psk:MediaSizeHeight", &property);
+ if (hr != S_OK) goto fail;
+ hr = write_int_value(property, ticket->page.media.size.height);
+ IXMLDOMElement_Release(property);
+
+fail:
+ if (option) IXMLDOMElement_Release(option);
+ IXMLDOMElement_Release(feature);
+ return hr;
+}
+
+static HRESULT write_attributes(IXMLDOMElement *element)
+{
+ HRESULT hr;
+
+ hr = add_attribute(element, L"xmlns:psf", L"http://schemas.microsoft.com/windows/2003/08/printing/printschemaframework");
+ if (hr != S_OK) return hr;
+ hr = add_attribute(element, L"xmlns:psk", L"http://schemas.microsoft.com/windows/2003/08/printing/printschemakeywords");
+ if (hr != S_OK) return hr;
+ hr = add_attribute(element, L"xmlns:xsi", L"http://www.w3.org/2001/XMLSchema-instance");
+ if (hr != S_OK) return hr;
+ hr = add_attribute(element, L"xmlns:xsd", L"http://www.w3.org/2001/XMLSchema");
+ if (hr != S_OK) return hr;
+
+ return add_attribute(element, L"version", L"1");
+}
+
+static HRESULT write_ticket(IStream *stream, const struct ticket *ticket, EPrintTicketScope scope)
+{
+ static const char xmldecl[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n";
+ HRESULT hr;
+ IXMLDOMDocument *doc;
+ IXMLDOMElement *root = NULL;
+ VARIANT var;
+
+ hr = CoCreateInstance(&CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER,
+ &IID_IXMLDOMDocument, (void **)&doc);
+ if (hr != S_OK) return hr;
+
+ hr = IXMLDOMDocument_createElement(doc, (BSTR)L"psf:PrintTicket", &root);
+ if (hr != S_OK) goto fail;
+
+ hr = IXMLDOMDocument_appendChild(doc, (IXMLDOMNode *)root, NULL);
+ if (hr != S_OK) goto fail;
+
+ hr = write_attributes(root);
+ if (hr != S_OK) goto fail;
+
+ hr = write_PageMediaSize(root, ticket);
+ if (hr != S_OK) goto fail;
+
+ hr = IStream_Write(stream, xmldecl, strlen(xmldecl), NULL);
+ if (hr != S_OK) goto fail;
+
+ V_VT(&var) = VT_UNKNOWN;
+ V_UNKNOWN(&var) = (IUnknown *)stream;
+ hr = IXMLDOMDocument_save(doc, var);
+
+fail:
+ if (root) IXMLDOMElement_Release(root);
+ IXMLDOMDocument_Release(doc);
+ return hr;
+}
+
+static void dump_fields(DWORD fields)
+{
+ int add_space = 0;
+
+#define CHECK_FIELD(flag) \
+do \
+{ \
+ if (fields & flag) \
+ { \
+ if (add_space++) TRACE(" "); \
+ TRACE(#flag); \
+ fields &= ~flag; \
+ } \
+} \
+while (0)
+
+ CHECK_FIELD(DM_ORIENTATION);
+ CHECK_FIELD(DM_PAPERSIZE);
+ CHECK_FIELD(DM_PAPERLENGTH);
+ CHECK_FIELD(DM_PAPERWIDTH);
+ CHECK_FIELD(DM_SCALE);
+ CHECK_FIELD(DM_POSITION);
+ CHECK_FIELD(DM_NUP);
+ CHECK_FIELD(DM_DISPLAYORIENTATION);
+ CHECK_FIELD(DM_COPIES);
+ CHECK_FIELD(DM_DEFAULTSOURCE);
+ CHECK_FIELD(DM_PRINTQUALITY);
+ CHECK_FIELD(DM_COLOR);
+ CHECK_FIELD(DM_DUPLEX);
+ CHECK_FIELD(DM_YRESOLUTION);
+ CHECK_FIELD(DM_TTOPTION);
+ CHECK_FIELD(DM_COLLATE);
+ CHECK_FIELD(DM_FORMNAME);
+ CHECK_FIELD(DM_LOGPIXELS);
+ CHECK_FIELD(DM_BITSPERPEL);
+ CHECK_FIELD(DM_PELSWIDTH);
+ CHECK_FIELD(DM_PELSHEIGHT);
+ CHECK_FIELD(DM_DISPLAYFLAGS);
+ CHECK_FIELD(DM_DISPLAYFREQUENCY);
+ CHECK_FIELD(DM_ICMMETHOD);
+ CHECK_FIELD(DM_ICMINTENT);
+ CHECK_FIELD(DM_MEDIATYPE);
+ CHECK_FIELD(DM_DITHERTYPE);
+ CHECK_FIELD(DM_PANNINGWIDTH);
+ CHECK_FIELD(DM_PANNINGHEIGHT);
+ if (fields) TRACE(" %#x", fields);
+ TRACE("\n");
+#undef CHECK_FIELD
+}
+
+/* Dump DEVMODE structure without a device specific part.
+ * Some applications and drivers fail to specify correct field
+ * flags (like DM_FORMNAME), so dump everything.
+ */
+static void dump_devmode(const DEVMODEW *dm)
+{
+ if (!TRACE_ON(prntvpt)) return;
+
+ TRACE("dmDeviceName: %s\n", debugstr_w(dm->dmDeviceName));
+ TRACE("dmSpecVersion: 0x%04x\n", dm->dmSpecVersion);
+ TRACE("dmDriverVersion: 0x%04x\n", dm->dmDriverVersion);
+ TRACE("dmSize: 0x%04x\n", dm->dmSize);
+ TRACE("dmDriverExtra: 0x%04x\n", dm->dmDriverExtra);
+ TRACE("dmFields: 0x%04x\n", dm->dmFields);
+ dump_fields(dm->dmFields);
+ TRACE("dmOrientation: %d\n", dm->u1.s1.dmOrientation);
+ TRACE("dmPaperSize: %d\n", dm->u1.s1.dmPaperSize);
+ TRACE("dmPaperLength: %d\n", dm->u1.s1.dmPaperLength);
+ TRACE("dmPaperWidth: %d\n", dm->u1.s1.dmPaperWidth);
+ TRACE("dmScale: %d\n", dm->u1.s1.dmScale);
+ TRACE("dmCopies: %d\n", dm->u1.s1.dmCopies);
+ TRACE("dmDefaultSource: %d\n", dm->u1.s1.dmDefaultSource);
+ TRACE("dmPrintQuality: %d\n", dm->u1.s1.dmPrintQuality);
+ TRACE("dmColor: %d\n", dm->dmColor);
+ TRACE("dmDuplex: %d\n", dm->dmDuplex);
+ TRACE("dmYResolution: %d\n", dm->dmYResolution);
+ TRACE("dmTTOption: %d\n", dm->dmTTOption);
+ TRACE("dmCollate: %d\n", dm->dmCollate);
+ TRACE("dmFormName: %s\n", debugstr_w(dm->dmFormName));
+ TRACE("dmLogPixels %u\n", dm->dmLogPixels);
+ TRACE("dmBitsPerPel %u\n", dm->dmBitsPerPel);
+ TRACE("dmPelsWidth %u\n", dm->dmPelsWidth);
+ TRACE("dmPelsHeight %u\n", dm->dmPelsHeight);
+}
+
+HRESULT WINAPI PTConvertDevModeToPrintTicket(HPTPROVIDER provider, ULONG size, PDEVMODEW dm,
+ EPrintTicketScope scope, IStream *stream)
+{
+ struct ticket ticket;
+
+ TRACE("%p,%u,%p,%d,%p\n", provider, size, dm, scope, stream);
+
+ if (!provider || !dm || !stream)
+ return E_INVALIDARG;
+
+ dump_devmode(dm);
+
+ if (!IsValidDevmodeW(dm, size))
+ return E_INVALIDARG;
+
+ initialize_ticket(&ticket);
+ devmode_to_ticket(dm, &ticket);
+
+ return write_ticket(stream, &ticket, scope);
+}
diff --git a/include/prntvpt.h b/include/prntvpt.h
index e1855badd1..f1d7edc350 100644
--- a/include/prntvpt.h
+++ b/include/prntvpt.h
@@ -43,6 +43,7 @@ typedef enum
HRESULT WINAPI PTOpenProvider(const WCHAR *printer, DWORD version, HPTPROVIDER *provider);
HRESULT WINAPI PTOpenProviderEx(const WCHAR *printer, DWORD max_version, DWORD pref_version, HPTPROVIDER *provider, DWORD *used_version);
HRESULT WINAPI PTCloseProvider(HPTPROVIDER);
+HRESULT WINAPI PTConvertDevModeToPrintTicket(HPTPROVIDER, ULONG, PDEVMODEW, EPrintTicketScope, IStream *);
HRESULT WINAPI PTConvertPrintTicketToDevMode(HPTPROVIDER, IStream *, EDefaultDevmodeType, EPrintTicketScope, ULONG *, PDEVMODEW *, BSTR *);
HRESULT WINAPI PTReleaseMemory(PVOID);
--
2.26.2
More information about the wine-devel
mailing list