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
20 #define NONAMELESSUNION
25 #include "inetcomm_private.h"
27 #include "wine/debug.h"
28 #include "wine/heap.h"
29 #include "wine/unicode.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(inetcomm
);
34 IUnknown IUnknown_inner
;
35 IInternetProtocol IInternetProtocol_iface
;
36 IInternetProtocolInfo IInternetProtocolInfo_iface
;
43 IInternetProtocolSink
*sink
;
49 const WCHAR
*location
;
53 IBindStatusCallback IBindStatusCallback_iface
;
57 MimeHtmlProtocol
*protocol
;
63 static const WCHAR mhtml_prefixW
[] = {'m','h','t','m','l',':'};
64 static const WCHAR mhtml_separatorW
[] = {'!','x','-','u','s','c',':'};
66 static inline LPWSTR
heap_strdupW(LPCWSTR str
)
73 size
= (strlenW(str
)+1)*sizeof(WCHAR
);
74 ret
= heap_alloc(size
);
76 memcpy(ret
, str
, size
);
82 static HRESULT
parse_mhtml_url(const WCHAR
*url
, mhtml_url_t
*r
)
86 if(strncmpiW(url
, mhtml_prefixW
, ARRAY_SIZE(mhtml_prefixW
)))
89 r
->mhtml
= url
+ ARRAY_SIZE(mhtml_prefixW
);
90 p
= strchrW(r
->mhtml
, '!');
92 r
->mhtml_len
= p
- r
->mhtml
;
93 /* FIXME: We handle '!' and '!x-usc:' in URLs as the same thing. Those should not be the same. */
94 if(!strncmpW(p
, mhtml_separatorW
, ARRAY_SIZE(mhtml_separatorW
)))
95 p
+= ARRAY_SIZE(mhtml_separatorW
);
99 r
->mhtml_len
= strlenW(r
->mhtml
);
106 static HRESULT
report_result(MimeHtmlProtocol
*protocol
, HRESULT result
)
109 IInternetProtocolSink_ReportResult(protocol
->sink
, result
, ERROR_SUCCESS
, NULL
);
110 IInternetProtocolSink_Release(protocol
->sink
);
111 protocol
->sink
= NULL
;
117 static HRESULT
on_mime_message_available(MimeHtmlProtocol
*protocol
, IMimeMessage
*mime_message
)
119 FINDBODY find
= {NULL
};
120 IMimeBody
*mime_body
;
125 hres
= IMimeMessage_FindFirst(mime_message
, &find
, &body
);
127 return report_result(protocol
, hres
);
129 if(protocol
->location
) {
132 hres
= IMimeMessage_FindNext(mime_message
, &find
, &body
);
134 WARN("location %s not found\n", debugstr_w(protocol
->location
));
135 return report_result(protocol
, hres
);
138 value
.vt
= VT_LPWSTR
;
139 hres
= IMimeMessage_GetBodyProp(mime_message
, body
, "content-location", 0, &value
);
140 if(hres
== MIME_E_NOT_FOUND
)
143 return report_result(protocol
, hres
);
145 found
= !strcmpW(protocol
->location
, value
.u
.pwszVal
);
146 PropVariantClear(&value
);
149 hres
= IMimeMessage_FindNext(mime_message
, &find
, &body
);
151 WARN("location %s not found\n", debugstr_w(protocol
->location
));
152 return report_result(protocol
, hres
);
156 hres
= IMimeMessage_BindToObject(mime_message
, body
, &IID_IMimeBody
, (void**)&mime_body
);
158 return report_result(protocol
, hres
);
160 value
.vt
= VT_LPWSTR
;
161 hres
= IMimeBody_GetProp(mime_body
, "content-type", 0, &value
);
162 if(SUCCEEDED(hres
)) {
163 hres
= IInternetProtocolSink_ReportProgress(protocol
->sink
, BINDSTATUS_MIMETYPEAVAILABLE
, value
.u
.pwszVal
);
164 PropVariantClear(&value
);
167 /* FIXME: Create and report cache file. */
169 hres
= IMimeBody_GetData(mime_body
, IET_DECODED
, &protocol
->stream
);
171 return report_result(protocol
, hres
);
173 IInternetProtocolSink_ReportData(protocol
->sink
, BSCF_FIRSTDATANOTIFICATION
174 | BSCF_INTERMEDIATEDATANOTIFICATION
175 | BSCF_LASTDATANOTIFICATION
176 | BSCF_DATAFULLYAVAILABLE
177 | BSCF_AVAILABLEDATASIZEUNKNOWN
, 0, 0);
179 return report_result(protocol
, S_OK
);
182 static HRESULT
load_mime_message(IStream
*stream
, IMimeMessage
**ret
)
184 IMimeMessage
*mime_message
;
187 hres
= MimeMessage_create(NULL
, (void**)&mime_message
);
191 IMimeMessage_InitNew(mime_message
);
193 hres
= IMimeMessage_Load(mime_message
, stream
);
195 IMimeMessage_Release(mime_message
);
203 static inline MimeHtmlBinding
*impl_from_IBindStatusCallback(IBindStatusCallback
*iface
)
205 return CONTAINING_RECORD(iface
, MimeHtmlBinding
, IBindStatusCallback_iface
);
208 static HRESULT WINAPI
BindStatusCallback_QueryInterface(IBindStatusCallback
*iface
,
209 REFIID riid
, void **ppv
)
211 MimeHtmlBinding
*This
= impl_from_IBindStatusCallback(iface
);
213 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
214 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
215 *ppv
= &This
->IBindStatusCallback_iface
;
216 }else if(IsEqualGUID(&IID_IBindStatusCallback
, riid
)) {
217 TRACE("(%p)->(IID_IBindStatusCallback %p)\n", This
, ppv
);
218 *ppv
= &This
->IBindStatusCallback_iface
;
220 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
222 return E_NOINTERFACE
;
225 IUnknown_AddRef((IUnknown
*)*ppv
);
229 static ULONG WINAPI
BindStatusCallback_AddRef(IBindStatusCallback
*iface
)
231 MimeHtmlBinding
*This
= impl_from_IBindStatusCallback(iface
);
232 LONG ref
= InterlockedIncrement(&This
->ref
);
234 TRACE("(%p) ref=%d\n", This
, ref
);
239 static ULONG WINAPI
BindStatusCallback_Release(IBindStatusCallback
*iface
)
241 MimeHtmlBinding
*This
= impl_from_IBindStatusCallback(iface
);
242 LONG ref
= InterlockedDecrement(&This
->ref
);
244 TRACE("(%p) ref=%d\n", This
, ref
);
248 IInternetProtocol_Release(&This
->protocol
->IInternetProtocol_iface
);
250 IStream_Release(This
->stream
);
257 static HRESULT WINAPI
BindStatusCallback_OnStartBinding(IBindStatusCallback
*iface
,
258 DWORD dwReserved
, IBinding
*pib
)
260 MimeHtmlBinding
*This
= impl_from_IBindStatusCallback(iface
);
262 TRACE("(%p)->(%x %p)\n", This
, dwReserved
, pib
);
264 assert(!This
->stream
);
265 return CreateStreamOnHGlobal(NULL
, TRUE
, &This
->stream
);
268 static HRESULT WINAPI
BindStatusCallback_GetPriority(IBindStatusCallback
*iface
, LONG
*pnPriority
)
273 static HRESULT WINAPI
BindStatusCallback_OnLowResource(IBindStatusCallback
*iface
, DWORD dwReserved
)
278 static HRESULT WINAPI
BindStatusCallback_OnProgress(IBindStatusCallback
*iface
, ULONG ulProgress
,
279 ULONG ulProgressMax
, ULONG ulStatusCode
, LPCWSTR szStatusText
)
281 MimeHtmlBinding
*This
= impl_from_IBindStatusCallback(iface
);
282 TRACE("(%p)->(%u/%u %u %s)\n", This
, ulProgress
, ulProgressMax
, ulStatusCode
, debugstr_w(szStatusText
));
286 static HRESULT WINAPI
BindStatusCallback_OnStopBinding(IBindStatusCallback
*iface
, HRESULT hresult
, LPCWSTR szError
)
288 MimeHtmlBinding
*This
= impl_from_IBindStatusCallback(iface
);
289 IMimeMessage
*mime_message
= NULL
;
291 TRACE("(%p)->(%x %s)\n", This
, hresult
, debugstr_w(szError
));
293 if(SUCCEEDED(hresult
)) {
294 hresult
= load_mime_message(This
->stream
, &mime_message
);
295 IStream_Release(This
->stream
);
299 This
->status
= hresult
;
302 on_mime_message_available(This
->protocol
, mime_message
);
304 report_result(This
->protocol
, hresult
);
307 IMimeMessage_Release(mime_message
);
308 IInternetProtocol_Release(&This
->protocol
->IInternetProtocol_iface
);
309 This
->protocol
= NULL
;
313 static HRESULT WINAPI
BindStatusCallback_GetBindInfo(IBindStatusCallback
*iface
,
314 DWORD
* grfBINDF
, BINDINFO
* pbindinfo
)
316 MimeHtmlBinding
*This
= impl_from_IBindStatusCallback(iface
);
318 TRACE("(%p)\n", This
);
320 *grfBINDF
= BINDF_ASYNCHRONOUS
;
324 static HRESULT WINAPI
BindStatusCallback_OnDataAvailable(IBindStatusCallback
*iface
, DWORD grfBSCF
,
325 DWORD dwSize
, FORMATETC
* pformatetc
, STGMEDIUM
* pstgmed
)
327 MimeHtmlBinding
*This
= impl_from_IBindStatusCallback(iface
);
332 TRACE("(%p)\n", This
);
334 assert(pstgmed
->tymed
== TYMED_ISTREAM
);
337 hres
= IStream_Read(pstgmed
->u
.pstm
, buf
, sizeof(buf
), &read
);
342 hres
= IStream_Write(This
->stream
, buf
, read
, NULL
);
349 static HRESULT WINAPI
BindStatusCallback_OnObjectAvailable(IBindStatusCallback
*iface
,
350 REFIID riid
, IUnknown
* punk
)
356 static const IBindStatusCallbackVtbl BindStatusCallbackVtbl
= {
357 BindStatusCallback_QueryInterface
,
358 BindStatusCallback_AddRef
,
359 BindStatusCallback_Release
,
360 BindStatusCallback_OnStartBinding
,
361 BindStatusCallback_GetPriority
,
362 BindStatusCallback_OnLowResource
,
363 BindStatusCallback_OnProgress
,
364 BindStatusCallback_OnStopBinding
,
365 BindStatusCallback_GetBindInfo
,
366 BindStatusCallback_OnDataAvailable
,
367 BindStatusCallback_OnObjectAvailable
370 static inline MimeHtmlProtocol
*impl_from_IUnknown(IUnknown
*iface
)
372 return CONTAINING_RECORD(iface
, MimeHtmlProtocol
, IUnknown_inner
);
375 static HRESULT WINAPI
MimeHtmlProtocol_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
377 MimeHtmlProtocol
*This
= impl_from_IUnknown(iface
);
379 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
380 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
381 *ppv
= &This
->IInternetProtocol_iface
;
382 }else if(IsEqualGUID(&IID_IInternetProtocolRoot
, riid
)) {
383 TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This
, ppv
);
384 *ppv
= &This
->IInternetProtocol_iface
;
385 }else if(IsEqualGUID(&IID_IInternetProtocol
, riid
)) {
386 TRACE("(%p)->(IID_IInternetProtocol %p)\n", This
, ppv
);
387 *ppv
= &This
->IInternetProtocol_iface
;
388 }else if(IsEqualGUID(&IID_IInternetProtocolInfo
, riid
)) {
389 TRACE("(%p)->(IID_IInternetProtocolInfo %p)\n", This
, ppv
);
390 *ppv
= &This
->IInternetProtocolInfo_iface
;
392 FIXME("unknown interface %s\n", debugstr_guid(riid
));
394 return E_NOINTERFACE
;
397 IUnknown_AddRef((IUnknown
*)*ppv
);
401 static ULONG WINAPI
MimeHtmlProtocol_AddRef(IUnknown
*iface
)
403 MimeHtmlProtocol
*This
= impl_from_IUnknown(iface
);
404 ULONG ref
= InterlockedIncrement(&This
->ref
);
406 TRACE("(%p) ref=%d\n", This
, ref
);
411 static ULONG WINAPI
MimeHtmlProtocol_Release(IUnknown
*iface
)
413 MimeHtmlProtocol
*This
= impl_from_IUnknown(iface
);
414 ULONG ref
= InterlockedDecrement(&This
->ref
);
416 TRACE("(%p) ref=%x\n", This
, ref
);
420 IInternetProtocolSink_Release(This
->sink
);
422 IStream_Release(This
->stream
);
423 heap_free(This
->location
);
430 static const IUnknownVtbl MimeHtmlProtocolInnerVtbl
= {
431 MimeHtmlProtocol_QueryInterface
,
432 MimeHtmlProtocol_AddRef
,
433 MimeHtmlProtocol_Release
436 static inline MimeHtmlProtocol
*impl_from_IInternetProtocol(IInternetProtocol
*iface
)
438 return CONTAINING_RECORD(iface
, MimeHtmlProtocol
, IInternetProtocol_iface
);
441 static HRESULT WINAPI
InternetProtocol_QueryInterface(IInternetProtocol
*iface
, REFIID riid
, void **ppv
)
443 MimeHtmlProtocol
*This
= impl_from_IInternetProtocol(iface
);
444 return IUnknown_QueryInterface(This
->outer_unk
, riid
, ppv
);
447 static ULONG WINAPI
InternetProtocol_AddRef(IInternetProtocol
*iface
)
449 MimeHtmlProtocol
*This
= impl_from_IInternetProtocol(iface
);
450 return IUnknown_AddRef(This
->outer_unk
);
453 static ULONG WINAPI
InternetProtocol_Release(IInternetProtocol
*iface
)
455 MimeHtmlProtocol
*This
= impl_from_IInternetProtocol(iface
);
456 return IUnknown_Release(This
->outer_unk
);
459 static HRESULT WINAPI
MimeHtmlProtocol_Start(IInternetProtocol
*iface
, const WCHAR
*szUrl
,
460 IInternetProtocolSink
* pOIProtSink
, IInternetBindInfo
* pOIBindInfo
,
461 DWORD grfPI
, HANDLE_PTR dwReserved
)
463 MimeHtmlProtocol
*This
= impl_from_IInternetProtocol(iface
);
464 BINDINFO bindinfo
= { sizeof(bindinfo
) };
465 MimeHtmlBinding
*binding
;
473 TRACE("(%p)->(%s %p %p %08x %lx)\n", This
, debugstr_w(szUrl
), pOIProtSink
, pOIBindInfo
, grfPI
, dwReserved
);
475 hres
= parse_mhtml_url(szUrl
, &url
);
479 if(url
.location
&& !(This
->location
= heap_strdupW(url
.location
)))
480 return E_OUTOFMEMORY
;
482 hres
= IInternetBindInfo_GetBindInfo(pOIBindInfo
, &bindf
, &bindinfo
);
484 WARN("GetBindInfo failed: %08x\n", hres
);
487 if((bindf
& (BINDF_ASYNCHRONOUS
|BINDF_FROMURLMON
|BINDF_NEEDFILE
)) != (BINDF_ASYNCHRONOUS
|BINDF_FROMURLMON
|BINDF_NEEDFILE
))
488 FIXME("unsupported bindf %x\n", bindf
);
490 IInternetProtocolSink_AddRef(This
->sink
= pOIProtSink
);
492 binding
= heap_alloc(FIELD_OFFSET(MimeHtmlBinding
, url
[url
.mhtml_len
+1]));
494 return E_OUTOFMEMORY
;
495 memcpy(binding
->url
, url
.mhtml
, url
.mhtml_len
*sizeof(WCHAR
));
496 binding
->url
[url
.mhtml_len
] = 0;
498 hres
= CreateURLMoniker(NULL
, binding
->url
, &mon
);
504 binding
->IBindStatusCallback_iface
.lpVtbl
= &BindStatusCallbackVtbl
;
506 binding
->status
= E_PENDING
;
507 binding
->stream
= NULL
;
508 binding
->protocol
= NULL
;
510 hres
= CreateAsyncBindCtx(0, &binding
->IBindStatusCallback_iface
, NULL
, &bind_ctx
);
512 IMoniker_Release(mon
);
513 IBindStatusCallback_Release(&binding
->IBindStatusCallback_iface
);
517 IInternetProtocol_AddRef(&This
->IInternetProtocol_iface
);
518 binding
->protocol
= This
;
520 hres
= IMoniker_BindToStorage(mon
, bind_ctx
, NULL
, &IID_IStream
, (void**)&stream
);
521 IBindCtx_Release(bind_ctx
);
522 IMoniker_Release(mon
);
524 IStream_Release(stream
);
525 hres
= binding
->status
;
526 IBindStatusCallback_Release(&binding
->IBindStatusCallback_iface
);
527 if(FAILED(hres
) && hres
!= E_PENDING
)
528 report_result(This
, hres
);
532 static HRESULT WINAPI
MimeHtmlProtocol_Continue(IInternetProtocol
*iface
, PROTOCOLDATA
*pProtocolData
)
534 MimeHtmlProtocol
*This
= impl_from_IInternetProtocol(iface
);
535 FIXME("(%p)->(%p)\n", This
, pProtocolData
);
539 static HRESULT WINAPI
MimeHtmlProtocol_Abort(IInternetProtocol
*iface
, HRESULT hrReason
, DWORD dwOptions
)
541 MimeHtmlProtocol
*This
= impl_from_IInternetProtocol(iface
);
542 FIXME("(%p)->(%08x %08x)\n", This
, hrReason
, dwOptions
);
546 static HRESULT WINAPI
MimeHtmlProtocol_Terminate(IInternetProtocol
*iface
, DWORD dwOptions
)
548 MimeHtmlProtocol
*This
= impl_from_IInternetProtocol(iface
);
549 TRACE("(%p)->(%08x)\n", This
, dwOptions
);
553 static HRESULT WINAPI
MimeHtmlProtocol_Suspend(IInternetProtocol
*iface
)
555 MimeHtmlProtocol
*This
= impl_from_IInternetProtocol(iface
);
556 FIXME("(%p)\n", This
);
560 static HRESULT WINAPI
MimeHtmlProtocol_Resume(IInternetProtocol
*iface
)
562 MimeHtmlProtocol
*This
= impl_from_IInternetProtocol(iface
);
563 FIXME("(%p)\n", This
);
567 static HRESULT WINAPI
MimeHtmlProtocol_Read(IInternetProtocol
*iface
, void* pv
, ULONG cb
, ULONG
* pcbRead
)
569 MimeHtmlProtocol
*This
= impl_from_IInternetProtocol(iface
);
573 TRACE("(%p)->(%p %u %p)\n", This
, pv
, cb
, pcbRead
);
575 hres
= IStream_Read(This
->stream
, pv
, cb
, &read
);
581 return read
? S_OK
: S_FALSE
;
584 static HRESULT WINAPI
MimeHtmlProtocol_Seek(IInternetProtocol
*iface
, LARGE_INTEGER dlibMove
,
585 DWORD dwOrigin
, ULARGE_INTEGER
* plibNewPosition
)
587 MimeHtmlProtocol
*This
= impl_from_IInternetProtocol(iface
);
588 FIXME("(%p)->(%d %d %p)\n", This
, dlibMove
.u
.LowPart
, dwOrigin
, plibNewPosition
);
592 static HRESULT WINAPI
MimeHtmlProtocol_LockRequest(IInternetProtocol
*iface
, DWORD dwOptions
)
594 MimeHtmlProtocol
*This
= impl_from_IInternetProtocol(iface
);
595 FIXME("(%p)->(%d)\n", This
, dwOptions
);
599 static HRESULT WINAPI
MimeHtmlProtocol_UnlockRequest(IInternetProtocol
*iface
)
601 MimeHtmlProtocol
*This
= impl_from_IInternetProtocol(iface
);
602 FIXME("(%p)\n", This
);
606 static const IInternetProtocolVtbl MimeHtmlProtocolVtbl
= {
607 InternetProtocol_QueryInterface
,
608 InternetProtocol_AddRef
,
609 InternetProtocol_Release
,
610 MimeHtmlProtocol_Start
,
611 MimeHtmlProtocol_Continue
,
612 MimeHtmlProtocol_Abort
,
613 MimeHtmlProtocol_Terminate
,
614 MimeHtmlProtocol_Suspend
,
615 MimeHtmlProtocol_Resume
,
616 MimeHtmlProtocol_Read
,
617 MimeHtmlProtocol_Seek
,
618 MimeHtmlProtocol_LockRequest
,
619 MimeHtmlProtocol_UnlockRequest
622 static inline MimeHtmlProtocol
*impl_from_IInternetProtocolInfo(IInternetProtocolInfo
*iface
)
624 return CONTAINING_RECORD(iface
, MimeHtmlProtocol
, IInternetProtocolInfo_iface
);
627 static HRESULT WINAPI
MimeHtmlProtocolInfo_QueryInterface(IInternetProtocolInfo
*iface
, REFIID riid
, void **ppv
)
629 MimeHtmlProtocol
*This
= impl_from_IInternetProtocolInfo(iface
);
630 return IUnknown_QueryInterface(This
->outer_unk
, riid
, ppv
);
633 static ULONG WINAPI
MimeHtmlProtocolInfo_AddRef(IInternetProtocolInfo
*iface
)
635 MimeHtmlProtocol
*This
= impl_from_IInternetProtocolInfo(iface
);
636 return IUnknown_AddRef(This
->outer_unk
);
639 static ULONG WINAPI
MimeHtmlProtocolInfo_Release(IInternetProtocolInfo
*iface
)
641 MimeHtmlProtocol
*This
= impl_from_IInternetProtocolInfo(iface
);
642 return IUnknown_Release(This
->outer_unk
);
645 static HRESULT WINAPI
MimeHtmlProtocolInfo_ParseUrl(IInternetProtocolInfo
*iface
, LPCWSTR pwzUrl
,
646 PARSEACTION ParseAction
, DWORD dwParseFlags
, LPWSTR pwzResult
, DWORD cchResult
,
647 DWORD
* pcchResult
, DWORD dwReserved
)
649 MimeHtmlProtocol
*This
= impl_from_IInternetProtocolInfo(iface
);
650 FIXME("(%p)->(%s %d %x %p %d %p %d)\n", This
, debugstr_w(pwzUrl
), ParseAction
,
651 dwParseFlags
, pwzResult
, cchResult
, pcchResult
, dwReserved
);
652 return INET_E_DEFAULT_ACTION
;
655 static HRESULT WINAPI
MimeHtmlProtocolInfo_CombineUrl(IInternetProtocolInfo
*iface
,
656 LPCWSTR pwzBaseUrl
, LPCWSTR pwzRelativeUrl
, DWORD dwCombineFlags
, LPWSTR pwzResult
,
657 DWORD cchResult
, DWORD
* pcchResult
, DWORD dwReserved
)
659 MimeHtmlProtocol
*This
= impl_from_IInternetProtocolInfo(iface
);
660 size_t len
= ARRAY_SIZE(mhtml_prefixW
);
665 TRACE("(%p)->(%s %s %08x %p %d %p %d)\n", This
, debugstr_w(pwzBaseUrl
),
666 debugstr_w(pwzRelativeUrl
), dwCombineFlags
, pwzResult
, cchResult
,
667 pcchResult
, dwReserved
);
669 hres
= parse_mhtml_url(pwzBaseUrl
, &url
);
673 if(!strncmpiW(pwzRelativeUrl
, mhtml_prefixW
, ARRAY_SIZE(mhtml_prefixW
))) {
674 FIXME("Relative URL is mhtml protocol\n");
675 return INET_E_USE_DEFAULT_PROTOCOLHANDLER
;
678 len
+= url
.mhtml_len
;
680 len
+= strlenW(pwzRelativeUrl
) + ARRAY_SIZE(mhtml_separatorW
);
681 if(len
>= cchResult
) {
686 memcpy(pwzResult
, mhtml_prefixW
, sizeof(mhtml_prefixW
));
687 p
= pwzResult
+ ARRAY_SIZE(mhtml_prefixW
);
688 memcpy(p
, url
.mhtml
, url
.mhtml_len
*sizeof(WCHAR
));
690 if(*pwzRelativeUrl
) {
691 memcpy(p
, mhtml_separatorW
, sizeof(mhtml_separatorW
));
692 p
+= ARRAY_SIZE(mhtml_separatorW
);
693 strcpyW(p
, pwzRelativeUrl
);
702 static HRESULT WINAPI
MimeHtmlProtocolInfo_CompareUrl(IInternetProtocolInfo
*iface
, LPCWSTR pwzUrl1
,
703 LPCWSTR pwzUrl2
, DWORD dwCompareFlags
)
705 MimeHtmlProtocol
*This
= impl_from_IInternetProtocolInfo(iface
);
706 FIXME("(%p)->(%s %s %08x)\n", This
, debugstr_w(pwzUrl1
), debugstr_w(pwzUrl2
), dwCompareFlags
);
710 static HRESULT WINAPI
MimeHtmlProtocolInfo_QueryInfo(IInternetProtocolInfo
*iface
, LPCWSTR pwzUrl
,
711 QUERYOPTION QueryOption
, DWORD dwQueryFlags
, LPVOID pBuffer
, DWORD cbBuffer
, DWORD
* pcbBuf
,
714 MimeHtmlProtocol
*This
= impl_from_IInternetProtocolInfo(iface
);
715 FIXME("(%p)->(%s %08x %08x %p %d %p %d)\n", This
, debugstr_w(pwzUrl
), QueryOption
, dwQueryFlags
, pBuffer
,
716 cbBuffer
, pcbBuf
, dwReserved
);
717 return INET_E_USE_DEFAULT_PROTOCOLHANDLER
;
720 static const IInternetProtocolInfoVtbl MimeHtmlProtocolInfoVtbl
= {
721 MimeHtmlProtocolInfo_QueryInterface
,
722 MimeHtmlProtocolInfo_AddRef
,
723 MimeHtmlProtocolInfo_Release
,
724 MimeHtmlProtocolInfo_ParseUrl
,
725 MimeHtmlProtocolInfo_CombineUrl
,
726 MimeHtmlProtocolInfo_CompareUrl
,
727 MimeHtmlProtocolInfo_QueryInfo
730 HRESULT
MimeHtmlProtocol_create(IUnknown
*outer
, void **obj
)
732 MimeHtmlProtocol
*protocol
;
734 protocol
= heap_alloc(sizeof(*protocol
));
736 return E_OUTOFMEMORY
;
738 protocol
->IUnknown_inner
.lpVtbl
= &MimeHtmlProtocolInnerVtbl
;
739 protocol
->IInternetProtocol_iface
.lpVtbl
= &MimeHtmlProtocolVtbl
;
740 protocol
->IInternetProtocolInfo_iface
.lpVtbl
= &MimeHtmlProtocolInfoVtbl
;
742 protocol
->outer_unk
= outer
? outer
: &protocol
->IUnknown_inner
;
743 protocol
->location
= NULL
;
744 protocol
->stream
= NULL
;
745 protocol
->sink
= NULL
;
747 *obj
= &protocol
->IUnknown_inner
;