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