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