| /* |
| * SHDOCVW - Internet Explorer Web Control |
| * |
| * Copyright 2001 John R. Sheets (for CodeWeavers) |
| * Copyright 2004 Mike McCormack (for CodeWeavers) |
| * Copyright 2008 Detlef Riekenberg |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
| */ |
| |
| #include "config.h" |
| |
| #include <stdarg.h> |
| #include <stdio.h> |
| |
| #include "wine/unicode.h" |
| #include "wine/debug.h" |
| |
| #include "shdocvw.h" |
| |
| #include "winreg.h" |
| #include "shlwapi.h" |
| #include "wininet.h" |
| #include "isguids.h" |
| |
| #include "initguid.h" |
| |
| WINE_DEFAULT_DEBUG_CHANNEL(shdocvw); |
| |
| LONG SHDOCVW_refCount = 0; |
| |
| static HMODULE SHDOCVW_hshell32 = 0; |
| static HINSTANCE ieframe_instance; |
| |
| static HINSTANCE get_ieframe_instance(void) |
| { |
| static const WCHAR ieframe_dllW[] = {'i','e','f','r','a','m','e','.','d','l','l',0}; |
| |
| if(!ieframe_instance) |
| ieframe_instance = LoadLibraryW(ieframe_dllW); |
| |
| return ieframe_instance; |
| } |
| |
| static HRESULT get_ieframe_object(REFCLSID rclsid, REFIID riid, void **ppv) |
| { |
| HINSTANCE ieframe_instance; |
| |
| static HRESULT (WINAPI *ieframe_DllGetClassObject)(REFCLSID,REFIID,void**); |
| |
| if(!ieframe_DllGetClassObject) { |
| ieframe_instance = get_ieframe_instance(); |
| if(!ieframe_instance) |
| return CLASS_E_CLASSNOTAVAILABLE; |
| |
| ieframe_DllGetClassObject = (void*)GetProcAddress(ieframe_instance, "DllGetClassObject"); |
| if(!ieframe_DllGetClassObject) |
| return CLASS_E_CLASSNOTAVAILABLE; |
| } |
| |
| return ieframe_DllGetClassObject(rclsid, riid, ppv); |
| } |
| |
| /************************************************************************* |
| * DllGetClassObject (SHDOCVW.@) |
| */ |
| HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv) |
| { |
| TRACE("(%s %s %p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv); |
| |
| if(IsEqualGUID(&CLSID_WebBrowser, rclsid) |
| || IsEqualGUID(&CLSID_WebBrowser_V1, rclsid) |
| || IsEqualGUID(&CLSID_InternetShortcut, rclsid) |
| || IsEqualGUID(&CLSID_CUrlHistory, rclsid) |
| || IsEqualGUID(&CLSID_TaskbarList, rclsid)) |
| return get_ieframe_object(rclsid, riid, ppv); |
| |
| /* As a last resort, figure if the CLSID belongs to a 'Shell Instance Object' */ |
| return SHDOCVW_GetShellInstanceObjectClassObject(rclsid, riid, ppv); |
| } |
| |
| /*********************************************************************** |
| * DllRegisterServer (shdocvw.@) |
| */ |
| HRESULT WINAPI DllRegisterServer(void) |
| { |
| TRACE("\n"); |
| return S_OK; |
| } |
| |
| /*********************************************************************** |
| * DllUnregisterServer (shdocvw.@) |
| */ |
| HRESULT WINAPI DllUnregisterServer(void) |
| { |
| TRACE("\n"); |
| return S_OK; |
| } |
| |
| /****************************************************************** |
| * IEWinMain (SHDOCVW.101) |
| * |
| * Only returns on error. |
| */ |
| DWORD WINAPI IEWinMain(LPSTR szCommandLine, int nShowWindow) |
| { |
| DWORD (WINAPI *pIEWinMain)(const WCHAR*,int); |
| WCHAR *cmdline; |
| DWORD ret, len; |
| |
| TRACE("%s %d\n", debugstr_a(szCommandLine), nShowWindow); |
| |
| pIEWinMain = (void*)GetProcAddress(get_ieframe_instance(), MAKEINTRESOURCEA(101)); |
| if(!pIEWinMain) |
| ExitProcess(1); |
| |
| len = MultiByteToWideChar(CP_ACP, 0, szCommandLine, -1, NULL, 0); |
| cmdline = heap_alloc(len*sizeof(WCHAR)); |
| if(!cmdline) |
| ExitProcess(1); |
| MultiByteToWideChar(CP_ACP, 0, szCommandLine, -1, cmdline, len); |
| |
| ret = pIEWinMain(cmdline, nShowWindow); |
| |
| heap_free(cmdline); |
| return ret; |
| } |
| |
| /************************************************************************* |
| * SHDOCVW DllMain |
| */ |
| BOOL WINAPI DllMain(HINSTANCE hinst, DWORD fdwReason, LPVOID fImpLoad) |
| { |
| TRACE("%p 0x%x %p\n", hinst, fdwReason, fImpLoad); |
| switch (fdwReason) |
| { |
| case DLL_PROCESS_ATTACH: |
| DisableThreadLibraryCalls(hinst); |
| break; |
| case DLL_PROCESS_DETACH: |
| if (fImpLoad) break; |
| if (SHDOCVW_hshell32) FreeLibrary(SHDOCVW_hshell32); |
| if (ieframe_instance) FreeLibrary(ieframe_instance); |
| break; |
| } |
| return TRUE; |
| } |
| |
| /************************************************************************* |
| * DllCanUnloadNow (SHDOCVW.@) |
| */ |
| HRESULT WINAPI DllCanUnloadNow(void) |
| { |
| return SHDOCVW_refCount ? S_FALSE : S_OK; |
| } |
| |
| /*********************************************************************** |
| * DllGetVersion (SHDOCVW.@) |
| */ |
| HRESULT WINAPI DllGetVersion(DLLVERSIONINFO *info) |
| { |
| if (info->cbSize != sizeof(DLLVERSIONINFO)) FIXME("support DLLVERSIONINFO2\n"); |
| |
| /* this is what IE6 on Windows 98 reports */ |
| info->dwMajorVersion = 6; |
| info->dwMinorVersion = 0; |
| info->dwBuildNumber = 2600; |
| info->dwPlatformID = DLLVER_PLATFORM_WINDOWS; |
| |
| return NOERROR; |
| } |
| |
| /************************************************************************* |
| * DllInstall (SHDOCVW.@) |
| */ |
| HRESULT WINAPI DllInstall(BOOL bInstall, LPCWSTR cmdline) |
| { |
| FIXME("(%s, %s): stub!\n", bInstall ? "TRUE":"FALSE", debugstr_w(cmdline)); |
| |
| return S_OK; |
| } |
| |
| /************************************************************************* |
| * SHDOCVW_LoadShell32 |
| * |
| * makes sure the handle to shell32 is valid |
| */ |
| static BOOL SHDOCVW_LoadShell32(void) |
| { |
| if (SHDOCVW_hshell32) |
| return TRUE; |
| return ((SHDOCVW_hshell32 = LoadLibraryA("shell32.dll")) != NULL); |
| } |
| |
| /*********************************************************************** |
| * @ (SHDOCVW.110) |
| * |
| * Called by Win98 explorer.exe main binary, definitely has 0 |
| * parameters. |
| */ |
| DWORD WINAPI WinList_Init(void) |
| { |
| FIXME("(), stub!\n"); |
| return 0x0deadfeed; |
| } |
| |
| /*********************************************************************** |
| * @ (SHDOCVW.118) |
| * |
| * Called by Win98 explorer.exe main binary, definitely has only one |
| * parameter. |
| */ |
| static BOOL (WINAPI *pShellDDEInit)(BOOL start) = NULL; |
| |
| BOOL WINAPI ShellDDEInit(BOOL start) |
| { |
| TRACE("(%d)\n", start); |
| |
| if (!pShellDDEInit) |
| { |
| if (!SHDOCVW_LoadShell32()) |
| return FALSE; |
| pShellDDEInit = (void *)GetProcAddress(SHDOCVW_hshell32, (LPCSTR)188); |
| } |
| |
| if (pShellDDEInit) |
| return pShellDDEInit(start); |
| else |
| return FALSE; |
| } |
| |
| /*********************************************************************** |
| * @ (SHDOCVW.125) |
| * |
| * Called by Win98 explorer.exe main binary, definitely has 0 |
| * parameters. |
| */ |
| DWORD WINAPI RunInstallUninstallStubs(void) |
| { |
| FIXME("(), stub!\n"); |
| return 0x0deadbee; |
| } |
| |
| /*********************************************************************** |
| * @ (SHDOCVW.130) |
| * |
| * Called by Emerge Desktop (alternative Windows Shell). |
| */ |
| DWORD WINAPI RunInstallUninstallStubs2(int arg) |
| { |
| FIXME("(%d), stub!\n", arg); |
| return 0x0deadbee; |
| } |
| |
| /*********************************************************************** |
| * SetQueryNetSessionCount (SHDOCVW.@) |
| */ |
| DWORD WINAPI SetQueryNetSessionCount(DWORD arg) |
| { |
| FIXME("(%u), stub!\n", arg); |
| return 0; |
| } |
| |
| /********************************************************************** |
| * Some forwards (by ordinal) to SHLWAPI |
| */ |
| |
| static void* fetch_shlwapi_ordinal(UINT_PTR ord) |
| { |
| static const WCHAR shlwapiW[] = {'s','h','l','w','a','p','i','.','d','l','l','\0'}; |
| static HANDLE h; |
| |
| if (!h && !(h = GetModuleHandleW(shlwapiW))) return NULL; |
| return (void*)GetProcAddress(h, (const char*)ord); |
| } |
| |
| /****************************************************************** |
| * WhichPlatformFORWARD (SHDOCVW.@) |
| */ |
| DWORD WINAPI WhichPlatformFORWARD(void) |
| { |
| static DWORD (WINAPI *p)(void); |
| |
| if (p || (p = fetch_shlwapi_ordinal(276))) return p(); |
| return 1; /* not integrated, see shlwapi.WhichPlatform */ |
| } |
| |
| /****************************************************************** |
| * StopWatchModeFORWARD (SHDOCVW.@) |
| */ |
| void WINAPI StopWatchModeFORWARD(void) |
| { |
| static void (WINAPI *p)(void); |
| |
| if (p || (p = fetch_shlwapi_ordinal(241))) p(); |
| } |
| |
| /****************************************************************** |
| * StopWatchFlushFORWARD (SHDOCVW.@) |
| */ |
| void WINAPI StopWatchFlushFORWARD(void) |
| { |
| static void (WINAPI *p)(void); |
| |
| if (p || (p = fetch_shlwapi_ordinal(242))) p(); |
| } |
| |
| /****************************************************************** |
| * StopWatchAFORWARD (SHDOCVW.@) |
| */ |
| DWORD WINAPI StopWatchAFORWARD(DWORD dwClass, LPCSTR lpszStr, DWORD dwUnknown, |
| DWORD dwMode, DWORD dwTimeStamp) |
| { |
| static DWORD (WINAPI *p)(DWORD, LPCSTR, DWORD, DWORD, DWORD); |
| |
| if (p || (p = fetch_shlwapi_ordinal(243))) |
| return p(dwClass, lpszStr, dwUnknown, dwMode, dwTimeStamp); |
| return ERROR_CALL_NOT_IMPLEMENTED; |
| } |
| |
| /****************************************************************** |
| * StopWatchWFORWARD (SHDOCVW.@) |
| */ |
| DWORD WINAPI StopWatchWFORWARD(DWORD dwClass, LPCWSTR lpszStr, DWORD dwUnknown, |
| DWORD dwMode, DWORD dwTimeStamp) |
| { |
| static DWORD (WINAPI *p)(DWORD, LPCWSTR, DWORD, DWORD, DWORD); |
| |
| if (p || (p = fetch_shlwapi_ordinal(244))) |
| return p(dwClass, lpszStr, dwUnknown, dwMode, dwTimeStamp); |
| return ERROR_CALL_NOT_IMPLEMENTED; |
| } |
| |
| /****************************************************************** |
| * URLSubRegQueryA (SHDOCVW.151) |
| */ |
| HRESULT WINAPI URLSubRegQueryA(LPCSTR regpath, LPCSTR name, DWORD type, |
| LPSTR out, DWORD outlen, DWORD unknown) |
| { |
| CHAR buffer[INTERNET_MAX_URL_LENGTH]; |
| DWORD len; |
| LONG res; |
| |
| TRACE("(%s, %s, %d, %p, %d, %d)\n", debugstr_a(regpath), debugstr_a(name), |
| type, out, outlen, unknown); |
| |
| if (!out) return S_OK; |
| |
| len = sizeof(buffer); |
| res = SHRegGetUSValueA(regpath, name, NULL, buffer, &len, FALSE, NULL, 0); |
| if (!res) { |
| lstrcpynA(out, buffer, outlen); |
| return S_OK; |
| } |
| |
| return E_FAIL; |
| } |
| |
| /****************************************************************** |
| * ParseURLFromOutsideSourceW (SHDOCVW.170) |
| */ |
| DWORD WINAPI ParseURLFromOutsideSourceW(LPCWSTR url, LPWSTR out, LPDWORD plen, LPDWORD unknown) |
| { |
| WCHAR buffer_in[INTERNET_MAX_URL_LENGTH]; |
| WCHAR buffer_out[INTERNET_MAX_URL_LENGTH]; |
| LPCWSTR ptr = url; |
| HRESULT hr; |
| DWORD needed; |
| DWORD len; |
| DWORD res = 0; |
| |
| |
| TRACE("(%s, %p, %p, %p) len: %d, unknown: 0x%x\n", debugstr_w(url), out, plen, unknown, |
| plen ? *plen : 0, unknown ? *unknown : 0); |
| |
| if (!PathIsURLW(ptr)) { |
| len = sizeof(buffer_in) / sizeof(buffer_in[0]); |
| buffer_in[0] = 0; |
| hr = UrlApplySchemeW(ptr, buffer_in, &len, URL_APPLY_GUESSSCHEME | URL_APPLY_DEFAULT); |
| TRACE("got 0x%x with %s\n", hr, debugstr_w(buffer_in)); |
| if (hr == S_OK) { |
| /* we parsed the url to buffer_in */ |
| ptr = buffer_in; |
| } |
| else |
| { |
| FIXME("call search hook for %s\n", debugstr_w(ptr)); |
| } |
| } |
| |
| len = sizeof(buffer_out) / sizeof(buffer_out[0]); |
| buffer_out[0] = '\0'; |
| hr = UrlCanonicalizeW(ptr, buffer_out, &len, URL_ESCAPE_SPACES_ONLY); |
| needed = lstrlenW(buffer_out)+1; |
| TRACE("got 0x%x with %s (need %d)\n", hr, debugstr_w(buffer_out), needed); |
| |
| if (*plen >= needed) { |
| if (out != NULL) { |
| lstrcpyW(out, buffer_out); |
| res++; |
| } |
| needed--; |
| } |
| |
| *plen = needed; |
| |
| TRACE("=> %d\n", res); |
| return res; |
| } |
| |
| /****************************************************************** |
| * ParseURLFromOutsideSourceA (SHDOCVW.169) |
| * |
| * See ParseURLFromOutsideSourceW |
| */ |
| DWORD WINAPI ParseURLFromOutsideSourceA(LPCSTR url, LPSTR out, LPDWORD plen, LPDWORD unknown) |
| { |
| WCHAR buffer[INTERNET_MAX_URL_LENGTH]; |
| LPWSTR urlW = NULL; |
| DWORD needed; |
| DWORD res; |
| DWORD len; |
| |
| TRACE("(%s, %p, %p, %p) len: %d, unknown: 0x%x\n", debugstr_a(url), out, plen, unknown, |
| plen ? *plen : 0, unknown ? *unknown : 0); |
| |
| if (url) { |
| len = MultiByteToWideChar(CP_ACP, 0, url, -1, NULL, 0); |
| urlW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| MultiByteToWideChar(CP_ACP, 0, url, -1, urlW, len); |
| } |
| |
| len = sizeof(buffer) / sizeof(buffer[0]); |
| ParseURLFromOutsideSourceW(urlW, buffer, &len, unknown); |
| HeapFree(GetProcessHeap(), 0, urlW); |
| |
| needed = WideCharToMultiByte(CP_ACP, 0, buffer, -1, NULL, 0, NULL, NULL); |
| |
| res = 0; |
| if (*plen >= needed) { |
| if (out != NULL) { |
| WideCharToMultiByte(CP_ACP, 0, buffer, -1, out, *plen, NULL, NULL); |
| res = needed; |
| } |
| needed--; |
| } |
| |
| *plen = needed; |
| |
| TRACE("=> %d\n", res); |
| return res; |
| } |
| |
| /****************************************************************** |
| * IEParseDisplayNameWithBCW (SHDOCVW.218) |
| */ |
| HRESULT WINAPI IEParseDisplayNameWithBCW(DWORD codepage, LPCWSTR lpszDisplayName, LPBC pbc, LPITEMIDLIST *ppidl) |
| { |
| /* Guessing at parameter 3 based on IShellFolder's ParseDisplayName */ |
| FIXME("stub: 0x%x %s %p %p\n",codepage,debugstr_w(lpszDisplayName),pbc,ppidl); |
| return E_FAIL; |
| } |
| |
| /****************************************************************** |
| * SHRestricted2W (SHDOCVW.159) |
| */ |
| DWORD WINAPI SHRestricted2W(DWORD res, LPCWSTR url, DWORD reserved) |
| { |
| FIXME("(%d %s %d) stub\n", res, debugstr_w(url), reserved); |
| return 0; |
| } |
| |
| /****************************************************************** |
| * SHRestricted2A (SHDOCVW.158) |
| * |
| * See SHRestricted2W |
| */ |
| DWORD WINAPI SHRestricted2A(DWORD restriction, LPCSTR url, DWORD reserved) |
| { |
| LPWSTR urlW = NULL; |
| DWORD res; |
| |
| TRACE("(%d, %s, %d)\n", restriction, debugstr_a(url), reserved); |
| if (url) { |
| DWORD len = MultiByteToWideChar(CP_ACP, 0, url, -1, NULL, 0); |
| urlW = heap_alloc(len * sizeof(WCHAR)); |
| MultiByteToWideChar(CP_ACP, 0, url, -1, urlW, len); |
| } |
| res = SHRestricted2W(restriction, urlW, reserved); |
| heap_free(urlW); |
| return res; |
| } |
| |
| /****************************************************************** |
| * ImportPrivacySettings (SHDOCVW.@) |
| * |
| * Import global and/or per site privacy preferences from an xml file |
| * |
| * PARAMS |
| * filename [I] XML file to use |
| * pGlobalPrefs [IO] PTR to a usage flag for the global privacy preferences |
| * pPerSitePrefs [IO] PTR to a usage flag for the per site privacy preferences |
| * |
| * RETURNS |
| * Success: TRUE (the privacy preferences where updated) |
| * Failure: FALSE (the privacy preferences are unchanged) |
| * |
| * NOTES |
| * Set the flag to TRUE, when the related privacy preferences in the xml file |
| * should be used (parsed and overwrite the current settings). |
| * On return, the flag is TRUE, when the related privacy settings where used |
| * |
| */ |
| BOOL WINAPI ImportPrivacySettings(LPCWSTR filename, BOOL *pGlobalPrefs, BOOL * pPerSitePrefs) |
| { |
| FIXME("(%s, %p->%d, %p->%d): stub\n", debugstr_w(filename), |
| pGlobalPrefs, pGlobalPrefs ? *pGlobalPrefs : 0, |
| pPerSitePrefs, pPerSitePrefs ? *pPerSitePrefs : 0); |
| |
| if (pGlobalPrefs) *pGlobalPrefs = FALSE; |
| if (pPerSitePrefs) *pPerSitePrefs = FALSE; |
| |
| return TRUE; |
| } |
| |
| /****************************************************************** |
| * ResetProfileSharing (SHDOCVW.164) |
| */ |
| HRESULT WINAPI ResetProfileSharing(HWND hwnd) |
| { |
| FIXME("(%p) stub\n", hwnd); |
| return E_NOTIMPL; |
| } |
| |
| /****************************************************************** |
| * InstallReg_RunDLL (SHDOCVW.@) |
| */ |
| void WINAPI InstallReg_RunDLL(HWND hwnd, HINSTANCE handle, LPCSTR cmdline, INT show) |
| { |
| FIXME("(%p %p %s %x)\n", hwnd, handle, debugstr_a(cmdline), show); |
| } |
| |
| /****************************************************************** |
| * DoFileDownload (SHDOCVW.@) |
| */ |
| BOOL WINAPI DoFileDownload(LPWSTR filename) |
| { |
| FIXME("(%s) stub\n", debugstr_w(filename)); |
| return FALSE; |
| } |