Author: akhaldi
Date: Sun Mar 5 21:33:13 2017
New Revision: 74105
URL:
http://svn.reactos.org/svn/reactos?rev=74105&view=rev
Log:
[INETCOMM] Sync with Wine Staging 2.2. CORE-12823
51e1a08 inetcomm: Return S_FALSE if no data is returned in IInternetProtocol::Read.
0672bfa inetcomm: Added support for decoding quoted-printable data.
07af9d0 inetcomm: Added mhtml binding tests.
cf8e259 inetcomm: Added support for binding mhtml protocol handler.
3f644cb inetcomm: Added IInternetProtocolInfo::CombineUrl implementation.
37792a2 inetcomm: Added MimeOleObjectFromMoniker semi-stub implementation.
242cbb1 inetcomm: Added tests reading MHTML page as MIME message.
eb0bd22 inetcomm: Removed unneeded type check in init_content_type.
56dc246 inetcomm: Read content encoding from MIME header.
dec243f inetcomm: Don't include headers in data stream in create_sub_body.
3ccba10 inetcomm: Properly handle boundary in the beginning of body stream in
create_body_offset_list.
9c01a94 inetcomm: Use relative seek in copy_headers_to_buf.
915acd6 inetcomm: Added support for decoding base64 in IMimeBody::GetData.
0b80666 inetcomm: Return a new instance of stream in IMimeBody::GetData.
393512d inetcomm: Don't restore base stream position in sub stream Read.
bb5056e inetcomm: Moved sub_stream_t implementation before MimeBody implementation.
a1d0c6d inetcomm: Added COM aggregation support to MimeHtmlProtocol object.
fe3e5b9 inetcomm: Added IInternetProtocolInfo stub implementation.
6832273 inetcomm: Added MimeHtmlProtocol stub implementation.
d5d9aa3 inetcomm: Register mhtml protocol handler.
Added:
trunk/reactos/dll/win32/inetcomm/inetcomm_r.rgs
- copied, changed from r74104, trunk/reactos/dll/win32/inetcomm/inetcomm.rgs
trunk/reactos/dll/win32/inetcomm/protocol.c (with props)
Removed:
trunk/reactos/dll/win32/inetcomm/inetcomm.rgs
Modified:
trunk/reactos/dll/win32/inetcomm/CMakeLists.txt
trunk/reactos/dll/win32/inetcomm/inetcomm.idl
trunk/reactos/dll/win32/inetcomm/inetcomm.rc
trunk/reactos/dll/win32/inetcomm/inetcomm_main.c
trunk/reactos/dll/win32/inetcomm/inetcomm_private.h
trunk/reactos/dll/win32/inetcomm/mimeole.c
trunk/reactos/media/doc/README.WINE
Modified: trunk/reactos/dll/win32/inetcomm/CMakeLists.txt
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/inetcomm/CMakeLi…
==============================================================================
--- trunk/reactos/dll/win32/inetcomm/CMakeLists.txt [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/inetcomm/CMakeLists.txt [iso-8859-1] Sun Mar 5 21:33:13 2017
@@ -10,6 +10,7 @@
mimeintl.c
mimeole.c
pop3transport.c
+ protocol.c
smtptransport.c
inetcomm_private.h)
@@ -22,6 +23,6 @@
set_module_type(inetcomm win32dll)
target_link_libraries(inetcomm uuid wine)
-add_importlibs(inetcomm ole32 oleaut32 ws2_32 user32 propsys msvcrt kernel32 ntdll)
+add_importlibs(inetcomm ole32 oleaut32 ws2_32 user32 propsys urlmon msvcrt kernel32
ntdll)
add_pch(inetcomm inetcomm_private.h SOURCE)
add_cd_file(TARGET inetcomm DESTINATION reactos/system32 FOR all)
Modified: trunk/reactos/dll/win32/inetcomm/inetcomm.idl
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/inetcomm/inetcom…
==============================================================================
--- trunk/reactos/dll/win32/inetcomm/inetcomm.idl [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/inetcomm/inetcomm.idl [iso-8859-1] Sun Mar 5 21:33:13 2017
@@ -124,3 +124,10 @@
uuid(ea678830-235d-11d2-a8b6-0000f8084f96)
]
coclass IPropPatchRequest { interface IPropPatchRequest; }
+
+[
+ helpstring("MHTML Asynchronous Pluggable Protocol Handler"),
+ threading(both),
+ uuid(05300401-bcbc-11d0-85e3-00c04fd85ab4)
+]
+coclass MimeHtmlProtocol { interface IInternetProtocol; }
Modified: trunk/reactos/dll/win32/inetcomm/inetcomm.rc
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/inetcomm/inetcom…
==============================================================================
--- trunk/reactos/dll/win32/inetcomm/inetcomm.rc [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/inetcomm/inetcomm.rc [iso-8859-1] Sun Mar 5 21:33:13 2017
@@ -1 +1,22 @@
-1 WINE_REGISTRY "inetcomm.rgs"
+/*
+ * Copyright 2016 Jacek Caban for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/* @makedep: inetcomm.rgs */
+1 WINE_REGISTRY inetcomm.rgs
+
+2 WINE_REGISTRY inetcomm_r.rgs
Removed: trunk/reactos/dll/win32/inetcomm/inetcomm.rgs
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/inetcomm/inetcom…
==============================================================================
--- trunk/reactos/dll/win32/inetcomm/inetcomm.rgs [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/inetcomm/inetcomm.rgs (removed)
@@ -1,69 +0,0 @@
-HKCR
-{
- NoRemove Interface
- {
- }
- NoRemove CLSID
- {
- '{FD853CDB-7F86-11D0-8252-00C04FD85AB4}' = s 'CLSID_IMimeBody'
- {
- InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both'
}
- }
- '{FD853CDD-7F86-11D0-8252-00C04FD85AB4}' = s
'CLSID_IMimeAllocator'
- {
- InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both'
}
- }
- '{FD853CDE-7F86-11D0-8252-00C04FD85AB4}' = s
'CLSID_IMimeSecurity'
- {
- InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both'
}
- }
- '{FD853CDF-7F86-11D0-8252-00C04FD85AB4}' = s
'CLSID_IVirtualStream'
- {
- InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both'
}
- }
- '{FD853CE3-7F86-11D0-8252-00C04FD85AB4}' = s
'CLSID_IMimeMessage'
- {
- InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both'
}
- }
- '{FD853CE6-7F86-11D0-8252-00C04FD85AB4}' = s
'CLSID_ISMTPTransport'
- {
- InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both'
}
- }
- '{FD853CE7-7F86-11D0-8252-00C04FD85AB4}' = s
'CLSID_IPOP3Transport'
- {
- InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both'
}
- }
- '{FD853CE8-7F86-11D0-8252-00C04FD85AB4}' = s
'CLSID_INNTPTransport'
- {
- InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both'
}
- }
- '{FD853CE9-7F86-11D0-8252-00C04FD85AB4}' = s
'CLSID_IRASTransport'
- {
- InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both'
}
- }
- '{FD853CEA-7F86-11D0-8252-00C04FD85AB4}' = s 'CLSID_IRangeList'
- {
- InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both'
}
- }
- '{FD853CEB-7F86-11D0-8252-00C04FD85AB4}' = s
'CLSID_IIMAPTransport'
- {
- InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both'
}
- }
- '{5A580C11-E5EB-11D1-A86E-0000F8084F96}' = s
'CLSID_IHTTPMailTransport'
- {
- InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both'
}
- }
- '{0DF2C7EC-3435-11D0-81D0-00C04FD85AB4}' = s
'CLSID_ISMTPTransport2'
- {
- InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both'
}
- }
- '{BB847B8A-054A-11D2-A894-0000F8084F96}' = s
'CLSID_IPropFindRequest'
- {
- InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both'
}
- }
- '{EA678830-235D-11D2-A8B6-0000F8084F96}' = s
'CLSID_IPropPatchRequest'
- {
- InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both'
}
- }
- }
-}
Modified: trunk/reactos/dll/win32/inetcomm/inetcomm_main.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/inetcomm/inetcom…
==============================================================================
--- trunk/reactos/dll/win32/inetcomm/inetcomm_main.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/inetcomm/inetcomm_main.c [iso-8859-1] Sun Mar 5 21:33:13
2017
@@ -74,7 +74,9 @@
return S_OK;
}
- FIXME("interface %s not implemented\n", debugstr_guid(riid));
+ if (!IsEqualGUID(riid, &IID_IInternetProtocolInfo))
+ FIXME("interface %s not implemented\n", debugstr_guid(riid));
+ *ppobj = NULL;
return E_NOINTERFACE;
}
@@ -99,13 +101,20 @@
*ppobj = NULL;
+ if (pOuter && !IsEqualGUID(&IID_IUnknown, riid))
+ return CLASS_E_NOAGGREGATION;
+
r = This->create_object( pOuter, (LPVOID*) &punk );
if (FAILED(r))
return r;
+ if (IsEqualGUID(&IID_IUnknown, riid)) {
+ *ppobj = punk;
+ return S_OK;
+ }
+
r = IUnknown_QueryInterface( punk, riid, ppobj );
IUnknown_Release( punk );
-
return r;
}
@@ -129,6 +138,7 @@
static cf mime_message_cf = { { &cf_vtbl }, MimeMessage_create };
static cf mime_security_cf = { { &cf_vtbl }, MimeSecurity_create };
static cf virtual_stream_cf = { { &cf_vtbl }, VirtualStream_create };
+static cf mhtml_protocol_cf = { { &cf_vtbl }, MimeHtmlProtocol_create };
/***********************************************************************
* DllGetClassObject (INETCOMM.@)
@@ -171,6 +181,10 @@
{
cf = &virtual_stream_cf.IClassFactory_iface;
}
+ else if( IsEqualCLSID( rclsid, &CLSID_IMimeHtmlProtocol ))
+ {
+ cf = &mhtml_protocol_cf.IClassFactory_iface;
+ }
if ( !cf )
{
Modified: trunk/reactos/dll/win32/inetcomm/inetcomm_private.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/inetcomm/inetcom…
==============================================================================
--- trunk/reactos/dll/win32/inetcomm/inetcomm_private.h [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/inetcomm/inetcomm_private.h [iso-8859-1] Sun Mar 5 21:33:13
2017
@@ -38,6 +38,7 @@
#include <imnxport.h>
#include <wine/list.h>
+#include <wine/unicode.h>
#include <wine/debug.h>
WINE_DEFAULT_DEBUG_CHANNEL(inetcomm);
@@ -95,6 +96,7 @@
HRESULT MimeMessage_create(IUnknown *outer, void **obj) DECLSPEC_HIDDEN;
HRESULT MimeSecurity_create(IUnknown *outer, void **obj) DECLSPEC_HIDDEN;
HRESULT VirtualStream_create(IUnknown *outer, void **obj) DECLSPEC_HIDDEN;
+HRESULT MimeHtmlProtocol_create(IUnknown *outer, void **obj) DECLSPEC_HIDDEN;
HRESULT MimeInternational_Construct(IMimeInternational **internat) DECLSPEC_HIDDEN;
@@ -102,4 +104,14 @@
HRESULT IMAPTransportCF_Create(REFIID riid, LPVOID *ppv) DECLSPEC_HIDDEN;
HRESULT POP3TransportCF_Create(REFIID riid, LPVOID *ppv) DECLSPEC_HIDDEN;
+static inline void * __WINE_ALLOC_SIZE(1) heap_alloc(size_t len)
+{
+ return HeapAlloc(GetProcessHeap(), 0, len);
+}
+
+static inline BOOL heap_free(void *mem)
+{
+ return HeapFree(GetProcessHeap(), 0, mem);
+}
+
#endif /* _INETCOMM_PRIVATE_H_ */
Copied: trunk/reactos/dll/win32/inetcomm/inetcomm_r.rgs (from r74104,
trunk/reactos/dll/win32/inetcomm/inetcomm.rgs)
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/inetcomm/inetcom…
==============================================================================
--- trunk/reactos/dll/win32/inetcomm/inetcomm.rgs [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/inetcomm/inetcomm_r.rgs [iso-8859-1] Sun Mar 5 21:33:13 2017
@@ -65,5 +65,9 @@
{
InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both'
}
}
+ '{05300401-BCBC-11D0-85E3-00C04FD85AB4}' = s 'MHTML Asynchronous
Pluggable Protocol Handler'
+ {
+ InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both'
}
+ }
}
}
Modified: trunk/reactos/dll/win32/inetcomm/mimeole.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/inetcomm/mimeole…
==============================================================================
--- trunk/reactos/dll/win32/inetcomm/mimeole.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/inetcomm/mimeole.c [iso-8859-1] Sun Mar 5 21:33:13 2017
@@ -150,6 +150,298 @@
BODYOFFSETS body_offsets;
} MimeBody;
+typedef struct
+{
+ IStream IStream_iface;
+ LONG ref;
+ IStream *base;
+ ULARGE_INTEGER pos, start, length;
+} sub_stream_t;
+
+static inline sub_stream_t *impl_from_IStream(IStream *iface)
+{
+ return CONTAINING_RECORD(iface, sub_stream_t, IStream_iface);
+}
+
+static HRESULT WINAPI sub_stream_QueryInterface(IStream *iface, REFIID riid, void **ppv)
+{
+ sub_stream_t *This = impl_from_IStream(iface);
+
+ TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
+ *ppv = NULL;
+
+ if(IsEqualIID(riid, &IID_IUnknown) ||
+ IsEqualIID(riid, &IID_ISequentialStream) ||
+ IsEqualIID(riid, &IID_IStream))
+ {
+ IStream_AddRef(iface);
+ *ppv = iface;
+ return S_OK;
+ }
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI sub_stream_AddRef(IStream *iface)
+{
+ sub_stream_t *This = impl_from_IStream(iface);
+ LONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) ref=%d\n", This, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI sub_stream_Release(IStream *iface)
+{
+ sub_stream_t *This = impl_from_IStream(iface);
+ LONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p) ref=%d\n", This, ref);
+
+ if(!ref)
+ {
+ IStream_Release(This->base);
+ HeapFree(GetProcessHeap(), 0, This);
+ }
+ return ref;
+}
+
+static HRESULT WINAPI sub_stream_Read(
+ IStream* iface,
+ void *pv,
+ ULONG cb,
+ ULONG *pcbRead)
+{
+ sub_stream_t *This = impl_from_IStream(iface);
+ HRESULT hr;
+ LARGE_INTEGER tmp_pos;
+
+ TRACE("(%p, %d, %p)\n", pv, cb, pcbRead);
+
+ tmp_pos.QuadPart = This->pos.QuadPart + This->start.QuadPart;
+ IStream_Seek(This->base, tmp_pos, STREAM_SEEK_SET, NULL);
+
+ if(This->pos.QuadPart + cb > This->length.QuadPart)
+ cb = This->length.QuadPart - This->pos.QuadPart;
+
+ hr = IStream_Read(This->base, pv, cb, pcbRead);
+
+ This->pos.QuadPart += *pcbRead;
+
+ return hr;
+}
+
+static HRESULT WINAPI sub_stream_Write(
+ IStream* iface,
+ const void *pv,
+ ULONG cb,
+ ULONG *pcbWritten)
+{
+ FIXME("stub\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI sub_stream_Seek(
+ IStream* iface,
+ LARGE_INTEGER dlibMove,
+ DWORD dwOrigin,
+ ULARGE_INTEGER *plibNewPosition)
+{
+ sub_stream_t *This = impl_from_IStream(iface);
+ LARGE_INTEGER new_pos;
+
+ TRACE("(%08x.%08x, %x, %p)\n", dlibMove.u.HighPart, dlibMove.u.LowPart,
dwOrigin, plibNewPosition);
+
+ switch(dwOrigin)
+ {
+ case STREAM_SEEK_SET:
+ new_pos = dlibMove;
+ break;
+ case STREAM_SEEK_CUR:
+ new_pos.QuadPart = This->pos.QuadPart + dlibMove.QuadPart;
+ break;
+ case STREAM_SEEK_END:
+ new_pos.QuadPart = This->length.QuadPart + dlibMove.QuadPart;
+ break;
+ default:
+ return STG_E_INVALIDFUNCTION;
+ }
+
+ if(new_pos.QuadPart < 0) new_pos.QuadPart = 0;
+ else if(new_pos.QuadPart > This->length.QuadPart) new_pos.QuadPart =
This->length.QuadPart;
+
+ This->pos.QuadPart = new_pos.QuadPart;
+
+ if(plibNewPosition) *plibNewPosition = This->pos;
+ return S_OK;
+}
+
+static HRESULT WINAPI sub_stream_SetSize(
+ IStream* iface,
+ ULARGE_INTEGER libNewSize)
+{
+ FIXME("stub\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI sub_stream_CopyTo(
+ IStream* iface,
+ IStream *pstm,
+ ULARGE_INTEGER cb,
+ ULARGE_INTEGER *pcbRead,
+ ULARGE_INTEGER *pcbWritten)
+{
+ HRESULT hr = S_OK;
+ BYTE tmpBuffer[128];
+ ULONG bytesRead, bytesWritten, copySize;
+ ULARGE_INTEGER totalBytesRead;
+ ULARGE_INTEGER totalBytesWritten;
+
+ TRACE("(%p)->(%p, %d, %p, %p)\n", iface, pstm, cb.u.LowPart, pcbRead,
pcbWritten);
+
+ totalBytesRead.QuadPart = 0;
+ totalBytesWritten.QuadPart = 0;
+
+ while ( cb.QuadPart > 0 )
+ {
+ if ( cb.QuadPart >= sizeof(tmpBuffer) )
+ copySize = sizeof(tmpBuffer);
+ else
+ copySize = cb.u.LowPart;
+
+ hr = IStream_Read(iface, tmpBuffer, copySize, &bytesRead);
+ if (FAILED(hr)) break;
+
+ totalBytesRead.QuadPart += bytesRead;
+
+ if (bytesRead)
+ {
+ hr = IStream_Write(pstm, tmpBuffer, bytesRead, &bytesWritten);
+ if (FAILED(hr)) break;
+ totalBytesWritten.QuadPart += bytesWritten;
+ }
+
+ if (bytesRead != copySize)
+ cb.QuadPart = 0;
+ else
+ cb.QuadPart -= bytesRead;
+ }
+
+ if (pcbRead) pcbRead->QuadPart = totalBytesRead.QuadPart;
+ if (pcbWritten) pcbWritten->QuadPart = totalBytesWritten.QuadPart;
+
+ return hr;
+}
+
+static HRESULT WINAPI sub_stream_Commit(
+ IStream* iface,
+ DWORD grfCommitFlags)
+{
+ FIXME("stub\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI sub_stream_Revert(
+ IStream* iface)
+{
+ FIXME("stub\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI sub_stream_LockRegion(
+ IStream* iface,
+ ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType)
+{
+ FIXME("stub\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI sub_stream_UnlockRegion(
+ IStream* iface,
+ ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType)
+{
+ FIXME("stub\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI sub_stream_Stat(
+ IStream* iface,
+ STATSTG *pstatstg,
+ DWORD grfStatFlag)
+{
+ sub_stream_t *This = impl_from_IStream(iface);
+ FIXME("(%p)->(%p, %08x)\n", This, pstatstg, grfStatFlag);
+ memset(pstatstg, 0, sizeof(*pstatstg));
+ pstatstg->cbSize = This->length;
+ return S_OK;
+}
+
+static HRESULT WINAPI sub_stream_Clone(
+ IStream* iface,
+ IStream **ppstm)
+{
+ FIXME("stub\n");
+ return E_NOTIMPL;
+}
+
+static struct IStreamVtbl sub_stream_vtbl =
+{
+ sub_stream_QueryInterface,
+ sub_stream_AddRef,
+ sub_stream_Release,
+ sub_stream_Read,
+ sub_stream_Write,
+ sub_stream_Seek,
+ sub_stream_SetSize,
+ sub_stream_CopyTo,
+ sub_stream_Commit,
+ sub_stream_Revert,
+ sub_stream_LockRegion,
+ sub_stream_UnlockRegion,
+ sub_stream_Stat,
+ sub_stream_Clone
+};
+
+static HRESULT create_sub_stream(IStream *stream, ULARGE_INTEGER start, ULARGE_INTEGER
length, IStream **out)
+{
+ sub_stream_t *This;
+
+ *out = NULL;
+ This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
+ if(!This) return E_OUTOFMEMORY;
+
+ This->IStream_iface.lpVtbl = &sub_stream_vtbl;
+ This->ref = 1;
+ This->start = start;
+ This->length = length;
+ This->pos.QuadPart = 0;
+ IStream_AddRef(stream);
+ This->base = stream;
+
+ *out = &This->IStream_iface;
+ return S_OK;
+}
+
+static HRESULT get_stream_size(IStream *stream, ULARGE_INTEGER *size)
+{
+ STATSTG statstg = {NULL};
+ LARGE_INTEGER zero;
+ HRESULT hres;
+
+ hres = IStream_Stat(stream, &statstg, STATFLAG_NONAME);
+ if(SUCCEEDED(hres)) {
+ *size = statstg.cbSize;
+ return S_OK;
+ }
+
+ zero.QuadPart = 0;
+ return IStream_Seek(stream, zero, STREAM_SEEK_END, size);
+}
+
static inline MimeBody *impl_from_IMimeBody(IMimeBody *iface)
{
return CONTAINING_RECORD(iface, MimeBody, IMimeBody_iface);
@@ -224,8 +516,8 @@
if(new_end - last_end == 2)
{
LARGE_INTEGER off;
- off.QuadPart = new_end;
- IStream_Seek(stm, off, STREAM_SEEK_SET, NULL);
+ off.QuadPart = (LONGLONG)new_end - offset;
+ IStream_Seek(stm, off, STREAM_SEEK_CUR, NULL);
buf[new_end] = '\0';
done = TRUE;
}
@@ -438,12 +730,6 @@
char *slash;
DWORD len;
- if(header->prop->id != PID_HDR_CNTTYPE)
- {
- ERR("called with header %s\n", header->prop->name);
- return;
- }
-
slash = strchr(header->value.u.pszVal, '/');
if(!slash)
{
@@ -457,6 +743,22 @@
body->content_sub_type = strdupA(slash + 1);
}
+static void init_content_encoding(MimeBody *body, header_t *header)
+{
+ const char *encoding = header->value.u.pszVal;
+
+ if(!strcasecmp(encoding, "base64"))
+ body->encoding = IET_BASE64;
+ else if(!strcasecmp(encoding, "quoted-printable"))
+ body->encoding = IET_QP;
+ else if(!strcasecmp(encoding, "7bit"))
+ body->encoding = IET_7BIT;
+ else if(!strcasecmp(encoding, "8bit"))
+ body->encoding = IET_8BIT;
+ else
+ FIXME("unknown encoding %s\n", debugstr_a(encoding));
+}
+
static HRESULT parse_headers(MimeBody *body, IStream *stm)
{
char *header_buf, *cur_header_ptr;
@@ -472,8 +774,14 @@
read_value(header, &cur_header_ptr);
list_add_tail(&body->headers, &header->entry);
- if(header->prop->id == PID_HDR_CNTTYPE)
+ switch(header->prop->id) {
+ case PID_HDR_CNTTYPE:
init_content_type(body, header);
+ break;
+ case PID_HDR_CNTXFER:
+ init_content_encoding(body, header);
+ break;
+ }
}
HeapFree(GetProcessHeap(), 0, header_buf);
@@ -1207,17 +1515,206 @@
return E_NOTIMPL;
}
+static const signed char base64_decode_table[] =
+{
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x00 */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x10 */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, /* 0x20 */
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, /* 0x30 */
+ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 0x40 */
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, /* 0x50 */
+ -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* 0x60 */
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1 /* 0x70 */
+};
+
+static HRESULT decode_base64(IStream *input, IStream **ret_stream)
+{
+ const unsigned char *ptr, *end;
+ unsigned char buf[1024];
+ LARGE_INTEGER pos;
+ unsigned char *ret;
+ unsigned char in[4];
+ IStream *output;
+ DWORD size;
+ int n = 0;
+ HRESULT hres;
+
+ pos.QuadPart = 0;
+ hres = IStream_Seek(input, pos, STREAM_SEEK_SET, NULL);
+ if(FAILED(hres))
+ return hres;
+
+ hres = CreateStreamOnHGlobal(NULL, TRUE, &output);
+ if(FAILED(hres))
+ return hres;
+
+ while(1) {
+ hres = IStream_Read(input, buf, sizeof(buf), &size);
+ if(FAILED(hres) || !size)
+ break;
+
+ ptr = ret = buf;
+ end = buf + size;
+
+ while(1) {
+ /* skip invalid chars */
+ while(ptr < end &&
+ (*ptr >= sizeof(base64_decode_table)/sizeof(*base64_decode_table)
+ || base64_decode_table[*ptr] == -1))
+ ptr++;
+ if(ptr == end)
+ break;
+
+ in[n++] = base64_decode_table[*ptr++];
+ switch(n) {
+ case 2:
+ *ret++ = in[0] << 2 | in[1] >> 4;
+ continue;
+ case 3:
+ *ret++ = in[1] << 4 | in[2] >> 2;
+ continue;
+ case 4:
+ *ret++ = ((in[2] << 6) & 0xc0) | in[3];
+ n = 0;
+ }
+ }
+
+ if(ret > buf) {
+ hres = IStream_Write(output, buf, ret - buf, NULL);
+ if(FAILED(hres))
+ break;
+ }
+ }
+
+ if(SUCCEEDED(hres))
+ hres = IStream_Seek(output, pos, STREAM_SEEK_SET, NULL);
+ if(FAILED(hres)) {
+ IStream_Release(output);
+ return hres;
+ }
+
+ *ret_stream = output;
+ return S_OK;
+}
+
+static int hex_digit(char c)
+{
+ if('0' <= c && c <= '9')
+ return c - '0';
+ if('A' <= c && c <= 'F')
+ return c - 'A' + 10;
+ if('a' <= c && c <= 'f')
+ return c - 'a' + 10;
+ return -1;
+}
+
+static HRESULT decode_qp(IStream *input, IStream **ret_stream)
+{
+ const unsigned char *ptr, *end;
+ unsigned char *ret, prev = 0;
+ unsigned char buf[1024];
+ LARGE_INTEGER pos;
+ IStream *output;
+ DWORD size;
+ int n = -1;
+ HRESULT hres;
+
+ pos.QuadPart = 0;
+ hres = IStream_Seek(input, pos, STREAM_SEEK_SET, NULL);
+ if(FAILED(hres))
+ return hres;
+
+ hres = CreateStreamOnHGlobal(NULL, TRUE, &output);
+ if(FAILED(hres))
+ return hres;
+
+ while(1) {
+ hres = IStream_Read(input, buf, sizeof(buf), &size);
+ if(FAILED(hres) || !size)
+ break;
+
+ ptr = ret = buf;
+ end = buf + size;
+
+ while(ptr < end) {
+ unsigned char byte = *ptr++;
+
+ switch(n) {
+ case -1:
+ if(byte == '=')
+ n = 0;
+ else
+ *ret++ = byte;
+ continue;
+ case 0:
+ prev = byte;
+ n = 1;
+ continue;
+ case 1:
+ if(prev != '\r' || byte != '\n') {
+ int h1 = hex_digit(prev), h2 = hex_digit(byte);
+ if(h1 != -1 && h2 != -1)
+ *ret++ = (h1 << 4) | h2;
+ else
+ *ret++ = '=';
+ }
+ n = -1;
+ continue;
+ }
+ }
+
+ if(ret > buf) {
+ hres = IStream_Write(output, buf, ret - buf, NULL);
+ if(FAILED(hres))
+ break;
+ }
+ }
+
+ if(SUCCEEDED(hres))
+ hres = IStream_Seek(output, pos, STREAM_SEEK_SET, NULL);
+ if(FAILED(hres)) {
+ IStream_Release(output);
+ return hres;
+ }
+
+ *ret_stream = output;
+ return S_OK;
+}
+
static HRESULT WINAPI MimeBody_GetData(
IMimeBody* iface,
ENCODINGTYPE ietEncoding,
IStream** ppStream)
{
MimeBody *This = impl_from_IMimeBody(iface);
- FIXME("(%p)->(%d, %p). Ignoring encoding type.\n", This, ietEncoding,
ppStream);
-
- *ppStream = This->data;
- IStream_AddRef(*ppStream);
- return S_OK;
+ ULARGE_INTEGER start, size;
+ HRESULT hres;
+
+ TRACE("(%p)->(%d %p)\n", This, ietEncoding, ppStream);
+
+ if(This->encoding != ietEncoding) {
+ switch(This->encoding) {
+ case IET_BASE64:
+ hres = decode_base64(This->data, ppStream);
+ break;
+ case IET_QP:
+ hres = decode_qp(This->data, ppStream);
+ break;
+ default:
+ FIXME("Decoding %d is not supported.\n", This->encoding);
+ hres = S_FALSE;
+ }
+ if(ietEncoding != IET_BINARY)
+ FIXME("Encoding %d is not supported.\n", ietEncoding);
+ if(hres != S_FALSE)
+ return hres;
+ }
+
+ start.QuadPart = 0;
+ hres = get_stream_size(This->data, &size);
+ if(SUCCEEDED(hres))
+ hres = create_sub_stream(This->data, start, size, ppStream);
+ return hres;
}
static HRESULT WINAPI MimeBody_SetData(
@@ -1410,291 +1907,6 @@
}
}
-
-
-typedef struct
-{
- IStream IStream_iface;
- LONG ref;
- IStream *base;
- ULARGE_INTEGER pos, start, length;
-} sub_stream_t;
-
-static inline sub_stream_t *impl_from_IStream(IStream *iface)
-{
- return CONTAINING_RECORD(iface, sub_stream_t, IStream_iface);
-}
-
-static HRESULT WINAPI sub_stream_QueryInterface(IStream *iface, REFIID riid, void **ppv)
-{
- sub_stream_t *This = impl_from_IStream(iface);
-
- TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
- *ppv = NULL;
-
- if(IsEqualIID(riid, &IID_IUnknown) ||
- IsEqualIID(riid, &IID_ISequentialStream) ||
- IsEqualIID(riid, &IID_IStream))
- {
- IStream_AddRef(iface);
- *ppv = iface;
- return S_OK;
- }
- return E_NOINTERFACE;
-}
-
-static ULONG WINAPI sub_stream_AddRef(IStream *iface)
-{
- sub_stream_t *This = impl_from_IStream(iface);
- LONG ref = InterlockedIncrement(&This->ref);
-
- TRACE("(%p) ref=%d\n", This, ref);
-
- return ref;
-}
-
-static ULONG WINAPI sub_stream_Release(IStream *iface)
-{
- sub_stream_t *This = impl_from_IStream(iface);
- LONG ref = InterlockedDecrement(&This->ref);
-
- TRACE("(%p) ref=%d\n", This, ref);
-
- if(!ref)
- {
- IStream_Release(This->base);
- HeapFree(GetProcessHeap(), 0, This);
- }
- return ref;
-}
-
-static HRESULT WINAPI sub_stream_Read(
- IStream* iface,
- void *pv,
- ULONG cb,
- ULONG *pcbRead)
-{
- sub_stream_t *This = impl_from_IStream(iface);
- HRESULT hr;
- ULARGE_INTEGER base_pos;
- LARGE_INTEGER tmp_pos;
-
- TRACE("(%p, %d, %p)\n", pv, cb, pcbRead);
-
- tmp_pos.QuadPart = 0;
- IStream_Seek(This->base, tmp_pos, STREAM_SEEK_CUR, &base_pos);
- tmp_pos.QuadPart = This->pos.QuadPart + This->start.QuadPart;
- IStream_Seek(This->base, tmp_pos, STREAM_SEEK_SET, NULL);
-
- if(This->pos.QuadPart + cb > This->length.QuadPart)
- cb = This->length.QuadPart - This->pos.QuadPart;
-
- hr = IStream_Read(This->base, pv, cb, pcbRead);
-
- This->pos.QuadPart += *pcbRead;
-
- tmp_pos.QuadPart = base_pos.QuadPart;
- IStream_Seek(This->base, tmp_pos, STREAM_SEEK_SET, NULL);
-
- return hr;
-}
-
-static HRESULT WINAPI sub_stream_Write(
- IStream* iface,
- const void *pv,
- ULONG cb,
- ULONG *pcbWritten)
-{
- FIXME("stub\n");
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI sub_stream_Seek(
- IStream* iface,
- LARGE_INTEGER dlibMove,
- DWORD dwOrigin,
- ULARGE_INTEGER *plibNewPosition)
-{
- sub_stream_t *This = impl_from_IStream(iface);
- LARGE_INTEGER new_pos;
-
- TRACE("(%08x.%08x, %x, %p)\n", dlibMove.u.HighPart, dlibMove.u.LowPart,
dwOrigin, plibNewPosition);
-
- switch(dwOrigin)
- {
- case STREAM_SEEK_SET:
- new_pos = dlibMove;
- break;
- case STREAM_SEEK_CUR:
- new_pos.QuadPart = This->pos.QuadPart + dlibMove.QuadPart;
- break;
- case STREAM_SEEK_END:
- new_pos.QuadPart = This->length.QuadPart + dlibMove.QuadPart;
- break;
- default:
- return STG_E_INVALIDFUNCTION;
- }
-
- if(new_pos.QuadPart < 0) new_pos.QuadPart = 0;
- else if(new_pos.QuadPart > This->length.QuadPart) new_pos.QuadPart =
This->length.QuadPart;
-
- This->pos.QuadPart = new_pos.QuadPart;
-
- if(plibNewPosition) *plibNewPosition = This->pos;
- return S_OK;
-}
-
-static HRESULT WINAPI sub_stream_SetSize(
- IStream* iface,
- ULARGE_INTEGER libNewSize)
-{
- FIXME("stub\n");
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI sub_stream_CopyTo(
- IStream* iface,
- IStream *pstm,
- ULARGE_INTEGER cb,
- ULARGE_INTEGER *pcbRead,
- ULARGE_INTEGER *pcbWritten)
-{
- HRESULT hr = S_OK;
- BYTE tmpBuffer[128];
- ULONG bytesRead, bytesWritten, copySize;
- ULARGE_INTEGER totalBytesRead;
- ULARGE_INTEGER totalBytesWritten;
-
- TRACE("(%p)->(%p, %d, %p, %p)\n", iface, pstm, cb.u.LowPart, pcbRead,
pcbWritten);
-
- totalBytesRead.QuadPart = 0;
- totalBytesWritten.QuadPart = 0;
-
- while ( cb.QuadPart > 0 )
- {
- if ( cb.QuadPart >= sizeof(tmpBuffer) )
- copySize = sizeof(tmpBuffer);
- else
- copySize = cb.u.LowPart;
-
- hr = IStream_Read(iface, tmpBuffer, copySize, &bytesRead);
- if (FAILED(hr)) break;
-
- totalBytesRead.QuadPart += bytesRead;
-
- if (bytesRead)
- {
- hr = IStream_Write(pstm, tmpBuffer, bytesRead, &bytesWritten);
- if (FAILED(hr)) break;
- totalBytesWritten.QuadPart += bytesWritten;
- }
-
- if (bytesRead != copySize)
- cb.QuadPart = 0;
- else
- cb.QuadPart -= bytesRead;
- }
-
- if (pcbRead) pcbRead->QuadPart = totalBytesRead.QuadPart;
- if (pcbWritten) pcbWritten->QuadPart = totalBytesWritten.QuadPart;
-
- return hr;
-}
-
-static HRESULT WINAPI sub_stream_Commit(
- IStream* iface,
- DWORD grfCommitFlags)
-{
- FIXME("stub\n");
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI sub_stream_Revert(
- IStream* iface)
-{
- FIXME("stub\n");
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI sub_stream_LockRegion(
- IStream* iface,
- ULARGE_INTEGER libOffset,
- ULARGE_INTEGER cb,
- DWORD dwLockType)
-{
- FIXME("stub\n");
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI sub_stream_UnlockRegion(
- IStream* iface,
- ULARGE_INTEGER libOffset,
- ULARGE_INTEGER cb,
- DWORD dwLockType)
-{
- FIXME("stub\n");
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI sub_stream_Stat(
- IStream* iface,
- STATSTG *pstatstg,
- DWORD grfStatFlag)
-{
- sub_stream_t *This = impl_from_IStream(iface);
- FIXME("(%p)->(%p, %08x)\n", This, pstatstg, grfStatFlag);
- memset(pstatstg, 0, sizeof(*pstatstg));
- pstatstg->cbSize = This->length;
- return S_OK;
-}
-
-static HRESULT WINAPI sub_stream_Clone(
- IStream* iface,
- IStream **ppstm)
-{
- FIXME("stub\n");
- return E_NOTIMPL;
-}
-
-static struct IStreamVtbl sub_stream_vtbl =
-{
- sub_stream_QueryInterface,
- sub_stream_AddRef,
- sub_stream_Release,
- sub_stream_Read,
- sub_stream_Write,
- sub_stream_Seek,
- sub_stream_SetSize,
- sub_stream_CopyTo,
- sub_stream_Commit,
- sub_stream_Revert,
- sub_stream_LockRegion,
- sub_stream_UnlockRegion,
- sub_stream_Stat,
- sub_stream_Clone
-};
-
-static HRESULT create_sub_stream(IStream *stream, ULARGE_INTEGER start, ULARGE_INTEGER
length, IStream **out)
-{
- sub_stream_t *This;
-
- *out = NULL;
- This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
- if(!This) return E_OUTOFMEMORY;
-
- This->IStream_iface.lpVtbl = &sub_stream_vtbl;
- This->ref = 1;
- This->start = start;
- This->length = length;
- This->pos.QuadPart = 0;
- IStream_AddRef(stream);
- This->base = stream;
-
- *out = &This->IStream_iface;
- return S_OK;
-}
-
-
typedef struct body_t
{
struct list entry;
@@ -1821,18 +2033,16 @@
static HRESULT create_body_offset_list(IStream *stm, const char *boundary, struct list
*body_offsets)
{
HRESULT hr;
- DWORD read;
+ DWORD read, boundary_start;
int boundary_len = strlen(boundary);
- char *buf, *nl_boundary, *ptr, *overlap;
+ char *buf, *ptr, *overlap;
DWORD start = 0, overlap_no;
offset_entry_t *cur_body = NULL;
+ BOOL is_first_line = TRUE;
ULARGE_INTEGER cur;
LARGE_INTEGER zero;
list_init(body_offsets);
- nl_boundary = HeapAlloc(GetProcessHeap(), 0, 4 + boundary_len + 1);
- memcpy(nl_boundary, "\r\n--", 4);
- memcpy(nl_boundary + 4, boundary, boundary_len + 1);
overlap_no = boundary_len + 5;
@@ -1849,39 +2059,44 @@
overlap[read] = '\0';
ptr = buf;
- do {
- ptr = strstr(ptr, nl_boundary);
- if(ptr)
- {
- DWORD boundary_start = start + ptr - buf;
- char *end = ptr + boundary_len + 4;
-
- if(*end == '\0' || *(end + 1) == '\0')
+ while(1) {
+ if(is_first_line) {
+ is_first_line = FALSE;
+ }else {
+ ptr = strstr(ptr, "\r\n");
+ if(!ptr)
break;
-
- if(*end == '\r' && *(end + 1) == '\n')
+ ptr += 2;
+ }
+
+ boundary_start = start + ptr - buf;
+
+ if(*ptr == '-' && *(ptr + 1) == '-' &&
!memcmp(ptr + 2, boundary, boundary_len)) {
+ ptr += boundary_len + 2;
+
+ if(*ptr == '\r' && *(ptr + 1) == '\n')
+ {
+ ptr += 2;
+ if(cur_body)
+ {
+ cur_body->offsets.cbBodyEnd = boundary_start - 2;
+ list_add_tail(body_offsets, &cur_body->entry);
+ }
+ cur_body = HeapAlloc(GetProcessHeap(), 0, sizeof(*cur_body));
+ cur_body->offsets.cbBoundaryStart = boundary_start;
+ cur_body->offsets.cbHeaderStart = start + ptr - buf;
+ }
+ else if(*ptr == '-' && *(ptr + 1) == '-')
{
if(cur_body)
{
- cur_body->offsets.cbBodyEnd = boundary_start;
- list_add_tail(body_offsets, &cur_body->entry);
- }
- cur_body = HeapAlloc(GetProcessHeap(), 0, sizeof(*cur_body));
- cur_body->offsets.cbBoundaryStart = boundary_start + 2; /*
doesn't including the leading \r\n */
- cur_body->offsets.cbHeaderStart = boundary_start + boundary_len +
6;
- }
- else if(*end == '-' && *(end + 1) == '-')
- {
- if(cur_body)
- {
- cur_body->offsets.cbBodyEnd = boundary_start;
+ cur_body->offsets.cbBodyEnd = boundary_start - 2;
list_add_tail(body_offsets, &cur_body->entry);
goto end;
}
}
- ptr = end + 2;
}
- } while(ptr);
+ }
if(overlap == buf) /* 1st iteration */
{
@@ -1897,26 +2112,33 @@
} while(1);
end:
- HeapFree(GetProcessHeap(), 0, nl_boundary);
HeapFree(GetProcessHeap(), 0, buf);
return hr;
}
static body_t *create_sub_body(MimeMessage *msg, IStream *pStm, BODYOFFSETS *offset,
body_t *parent)
{
+ ULARGE_INTEGER start, length;
MimeBody *mime_body;
HRESULT hr;
body_t *body;
- ULARGE_INTEGER cur;
- LARGE_INTEGER zero;
+ LARGE_INTEGER pos;
+
+ pos.QuadPart = offset->cbHeaderStart;
+ IStream_Seek(pStm, pos, STREAM_SEEK_SET, NULL);
mime_body = mimebody_create();
IMimeBody_Load(&mime_body->IMimeBody_iface, pStm);
- zero.QuadPart = 0;
- hr = IStream_Seek(pStm, zero, STREAM_SEEK_CUR, &cur);
- offset->cbBodyStart = cur.u.LowPart + offset->cbHeaderStart;
+
+ pos.QuadPart = 0;
+ hr = IStream_Seek(pStm, pos, STREAM_SEEK_CUR, &start);
+ offset->cbBodyStart = start.QuadPart;
if (parent) MimeBody_set_offsets(mime_body, offset);
- IMimeBody_SetData(&mime_body->IMimeBody_iface, IET_BINARY, NULL, NULL,
&IID_IStream, pStm);
+
+ length.QuadPart = offset->cbBodyEnd - offset->cbBodyStart;
+ create_sub_stream(pStm, start, length, (IStream**)&mime_body->data);
+ mime_body->data_iid = IID_IStream;
+
body = new_body_entry(mime_body, msg->next_index++, parent);
if(IMimeBody_IsContentType(&mime_body->IMimeBody_iface, "multipart",
NULL) == S_OK)
@@ -1941,14 +2163,8 @@
LIST_FOR_EACH_ENTRY_SAFE(cur, cursor2, &offset_list, offset_entry_t,
entry)
{
body_t *sub_body;
- IStream *sub_stream;
- ULARGE_INTEGER start, length;
-
- start.QuadPart = cur->offsets.cbHeaderStart;
- length.QuadPart = cur->offsets.cbBodyEnd -
cur->offsets.cbHeaderStart;
- create_sub_stream(pStm, start, length, &sub_stream);
- sub_body = create_sub_body(msg, sub_stream, &cur->offsets,
body);
- IStream_Release(sub_stream);
+
+ sub_body = create_sub_body(msg, pStm, &cur->offsets, body);
list_add_tail(&body->children, &sub_body->entry);
list_remove(&cur->entry);
HeapFree(GetProcessHeap(), 0, cur);
@@ -3421,10 +3637,70 @@
return E_NOTIMPL;
}
+static HRESULT WINAPI mime_obj_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
+{
+ FIXME("(%s %p)\n", debugstr_guid(riid), ppv);
+ *ppv = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI mime_obj_AddRef(IUnknown *iface)
+{
+ TRACE("\n");
+ return 2;
+}
+
+static ULONG WINAPI mime_obj_Release(IUnknown *iface)
+{
+ TRACE("\n");
+ return 1;
+}
+
+static const IUnknownVtbl mime_obj_vtbl = {
+ mime_obj_QueryInterface,
+ mime_obj_AddRef,
+ mime_obj_Release
+};
+
+static IUnknown mime_obj = { &mime_obj_vtbl };
+
HRESULT WINAPI MimeOleObjectFromMoniker(BINDF bindf, IMoniker *moniker, IBindCtx
*binding,
REFIID riid, void **out, IMoniker **moniker_new)
{
- FIXME("(0x%08x, %p, %p, %s, %p, %p) stub\n", bindf, moniker, binding,
debugstr_guid(riid), out, moniker_new);
-
- return E_NOTIMPL;
-}
+ WCHAR *display_name, *mhtml_url;
+ size_t len;
+ HRESULT hres;
+
+ static const WCHAR mhtml_prefixW[] =
{'m','h','t','m','l',':'};
+
+ WARN("(0x%08x, %p, %p, %s, %p, %p) semi-stub\n", bindf, moniker, binding,
debugstr_guid(riid), out, moniker_new);
+
+ if(!IsEqualGUID(&IID_IUnknown, riid)) {
+ FIXME("Unsupported riid %s\n", debugstr_guid(riid));
+ return E_NOINTERFACE;
+ }
+
+ hres = IMoniker_GetDisplayName(moniker, NULL, NULL, &display_name);
+ if(FAILED(hres))
+ return hres;
+
+ TRACE("display name %s\n", debugstr_w(display_name));
+
+ len = strlenW(display_name);
+ mhtml_url = heap_alloc((len+1)*sizeof(WCHAR) + sizeof(mhtml_prefixW));
+ if(!mhtml_url)
+ return E_OUTOFMEMORY;
+
+ memcpy(mhtml_url, mhtml_prefixW, sizeof(mhtml_prefixW));
+ strcpyW(mhtml_url + sizeof(mhtml_prefixW)/sizeof(WCHAR), display_name);
+ HeapFree(GetProcessHeap(), 0, display_name);
+
+ hres = CreateURLMoniker(NULL, mhtml_url, moniker_new);
+ heap_free(mhtml_url);
+ if(FAILED(hres))
+ return hres;
+
+ /* FIXME: We most likely should start binding here and return something more
meaningful as mime object. */
+ *out = &mime_obj;
+ return S_OK;
+}
Added: trunk/reactos/dll/win32/inetcomm/protocol.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/inetcomm/protoco…
==============================================================================
--- trunk/reactos/dll/win32/inetcomm/protocol.c (added)
+++ trunk/reactos/dll/win32/inetcomm/protocol.c [iso-8859-1] Sun Mar 5 21:33:13 2017
@@ -0,0 +1,738 @@
+/*
+ * Copyright 2017 Jacek Caban for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "inetcomm_private.h"
+
+#include <assert.h>
+
+typedef struct {
+ IUnknown IUnknown_inner;
+ IInternetProtocol IInternetProtocol_iface;
+ IInternetProtocolInfo IInternetProtocolInfo_iface;
+
+ LONG ref;
+ IUnknown *outer_unk;
+
+ WCHAR *location;
+ IStream *stream;
+ IInternetProtocolSink *sink;
+} MimeHtmlProtocol;
+
+typedef struct {
+ const WCHAR *mhtml;
+ size_t mhtml_len;
+ const WCHAR *location;
+} mhtml_url_t;
+
+typedef struct {
+ IBindStatusCallback IBindStatusCallback_iface;
+
+ LONG ref;
+
+ MimeHtmlProtocol *protocol;
+ HRESULT status;
+ IStream *stream;
+ WCHAR url[1];
+} MimeHtmlBinding;
+
+static const WCHAR mhtml_prefixW[] =
{'m','h','t','m','l',':'};
+static const WCHAR mhtml_separatorW[] =
{'!','x','-','u','s','c',':'};
+
+static inline LPWSTR heap_strdupW(LPCWSTR str)
+{
+ LPWSTR ret = NULL;
+
+ if(str) {
+ DWORD size;
+
+ size = (strlenW(str)+1)*sizeof(WCHAR);
+ ret = heap_alloc(size);
+ if(ret)
+ memcpy(ret, str, size);
+ }
+
+ return ret;
+}
+
+static HRESULT parse_mhtml_url(const WCHAR *url, mhtml_url_t *r)
+{
+ const WCHAR *p;
+
+ if(strncmpiW(url, mhtml_prefixW, sizeof(mhtml_prefixW)/sizeof(WCHAR)))
+ return E_FAIL;
+
+ r->mhtml = url + sizeof(mhtml_prefixW)/sizeof(WCHAR);
+ p = strchrW(r->mhtml, '!');
+ if(p) {
+ r->mhtml_len = p - r->mhtml;
+ /* FIXME: We handle '!' and '!x-usc:' in URLs as the same thing.
Those should not be the same. */
+ if(!strncmpW(p, mhtml_separatorW, sizeof(mhtml_separatorW)/sizeof(WCHAR)))
+ p += sizeof(mhtml_separatorW)/sizeof(WCHAR);
+ else
+ p++;
+ }else {
+ r->mhtml_len = strlenW(r->mhtml);
+ }
+
+ r->location = p;
+ return S_OK;
+}
+
+static HRESULT report_result(MimeHtmlProtocol *protocol, HRESULT result)
+{
+ if(protocol->sink) {
+ IInternetProtocolSink_ReportResult(protocol->sink, result, ERROR_SUCCESS,
NULL);
+ IInternetProtocolSink_Release(protocol->sink);
+ protocol->sink = NULL;
+ }
+
+ return result;
+}
+
+static HRESULT on_mime_message_available(MimeHtmlProtocol *protocol, IMimeMessage
*mime_message)
+{
+ FINDBODY find = {NULL};
+ IMimeBody *mime_body;
+ PROPVARIANT value;
+ HBODY body;
+ HRESULT hres;
+
+ hres = IMimeMessage_FindFirst(mime_message, &find, &body);
+ if(FAILED(hres))
+ return report_result(protocol, hres);
+
+ if(protocol->location) {
+ BOOL found = FALSE;
+ do {
+ hres = IMimeMessage_FindNext(mime_message, &find, &body);
+ if(FAILED(hres)) {
+ WARN("location %s not found\n",
debugstr_w(protocol->location));
+ return report_result(protocol, hres);
+ }
+
+ value.vt = VT_LPWSTR;
+ hres = IMimeMessage_GetBodyProp(mime_message, body,
"content-location", 0, &value);
+ if(hres == MIME_E_NOT_FOUND)
+ continue;
+ if(FAILED(hres))
+ return report_result(protocol, hres);
+
+ found = !strcmpW(protocol->location, value.u.pwszVal);
+ PropVariantClear(&value);
+ }while(!found);
+ }else {
+ hres = IMimeMessage_FindNext(mime_message, &find, &body);
+ if(FAILED(hres)) {
+ WARN("location %s not found\n",
debugstr_w(protocol->location));
+ return report_result(protocol, hres);
+ }
+ }
+
+ hres = IMimeMessage_BindToObject(mime_message, body, &IID_IMimeBody,
(void**)&mime_body);
+ if(FAILED(hres))
+ return report_result(protocol, hres);
+
+ value.vt = VT_LPWSTR;
+ hres = IMimeBody_GetProp(mime_body, "content-type", 0, &value);
+ if(SUCCEEDED(hres)) {
+ hres = IInternetProtocolSink_ReportProgress(protocol->sink,
BINDSTATUS_MIMETYPEAVAILABLE, value.u.pwszVal);
+ PropVariantClear(&value);
+ }
+
+ /* FIXME: Create and report cache file. */
+
+ hres = IMimeBody_GetData(mime_body, IET_DECODED, &protocol->stream);
+ if(FAILED(hres))
+ return report_result(protocol, hres);
+
+ IInternetProtocolSink_ReportData(protocol->sink, BSCF_FIRSTDATANOTIFICATION
+ | BSCF_INTERMEDIATEDATANOTIFICATION
+ | BSCF_LASTDATANOTIFICATION
+ | BSCF_DATAFULLYAVAILABLE
+ | BSCF_AVAILABLEDATASIZEUNKNOWN, 0, 0);
+
+ return report_result(protocol, S_OK);
+}
+
+static HRESULT load_mime_message(IStream *stream, IMimeMessage **ret)
+{
+ IMimeMessage *mime_message;
+ HRESULT hres;
+
+ hres = MimeMessage_create(NULL, (void**)&mime_message);
+ if(FAILED(hres))
+ return hres;
+
+ IMimeMessage_InitNew(mime_message);
+
+ hres = IMimeMessage_Load(mime_message, stream);
+ if(FAILED(hres)) {
+ IMimeMessage_Release(mime_message);
+ return hres;
+ }
+
+ *ret = mime_message;
+ return S_OK;
+}
+
+static inline MimeHtmlBinding *impl_from_IBindStatusCallback(IBindStatusCallback *iface)
+{
+ return CONTAINING_RECORD(iface, MimeHtmlBinding, IBindStatusCallback_iface);
+}
+
+static HRESULT WINAPI BindStatusCallback_QueryInterface(IBindStatusCallback *iface,
+ REFIID riid, void **ppv)
+{
+ MimeHtmlBinding *This = impl_from_IBindStatusCallback(iface);
+
+ if(IsEqualGUID(&IID_IUnknown, riid)) {
+ TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
+ *ppv = &This->IBindStatusCallback_iface;
+ }else if(IsEqualGUID(&IID_IBindStatusCallback, riid)) {
+ TRACE("(%p)->(IID_IBindStatusCallback %p)\n", This, ppv);
+ *ppv = &This->IBindStatusCallback_iface;
+ }else {
+ TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+}
+
+static ULONG WINAPI BindStatusCallback_AddRef(IBindStatusCallback *iface)
+{
+ MimeHtmlBinding *This = impl_from_IBindStatusCallback(iface);
+ LONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) ref=%d\n", This, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI BindStatusCallback_Release(IBindStatusCallback *iface)
+{
+ MimeHtmlBinding *This = impl_from_IBindStatusCallback(iface);
+ LONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p) ref=%d\n", This, ref);
+
+ if(!ref) {
+ if(This->protocol)
+
IInternetProtocol_Release(&This->protocol->IInternetProtocol_iface);
+ if(This->stream)
+ IStream_Release(This->stream);
+ heap_free(This);
+ }
+
+ return ref;
+}
+
+static HRESULT WINAPI BindStatusCallback_OnStartBinding(IBindStatusCallback *iface,
+ DWORD dwReserved, IBinding *pib)
+{
+ MimeHtmlBinding *This = impl_from_IBindStatusCallback(iface);
+
+ TRACE("(%p)->(%x %p)\n", This, dwReserved, pib);
+
+ assert(!This->stream);
+ return CreateStreamOnHGlobal(NULL, TRUE, &This->stream);
+}
+
+static HRESULT WINAPI BindStatusCallback_GetPriority(IBindStatusCallback *iface, LONG
*pnPriority)
+{
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI BindStatusCallback_OnLowResource(IBindStatusCallback *iface, DWORD
dwReserved)
+{
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI BindStatusCallback_OnProgress(IBindStatusCallback *iface, ULONG
ulProgress,
+ ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
+{
+ MimeHtmlBinding *This = impl_from_IBindStatusCallback(iface);
+ TRACE("(%p)->(%u/%u %u %s)\n", This, ulProgress, ulProgressMax,
ulStatusCode, debugstr_w(szStatusText));
+ return S_OK;
+}
+
+static HRESULT WINAPI BindStatusCallback_OnStopBinding(IBindStatusCallback *iface,
HRESULT hresult, LPCWSTR szError)
+{
+ MimeHtmlBinding *This = impl_from_IBindStatusCallback(iface);
+ IMimeMessage *mime_message = NULL;
+
+ TRACE("(%p)->(%x %s)\n", This, hresult, debugstr_w(szError));
+
+ if(SUCCEEDED(hresult)) {
+ hresult = load_mime_message(This->stream, &mime_message);
+ IStream_Release(This->stream);
+ This->stream = NULL;
+ }
+
+ This->status = hresult;
+
+ if(mime_message)
+ on_mime_message_available(This->protocol, mime_message);
+ else
+ report_result(This->protocol, hresult);
+
+ if(mime_message)
+ IMimeMessage_Release(mime_message);
+ IInternetProtocol_Release(&This->protocol->IInternetProtocol_iface);
+ This->protocol = NULL;
+ return S_OK;
+}
+
+static HRESULT WINAPI BindStatusCallback_GetBindInfo(IBindStatusCallback *iface,
+ DWORD* grfBINDF, BINDINFO* pbindinfo)
+{
+ MimeHtmlBinding *This = impl_from_IBindStatusCallback(iface);
+
+ TRACE("(%p)\n", This);
+
+ *grfBINDF = BINDF_ASYNCHRONOUS;
+ return S_OK;
+}
+
+static HRESULT WINAPI BindStatusCallback_OnDataAvailable(IBindStatusCallback *iface,
DWORD grfBSCF,
+ DWORD dwSize, FORMATETC* pformatetc, STGMEDIUM* pstgmed)
+{
+ MimeHtmlBinding *This = impl_from_IBindStatusCallback(iface);
+ BYTE buf[4*1024];
+ DWORD read;
+ HRESULT hres;
+
+ TRACE("(%p)\n", This);
+
+ assert(pstgmed->tymed == TYMED_ISTREAM);
+
+ while(1) {
+ hres = IStream_Read(pstgmed->u.pstm, buf, sizeof(buf), &read);
+ if(FAILED(hres))
+ return hres;
+ if(!read)
+ break;
+ hres = IStream_Write(This->stream, buf, read, NULL);
+ if(FAILED(hres))
+ return hres;
+ }
+ return S_OK;
+}
+
+static HRESULT WINAPI BindStatusCallback_OnObjectAvailable(IBindStatusCallback *iface,
+ REFIID riid, IUnknown* punk)
+{
+ ERR("\n");
+ return E_NOTIMPL;
+}
+
+static const IBindStatusCallbackVtbl BindStatusCallbackVtbl = {
+ BindStatusCallback_QueryInterface,
+ BindStatusCallback_AddRef,
+ BindStatusCallback_Release,
+ BindStatusCallback_OnStartBinding,
+ BindStatusCallback_GetPriority,
+ BindStatusCallback_OnLowResource,
+ BindStatusCallback_OnProgress,
+ BindStatusCallback_OnStopBinding,
+ BindStatusCallback_GetBindInfo,
+ BindStatusCallback_OnDataAvailable,
+ BindStatusCallback_OnObjectAvailable
+};
+
+static inline MimeHtmlProtocol *impl_from_IUnknown(IUnknown *iface)
+{
+ return CONTAINING_RECORD(iface, MimeHtmlProtocol, IUnknown_inner);
+}
+
+static HRESULT WINAPI MimeHtmlProtocol_QueryInterface(IUnknown *iface, REFIID riid, void
**ppv)
+{
+ MimeHtmlProtocol *This = impl_from_IUnknown(iface);
+
+ if(IsEqualGUID(&IID_IUnknown, riid)) {
+ TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
+ *ppv = &This->IInternetProtocol_iface;
+ }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
+ TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv);
+ *ppv = &This->IInternetProtocol_iface;
+ }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
+ TRACE("(%p)->(IID_IInternetProtocol %p)\n", This, ppv);
+ *ppv = &This->IInternetProtocol_iface;
+ }else if(IsEqualGUID(&IID_IInternetProtocolInfo, riid)) {
+ TRACE("(%p)->(IID_IInternetProtocolInfo %p)\n", This, ppv);
+ *ppv = &This->IInternetProtocolInfo_iface;
+ }else {
+ FIXME("unknown interface %s\n", debugstr_guid(riid));
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+}
+
+static ULONG WINAPI MimeHtmlProtocol_AddRef(IUnknown *iface)
+{
+ MimeHtmlProtocol *This = impl_from_IUnknown(iface);
+ ULONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) ref=%d\n", This, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI MimeHtmlProtocol_Release(IUnknown *iface)
+{
+ MimeHtmlProtocol *This = impl_from_IUnknown(iface);
+ ULONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p) ref=%x\n", This, ref);
+
+ if(!ref) {
+ if(This->sink)
+ IInternetProtocolSink_Release(This->sink);
+ if(This->stream)
+ IStream_Release(This->stream);
+ heap_free(This->location);
+ heap_free(This);
+ }
+
+ return ref;
+}
+
+static const IUnknownVtbl MimeHtmlProtocolInnerVtbl = {
+ MimeHtmlProtocol_QueryInterface,
+ MimeHtmlProtocol_AddRef,
+ MimeHtmlProtocol_Release
+};
+
+static inline MimeHtmlProtocol *impl_from_IInternetProtocol(IInternetProtocol *iface)
+{
+ return CONTAINING_RECORD(iface, MimeHtmlProtocol, IInternetProtocol_iface);
+}
+
+static HRESULT WINAPI InternetProtocol_QueryInterface(IInternetProtocol *iface, REFIID
riid, void **ppv)
+{
+ MimeHtmlProtocol *This = impl_from_IInternetProtocol(iface);
+ return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
+}
+
+static ULONG WINAPI InternetProtocol_AddRef(IInternetProtocol *iface)
+{
+ MimeHtmlProtocol *This = impl_from_IInternetProtocol(iface);
+ return IUnknown_AddRef(This->outer_unk);
+}
+
+static ULONG WINAPI InternetProtocol_Release(IInternetProtocol *iface)
+{
+ MimeHtmlProtocol *This = impl_from_IInternetProtocol(iface);
+ return IUnknown_Release(This->outer_unk);
+}
+
+static HRESULT WINAPI MimeHtmlProtocol_Start(IInternetProtocol *iface, const WCHAR
*szUrl,
+ IInternetProtocolSink* pOIProtSink, IInternetBindInfo* pOIBindInfo,
+ DWORD grfPI, HANDLE_PTR dwReserved)
+{
+ MimeHtmlProtocol *This = impl_from_IInternetProtocol(iface);
+ BINDINFO bindinfo = { sizeof(bindinfo) };
+ MimeHtmlBinding *binding;
+ IBindCtx *bind_ctx;
+ IStream *stream;
+ mhtml_url_t url;
+ DWORD bindf = 0;
+ IMoniker *mon;
+ HRESULT hres;
+
+ TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl),
pOIProtSink, pOIBindInfo, grfPI, dwReserved);
+
+ hres = parse_mhtml_url(szUrl, &url);
+ if(FAILED(hres))
+ return hres;
+
+ if(url.location && !(This->location = heap_strdupW(url.location)))
+ return E_OUTOFMEMORY;
+
+ hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &bindf, &bindinfo);
+ if(FAILED(hres)) {
+ WARN("GetBindInfo failed: %08x\n", hres);
+ return hres;
+ }
+ if((bindf & (BINDF_ASYNCHRONOUS|BINDF_FROMURLMON|BINDF_NEEDFILE)) !=
(BINDF_ASYNCHRONOUS|BINDF_FROMURLMON|BINDF_NEEDFILE))
+ FIXME("unsupported bindf %x\n", bindf);
+
+ This->sink = pOIProtSink;
+ IInternetProtocolSink_AddRef(This->sink);
+
+ binding = heap_alloc(FIELD_OFFSET(MimeHtmlBinding, url[url.mhtml_len+1]));
+ if(!binding)
+ return E_OUTOFMEMORY;
+ memcpy(binding->url, url.mhtml, url.mhtml_len*sizeof(WCHAR));
+ binding->url[url.mhtml_len] = 0;
+
+ hres = CreateURLMoniker(NULL, binding->url, &mon);
+ if(FAILED(hres))
+ return hres;
+
+ binding->IBindStatusCallback_iface.lpVtbl = &BindStatusCallbackVtbl;
+ binding->ref = 1;
+ binding->status = E_PENDING;
+ binding->stream = NULL;
+ binding->protocol = NULL;
+
+ hres = CreateAsyncBindCtx(0, &binding->IBindStatusCallback_iface, NULL,
&bind_ctx);
+ if(FAILED(hres)) {
+ IMoniker_Release(mon);
+ IBindStatusCallback_Release(&binding->IBindStatusCallback_iface);
+ return hres;
+ }
+
+ IInternetProtocol_AddRef(&This->IInternetProtocol_iface);
+ binding->protocol = This;
+
+ hres = IMoniker_BindToStorage(mon, bind_ctx, NULL, &IID_IStream,
(void**)&stream);
+ IBindCtx_Release(bind_ctx);
+ IMoniker_Release(mon);
+ if(stream)
+ IStream_Release(stream);
+ hres = binding->status;
+ IBindStatusCallback_Release(&binding->IBindStatusCallback_iface);
+ if(FAILED(hres) && hres != E_PENDING)
+ report_result(This, hres);
+ return hres;
+}
+
+static HRESULT WINAPI MimeHtmlProtocol_Continue(IInternetProtocol *iface, PROTOCOLDATA
*pProtocolData)
+{
+ MimeHtmlProtocol *This = impl_from_IInternetProtocol(iface);
+ FIXME("(%p)->(%p)\n", This, pProtocolData);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI MimeHtmlProtocol_Abort(IInternetProtocol *iface, HRESULT hrReason,
DWORD dwOptions)
+{
+ MimeHtmlProtocol *This = impl_from_IInternetProtocol(iface);
+ FIXME("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI MimeHtmlProtocol_Terminate(IInternetProtocol *iface, DWORD
dwOptions)
+{
+ MimeHtmlProtocol *This = impl_from_IInternetProtocol(iface);
+ TRACE("(%p)->(%08x)\n", This, dwOptions);
+ return S_OK;
+}
+
+static HRESULT WINAPI MimeHtmlProtocol_Suspend(IInternetProtocol *iface)
+{
+ MimeHtmlProtocol *This = impl_from_IInternetProtocol(iface);
+ FIXME("(%p)\n", This);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI MimeHtmlProtocol_Resume(IInternetProtocol *iface)
+{
+ MimeHtmlProtocol *This = impl_from_IInternetProtocol(iface);
+ FIXME("(%p)\n", This);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI MimeHtmlProtocol_Read(IInternetProtocol *iface, void* pv, ULONG cb,
ULONG* pcbRead)
+{
+ MimeHtmlProtocol *This = impl_from_IInternetProtocol(iface);
+ ULONG read = 0;
+ HRESULT hres;
+
+ TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
+
+ hres = IStream_Read(This->stream, pv, cb, &read);
+ if(pcbRead)
+ *pcbRead = read;
+ if(hres != S_OK)
+ return hres;
+
+ return read ? S_OK : S_FALSE;
+}
+
+static HRESULT WINAPI MimeHtmlProtocol_Seek(IInternetProtocol *iface, LARGE_INTEGER
dlibMove,
+ DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition)
+{
+ MimeHtmlProtocol *This = impl_from_IInternetProtocol(iface);
+ FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin,
plibNewPosition);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI MimeHtmlProtocol_LockRequest(IInternetProtocol *iface, DWORD
dwOptions)
+{
+ MimeHtmlProtocol *This = impl_from_IInternetProtocol(iface);
+ FIXME("(%p)->(%d)\n", This, dwOptions);
+ return S_OK;
+}
+
+static HRESULT WINAPI MimeHtmlProtocol_UnlockRequest(IInternetProtocol *iface)
+{
+ MimeHtmlProtocol *This = impl_from_IInternetProtocol(iface);
+ FIXME("(%p)\n", This);
+ return S_OK;
+}
+
+static const IInternetProtocolVtbl MimeHtmlProtocolVtbl = {
+ InternetProtocol_QueryInterface,
+ InternetProtocol_AddRef,
+ InternetProtocol_Release,
+ MimeHtmlProtocol_Start,
+ MimeHtmlProtocol_Continue,
+ MimeHtmlProtocol_Abort,
+ MimeHtmlProtocol_Terminate,
+ MimeHtmlProtocol_Suspend,
+ MimeHtmlProtocol_Resume,
+ MimeHtmlProtocol_Read,
+ MimeHtmlProtocol_Seek,
+ MimeHtmlProtocol_LockRequest,
+ MimeHtmlProtocol_UnlockRequest
+};
+
+static inline MimeHtmlProtocol *impl_from_IInternetProtocolInfo(IInternetProtocolInfo
*iface)
+{
+ return CONTAINING_RECORD(iface, MimeHtmlProtocol, IInternetProtocolInfo_iface);
+}
+
+static HRESULT WINAPI MimeHtmlProtocolInfo_QueryInterface(IInternetProtocolInfo *iface,
REFIID riid, void **ppv)
+{
+ MimeHtmlProtocol *This = impl_from_IInternetProtocolInfo(iface);
+ return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
+}
+
+static ULONG WINAPI MimeHtmlProtocolInfo_AddRef(IInternetProtocolInfo *iface)
+{
+ MimeHtmlProtocol *This = impl_from_IInternetProtocolInfo(iface);
+ return IUnknown_AddRef(This->outer_unk);
+}
+
+static ULONG WINAPI MimeHtmlProtocolInfo_Release(IInternetProtocolInfo *iface)
+{
+ MimeHtmlProtocol *This = impl_from_IInternetProtocolInfo(iface);
+ return IUnknown_Release(This->outer_unk);
+}
+
+static HRESULT WINAPI MimeHtmlProtocolInfo_ParseUrl(IInternetProtocolInfo *iface, LPCWSTR
pwzUrl,
+ PARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult,
+ DWORD* pcchResult, DWORD dwReserved)
+{
+ MimeHtmlProtocol *This = impl_from_IInternetProtocolInfo(iface);
+ FIXME("(%p)->(%s %d %x %p %d %p %d)\n", This, debugstr_w(pwzUrl),
ParseAction,
+ dwParseFlags, pwzResult, cchResult, pcchResult, dwReserved);
+ return INET_E_DEFAULT_ACTION;
+}
+
+static HRESULT WINAPI MimeHtmlProtocolInfo_CombineUrl(IInternetProtocolInfo *iface,
+ LPCWSTR pwzBaseUrl, LPCWSTR pwzRelativeUrl, DWORD dwCombineFlags, LPWSTR
pwzResult,
+ DWORD cchResult, DWORD* pcchResult, DWORD dwReserved)
+{
+ MimeHtmlProtocol *This = impl_from_IInternetProtocolInfo(iface);
+ size_t len = sizeof(mhtml_prefixW)/sizeof(WCHAR);
+ mhtml_url_t url;
+ WCHAR *p;
+ HRESULT hres;
+
+ TRACE("(%p)->(%s %s %08x %p %d %p %d)\n", This, debugstr_w(pwzBaseUrl),
+ debugstr_w(pwzRelativeUrl), dwCombineFlags, pwzResult, cchResult,
+ pcchResult, dwReserved);
+
+ hres = parse_mhtml_url(pwzBaseUrl, &url);
+ if(FAILED(hres))
+ return hres;
+
+ if(!strncmpiW(pwzRelativeUrl, mhtml_prefixW, sizeof(mhtml_prefixW)/sizeof(WCHAR))) {
+ FIXME("Relative URL is mhtml protocol\n");
+ return INET_E_USE_DEFAULT_PROTOCOLHANDLER;
+ }
+
+ len += url.mhtml_len;
+ if(*pwzRelativeUrl)
+ len += strlenW(pwzRelativeUrl) + sizeof(mhtml_separatorW)/sizeof(WCHAR);
+ if(len >= cchResult) {
+ *pcchResult = 0;
+ return E_FAIL;
+ }
+
+ memcpy(pwzResult, mhtml_prefixW, sizeof(mhtml_prefixW));
+ p = pwzResult + sizeof(mhtml_prefixW)/sizeof(WCHAR);
+ memcpy(p, url.mhtml, url.mhtml_len*sizeof(WCHAR));
+ p += url.mhtml_len;
+ if(*pwzRelativeUrl) {
+ memcpy(p, mhtml_separatorW, sizeof(mhtml_separatorW));
+ p += sizeof(mhtml_separatorW)/sizeof(WCHAR);
+ strcpyW(p, pwzRelativeUrl);
+ }else {
+ *p = 0;
+ }
+
+ *pcchResult = len;
+ return S_OK;
+}
+
+static HRESULT WINAPI MimeHtmlProtocolInfo_CompareUrl(IInternetProtocolInfo *iface,
LPCWSTR pwzUrl1,
+ LPCWSTR pwzUrl2, DWORD dwCompareFlags)
+{
+ MimeHtmlProtocol *This = impl_from_IInternetProtocolInfo(iface);
+ FIXME("(%p)->(%s %s %08x)\n", This, debugstr_w(pwzUrl1),
debugstr_w(pwzUrl2), dwCompareFlags);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI MimeHtmlProtocolInfo_QueryInfo(IInternetProtocolInfo *iface,
LPCWSTR pwzUrl,
+ QUERYOPTION QueryOption, DWORD dwQueryFlags, LPVOID pBuffer, DWORD cbBuffer,
DWORD* pcbBuf,
+ DWORD dwReserved)
+{
+ MimeHtmlProtocol *This = impl_from_IInternetProtocolInfo(iface);
+ FIXME("(%p)->(%s %08x %08x %p %d %p %d)\n", This, debugstr_w(pwzUrl),
QueryOption, dwQueryFlags, pBuffer,
+ cbBuffer, pcbBuf, dwReserved);
+ return INET_E_USE_DEFAULT_PROTOCOLHANDLER;
+}
+
+static const IInternetProtocolInfoVtbl MimeHtmlProtocolInfoVtbl = {
+ MimeHtmlProtocolInfo_QueryInterface,
+ MimeHtmlProtocolInfo_AddRef,
+ MimeHtmlProtocolInfo_Release,
+ MimeHtmlProtocolInfo_ParseUrl,
+ MimeHtmlProtocolInfo_CombineUrl,
+ MimeHtmlProtocolInfo_CompareUrl,
+ MimeHtmlProtocolInfo_QueryInfo
+};
+
+HRESULT MimeHtmlProtocol_create(IUnknown *outer, void **obj)
+{
+ MimeHtmlProtocol *protocol;
+
+ protocol = heap_alloc(sizeof(*protocol));
+ if(!protocol)
+ return E_OUTOFMEMORY;
+
+ protocol->IUnknown_inner.lpVtbl = &MimeHtmlProtocolInnerVtbl;
+ protocol->IInternetProtocol_iface.lpVtbl = &MimeHtmlProtocolVtbl;
+ protocol->IInternetProtocolInfo_iface.lpVtbl = &MimeHtmlProtocolInfoVtbl;
+ protocol->ref = 1;
+ protocol->outer_unk = outer ? outer : &protocol->IUnknown_inner;
+ protocol->location = NULL;
+ protocol->stream = NULL;
+ protocol->sink = NULL;
+
+ *obj = &protocol->IUnknown_inner;
+ return S_OK;
+}
Propchange: trunk/reactos/dll/win32/inetcomm/protocol.c
------------------------------------------------------------------------------
svn:eol-style = native
Modified: trunk/reactos/media/doc/README.WINE
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/media/doc/README.WINE?rev=…
==============================================================================
--- trunk/reactos/media/doc/README.WINE [iso-8859-1] (original)
+++ trunk/reactos/media/doc/README.WINE [iso-8859-1] Sun Mar 5 21:33:13 2017
@@ -78,7 +78,7 @@
reactos/dll/win32/imaadp32.acm # Synced to WineStaging-2.2
reactos/dll/win32/imagehlp # Synced to WineStaging-1.9.11
reactos/dll/win32/imm32 # Synced to Wine-1.7.27
-reactos/dll/win32/inetcomm # Synced to WineStaging-1.9.23
+reactos/dll/win32/inetcomm # Synced to WineStaging-2.2
reactos/dll/win32/inetmib1 # Synced to WineStaging-1.9.11
reactos/dll/win32/initpki # Synced to WineStaging-1.9.11
reactos/dll/win32/inseng # Synced to WineStaging-2.2