xref: /reactos/dll/win32/inetcomm/protocol.c (revision ae07dd64)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * Copyright 2017 Jacek Caban for CodeWeavers
3c2c66affSColin Finck  *
4c2c66affSColin Finck  * This library is free software; you can redistribute it and/or
5c2c66affSColin Finck  * modify it under the terms of the GNU Lesser General Public
6c2c66affSColin Finck  * License as published by the Free Software Foundation; either
7c2c66affSColin Finck  * version 2.1 of the License, or (at your option) any later version.
8c2c66affSColin Finck  *
9c2c66affSColin Finck  * This library is distributed in the hope that it will be useful,
10c2c66affSColin Finck  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11c2c66affSColin Finck  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12c2c66affSColin Finck  * Lesser General Public License for more details.
13c2c66affSColin Finck  *
14c2c66affSColin Finck  * You should have received a copy of the GNU Lesser General Public
15c2c66affSColin Finck  * License along with this library; if not, write to the Free Software
16c2c66affSColin Finck  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17c2c66affSColin Finck  */
18c2c66affSColin Finck 
19af764263SAmine Khaldi #define COBJMACROS
20af764263SAmine Khaldi #define NONAMELESSUNION
21c2c66affSColin Finck 
22c2c66affSColin Finck #include <assert.h>
23c2c66affSColin Finck 
24af764263SAmine Khaldi #include "mimeole.h"
25af764263SAmine Khaldi #include "inetcomm_private.h"
26af764263SAmine Khaldi 
27af764263SAmine Khaldi #include "wine/debug.h"
28af764263SAmine Khaldi #include "wine/heap.h"
29af764263SAmine Khaldi 
30af764263SAmine Khaldi WINE_DEFAULT_DEBUG_CHANNEL(inetcomm);
31af764263SAmine Khaldi 
32c2c66affSColin Finck typedef struct {
33c2c66affSColin Finck     IUnknown IUnknown_inner;
34c2c66affSColin Finck     IInternetProtocol IInternetProtocol_iface;
35c2c66affSColin Finck     IInternetProtocolInfo IInternetProtocolInfo_iface;
36c2c66affSColin Finck 
37c2c66affSColin Finck     LONG ref;
38c2c66affSColin Finck     IUnknown *outer_unk;
39c2c66affSColin Finck 
40c2c66affSColin Finck     WCHAR *location;
41c2c66affSColin Finck     IStream *stream;
42c2c66affSColin Finck     IInternetProtocolSink *sink;
43c2c66affSColin Finck } MimeHtmlProtocol;
44c2c66affSColin Finck 
45c2c66affSColin Finck typedef struct {
46c2c66affSColin Finck     const WCHAR *mhtml;
47c2c66affSColin Finck     size_t mhtml_len;
48c2c66affSColin Finck     const WCHAR *location;
49c2c66affSColin Finck } mhtml_url_t;
50c2c66affSColin Finck 
51c2c66affSColin Finck typedef struct {
52c2c66affSColin Finck     IBindStatusCallback IBindStatusCallback_iface;
53c2c66affSColin Finck 
54c2c66affSColin Finck     LONG ref;
55c2c66affSColin Finck 
56c2c66affSColin Finck     MimeHtmlProtocol *protocol;
57c2c66affSColin Finck     HRESULT status;
58c2c66affSColin Finck     IStream *stream;
59c2c66affSColin Finck     WCHAR url[1];
60c2c66affSColin Finck } MimeHtmlBinding;
61c2c66affSColin Finck 
62c2c66affSColin Finck static const WCHAR mhtml_prefixW[] = {'m','h','t','m','l',':'};
63c2c66affSColin Finck static const WCHAR mhtml_separatorW[] = {'!','x','-','u','s','c',':'};
64c2c66affSColin Finck 
heap_strdupW(LPCWSTR str)65c2c66affSColin Finck static inline LPWSTR heap_strdupW(LPCWSTR str)
66c2c66affSColin Finck {
67c2c66affSColin Finck     LPWSTR ret = NULL;
68c2c66affSColin Finck 
69c2c66affSColin Finck     if(str) {
70c2c66affSColin Finck         DWORD size;
71c2c66affSColin Finck 
72*ae07dd64SAmine Khaldi         size = (lstrlenW(str)+1)*sizeof(WCHAR);
73c2c66affSColin Finck         ret = heap_alloc(size);
74c2c66affSColin Finck         if(ret)
75c2c66affSColin Finck             memcpy(ret, str, size);
76c2c66affSColin Finck     }
77c2c66affSColin Finck 
78c2c66affSColin Finck     return ret;
79c2c66affSColin Finck }
80c2c66affSColin Finck 
parse_mhtml_url(const WCHAR * url,mhtml_url_t * r)81c2c66affSColin Finck static HRESULT parse_mhtml_url(const WCHAR *url, mhtml_url_t *r)
82c2c66affSColin Finck {
83c2c66affSColin Finck     const WCHAR *p;
84c2c66affSColin Finck 
85*ae07dd64SAmine Khaldi     if(_wcsnicmp(url, mhtml_prefixW, ARRAY_SIZE(mhtml_prefixW)))
86c2c66affSColin Finck         return E_FAIL;
87c2c66affSColin Finck 
8833351fe5SAmine Khaldi     r->mhtml = url + ARRAY_SIZE(mhtml_prefixW);
89*ae07dd64SAmine Khaldi     p = wcschr(r->mhtml, '!');
90c2c66affSColin Finck     if(p) {
91c2c66affSColin Finck         r->mhtml_len = p - r->mhtml;
92c2c66affSColin Finck         /* FIXME: We handle '!' and '!x-usc:' in URLs as the same thing. Those should not be the same. */
93*ae07dd64SAmine Khaldi         if(!wcsncmp(p, mhtml_separatorW, ARRAY_SIZE(mhtml_separatorW)))
9433351fe5SAmine Khaldi             p += ARRAY_SIZE(mhtml_separatorW);
95c2c66affSColin Finck         else
96c2c66affSColin Finck             p++;
97c2c66affSColin Finck     }else {
98*ae07dd64SAmine Khaldi         r->mhtml_len = lstrlenW(r->mhtml);
99c2c66affSColin Finck     }
100c2c66affSColin Finck 
101c2c66affSColin Finck     r->location = p;
102c2c66affSColin Finck     return S_OK;
103c2c66affSColin Finck }
104c2c66affSColin Finck 
report_result(MimeHtmlProtocol * protocol,HRESULT result)105c2c66affSColin Finck static HRESULT report_result(MimeHtmlProtocol *protocol, HRESULT result)
106c2c66affSColin Finck {
107c2c66affSColin Finck     if(protocol->sink) {
108c2c66affSColin Finck         IInternetProtocolSink_ReportResult(protocol->sink, result, ERROR_SUCCESS, NULL);
109c2c66affSColin Finck         IInternetProtocolSink_Release(protocol->sink);
110c2c66affSColin Finck         protocol->sink = NULL;
111c2c66affSColin Finck     }
112c2c66affSColin Finck 
113c2c66affSColin Finck     return result;
114c2c66affSColin Finck }
115c2c66affSColin Finck 
on_mime_message_available(MimeHtmlProtocol * protocol,IMimeMessage * mime_message)116c2c66affSColin Finck static HRESULT on_mime_message_available(MimeHtmlProtocol *protocol, IMimeMessage *mime_message)
117c2c66affSColin Finck {
118c2c66affSColin Finck     FINDBODY find = {NULL};
119c2c66affSColin Finck     IMimeBody *mime_body;
120c2c66affSColin Finck     PROPVARIANT value;
121c2c66affSColin Finck     HBODY body;
122c2c66affSColin Finck     HRESULT hres;
123c2c66affSColin Finck 
124c2c66affSColin Finck     hres = IMimeMessage_FindFirst(mime_message, &find, &body);
125c2c66affSColin Finck     if(FAILED(hres))
126c2c66affSColin Finck         return report_result(protocol, hres);
127c2c66affSColin Finck 
128c2c66affSColin Finck     if(protocol->location) {
129c2c66affSColin Finck         BOOL found = FALSE;
130c2c66affSColin Finck         do {
131c2c66affSColin Finck             hres = IMimeMessage_FindNext(mime_message, &find, &body);
132c2c66affSColin Finck             if(FAILED(hres)) {
133c2c66affSColin Finck                 WARN("location %s not found\n", debugstr_w(protocol->location));
134c2c66affSColin Finck                 return report_result(protocol, hres);
135c2c66affSColin Finck             }
136c2c66affSColin Finck 
137c2c66affSColin Finck             value.vt = VT_LPWSTR;
138c2c66affSColin Finck             hres = IMimeMessage_GetBodyProp(mime_message, body, "content-location", 0, &value);
139c2c66affSColin Finck             if(hres == MIME_E_NOT_FOUND)
140c2c66affSColin Finck                 continue;
141c2c66affSColin Finck             if(FAILED(hres))
142c2c66affSColin Finck                 return report_result(protocol, hres);
143c2c66affSColin Finck 
144*ae07dd64SAmine Khaldi             found = !lstrcmpW(protocol->location, value.u.pwszVal);
145c2c66affSColin Finck             PropVariantClear(&value);
146c2c66affSColin Finck         }while(!found);
147c2c66affSColin Finck     }else {
148c2c66affSColin Finck         hres = IMimeMessage_FindNext(mime_message, &find, &body);
149c2c66affSColin Finck         if(FAILED(hres)) {
150c2c66affSColin Finck             WARN("location %s not found\n", debugstr_w(protocol->location));
151c2c66affSColin Finck             return report_result(protocol, hres);
152c2c66affSColin Finck         }
153c2c66affSColin Finck     }
154c2c66affSColin Finck 
155c2c66affSColin Finck     hres = IMimeMessage_BindToObject(mime_message, body, &IID_IMimeBody, (void**)&mime_body);
156c2c66affSColin Finck     if(FAILED(hres))
157c2c66affSColin Finck         return report_result(protocol, hres);
158c2c66affSColin Finck 
159c2c66affSColin Finck     value.vt = VT_LPWSTR;
160c2c66affSColin Finck     hres = IMimeBody_GetProp(mime_body, "content-type", 0, &value);
161c2c66affSColin Finck     if(SUCCEEDED(hres)) {
162c2c66affSColin Finck         hres = IInternetProtocolSink_ReportProgress(protocol->sink, BINDSTATUS_MIMETYPEAVAILABLE, value.u.pwszVal);
163c2c66affSColin Finck         PropVariantClear(&value);
164c2c66affSColin Finck     }
165c2c66affSColin Finck 
166c2c66affSColin Finck     /* FIXME: Create and report cache file. */
167c2c66affSColin Finck 
168c2c66affSColin Finck     hres = IMimeBody_GetData(mime_body, IET_DECODED, &protocol->stream);
169c2c66affSColin Finck     if(FAILED(hres))
170c2c66affSColin Finck         return report_result(protocol, hres);
171c2c66affSColin Finck 
172c2c66affSColin Finck     IInternetProtocolSink_ReportData(protocol->sink, BSCF_FIRSTDATANOTIFICATION
173c2c66affSColin Finck                                      | BSCF_INTERMEDIATEDATANOTIFICATION
174c2c66affSColin Finck                                      | BSCF_LASTDATANOTIFICATION
175c2c66affSColin Finck                                      | BSCF_DATAFULLYAVAILABLE
176c2c66affSColin Finck                                      | BSCF_AVAILABLEDATASIZEUNKNOWN, 0, 0);
177c2c66affSColin Finck 
178c2c66affSColin Finck     return report_result(protocol, S_OK);
179c2c66affSColin Finck }
180c2c66affSColin Finck 
load_mime_message(IStream * stream,IMimeMessage ** ret)181c2c66affSColin Finck static HRESULT load_mime_message(IStream *stream, IMimeMessage **ret)
182c2c66affSColin Finck {
183c2c66affSColin Finck     IMimeMessage *mime_message;
184c2c66affSColin Finck     HRESULT hres;
185c2c66affSColin Finck 
186c2c66affSColin Finck     hres = MimeMessage_create(NULL, (void**)&mime_message);
187c2c66affSColin Finck     if(FAILED(hres))
188c2c66affSColin Finck         return hres;
189c2c66affSColin Finck 
190c2c66affSColin Finck     IMimeMessage_InitNew(mime_message);
191c2c66affSColin Finck 
192c2c66affSColin Finck     hres = IMimeMessage_Load(mime_message, stream);
193c2c66affSColin Finck     if(FAILED(hres)) {
194c2c66affSColin Finck         IMimeMessage_Release(mime_message);
195c2c66affSColin Finck         return hres;
196c2c66affSColin Finck     }
197c2c66affSColin Finck 
198c2c66affSColin Finck     *ret = mime_message;
199c2c66affSColin Finck     return S_OK;
200c2c66affSColin Finck }
201c2c66affSColin Finck 
impl_from_IBindStatusCallback(IBindStatusCallback * iface)202c2c66affSColin Finck static inline MimeHtmlBinding *impl_from_IBindStatusCallback(IBindStatusCallback *iface)
203c2c66affSColin Finck {
204c2c66affSColin Finck     return CONTAINING_RECORD(iface, MimeHtmlBinding, IBindStatusCallback_iface);
205c2c66affSColin Finck }
206c2c66affSColin Finck 
BindStatusCallback_QueryInterface(IBindStatusCallback * iface,REFIID riid,void ** ppv)207c2c66affSColin Finck static HRESULT WINAPI BindStatusCallback_QueryInterface(IBindStatusCallback *iface,
208c2c66affSColin Finck         REFIID riid, void **ppv)
209c2c66affSColin Finck {
210c2c66affSColin Finck     MimeHtmlBinding *This = impl_from_IBindStatusCallback(iface);
211c2c66affSColin Finck 
212c2c66affSColin Finck     if(IsEqualGUID(&IID_IUnknown, riid)) {
213c2c66affSColin Finck         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
214c2c66affSColin Finck         *ppv = &This->IBindStatusCallback_iface;
215c2c66affSColin Finck     }else if(IsEqualGUID(&IID_IBindStatusCallback, riid)) {
216c2c66affSColin Finck         TRACE("(%p)->(IID_IBindStatusCallback %p)\n", This, ppv);
217c2c66affSColin Finck         *ppv = &This->IBindStatusCallback_iface;
218c2c66affSColin Finck     }else {
219c2c66affSColin Finck         TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
220c2c66affSColin Finck         *ppv = NULL;
221c2c66affSColin Finck         return E_NOINTERFACE;
222c2c66affSColin Finck     }
223c2c66affSColin Finck 
224c2c66affSColin Finck     IUnknown_AddRef((IUnknown*)*ppv);
225c2c66affSColin Finck     return S_OK;
226c2c66affSColin Finck }
227c2c66affSColin Finck 
BindStatusCallback_AddRef(IBindStatusCallback * iface)228c2c66affSColin Finck static ULONG WINAPI BindStatusCallback_AddRef(IBindStatusCallback *iface)
229c2c66affSColin Finck {
230c2c66affSColin Finck     MimeHtmlBinding *This = impl_from_IBindStatusCallback(iface);
231c2c66affSColin Finck     LONG ref = InterlockedIncrement(&This->ref);
232c2c66affSColin Finck 
233c2c66affSColin Finck     TRACE("(%p) ref=%d\n", This, ref);
234c2c66affSColin Finck 
235c2c66affSColin Finck     return ref;
236c2c66affSColin Finck }
237c2c66affSColin Finck 
BindStatusCallback_Release(IBindStatusCallback * iface)238c2c66affSColin Finck static ULONG WINAPI BindStatusCallback_Release(IBindStatusCallback *iface)
239c2c66affSColin Finck {
240c2c66affSColin Finck     MimeHtmlBinding *This = impl_from_IBindStatusCallback(iface);
241c2c66affSColin Finck     LONG ref = InterlockedDecrement(&This->ref);
242c2c66affSColin Finck 
243c2c66affSColin Finck     TRACE("(%p) ref=%d\n", This, ref);
244c2c66affSColin Finck 
245c2c66affSColin Finck     if(!ref) {
246c2c66affSColin Finck         if(This->protocol)
247c2c66affSColin Finck             IInternetProtocol_Release(&This->protocol->IInternetProtocol_iface);
248c2c66affSColin Finck         if(This->stream)
249c2c66affSColin Finck             IStream_Release(This->stream);
250c2c66affSColin Finck         heap_free(This);
251c2c66affSColin Finck     }
252c2c66affSColin Finck 
253c2c66affSColin Finck     return ref;
254c2c66affSColin Finck }
255c2c66affSColin Finck 
BindStatusCallback_OnStartBinding(IBindStatusCallback * iface,DWORD dwReserved,IBinding * pib)256c2c66affSColin Finck static HRESULT WINAPI BindStatusCallback_OnStartBinding(IBindStatusCallback *iface,
257c2c66affSColin Finck         DWORD dwReserved, IBinding *pib)
258c2c66affSColin Finck {
259c2c66affSColin Finck     MimeHtmlBinding *This = impl_from_IBindStatusCallback(iface);
260c2c66affSColin Finck 
261c2c66affSColin Finck     TRACE("(%p)->(%x %p)\n", This, dwReserved, pib);
262c2c66affSColin Finck 
263c2c66affSColin Finck     assert(!This->stream);
264c2c66affSColin Finck     return CreateStreamOnHGlobal(NULL, TRUE, &This->stream);
265c2c66affSColin Finck }
266c2c66affSColin Finck 
BindStatusCallback_GetPriority(IBindStatusCallback * iface,LONG * pnPriority)267c2c66affSColin Finck static HRESULT WINAPI BindStatusCallback_GetPriority(IBindStatusCallback *iface, LONG *pnPriority)
268c2c66affSColin Finck {
269c2c66affSColin Finck     return E_NOTIMPL;
270c2c66affSColin Finck }
271c2c66affSColin Finck 
BindStatusCallback_OnLowResource(IBindStatusCallback * iface,DWORD dwReserved)272c2c66affSColin Finck static HRESULT WINAPI BindStatusCallback_OnLowResource(IBindStatusCallback *iface, DWORD dwReserved)
273c2c66affSColin Finck {
274c2c66affSColin Finck     return E_NOTIMPL;
275c2c66affSColin Finck }
276c2c66affSColin Finck 
BindStatusCallback_OnProgress(IBindStatusCallback * iface,ULONG ulProgress,ULONG ulProgressMax,ULONG ulStatusCode,LPCWSTR szStatusText)277c2c66affSColin Finck static HRESULT WINAPI BindStatusCallback_OnProgress(IBindStatusCallback *iface, ULONG ulProgress,
278c2c66affSColin Finck         ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
279c2c66affSColin Finck {
280c2c66affSColin Finck     MimeHtmlBinding *This = impl_from_IBindStatusCallback(iface);
281c2c66affSColin Finck     TRACE("(%p)->(%u/%u %u %s)\n", This, ulProgress, ulProgressMax, ulStatusCode, debugstr_w(szStatusText));
282c2c66affSColin Finck     return S_OK;
283c2c66affSColin Finck }
284c2c66affSColin Finck 
BindStatusCallback_OnStopBinding(IBindStatusCallback * iface,HRESULT hresult,LPCWSTR szError)285c2c66affSColin Finck static HRESULT WINAPI BindStatusCallback_OnStopBinding(IBindStatusCallback *iface, HRESULT hresult, LPCWSTR szError)
286c2c66affSColin Finck {
287c2c66affSColin Finck     MimeHtmlBinding *This = impl_from_IBindStatusCallback(iface);
288c2c66affSColin Finck     IMimeMessage *mime_message = NULL;
289c2c66affSColin Finck 
290c2c66affSColin Finck     TRACE("(%p)->(%x %s)\n", This, hresult, debugstr_w(szError));
291c2c66affSColin Finck 
292c2c66affSColin Finck     if(SUCCEEDED(hresult)) {
293c2c66affSColin Finck         hresult = load_mime_message(This->stream, &mime_message);
294c2c66affSColin Finck         IStream_Release(This->stream);
295c2c66affSColin Finck         This->stream = NULL;
296c2c66affSColin Finck     }
297c2c66affSColin Finck 
298c2c66affSColin Finck     This->status = hresult;
299c2c66affSColin Finck 
300c2c66affSColin Finck     if(mime_message)
301c2c66affSColin Finck         on_mime_message_available(This->protocol, mime_message);
302c2c66affSColin Finck     else
303c2c66affSColin Finck         report_result(This->protocol, hresult);
304c2c66affSColin Finck 
305c2c66affSColin Finck     if(mime_message)
306c2c66affSColin Finck         IMimeMessage_Release(mime_message);
307c2c66affSColin Finck     IInternetProtocol_Release(&This->protocol->IInternetProtocol_iface);
308c2c66affSColin Finck     This->protocol = NULL;
309c2c66affSColin Finck     return S_OK;
310c2c66affSColin Finck }
311c2c66affSColin Finck 
BindStatusCallback_GetBindInfo(IBindStatusCallback * iface,DWORD * grfBINDF,BINDINFO * pbindinfo)312c2c66affSColin Finck static HRESULT WINAPI BindStatusCallback_GetBindInfo(IBindStatusCallback *iface,
313c2c66affSColin Finck         DWORD* grfBINDF, BINDINFO* pbindinfo)
314c2c66affSColin Finck {
315c2c66affSColin Finck     MimeHtmlBinding *This = impl_from_IBindStatusCallback(iface);
316c2c66affSColin Finck 
317c2c66affSColin Finck     TRACE("(%p)\n", This);
318c2c66affSColin Finck 
319c2c66affSColin Finck     *grfBINDF = BINDF_ASYNCHRONOUS;
320c2c66affSColin Finck     return S_OK;
321c2c66affSColin Finck }
322c2c66affSColin Finck 
BindStatusCallback_OnDataAvailable(IBindStatusCallback * iface,DWORD grfBSCF,DWORD dwSize,FORMATETC * pformatetc,STGMEDIUM * pstgmed)323c2c66affSColin Finck static HRESULT WINAPI BindStatusCallback_OnDataAvailable(IBindStatusCallback *iface, DWORD grfBSCF,
324c2c66affSColin Finck         DWORD dwSize, FORMATETC* pformatetc, STGMEDIUM* pstgmed)
325c2c66affSColin Finck {
326c2c66affSColin Finck     MimeHtmlBinding *This = impl_from_IBindStatusCallback(iface);
327c2c66affSColin Finck     BYTE buf[4*1024];
328c2c66affSColin Finck     DWORD read;
329c2c66affSColin Finck     HRESULT hres;
330c2c66affSColin Finck 
331c2c66affSColin Finck     TRACE("(%p)\n", This);
332c2c66affSColin Finck 
333c2c66affSColin Finck     assert(pstgmed->tymed == TYMED_ISTREAM);
334c2c66affSColin Finck 
335c2c66affSColin Finck     while(1) {
336c2c66affSColin Finck         hres = IStream_Read(pstgmed->u.pstm, buf, sizeof(buf), &read);
337c2c66affSColin Finck         if(FAILED(hres))
338c2c66affSColin Finck             return hres;
339c2c66affSColin Finck         if(!read)
340c2c66affSColin Finck             break;
341c2c66affSColin Finck         hres = IStream_Write(This->stream, buf, read, NULL);
342c2c66affSColin Finck         if(FAILED(hres))
343c2c66affSColin Finck             return hres;
344c2c66affSColin Finck     }
345c2c66affSColin Finck     return S_OK;
346c2c66affSColin Finck }
347c2c66affSColin Finck 
BindStatusCallback_OnObjectAvailable(IBindStatusCallback * iface,REFIID riid,IUnknown * punk)348c2c66affSColin Finck static HRESULT WINAPI BindStatusCallback_OnObjectAvailable(IBindStatusCallback *iface,
349c2c66affSColin Finck         REFIID riid, IUnknown* punk)
350c2c66affSColin Finck {
351c2c66affSColin Finck     ERR("\n");
352c2c66affSColin Finck     return E_NOTIMPL;
353c2c66affSColin Finck }
354c2c66affSColin Finck 
355c2c66affSColin Finck static const IBindStatusCallbackVtbl BindStatusCallbackVtbl = {
356c2c66affSColin Finck     BindStatusCallback_QueryInterface,
357c2c66affSColin Finck     BindStatusCallback_AddRef,
358c2c66affSColin Finck     BindStatusCallback_Release,
359c2c66affSColin Finck     BindStatusCallback_OnStartBinding,
360c2c66affSColin Finck     BindStatusCallback_GetPriority,
361c2c66affSColin Finck     BindStatusCallback_OnLowResource,
362c2c66affSColin Finck     BindStatusCallback_OnProgress,
363c2c66affSColin Finck     BindStatusCallback_OnStopBinding,
364c2c66affSColin Finck     BindStatusCallback_GetBindInfo,
365c2c66affSColin Finck     BindStatusCallback_OnDataAvailable,
366c2c66affSColin Finck     BindStatusCallback_OnObjectAvailable
367c2c66affSColin Finck };
368c2c66affSColin Finck 
impl_from_IUnknown(IUnknown * iface)369c2c66affSColin Finck static inline MimeHtmlProtocol *impl_from_IUnknown(IUnknown *iface)
370c2c66affSColin Finck {
371c2c66affSColin Finck     return CONTAINING_RECORD(iface, MimeHtmlProtocol, IUnknown_inner);
372c2c66affSColin Finck }
373c2c66affSColin Finck 
MimeHtmlProtocol_QueryInterface(IUnknown * iface,REFIID riid,void ** ppv)374c2c66affSColin Finck static HRESULT WINAPI MimeHtmlProtocol_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
375c2c66affSColin Finck {
376c2c66affSColin Finck     MimeHtmlProtocol *This = impl_from_IUnknown(iface);
377c2c66affSColin Finck 
378c2c66affSColin Finck     if(IsEqualGUID(&IID_IUnknown, riid)) {
379c2c66affSColin Finck         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
380c2c66affSColin Finck         *ppv = &This->IInternetProtocol_iface;
381c2c66affSColin Finck     }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
382c2c66affSColin Finck         TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv);
383c2c66affSColin Finck         *ppv = &This->IInternetProtocol_iface;
384c2c66affSColin Finck     }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
385c2c66affSColin Finck         TRACE("(%p)->(IID_IInternetProtocol %p)\n", This, ppv);
386c2c66affSColin Finck         *ppv = &This->IInternetProtocol_iface;
387c2c66affSColin Finck     }else if(IsEqualGUID(&IID_IInternetProtocolInfo, riid)) {
388c2c66affSColin Finck         TRACE("(%p)->(IID_IInternetProtocolInfo %p)\n", This, ppv);
389c2c66affSColin Finck         *ppv = &This->IInternetProtocolInfo_iface;
390c2c66affSColin Finck     }else {
391c2c66affSColin Finck         FIXME("unknown interface %s\n", debugstr_guid(riid));
392c2c66affSColin Finck         *ppv = NULL;
393c2c66affSColin Finck         return E_NOINTERFACE;
394c2c66affSColin Finck     }
395c2c66affSColin Finck 
396c2c66affSColin Finck     IUnknown_AddRef((IUnknown*)*ppv);
397c2c66affSColin Finck     return S_OK;
398c2c66affSColin Finck }
399c2c66affSColin Finck 
MimeHtmlProtocol_AddRef(IUnknown * iface)400c2c66affSColin Finck static ULONG WINAPI MimeHtmlProtocol_AddRef(IUnknown *iface)
401c2c66affSColin Finck {
402c2c66affSColin Finck     MimeHtmlProtocol *This = impl_from_IUnknown(iface);
403c2c66affSColin Finck     ULONG ref = InterlockedIncrement(&This->ref);
404c2c66affSColin Finck 
405c2c66affSColin Finck     TRACE("(%p) ref=%d\n", This, ref);
406c2c66affSColin Finck 
407c2c66affSColin Finck     return ref;
408c2c66affSColin Finck }
409c2c66affSColin Finck 
MimeHtmlProtocol_Release(IUnknown * iface)410c2c66affSColin Finck static ULONG WINAPI MimeHtmlProtocol_Release(IUnknown *iface)
411c2c66affSColin Finck {
412c2c66affSColin Finck     MimeHtmlProtocol *This = impl_from_IUnknown(iface);
413c2c66affSColin Finck     ULONG ref = InterlockedDecrement(&This->ref);
414c2c66affSColin Finck 
415c2c66affSColin Finck     TRACE("(%p) ref=%x\n", This, ref);
416c2c66affSColin Finck 
417c2c66affSColin Finck     if(!ref) {
418c2c66affSColin Finck         if(This->sink)
419c2c66affSColin Finck             IInternetProtocolSink_Release(This->sink);
420c2c66affSColin Finck         if(This->stream)
421c2c66affSColin Finck             IStream_Release(This->stream);
422c2c66affSColin Finck         heap_free(This->location);
423c2c66affSColin Finck         heap_free(This);
424c2c66affSColin Finck     }
425c2c66affSColin Finck 
426c2c66affSColin Finck     return ref;
427c2c66affSColin Finck }
428c2c66affSColin Finck 
429c2c66affSColin Finck static const IUnknownVtbl MimeHtmlProtocolInnerVtbl = {
430c2c66affSColin Finck     MimeHtmlProtocol_QueryInterface,
431c2c66affSColin Finck     MimeHtmlProtocol_AddRef,
432c2c66affSColin Finck     MimeHtmlProtocol_Release
433c2c66affSColin Finck };
434c2c66affSColin Finck 
impl_from_IInternetProtocol(IInternetProtocol * iface)435c2c66affSColin Finck static inline MimeHtmlProtocol *impl_from_IInternetProtocol(IInternetProtocol *iface)
436c2c66affSColin Finck {
437c2c66affSColin Finck     return CONTAINING_RECORD(iface, MimeHtmlProtocol, IInternetProtocol_iface);
438c2c66affSColin Finck }
439c2c66affSColin Finck 
InternetProtocol_QueryInterface(IInternetProtocol * iface,REFIID riid,void ** ppv)440c2c66affSColin Finck static HRESULT WINAPI InternetProtocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
441c2c66affSColin Finck {
442c2c66affSColin Finck     MimeHtmlProtocol *This = impl_from_IInternetProtocol(iface);
443c2c66affSColin Finck     return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
444c2c66affSColin Finck }
445c2c66affSColin Finck 
InternetProtocol_AddRef(IInternetProtocol * iface)446c2c66affSColin Finck static ULONG WINAPI InternetProtocol_AddRef(IInternetProtocol *iface)
447c2c66affSColin Finck {
448c2c66affSColin Finck     MimeHtmlProtocol *This = impl_from_IInternetProtocol(iface);
449c2c66affSColin Finck     return IUnknown_AddRef(This->outer_unk);
450c2c66affSColin Finck }
451c2c66affSColin Finck 
InternetProtocol_Release(IInternetProtocol * iface)452c2c66affSColin Finck static ULONG WINAPI InternetProtocol_Release(IInternetProtocol *iface)
453c2c66affSColin Finck {
454c2c66affSColin Finck     MimeHtmlProtocol *This = impl_from_IInternetProtocol(iface);
455c2c66affSColin Finck     return IUnknown_Release(This->outer_unk);
456c2c66affSColin Finck }
457c2c66affSColin Finck 
MimeHtmlProtocol_Start(IInternetProtocol * iface,const WCHAR * szUrl,IInternetProtocolSink * pOIProtSink,IInternetBindInfo * pOIBindInfo,DWORD grfPI,HANDLE_PTR dwReserved)458c2c66affSColin Finck static HRESULT WINAPI MimeHtmlProtocol_Start(IInternetProtocol *iface, const WCHAR *szUrl,
459c2c66affSColin Finck         IInternetProtocolSink* pOIProtSink, IInternetBindInfo* pOIBindInfo,
460c2c66affSColin Finck         DWORD grfPI, HANDLE_PTR dwReserved)
461c2c66affSColin Finck {
462c2c66affSColin Finck     MimeHtmlProtocol *This = impl_from_IInternetProtocol(iface);
463c2c66affSColin Finck     BINDINFO bindinfo = { sizeof(bindinfo) };
464c2c66affSColin Finck     MimeHtmlBinding *binding;
465c2c66affSColin Finck     IBindCtx *bind_ctx;
466c2c66affSColin Finck     IStream *stream;
467c2c66affSColin Finck     mhtml_url_t url;
468c2c66affSColin Finck     DWORD bindf = 0;
469c2c66affSColin Finck     IMoniker *mon;
470c2c66affSColin Finck     HRESULT hres;
471c2c66affSColin Finck 
472c2c66affSColin Finck     TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink, pOIBindInfo, grfPI, dwReserved);
473c2c66affSColin Finck 
474c2c66affSColin Finck     hres = parse_mhtml_url(szUrl, &url);
475c2c66affSColin Finck     if(FAILED(hres))
476c2c66affSColin Finck         return hres;
477c2c66affSColin Finck 
478c2c66affSColin Finck     if(url.location && !(This->location = heap_strdupW(url.location)))
479c2c66affSColin Finck         return E_OUTOFMEMORY;
480c2c66affSColin Finck 
481c2c66affSColin Finck     hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &bindf, &bindinfo);
482c2c66affSColin Finck     if(FAILED(hres)) {
483c2c66affSColin Finck         WARN("GetBindInfo failed: %08x\n", hres);
484c2c66affSColin Finck         return hres;
485c2c66affSColin Finck     }
486c2c66affSColin Finck     if((bindf & (BINDF_ASYNCHRONOUS|BINDF_FROMURLMON|BINDF_NEEDFILE)) != (BINDF_ASYNCHRONOUS|BINDF_FROMURLMON|BINDF_NEEDFILE))
487c2c66affSColin Finck         FIXME("unsupported bindf %x\n", bindf);
488c2c66affSColin Finck 
489af764263SAmine Khaldi     IInternetProtocolSink_AddRef(This->sink = pOIProtSink);
490c2c66affSColin Finck 
491c2c66affSColin Finck     binding = heap_alloc(FIELD_OFFSET(MimeHtmlBinding,  url[url.mhtml_len+1]));
492c2c66affSColin Finck     if(!binding)
493c2c66affSColin Finck         return E_OUTOFMEMORY;
494c2c66affSColin Finck     memcpy(binding->url, url.mhtml, url.mhtml_len*sizeof(WCHAR));
495c2c66affSColin Finck     binding->url[url.mhtml_len] = 0;
496c2c66affSColin Finck 
497c2c66affSColin Finck     hres = CreateURLMoniker(NULL, binding->url, &mon);
498c2c66affSColin Finck     if(FAILED(hres)) {
499c2c66affSColin Finck         heap_free(binding);
500c2c66affSColin Finck         return hres;
501c2c66affSColin Finck     }
502c2c66affSColin Finck 
503c2c66affSColin Finck     binding->IBindStatusCallback_iface.lpVtbl = &BindStatusCallbackVtbl;
504c2c66affSColin Finck     binding->ref = 1;
505c2c66affSColin Finck     binding->status = E_PENDING;
506c2c66affSColin Finck     binding->stream = NULL;
507c2c66affSColin Finck     binding->protocol = NULL;
508c2c66affSColin Finck 
509c2c66affSColin Finck     hres = CreateAsyncBindCtx(0, &binding->IBindStatusCallback_iface, NULL, &bind_ctx);
510c2c66affSColin Finck     if(FAILED(hres)) {
511c2c66affSColin Finck         IMoniker_Release(mon);
512c2c66affSColin Finck         IBindStatusCallback_Release(&binding->IBindStatusCallback_iface);
513c2c66affSColin Finck         return hres;
514c2c66affSColin Finck     }
515c2c66affSColin Finck 
516c2c66affSColin Finck     IInternetProtocol_AddRef(&This->IInternetProtocol_iface);
517c2c66affSColin Finck     binding->protocol = This;
518c2c66affSColin Finck 
519c2c66affSColin Finck     hres = IMoniker_BindToStorage(mon, bind_ctx, NULL, &IID_IStream, (void**)&stream);
520c2c66affSColin Finck     IBindCtx_Release(bind_ctx);
521c2c66affSColin Finck     IMoniker_Release(mon);
522c2c66affSColin Finck     if(stream)
523c2c66affSColin Finck         IStream_Release(stream);
524c2c66affSColin Finck     hres = binding->status;
525c2c66affSColin Finck     IBindStatusCallback_Release(&binding->IBindStatusCallback_iface);
526c2c66affSColin Finck     if(FAILED(hres) && hres != E_PENDING)
527c2c66affSColin Finck         report_result(This, hres);
528c2c66affSColin Finck     return hres;
529c2c66affSColin Finck }
530c2c66affSColin Finck 
MimeHtmlProtocol_Continue(IInternetProtocol * iface,PROTOCOLDATA * pProtocolData)531c2c66affSColin Finck static HRESULT WINAPI MimeHtmlProtocol_Continue(IInternetProtocol *iface, PROTOCOLDATA *pProtocolData)
532c2c66affSColin Finck {
533c2c66affSColin Finck     MimeHtmlProtocol *This = impl_from_IInternetProtocol(iface);
534c2c66affSColin Finck     FIXME("(%p)->(%p)\n", This, pProtocolData);
535c2c66affSColin Finck     return E_NOTIMPL;
536c2c66affSColin Finck }
537c2c66affSColin Finck 
MimeHtmlProtocol_Abort(IInternetProtocol * iface,HRESULT hrReason,DWORD dwOptions)538c2c66affSColin Finck static HRESULT WINAPI MimeHtmlProtocol_Abort(IInternetProtocol *iface, HRESULT hrReason, DWORD dwOptions)
539c2c66affSColin Finck {
540c2c66affSColin Finck     MimeHtmlProtocol *This = impl_from_IInternetProtocol(iface);
541c2c66affSColin Finck     FIXME("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
542c2c66affSColin Finck     return E_NOTIMPL;
543c2c66affSColin Finck }
544c2c66affSColin Finck 
MimeHtmlProtocol_Terminate(IInternetProtocol * iface,DWORD dwOptions)545c2c66affSColin Finck static HRESULT WINAPI MimeHtmlProtocol_Terminate(IInternetProtocol *iface, DWORD dwOptions)
546c2c66affSColin Finck {
547c2c66affSColin Finck     MimeHtmlProtocol *This = impl_from_IInternetProtocol(iface);
548c2c66affSColin Finck     TRACE("(%p)->(%08x)\n", This, dwOptions);
549c2c66affSColin Finck     return S_OK;
550c2c66affSColin Finck }
551c2c66affSColin Finck 
MimeHtmlProtocol_Suspend(IInternetProtocol * iface)552c2c66affSColin Finck static HRESULT WINAPI MimeHtmlProtocol_Suspend(IInternetProtocol *iface)
553c2c66affSColin Finck {
554c2c66affSColin Finck     MimeHtmlProtocol *This = impl_from_IInternetProtocol(iface);
555c2c66affSColin Finck     FIXME("(%p)\n", This);
556c2c66affSColin Finck     return E_NOTIMPL;
557c2c66affSColin Finck }
558c2c66affSColin Finck 
MimeHtmlProtocol_Resume(IInternetProtocol * iface)559c2c66affSColin Finck static HRESULT WINAPI MimeHtmlProtocol_Resume(IInternetProtocol *iface)
560c2c66affSColin Finck {
561c2c66affSColin Finck     MimeHtmlProtocol *This = impl_from_IInternetProtocol(iface);
562c2c66affSColin Finck     FIXME("(%p)\n", This);
563c2c66affSColin Finck     return E_NOTIMPL;
564c2c66affSColin Finck }
565c2c66affSColin Finck 
MimeHtmlProtocol_Read(IInternetProtocol * iface,void * pv,ULONG cb,ULONG * pcbRead)566c2c66affSColin Finck static HRESULT WINAPI MimeHtmlProtocol_Read(IInternetProtocol *iface, void* pv, ULONG cb, ULONG* pcbRead)
567c2c66affSColin Finck {
568c2c66affSColin Finck     MimeHtmlProtocol *This = impl_from_IInternetProtocol(iface);
569c2c66affSColin Finck     ULONG read = 0;
570c2c66affSColin Finck     HRESULT hres;
571c2c66affSColin Finck 
572c2c66affSColin Finck     TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
573c2c66affSColin Finck 
574c2c66affSColin Finck     hres = IStream_Read(This->stream, pv, cb, &read);
575c2c66affSColin Finck     if(pcbRead)
576c2c66affSColin Finck         *pcbRead = read;
577c2c66affSColin Finck     if(hres != S_OK)
578c2c66affSColin Finck         return hres;
579c2c66affSColin Finck 
580c2c66affSColin Finck     return read ? S_OK : S_FALSE;
581c2c66affSColin Finck }
582c2c66affSColin Finck 
MimeHtmlProtocol_Seek(IInternetProtocol * iface,LARGE_INTEGER dlibMove,DWORD dwOrigin,ULARGE_INTEGER * plibNewPosition)583c2c66affSColin Finck static HRESULT WINAPI MimeHtmlProtocol_Seek(IInternetProtocol *iface, LARGE_INTEGER dlibMove,
584c2c66affSColin Finck         DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition)
585c2c66affSColin Finck {
586c2c66affSColin Finck     MimeHtmlProtocol *This = impl_from_IInternetProtocol(iface);
587c2c66affSColin Finck     FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
588c2c66affSColin Finck     return E_NOTIMPL;
589c2c66affSColin Finck }
590c2c66affSColin Finck 
MimeHtmlProtocol_LockRequest(IInternetProtocol * iface,DWORD dwOptions)591c2c66affSColin Finck static HRESULT WINAPI MimeHtmlProtocol_LockRequest(IInternetProtocol *iface, DWORD dwOptions)
592c2c66affSColin Finck {
593c2c66affSColin Finck     MimeHtmlProtocol *This = impl_from_IInternetProtocol(iface);
594c2c66affSColin Finck     FIXME("(%p)->(%d)\n", This, dwOptions);
595c2c66affSColin Finck     return S_OK;
596c2c66affSColin Finck }
597c2c66affSColin Finck 
MimeHtmlProtocol_UnlockRequest(IInternetProtocol * iface)598c2c66affSColin Finck static HRESULT WINAPI MimeHtmlProtocol_UnlockRequest(IInternetProtocol *iface)
599c2c66affSColin Finck {
600c2c66affSColin Finck     MimeHtmlProtocol *This = impl_from_IInternetProtocol(iface);
601c2c66affSColin Finck     FIXME("(%p)\n", This);
602c2c66affSColin Finck     return S_OK;
603c2c66affSColin Finck }
604c2c66affSColin Finck 
605c2c66affSColin Finck static const IInternetProtocolVtbl MimeHtmlProtocolVtbl = {
606c2c66affSColin Finck     InternetProtocol_QueryInterface,
607c2c66affSColin Finck     InternetProtocol_AddRef,
608c2c66affSColin Finck     InternetProtocol_Release,
609c2c66affSColin Finck     MimeHtmlProtocol_Start,
610c2c66affSColin Finck     MimeHtmlProtocol_Continue,
611c2c66affSColin Finck     MimeHtmlProtocol_Abort,
612c2c66affSColin Finck     MimeHtmlProtocol_Terminate,
613c2c66affSColin Finck     MimeHtmlProtocol_Suspend,
614c2c66affSColin Finck     MimeHtmlProtocol_Resume,
615c2c66affSColin Finck     MimeHtmlProtocol_Read,
616c2c66affSColin Finck     MimeHtmlProtocol_Seek,
617c2c66affSColin Finck     MimeHtmlProtocol_LockRequest,
618c2c66affSColin Finck     MimeHtmlProtocol_UnlockRequest
619c2c66affSColin Finck };
620c2c66affSColin Finck 
impl_from_IInternetProtocolInfo(IInternetProtocolInfo * iface)621c2c66affSColin Finck static inline MimeHtmlProtocol *impl_from_IInternetProtocolInfo(IInternetProtocolInfo *iface)
622c2c66affSColin Finck {
623c2c66affSColin Finck     return CONTAINING_RECORD(iface, MimeHtmlProtocol, IInternetProtocolInfo_iface);
624c2c66affSColin Finck }
625c2c66affSColin Finck 
MimeHtmlProtocolInfo_QueryInterface(IInternetProtocolInfo * iface,REFIID riid,void ** ppv)626c2c66affSColin Finck static HRESULT WINAPI MimeHtmlProtocolInfo_QueryInterface(IInternetProtocolInfo *iface, REFIID riid, void **ppv)
627c2c66affSColin Finck {
628c2c66affSColin Finck     MimeHtmlProtocol *This = impl_from_IInternetProtocolInfo(iface);
629c2c66affSColin Finck     return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
630c2c66affSColin Finck }
631c2c66affSColin Finck 
MimeHtmlProtocolInfo_AddRef(IInternetProtocolInfo * iface)632c2c66affSColin Finck static ULONG WINAPI MimeHtmlProtocolInfo_AddRef(IInternetProtocolInfo *iface)
633c2c66affSColin Finck {
634c2c66affSColin Finck     MimeHtmlProtocol *This = impl_from_IInternetProtocolInfo(iface);
635c2c66affSColin Finck     return IUnknown_AddRef(This->outer_unk);
636c2c66affSColin Finck }
637c2c66affSColin Finck 
MimeHtmlProtocolInfo_Release(IInternetProtocolInfo * iface)638c2c66affSColin Finck static ULONG WINAPI MimeHtmlProtocolInfo_Release(IInternetProtocolInfo *iface)
639c2c66affSColin Finck {
640c2c66affSColin Finck     MimeHtmlProtocol *This = impl_from_IInternetProtocolInfo(iface);
641c2c66affSColin Finck     return IUnknown_Release(This->outer_unk);
642c2c66affSColin Finck }
643c2c66affSColin Finck 
MimeHtmlProtocolInfo_ParseUrl(IInternetProtocolInfo * iface,LPCWSTR pwzUrl,PARSEACTION ParseAction,DWORD dwParseFlags,LPWSTR pwzResult,DWORD cchResult,DWORD * pcchResult,DWORD dwReserved)644c2c66affSColin Finck static HRESULT WINAPI MimeHtmlProtocolInfo_ParseUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
645c2c66affSColin Finck         PARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult,
646c2c66affSColin Finck         DWORD* pcchResult, DWORD dwReserved)
647c2c66affSColin Finck {
648c2c66affSColin Finck     MimeHtmlProtocol *This = impl_from_IInternetProtocolInfo(iface);
649c2c66affSColin Finck     FIXME("(%p)->(%s %d %x %p %d %p %d)\n", This, debugstr_w(pwzUrl), ParseAction,
650c2c66affSColin Finck           dwParseFlags, pwzResult, cchResult, pcchResult, dwReserved);
651c2c66affSColin Finck     return INET_E_DEFAULT_ACTION;
652c2c66affSColin Finck }
653c2c66affSColin Finck 
MimeHtmlProtocolInfo_CombineUrl(IInternetProtocolInfo * iface,LPCWSTR pwzBaseUrl,LPCWSTR pwzRelativeUrl,DWORD dwCombineFlags,LPWSTR pwzResult,DWORD cchResult,DWORD * pcchResult,DWORD dwReserved)654c2c66affSColin Finck static HRESULT WINAPI MimeHtmlProtocolInfo_CombineUrl(IInternetProtocolInfo *iface,
655c2c66affSColin Finck         LPCWSTR pwzBaseUrl, LPCWSTR pwzRelativeUrl, DWORD dwCombineFlags, LPWSTR pwzResult,
656c2c66affSColin Finck         DWORD cchResult, DWORD* pcchResult, DWORD dwReserved)
657c2c66affSColin Finck {
658c2c66affSColin Finck     MimeHtmlProtocol *This = impl_from_IInternetProtocolInfo(iface);
65933351fe5SAmine Khaldi     size_t len = ARRAY_SIZE(mhtml_prefixW);
660c2c66affSColin Finck     mhtml_url_t url;
661c2c66affSColin Finck     WCHAR *p;
662c2c66affSColin Finck     HRESULT hres;
663c2c66affSColin Finck 
664c2c66affSColin Finck     TRACE("(%p)->(%s %s %08x %p %d %p %d)\n", This, debugstr_w(pwzBaseUrl),
665c2c66affSColin Finck           debugstr_w(pwzRelativeUrl), dwCombineFlags, pwzResult, cchResult,
666c2c66affSColin Finck           pcchResult, dwReserved);
667c2c66affSColin Finck 
668c2c66affSColin Finck     hres = parse_mhtml_url(pwzBaseUrl, &url);
669c2c66affSColin Finck     if(FAILED(hres))
670c2c66affSColin Finck         return hres;
671c2c66affSColin Finck 
672*ae07dd64SAmine Khaldi     if(!_wcsnicmp(pwzRelativeUrl, mhtml_prefixW, ARRAY_SIZE(mhtml_prefixW))) {
673c2c66affSColin Finck         FIXME("Relative URL is mhtml protocol\n");
674c2c66affSColin Finck         return INET_E_USE_DEFAULT_PROTOCOLHANDLER;
675c2c66affSColin Finck     }
676c2c66affSColin Finck 
677c2c66affSColin Finck     len += url.mhtml_len;
678c2c66affSColin Finck     if(*pwzRelativeUrl)
679*ae07dd64SAmine Khaldi         len += lstrlenW(pwzRelativeUrl) + ARRAY_SIZE(mhtml_separatorW);
680c2c66affSColin Finck     if(len >= cchResult) {
681c2c66affSColin Finck         *pcchResult = 0;
682c2c66affSColin Finck         return E_FAIL;
683c2c66affSColin Finck     }
684c2c66affSColin Finck 
685c2c66affSColin Finck     memcpy(pwzResult, mhtml_prefixW, sizeof(mhtml_prefixW));
68633351fe5SAmine Khaldi     p = pwzResult + ARRAY_SIZE(mhtml_prefixW);
687c2c66affSColin Finck     memcpy(p, url.mhtml, url.mhtml_len*sizeof(WCHAR));
688c2c66affSColin Finck     p += url.mhtml_len;
689c2c66affSColin Finck     if(*pwzRelativeUrl) {
690c2c66affSColin Finck         memcpy(p, mhtml_separatorW, sizeof(mhtml_separatorW));
69133351fe5SAmine Khaldi         p += ARRAY_SIZE(mhtml_separatorW);
692*ae07dd64SAmine Khaldi         lstrcpyW(p, pwzRelativeUrl);
693c2c66affSColin Finck     }else {
694c2c66affSColin Finck         *p = 0;
695c2c66affSColin Finck     }
696c2c66affSColin Finck 
697c2c66affSColin Finck     *pcchResult = len;
698c2c66affSColin Finck     return S_OK;
699c2c66affSColin Finck }
700c2c66affSColin Finck 
MimeHtmlProtocolInfo_CompareUrl(IInternetProtocolInfo * iface,LPCWSTR pwzUrl1,LPCWSTR pwzUrl2,DWORD dwCompareFlags)701c2c66affSColin Finck static HRESULT WINAPI MimeHtmlProtocolInfo_CompareUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl1,
702c2c66affSColin Finck         LPCWSTR pwzUrl2, DWORD dwCompareFlags)
703c2c66affSColin Finck {
704c2c66affSColin Finck     MimeHtmlProtocol *This = impl_from_IInternetProtocolInfo(iface);
705c2c66affSColin Finck     FIXME("(%p)->(%s %s %08x)\n", This, debugstr_w(pwzUrl1), debugstr_w(pwzUrl2), dwCompareFlags);
706c2c66affSColin Finck     return E_NOTIMPL;
707c2c66affSColin Finck }
708c2c66affSColin Finck 
MimeHtmlProtocolInfo_QueryInfo(IInternetProtocolInfo * iface,LPCWSTR pwzUrl,QUERYOPTION QueryOption,DWORD dwQueryFlags,LPVOID pBuffer,DWORD cbBuffer,DWORD * pcbBuf,DWORD dwReserved)709c2c66affSColin Finck static HRESULT WINAPI MimeHtmlProtocolInfo_QueryInfo(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
710c2c66affSColin Finck         QUERYOPTION QueryOption, DWORD dwQueryFlags, LPVOID pBuffer, DWORD cbBuffer, DWORD* pcbBuf,
711c2c66affSColin Finck         DWORD dwReserved)
712c2c66affSColin Finck {
713c2c66affSColin Finck     MimeHtmlProtocol *This = impl_from_IInternetProtocolInfo(iface);
714c2c66affSColin Finck     FIXME("(%p)->(%s %08x %08x %p %d %p %d)\n", This, debugstr_w(pwzUrl), QueryOption, dwQueryFlags, pBuffer,
715c2c66affSColin Finck           cbBuffer, pcbBuf, dwReserved);
716c2c66affSColin Finck     return INET_E_USE_DEFAULT_PROTOCOLHANDLER;
717c2c66affSColin Finck }
718c2c66affSColin Finck 
719c2c66affSColin Finck static const IInternetProtocolInfoVtbl MimeHtmlProtocolInfoVtbl = {
720c2c66affSColin Finck     MimeHtmlProtocolInfo_QueryInterface,
721c2c66affSColin Finck     MimeHtmlProtocolInfo_AddRef,
722c2c66affSColin Finck     MimeHtmlProtocolInfo_Release,
723c2c66affSColin Finck     MimeHtmlProtocolInfo_ParseUrl,
724c2c66affSColin Finck     MimeHtmlProtocolInfo_CombineUrl,
725c2c66affSColin Finck     MimeHtmlProtocolInfo_CompareUrl,
726c2c66affSColin Finck     MimeHtmlProtocolInfo_QueryInfo
727c2c66affSColin Finck };
728c2c66affSColin Finck 
MimeHtmlProtocol_create(IUnknown * outer,void ** obj)729c2c66affSColin Finck HRESULT MimeHtmlProtocol_create(IUnknown *outer, void **obj)
730c2c66affSColin Finck {
731c2c66affSColin Finck     MimeHtmlProtocol *protocol;
732c2c66affSColin Finck 
733c2c66affSColin Finck     protocol = heap_alloc(sizeof(*protocol));
734c2c66affSColin Finck     if(!protocol)
735c2c66affSColin Finck         return E_OUTOFMEMORY;
736c2c66affSColin Finck 
737c2c66affSColin Finck     protocol->IUnknown_inner.lpVtbl = &MimeHtmlProtocolInnerVtbl;
738c2c66affSColin Finck     protocol->IInternetProtocol_iface.lpVtbl = &MimeHtmlProtocolVtbl;
739c2c66affSColin Finck     protocol->IInternetProtocolInfo_iface.lpVtbl = &MimeHtmlProtocolInfoVtbl;
740c2c66affSColin Finck     protocol->ref = 1;
741c2c66affSColin Finck     protocol->outer_unk = outer ? outer : &protocol->IUnknown_inner;
742c2c66affSColin Finck     protocol->location = NULL;
743c2c66affSColin Finck     protocol->stream = NULL;
744c2c66affSColin Finck     protocol->sink = NULL;
745c2c66affSColin Finck 
746c2c66affSColin Finck     *obj = &protocol->IUnknown_inner;
747c2c66affSColin Finck     return S_OK;
748c2c66affSColin Finck }
749