bb707498a184fc327a9bcc850d0bc0947bd286b0
[reactos.git] / reactos / dll / win32 / urlmon / urlmon_main.c
1 /*
2 * UrlMon
3 *
4 * Copyright (c) 2000 Patrik Stridvall
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 //#include <stdarg.h>
22
23 #include "urlmon_main.h"
24
25 //#include "winreg.h"
26
27 #define NO_SHLWAPI_REG
28 //#include "shlwapi.h"
29 #include <advpub.h>
30 #include <initguid.h>
31
32 #include <wine/debug.h>
33
34 #include "urlmon.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
37
38 DEFINE_GUID(CLSID_CUri, 0xDF2FCE13, 0x25EC, 0x45BB, 0x9D,0x4C, 0xCE,0xCD,0x47,0xC2,0x43,0x0C);
39
40 LONG URLMON_refCount = 0;
41 HINSTANCE urlmon_instance;
42
43 static HMODULE hCabinet = NULL;
44 static DWORD urlmon_tls = TLS_OUT_OF_INDEXES;
45
46 static void init_session(void);
47
48 static struct list tls_list = LIST_INIT(tls_list);
49
50 static CRITICAL_SECTION tls_cs;
51 static CRITICAL_SECTION_DEBUG tls_cs_dbg =
52 {
53 0, 0, &tls_cs,
54 { &tls_cs_dbg.ProcessLocksList, &tls_cs_dbg.ProcessLocksList },
55 0, 0, { (DWORD_PTR)(__FILE__ ": tls") }
56 };
57
58 static CRITICAL_SECTION tls_cs = { &tls_cs_dbg, -1, 0, 0, 0, 0 };
59
60 tls_data_t *get_tls_data(void)
61 {
62 tls_data_t *data;
63
64 if(urlmon_tls == TLS_OUT_OF_INDEXES) {
65 DWORD tls = TlsAlloc();
66 if(tls == TLS_OUT_OF_INDEXES)
67 return NULL;
68
69 tls = InterlockedCompareExchange((LONG*)&urlmon_tls, tls, TLS_OUT_OF_INDEXES);
70 if(tls != urlmon_tls)
71 TlsFree(tls);
72 }
73
74 data = TlsGetValue(urlmon_tls);
75 if(!data) {
76 data = heap_alloc_zero(sizeof(tls_data_t));
77 if(!data)
78 return NULL;
79
80 EnterCriticalSection(&tls_cs);
81 list_add_tail(&tls_list, &data->entry);
82 LeaveCriticalSection(&tls_cs);
83
84 TlsSetValue(urlmon_tls, data);
85 }
86
87 return data;
88 }
89
90 static void free_tls_list(void)
91 {
92 tls_data_t *data;
93
94 if(urlmon_tls == TLS_OUT_OF_INDEXES)
95 return;
96
97 while(!list_empty(&tls_list)) {
98 data = LIST_ENTRY(list_head(&tls_list), tls_data_t, entry);
99 list_remove(&data->entry);
100 heap_free(data);
101 }
102
103 TlsFree(urlmon_tls);
104 }
105
106 static void detach_thread(void)
107 {
108 tls_data_t *data;
109
110 if(urlmon_tls == TLS_OUT_OF_INDEXES)
111 return;
112
113 data = TlsGetValue(urlmon_tls);
114 if(!data)
115 return;
116
117 EnterCriticalSection(&tls_cs);
118 list_remove(&data->entry);
119 LeaveCriticalSection(&tls_cs);
120
121 if(data->notif_hwnd) {
122 WARN("notif_hwnd not destroyed\n");
123 DestroyWindow(data->notif_hwnd);
124 }
125
126 heap_free(data);
127 }
128
129 static void process_detach(void)
130 {
131 HINTERNET internet_session;
132
133 internet_session = get_internet_session(NULL);
134 if(internet_session)
135 InternetCloseHandle(internet_session);
136
137 if (hCabinet)
138 FreeLibrary(hCabinet);
139
140 free_session();
141 free_tls_list();
142 }
143
144 /***********************************************************************
145 * DllMain (URLMON.init)
146 */
147 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
148 {
149 TRACE("%p 0x%x %p\n", hinstDLL, fdwReason, fImpLoad);
150
151 URLMON_DllMain( hinstDLL, fdwReason, fImpLoad );
152
153 switch(fdwReason) {
154 case DLL_PROCESS_ATTACH:
155 urlmon_instance = hinstDLL;
156 init_session();
157 break;
158
159 case DLL_PROCESS_DETACH:
160 if (fImpLoad) break;
161 process_detach();
162 DeleteCriticalSection(&tls_cs);
163 break;
164
165 case DLL_THREAD_DETACH:
166 detach_thread();
167 break;
168 }
169 return TRUE;
170 }
171
172 const char *debugstr_bindstatus(ULONG status)
173 {
174 switch(status) {
175 #define X(x) case x: return #x
176 X(BINDSTATUS_FINDINGRESOURCE);
177 X(BINDSTATUS_CONNECTING);
178 X(BINDSTATUS_REDIRECTING);
179 X(BINDSTATUS_BEGINDOWNLOADDATA);
180 X(BINDSTATUS_DOWNLOADINGDATA);
181 X(BINDSTATUS_ENDDOWNLOADDATA);
182 X(BINDSTATUS_BEGINDOWNLOADCOMPONENTS);
183 X(BINDSTATUS_INSTALLINGCOMPONENTS);
184 X(BINDSTATUS_ENDDOWNLOADCOMPONENTS);
185 X(BINDSTATUS_USINGCACHEDCOPY);
186 X(BINDSTATUS_SENDINGREQUEST);
187 X(BINDSTATUS_CLASSIDAVAILABLE);
188 X(BINDSTATUS_MIMETYPEAVAILABLE);
189 X(BINDSTATUS_CACHEFILENAMEAVAILABLE);
190 X(BINDSTATUS_BEGINSYNCOPERATION);
191 X(BINDSTATUS_ENDSYNCOPERATION);
192 X(BINDSTATUS_BEGINUPLOADDATA);
193 X(BINDSTATUS_UPLOADINGDATA);
194 X(BINDSTATUS_ENDUPLOADINGDATA);
195 X(BINDSTATUS_PROTOCOLCLASSID);
196 X(BINDSTATUS_ENCODING);
197 X(BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE);
198 X(BINDSTATUS_CLASSINSTALLLOCATION);
199 X(BINDSTATUS_DECODING);
200 X(BINDSTATUS_LOADINGMIMEHANDLER);
201 X(BINDSTATUS_CONTENTDISPOSITIONATTACH);
202 X(BINDSTATUS_FILTERREPORTMIMETYPE);
203 X(BINDSTATUS_CLSIDCANINSTANTIATE);
204 X(BINDSTATUS_IUNKNOWNAVAILABLE);
205 X(BINDSTATUS_DIRECTBIND);
206 X(BINDSTATUS_RAWMIMETYPE);
207 X(BINDSTATUS_PROXYDETECTING);
208 X(BINDSTATUS_ACCEPTRANGES);
209 X(BINDSTATUS_COOKIE_SENT);
210 X(BINDSTATUS_COMPACT_POLICY_RECEIVED);
211 X(BINDSTATUS_COOKIE_SUPPRESSED);
212 X(BINDSTATUS_COOKIE_STATE_UNKNOWN);
213 X(BINDSTATUS_COOKIE_STATE_ACCEPT);
214 X(BINDSTATUS_COOKIE_STATE_REJECT);
215 X(BINDSTATUS_COOKIE_STATE_PROMPT);
216 X(BINDSTATUS_COOKIE_STATE_LEASH);
217 X(BINDSTATUS_COOKIE_STATE_DOWNGRADE);
218 X(BINDSTATUS_POLICY_HREF);
219 X(BINDSTATUS_P3P_HEADER);
220 X(BINDSTATUS_SESSION_COOKIE_RECEIVED);
221 X(BINDSTATUS_PERSISTENT_COOKIE_RECEIVED);
222 X(BINDSTATUS_SESSION_COOKIES_ALLOWED);
223 X(BINDSTATUS_CACHECONTROL);
224 X(BINDSTATUS_CONTENTDISPOSITIONFILENAME);
225 X(BINDSTATUS_MIMETEXTPLAINMISMATCH);
226 X(BINDSTATUS_PUBLISHERAVAILABLE);
227 X(BINDSTATUS_DISPLAYNAMEAVAILABLE);
228 #undef X
229 default:
230 return wine_dbg_sprintf("(invalid status %u)", status);
231 }
232 }
233
234 /***********************************************************************
235 * DllInstall (URLMON.@)
236 */
237 HRESULT WINAPI DllInstall(BOOL bInstall, LPCWSTR cmdline)
238 {
239 FIXME("(%s, %s): stub\n", bInstall?"TRUE":"FALSE",
240 debugstr_w(cmdline));
241
242 return S_OK;
243 }
244
245 /***********************************************************************
246 * DllCanUnloadNow (URLMON.@)
247 */
248 HRESULT WINAPI DllCanUnloadNow(void)
249 {
250 return URLMON_refCount != 0 ? S_FALSE : S_OK;
251 }
252
253
254
255 /******************************************************************************
256 * Urlmon ClassFactory
257 */
258 typedef struct {
259 IClassFactory IClassFactory_iface;
260
261 HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
262 } ClassFactory;
263
264 static inline ClassFactory *impl_from_IClassFactory(IClassFactory *iface)
265 {
266 return CONTAINING_RECORD(iface, ClassFactory, IClassFactory_iface);
267 }
268
269 static HRESULT WINAPI CF_QueryInterface(IClassFactory *iface, REFIID riid, LPVOID *ppv)
270 {
271 *ppv = NULL;
272
273 if(IsEqualGUID(riid, &IID_IUnknown)) {
274 TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv);
275 *ppv = iface;
276 }else if(IsEqualGUID(riid, &IID_IClassFactory)) {
277 TRACE("(%p)->(IID_IClassFactory %p)\n", iface, ppv);
278 *ppv = iface;
279 }
280
281 if(*ppv) {
282 IUnknown_AddRef((IUnknown*)*ppv);
283 return S_OK;
284 }
285
286 WARN("(%p)->(%s,%p),not found\n", iface, debugstr_guid(riid), ppv);
287 return E_NOINTERFACE;
288 }
289
290 static ULONG WINAPI CF_AddRef(IClassFactory *iface)
291 {
292 URLMON_LockModule();
293 return 2;
294 }
295
296 static ULONG WINAPI CF_Release(IClassFactory *iface)
297 {
298 URLMON_UnlockModule();
299 return 1;
300 }
301
302
303 static HRESULT WINAPI CF_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
304 REFIID riid, LPVOID *ppobj)
305 {
306 ClassFactory *This = impl_from_IClassFactory(iface);
307 HRESULT hres;
308 LPUNKNOWN punk;
309
310 TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
311
312 *ppobj = NULL;
313 if(SUCCEEDED(hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk))) {
314 hres = IUnknown_QueryInterface(punk, riid, ppobj);
315 IUnknown_Release(punk);
316 }
317 return hres;
318 }
319
320 static HRESULT WINAPI CF_LockServer(LPCLASSFACTORY iface,BOOL dolock)
321 {
322 TRACE("(%d)\n", dolock);
323
324 if (dolock)
325 URLMON_LockModule();
326 else
327 URLMON_UnlockModule();
328
329 return S_OK;
330 }
331
332 static const IClassFactoryVtbl ClassFactoryVtbl =
333 {
334 CF_QueryInterface,
335 CF_AddRef,
336 CF_Release,
337 CF_CreateInstance,
338 CF_LockServer
339 };
340
341 static ClassFactory FileProtocolCF =
342 { { &ClassFactoryVtbl }, FileProtocol_Construct};
343 static ClassFactory FtpProtocolCF =
344 { { &ClassFactoryVtbl }, FtpProtocol_Construct};
345 static ClassFactory GopherProtocolCF =
346 { { &ClassFactoryVtbl }, GopherProtocol_Construct};
347 static ClassFactory HttpProtocolCF =
348 { { &ClassFactoryVtbl }, HttpProtocol_Construct};
349 static ClassFactory HttpSProtocolCF =
350 { { &ClassFactoryVtbl }, HttpSProtocol_Construct};
351 static ClassFactory MkProtocolCF =
352 { { &ClassFactoryVtbl }, MkProtocol_Construct};
353 static ClassFactory SecurityManagerCF =
354 { { &ClassFactoryVtbl }, SecManagerImpl_Construct};
355 static ClassFactory ZoneManagerCF =
356 { { &ClassFactoryVtbl }, ZoneMgrImpl_Construct};
357 static ClassFactory StdURLMonikerCF =
358 { { &ClassFactoryVtbl }, StdURLMoniker_Construct};
359 static ClassFactory MimeFilterCF =
360 { { &ClassFactoryVtbl }, MimeFilter_Construct};
361 static ClassFactory CUriCF =
362 { { &ClassFactoryVtbl }, Uri_Construct};
363
364 struct object_creation_info
365 {
366 const CLSID *clsid;
367 IClassFactory *cf;
368 LPCWSTR protocol;
369 };
370
371 static const WCHAR wszFile[] = {'f','i','l','e',0};
372 static const WCHAR wszFtp[] = {'f','t','p',0};
373 static const WCHAR wszGopher[] = {'g','o','p','h','e','r',0};
374 static const WCHAR wszHttp[] = {'h','t','t','p',0};
375 static const WCHAR wszHttps[] = {'h','t','t','p','s',0};
376 static const WCHAR wszMk[] = {'m','k',0};
377
378 static const struct object_creation_info object_creation[] =
379 {
380 { &CLSID_FileProtocol, &FileProtocolCF.IClassFactory_iface, wszFile },
381 { &CLSID_FtpProtocol, &FtpProtocolCF.IClassFactory_iface, wszFtp },
382 { &CLSID_GopherProtocol, &GopherProtocolCF.IClassFactory_iface, wszGopher },
383 { &CLSID_HttpProtocol, &HttpProtocolCF.IClassFactory_iface, wszHttp },
384 { &CLSID_HttpSProtocol, &HttpSProtocolCF.IClassFactory_iface, wszHttps },
385 { &CLSID_MkProtocol, &MkProtocolCF.IClassFactory_iface, wszMk },
386 { &CLSID_InternetSecurityManager, &SecurityManagerCF.IClassFactory_iface, NULL },
387 { &CLSID_InternetZoneManager, &ZoneManagerCF.IClassFactory_iface, NULL },
388 { &CLSID_StdURLMoniker, &StdURLMonikerCF.IClassFactory_iface, NULL },
389 { &CLSID_DeCompMimeFilter, &MimeFilterCF.IClassFactory_iface, NULL },
390 { &CLSID_CUri, &CUriCF.IClassFactory_iface, NULL }
391 };
392
393 static void init_session(void)
394 {
395 unsigned int i;
396
397 for(i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++) {
398 if(object_creation[i].protocol)
399 register_namespace(object_creation[i].cf, object_creation[i].clsid,
400 object_creation[i].protocol, TRUE);
401 }
402 }
403
404 /*******************************************************************************
405 * DllGetClassObject [URLMON.@]
406 * Retrieves class object from a DLL object
407 *
408 * NOTES
409 * Docs say returns STDAPI
410 *
411 * PARAMS
412 * rclsid [I] CLSID for the class object
413 * riid [I] Reference to identifier of interface for class object
414 * ppv [O] Address of variable to receive interface pointer for riid
415 *
416 * RETURNS
417 * Success: S_OK
418 * Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG,
419 * E_UNEXPECTED
420 */
421
422 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
423 {
424 unsigned int i;
425 HRESULT hr;
426
427 TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
428
429 for (i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++)
430 {
431 if (IsEqualGUID(object_creation[i].clsid, rclsid))
432 return IClassFactory_QueryInterface(object_creation[i].cf, riid, ppv);
433 }
434
435 hr = URLMON_DllGetClassObject(rclsid, riid, ppv);
436 if(SUCCEEDED(hr))
437 return hr;
438
439 FIXME("%s: no class found.\n", debugstr_guid(rclsid));
440 return CLASS_E_CLASSNOTAVAILABLE;
441 }
442
443 static HRESULT register_inf(BOOL doregister)
444 {
445 HRESULT (WINAPI *pRegInstall)(HMODULE hm, LPCSTR pszSection, const STRTABLEA* pstTable);
446 HMODULE hAdvpack;
447
448 static const WCHAR wszAdvpack[] = {'a','d','v','p','a','c','k','.','d','l','l',0};
449
450 hAdvpack = LoadLibraryW(wszAdvpack);
451 pRegInstall = (void *)GetProcAddress(hAdvpack, "RegInstall");
452
453 return pRegInstall(hProxyDll, doregister ? "RegisterDll" : "UnregisterDll", NULL);
454 }
455
456 /***********************************************************************
457 * DllRegisterServer (URLMON.@)
458 */
459 HRESULT WINAPI DllRegisterServer(void)
460 {
461 HRESULT hr;
462
463 TRACE("\n");
464
465 hr = URLMON_DllRegisterServer();
466 return SUCCEEDED(hr) ? register_inf(TRUE) : hr;
467 }
468
469 /***********************************************************************
470 * DllUnregisterServer (URLMON.@)
471 */
472 HRESULT WINAPI DllUnregisterServer(void)
473 {
474 HRESULT hr;
475
476 TRACE("\n");
477
478 hr = URLMON_DllUnregisterServer();
479 return SUCCEEDED(hr) ? register_inf(FALSE) : hr;
480 }
481
482 /***********************************************************************
483 * DllRegisterServerEx (URLMON.@)
484 */
485 HRESULT WINAPI DllRegisterServerEx(void)
486 {
487 FIXME("(void): stub\n");
488
489 return E_FAIL;
490 }
491
492 /**************************************************************************
493 * IsValidURL (URLMON.@)
494 *
495 * Determines if a specified string is a valid URL.
496 *
497 * PARAMS
498 * pBC [I] ignored, should be NULL.
499 * szURL [I] string that represents the URL in question.
500 * dwReserved [I] reserved and must be zero.
501 *
502 * RETURNS
503 * Success: S_OK.
504 * Failure: S_FALSE.
505 * returns E_INVALIDARG if one or more of the args is invalid.
506 *
507 * TODO:
508 * test functionality against windows to see what a valid URL is.
509 */
510 HRESULT WINAPI IsValidURL(LPBC pBC, LPCWSTR szURL, DWORD dwReserved)
511 {
512 FIXME("(%p, %s, %d): stub\n", pBC, debugstr_w(szURL), dwReserved);
513
514 if (dwReserved || !szURL)
515 return E_INVALIDARG;
516
517 return S_OK;
518 }
519
520 /**************************************************************************
521 * FaultInIEFeature (URLMON.@)
522 *
523 * Undocumented. Appears to be used by native shdocvw.dll.
524 */
525 HRESULT WINAPI FaultInIEFeature( HWND hwnd, uCLSSPEC * pClassSpec,
526 QUERYCONTEXT *pQuery, DWORD flags )
527 {
528 FIXME("%p %p %p %08x\n", hwnd, pClassSpec, pQuery, flags);
529 return E_NOTIMPL;
530 }
531
532 /**************************************************************************
533 * CoGetClassObjectFromURL (URLMON.@)
534 */
535 HRESULT WINAPI CoGetClassObjectFromURL( REFCLSID rclsid, LPCWSTR szCodeURL, DWORD dwFileVersionMS,
536 DWORD dwFileVersionLS, LPCWSTR szContentType,
537 LPBINDCTX pBindCtx, DWORD dwClsContext, LPVOID pvReserved,
538 REFIID riid, LPVOID *ppv )
539 {
540 FIXME("(%s %s %d %d %s %p %d %p %s %p) Stub!\n", debugstr_guid(rclsid), debugstr_w(szCodeURL),
541 dwFileVersionMS, dwFileVersionLS, debugstr_w(szContentType), pBindCtx, dwClsContext, pvReserved,
542 debugstr_guid(riid), ppv);
543 return E_NOINTERFACE;
544 }
545
546 /***********************************************************************
547 * ReleaseBindInfo (URLMON.@)
548 *
549 * Release the resources used by the specified BINDINFO structure.
550 *
551 * PARAMS
552 * pbindinfo [I] BINDINFO to release.
553 *
554 * RETURNS
555 * Nothing.
556 */
557 void WINAPI ReleaseBindInfo(BINDINFO* pbindinfo)
558 {
559 DWORD size;
560
561 TRACE("(%p)\n", pbindinfo);
562
563 if(!pbindinfo || !(size = pbindinfo->cbSize))
564 return;
565
566 CoTaskMemFree(pbindinfo->szExtraInfo);
567 ReleaseStgMedium(&pbindinfo->stgmedData);
568
569 if(offsetof(BINDINFO, szExtraInfo) < size)
570 CoTaskMemFree(pbindinfo->szCustomVerb);
571
572 if(pbindinfo->pUnk && offsetof(BINDINFO, pUnk) < size)
573 IUnknown_Release(pbindinfo->pUnk);
574
575 memset(pbindinfo, 0, size);
576 pbindinfo->cbSize = size;
577 }
578
579 /***********************************************************************
580 * CopyStgMedium (URLMON.@)
581 */
582 HRESULT WINAPI CopyStgMedium(const STGMEDIUM *src, STGMEDIUM *dst)
583 {
584 TRACE("(%p %p)\n", src, dst);
585
586 if(!src || !dst)
587 return E_POINTER;
588
589 *dst = *src;
590
591 switch(dst->tymed) {
592 case TYMED_NULL:
593 break;
594 case TYMED_FILE:
595 if(src->u.lpszFileName && !src->pUnkForRelease) {
596 DWORD size = (strlenW(src->u.lpszFileName)+1)*sizeof(WCHAR);
597 dst->u.lpszFileName = CoTaskMemAlloc(size);
598 if(!dst->u.lpszFileName)
599 return E_OUTOFMEMORY;
600 memcpy(dst->u.lpszFileName, src->u.lpszFileName, size);
601 }
602 break;
603 case TYMED_ISTREAM:
604 if(dst->u.pstm)
605 IStream_AddRef(dst->u.pstm);
606 break;
607 case TYMED_ISTORAGE:
608 if(dst->u.pstg)
609 IStorage_AddRef(dst->u.pstg);
610 break;
611 case TYMED_HGLOBAL:
612 if(dst->u.hGlobal) {
613 SIZE_T size = GlobalSize(src->u.hGlobal);
614 char *src_ptr, *dst_ptr;
615
616 dst->u.hGlobal = GlobalAlloc(GMEM_FIXED, size);
617 if(!dst->u.hGlobal)
618 return E_OUTOFMEMORY;
619 dst_ptr = GlobalLock(dst->u.hGlobal);
620 src_ptr = GlobalLock(src->u.hGlobal);
621 memcpy(dst_ptr, src_ptr, size);
622 GlobalUnlock(src_ptr);
623 GlobalUnlock(dst_ptr);
624 }
625 break;
626 default:
627 FIXME("Unimplemented tymed %d\n", src->tymed);
628 }
629
630 if(dst->pUnkForRelease)
631 IUnknown_AddRef(dst->pUnkForRelease);
632
633 return S_OK;
634 }
635
636 /***********************************************************************
637 * CopyBindInfo (URLMON.@)
638 */
639 HRESULT WINAPI CopyBindInfo(const BINDINFO *pcbiSrc, BINDINFO *pcbiDest)
640 {
641 DWORD size;
642 HRESULT hres;
643
644 TRACE("(%p %p)\n", pcbiSrc, pcbiDest);
645
646 if(!pcbiSrc || !pcbiDest)
647 return E_POINTER;
648 if(!pcbiSrc->cbSize || !pcbiDest->cbSize)
649 return E_INVALIDARG;
650
651 size = pcbiDest->cbSize;
652 if(size > pcbiSrc->cbSize) {
653 memcpy(pcbiDest, pcbiSrc, pcbiSrc->cbSize);
654 memset((char*)pcbiDest+pcbiSrc->cbSize, 0, size-pcbiSrc->cbSize);
655 } else {
656 memcpy(pcbiDest, pcbiSrc, size);
657 }
658 pcbiDest->cbSize = size;
659
660 size = FIELD_OFFSET(BINDINFO, szExtraInfo)+sizeof(void*);
661 if(pcbiSrc->cbSize>=size && pcbiDest->cbSize>=size && pcbiSrc->szExtraInfo) {
662 size = (strlenW(pcbiSrc->szExtraInfo)+1)*sizeof(WCHAR);
663 pcbiDest->szExtraInfo = CoTaskMemAlloc(size);
664 if(!pcbiDest->szExtraInfo)
665 return E_OUTOFMEMORY;
666 memcpy(pcbiDest->szExtraInfo, pcbiSrc->szExtraInfo, size);
667 }
668
669 size = FIELD_OFFSET(BINDINFO, stgmedData)+sizeof(STGMEDIUM);
670 if(pcbiSrc->cbSize>=size && pcbiDest->cbSize>=size) {
671 hres = CopyStgMedium(&pcbiSrc->stgmedData, &pcbiDest->stgmedData);
672 if(FAILED(hres)) {
673 CoTaskMemFree(pcbiDest->szExtraInfo);
674 return hres;
675 }
676 }
677
678 size = FIELD_OFFSET(BINDINFO, szCustomVerb)+sizeof(void*);
679 if(pcbiSrc->cbSize>=size && pcbiDest->cbSize>=size && pcbiSrc->szCustomVerb) {
680 size = (strlenW(pcbiSrc->szCustomVerb)+1)*sizeof(WCHAR);
681 pcbiDest->szCustomVerb = CoTaskMemAlloc(size);
682 if(!pcbiDest->szCustomVerb) {
683 CoTaskMemFree(pcbiDest->szExtraInfo);
684 ReleaseStgMedium(&pcbiDest->stgmedData);
685 return E_OUTOFMEMORY;
686 }
687 memcpy(pcbiDest->szCustomVerb, pcbiSrc->szCustomVerb, size);
688 }
689
690 size = FIELD_OFFSET(BINDINFO, securityAttributes)+sizeof(SECURITY_ATTRIBUTES);
691 if(pcbiDest->cbSize >= size)
692 memset(&pcbiDest->securityAttributes, 0, sizeof(SECURITY_ATTRIBUTES));
693
694 if(pcbiSrc->pUnk)
695 IUnknown_AddRef(pcbiDest->pUnk);
696
697 return S_OK;
698 }
699
700 /***********************************************************************
701 * GetClassFileOrMime (URLMON.@)
702 *
703 * Determines the class ID from the bind context, file name or MIME type.
704 */
705 HRESULT WINAPI GetClassFileOrMime(LPBC pBC, LPCWSTR pszFilename,
706 LPVOID pBuffer, DWORD cbBuffer, LPCWSTR pszMimeType, DWORD dwReserved,
707 CLSID *pclsid)
708 {
709 FIXME("(%p, %s, %p, %d, %s, 0x%08x, %p): stub\n", pBC, debugstr_w(pszFilename), pBuffer,
710 cbBuffer, debugstr_w(pszMimeType), dwReserved, pclsid);
711 return E_NOTIMPL;
712 }
713
714 /***********************************************************************
715 * Extract (URLMON.@)
716 */
717 HRESULT WINAPI Extract(void *dest, LPCSTR szCabName)
718 {
719 HRESULT (WINAPI *pExtract)(void *, LPCSTR);
720
721 if (!hCabinet)
722 hCabinet = LoadLibraryA("cabinet.dll");
723
724 if (!hCabinet) return HRESULT_FROM_WIN32(GetLastError());
725 pExtract = (void *)GetProcAddress(hCabinet, "Extract");
726 if (!pExtract) return HRESULT_FROM_WIN32(GetLastError());
727
728 return pExtract(dest, szCabName);
729 }
730
731 /***********************************************************************
732 * IsLoggingEnabledA (URLMON.@)
733 */
734 BOOL WINAPI IsLoggingEnabledA(LPCSTR url)
735 {
736 FIXME("(%s)\n", debugstr_a(url));
737 return FALSE;
738 }
739
740 /***********************************************************************
741 * IsLoggingEnabledW (URLMON.@)
742 */
743 BOOL WINAPI IsLoggingEnabledW(LPCWSTR url)
744 {
745 FIXME("(%s)\n", debugstr_w(url));
746 return FALSE;
747 }
748
749 /***********************************************************************
750 * IsProtectedModeURL (URLMON.111)
751 * Undocumented, added in IE7
752 */
753 BOOL WINAPI IsProtectedModeURL(const WCHAR *url)
754 {
755 FIXME("stub: %s\n", debugstr_w(url));
756 return TRUE;
757 }
758
759 /***********************************************************************
760 * LogSqmBits (URLMON.410)
761 * Undocumented, added in IE8
762 */
763 int WINAPI LogSqmBits(DWORD unk1, DWORD unk2)
764 {
765 FIXME("stub: %d %d\n", unk1, unk2);
766 return 0;
767 }
768
769 /***********************************************************************
770 * LogSqmUXCommandOffsetInternal (URLMON.423)
771 * Undocumented, added in IE8
772 */
773 void WINAPI LogSqmUXCommandOffsetInternal(DWORD unk1, DWORD unk2, DWORD unk3, DWORD unk4)
774 {
775 FIXME("stub: %d %d %d %d\n", unk1, unk2, unk3, unk4);
776 }
777
778 /***********************************************************************
779 * MapUriToBrowserEmulationState (URLMON.444)
780 * Undocumented, added in IE8
781 */
782 int WINAPI MapUriToBrowserEmulationState(DWORD unk1, DWORD unk2, DWORD unk3)
783 {
784 FIXME("stub: %d %d %d\n", unk1, unk2, unk3);
785 return 0;
786 }
787
788 /***********************************************************************
789 * MapBrowserEmulationModeToUserAgent (URLMON.445)
790 * Undocumented, added in IE8
791 */
792 int WINAPI MapBrowserEmulationModeToUserAgent(DWORD unk1, DWORD unk2)
793 {
794 FIXME("stub: %d %d\n", unk1, unk2);
795 return 0;
796 }
797
798 /***********************************************************************
799 * FlushUrlmonZonesCache (URLMON.455)
800 * Undocumented, added in IE8
801 */
802 void WINAPI FlushUrlmonZonesCache(void)
803 {
804 FIXME("stub\n");
805 }
806
807 /***********************************************************************
808 * RegisterMediaTypes
809 * Added in IE3, registers known MIME-type strings.
810 */
811 HRESULT WINAPI RegisterMediaTypes(UINT types, LPCSTR *szTypes, CLIPFORMAT *cfTypes)
812 {
813 FIXME("stub: %u %p %p\n", types, szTypes, cfTypes);
814 return E_INVALIDARG;
815 }