[SHDOCVW] Sync with Wine Staging 4.18. CORE-16441
[reactos.git] / dll / win32 / shdocvw / shdocvw_main.c
1 /*
2 * SHDOCVW - Internet Explorer Web Control
3 *
4 * Copyright 2001 John R. Sheets (for CodeWeavers)
5 * Copyright 2004 Mike McCormack (for CodeWeavers)
6 * Copyright 2008 Detlef Riekenberg
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 */
22
23 #include <stdarg.h>
24 #include <stdio.h>
25
26 #include "wine/debug.h"
27
28 #include "shdocvw.h"
29
30 #include "winreg.h"
31 #ifdef __REACTOS__
32 #include "winnls.h"
33 #endif
34 #include "shlwapi.h"
35 #include "wininet.h"
36 #include "isguids.h"
37
38 #include "initguid.h"
39
40 WINE_DEFAULT_DEBUG_CHANNEL(shdocvw);
41
42 LONG SHDOCVW_refCount = 0;
43
44 static HMODULE SHDOCVW_hshell32 = 0;
45 static HINSTANCE ieframe_instance;
46
47 static HINSTANCE get_ieframe_instance(void)
48 {
49 static const WCHAR ieframe_dllW[] = {'i','e','f','r','a','m','e','.','d','l','l',0};
50
51 if(!ieframe_instance)
52 ieframe_instance = LoadLibraryW(ieframe_dllW);
53
54 return ieframe_instance;
55 }
56
57 static HRESULT get_ieframe_object(REFCLSID rclsid, REFIID riid, void **ppv)
58 {
59 HINSTANCE ieframe_instance;
60
61 static HRESULT (WINAPI *ieframe_DllGetClassObject)(REFCLSID,REFIID,void**);
62
63 if(!ieframe_DllGetClassObject) {
64 ieframe_instance = get_ieframe_instance();
65 if(!ieframe_instance)
66 return CLASS_E_CLASSNOTAVAILABLE;
67
68 ieframe_DllGetClassObject = (void*)GetProcAddress(ieframe_instance, "DllGetClassObject");
69 if(!ieframe_DllGetClassObject)
70 return CLASS_E_CLASSNOTAVAILABLE;
71 }
72
73 return ieframe_DllGetClassObject(rclsid, riid, ppv);
74 }
75
76 /*************************************************************************
77 * DllGetClassObject (SHDOCVW.@)
78 */
79 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv)
80 {
81 TRACE("(%s %s %p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
82
83 if(IsEqualGUID(&CLSID_WebBrowser, rclsid)
84 || IsEqualGUID(&CLSID_WebBrowser_V1, rclsid)
85 || IsEqualGUID(&CLSID_InternetShortcut, rclsid)
86 || IsEqualGUID(&CLSID_CUrlHistory, rclsid)
87 || IsEqualGUID(&CLSID_TaskbarList, rclsid))
88 return get_ieframe_object(rclsid, riid, ppv);
89
90 /* As a last resort, figure if the CLSID belongs to a 'Shell Instance Object' */
91 return SHDOCVW_GetShellInstanceObjectClassObject(rclsid, riid, ppv);
92 }
93
94 /***********************************************************************
95 * DllRegisterServer (shdocvw.@)
96 */
97 HRESULT WINAPI DllRegisterServer(void)
98 {
99 TRACE("\n");
100 return S_OK;
101 }
102
103 /***********************************************************************
104 * DllUnregisterServer (shdocvw.@)
105 */
106 HRESULT WINAPI DllUnregisterServer(void)
107 {
108 TRACE("\n");
109 return S_OK;
110 }
111
112 /******************************************************************
113 * IEWinMain (SHDOCVW.101)
114 *
115 * Only returns on error.
116 */
117 DWORD WINAPI IEWinMain(LPSTR szCommandLine, int nShowWindow)
118 {
119 DWORD (WINAPI *pIEWinMain)(const WCHAR*,int);
120 WCHAR *cmdline;
121 DWORD ret, len;
122
123 TRACE("%s %d\n", debugstr_a(szCommandLine), nShowWindow);
124
125 pIEWinMain = (void*)GetProcAddress(get_ieframe_instance(), MAKEINTRESOURCEA(101));
126 if(!pIEWinMain)
127 ExitProcess(1);
128
129 len = MultiByteToWideChar(CP_ACP, 0, szCommandLine, -1, NULL, 0);
130 cmdline = heap_alloc(len*sizeof(WCHAR));
131 if(!cmdline)
132 ExitProcess(1);
133 MultiByteToWideChar(CP_ACP, 0, szCommandLine, -1, cmdline, len);
134
135 ret = pIEWinMain(cmdline, nShowWindow);
136
137 heap_free(cmdline);
138 return ret;
139 }
140
141 /*************************************************************************
142 * SHDOCVW DllMain
143 */
144 BOOL WINAPI DllMain(HINSTANCE hinst, DWORD fdwReason, LPVOID fImpLoad)
145 {
146 TRACE("%p 0x%x %p\n", hinst, fdwReason, fImpLoad);
147 switch (fdwReason)
148 {
149 case DLL_PROCESS_ATTACH:
150 DisableThreadLibraryCalls(hinst);
151 break;
152 case DLL_PROCESS_DETACH:
153 if (fImpLoad) break;
154 if (SHDOCVW_hshell32) FreeLibrary(SHDOCVW_hshell32);
155 if (ieframe_instance) FreeLibrary(ieframe_instance);
156 break;
157 }
158 return TRUE;
159 }
160
161 /*************************************************************************
162 * DllCanUnloadNow (SHDOCVW.@)
163 */
164 HRESULT WINAPI DllCanUnloadNow(void)
165 {
166 return SHDOCVW_refCount ? S_FALSE : S_OK;
167 }
168
169 /***********************************************************************
170 * DllGetVersion (SHDOCVW.@)
171 */
172 HRESULT WINAPI DllGetVersion(DLLVERSIONINFO *info)
173 {
174 if (info->cbSize != sizeof(DLLVERSIONINFO)) FIXME("support DLLVERSIONINFO2\n");
175
176 /* this is what IE6 on Windows 98 reports */
177 info->dwMajorVersion = 6;
178 info->dwMinorVersion = 0;
179 info->dwBuildNumber = 2600;
180 info->dwPlatformID = DLLVER_PLATFORM_WINDOWS;
181
182 return NOERROR;
183 }
184
185 /*************************************************************************
186 * DllInstall (SHDOCVW.@)
187 */
188 HRESULT WINAPI DllInstall(BOOL bInstall, LPCWSTR cmdline)
189 {
190 FIXME("(%s, %s): stub!\n", bInstall ? "TRUE":"FALSE", debugstr_w(cmdline));
191
192 return S_OK;
193 }
194
195 /*************************************************************************
196 * SHDOCVW_LoadShell32
197 *
198 * makes sure the handle to shell32 is valid
199 */
200 static BOOL SHDOCVW_LoadShell32(void)
201 {
202 if (SHDOCVW_hshell32)
203 return TRUE;
204 return ((SHDOCVW_hshell32 = LoadLibraryA("shell32.dll")) != NULL);
205 }
206
207 /***********************************************************************
208 * @ (SHDOCVW.110)
209 *
210 * Called by Win98 explorer.exe main binary, definitely has 0
211 * parameters.
212 */
213 DWORD WINAPI WinList_Init(void)
214 {
215 FIXME("(), stub!\n");
216 return 0x0deadfeed;
217 }
218
219 /***********************************************************************
220 * @ (SHDOCVW.118)
221 *
222 * Called by Win98 explorer.exe main binary, definitely has only one
223 * parameter.
224 */
225 static BOOL (WINAPI *pShellDDEInit)(BOOL start) = NULL;
226
227 BOOL WINAPI ShellDDEInit(BOOL start)
228 {
229 TRACE("(%d)\n", start);
230
231 if (!pShellDDEInit)
232 {
233 if (!SHDOCVW_LoadShell32())
234 return FALSE;
235 pShellDDEInit = (void *)GetProcAddress(SHDOCVW_hshell32, (LPCSTR)188);
236 }
237
238 if (pShellDDEInit)
239 return pShellDDEInit(start);
240 else
241 return FALSE;
242 }
243
244 /***********************************************************************
245 * @ (SHDOCVW.125)
246 *
247 * Called by Win98 explorer.exe main binary, definitely has 0
248 * parameters.
249 */
250 DWORD WINAPI RunInstallUninstallStubs(void)
251 {
252 FIXME("(), stub!\n");
253 return 0x0deadbee;
254 }
255
256 /***********************************************************************
257 * @ (SHDOCVW.130)
258 *
259 * Called by Emerge Desktop (alternative Windows Shell).
260 */
261 DWORD WINAPI RunInstallUninstallStubs2(int arg)
262 {
263 FIXME("(%d), stub!\n", arg);
264 return 0x0deadbee;
265 }
266
267 /***********************************************************************
268 * SetQueryNetSessionCount (SHDOCVW.@)
269 */
270 DWORD WINAPI SetQueryNetSessionCount(DWORD arg)
271 {
272 FIXME("(%u), stub!\n", arg);
273 return 0;
274 }
275
276 /**********************************************************************
277 * Some forwards (by ordinal) to SHLWAPI
278 */
279
280 static void* fetch_shlwapi_ordinal(UINT_PTR ord)
281 {
282 static const WCHAR shlwapiW[] = {'s','h','l','w','a','p','i','.','d','l','l','\0'};
283 static HANDLE h;
284
285 if (!h && !(h = GetModuleHandleW(shlwapiW))) return NULL;
286 return (void*)GetProcAddress(h, (const char*)ord);
287 }
288
289 /******************************************************************
290 * WhichPlatformFORWARD (SHDOCVW.@)
291 */
292 DWORD WINAPI WhichPlatformFORWARD(void)
293 {
294 static DWORD (WINAPI *p)(void);
295
296 if (p || (p = fetch_shlwapi_ordinal(276))) return p();
297 return 1; /* not integrated, see shlwapi.WhichPlatform */
298 }
299
300 /******************************************************************
301 * StopWatchModeFORWARD (SHDOCVW.@)
302 */
303 void WINAPI StopWatchModeFORWARD(void)
304 {
305 static void (WINAPI *p)(void);
306
307 if (p || (p = fetch_shlwapi_ordinal(241))) p();
308 }
309
310 /******************************************************************
311 * StopWatchFlushFORWARD (SHDOCVW.@)
312 */
313 void WINAPI StopWatchFlushFORWARD(void)
314 {
315 static void (WINAPI *p)(void);
316
317 if (p || (p = fetch_shlwapi_ordinal(242))) p();
318 }
319
320 /******************************************************************
321 * StopWatchAFORWARD (SHDOCVW.@)
322 */
323 DWORD WINAPI StopWatchAFORWARD(DWORD dwClass, LPCSTR lpszStr, DWORD dwUnknown,
324 DWORD dwMode, DWORD dwTimeStamp)
325 {
326 static DWORD (WINAPI *p)(DWORD, LPCSTR, DWORD, DWORD, DWORD);
327
328 if (p || (p = fetch_shlwapi_ordinal(243)))
329 return p(dwClass, lpszStr, dwUnknown, dwMode, dwTimeStamp);
330 return ERROR_CALL_NOT_IMPLEMENTED;
331 }
332
333 /******************************************************************
334 * StopWatchWFORWARD (SHDOCVW.@)
335 */
336 DWORD WINAPI StopWatchWFORWARD(DWORD dwClass, LPCWSTR lpszStr, DWORD dwUnknown,
337 DWORD dwMode, DWORD dwTimeStamp)
338 {
339 static DWORD (WINAPI *p)(DWORD, LPCWSTR, DWORD, DWORD, DWORD);
340
341 if (p || (p = fetch_shlwapi_ordinal(244)))
342 return p(dwClass, lpszStr, dwUnknown, dwMode, dwTimeStamp);
343 return ERROR_CALL_NOT_IMPLEMENTED;
344 }
345
346 /******************************************************************
347 * URLSubRegQueryA (SHDOCVW.151)
348 */
349 HRESULT WINAPI URLSubRegQueryA(LPCSTR regpath, LPCSTR name, DWORD type,
350 LPSTR out, DWORD outlen, DWORD unknown)
351 {
352 CHAR buffer[INTERNET_MAX_URL_LENGTH];
353 DWORD len;
354 LONG res;
355
356 TRACE("(%s, %s, %d, %p, %d, %d)\n", debugstr_a(regpath), debugstr_a(name),
357 type, out, outlen, unknown);
358
359 if (!out) return S_OK;
360
361 len = sizeof(buffer);
362 res = SHRegGetUSValueA(regpath, name, NULL, buffer, &len, FALSE, NULL, 0);
363 if (!res) {
364 lstrcpynA(out, buffer, outlen);
365 return S_OK;
366 }
367
368 return E_FAIL;
369 }
370
371 /******************************************************************
372 * ParseURLFromOutsideSourceW (SHDOCVW.170)
373 */
374 DWORD WINAPI ParseURLFromOutsideSourceW(LPCWSTR url, LPWSTR out, LPDWORD plen, LPDWORD unknown)
375 {
376 WCHAR buffer_in[INTERNET_MAX_URL_LENGTH];
377 WCHAR buffer_out[INTERNET_MAX_URL_LENGTH];
378 LPCWSTR ptr = url;
379 HRESULT hr;
380 DWORD needed;
381 DWORD len;
382 DWORD res;
383
384 TRACE("(%s, %p, %p, %p) len: %d, unknown: 0x%x\n", debugstr_w(url), out, plen, unknown,
385 plen ? *plen : 0, unknown ? *unknown : 0);
386
387 if (!PathIsURLW(ptr)) {
388 len = ARRAY_SIZE(buffer_in);
389 buffer_in[0] = 0;
390 hr = UrlApplySchemeW(ptr, buffer_in, &len, URL_APPLY_GUESSSCHEME | URL_APPLY_DEFAULT);
391 TRACE("got 0x%x with %s\n", hr, debugstr_w(buffer_in));
392 if (hr == S_OK) {
393 /* we parsed the url to buffer_in */
394 ptr = buffer_in;
395 }
396 else
397 {
398 FIXME("call search hook for %s\n", debugstr_w(ptr));
399 }
400 }
401
402 len = ARRAY_SIZE(buffer_out);
403 buffer_out[0] = '\0';
404 hr = UrlCanonicalizeW(ptr, buffer_out, &len, URL_ESCAPE_SPACES_ONLY);
405 needed = lstrlenW(buffer_out)+1;
406 TRACE("got 0x%x with %s (need %d)\n", hr, debugstr_w(buffer_out), needed);
407
408 res = 0;
409 if (*plen >= needed) {
410 if (out != NULL) {
411 lstrcpyW(out, buffer_out);
412 /* On success, 1 is returned for unicode version */
413 res = 1;
414 }
415 needed--;
416 }
417
418 *plen = needed;
419
420 TRACE("=> %d\n", res);
421 return res;
422 }
423
424 /******************************************************************
425 * ParseURLFromOutsideSourceA (SHDOCVW.169)
426 *
427 * See ParseURLFromOutsideSourceW
428 */
429 DWORD WINAPI ParseURLFromOutsideSourceA(LPCSTR url, LPSTR out, LPDWORD plen, LPDWORD unknown)
430 {
431 WCHAR buffer[INTERNET_MAX_URL_LENGTH];
432 LPWSTR urlW = NULL;
433 DWORD needed;
434 DWORD res;
435 DWORD len;
436
437 TRACE("(%s, %p, %p, %p) len: %d, unknown: 0x%x\n", debugstr_a(url), out, plen, unknown,
438 plen ? *plen : 0, unknown ? *unknown : 0);
439
440 if (url) {
441 len = MultiByteToWideChar(CP_ACP, 0, url, -1, NULL, 0);
442 urlW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
443 MultiByteToWideChar(CP_ACP, 0, url, -1, urlW, len);
444 }
445
446 len = ARRAY_SIZE(buffer);
447 ParseURLFromOutsideSourceW(urlW, buffer, &len, unknown);
448 HeapFree(GetProcessHeap(), 0, urlW);
449
450 needed = WideCharToMultiByte(CP_ACP, 0, buffer, -1, NULL, 0, NULL, NULL);
451
452 res = 0;
453 if (*plen >= needed) {
454 if (out != NULL) {
455 WideCharToMultiByte(CP_ACP, 0, buffer, -1, out, *plen, NULL, NULL);
456 /* On success, string size including terminating 0 is returned for ansi version */
457 res = needed;
458 }
459 needed--;
460 }
461
462 *plen = needed;
463
464 TRACE("=> %d\n", res);
465 return res;
466 }
467
468 /******************************************************************
469 * IEParseDisplayNameWithBCW (SHDOCVW.218)
470 */
471 HRESULT WINAPI IEParseDisplayNameWithBCW(DWORD codepage, LPCWSTR lpszDisplayName, LPBC pbc, LPITEMIDLIST *ppidl)
472 {
473 /* Guessing at parameter 3 based on IShellFolder's ParseDisplayName */
474 FIXME("stub: 0x%x %s %p %p\n",codepage,debugstr_w(lpszDisplayName),pbc,ppidl);
475 return E_FAIL;
476 }
477
478 /******************************************************************
479 * SHRestricted2W (SHDOCVW.159)
480 */
481 DWORD WINAPI SHRestricted2W(DWORD res, LPCWSTR url, DWORD reserved)
482 {
483 FIXME("(%d %s %d) stub\n", res, debugstr_w(url), reserved);
484 return 0;
485 }
486
487 /******************************************************************
488 * SHRestricted2A (SHDOCVW.158)
489 *
490 * See SHRestricted2W
491 */
492 DWORD WINAPI SHRestricted2A(DWORD restriction, LPCSTR url, DWORD reserved)
493 {
494 LPWSTR urlW = NULL;
495 DWORD res;
496
497 TRACE("(%d, %s, %d)\n", restriction, debugstr_a(url), reserved);
498 if (url) {
499 DWORD len = MultiByteToWideChar(CP_ACP, 0, url, -1, NULL, 0);
500 urlW = heap_alloc(len * sizeof(WCHAR));
501 MultiByteToWideChar(CP_ACP, 0, url, -1, urlW, len);
502 }
503 res = SHRestricted2W(restriction, urlW, reserved);
504 heap_free(urlW);
505 return res;
506 }
507
508 /******************************************************************
509 * ImportPrivacySettings (SHDOCVW.@)
510 *
511 * Import global and/or per site privacy preferences from an xml file
512 *
513 * PARAMS
514 * filename [I] XML file to use
515 * pGlobalPrefs [IO] PTR to a usage flag for the global privacy preferences
516 * pPerSitePrefs [IO] PTR to a usage flag for the per site privacy preferences
517 *
518 * RETURNS
519 * Success: TRUE (the privacy preferences where updated)
520 * Failure: FALSE (the privacy preferences are unchanged)
521 *
522 * NOTES
523 * Set the flag to TRUE, when the related privacy preferences in the xml file
524 * should be used (parsed and overwrite the current settings).
525 * On return, the flag is TRUE, when the related privacy settings where used
526 *
527 */
528 BOOL WINAPI ImportPrivacySettings(LPCWSTR filename, BOOL *pGlobalPrefs, BOOL * pPerSitePrefs)
529 {
530 FIXME("(%s, %p->%d, %p->%d): stub\n", debugstr_w(filename),
531 pGlobalPrefs, pGlobalPrefs ? *pGlobalPrefs : 0,
532 pPerSitePrefs, pPerSitePrefs ? *pPerSitePrefs : 0);
533
534 if (pGlobalPrefs) *pGlobalPrefs = FALSE;
535 if (pPerSitePrefs) *pPerSitePrefs = FALSE;
536
537 return TRUE;
538 }
539
540 /******************************************************************
541 * ResetProfileSharing (SHDOCVW.164)
542 */
543 HRESULT WINAPI ResetProfileSharing(HWND hwnd)
544 {
545 FIXME("(%p) stub\n", hwnd);
546 return E_NOTIMPL;
547 }
548
549 /******************************************************************
550 * InstallReg_RunDLL (SHDOCVW.@)
551 */
552 void WINAPI InstallReg_RunDLL(HWND hwnd, HINSTANCE handle, LPCSTR cmdline, INT show)
553 {
554 FIXME("(%p %p %s %x)\n", hwnd, handle, debugstr_a(cmdline), show);
555 }
556
557 /******************************************************************
558 * DoFileDownload (SHDOCVW.@)
559 */
560 BOOL WINAPI DoFileDownload(LPWSTR filename)
561 {
562 FIXME("(%s) stub\n", debugstr_w(filename));
563 return FALSE;
564 }
565
566 /******************************************************************
567 * DoOrganizeFavDlgW (SHDOCVW.@)
568 */
569 BOOL WINAPI DoOrganizeFavDlgW(HWND hwnd, LPCWSTR initDir)
570 {
571 FIXME("(%p %s) stub\n", hwnd, debugstr_w(initDir));
572 return FALSE;
573 }
574
575 /******************************************************************
576 * DoOrganizeFavDlg (SHDOCVW.@)
577 */
578 BOOL WINAPI DoOrganizeFavDlg(HWND hwnd, LPCSTR initDir)
579 {
580 LPWSTR initDirW = NULL;
581 BOOL res;
582
583 TRACE("(%p %s)\n", hwnd, debugstr_a(initDir));
584
585 if (initDir) {
586 DWORD len = MultiByteToWideChar(CP_ACP, 0, initDir, -1, NULL, 0);
587 initDirW = heap_alloc(len * sizeof(WCHAR));
588 MultiByteToWideChar(CP_ACP, 0, initDir, -1, initDirW, len);
589 }
590 res = DoOrganizeFavDlgW(hwnd, initDirW);
591 heap_free(initDirW);
592 return res;
593 }