shell32/autocomplete: Remove the property after replacing the callback instead of...
[wine.git] / dlls / mshtml / protocol.c
blobf7b02c9aa06425ffdd8ad30efb8a63aa62d5b7c0
1 /*
2 * Copyright 2005 Jacek Caban
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 "config.h"
21 #include <stdarg.h>
22 #include <stdio.h>
24 #define COBJMACROS
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "ole2.h"
31 #include "wine/debug.h"
33 #include "mshtml_private.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
37 typedef struct {
38 IUnknown IUnknown_inner;
39 IInternetProtocol IInternetProtocol_iface;
41 LONG ref;
43 BYTE *data;
44 ULONG data_len;
45 ULONG cur;
47 IUnknown *outer;
48 } InternetProtocol;
50 /********************************************************************
51 * common ProtocolFactory implementation
54 typedef struct {
55 IInternetProtocolInfo IInternetProtocolInfo_iface;
56 IClassFactory IClassFactory_iface;
57 } ProtocolFactory;
59 static inline ProtocolFactory *impl_from_IInternetProtocolInfo(IInternetProtocolInfo *iface)
61 return CONTAINING_RECORD(iface, ProtocolFactory, IInternetProtocolInfo_iface);
64 static HRESULT WINAPI InternetProtocolInfo_QueryInterface(IInternetProtocolInfo *iface, REFIID riid, void **ppv)
66 ProtocolFactory *This = impl_from_IInternetProtocolInfo(iface);
68 *ppv = NULL;
69 if(IsEqualGUID(&IID_IUnknown, riid)) {
70 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
71 *ppv = &This->IInternetProtocolInfo_iface;
72 }else if(IsEqualGUID(&IID_IInternetProtocolInfo, riid)) {
73 TRACE("(%p)->(IID_IInternetProtocolInfo %p)\n", This, ppv);
74 *ppv = &This->IInternetProtocolInfo_iface;
75 }else if(IsEqualGUID(&IID_IClassFactory, riid)) {
76 TRACE("(%p)->(IID_IClassFactory %p)\n", This, ppv);
77 *ppv = &This->IClassFactory_iface;
80 if(!*ppv) {
81 WARN("unknown interface %s\n", debugstr_guid(riid));
82 return E_NOINTERFACE;
85 IInternetProtocolInfo_AddRef(iface);
86 return S_OK;
89 static ULONG WINAPI InternetProtocolInfo_AddRef(IInternetProtocolInfo *iface)
91 TRACE("(%p)\n", iface);
92 return 2;
95 static ULONG WINAPI InternetProtocolInfo_Release(IInternetProtocolInfo *iface)
97 TRACE("(%p)\n", iface);
98 return 1;
101 static HRESULT WINAPI InternetProtocolInfo_CombineUrl(IInternetProtocolInfo *iface,
102 LPCWSTR pwzBaseUrl, LPCWSTR pwzRelativeUrl, DWORD dwCombineFlags, LPWSTR pwzResult,
103 DWORD cchResult, DWORD* pcchResult, DWORD dwReserved)
105 TRACE("%p)->(%s %s %08x %p %d %p %d)\n", iface, debugstr_w(pwzBaseUrl),
106 debugstr_w(pwzRelativeUrl), dwCombineFlags, pwzResult, cchResult,
107 pcchResult, dwReserved);
109 return INET_E_USE_DEFAULT_PROTOCOLHANDLER;
112 static HRESULT WINAPI InternetProtocolInfo_CompareUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl1,
113 LPCWSTR pwzUrl2, DWORD dwCompareFlags)
115 TRACE("%p)->(%s %s %08x)\n", iface, debugstr_w(pwzUrl1), debugstr_w(pwzUrl2), dwCompareFlags);
116 return E_NOTIMPL;
119 static inline ProtocolFactory *impl_from_IClassFactory(IClassFactory *iface)
121 return CONTAINING_RECORD(iface, ProtocolFactory, IClassFactory_iface);
124 static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
126 ProtocolFactory *This = impl_from_IClassFactory(iface);
127 return IInternetProtocolInfo_QueryInterface(&This->IInternetProtocolInfo_iface, riid, ppv);
130 static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface)
132 ProtocolFactory *This = impl_from_IClassFactory(iface);
133 return IInternetProtocolInfo_AddRef(&This->IInternetProtocolInfo_iface);
136 static ULONG WINAPI ClassFactory_Release(IClassFactory *iface)
138 ProtocolFactory *This = impl_from_IClassFactory(iface);
139 return IInternetProtocolInfo_Release(&This->IInternetProtocolInfo_iface);
142 static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL dolock)
144 TRACE("(%p)->(%x)\n", iface, dolock);
145 return S_OK;
148 static inline InternetProtocol *impl_from_IUnknown(IUnknown *iface)
150 return CONTAINING_RECORD(iface, InternetProtocol, IUnknown_inner);
153 static inline InternetProtocol *impl_from_IInternetProtocol(IInternetProtocol *iface)
155 return CONTAINING_RECORD(iface, InternetProtocol, IInternetProtocol_iface);
158 static HRESULT WINAPI Protocol_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
160 InternetProtocol *This = impl_from_IUnknown(iface);
162 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
164 if(IsEqualGUID(&IID_IUnknown, riid)) {
165 *ppv = &This->IUnknown_inner;
166 }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
167 *ppv = &This->IInternetProtocol_iface;
168 }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
169 *ppv = &This->IInternetProtocol_iface;
170 }else {
171 if(IsEqualGUID(&IID_IServiceProvider, riid))
172 FIXME("IServiceProvider is not implemented\n");
173 *ppv = NULL;
174 return E_NOINTERFACE;
177 IUnknown_AddRef((IUnknown*)*ppv);
178 return S_OK;
181 static ULONG WINAPI Protocol_AddRef(IUnknown *iface)
183 InternetProtocol *This = impl_from_IUnknown(iface);
184 ULONG ref = InterlockedIncrement(&This->ref);
185 TRACE("(%p) ref=%d\n", iface, ref);
186 return ref;
189 static ULONG WINAPI Protocol_Release(IUnknown *iface)
191 InternetProtocol *This = impl_from_IUnknown(iface);
192 ULONG ref = InterlockedDecrement(&This->ref);
194 TRACE("(%p) ref=%x\n", iface, ref);
196 if(!ref) {
197 heap_free(This->data);
198 heap_free(This);
201 return ref;
204 static const IUnknownVtbl ProtocolUnkVtbl = {
205 Protocol_QueryInterface,
206 Protocol_AddRef,
207 Protocol_Release
210 static HRESULT WINAPI InternetProtocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
212 InternetProtocol *This = impl_from_IInternetProtocol(iface);
213 return IUnknown_QueryInterface(This->outer, riid, ppv);
216 static ULONG WINAPI InternetProtocol_AddRef(IInternetProtocol *iface)
218 InternetProtocol *This = impl_from_IInternetProtocol(iface);
219 return IUnknown_AddRef(This->outer);
222 static ULONG WINAPI InternetProtocol_Release(IInternetProtocol *iface)
224 InternetProtocol *This = impl_from_IInternetProtocol(iface);
225 return IUnknown_Release(This->outer);
228 static HRESULT WINAPI InternetProtocol_Continue(IInternetProtocol *iface, PROTOCOLDATA* pProtocolData)
230 InternetProtocol *This = impl_from_IInternetProtocol(iface);
231 FIXME("(%p)->(%p)\n", This, pProtocolData);
232 return E_NOTIMPL;
235 static HRESULT WINAPI InternetProtocol_Abort(IInternetProtocol *iface, HRESULT hrReason,
236 DWORD dwOptions)
238 InternetProtocol *This = impl_from_IInternetProtocol(iface);
239 FIXME("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
240 return E_NOTIMPL;
243 static HRESULT WINAPI InternetProtocol_Terminate(IInternetProtocol *iface, DWORD dwOptions)
245 InternetProtocol *This = impl_from_IInternetProtocol(iface);
246 TRACE("(%p)->(%08x)\n", This, dwOptions);
247 return S_OK;
250 static HRESULT WINAPI InternetProtocol_Suspend(IInternetProtocol *iface)
252 InternetProtocol *This = impl_from_IInternetProtocol(iface);
253 FIXME("(%p)\n", This);
254 return E_NOTIMPL;
257 static HRESULT WINAPI InternetProtocol_Resume(IInternetProtocol *iface)
259 InternetProtocol *This = impl_from_IInternetProtocol(iface);
260 FIXME("(%p)\n", This);
261 return E_NOTIMPL;
264 static HRESULT WINAPI InternetProtocol_Read(IInternetProtocol *iface, void* pv, ULONG cb, ULONG* pcbRead)
266 InternetProtocol *This = impl_from_IInternetProtocol(iface);
268 TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
270 if(!This->data)
271 return E_FAIL;
273 *pcbRead = (cb > This->data_len-This->cur ? This->data_len-This->cur : cb);
275 if(!*pcbRead)
276 return S_FALSE;
278 memcpy(pv, This->data+This->cur, *pcbRead);
279 This->cur += *pcbRead;
281 return S_OK;
284 static HRESULT WINAPI InternetProtocol_Seek(IInternetProtocol *iface, LARGE_INTEGER dlibMove,
285 DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition)
287 InternetProtocol *This = impl_from_IInternetProtocol(iface);
288 FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
289 return E_NOTIMPL;
292 static HRESULT WINAPI InternetProtocol_LockRequest(IInternetProtocol *iface, DWORD dwOptions)
294 InternetProtocol *This = impl_from_IInternetProtocol(iface);
296 TRACE("(%p)->(%d)\n", This, dwOptions);
298 return S_OK;
301 static HRESULT WINAPI InternetProtocol_UnlockRequest(IInternetProtocol *iface)
303 InternetProtocol *This = impl_from_IInternetProtocol(iface);
305 TRACE("(%p)\n", This);
307 return S_OK;
310 static HRESULT create_protocol_instance(const IInternetProtocolVtbl *protocol_vtbl,
311 IUnknown *outer, REFIID riid, void **ppv)
313 InternetProtocol *protocol;
314 HRESULT hres;
316 if(outer && !IsEqualGUID(&IID_IUnknown, riid)) {
317 *ppv = NULL;
318 return E_INVALIDARG;
321 protocol = heap_alloc_zero(sizeof(InternetProtocol));
322 protocol->IUnknown_inner.lpVtbl = &ProtocolUnkVtbl;
323 protocol->IInternetProtocol_iface.lpVtbl = protocol_vtbl;
324 protocol->outer = outer ? outer : &protocol->IUnknown_inner;
325 protocol->ref = 1;
327 hres = IUnknown_QueryInterface(&protocol->IUnknown_inner, riid, ppv);
328 IUnknown_Release(&protocol->IUnknown_inner);
329 return hres;
332 /********************************************************************
333 * about protocol implementation
336 static HRESULT WINAPI AboutProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl,
337 IInternetProtocolSink* pOIProtSink, IInternetBindInfo* pOIBindInfo,
338 DWORD grfPI, HANDLE_PTR dwReserved)
340 InternetProtocol *This = impl_from_IInternetProtocol(iface);
341 BINDINFO bindinfo;
342 DWORD grfBINDF = 0;
343 LPCWSTR text = NULL;
344 DWORD data_len;
345 BYTE *data;
346 HRESULT hres;
348 static const WCHAR html_begin[] = {0xfeff,'<','H','T','M','L','>',0};
349 static const WCHAR html_end[] = {'<','/','H','T','M','L','>',0};
350 static const WCHAR wszBlank[] = {'b','l','a','n','k',0};
351 static const WCHAR wszAbout[] = {'a','b','o','u','t',':'};
352 static const WCHAR wszTextHtml[] = {'t','e','x','t','/','h','t','m','l',0};
354 /* NOTE:
355 * the about protocol seems not to work as I would expect. It creates html document
356 * for a given url, eg. about:some_text -> <HTML>some_text</HTML> except for the case when
357 * some_text = "blank", when document is blank (<HTML></HMTL>). The same happens
358 * when the url does not have "about:" in the beginning.
361 TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink,
362 pOIBindInfo, grfPI, dwReserved);
364 memset(&bindinfo, 0, sizeof(bindinfo));
365 bindinfo.cbSize = sizeof(BINDINFO);
366 hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &grfBINDF, &bindinfo);
367 if(FAILED(hres))
368 return hres;
369 ReleaseBindInfo(&bindinfo);
371 TRACE("bindf %x\n", grfBINDF);
373 if(strlenW(szUrl) >= ARRAY_SIZE(wszAbout) && !memcmp(wszAbout, szUrl, sizeof(wszAbout))) {
374 text = szUrl + ARRAY_SIZE(wszAbout);
375 if(!strcmpW(wszBlank, text))
376 text = NULL;
379 data_len = sizeof(html_begin)+sizeof(html_end)-sizeof(WCHAR)
380 + (text ? strlenW(text)*sizeof(WCHAR) : 0);
381 data = heap_alloc(data_len);
382 if(!data)
383 return E_OUTOFMEMORY;
385 heap_free(This->data);
386 This->data = data;
387 This->data_len = data_len;
389 memcpy(This->data, html_begin, sizeof(html_begin));
390 if(text)
391 strcatW((LPWSTR)This->data, text);
392 strcatW((LPWSTR)This->data, html_end);
394 This->cur = 0;
396 IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_MIMETYPEAVAILABLE, wszTextHtml);
398 IInternetProtocolSink_ReportData(pOIProtSink,
399 BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION | BSCF_DATAFULLYAVAILABLE,
400 This->data_len, This->data_len);
402 IInternetProtocolSink_ReportResult(pOIProtSink, S_OK, 0, NULL);
404 return S_OK;
407 static const IInternetProtocolVtbl AboutProtocolVtbl = {
408 InternetProtocol_QueryInterface,
409 InternetProtocol_AddRef,
410 InternetProtocol_Release,
411 AboutProtocol_Start,
412 InternetProtocol_Continue,
413 InternetProtocol_Abort,
414 InternetProtocol_Terminate,
415 InternetProtocol_Suspend,
416 InternetProtocol_Resume,
417 InternetProtocol_Read,
418 InternetProtocol_Seek,
419 InternetProtocol_LockRequest,
420 InternetProtocol_UnlockRequest
423 static HRESULT WINAPI AboutProtocolFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter,
424 REFIID riid, void **ppv)
426 TRACE("(%p)->(%p %s %p)\n", iface, pUnkOuter, debugstr_guid(riid), ppv);
428 return create_protocol_instance(&AboutProtocolVtbl, pUnkOuter, riid, ppv);
431 static HRESULT WINAPI AboutProtocolInfo_ParseUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
432 PARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult,
433 DWORD* pcchResult, DWORD dwReserved)
435 TRACE("%p)->(%s %d %08x %p %d %p %d)\n", iface, debugstr_w(pwzUrl), ParseAction,
436 dwParseFlags, pwzResult, cchResult, pcchResult, dwReserved);
438 if(ParseAction == PARSE_SECURITY_URL) {
439 unsigned int len = strlenW(pwzUrl)+1;
441 *pcchResult = len;
442 if(len > cchResult)
443 return S_FALSE;
445 memcpy(pwzResult, pwzUrl, len*sizeof(WCHAR));
446 return S_OK;
449 if(ParseAction == PARSE_DOMAIN) {
450 if(!pcchResult)
451 return E_POINTER;
453 if(pwzUrl)
454 *pcchResult = strlenW(pwzUrl)+1;
455 else
456 *pcchResult = 1;
457 return E_FAIL;
460 return INET_E_DEFAULT_ACTION;
463 static HRESULT WINAPI AboutProtocolInfo_QueryInfo(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
464 QUERYOPTION QueryOption, DWORD dwQueryFlags, LPVOID pBuffer, DWORD cbBuffer, DWORD* pcbBuf,
465 DWORD dwReserved)
467 TRACE("%p)->(%s %08x %08x %p %d %p %d)\n", iface, debugstr_w(pwzUrl), QueryOption, dwQueryFlags, pBuffer,
468 cbBuffer, pcbBuf, dwReserved);
470 switch(QueryOption) {
471 case QUERY_CAN_NAVIGATE:
472 return INET_E_USE_DEFAULT_PROTOCOLHANDLER;
474 case QUERY_USES_NETWORK:
475 if(!pBuffer || cbBuffer < sizeof(DWORD))
476 return E_FAIL;
478 *(DWORD*)pBuffer = 0;
479 if(pcbBuf)
480 *pcbBuf = sizeof(DWORD);
482 break;
484 case QUERY_IS_CACHED:
485 FIXME("Unsupported option QUERY_IS_CACHED\n");
486 return E_NOTIMPL;
487 case QUERY_IS_INSTALLEDENTRY:
488 FIXME("Unsupported option QUERY_IS_INSTALLEDENTRY\n");
489 return E_NOTIMPL;
490 case QUERY_IS_CACHED_OR_MAPPED:
491 FIXME("Unsupported option QUERY_IS_CACHED_OR_MAPPED\n");
492 return E_NOTIMPL;
493 case QUERY_IS_SECURE:
494 FIXME("Unsupported option QUERY_IS_SECURE\n");
495 return E_NOTIMPL;
496 case QUERY_IS_SAFE:
497 FIXME("Unsupported option QUERY_IS_SAFE\n");
498 return E_NOTIMPL;
499 case QUERY_USES_HISTORYFOLDER:
500 FIXME("Unsupported option QUERY_USES_HISTORYFOLDER\n");
501 return E_FAIL;
502 case QUERY_IS_CACHED_AND_USABLE_OFFLINE:
503 FIXME("Unsupported option QUERY_IS_CACHED_AND_USABLE_OFFLINE\n");
504 return E_NOTIMPL;
505 default:
506 return E_FAIL;
509 return S_OK;
512 static const IInternetProtocolInfoVtbl AboutProtocolInfoVtbl = {
513 InternetProtocolInfo_QueryInterface,
514 InternetProtocolInfo_AddRef,
515 InternetProtocolInfo_Release,
516 AboutProtocolInfo_ParseUrl,
517 InternetProtocolInfo_CombineUrl,
518 InternetProtocolInfo_CompareUrl,
519 AboutProtocolInfo_QueryInfo
522 static const IClassFactoryVtbl AboutProtocolFactoryVtbl = {
523 ClassFactory_QueryInterface,
524 ClassFactory_AddRef,
525 ClassFactory_Release,
526 AboutProtocolFactory_CreateInstance,
527 ClassFactory_LockServer
530 static ProtocolFactory AboutProtocolFactory = {
531 { &AboutProtocolInfoVtbl },
532 { &AboutProtocolFactoryVtbl }
535 /********************************************************************
536 * res protocol implementation
539 static HRESULT WINAPI ResProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl,
540 IInternetProtocolSink* pOIProtSink, IInternetBindInfo* pOIBindInfo,
541 DWORD grfPI, HANDLE_PTR dwReserved)
543 InternetProtocol *This = impl_from_IInternetProtocol(iface);
544 WCHAR *url_dll, *url_file, *url, *mime, *res_type = (LPWSTR)RT_HTML, *ptr;
545 DWORD grfBINDF = 0, len;
546 BINDINFO bindinfo;
547 HMODULE hdll;
548 HRSRC src;
549 HRESULT hres;
551 static const WCHAR wszRes[] = {'r','e','s',':','/','/'};
553 TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink,
554 pOIBindInfo, grfPI, dwReserved);
556 memset(&bindinfo, 0, sizeof(bindinfo));
557 bindinfo.cbSize = sizeof(BINDINFO);
558 hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &grfBINDF, &bindinfo);
559 if(FAILED(hres))
560 return hres;
561 ReleaseBindInfo(&bindinfo);
563 len = strlenW(szUrl)+16;
564 url = heap_alloc(len*sizeof(WCHAR));
565 hres = CoInternetParseUrl(szUrl, PARSE_ENCODE, 0, url, len, &len, 0);
566 if(FAILED(hres)) {
567 WARN("CoInternetParseUrl failed: %08x\n", hres);
568 heap_free(url);
569 IInternetProtocolSink_ReportResult(pOIProtSink, hres, 0, NULL);
570 return hres;
573 if(len < ARRAY_SIZE(wszRes) || memcmp(url, wszRes, sizeof(wszRes))) {
574 WARN("Wrong protocol of url: %s\n", debugstr_w(url));
575 IInternetProtocolSink_ReportResult(pOIProtSink, E_INVALIDARG, 0, NULL);
576 heap_free(url);
577 return E_INVALIDARG;
580 url_dll = url + ARRAY_SIZE(wszRes);
581 if(!(res_type = strchrW(url_dll, '/'))) {
582 WARN("wrong url: %s\n", debugstr_w(url));
583 IInternetProtocolSink_ReportResult(pOIProtSink, MK_E_SYNTAX, 0, NULL);
584 heap_free(url);
585 return MK_E_SYNTAX;
588 *res_type++ = 0;
589 if ((url_file = strchrW(res_type, '/'))) {
590 *url_file++ = 0;
591 }else {
592 url_file = res_type;
593 res_type = (LPWSTR)RT_HTML;
596 /* Ignore query and hash parts. */
597 if((ptr = strchrW(url_file, '?')))
598 *ptr = 0;
599 if(*url_file && (ptr = strchrW(url_file+1, '#')))
600 *ptr = 0;
602 hdll = LoadLibraryExW(url_dll, NULL, LOAD_LIBRARY_AS_DATAFILE);
603 if(!hdll) {
604 WARN("Could not open dll: %s\n", debugstr_w(url_dll));
605 IInternetProtocolSink_ReportResult(pOIProtSink, HRESULT_FROM_WIN32(GetLastError()), 0, NULL);
606 heap_free(url);
607 return HRESULT_FROM_WIN32(GetLastError());
610 TRACE("trying to find resource type %s, name %s\n", debugstr_w(res_type), debugstr_w(url_file));
612 src = FindResourceW(hdll, url_file, res_type);
613 if(!src) {
614 LPWSTR endpoint = NULL;
615 DWORD file_id = strtolW(url_file, &endpoint, 10);
616 if(endpoint == url_file+strlenW(url_file))
617 src = FindResourceW(hdll, MAKEINTRESOURCEW(file_id), res_type);
619 if(!src) {
620 WARN("Could not find resource\n");
621 IInternetProtocolSink_ReportResult(pOIProtSink,
622 HRESULT_FROM_WIN32(GetLastError()), 0, NULL);
623 heap_free(url);
624 return HRESULT_FROM_WIN32(GetLastError());
628 if(This->data) {
629 WARN("data already loaded\n");
630 heap_free(This->data);
633 This->data_len = SizeofResource(hdll, src);
634 This->data = heap_alloc(This->data_len);
635 memcpy(This->data, LoadResource(hdll, src), This->data_len);
636 This->cur = 0;
638 FreeLibrary(hdll);
640 hres = FindMimeFromData(NULL, url_file, This->data, This->data_len, NULL, 0, &mime, 0);
641 heap_free(url);
642 if(SUCCEEDED(hres)) {
643 IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_MIMETYPEAVAILABLE, mime);
644 CoTaskMemFree(mime);
647 IInternetProtocolSink_ReportData(pOIProtSink,
648 BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION | BSCF_DATAFULLYAVAILABLE,
649 This->data_len, This->data_len);
651 IInternetProtocolSink_ReportResult(pOIProtSink, S_OK, 0, NULL);
653 return S_OK;
656 static const IInternetProtocolVtbl ResProtocolVtbl = {
657 InternetProtocol_QueryInterface,
658 InternetProtocol_AddRef,
659 InternetProtocol_Release,
660 ResProtocol_Start,
661 InternetProtocol_Continue,
662 InternetProtocol_Abort,
663 InternetProtocol_Terminate,
664 InternetProtocol_Suspend,
665 InternetProtocol_Resume,
666 InternetProtocol_Read,
667 InternetProtocol_Seek,
668 InternetProtocol_LockRequest,
669 InternetProtocol_UnlockRequest
672 static HRESULT WINAPI ResProtocolFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter,
673 REFIID riid, void **ppv)
675 TRACE("(%p)->(%p %s %p)\n", iface, pUnkOuter, debugstr_guid(riid), ppv);
677 return create_protocol_instance(&ResProtocolVtbl, pUnkOuter, riid, ppv);
680 static HRESULT WINAPI ResProtocolInfo_ParseUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
681 PARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult,
682 DWORD* pcchResult, DWORD dwReserved)
684 TRACE("%p)->(%s %d %x %p %d %p %d)\n", iface, debugstr_w(pwzUrl), ParseAction,
685 dwParseFlags, pwzResult, cchResult, pcchResult, dwReserved);
687 if(ParseAction == PARSE_SECURITY_URL) {
688 WCHAR file_part[MAX_PATH], full_path[MAX_PATH];
689 WCHAR *ptr;
690 DWORD size, len;
692 static const WCHAR wszFile[] = {'f','i','l','e',':','/','/'};
693 static const WCHAR wszRes[] = {'r','e','s',':','/','/'};
695 if(strlenW(pwzUrl) <= ARRAY_SIZE(wszRes) || memcmp(pwzUrl, wszRes, sizeof(wszRes)))
696 return E_INVALIDARG;
698 ptr = strchrW(pwzUrl + ARRAY_SIZE(wszRes), '/');
699 if(!ptr)
700 return E_INVALIDARG;
702 len = ptr - (pwzUrl + ARRAY_SIZE(wszRes));
703 if(len >= ARRAY_SIZE(file_part)) {
704 FIXME("Too long URL\n");
705 return MK_E_SYNTAX;
708 memcpy(file_part, pwzUrl + ARRAY_SIZE(wszRes), len*sizeof(WCHAR));
709 file_part[len] = 0;
711 len = SearchPathW(NULL, file_part, NULL, ARRAY_SIZE(full_path), full_path, NULL);
712 if(!len) {
713 HMODULE module;
715 /* SearchPath does not work well with winelib files (like our test executable),
716 * so we also try to load the library here */
717 module = LoadLibraryExW(file_part, NULL, LOAD_LIBRARY_AS_DATAFILE);
718 if(!module) {
719 WARN("Could not find file %s\n", debugstr_w(file_part));
720 return MK_E_SYNTAX;
723 len = GetModuleFileNameW(module, full_path, ARRAY_SIZE(full_path));
724 FreeLibrary(module);
725 if(!len)
726 return E_FAIL;
729 size = ARRAY_SIZE(wszFile) + len + 1;
730 if(pcchResult)
731 *pcchResult = size;
732 if(size > cchResult)
733 return S_FALSE;
735 memcpy(pwzResult, wszFile, sizeof(wszFile));
736 memcpy(pwzResult + ARRAY_SIZE(wszFile), full_path, (len+1)*sizeof(WCHAR));
737 return S_OK;
740 if(ParseAction == PARSE_DOMAIN) {
741 if(!pcchResult)
742 return E_POINTER;
744 if(pwzUrl)
745 *pcchResult = strlenW(pwzUrl)+1;
746 else
747 *pcchResult = 1;
748 return E_FAIL;
751 return INET_E_DEFAULT_ACTION;
754 static HRESULT WINAPI ResProtocolInfo_QueryInfo(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
755 QUERYOPTION QueryOption, DWORD dwQueryFlags, LPVOID pBuffer, DWORD cbBuffer, DWORD* pcbBuf,
756 DWORD dwReserved)
758 TRACE("%p)->(%s %08x %08x %p %d %p %d)\n", iface, debugstr_w(pwzUrl), QueryOption, dwQueryFlags, pBuffer,
759 cbBuffer, pcbBuf, dwReserved);
761 switch(QueryOption) {
762 case QUERY_USES_NETWORK:
763 if(!pBuffer || cbBuffer < sizeof(DWORD))
764 return E_FAIL;
766 *(DWORD*)pBuffer = 0;
767 if(pcbBuf)
768 *pcbBuf = sizeof(DWORD);
769 break;
771 case QUERY_IS_SECURE:
772 FIXME("QUERY_IS_SECURE not supported\n");
773 return E_NOTIMPL;
774 case QUERY_IS_SAFE:
775 FIXME("QUERY_IS_SAFE not supported\n");
776 return E_NOTIMPL;
777 default:
778 return INET_E_USE_DEFAULT_PROTOCOLHANDLER;
781 return S_OK;
784 static const IInternetProtocolInfoVtbl ResProtocolInfoVtbl = {
785 InternetProtocolInfo_QueryInterface,
786 InternetProtocolInfo_AddRef,
787 InternetProtocolInfo_Release,
788 ResProtocolInfo_ParseUrl,
789 InternetProtocolInfo_CombineUrl,
790 InternetProtocolInfo_CompareUrl,
791 ResProtocolInfo_QueryInfo
794 static const IClassFactoryVtbl ResProtocolFactoryVtbl = {
795 ClassFactory_QueryInterface,
796 ClassFactory_AddRef,
797 ClassFactory_Release,
798 ResProtocolFactory_CreateInstance,
799 ClassFactory_LockServer
802 static ProtocolFactory ResProtocolFactory = {
803 { &ResProtocolInfoVtbl },
804 { &ResProtocolFactoryVtbl }
807 /********************************************************************
808 * JSProtocol implementation
811 static HRESULT WINAPI JSProtocolFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter,
812 REFIID riid, void **ppv)
814 FIXME("(%p)->(%p %s %p)\n", iface, pUnkOuter, debugstr_guid(riid), ppv);
815 return E_NOTIMPL;
818 static HRESULT WINAPI JSProtocolInfo_ParseUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
819 PARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult,
820 DWORD* pcchResult, DWORD dwReserved)
822 TRACE("%p)->(%s %d %x %p %d %p %d)\n", iface, debugstr_w(pwzUrl), ParseAction,
823 dwParseFlags, pwzResult, cchResult, pcchResult, dwReserved);
825 switch(ParseAction) {
826 case PARSE_SECURITY_URL:
827 FIXME("PARSE_SECURITY_URL\n");
828 return E_NOTIMPL;
829 case PARSE_DOMAIN:
830 FIXME("PARSE_DOMAIN\n");
831 return E_NOTIMPL;
832 default:
833 return INET_E_DEFAULT_ACTION;
836 return S_OK;
839 static HRESULT WINAPI JSProtocolInfo_QueryInfo(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
840 QUERYOPTION QueryOption, DWORD dwQueryFlags, LPVOID pBuffer, DWORD cbBuffer, DWORD* pcbBuf,
841 DWORD dwReserved)
843 TRACE("%p)->(%s %08x %08x %p %d %p %d)\n", iface, debugstr_w(pwzUrl), QueryOption, dwQueryFlags, pBuffer,
844 cbBuffer, pcbBuf, dwReserved);
846 switch(QueryOption) {
847 case QUERY_USES_NETWORK:
848 if(!pBuffer || cbBuffer < sizeof(DWORD))
849 return E_FAIL;
851 *(DWORD*)pBuffer = 0;
852 if(pcbBuf)
853 *pcbBuf = sizeof(DWORD);
854 break;
856 case QUERY_IS_SECURE:
857 FIXME("QUERY_IS_SECURE not supported\n");
858 return E_NOTIMPL;
860 default:
861 return INET_E_USE_DEFAULT_PROTOCOLHANDLER;
864 return S_OK;
867 static const IInternetProtocolInfoVtbl JSProtocolInfoVtbl = {
868 InternetProtocolInfo_QueryInterface,
869 InternetProtocolInfo_AddRef,
870 InternetProtocolInfo_Release,
871 JSProtocolInfo_ParseUrl,
872 InternetProtocolInfo_CombineUrl,
873 InternetProtocolInfo_CompareUrl,
874 JSProtocolInfo_QueryInfo
877 static const IClassFactoryVtbl JSProtocolFactoryVtbl = {
878 ClassFactory_QueryInterface,
879 ClassFactory_AddRef,
880 ClassFactory_Release,
881 JSProtocolFactory_CreateInstance,
882 ClassFactory_LockServer
885 static ProtocolFactory JSProtocolFactory = {
886 { &JSProtocolInfoVtbl },
887 { &JSProtocolFactoryVtbl }
890 HRESULT ProtocolFactory_Create(REFCLSID rclsid, REFIID riid, void **ppv)
892 ProtocolFactory *cf = NULL;
894 if(IsEqualGUID(&CLSID_AboutProtocol, rclsid))
895 cf = &AboutProtocolFactory;
896 else if(IsEqualGUID(&CLSID_ResProtocol, rclsid))
897 cf = &ResProtocolFactory;
898 else if(IsEqualGUID(&CLSID_JSProtocol, rclsid))
899 cf = &JSProtocolFactory;
901 if(!cf) {
902 FIXME("not implemented protocol %s\n", debugstr_guid(rclsid));
903 return CLASS_E_CLASSNOTAVAILABLE;
906 return IInternetProtocolInfo_QueryInterface(&cf->IInternetProtocolInfo_iface, riid, ppv);