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/unicode.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(inetcomm
);
33 IUnknown IUnknown_inner
;
34 IInternetProtocol IInternetProtocol_iface
;
35 IInternetProtocolInfo IInternetProtocolInfo_iface
;
42 IInternetProtocolSink
*sink
;
48 const WCHAR
*location
;
52 IBindStatusCallback IBindStatusCallback_iface
;
56 MimeHtmlProtocol
*protocol
;
62 static const WCHAR mhtml_prefixW
[] = {'m','h','t','m','l',':'};
63 static const WCHAR mhtml_separatorW
[] = {'!','x','-','u','s','c',':'};
65 static inline LPWSTR
heap_strdupW(LPCWSTR str
)
72 size
= (strlenW(str
)+1)*sizeof(WCHAR
);
73 ret
= heap_alloc(size
);
75 memcpy(ret
, str
, size
);
81 static HRESULT
parse_mhtml_url(const WCHAR
*url
, mhtml_url_t
*r
)
85 if(strncmpiW(url
, mhtml_prefixW
, sizeof(mhtml_prefixW
)/sizeof(WCHAR
)))
88 r
->mhtml
= url
+ sizeof(mhtml_prefixW
)/sizeof(WCHAR
);
89 p
= strchrW(r
->mhtml
, '!');
91 r
->mhtml_len
= p
- r
->mhtml
;
92 /* FIXME: We handle '!' and '!x-usc:' in URLs as the same thing. Those should not be the same. */
93 if(!strncmpW(p
, mhtml_separatorW
, sizeof(mhtml_separatorW
)/sizeof(WCHAR
)))
94 p
+= sizeof(mhtml_separatorW
)/sizeof(WCHAR
);
98 r
->mhtml_len
= strlenW(r
->mhtml
);
105 static HRESULT
report_result(MimeHtmlProtocol
*protocol
, HRESULT result
)
108 IInternetProtocolSink_ReportResult(protocol
->sink
, result
, ERROR_SUCCESS
, NULL
);
109 IInternetProtocolSink_Release(protocol
->sink
);
110 protocol
->sink
= NULL
;
116 static HRESULT
on_mime_message_available(MimeHtmlProtocol
*protocol
, IMimeMessage
*mime_message
)
118 FINDBODY find
= {NULL
};
119 IMimeBody
*mime_body
;
124 hres
= IMimeMessage_FindFirst(mime_message
, &find
, &body
);
126 return report_result(protocol
, hres
);
128 if(protocol
->location
) {
131 hres
= IMimeMessage_FindNext(mime_message
, &find
, &body
);
133 WARN("location %s not found\n", debugstr_w(protocol
->location
));
134 return report_result(protocol
, hres
);
137 value
.vt
= VT_LPWSTR
;
138 hres
= IMimeMessage_GetBodyProp(mime_message
, body
, "content-location", 0, &value
);
139 if(hres
== MIME_E_NOT_FOUND
)
142 return report_result(protocol
, hres
);
144 found
= !strcmpW(protocol
->location
, value
.u
.pwszVal
);
145 PropVariantClear(&value
);
148 hres
= IMimeMessage_FindNext(mime_message
, &find
, &body
);
150 WARN("location %s not found\n", debugstr_w(protocol
->location
));
151 return report_result(protocol
, hres
);
155 hres
= IMimeMessage_BindToObject(mime_message
, body
, &IID_IMimeBody
, (void**)&mime_body
);
157 return report_result(protocol
, hres
);
159 value
.vt
= VT_LPWSTR
;
160 hres
= IMimeBody_GetProp(mime_body
, "content-type", 0, &value
);
161 if(SUCCEEDED(hres
)) {
162 hres
= IInternetProtocolSink_ReportProgress(protocol
->sink
, BINDSTATUS_MIMETYPEAVAILABLE
, value
.u
.pwszVal
);
163 PropVariantClear(&value
);
166 /* FIXME: Create and report cache file. */
168 hres
= IMimeBody_GetData(mime_body
, IET_DECODED
, &protocol
->stream
);
170 return report_result(protocol
, hres
);
172 IInternetProtocolSink_ReportData(protocol
->sink
, BSCF_FIRSTDATANOTIFICATION
173 | BSCF_INTERMEDIATEDATANOTIFICATION
174 | BSCF_LASTDATANOTIFICATION
175 | BSCF_DATAFULLYAVAILABLE
176 | BSCF_AVAILABLEDATASIZEUNKNOWN
, 0, 0);
178 return report_result(protocol
, S_OK
);
181 static HRESULT
load_mime_message(IStream
*stream
, IMimeMessage
**ret
)
183 IMimeMessage
*mime_message
;
186 hres
= MimeMessage_create(NULL
, (void**)&mime_message
);
190 IMimeMessage_InitNew(mime_message
);
192 hres
= IMimeMessage_Load(mime_message
, stream
);
194 IMimeMessage_Release(mime_message
);
202 static inline MimeHtmlBinding
*impl_from_IBindStatusCallback(IBindStatusCallback
*iface
)
204 return CONTAINING_RECORD(iface
, MimeHtmlBinding
, IBindStatusCallback_iface
);
207 static HRESULT WINAPI
BindStatusCallback_QueryInterface(IBindStatusCallback
*iface
,
208 REFIID riid
, void **ppv
)
210 MimeHtmlBinding
*This
= impl_from_IBindStatusCallback(iface
);
212 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
213 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
214 *ppv
= &This
->IBindStatusCallback_iface
;
215 }else if(IsEqualGUID(&IID_IBindStatusCallback
, riid
)) {
216 TRACE("(%p)->(IID_IBindStatusCallback %p)\n", This
, ppv
);
217 *ppv
= &This
->IBindStatusCallback_iface
;
219 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
221 return E_NOINTERFACE
;
224 IUnknown_AddRef((IUnknown
*)*ppv
);
228 static ULONG WINAPI
BindStatusCallback_AddRef(IBindStatusCallback
*iface
)
230 MimeHtmlBinding
*This
= impl_from_IBindStatusCallback(iface
);
231 LONG ref
= InterlockedIncrement(&This
->ref
);
233 TRACE("(%p) ref=%d\n", This
, ref
);
238 static ULONG WINAPI
BindStatusCallback_Release(IBindStatusCallback
*iface
)
240 MimeHtmlBinding
*This
= impl_from_IBindStatusCallback(iface
);
241 LONG ref
= InterlockedDecrement(&This
->ref
);
243 TRACE("(%p) ref=%d\n", This
, ref
);
247 IInternetProtocol_Release(&This
->protocol
->IInternetProtocol_iface
);
249 IStream_Release(This
->stream
);
256 static HRESULT WINAPI
BindStatusCallback_OnStartBinding(IBindStatusCallback
*iface
,
257 DWORD dwReserved
, IBinding
*pib
)
259 MimeHtmlBinding
*This
= impl_from_IBindStatusCallback(iface
);
261 TRACE("(%p)->(%x %p)\n", This
, dwReserved
, pib
);
263 assert(!This
->stream
);
264 return CreateStreamOnHGlobal(NULL
, TRUE
, &This
->stream
);
267 static HRESULT WINAPI
BindStatusCallback_GetPriority(IBindStatusCallback
*iface
, LONG
*pnPriority
)
272 static HRESULT WINAPI
BindStatusCallback_OnLowResource(IBindStatusCallback
*iface
, DWORD dwReserved
)
277 static HRESULT WINAPI
BindStatusCallback_OnProgress(IBindStatusCallback
*iface
, ULONG ulProgress
,
278 ULONG ulProgressMax
, ULONG ulStatusCode
, LPCWSTR szStatusText
)
280 MimeHtmlBinding
*This
= impl_from_IBindStatusCallback(iface
);
281 TRACE("(%p)->(%u/%u %u %s)\n", This
, ulProgress
, ulProgressMax
, ulStatusCode
, debugstr_w(szStatusText
));
285 static HRESULT WINAPI
BindStatusCallback_OnStopBinding(IBindStatusCallback
*iface
, HRESULT hresult
, LPCWSTR szError
)
287 MimeHtmlBinding
*This
= impl_from_IBindStatusCallback(iface
);
288 IMimeMessage
*mime_message
= NULL
;
290 TRACE("(%p)->(%x %s)\n", This
, hresult
, debugstr_w(szError
));
292 if(SUCCEEDED(hresult
)) {
293 hresult
= load_mime_message(This
->stream
, &mime_message
);
294 IStream_Release(This
->stream
);
298 This
->status
= hresult
;
301 on_mime_message_available(This
->protocol
, mime_message
);
303 report_result(This
->protocol
, hresult
);
306 IMimeMessage_Release(mime_message
);
307 IInternetProtocol_Release(&This
->protocol
->IInternetProtocol_iface
);
308 This
->protocol
= NULL
;
312 static HRESULT WINAPI
BindStatusCallback_GetBindInfo(IBindStatusCallback
*iface
,
313 DWORD
* grfBINDF
, BINDINFO
* pbindinfo
)
315 MimeHtmlBinding
*This
= impl_from_IBindStatusCallback(iface
);
317 TRACE("(%p)\n", This
);
319 *grfBINDF
= BINDF_ASYNCHRONOUS
;
323 static HRESULT WINAPI
BindStatusCallback_OnDataAvailable(IBindStatusCallback
*iface
, DWORD grfBSCF
,
324 DWORD dwSize
, FORMATETC
* pformatetc
, STGMEDIUM
* pstgmed
)
326 MimeHtmlBinding
*This
= impl_from_IBindStatusCallback(iface
);
331 TRACE("(%p)\n", This
);
333 assert(pstgmed
->tymed
== TYMED_ISTREAM
);
336 hres
= IStream_Read(pstgmed
->u
.pstm
, buf
, sizeof(buf
), &read
);
341 hres
= IStream_Write(This
->stream
, buf
, read
, NULL
);
348 static HRESULT WINAPI
BindStatusCallback_OnObjectAvailable(IBindStatusCallback
*iface
,
349 REFIID riid
, IUnknown
* punk
)
355 static const IBindStatusCallbackVtbl BindStatusCallbackVtbl
= {
356 BindStatusCallback_QueryInterface
,
357 BindStatusCallback_AddRef
,
358 BindStatusCallback_Release
,
359 BindStatusCallback_OnStartBinding
,
360 BindStatusCallback_GetPriority
,
361 BindStatusCallback_OnLowResource
,
362 BindStatusCallback_OnProgress
,
363 BindStatusCallback_OnStopBinding
,
364 BindStatusCallback_GetBindInfo
,
365 BindStatusCallback_OnDataAvailable
,
366 BindStatusCallback_OnObjectAvailable
369 static inline MimeHtmlProtocol
*impl_from_IUnknown(IUnknown
*iface
)
371 return CONTAINING_RECORD(iface
, MimeHtmlProtocol
, IUnknown_inner
);
374 static HRESULT WINAPI
MimeHtmlProtocol_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
376 MimeHtmlProtocol
*This
= impl_from_IUnknown(iface
);
378 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
379 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
380 *ppv
= &This
->IInternetProtocol_iface
;
381 }else if(IsEqualGUID(&IID_IInternetProtocolRoot
, riid
)) {
382 TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This
, ppv
);
383 *ppv
= &This
->IInternetProtocol_iface
;
384 }else if(IsEqualGUID(&IID_IInternetProtocol
, riid
)) {
385 TRACE("(%p)->(IID_IInternetProtocol %p)\n", This
, ppv
);
386 *ppv
= &This
->IInternetProtocol_iface
;
387 }else if(IsEqualGUID(&IID_IInternetProtocolInfo
, riid
)) {
388 TRACE("(%p)->(IID_IInternetProtocolInfo %p)\n", This
, ppv
);
389 *ppv
= &This
->IInternetProtocolInfo_iface
;
391 FIXME("unknown interface %s\n", debugstr_guid(riid
));
393 return E_NOINTERFACE
;
396 IUnknown_AddRef((IUnknown
*)*ppv
);
400 static ULONG WINAPI
MimeHtmlProtocol_AddRef(IUnknown
*iface
)
402 MimeHtmlProtocol
*This
= impl_from_IUnknown(iface
);
403 ULONG ref
= InterlockedIncrement(&This
->ref
);
405 TRACE("(%p) ref=%d\n", This
, ref
);
410 static ULONG WINAPI
MimeHtmlProtocol_Release(IUnknown
*iface
)
412 MimeHtmlProtocol
*This
= impl_from_IUnknown(iface
);
413 ULONG ref
= InterlockedDecrement(&This
->ref
);
415 TRACE("(%p) ref=%x\n", This
, ref
);
419 IInternetProtocolSink_Release(This
->sink
);
421 IStream_Release(This
->stream
);
422 heap_free(This
->location
);
429 static const IUnknownVtbl MimeHtmlProtocolInnerVtbl
= {
430 MimeHtmlProtocol_QueryInterface
,
431 MimeHtmlProtocol_AddRef
,
432 MimeHtmlProtocol_Release
435 static inline MimeHtmlProtocol
*impl_from_IInternetProtocol(IInternetProtocol
*iface
)
437 return CONTAINING_RECORD(iface
, MimeHtmlProtocol
, IInternetProtocol_iface
);
440 static HRESULT WINAPI
InternetProtocol_QueryInterface(IInternetProtocol
*iface
, REFIID riid
, void **ppv
)
442 MimeHtmlProtocol
*This
= impl_from_IInternetProtocol(iface
);
443 return IUnknown_QueryInterface(This
->outer_unk
, riid
, ppv
);
446 static ULONG WINAPI
InternetProtocol_AddRef(IInternetProtocol
*iface
)
448 MimeHtmlProtocol
*This
= impl_from_IInternetProtocol(iface
);
449 return IUnknown_AddRef(This
->outer_unk
);
452 static ULONG WINAPI
InternetProtocol_Release(IInternetProtocol
*iface
)
454 MimeHtmlProtocol
*This
= impl_from_IInternetProtocol(iface
);
455 return IUnknown_Release(This
->outer_unk
);
458 static HRESULT WINAPI
MimeHtmlProtocol_Start(IInternetProtocol
*iface
, const WCHAR
*szUrl
,
459 IInternetProtocolSink
* pOIProtSink
, IInternetBindInfo
* pOIBindInfo
,
460 DWORD grfPI
, HANDLE_PTR dwReserved
)
462 MimeHtmlProtocol
*This
= impl_from_IInternetProtocol(iface
);
463 BINDINFO bindinfo
= { sizeof(bindinfo
) };
464 MimeHtmlBinding
*binding
;
472 TRACE("(%p)->(%s %p %p %08x %lx)\n", This
, debugstr_w(szUrl
), pOIProtSink
, pOIBindInfo
, grfPI
, dwReserved
);
474 hres
= parse_mhtml_url(szUrl
, &url
);
478 if(url
.location
&& !(This
->location
= heap_strdupW(url
.location
)))
479 return E_OUTOFMEMORY
;
481 hres
= IInternetBindInfo_GetBindInfo(pOIBindInfo
, &bindf
, &bindinfo
);
483 WARN("GetBindInfo failed: %08x\n", hres
);
486 if((bindf
& (BINDF_ASYNCHRONOUS
|BINDF_FROMURLMON
|BINDF_NEEDFILE
)) != (BINDF_ASYNCHRONOUS
|BINDF_FROMURLMON
|BINDF_NEEDFILE
))
487 FIXME("unsupported bindf %x\n", bindf
);
489 IInternetProtocolSink_AddRef(This
->sink
= pOIProtSink
);
491 binding
= heap_alloc(FIELD_OFFSET(MimeHtmlBinding
, url
[url
.mhtml_len
+1]));
493 return E_OUTOFMEMORY
;
494 memcpy(binding
->url
, url
.mhtml
, url
.mhtml_len
*sizeof(WCHAR
));
495 binding
->url
[url
.mhtml_len
] = 0;
497 hres
= CreateURLMoniker(NULL
, binding
->url
, &mon
);
503 binding
->IBindStatusCallback_iface
.lpVtbl
= &BindStatusCallbackVtbl
;
505 binding
->status
= E_PENDING
;
506 binding
->stream
= NULL
;
507 binding
->protocol
= NULL
;
509 hres
= CreateAsyncBindCtx(0, &binding
->IBindStatusCallback_iface
, NULL
, &bind_ctx
);
511 IMoniker_Release(mon
);
512 IBindStatusCallback_Release(&binding
->IBindStatusCallback_iface
);
516 IInternetProtocol_AddRef(&This
->IInternetProtocol_iface
);
517 binding
->protocol
= This
;
519 hres
= IMoniker_BindToStorage(mon
, bind_ctx
, NULL
, &IID_IStream
, (void**)&stream
);
520 IBindCtx_Release(bind_ctx
);
521 IMoniker_Release(mon
);
523 IStream_Release(stream
);
524 hres
= binding
->status
;
525 IBindStatusCallback_Release(&binding
->IBindStatusCallback_iface
);
526 if(FAILED(hres
) && hres
!= E_PENDING
)
527 report_result(This
, hres
);
531 static HRESULT WINAPI
MimeHtmlProtocol_Continue(IInternetProtocol
*iface
, PROTOCOLDATA
*pProtocolData
)
533 MimeHtmlProtocol
*This
= impl_from_IInternetProtocol(iface
);
534 FIXME("(%p)->(%p)\n", This
, pProtocolData
);
538 static HRESULT WINAPI
MimeHtmlProtocol_Abort(IInternetProtocol
*iface
, HRESULT hrReason
, DWORD dwOptions
)
540 MimeHtmlProtocol
*This
= impl_from_IInternetProtocol(iface
);
541 FIXME("(%p)->(%08x %08x)\n", This
, hrReason
, dwOptions
);
545 static HRESULT WINAPI
MimeHtmlProtocol_Terminate(IInternetProtocol
*iface
, DWORD dwOptions
)
547 MimeHtmlProtocol
*This
= impl_from_IInternetProtocol(iface
);
548 TRACE("(%p)->(%08x)\n", This
, dwOptions
);
552 static HRESULT WINAPI
MimeHtmlProtocol_Suspend(IInternetProtocol
*iface
)
554 MimeHtmlProtocol
*This
= impl_from_IInternetProtocol(iface
);
555 FIXME("(%p)\n", This
);
559 static HRESULT WINAPI
MimeHtmlProtocol_Resume(IInternetProtocol
*iface
)
561 MimeHtmlProtocol
*This
= impl_from_IInternetProtocol(iface
);
562 FIXME("(%p)\n", This
);
566 static HRESULT WINAPI
MimeHtmlProtocol_Read(IInternetProtocol
*iface
, void* pv
, ULONG cb
, ULONG
* pcbRead
)
568 MimeHtmlProtocol
*This
= impl_from_IInternetProtocol(iface
);
572 TRACE("(%p)->(%p %u %p)\n", This
, pv
, cb
, pcbRead
);
574 hres
= IStream_Read(This
->stream
, pv
, cb
, &read
);
580 return read
? S_OK
: S_FALSE
;
583 static HRESULT WINAPI
MimeHtmlProtocol_Seek(IInternetProtocol
*iface
, LARGE_INTEGER dlibMove
,
584 DWORD dwOrigin
, ULARGE_INTEGER
* plibNewPosition
)
586 MimeHtmlProtocol
*This
= impl_from_IInternetProtocol(iface
);
587 FIXME("(%p)->(%d %d %p)\n", This
, dlibMove
.u
.LowPart
, dwOrigin
, plibNewPosition
);
591 static HRESULT WINAPI
MimeHtmlProtocol_LockRequest(IInternetProtocol
*iface
, DWORD dwOptions
)
593 MimeHtmlProtocol
*This
= impl_from_IInternetProtocol(iface
);
594 FIXME("(%p)->(%d)\n", This
, dwOptions
);
598 static HRESULT WINAPI
MimeHtmlProtocol_UnlockRequest(IInternetProtocol
*iface
)
600 MimeHtmlProtocol
*This
= impl_from_IInternetProtocol(iface
);
601 FIXME("(%p)\n", This
);
605 static const IInternetProtocolVtbl MimeHtmlProtocolVtbl
= {
606 InternetProtocol_QueryInterface
,
607 InternetProtocol_AddRef
,
608 InternetProtocol_Release
,
609 MimeHtmlProtocol_Start
,
610 MimeHtmlProtocol_Continue
,
611 MimeHtmlProtocol_Abort
,
612 MimeHtmlProtocol_Terminate
,
613 MimeHtmlProtocol_Suspend
,
614 MimeHtmlProtocol_Resume
,
615 MimeHtmlProtocol_Read
,
616 MimeHtmlProtocol_Seek
,
617 MimeHtmlProtocol_LockRequest
,
618 MimeHtmlProtocol_UnlockRequest
621 static inline MimeHtmlProtocol
*impl_from_IInternetProtocolInfo(IInternetProtocolInfo
*iface
)
623 return CONTAINING_RECORD(iface
, MimeHtmlProtocol
, IInternetProtocolInfo_iface
);
626 static HRESULT WINAPI
MimeHtmlProtocolInfo_QueryInterface(IInternetProtocolInfo
*iface
, REFIID riid
, void **ppv
)
628 MimeHtmlProtocol
*This
= impl_from_IInternetProtocolInfo(iface
);
629 return IUnknown_QueryInterface(This
->outer_unk
, riid
, ppv
);
632 static ULONG WINAPI
MimeHtmlProtocolInfo_AddRef(IInternetProtocolInfo
*iface
)
634 MimeHtmlProtocol
*This
= impl_from_IInternetProtocolInfo(iface
);
635 return IUnknown_AddRef(This
->outer_unk
);
638 static ULONG WINAPI
MimeHtmlProtocolInfo_Release(IInternetProtocolInfo
*iface
)
640 MimeHtmlProtocol
*This
= impl_from_IInternetProtocolInfo(iface
);
641 return IUnknown_Release(This
->outer_unk
);
644 static HRESULT WINAPI
MimeHtmlProtocolInfo_ParseUrl(IInternetProtocolInfo
*iface
, LPCWSTR pwzUrl
,
645 PARSEACTION ParseAction
, DWORD dwParseFlags
, LPWSTR pwzResult
, DWORD cchResult
,
646 DWORD
* pcchResult
, DWORD dwReserved
)
648 MimeHtmlProtocol
*This
= impl_from_IInternetProtocolInfo(iface
);
649 FIXME("(%p)->(%s %d %x %p %d %p %d)\n", This
, debugstr_w(pwzUrl
), ParseAction
,
650 dwParseFlags
, pwzResult
, cchResult
, pcchResult
, dwReserved
);
651 return INET_E_DEFAULT_ACTION
;
654 static HRESULT WINAPI
MimeHtmlProtocolInfo_CombineUrl(IInternetProtocolInfo
*iface
,
655 LPCWSTR pwzBaseUrl
, LPCWSTR pwzRelativeUrl
, DWORD dwCombineFlags
, LPWSTR pwzResult
,
656 DWORD cchResult
, DWORD
* pcchResult
, DWORD dwReserved
)
658 MimeHtmlProtocol
*This
= impl_from_IInternetProtocolInfo(iface
);
659 size_t len
= sizeof(mhtml_prefixW
)/sizeof(WCHAR
);
664 TRACE("(%p)->(%s %s %08x %p %d %p %d)\n", This
, debugstr_w(pwzBaseUrl
),
665 debugstr_w(pwzRelativeUrl
), dwCombineFlags
, pwzResult
, cchResult
,
666 pcchResult
, dwReserved
);
668 hres
= parse_mhtml_url(pwzBaseUrl
, &url
);
672 if(!strncmpiW(pwzRelativeUrl
, mhtml_prefixW
, sizeof(mhtml_prefixW
)/sizeof(WCHAR
))) {
673 FIXME("Relative URL is mhtml protocol\n");
674 return INET_E_USE_DEFAULT_PROTOCOLHANDLER
;
677 len
+= url
.mhtml_len
;
679 len
+= strlenW(pwzRelativeUrl
) + sizeof(mhtml_separatorW
)/sizeof(WCHAR
);
680 if(len
>= cchResult
) {
685 memcpy(pwzResult
, mhtml_prefixW
, sizeof(mhtml_prefixW
));
686 p
= pwzResult
+ sizeof(mhtml_prefixW
)/sizeof(WCHAR
);
687 memcpy(p
, url
.mhtml
, url
.mhtml_len
*sizeof(WCHAR
));
689 if(*pwzRelativeUrl
) {
690 memcpy(p
, mhtml_separatorW
, sizeof(mhtml_separatorW
));
691 p
+= sizeof(mhtml_separatorW
)/sizeof(WCHAR
);
692 strcpyW(p
, pwzRelativeUrl
);
701 static HRESULT WINAPI
MimeHtmlProtocolInfo_CompareUrl(IInternetProtocolInfo
*iface
, LPCWSTR pwzUrl1
,
702 LPCWSTR pwzUrl2
, DWORD dwCompareFlags
)
704 MimeHtmlProtocol
*This
= impl_from_IInternetProtocolInfo(iface
);
705 FIXME("(%p)->(%s %s %08x)\n", This
, debugstr_w(pwzUrl1
), debugstr_w(pwzUrl2
), dwCompareFlags
);
709 static HRESULT WINAPI
MimeHtmlProtocolInfo_QueryInfo(IInternetProtocolInfo
*iface
, LPCWSTR pwzUrl
,
710 QUERYOPTION QueryOption
, DWORD dwQueryFlags
, LPVOID pBuffer
, DWORD cbBuffer
, DWORD
* pcbBuf
,
713 MimeHtmlProtocol
*This
= impl_from_IInternetProtocolInfo(iface
);
714 FIXME("(%p)->(%s %08x %08x %p %d %p %d)\n", This
, debugstr_w(pwzUrl
), QueryOption
, dwQueryFlags
, pBuffer
,
715 cbBuffer
, pcbBuf
, dwReserved
);
716 return INET_E_USE_DEFAULT_PROTOCOLHANDLER
;
719 static const IInternetProtocolInfoVtbl MimeHtmlProtocolInfoVtbl
= {
720 MimeHtmlProtocolInfo_QueryInterface
,
721 MimeHtmlProtocolInfo_AddRef
,
722 MimeHtmlProtocolInfo_Release
,
723 MimeHtmlProtocolInfo_ParseUrl
,
724 MimeHtmlProtocolInfo_CombineUrl
,
725 MimeHtmlProtocolInfo_CompareUrl
,
726 MimeHtmlProtocolInfo_QueryInfo
729 HRESULT
MimeHtmlProtocol_create(IUnknown
*outer
, void **obj
)
731 MimeHtmlProtocol
*protocol
;
733 protocol
= heap_alloc(sizeof(*protocol
));
735 return E_OUTOFMEMORY
;
737 protocol
->IUnknown_inner
.lpVtbl
= &MimeHtmlProtocolInnerVtbl
;
738 protocol
->IInternetProtocol_iface
.lpVtbl
= &MimeHtmlProtocolVtbl
;
739 protocol
->IInternetProtocolInfo_iface
.lpVtbl
= &MimeHtmlProtocolInfoVtbl
;
741 protocol
->outer_unk
= outer
? outer
: &protocol
->IUnknown_inner
;
742 protocol
->location
= NULL
;
743 protocol
->stream
= NULL
;
744 protocol
->sink
= NULL
;
746 *obj
= &protocol
->IUnknown_inner
;