* Slap *some* sense into our header inclusions.
[reactos.git] / reactos / dll / win32 / mshtml / protocol.c
1 /*
2 * Copyright 2005 Jacek Caban
3 *
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.
8 *
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.
13 *
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
17 */
18
19 #define WIN32_NO_STATUS
20 #define _INC_WINDOWS
21 #define COM_NO_WINDOWS_H
22
23 #include <config.h>
24
25 #include <stdarg.h>
26 //#include <stdio.h>
27
28 #define COBJMACROS
29
30 #include <windef.h>
31 #include <winbase.h>
32 //#include "winuser.h"
33 #include <ole2.h>
34
35 #include <wine/debug.h>
36 //#include "wine/unicode.h"
37
38 #include "mshtml_private.h"
39
40 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
41
42 /********************************************************************
43 * common ProtocolFactory implementation
44 */
45
46 #define CLASSFACTORY(x) (&(x)->lpClassFactoryVtbl)
47 #define PROTOCOL(x) ((IInternetProtocol*) &(x)->lpInternetProtocolVtbl)
48 #define PROTOCOLINFO(x) ((IInternetProtocolInfo*) &(x)->lpInternetProtocolInfoVtbl)
49
50 typedef struct {
51 const IInternetProtocolInfoVtbl *lpInternetProtocolInfoVtbl;
52 const IClassFactoryVtbl *lpClassFactoryVtbl;
53 } ProtocolFactory;
54
55 #define PROTOCOLINFO_THIS(iface) DEFINE_THIS(ProtocolFactory, InternetProtocolInfo, iface)
56
57 static HRESULT WINAPI InternetProtocolInfo_QueryInterface(IInternetProtocolInfo *iface, REFIID riid, void **ppv)
58 {
59 ProtocolFactory *This = PROTOCOLINFO_THIS(iface);
60
61 *ppv = NULL;
62 if(IsEqualGUID(&IID_IUnknown, riid)) {
63 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
64 *ppv = PROTOCOLINFO(This);
65 }else if(IsEqualGUID(&IID_IInternetProtocolInfo, riid)) {
66 TRACE("(%p)->(IID_IInternetProtocolInfo %p)\n", This, ppv);
67 *ppv = PROTOCOLINFO(This);
68 }else if(IsEqualGUID(&IID_IClassFactory, riid)) {
69 TRACE("(%p)->(IID_IClassFactory %p)\n", This, ppv);
70 *ppv = CLASSFACTORY(This);
71 }
72
73 if(!*ppv) {
74 WARN("unknown interface %s\n", debugstr_guid(riid));
75 return E_NOINTERFACE;
76 }
77
78 IInternetProtocolInfo_AddRef(iface);
79 return S_OK;
80 }
81
82 static ULONG WINAPI InternetProtocolInfo_AddRef(IInternetProtocolInfo *iface)
83 {
84 TRACE("(%p)\n", iface);
85 return 2;
86 }
87
88 static ULONG WINAPI InternetProtocolInfo_Release(IInternetProtocolInfo *iface)
89 {
90 TRACE("(%p)\n", iface);
91 return 1;
92 }
93
94 static HRESULT WINAPI InternetProtocolInfo_CombineUrl(IInternetProtocolInfo *iface,
95 LPCWSTR pwzBaseUrl, LPCWSTR pwzRelativeUrl, DWORD dwCombineFlags, LPWSTR pwzResult,
96 DWORD cchResult, DWORD* pcchResult, DWORD dwReserved)
97 {
98 TRACE("%p)->(%s %s %08x %p %d %p %d)\n", iface, debugstr_w(pwzBaseUrl),
99 debugstr_w(pwzRelativeUrl), dwCombineFlags, pwzResult, cchResult,
100 pcchResult, dwReserved);
101
102 return INET_E_USE_DEFAULT_PROTOCOLHANDLER;
103 }
104
105 static HRESULT WINAPI InternetProtocolInfo_CompareUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl1,
106 LPCWSTR pwzUrl2, DWORD dwCompareFlags)
107 {
108 TRACE("%p)->(%s %s %08x)\n", iface, debugstr_w(pwzUrl1), debugstr_w(pwzUrl2), dwCompareFlags);
109 return E_NOTIMPL;
110 }
111
112 #undef PROTOCOLINFO_THIS
113
114 #define CLASSFACTORY_THIS(iface) DEFINE_THIS(ProtocolFactory, ClassFactory, iface)
115
116 static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
117 {
118 ProtocolFactory *This = CLASSFACTORY_THIS(iface);
119 return IInternetProtocolInfo_QueryInterface(PROTOCOLINFO(This), riid, ppv);
120 }
121
122 static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface)
123 {
124 ProtocolFactory *This = CLASSFACTORY_THIS(iface);
125 return IInternetProtocolInfo_AddRef(PROTOCOLINFO(This));
126 }
127
128 static ULONG WINAPI ClassFactory_Release(IClassFactory *iface)
129 {
130 ProtocolFactory *This = CLASSFACTORY_THIS(iface);
131 return IInternetProtocolInfo_Release(PROTOCOLINFO(This));
132 }
133
134 static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL dolock)
135 {
136 TRACE("(%p)->(%x)\n", iface, dolock);
137 return S_OK;
138 }
139
140 #undef CLASSFACTORY_THIS
141
142 /********************************************************************
143 * AboutProtocol implementation
144 */
145
146 typedef struct {
147 const IInternetProtocolVtbl *lpInternetProtocolVtbl;
148
149 LONG ref;
150
151 BYTE *data;
152 ULONG data_len;
153 ULONG cur;
154
155 IUnknown *pUnkOuter;
156 } AboutProtocol;
157
158 #define PROTOCOL_THIS(iface) DEFINE_THIS(AboutProtocol, InternetProtocol, iface)
159
160 static HRESULT WINAPI AboutProtocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
161 {
162 AboutProtocol *This = PROTOCOL_THIS(iface);
163
164 *ppv = NULL;
165
166 if(IsEqualGUID(&IID_IUnknown, riid)) {
167 TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv);
168 if(This->pUnkOuter)
169 return IUnknown_QueryInterface(This->pUnkOuter, riid, ppv);
170 *ppv = PROTOCOL(This);
171 }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
172 TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", iface, ppv);
173 *ppv = PROTOCOL(This);
174 }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
175 TRACE("(%p)->(IID_IInternetProtocol %p)\n", iface, ppv);
176 *ppv = PROTOCOL(This);
177 }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
178 FIXME("IServiceProvider is not implemented\n");
179 return E_NOINTERFACE;
180 }
181
182 if(!*ppv) {
183 TRACE("unknown interface %s\n", debugstr_guid(riid));
184 return E_NOINTERFACE;
185 }
186
187 IInternetProtocol_AddRef(iface);
188 return S_OK;
189 }
190
191 static ULONG WINAPI AboutProtocol_AddRef(IInternetProtocol *iface)
192 {
193 AboutProtocol *This = PROTOCOL_THIS(iface);
194 ULONG ref = InterlockedIncrement(&This->ref);
195 TRACE("(%p) ref=%d\n", iface, ref);
196 return This->pUnkOuter ? IUnknown_AddRef(This->pUnkOuter) : ref;
197 }
198
199 static ULONG WINAPI AboutProtocol_Release(IInternetProtocol *iface)
200 {
201 AboutProtocol *This = PROTOCOL_THIS(iface);
202 IUnknown *pUnkOuter = This->pUnkOuter;
203 ULONG ref = InterlockedDecrement(&This->ref);
204
205 TRACE("(%p) ref=%x\n", iface, ref);
206
207 if(!ref) {
208 heap_free(This->data);
209 heap_free(This);
210 }
211
212 return pUnkOuter ? IUnknown_Release(pUnkOuter) : ref;
213 }
214
215 static HRESULT WINAPI AboutProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl,
216 IInternetProtocolSink* pOIProtSink, IInternetBindInfo* pOIBindInfo,
217 DWORD grfPI, HANDLE_PTR dwReserved)
218 {
219 AboutProtocol *This = PROTOCOL_THIS(iface);
220 BINDINFO bindinfo;
221 DWORD grfBINDF = 0;
222 LPCWSTR text = NULL;
223
224 static const WCHAR html_begin[] = {0xfeff,'<','H','T','M','L','>',0};
225 static const WCHAR html_end[] = {'<','/','H','T','M','L','>',0};
226 static const WCHAR wszBlank[] = {'b','l','a','n','k',0};
227 static const WCHAR wszAbout[] = {'a','b','o','u','t',':'};
228 static const WCHAR wszTextHtml[] = {'t','e','x','t','/','h','t','m','l',0};
229
230 /* NOTE:
231 * the about protocol seems not to work as I would expect. It creates html document
232 * for a given url, eg. about:some_text -> <HTML>some_text</HTML> except for the case when
233 * some_text = "blank", when document is blank (<HTML></HMTL>). The same happens
234 * when the url does not have "about:" in the beginning.
235 */
236
237 TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink,
238 pOIBindInfo, grfPI, dwReserved);
239
240 memset(&bindinfo, 0, sizeof(bindinfo));
241 bindinfo.cbSize = sizeof(BINDINFO);
242 IInternetBindInfo_GetBindInfo(pOIBindInfo, &grfBINDF, &bindinfo);
243 ReleaseBindInfo(&bindinfo);
244
245 TRACE("bindf %x\n", grfBINDF);
246
247 if(strlenW(szUrl)>=sizeof(wszAbout)/sizeof(WCHAR) && !memcmp(wszAbout, szUrl, sizeof(wszAbout))) {
248 text = szUrl + sizeof(wszAbout)/sizeof(WCHAR);
249 if(!strcmpW(wszBlank, text))
250 text = NULL;
251 }
252
253 This->data_len = sizeof(html_begin)+sizeof(html_end)-sizeof(WCHAR)
254 + (text ? strlenW(text)*sizeof(WCHAR) : 0);
255 This->data = heap_alloc(This->data_len);
256
257 memcpy(This->data, html_begin, sizeof(html_begin));
258 if(text)
259 strcatW((LPWSTR)This->data, text);
260 strcatW((LPWSTR)This->data, html_end);
261
262 This->cur = 0;
263
264 IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_MIMETYPEAVAILABLE, wszTextHtml);
265
266 IInternetProtocolSink_ReportData(pOIProtSink,
267 BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION | BSCF_DATAFULLYAVAILABLE,
268 This->data_len, This->data_len);
269
270 IInternetProtocolSink_ReportResult(pOIProtSink, S_OK, 0, NULL);
271
272 return S_OK;
273 }
274
275 static HRESULT WINAPI AboutProtocol_Continue(IInternetProtocol *iface, PROTOCOLDATA* pProtocolData)
276 {
277 AboutProtocol *This = PROTOCOL_THIS(iface);
278 FIXME("(%p)->(%p)\n", This, pProtocolData);
279 return E_NOTIMPL;
280 }
281
282 static HRESULT WINAPI AboutProtocol_Abort(IInternetProtocol *iface, HRESULT hrReason,
283 DWORD dwOptions)
284 {
285 AboutProtocol *This = PROTOCOL_THIS(iface);
286 FIXME("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
287 return E_NOTIMPL;
288 }
289
290 static HRESULT WINAPI AboutProtocol_Terminate(IInternetProtocol *iface, DWORD dwOptions)
291 {
292 AboutProtocol *This = PROTOCOL_THIS(iface);
293 TRACE("(%p)->(%08x)\n", This, dwOptions);
294 return S_OK;
295 }
296
297 static HRESULT WINAPI AboutProtocol_Suspend(IInternetProtocol *iface)
298 {
299 AboutProtocol *This = PROTOCOL_THIS(iface);
300 FIXME("(%p)\n", This);
301 return E_NOTIMPL;
302 }
303
304 static HRESULT WINAPI AboutProtocol_Resume(IInternetProtocol *iface)
305 {
306 AboutProtocol *This = PROTOCOL_THIS(iface);
307 FIXME("(%p)\n", This);
308 return E_NOTIMPL;
309 }
310
311 static HRESULT WINAPI AboutProtocol_Read(IInternetProtocol *iface, void* pv, ULONG cb, ULONG* pcbRead)
312 {
313 AboutProtocol *This = PROTOCOL_THIS(iface);
314
315 TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
316
317 if(!This->data)
318 return E_FAIL;
319
320 *pcbRead = (cb > This->data_len-This->cur ? This->data_len-This->cur : cb);
321
322 if(!*pcbRead)
323 return S_FALSE;
324
325 memcpy(pv, This->data+This->cur, *pcbRead);
326 This->cur += *pcbRead;
327
328 return S_OK;
329 }
330
331 static HRESULT WINAPI AboutProtocol_Seek(IInternetProtocol *iface, LARGE_INTEGER dlibMove,
332 DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition)
333 {
334 AboutProtocol *This = PROTOCOL_THIS(iface);
335 FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
336 return E_NOTIMPL;
337 }
338
339 static HRESULT WINAPI AboutProtocol_LockRequest(IInternetProtocol *iface, DWORD dwOptions)
340 {
341 AboutProtocol *This = PROTOCOL_THIS(iface);
342
343 TRACE("(%p)->(%d)\n", This, dwOptions);
344
345 return S_OK;
346 }
347
348 static HRESULT WINAPI AboutProtocol_UnlockRequest(IInternetProtocol *iface)
349 {
350 AboutProtocol *This = PROTOCOL_THIS(iface);
351
352 TRACE("(%p)\n", This);
353
354 return S_OK;
355 }
356
357 #undef PROTOCOL_THIS
358
359 static const IInternetProtocolVtbl AboutProtocolVtbl = {
360 AboutProtocol_QueryInterface,
361 AboutProtocol_AddRef,
362 AboutProtocol_Release,
363 AboutProtocol_Start,
364 AboutProtocol_Continue,
365 AboutProtocol_Abort,
366 AboutProtocol_Terminate,
367 AboutProtocol_Suspend,
368 AboutProtocol_Resume,
369 AboutProtocol_Read,
370 AboutProtocol_Seek,
371 AboutProtocol_LockRequest,
372 AboutProtocol_UnlockRequest
373 };
374
375 static HRESULT WINAPI AboutProtocolFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter,
376 REFIID riid, void **ppv)
377 {
378 AboutProtocol *ret;
379 HRESULT hres = S_OK;
380
381 TRACE("(%p)->(%p %s %p)\n", iface, pUnkOuter, debugstr_guid(riid), ppv);
382
383 ret = heap_alloc(sizeof(AboutProtocol));
384 ret->lpInternetProtocolVtbl = &AboutProtocolVtbl;
385 ret->ref = 0;
386
387 ret->data = NULL;
388 ret->data_len = 0;
389 ret->cur = 0;
390 ret->pUnkOuter = pUnkOuter;
391
392 if(pUnkOuter) {
393 ret->ref = 1;
394 if(IsEqualGUID(&IID_IUnknown, riid))
395 *ppv = PROTOCOL(ret);
396 else
397 hres = E_INVALIDARG;
398 }else {
399 hres = IInternetProtocol_QueryInterface(PROTOCOL(ret), riid, ppv);
400 }
401
402 if(FAILED(hres))
403 heap_free(ret);
404
405 return hres;
406 }
407
408 static HRESULT WINAPI AboutProtocolInfo_ParseUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
409 PARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult,
410 DWORD* pcchResult, DWORD dwReserved)
411 {
412 TRACE("%p)->(%s %08x %08x %p %d %p %d)\n", iface, debugstr_w(pwzUrl), ParseAction,
413 dwParseFlags, pwzResult, cchResult, pcchResult, dwReserved);
414
415 if(ParseAction == PARSE_SECURITY_URL) {
416 unsigned int len = strlenW(pwzUrl);
417
418 if(len >= cchResult)
419 return S_FALSE;
420
421 memcpy(pwzResult, pwzUrl, (len+1)*sizeof(WCHAR));
422 return S_OK;
423 }
424
425 if(ParseAction == PARSE_DOMAIN) {
426 if(!pcchResult)
427 return E_POINTER;
428
429 if(pwzUrl)
430 *pcchResult = strlenW(pwzUrl)+1;
431 else
432 *pcchResult = 1;
433 return E_FAIL;
434 }
435
436 return INET_E_DEFAULT_ACTION;
437 }
438
439 static HRESULT WINAPI AboutProtocolInfo_QueryInfo(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
440 QUERYOPTION QueryOption, DWORD dwQueryFlags, LPVOID pBuffer, DWORD cbBuffer, DWORD* pcbBuf,
441 DWORD dwReserved)
442 {
443 TRACE("%p)->(%s %08x %08x %p %d %p %d)\n", iface, debugstr_w(pwzUrl), QueryOption, dwQueryFlags, pBuffer,
444 cbBuffer, pcbBuf, dwReserved);
445
446 switch(QueryOption) {
447 case QUERY_CAN_NAVIGATE:
448 return INET_E_USE_DEFAULT_PROTOCOLHANDLER;
449
450 case QUERY_USES_NETWORK:
451 if(!pBuffer || cbBuffer < sizeof(DWORD))
452 return E_FAIL;
453
454 *(DWORD*)pBuffer = 0;
455 if(pcbBuf)
456 *pcbBuf = sizeof(DWORD);
457
458 break;
459
460 case QUERY_IS_CACHED:
461 FIXME("Unsupported option QUERY_IS_CACHED\n");
462 return E_NOTIMPL;
463 case QUERY_IS_INSTALLEDENTRY:
464 FIXME("Unsupported option QUERY_IS_INSTALLEDENTRY\n");
465 return E_NOTIMPL;
466 case QUERY_IS_CACHED_OR_MAPPED:
467 FIXME("Unsupported option QUERY_IS_CACHED_OR_MAPPED\n");
468 return E_NOTIMPL;
469 case QUERY_IS_SECURE:
470 FIXME("Unsupported option QUERY_IS_SECURE\n");
471 return E_NOTIMPL;
472 case QUERY_IS_SAFE:
473 FIXME("Unsupported option QUERY_IS_SAFE\n");
474 return E_NOTIMPL;
475 case QUERY_USES_HISTORYFOLDER:
476 FIXME("Unsupported option QUERY_USES_HISTORYFOLDER\n");
477 return E_FAIL;
478 default:
479 return E_FAIL;
480 }
481
482 return S_OK;
483 }
484
485 static const IInternetProtocolInfoVtbl AboutProtocolInfoVtbl = {
486 InternetProtocolInfo_QueryInterface,
487 InternetProtocolInfo_AddRef,
488 InternetProtocolInfo_Release,
489 AboutProtocolInfo_ParseUrl,
490 InternetProtocolInfo_CombineUrl,
491 InternetProtocolInfo_CompareUrl,
492 AboutProtocolInfo_QueryInfo
493 };
494
495 static const IClassFactoryVtbl AboutProtocolFactoryVtbl = {
496 ClassFactory_QueryInterface,
497 ClassFactory_AddRef,
498 ClassFactory_Release,
499 AboutProtocolFactory_CreateInstance,
500 ClassFactory_LockServer
501 };
502
503 static ProtocolFactory AboutProtocolFactory = {
504 &AboutProtocolInfoVtbl,
505 &AboutProtocolFactoryVtbl
506 };
507
508 /********************************************************************
509 * ResProtocol implementation
510 */
511
512 typedef struct {
513 const IInternetProtocolVtbl *lpInternetProtocolVtbl;
514 LONG ref;
515
516 BYTE *data;
517 ULONG data_len;
518 ULONG cur;
519
520 IUnknown *pUnkOuter;
521 } ResProtocol;
522
523 #define PROTOCOL_THIS(iface) DEFINE_THIS(ResProtocol, InternetProtocol, iface)
524
525 static HRESULT WINAPI ResProtocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
526 {
527 ResProtocol *This = PROTOCOL_THIS(iface);
528
529 *ppv = NULL;
530
531 if(IsEqualGUID(&IID_IUnknown, riid)) {
532 TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv);
533 if(This->pUnkOuter)
534 return IUnknown_QueryInterface(This->pUnkOuter, &IID_IUnknown, ppv);
535 *ppv = PROTOCOL(This);
536 }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
537 TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", iface, ppv);
538 *ppv = PROTOCOL(This);
539 }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
540 TRACE("(%p)->(IID_IInternetProtocol %p)\n", iface, ppv);
541 *ppv = PROTOCOL(This);
542 }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
543 FIXME("IServiceProvider is not implemented\n");
544 return E_NOINTERFACE;
545 }
546
547 if(!*ppv) {
548 TRACE("unknown interface %s\n", debugstr_guid(riid));
549 return E_NOINTERFACE;
550 }
551
552 IInternetProtocol_AddRef(iface);
553 return S_OK;
554 }
555
556 static ULONG WINAPI ResProtocol_AddRef(IInternetProtocol *iface)
557 {
558 ResProtocol *This = PROTOCOL_THIS(iface);
559 ULONG ref = InterlockedIncrement(&This->ref);
560 TRACE("(%p) ref=%d\n", iface, ref);
561 return This->pUnkOuter ? IUnknown_AddRef(This->pUnkOuter) : ref;
562 }
563
564 static ULONG WINAPI ResProtocol_Release(IInternetProtocol *iface)
565 {
566 ResProtocol *This = (ResProtocol*)iface;
567 IUnknown *pUnkOuter = This->pUnkOuter;
568 ULONG ref = InterlockedDecrement(&This->ref);
569
570 TRACE("(%p) ref=%x\n", iface, ref);
571
572 if(!ref) {
573 heap_free(This->data);
574 heap_free(This);
575 }
576
577 return pUnkOuter ? IUnknown_Release(pUnkOuter) : ref;
578 }
579
580 static HRESULT WINAPI ResProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl,
581 IInternetProtocolSink* pOIProtSink, IInternetBindInfo* pOIBindInfo,
582 DWORD grfPI, HANDLE_PTR dwReserved)
583 {
584 ResProtocol *This = PROTOCOL_THIS(iface);
585 DWORD grfBINDF = 0, len;
586 BINDINFO bindinfo;
587 LPWSTR url_dll, url_file, url, mime, res_type = (LPWSTR)RT_HTML;
588 HMODULE hdll;
589 HRSRC src;
590 HRESULT hres;
591
592 static const WCHAR wszRes[] = {'r','e','s',':','/','/'};
593
594 TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink,
595 pOIBindInfo, grfPI, dwReserved);
596
597 memset(&bindinfo, 0, sizeof(bindinfo));
598 bindinfo.cbSize = sizeof(BINDINFO);
599 IInternetBindInfo_GetBindInfo(pOIBindInfo, &grfBINDF, &bindinfo);
600 ReleaseBindInfo(&bindinfo);
601
602 len = strlenW(szUrl)+16;
603 url = heap_alloc(len*sizeof(WCHAR));
604 hres = CoInternetParseUrl(szUrl, PARSE_ENCODE, 0, url, len, &len, 0);
605 if(FAILED(hres)) {
606 WARN("CoInternetParseUrl failed: %08x\n", hres);
607 heap_free(url);
608 IInternetProtocolSink_ReportResult(pOIProtSink, hres, 0, NULL);
609 return hres;
610 }
611
612 if(len < sizeof(wszRes)/sizeof(wszRes[0]) || memcmp(url, wszRes, sizeof(wszRes))) {
613 WARN("Wrong protocol of url: %s\n", debugstr_w(url));
614 IInternetProtocolSink_ReportResult(pOIProtSink, E_INVALIDARG, 0, NULL);
615 heap_free(url);
616 return E_INVALIDARG;
617 }
618
619 url_dll = url + sizeof(wszRes)/sizeof(wszRes[0]);
620 if(!(url_file = strrchrW(url_dll, '/'))) {
621 WARN("wrong url: %s\n", debugstr_w(url));
622 IInternetProtocolSink_ReportResult(pOIProtSink, MK_E_SYNTAX, 0, NULL);
623 heap_free(url);
624 return MK_E_SYNTAX;
625 }
626
627 *url_file++ = 0;
628 hdll = LoadLibraryExW(url_dll, NULL, LOAD_LIBRARY_AS_DATAFILE);
629 if(!hdll) {
630 if (!(res_type = strrchrW(url_dll, '/'))) {
631 WARN("Could not open dll: %s\n", debugstr_w(url_dll));
632 IInternetProtocolSink_ReportResult(pOIProtSink, HRESULT_FROM_WIN32(GetLastError()), 0, NULL);
633 heap_free(url);
634 return HRESULT_FROM_WIN32(GetLastError());
635 }
636 *res_type++ = 0;
637
638 hdll = LoadLibraryExW(url_dll, NULL, LOAD_LIBRARY_AS_DATAFILE);
639 if(!hdll) {
640 WARN("Could not open dll: %s\n", debugstr_w(url_dll));
641 IInternetProtocolSink_ReportResult(pOIProtSink, HRESULT_FROM_WIN32(GetLastError()), 0, NULL);
642 heap_free(url);
643 return HRESULT_FROM_WIN32(GetLastError());
644 }
645 }
646
647 TRACE("trying to find resource type %s, name %s\n", debugstr_w(res_type), debugstr_w(url_file));
648
649 src = FindResourceW(hdll, url_file, res_type);
650 if(!src) {
651 LPWSTR endpoint = NULL;
652 DWORD file_id = strtolW(url_file, &endpoint, 10);
653 if(endpoint == url_file+strlenW(url_file))
654 src = FindResourceW(hdll, MAKEINTRESOURCEW(file_id), MAKEINTRESOURCEW(RT_HTML));
655
656 if(!src) {
657 WARN("Could not find resource\n");
658 IInternetProtocolSink_ReportResult(pOIProtSink,
659 HRESULT_FROM_WIN32(GetLastError()), 0, NULL);
660 heap_free(url);
661 return HRESULT_FROM_WIN32(GetLastError());
662 }
663 }
664
665 if(This->data) {
666 WARN("data already loaded\n");
667 heap_free(This->data);
668 }
669
670 This->data_len = SizeofResource(hdll, src);
671 This->data = heap_alloc(This->data_len);
672 memcpy(This->data, LoadResource(hdll, src), This->data_len);
673 This->cur = 0;
674
675 FreeLibrary(hdll);
676
677 hres = FindMimeFromData(NULL, url_file, This->data, This->data_len, NULL, 0, &mime, 0);
678 heap_free(url);
679 if(SUCCEEDED(hres)) {
680 IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_MIMETYPEAVAILABLE, mime);
681 CoTaskMemFree(mime);
682 }
683
684 IInternetProtocolSink_ReportData(pOIProtSink,
685 BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION | BSCF_DATAFULLYAVAILABLE,
686 This->data_len, This->data_len);
687
688 IInternetProtocolSink_ReportResult(pOIProtSink, S_OK, 0, NULL);
689
690 return S_OK;
691 }
692
693 static HRESULT WINAPI ResProtocol_Continue(IInternetProtocol *iface, PROTOCOLDATA* pProtocolData)
694 {
695 ResProtocol *This = PROTOCOL_THIS(iface);
696 FIXME("(%p)->(%p)\n", This, pProtocolData);
697 return E_NOTIMPL;
698 }
699
700 static HRESULT WINAPI ResProtocol_Abort(IInternetProtocol *iface, HRESULT hrReason,
701 DWORD dwOptions)
702 {
703 ResProtocol *This = PROTOCOL_THIS(iface);
704 FIXME("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
705 return E_NOTIMPL;
706 }
707
708 static HRESULT WINAPI ResProtocol_Terminate(IInternetProtocol *iface, DWORD dwOptions)
709 {
710 ResProtocol *This = PROTOCOL_THIS(iface);
711
712 TRACE("(%p)->(%08x)\n", This, dwOptions);
713
714 /* test show that we don't have to do anything here */
715 return S_OK;
716 }
717
718 static HRESULT WINAPI ResProtocol_Suspend(IInternetProtocol *iface)
719 {
720 ResProtocol *This = PROTOCOL_THIS(iface);
721 FIXME("(%p)\n", This);
722 return E_NOTIMPL;
723 }
724
725 static HRESULT WINAPI ResProtocol_Resume(IInternetProtocol *iface)
726 {
727 ResProtocol *This = PROTOCOL_THIS(iface);
728 FIXME("(%p)\n", This);
729 return E_NOTIMPL;
730 }
731
732 static HRESULT WINAPI ResProtocol_Read(IInternetProtocol *iface, void* pv, ULONG cb, ULONG* pcbRead)
733 {
734 ResProtocol *This = PROTOCOL_THIS(iface);
735
736 TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
737
738 if(!This->data)
739 return E_FAIL;
740
741 *pcbRead = (cb > This->data_len-This->cur ? This->data_len-This->cur : cb);
742
743 if(!*pcbRead)
744 return S_FALSE;
745
746 memcpy(pv, This->data+This->cur, *pcbRead);
747 This->cur += *pcbRead;
748
749 return S_OK;
750 }
751
752 static HRESULT WINAPI ResProtocol_Seek(IInternetProtocol *iface, LARGE_INTEGER dlibMove,
753 DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition)
754 {
755 ResProtocol *This = PROTOCOL_THIS(iface);
756 FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
757 return E_NOTIMPL;
758 }
759
760 static HRESULT WINAPI ResProtocol_LockRequest(IInternetProtocol *iface, DWORD dwOptions)
761 {
762 ResProtocol *This = PROTOCOL_THIS(iface);
763
764 TRACE("(%p)->(%d)\n", This, dwOptions);
765
766 /* test show that we don't have to do anything here */
767 return S_OK;
768 }
769
770 static HRESULT WINAPI ResProtocol_UnlockRequest(IInternetProtocol *iface)
771 {
772 ResProtocol *This = PROTOCOL_THIS(iface);
773
774 TRACE("(%p)\n", This);
775
776 /* test show that we don't have to do anything here */
777 return S_OK;
778 }
779
780 #undef PROTOCOL_THIS
781
782 static const IInternetProtocolVtbl ResProtocolVtbl = {
783 ResProtocol_QueryInterface,
784 ResProtocol_AddRef,
785 ResProtocol_Release,
786 ResProtocol_Start,
787 ResProtocol_Continue,
788 ResProtocol_Abort,
789 ResProtocol_Terminate,
790 ResProtocol_Suspend,
791 ResProtocol_Resume,
792 ResProtocol_Read,
793 ResProtocol_Seek,
794 ResProtocol_LockRequest,
795 ResProtocol_UnlockRequest
796 };
797
798 static HRESULT WINAPI ResProtocolFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter,
799 REFIID riid, void **ppv)
800 {
801 ResProtocol *ret;
802 HRESULT hres = S_OK;
803
804 TRACE("(%p)->(%p %s %p)\n", iface, pUnkOuter, debugstr_guid(riid), ppv);
805
806 ret = heap_alloc(sizeof(ResProtocol));
807 ret->lpInternetProtocolVtbl = &ResProtocolVtbl;
808 ret->ref = 0;
809 ret->data = NULL;
810 ret->data_len = 0;
811 ret->cur = 0;
812 ret->pUnkOuter = pUnkOuter;
813
814 if(pUnkOuter) {
815 ret->ref = 1;
816 if(IsEqualGUID(&IID_IUnknown, riid))
817 *ppv = PROTOCOL(ret);
818 else
819 hres = E_FAIL;
820 }else {
821 hres = IInternetProtocol_QueryInterface(PROTOCOL(ret), riid, ppv);
822 }
823
824 if(FAILED(hres))
825 heap_free(ret);
826
827 return hres;
828 }
829
830 static HRESULT WINAPI ResProtocolInfo_ParseUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
831 PARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult,
832 DWORD* pcchResult, DWORD dwReserved)
833 {
834 TRACE("%p)->(%s %d %x %p %d %p %d)\n", iface, debugstr_w(pwzUrl), ParseAction,
835 dwParseFlags, pwzResult, cchResult, pcchResult, dwReserved);
836
837 if(ParseAction == PARSE_SECURITY_URL) {
838 WCHAR file_part[MAX_PATH], full_path[MAX_PATH];
839 WCHAR *ptr;
840 DWORD size, len;
841
842 static const WCHAR wszFile[] = {'f','i','l','e',':','/','/'};
843 static const WCHAR wszRes[] = {'r','e','s',':','/','/'};
844
845 if(strlenW(pwzUrl) <= sizeof(wszRes)/sizeof(WCHAR) || memcmp(pwzUrl, wszRes, sizeof(wszRes)))
846 return E_INVALIDARG;
847
848 ptr = strchrW(pwzUrl + sizeof(wszRes)/sizeof(WCHAR), '/');
849 if(!ptr)
850 return E_INVALIDARG;
851
852 len = ptr - (pwzUrl + sizeof(wszRes)/sizeof(WCHAR));
853 if(len >= sizeof(file_part)/sizeof(WCHAR)) {
854 FIXME("Too long URL\n");
855 return MK_E_SYNTAX;
856 }
857
858 memcpy(file_part, pwzUrl + sizeof(wszRes)/sizeof(WCHAR), len*sizeof(WCHAR));
859 file_part[len] = 0;
860
861 len = SearchPathW(NULL, file_part, NULL, sizeof(full_path)/sizeof(WCHAR), full_path, NULL);
862 if(!len) {
863 WARN("Could not find file %s\n", debugstr_w(file_part));
864 return MK_E_SYNTAX;
865 }
866
867 size = sizeof(wszFile)/sizeof(WCHAR) + len + 1;
868 if(pcchResult)
869 *pcchResult = size;
870 if(size >= cchResult)
871 return S_FALSE;
872
873 memcpy(pwzResult, wszFile, sizeof(wszFile));
874 memcpy(pwzResult + sizeof(wszFile)/sizeof(WCHAR), full_path, (len+1)*sizeof(WCHAR));
875 return S_OK;
876 }
877
878 if(ParseAction == PARSE_DOMAIN) {
879 if(!pcchResult)
880 return E_POINTER;
881
882 if(pwzUrl)
883 *pcchResult = strlenW(pwzUrl)+1;
884 else
885 *pcchResult = 1;
886 return E_FAIL;
887 }
888
889 return INET_E_DEFAULT_ACTION;
890 }
891
892 static HRESULT WINAPI ResProtocolInfo_QueryInfo(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
893 QUERYOPTION QueryOption, DWORD dwQueryFlags, LPVOID pBuffer, DWORD cbBuffer, DWORD* pcbBuf,
894 DWORD dwReserved)
895 {
896 TRACE("%p)->(%s %08x %08x %p %d %p %d)\n", iface, debugstr_w(pwzUrl), QueryOption, dwQueryFlags, pBuffer,
897 cbBuffer, pcbBuf, dwReserved);
898
899 switch(QueryOption) {
900 case QUERY_USES_NETWORK:
901 if(!pBuffer || cbBuffer < sizeof(DWORD))
902 return E_FAIL;
903
904 *(DWORD*)pBuffer = 0;
905 if(pcbBuf)
906 *pcbBuf = sizeof(DWORD);
907 break;
908
909 case QUERY_IS_SECURE:
910 FIXME("not supporte QUERY_IS_SECURE\n");
911 return E_NOTIMPL;
912 case QUERY_IS_SAFE:
913 FIXME("not supporte QUERY_IS_SAFE\n");
914 return E_NOTIMPL;
915 default:
916 return INET_E_USE_DEFAULT_PROTOCOLHANDLER;
917 }
918
919 return S_OK;
920 }
921
922 static const IInternetProtocolInfoVtbl ResProtocolInfoVtbl = {
923 InternetProtocolInfo_QueryInterface,
924 InternetProtocolInfo_AddRef,
925 InternetProtocolInfo_Release,
926 ResProtocolInfo_ParseUrl,
927 InternetProtocolInfo_CombineUrl,
928 InternetProtocolInfo_CompareUrl,
929 ResProtocolInfo_QueryInfo
930 };
931
932 static const IClassFactoryVtbl ResProtocolFactoryVtbl = {
933 ClassFactory_QueryInterface,
934 ClassFactory_AddRef,
935 ClassFactory_Release,
936 ResProtocolFactory_CreateInstance,
937 ClassFactory_LockServer
938 };
939
940 static ProtocolFactory ResProtocolFactory = {
941 &ResProtocolInfoVtbl,
942 &ResProtocolFactoryVtbl
943 };
944
945 /********************************************************************
946 * JSProtocol implementation
947 */
948
949 static HRESULT WINAPI JSProtocolFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter,
950 REFIID riid, void **ppv)
951 {
952 FIXME("(%p)->(%p %s %p)\n", iface, pUnkOuter, debugstr_guid(riid), ppv);
953 return E_NOTIMPL;
954 }
955
956 static HRESULT WINAPI JSProtocolInfo_ParseUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
957 PARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult,
958 DWORD* pcchResult, DWORD dwReserved)
959 {
960 TRACE("%p)->(%s %d %x %p %d %p %d)\n", iface, debugstr_w(pwzUrl), ParseAction,
961 dwParseFlags, pwzResult, cchResult, pcchResult, dwReserved);
962
963 switch(ParseAction) {
964 case PARSE_SECURITY_URL:
965 FIXME("PARSE_SECURITY_URL\n");
966 return E_NOTIMPL;
967 case PARSE_DOMAIN:
968 FIXME("PARSE_DOMAIN\n");
969 return E_NOTIMPL;
970 default:
971 return INET_E_DEFAULT_ACTION;
972 }
973
974 return S_OK;
975 }
976
977 static HRESULT WINAPI JSProtocolInfo_QueryInfo(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
978 QUERYOPTION QueryOption, DWORD dwQueryFlags, LPVOID pBuffer, DWORD cbBuffer, DWORD* pcbBuf,
979 DWORD dwReserved)
980 {
981 TRACE("%p)->(%s %08x %08x %p %d %p %d)\n", iface, debugstr_w(pwzUrl), QueryOption, dwQueryFlags, pBuffer,
982 cbBuffer, pcbBuf, dwReserved);
983
984 switch(QueryOption) {
985 case QUERY_USES_NETWORK:
986 if(!pBuffer || cbBuffer < sizeof(DWORD))
987 return E_FAIL;
988
989 *(DWORD*)pBuffer = 0;
990 if(pcbBuf)
991 *pcbBuf = sizeof(DWORD);
992 break;
993
994 case QUERY_IS_SECURE:
995 FIXME("not supporte QUERY_IS_SECURE\n");
996 return E_NOTIMPL;
997
998 default:
999 return INET_E_USE_DEFAULT_PROTOCOLHANDLER;
1000 }
1001
1002 return S_OK;
1003 }
1004
1005 static const IInternetProtocolInfoVtbl JSProtocolInfoVtbl = {
1006 InternetProtocolInfo_QueryInterface,
1007 InternetProtocolInfo_AddRef,
1008 InternetProtocolInfo_Release,
1009 JSProtocolInfo_ParseUrl,
1010 InternetProtocolInfo_CombineUrl,
1011 InternetProtocolInfo_CompareUrl,
1012 JSProtocolInfo_QueryInfo
1013 };
1014
1015 static const IClassFactoryVtbl JSProtocolFactoryVtbl = {
1016 ClassFactory_QueryInterface,
1017 ClassFactory_AddRef,
1018 ClassFactory_Release,
1019 JSProtocolFactory_CreateInstance,
1020 ClassFactory_LockServer
1021 };
1022
1023 static ProtocolFactory JSProtocolFactory = {
1024 &JSProtocolInfoVtbl,
1025 &JSProtocolFactoryVtbl
1026 };
1027
1028 HRESULT ProtocolFactory_Create(REFCLSID rclsid, REFIID riid, void **ppv)
1029 {
1030 ProtocolFactory *cf = NULL;
1031
1032 if(IsEqualGUID(&CLSID_AboutProtocol, rclsid))
1033 cf = &AboutProtocolFactory;
1034 else if(IsEqualGUID(&CLSID_ResProtocol, rclsid))
1035 cf = &ResProtocolFactory;
1036 else if(IsEqualGUID(&CLSID_JSProtocol, rclsid))
1037 cf = &JSProtocolFactory;
1038
1039 if(!cf) {
1040 FIXME("not implemented protocol %s\n", debugstr_guid(rclsid));
1041 return CLASS_E_CLASSNOTAVAILABLE;
1042 }
1043
1044 return IUnknown_QueryInterface((IUnknown*)cf, riid, ppv);
1045 }