2 * Copyright 2017 Jacek Caban for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include "inetcomm_private.h"
24 IUnknown IUnknown_inner
;
25 IInternetProtocol IInternetProtocol_iface
;
26 IInternetProtocolInfo IInternetProtocolInfo_iface
;
33 IInternetProtocolSink
*sink
;
39 const WCHAR
*location
;
43 IBindStatusCallback IBindStatusCallback_iface
;
47 MimeHtmlProtocol
*protocol
;
53 static const WCHAR mhtml_prefixW
[] = {'m','h','t','m','l',':'};
54 static const WCHAR mhtml_separatorW
[] = {'!','x','-','u','s','c',':'};
56 static inline LPWSTR
heap_strdupW(LPCWSTR str
)
63 size
= (strlenW(str
)+1)*sizeof(WCHAR
);
64 ret
= heap_alloc(size
);
66 memcpy(ret
, str
, size
);
72 static HRESULT
parse_mhtml_url(const WCHAR
*url
, mhtml_url_t
*r
)
76 if(strncmpiW(url
, mhtml_prefixW
, sizeof(mhtml_prefixW
)/sizeof(WCHAR
)))
79 r
->mhtml
= url
+ sizeof(mhtml_prefixW
)/sizeof(WCHAR
);
80 p
= strchrW(r
->mhtml
, '!');
82 r
->mhtml_len
= p
- r
->mhtml
;
83 /* FIXME: We handle '!' and '!x-usc:' in URLs as the same thing. Those should not be the same. */
84 if(!strncmpW(p
, mhtml_separatorW
, sizeof(mhtml_separatorW
)/sizeof(WCHAR
)))
85 p
+= sizeof(mhtml_separatorW
)/sizeof(WCHAR
);
89 r
->mhtml_len
= strlenW(r
->mhtml
);
96 static HRESULT
report_result(MimeHtmlProtocol
*protocol
, HRESULT result
)
99 IInternetProtocolSink_ReportResult(protocol
->sink
, result
, ERROR_SUCCESS
, NULL
);
100 IInternetProtocolSink_Release(protocol
->sink
);
101 protocol
->sink
= NULL
;
107 static HRESULT
on_mime_message_available(MimeHtmlProtocol
*protocol
, IMimeMessage
*mime_message
)
109 FINDBODY find
= {NULL
};
110 IMimeBody
*mime_body
;
115 hres
= IMimeMessage_FindFirst(mime_message
, &find
, &body
);
117 return report_result(protocol
, hres
);
119 if(protocol
->location
) {
122 hres
= IMimeMessage_FindNext(mime_message
, &find
, &body
);
124 WARN("location %s not found\n", debugstr_w(protocol
->location
));
125 return report_result(protocol
, hres
);
128 value
.vt
= VT_LPWSTR
;
129 hres
= IMimeMessage_GetBodyProp(mime_message
, body
, "content-location", 0, &value
);
130 if(hres
== MIME_E_NOT_FOUND
)
133 return report_result(protocol
, hres
);
135 found
= !strcmpW(protocol
->location
, value
.u
.pwszVal
);
136 PropVariantClear(&value
);
139 hres
= IMimeMessage_FindNext(mime_message
, &find
, &body
);
141 WARN("location %s not found\n", debugstr_w(protocol
->location
));
142 return report_result(protocol
, hres
);
146 hres
= IMimeMessage_BindToObject(mime_message
, body
, &IID_IMimeBody
, (void**)&mime_body
);
148 return report_result(protocol
, hres
);
150 value
.vt
= VT_LPWSTR
;
151 hres
= IMimeBody_GetProp(mime_body
, "content-type", 0, &value
);
152 if(SUCCEEDED(hres
)) {
153 hres
= IInternetProtocolSink_ReportProgress(protocol
->sink
, BINDSTATUS_MIMETYPEAVAILABLE
, value
.u
.pwszVal
);
154 PropVariantClear(&value
);
157 /* FIXME: Create and report cache file. */
159 hres
= IMimeBody_GetData(mime_body
, IET_DECODED
, &protocol
->stream
);
161 return report_result(protocol
, hres
);
163 IInternetProtocolSink_ReportData(protocol
->sink
, BSCF_FIRSTDATANOTIFICATION
164 | BSCF_INTERMEDIATEDATANOTIFICATION
165 | BSCF_LASTDATANOTIFICATION
166 | BSCF_DATAFULLYAVAILABLE
167 | BSCF_AVAILABLEDATASIZEUNKNOWN
, 0, 0);
169 return report_result(protocol
, S_OK
);
172 static HRESULT
load_mime_message(IStream
*stream
, IMimeMessage
**ret
)
174 IMimeMessage
*mime_message
;
177 hres
= MimeMessage_create(NULL
, (void**)&mime_message
);
181 IMimeMessage_InitNew(mime_message
);
183 hres
= IMimeMessage_Load(mime_message
, stream
);
185 IMimeMessage_Release(mime_message
);
193 static inline MimeHtmlBinding
*impl_from_IBindStatusCallback(IBindStatusCallback
*iface
)
195 return CONTAINING_RECORD(iface
, MimeHtmlBinding
, IBindStatusCallback_iface
);
198 static HRESULT WINAPI
BindStatusCallback_QueryInterface(IBindStatusCallback
*iface
,
199 REFIID riid
, void **ppv
)
201 MimeHtmlBinding
*This
= impl_from_IBindStatusCallback(iface
);
203 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
204 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
205 *ppv
= &This
->IBindStatusCallback_iface
;
206 }else if(IsEqualGUID(&IID_IBindStatusCallback
, riid
)) {
207 TRACE("(%p)->(IID_IBindStatusCallback %p)\n", This
, ppv
);
208 *ppv
= &This
->IBindStatusCallback_iface
;
210 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
212 return E_NOINTERFACE
;
215 IUnknown_AddRef((IUnknown
*)*ppv
);
219 static ULONG WINAPI
BindStatusCallback_AddRef(IBindStatusCallback
*iface
)
221 MimeHtmlBinding
*This
= impl_from_IBindStatusCallback(iface
);
222 LONG ref
= InterlockedIncrement(&This
->ref
);
224 TRACE("(%p) ref=%d\n", This
, ref
);
229 static ULONG WINAPI
BindStatusCallback_Release(IBindStatusCallback
*iface
)
231 MimeHtmlBinding
*This
= impl_from_IBindStatusCallback(iface
);
232 LONG ref
= InterlockedDecrement(&This
->ref
);
234 TRACE("(%p) ref=%d\n", This
, ref
);
238 IInternetProtocol_Release(&This
->protocol
->IInternetProtocol_iface
);
240 IStream_Release(This
->stream
);
247 static HRESULT WINAPI
BindStatusCallback_OnStartBinding(IBindStatusCallback
*iface
,
248 DWORD dwReserved
, IBinding
*pib
)
250 MimeHtmlBinding
*This
= impl_from_IBindStatusCallback(iface
);
252 TRACE("(%p)->(%x %p)\n", This
, dwReserved
, pib
);
254 assert(!This
->stream
);
255 return CreateStreamOnHGlobal(NULL
, TRUE
, &This
->stream
);
258 static HRESULT WINAPI
BindStatusCallback_GetPriority(IBindStatusCallback
*iface
, LONG
*pnPriority
)
263 static HRESULT WINAPI
BindStatusCallback_OnLowResource(IBindStatusCallback
*iface
, DWORD dwReserved
)
268 static HRESULT WINAPI
BindStatusCallback_OnProgress(IBindStatusCallback
*iface
, ULONG ulProgress
,
269 ULONG ulProgressMax
, ULONG ulStatusCode
, LPCWSTR szStatusText
)
271 MimeHtmlBinding
*This
= impl_from_IBindStatusCallback(iface
);
272 TRACE("(%p)->(%u/%u %u %s)\n", This
, ulProgress
, ulProgressMax
, ulStatusCode
, debugstr_w(szStatusText
));
276 static HRESULT WINAPI
BindStatusCallback_OnStopBinding(IBindStatusCallback
*iface
, HRESULT hresult
, LPCWSTR szError
)
278 MimeHtmlBinding
*This
= impl_from_IBindStatusCallback(iface
);
279 IMimeMessage
*mime_message
= NULL
;
281 TRACE("(%p)->(%x %s)\n", This
, hresult
, debugstr_w(szError
));
283 if(SUCCEEDED(hresult
)) {
284 hresult
= load_mime_message(This
->stream
, &mime_message
);
285 IStream_Release(This
->stream
);
289 This
->status
= hresult
;
292 on_mime_message_available(This
->protocol
, mime_message
);
294 report_result(This
->protocol
, hresult
);
297 IMimeMessage_Release(mime_message
);
298 IInternetProtocol_Release(&This
->protocol
->IInternetProtocol_iface
);
299 This
->protocol
= NULL
;
303 static HRESULT WINAPI
BindStatusCallback_GetBindInfo(IBindStatusCallback
*iface
,
304 DWORD
* grfBINDF
, BINDINFO
* pbindinfo
)
306 MimeHtmlBinding
*This
= impl_from_IBindStatusCallback(iface
);
308 TRACE("(%p)\n", This
);
310 *grfBINDF
= BINDF_ASYNCHRONOUS
;
314 static HRESULT WINAPI
BindStatusCallback_OnDataAvailable(IBindStatusCallback
*iface
, DWORD grfBSCF
,
315 DWORD dwSize
, FORMATETC
* pformatetc
, STGMEDIUM
* pstgmed
)
317 MimeHtmlBinding
*This
= impl_from_IBindStatusCallback(iface
);
322 TRACE("(%p)\n", This
);
324 assert(pstgmed
->tymed
== TYMED_ISTREAM
);
327 hres
= IStream_Read(pstgmed
->u
.pstm
, buf
, sizeof(buf
), &read
);
332 hres
= IStream_Write(This
->stream
, buf
, read
, NULL
);
339 static HRESULT WINAPI
BindStatusCallback_OnObjectAvailable(IBindStatusCallback
*iface
,
340 REFIID riid
, IUnknown
* punk
)
346 static const IBindStatusCallbackVtbl BindStatusCallbackVtbl
= {
347 BindStatusCallback_QueryInterface
,
348 BindStatusCallback_AddRef
,
349 BindStatusCallback_Release
,
350 BindStatusCallback_OnStartBinding
,
351 BindStatusCallback_GetPriority
,
352 BindStatusCallback_OnLowResource
,
353 BindStatusCallback_OnProgress
,
354 BindStatusCallback_OnStopBinding
,
355 BindStatusCallback_GetBindInfo
,
356 BindStatusCallback_OnDataAvailable
,
357 BindStatusCallback_OnObjectAvailable
360 static inline MimeHtmlProtocol
*impl_from_IUnknown(IUnknown
*iface
)
362 return CONTAINING_RECORD(iface
, MimeHtmlProtocol
, IUnknown_inner
);
365 static HRESULT WINAPI
MimeHtmlProtocol_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
367 MimeHtmlProtocol
*This
= impl_from_IUnknown(iface
);
369 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
370 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
371 *ppv
= &This
->IInternetProtocol_iface
;
372 }else if(IsEqualGUID(&IID_IInternetProtocolRoot
, riid
)) {
373 TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This
, ppv
);
374 *ppv
= &This
->IInternetProtocol_iface
;
375 }else if(IsEqualGUID(&IID_IInternetProtocol
, riid
)) {
376 TRACE("(%p)->(IID_IInternetProtocol %p)\n", This
, ppv
);
377 *ppv
= &This
->IInternetProtocol_iface
;
378 }else if(IsEqualGUID(&IID_IInternetProtocolInfo
, riid
)) {
379 TRACE("(%p)->(IID_IInternetProtocolInfo %p)\n", This
, ppv
);
380 *ppv
= &This
->IInternetProtocolInfo_iface
;
382 FIXME("unknown interface %s\n", debugstr_guid(riid
));
384 return E_NOINTERFACE
;
387 IUnknown_AddRef((IUnknown
*)*ppv
);
391 static ULONG WINAPI
MimeHtmlProtocol_AddRef(IUnknown
*iface
)
393 MimeHtmlProtocol
*This
= impl_from_IUnknown(iface
);
394 ULONG ref
= InterlockedIncrement(&This
->ref
);
396 TRACE("(%p) ref=%d\n", This
, ref
);
401 static ULONG WINAPI
MimeHtmlProtocol_Release(IUnknown
*iface
)
403 MimeHtmlProtocol
*This
= impl_from_IUnknown(iface
);
404 ULONG ref
= InterlockedDecrement(&This
->ref
);
406 TRACE("(%p) ref=%x\n", This
, ref
);
410 IInternetProtocolSink_Release(This
->sink
);
412 IStream_Release(This
->stream
);
413 heap_free(This
->location
);
420 static const IUnknownVtbl MimeHtmlProtocolInnerVtbl
= {
421 MimeHtmlProtocol_QueryInterface
,
422 MimeHtmlProtocol_AddRef
,
423 MimeHtmlProtocol_Release
426 static inline MimeHtmlProtocol
*impl_from_IInternetProtocol(IInternetProtocol
*iface
)
428 return CONTAINING_RECORD(iface
, MimeHtmlProtocol
, IInternetProtocol_iface
);
431 static HRESULT WINAPI
InternetProtocol_QueryInterface(IInternetProtocol
*iface
, REFIID riid
, void **ppv
)
433 MimeHtmlProtocol
*This
= impl_from_IInternetProtocol(iface
);
434 return IUnknown_QueryInterface(This
->outer_unk
, riid
, ppv
);
437 static ULONG WINAPI
InternetProtocol_AddRef(IInternetProtocol
*iface
)
439 MimeHtmlProtocol
*This
= impl_from_IInternetProtocol(iface
);
440 return IUnknown_AddRef(This
->outer_unk
);
443 static ULONG WINAPI
InternetProtocol_Release(IInternetProtocol
*iface
)
445 MimeHtmlProtocol
*This
= impl_from_IInternetProtocol(iface
);
446 return IUnknown_Release(This
->outer_unk
);
449 static HRESULT WINAPI
MimeHtmlProtocol_Start(IInternetProtocol
*iface
, const WCHAR
*szUrl
,
450 IInternetProtocolSink
* pOIProtSink
, IInternetBindInfo
* pOIBindInfo
,
451 DWORD grfPI
, HANDLE_PTR dwReserved
)
453 MimeHtmlProtocol
*This
= impl_from_IInternetProtocol(iface
);
454 BINDINFO bindinfo
= { sizeof(bindinfo
) };
455 MimeHtmlBinding
*binding
;
463 TRACE("(%p)->(%s %p %p %08x %lx)\n", This
, debugstr_w(szUrl
), pOIProtSink
, pOIBindInfo
, grfPI
, dwReserved
);
465 hres
= parse_mhtml_url(szUrl
, &url
);
469 if(url
.location
&& !(This
->location
= heap_strdupW(url
.location
)))
470 return E_OUTOFMEMORY
;
472 hres
= IInternetBindInfo_GetBindInfo(pOIBindInfo
, &bindf
, &bindinfo
);
474 WARN("GetBindInfo failed: %08x\n", hres
);
477 if((bindf
& (BINDF_ASYNCHRONOUS
|BINDF_FROMURLMON
|BINDF_NEEDFILE
)) != (BINDF_ASYNCHRONOUS
|BINDF_FROMURLMON
|BINDF_NEEDFILE
))
478 FIXME("unsupported bindf %x\n", bindf
);
480 This
->sink
= pOIProtSink
;
481 IInternetProtocolSink_AddRef(This
->sink
);
483 binding
= heap_alloc(FIELD_OFFSET(MimeHtmlBinding
, url
[url
.mhtml_len
+1]));
485 return E_OUTOFMEMORY
;
486 memcpy(binding
->url
, url
.mhtml
, url
.mhtml_len
*sizeof(WCHAR
));
487 binding
->url
[url
.mhtml_len
] = 0;
489 hres
= CreateURLMoniker(NULL
, binding
->url
, &mon
);
493 binding
->IBindStatusCallback_iface
.lpVtbl
= &BindStatusCallbackVtbl
;
495 binding
->status
= E_PENDING
;
496 binding
->stream
= NULL
;
497 binding
->protocol
= NULL
;
499 hres
= CreateAsyncBindCtx(0, &binding
->IBindStatusCallback_iface
, NULL
, &bind_ctx
);
501 IMoniker_Release(mon
);
502 IBindStatusCallback_Release(&binding
->IBindStatusCallback_iface
);
506 IInternetProtocol_AddRef(&This
->IInternetProtocol_iface
);
507 binding
->protocol
= This
;
509 hres
= IMoniker_BindToStorage(mon
, bind_ctx
, NULL
, &IID_IStream
, (void**)&stream
);
510 IBindCtx_Release(bind_ctx
);
511 IMoniker_Release(mon
);
513 IStream_Release(stream
);
514 hres
= binding
->status
;
515 IBindStatusCallback_Release(&binding
->IBindStatusCallback_iface
);
516 if(FAILED(hres
) && hres
!= E_PENDING
)
517 report_result(This
, hres
);
521 static HRESULT WINAPI
MimeHtmlProtocol_Continue(IInternetProtocol
*iface
, PROTOCOLDATA
*pProtocolData
)
523 MimeHtmlProtocol
*This
= impl_from_IInternetProtocol(iface
);
524 FIXME("(%p)->(%p)\n", This
, pProtocolData
);
528 static HRESULT WINAPI
MimeHtmlProtocol_Abort(IInternetProtocol
*iface
, HRESULT hrReason
, DWORD dwOptions
)
530 MimeHtmlProtocol
*This
= impl_from_IInternetProtocol(iface
);
531 FIXME("(%p)->(%08x %08x)\n", This
, hrReason
, dwOptions
);
535 static HRESULT WINAPI
MimeHtmlProtocol_Terminate(IInternetProtocol
*iface
, DWORD dwOptions
)
537 MimeHtmlProtocol
*This
= impl_from_IInternetProtocol(iface
);
538 TRACE("(%p)->(%08x)\n", This
, dwOptions
);
542 static HRESULT WINAPI
MimeHtmlProtocol_Suspend(IInternetProtocol
*iface
)
544 MimeHtmlProtocol
*This
= impl_from_IInternetProtocol(iface
);
545 FIXME("(%p)\n", This
);
549 static HRESULT WINAPI
MimeHtmlProtocol_Resume(IInternetProtocol
*iface
)
551 MimeHtmlProtocol
*This
= impl_from_IInternetProtocol(iface
);
552 FIXME("(%p)\n", This
);
556 static HRESULT WINAPI
MimeHtmlProtocol_Read(IInternetProtocol
*iface
, void* pv
, ULONG cb
, ULONG
* pcbRead
)
558 MimeHtmlProtocol
*This
= impl_from_IInternetProtocol(iface
);
562 TRACE("(%p)->(%p %u %p)\n", This
, pv
, cb
, pcbRead
);
564 hres
= IStream_Read(This
->stream
, pv
, cb
, &read
);
570 return read
? S_OK
: S_FALSE
;
573 static HRESULT WINAPI
MimeHtmlProtocol_Seek(IInternetProtocol
*iface
, LARGE_INTEGER dlibMove
,
574 DWORD dwOrigin
, ULARGE_INTEGER
* plibNewPosition
)
576 MimeHtmlProtocol
*This
= impl_from_IInternetProtocol(iface
);
577 FIXME("(%p)->(%d %d %p)\n", This
, dlibMove
.u
.LowPart
, dwOrigin
, plibNewPosition
);
581 static HRESULT WINAPI
MimeHtmlProtocol_LockRequest(IInternetProtocol
*iface
, DWORD dwOptions
)
583 MimeHtmlProtocol
*This
= impl_from_IInternetProtocol(iface
);
584 FIXME("(%p)->(%d)\n", This
, dwOptions
);
588 static HRESULT WINAPI
MimeHtmlProtocol_UnlockRequest(IInternetProtocol
*iface
)
590 MimeHtmlProtocol
*This
= impl_from_IInternetProtocol(iface
);
591 FIXME("(%p)\n", This
);
595 static const IInternetProtocolVtbl MimeHtmlProtocolVtbl
= {
596 InternetProtocol_QueryInterface
,
597 InternetProtocol_AddRef
,
598 InternetProtocol_Release
,
599 MimeHtmlProtocol_Start
,
600 MimeHtmlProtocol_Continue
,
601 MimeHtmlProtocol_Abort
,
602 MimeHtmlProtocol_Terminate
,
603 MimeHtmlProtocol_Suspend
,
604 MimeHtmlProtocol_Resume
,
605 MimeHtmlProtocol_Read
,
606 MimeHtmlProtocol_Seek
,
607 MimeHtmlProtocol_LockRequest
,
608 MimeHtmlProtocol_UnlockRequest
611 static inline MimeHtmlProtocol
*impl_from_IInternetProtocolInfo(IInternetProtocolInfo
*iface
)
613 return CONTAINING_RECORD(iface
, MimeHtmlProtocol
, IInternetProtocolInfo_iface
);
616 static HRESULT WINAPI
MimeHtmlProtocolInfo_QueryInterface(IInternetProtocolInfo
*iface
, REFIID riid
, void **ppv
)
618 MimeHtmlProtocol
*This
= impl_from_IInternetProtocolInfo(iface
);
619 return IUnknown_QueryInterface(This
->outer_unk
, riid
, ppv
);
622 static ULONG WINAPI
MimeHtmlProtocolInfo_AddRef(IInternetProtocolInfo
*iface
)
624 MimeHtmlProtocol
*This
= impl_from_IInternetProtocolInfo(iface
);
625 return IUnknown_AddRef(This
->outer_unk
);
628 static ULONG WINAPI
MimeHtmlProtocolInfo_Release(IInternetProtocolInfo
*iface
)
630 MimeHtmlProtocol
*This
= impl_from_IInternetProtocolInfo(iface
);
631 return IUnknown_Release(This
->outer_unk
);
634 static HRESULT WINAPI
MimeHtmlProtocolInfo_ParseUrl(IInternetProtocolInfo
*iface
, LPCWSTR pwzUrl
,
635 PARSEACTION ParseAction
, DWORD dwParseFlags
, LPWSTR pwzResult
, DWORD cchResult
,
636 DWORD
* pcchResult
, DWORD dwReserved
)
638 MimeHtmlProtocol
*This
= impl_from_IInternetProtocolInfo(iface
);
639 FIXME("(%p)->(%s %d %x %p %d %p %d)\n", This
, debugstr_w(pwzUrl
), ParseAction
,
640 dwParseFlags
, pwzResult
, cchResult
, pcchResult
, dwReserved
);
641 return INET_E_DEFAULT_ACTION
;
644 static HRESULT WINAPI
MimeHtmlProtocolInfo_CombineUrl(IInternetProtocolInfo
*iface
,
645 LPCWSTR pwzBaseUrl
, LPCWSTR pwzRelativeUrl
, DWORD dwCombineFlags
, LPWSTR pwzResult
,
646 DWORD cchResult
, DWORD
* pcchResult
, DWORD dwReserved
)
648 MimeHtmlProtocol
*This
= impl_from_IInternetProtocolInfo(iface
);
649 size_t len
= sizeof(mhtml_prefixW
)/sizeof(WCHAR
);
654 TRACE("(%p)->(%s %s %08x %p %d %p %d)\n", This
, debugstr_w(pwzBaseUrl
),
655 debugstr_w(pwzRelativeUrl
), dwCombineFlags
, pwzResult
, cchResult
,
656 pcchResult
, dwReserved
);
658 hres
= parse_mhtml_url(pwzBaseUrl
, &url
);
662 if(!strncmpiW(pwzRelativeUrl
, mhtml_prefixW
, sizeof(mhtml_prefixW
)/sizeof(WCHAR
))) {
663 FIXME("Relative URL is mhtml protocol\n");
664 return INET_E_USE_DEFAULT_PROTOCOLHANDLER
;
667 len
+= url
.mhtml_len
;
669 len
+= strlenW(pwzRelativeUrl
) + sizeof(mhtml_separatorW
)/sizeof(WCHAR
);
670 if(len
>= cchResult
) {
675 memcpy(pwzResult
, mhtml_prefixW
, sizeof(mhtml_prefixW
));
676 p
= pwzResult
+ sizeof(mhtml_prefixW
)/sizeof(WCHAR
);
677 memcpy(p
, url
.mhtml
, url
.mhtml_len
*sizeof(WCHAR
));
679 if(*pwzRelativeUrl
) {
680 memcpy(p
, mhtml_separatorW
, sizeof(mhtml_separatorW
));
681 p
+= sizeof(mhtml_separatorW
)/sizeof(WCHAR
);
682 strcpyW(p
, pwzRelativeUrl
);
691 static HRESULT WINAPI
MimeHtmlProtocolInfo_CompareUrl(IInternetProtocolInfo
*iface
, LPCWSTR pwzUrl1
,
692 LPCWSTR pwzUrl2
, DWORD dwCompareFlags
)
694 MimeHtmlProtocol
*This
= impl_from_IInternetProtocolInfo(iface
);
695 FIXME("(%p)->(%s %s %08x)\n", This
, debugstr_w(pwzUrl1
), debugstr_w(pwzUrl2
), dwCompareFlags
);
699 static HRESULT WINAPI
MimeHtmlProtocolInfo_QueryInfo(IInternetProtocolInfo
*iface
, LPCWSTR pwzUrl
,
700 QUERYOPTION QueryOption
, DWORD dwQueryFlags
, LPVOID pBuffer
, DWORD cbBuffer
, DWORD
* pcbBuf
,
703 MimeHtmlProtocol
*This
= impl_from_IInternetProtocolInfo(iface
);
704 FIXME("(%p)->(%s %08x %08x %p %d %p %d)\n", This
, debugstr_w(pwzUrl
), QueryOption
, dwQueryFlags
, pBuffer
,
705 cbBuffer
, pcbBuf
, dwReserved
);
706 return INET_E_USE_DEFAULT_PROTOCOLHANDLER
;
709 static const IInternetProtocolInfoVtbl MimeHtmlProtocolInfoVtbl
= {
710 MimeHtmlProtocolInfo_QueryInterface
,
711 MimeHtmlProtocolInfo_AddRef
,
712 MimeHtmlProtocolInfo_Release
,
713 MimeHtmlProtocolInfo_ParseUrl
,
714 MimeHtmlProtocolInfo_CombineUrl
,
715 MimeHtmlProtocolInfo_CompareUrl
,
716 MimeHtmlProtocolInfo_QueryInfo
719 HRESULT
MimeHtmlProtocol_create(IUnknown
*outer
, void **obj
)
721 MimeHtmlProtocol
*protocol
;
723 protocol
= heap_alloc(sizeof(*protocol
));
725 return E_OUTOFMEMORY
;
727 protocol
->IUnknown_inner
.lpVtbl
= &MimeHtmlProtocolInnerVtbl
;
728 protocol
->IInternetProtocol_iface
.lpVtbl
= &MimeHtmlProtocolVtbl
;
729 protocol
->IInternetProtocolInfo_iface
.lpVtbl
= &MimeHtmlProtocolInfoVtbl
;
731 protocol
->outer_unk
= outer
? outer
: &protocol
->IUnknown_inner
;
732 protocol
->location
= NULL
;
733 protocol
->stream
= NULL
;
734 protocol
->sink
= NULL
;
736 *obj
= &protocol
->IUnknown_inner
;