diff --git a/dlls/xmllite/reader.c b/dlls/xmllite/reader.c index f74b8156ede..6e51d5efe4b 100644 --- a/dlls/xmllite/reader.c +++ b/dlls/xmllite/reader.c @@ -38,13 +38,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(xmllite); /* not defined in public headers */ DEFINE_GUID(IID_IXmlReaderInput, 0x0b3ccc9b, 0x9214, 0x428b, 0xa2, 0xae, 0xef, 0x3a, 0xa8, 0x71, 0xaf, 0xda); -typedef enum -{ - XmlEncoding_UTF16, - XmlEncoding_UTF8, - XmlEncoding_Unknown -} xml_encoding; - typedef enum { XmlReadInState_Initial, @@ -265,14 +258,6 @@ static inline xmlreaderinput *impl_from_IXmlReaderInput(IXmlReaderInput *iface) return CONTAINING_RECORD(iface, xmlreaderinput, IXmlReaderInput_iface); } -static inline void *m_alloc(IMalloc *imalloc, size_t len) -{ - if (imalloc) - return IMalloc_Alloc(imalloc, len); - else - return heap_alloc(len); -} - static inline void *m_realloc(IMalloc *imalloc, void *mem, size_t len) { if (imalloc) @@ -281,14 +266,6 @@ static inline void *m_realloc(IMalloc *imalloc, void *mem, size_t len) return heap_realloc(mem, len); } -static inline void m_free(IMalloc *imalloc, void *mem) -{ - if (imalloc) - IMalloc_Free(imalloc, mem); - else - heap_free(mem); -} - /* reader memory allocation functions */ static inline void *reader_alloc(xmlreader *reader, size_t len) { @@ -590,7 +567,7 @@ static HRESULT get_code_page(xml_encoding encoding, UINT *cp) return S_OK; } -static xml_encoding parse_encoding_name(const WCHAR *name, int len) +xml_encoding parse_encoding_name(const WCHAR *name, int len) { int min, max, n, c; diff --git a/dlls/xmllite/tests/writer.c b/dlls/xmllite/tests/writer.c index 5f3d51104d3..f182aebe3ce 100644 --- a/dlls/xmllite/tests/writer.c +++ b/dlls/xmllite/tests/writer.c @@ -28,7 +28,44 @@ #include "xmllite.h" #include "wine/test.h" +#include "initguid.h" +DEFINE_GUID(IID_IXmlWriterOutput, 0xc1131708, 0x0f59, 0x477f, 0x93, 0x59, 0x7d, 0x33, 0x24, 0x51, 0xbc, 0x1a); + static HRESULT (WINAPI *pCreateXmlWriter)(REFIID riid, void **ppvObject, IMalloc *pMalloc); +static HRESULT (WINAPI *pCreateXmlWriterOutputWithEncodingName)(IUnknown *stream, + IMalloc *imalloc, + LPCWSTR encoding_name, + IXmlWriterOutput **output); + +static HRESULT WINAPI testoutput_QueryInterface(IUnknown *iface, REFIID riid, void **obj) +{ + if (IsEqualGUID(riid, &IID_IUnknown)) { + *obj = iface; + return S_OK; + } + else { + ok(0, "unknown riid=%s\n", wine_dbgstr_guid(riid)); + return E_NOINTERFACE; + } +} + +static ULONG WINAPI testoutput_AddRef(IUnknown *iface) +{ + return 2; +} + +static ULONG WINAPI testoutput_Release(IUnknown *iface) +{ + return 1; +} + +static const IUnknownVtbl testoutputvtbl = { + testoutput_QueryInterface, + testoutput_AddRef, + testoutput_Release +}; + +static IUnknown testoutput = { &testoutputvtbl }; static void test_writer_create(void) { @@ -44,10 +81,7 @@ static void test_writer_create(void) hr = pCreateXmlWriter(&IID_IXmlWriter, (LPVOID*)&writer, NULL); ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); - if(hr == S_OK) - { - IXmlWriter_Release(writer); - } + IXmlWriter_Release(writer); } static BOOL init_pointers(void) @@ -63,15 +97,34 @@ static BOOL init_pointers(void) #define MAKEFUNC(f) if (!(p##f = (void*)GetProcAddress(mod, #f))) return FALSE; MAKEFUNC(CreateXmlWriter); + MAKEFUNC(CreateXmlWriterOutputWithEncodingName); #undef MAKEFUNC return TRUE; } +static void test_writeroutput(void) +{ + static const WCHAR utf16W[] = {'u','t','f','-','1','6',0}; + IXmlWriterOutput *output; + IUnknown *unk; + HRESULT hr; + + hr = pCreateXmlWriterOutputWithEncodingName(&testoutput, NULL, utf16W, &output); + ok(hr == S_OK, "got %08x\n", hr); + unk = NULL; + hr = IUnknown_QueryInterface(output, &IID_IXmlWriterOutput, (void**)&unk); + ok(hr == S_OK, "got %08x\n", hr); + ok(unk != NULL, "got %p\n", unk); + /* releasing 'unk' crashes on native */ + IUnknown_Release(output); +} + START_TEST(writer) { if (!init_pointers()) return; test_writer_create(); + test_writeroutput(); } diff --git a/dlls/xmllite/writer.c b/dlls/xmllite/writer.c index f60e0d965ab..a0e2703e781 100644 --- a/dlls/xmllite/writer.c +++ b/dlls/xmllite/writer.c @@ -24,11 +24,25 @@ #include "winbase.h" #include "objbase.h" #include "xmllite.h" +#include "xmllite_private.h" +#include "initguid.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(xmllite); +/* not defined in public headers */ +DEFINE_GUID(IID_IXmlWriterOutput, 0xc1131708, 0x0f59, 0x477f, 0x93, 0x59, 0x7d, 0x33, 0x24, 0x51, 0xbc, 0x1a); + +typedef struct +{ + IXmlWriterOutput IXmlWriterOutput_iface; + LONG ref; + IUnknown *output; + IMalloc *imalloc; + xml_encoding encoding; +} xmlwriteroutput; + typedef struct _xmlwriter { IXmlWriter IXmlWriter_iface; @@ -40,6 +54,22 @@ static inline xmlwriter *impl_from_IXmlWriter(IXmlWriter *iface) return CONTAINING_RECORD(iface, xmlwriter, IXmlWriter_iface); } +static inline xmlwriteroutput *impl_from_IXmlWriterOutput(IXmlWriterOutput *iface) +{ + return CONTAINING_RECORD(iface, xmlwriteroutput, IXmlWriterOutput_iface); +} + +/* reader input memory allocation functions */ +static inline void *writeroutput_alloc(xmlwriteroutput *output, size_t len) +{ + return m_alloc(output->imalloc, len); +} + +static inline void writeroutput_free(xmlwriteroutput *output, void *mem) +{ + m_free(output->imalloc, mem); +} + static HRESULT WINAPI xmlwriter_QueryInterface(IXmlWriter *iface, REFIID riid, void **ppvObject) { xmlwriter *This = impl_from_IXmlWriter(iface); @@ -73,9 +103,7 @@ static ULONG WINAPI xmlwriter_Release(IXmlWriter *iface) ref = InterlockedDecrement(&This->ref); if (ref == 0) - { - HeapFree(GetProcessHeap(), 0, This); - } + heap_free(This); return ref; } @@ -385,6 +413,63 @@ static const struct IXmlWriterVtbl xmlwriter_vtbl = xmlwriter_Flush }; +/** IXmlWriterOutput **/ +static HRESULT WINAPI xmlwriteroutput_QueryInterface(IXmlWriterOutput *iface, REFIID riid, void** ppvObject) +{ + xmlwriteroutput *This = impl_from_IXmlWriterOutput(iface); + + TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject); + + if (IsEqualGUID(riid, &IID_IXmlWriterOutput) || + IsEqualGUID(riid, &IID_IUnknown)) + { + *ppvObject = iface; + } + else + { + WARN("interface %s not implemented\n", debugstr_guid(riid)); + *ppvObject = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef(iface); + + return S_OK; +} + +static ULONG WINAPI xmlwriteroutput_AddRef(IXmlWriterOutput *iface) +{ + xmlwriteroutput *This = impl_from_IXmlWriterOutput(iface); + ULONG ref = InterlockedIncrement(&This->ref); + TRACE("(%p)->(%d)\n", This, ref); + return ref; +} + +static ULONG WINAPI xmlwriteroutput_Release(IXmlWriterOutput *iface) +{ + xmlwriteroutput *This = impl_from_IXmlWriterOutput(iface); + LONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p)->(%d)\n", This, ref); + + if (ref == 0) + { + IMalloc *imalloc = This->imalloc; + if (This->output) IUnknown_Release(This->output); + writeroutput_free(This, This); + if (imalloc) IMalloc_Release(imalloc); + } + + return ref; +} + +static const struct IUnknownVtbl xmlwriteroutputvtbl = +{ + xmlwriteroutput_QueryInterface, + xmlwriteroutput_AddRef, + xmlwriteroutput_Release +}; + HRESULT WINAPI CreateXmlWriter(REFIID riid, void **pObject, IMalloc *pMalloc) { xmlwriter *writer; @@ -399,7 +484,7 @@ HRESULT WINAPI CreateXmlWriter(REFIID riid, void **pObject, IMalloc *pMalloc) return E_FAIL; } - writer = HeapAlloc(GetProcessHeap(), 0, sizeof (*writer)); + writer = heap_alloc(sizeof(*writer)); if(!writer) return E_OUTOFMEMORY; writer->IXmlWriter_iface.lpVtbl = &xmlwriter_vtbl; @@ -411,3 +496,35 @@ HRESULT WINAPI CreateXmlWriter(REFIID riid, void **pObject, IMalloc *pMalloc) return S_OK; } + +HRESULT WINAPI CreateXmlWriterOutputWithEncodingName(IUnknown *stream, + IMalloc *imalloc, + LPCWSTR encoding, + IXmlWriterOutput **output) +{ + xmlwriteroutput *writeroutput; + + TRACE("%p %p %s %p\n", stream, imalloc, debugstr_w(encoding), output); + + if (!stream || !output) return E_INVALIDARG; + + if (imalloc) + writeroutput = IMalloc_Alloc(imalloc, sizeof(*writeroutput)); + else + writeroutput = heap_alloc(sizeof(*writeroutput)); + if(!writeroutput) return E_OUTOFMEMORY; + + writeroutput->IXmlWriterOutput_iface.lpVtbl = &xmlwriteroutputvtbl; + writeroutput->ref = 1; + writeroutput->imalloc = imalloc; + if (imalloc) IMalloc_AddRef(imalloc); + writeroutput->encoding = parse_encoding_name(encoding, -1); + + IUnknown_QueryInterface(stream, &IID_IUnknown, (void**)&writeroutput->output); + + *output = &writeroutput->IXmlWriterOutput_iface; + + TRACE("returning iface %p\n", *output); + + return S_OK; +} diff --git a/dlls/xmllite/xmllite.spec b/dlls/xmllite/xmllite.spec index 30b02aae9ef..295bff6381c 100644 --- a/dlls/xmllite/xmllite.spec +++ b/dlls/xmllite/xmllite.spec @@ -3,4 +3,4 @@ @ stdcall CreateXmlReaderInputWithEncodingName(ptr ptr ptr long ptr ptr) @ stdcall CreateXmlWriter(ptr ptr ptr) @ stub CreateXmlWriterOutputWithEncodingCodePage -@ stub CreateXmlWriterOutputWithEncodingName +@ stdcall CreateXmlWriterOutputWithEncodingName(ptr ptr wstr ptr) diff --git a/dlls/xmllite/xmllite_private.h b/dlls/xmllite/xmllite_private.h index 97993e10b6e..96a78fadc02 100644 --- a/dlls/xmllite/xmllite_private.h +++ b/dlls/xmllite/xmllite_private.h @@ -37,4 +37,29 @@ static inline BOOL heap_free(void *mem) return HeapFree(GetProcessHeap(), 0, mem); } +static inline void *m_alloc(IMalloc *imalloc, size_t len) +{ + if (imalloc) + return IMalloc_Alloc(imalloc, len); + else + return heap_alloc(len); +} + +static inline void m_free(IMalloc *imalloc, void *mem) +{ + if (imalloc) + IMalloc_Free(imalloc, mem); + else + heap_free(mem); +} + +typedef enum +{ + XmlEncoding_UTF16, + XmlEncoding_UTF8, + XmlEncoding_Unknown +} xml_encoding; + +xml_encoding parse_encoding_name(const WCHAR *name, int len) DECLSPEC_HIDDEN; + #endif /* __XMLLITE_PRIVATE__ */ diff --git a/include/xmllite.idl b/include/xmllite.idl index 7547d1ac194..5dc0012aaa0 100644 --- a/include/xmllite.idl +++ b/include/xmllite.idl @@ -293,3 +293,10 @@ interface IXmlWriter : IUnknown HRESULT WriteWhitespace([in] LPCWSTR pwszWhitespace); HRESULT Flush(); } + +/* IXmlWriter construction */ +cpp_quote("STDAPI CreateXmlWriter(REFIID riid, void **ppvObject, IMalloc *pMalloc);") + +cpp_quote("typedef IUnknown IXmlWriterOutput;") +cpp_quote("STDAPI CreateXmlWriterOutputWithEncodingName(IUnknown *stream, IMalloc *pMalloc,") +cpp_quote(" LPCWSTR encoding, IXmlWriterOutput **output);")