|  | /* | 
|  | * Implementation of class factory for IE Web Browser | 
|  | * | 
|  | * Copyright 2001 John R. Sheets (for CodeWeavers) | 
|  | * | 
|  | * 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 <string.h> | 
|  | #include <stdio.h> | 
|  |  | 
|  | #include "shdocvw.h" | 
|  | #include "winreg.h" | 
|  | #include "advpub.h" | 
|  | #include "isguids.h" | 
|  |  | 
|  | #include "winver.h" | 
|  |  | 
|  | #include "wine/debug.h" | 
|  |  | 
|  | WINE_DEFAULT_DEBUG_CHANNEL(shdocvw); | 
|  |  | 
|  | /********************************************************************** | 
|  | * Implement the WebBrowser class factory | 
|  | * | 
|  | * (Based on implementation in ddraw/main.c) | 
|  | */ | 
|  |  | 
|  | #define FACTORY(x) ((IClassFactory*) &(x)->lpClassFactoryVtbl) | 
|  |  | 
|  | typedef struct | 
|  | { | 
|  | /* IUnknown fields */ | 
|  | const IClassFactoryVtbl *lpClassFactoryVtbl; | 
|  | HRESULT (*cf)(LPUNKNOWN, REFIID, LPVOID *); | 
|  | LONG ref; | 
|  | } IClassFactoryImpl; | 
|  |  | 
|  |  | 
|  | /********************************************************************** | 
|  | * WBCF_QueryInterface (IUnknown) | 
|  | */ | 
|  | static HRESULT WINAPI WBCF_QueryInterface(LPCLASSFACTORY iface, | 
|  | REFIID riid, LPVOID *ppobj) | 
|  | { | 
|  | TRACE("(%s %p)\n", debugstr_guid(riid), ppobj); | 
|  |  | 
|  | if (!ppobj) | 
|  | return E_POINTER; | 
|  |  | 
|  | if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IClassFactory, riid)) { | 
|  | *ppobj = iface; | 
|  | IClassFactory_AddRef(iface); | 
|  | return S_OK; | 
|  | } | 
|  |  | 
|  | WARN("Not supported interface %s\n", debugstr_guid(riid)); | 
|  |  | 
|  | *ppobj = NULL; | 
|  | return E_NOINTERFACE; | 
|  | } | 
|  |  | 
|  | /************************************************************************ | 
|  | * WBCF_AddRef (IUnknown) | 
|  | */ | 
|  | static ULONG WINAPI WBCF_AddRef(LPCLASSFACTORY iface) | 
|  | { | 
|  | SHDOCVW_LockModule(); | 
|  |  | 
|  | return 2; /* non-heap based object */ | 
|  | } | 
|  |  | 
|  | /************************************************************************ | 
|  | * WBCF_Release (IUnknown) | 
|  | */ | 
|  | static ULONG WINAPI WBCF_Release(LPCLASSFACTORY iface) | 
|  | { | 
|  | SHDOCVW_UnlockModule(); | 
|  |  | 
|  | return 1; /* non-heap based object */ | 
|  | } | 
|  |  | 
|  | /************************************************************************ | 
|  | * WBCF_CreateInstance (IClassFactory) | 
|  | */ | 
|  | static HRESULT WINAPI WBCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, | 
|  | REFIID riid, LPVOID *ppobj) | 
|  | { | 
|  | IClassFactoryImpl *This = (IClassFactoryImpl *) iface; | 
|  | return This->cf(pOuter, riid, ppobj); | 
|  | } | 
|  |  | 
|  | /************************************************************************ | 
|  | * WBCF_LockServer (IClassFactory) | 
|  | */ | 
|  | static HRESULT WINAPI WBCF_LockServer(LPCLASSFACTORY iface, BOOL dolock) | 
|  | { | 
|  | TRACE("(%d)\n", dolock); | 
|  |  | 
|  | if (dolock) | 
|  | SHDOCVW_LockModule(); | 
|  | else | 
|  | SHDOCVW_UnlockModule(); | 
|  |  | 
|  | return S_OK; | 
|  | } | 
|  |  | 
|  | static const IClassFactoryVtbl WBCF_Vtbl = | 
|  | { | 
|  | WBCF_QueryInterface, | 
|  | WBCF_AddRef, | 
|  | WBCF_Release, | 
|  | WBCF_CreateInstance, | 
|  | WBCF_LockServer | 
|  | }; | 
|  |  | 
|  | /************************************************************************* | 
|  | *              DllGetClassObject (SHDOCVW.@) | 
|  | */ | 
|  | HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv) | 
|  | { | 
|  | static IClassFactoryImpl WB1ClassFactory = {&WBCF_Vtbl, WebBrowserV1_Create}; | 
|  | static IClassFactoryImpl WB2ClassFactory = {&WBCF_Vtbl, WebBrowserV2_Create}; | 
|  | static IClassFactoryImpl CUHClassFactory = {&WBCF_Vtbl, CUrlHistory_Create}; | 
|  | static IClassFactoryImpl ISCClassFactory = {&WBCF_Vtbl, InternetShortcut_Create}; | 
|  | static IClassFactoryImpl TBLClassFactory = {&WBCF_Vtbl, TaskbarList_Create}; | 
|  |  | 
|  | TRACE("\n"); | 
|  |  | 
|  | if(IsEqualGUID(&CLSID_WebBrowser, rclsid)) | 
|  | return IClassFactory_QueryInterface(FACTORY(&WB2ClassFactory), riid, ppv); | 
|  |  | 
|  | if(IsEqualGUID(&CLSID_WebBrowser_V1, rclsid)) | 
|  | return IClassFactory_QueryInterface(FACTORY(&WB1ClassFactory), riid, ppv); | 
|  |  | 
|  | if(IsEqualGUID(&CLSID_CUrlHistory, rclsid)) | 
|  | return IClassFactory_QueryInterface(FACTORY(&CUHClassFactory), riid, ppv); | 
|  |  | 
|  | if(IsEqualGUID(&CLSID_InternetShortcut, rclsid)) | 
|  | return IClassFactory_QueryInterface(FACTORY(&ISCClassFactory), riid, ppv); | 
|  |  | 
|  | if(IsEqualGUID(&CLSID_TaskbarList, rclsid)) | 
|  | return IClassFactory_QueryInterface(FACTORY(&TBLClassFactory), riid, ppv); | 
|  |  | 
|  | /* As a last resort, figure if the CLSID belongs to a 'Shell Instance Object' */ | 
|  | return SHDOCVW_GetShellInstanceObjectClassObject(rclsid, riid, ppv); | 
|  | } | 
|  |  | 
|  | HRESULT register_class_object(BOOL do_reg) | 
|  | { | 
|  | HRESULT hres; | 
|  |  | 
|  | static DWORD cookie; | 
|  | static IClassFactoryImpl IEClassFactory = {&WBCF_Vtbl, InternetExplorer_Create}; | 
|  |  | 
|  | if(do_reg) { | 
|  | hres = CoRegisterClassObject(&CLSID_InternetExplorer, (IUnknown*)FACTORY(&IEClassFactory), | 
|  | CLSCTX_SERVER, REGCLS_MULTIPLEUSE|REGCLS_SUSPENDED, &cookie); | 
|  | if (FAILED(hres)) { | 
|  | ERR("failed to register object %08x\n", hres); | 
|  | return hres; | 
|  | } | 
|  |  | 
|  | hres = CoResumeClassObjects(); | 
|  | if(SUCCEEDED(hres)) | 
|  | return hres; | 
|  |  | 
|  | ERR("failed to resume object %08x\n", hres); | 
|  | } | 
|  |  | 
|  | return CoRevokeClassObject(cookie); | 
|  | } | 
|  |  | 
|  | static HRESULT reg_install(LPCSTR section, STRTABLEA *strtable) | 
|  | { | 
|  | HRESULT (WINAPI *pRegInstall)(HMODULE hm, LPCSTR pszSection, const STRTABLEA* pstTable); | 
|  | HMODULE hadvpack; | 
|  | HRESULT hres; | 
|  |  | 
|  | static const WCHAR advpackW[] = {'a','d','v','p','a','c','k','.','d','l','l',0}; | 
|  |  | 
|  | hadvpack = LoadLibraryW(advpackW); | 
|  | pRegInstall = (void *)GetProcAddress(hadvpack, "RegInstall"); | 
|  |  | 
|  | hres = pRegInstall(shdocvw_hinstance, section, strtable); | 
|  |  | 
|  | FreeLibrary(hadvpack); | 
|  | return hres; | 
|  | } | 
|  |  | 
|  | static const GUID CLSID_MicrosoftBrowserArchitecture = | 
|  | {0xa5e46e3a, 0x8849, 0x11d1, {0x9d, 0x8c, 0x00, 0xc0, 0x4f, 0xc9, 0x9d, 0x61}}; | 
|  | static const GUID CLSID_MruLongList = | 
|  | {0x53bd6b4e, 0x3780, 0x4693, {0xaf, 0xc3, 0x71, 0x61, 0xc2, 0xf3, 0xee, 0x9c}}; | 
|  |  | 
|  | #define INF_SET_CLSID(clsid)                  \ | 
|  | do                                        \ | 
|  | {                                         \ | 
|  | static CHAR name[] = "CLSID_" #clsid; \ | 
|  | \ | 
|  | pse[i].pszName = name;                \ | 
|  | clsids[i++] = &CLSID_ ## clsid;       \ | 
|  | } while (0) | 
|  |  | 
|  | static HRESULT register_server(BOOL doregister) | 
|  | { | 
|  | STRTABLEA strtable; | 
|  | STRENTRYA pse[15]; | 
|  | static CLSID const *clsids[15]; | 
|  | unsigned int i = 0; | 
|  | HRESULT hres; | 
|  |  | 
|  | INF_SET_CLSID(CUrlHistory); | 
|  | INF_SET_CLSID(Internet); | 
|  | INF_SET_CLSID(InternetExplorer); | 
|  | INF_SET_CLSID(InternetShortcut); | 
|  | INF_SET_CLSID(MicrosoftBrowserArchitecture); | 
|  | INF_SET_CLSID(MruLongList); | 
|  | INF_SET_CLSID(SearchAssistantOC); | 
|  | INF_SET_CLSID(ShellNameSpace); | 
|  | INF_SET_CLSID(ShellSearchAssistantOC); | 
|  | INF_SET_CLSID(ShellShellNameSpace); | 
|  | INF_SET_CLSID(ShellUIHelper); | 
|  | INF_SET_CLSID(ShellWindows); | 
|  | INF_SET_CLSID(TaskbarList); | 
|  | INF_SET_CLSID(WebBrowser); | 
|  | INF_SET_CLSID(WebBrowser_V1); | 
|  |  | 
|  | for(i = 0; i < sizeof(pse)/sizeof(pse[0]); i++) { | 
|  | pse[i].pszValue = HeapAlloc(GetProcessHeap(), 0, 39); | 
|  | sprintf(pse[i].pszValue, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", | 
|  | clsids[i]->Data1, clsids[i]->Data2, clsids[i]->Data3, clsids[i]->Data4[0], | 
|  | clsids[i]->Data4[1], clsids[i]->Data4[2], clsids[i]->Data4[3], clsids[i]->Data4[4], | 
|  | clsids[i]->Data4[5], clsids[i]->Data4[6], clsids[i]->Data4[7]); | 
|  | } | 
|  |  | 
|  | strtable.cEntries = sizeof(pse)/sizeof(pse[0]); | 
|  | strtable.pse = pse; | 
|  |  | 
|  | hres = reg_install(doregister ? "RegisterDll" : "UnregisterDll", &strtable); | 
|  |  | 
|  | for(i=0; i < sizeof(pse)/sizeof(pse[0]); i++) | 
|  | HeapFree(GetProcessHeap(), 0, pse[i].pszValue); | 
|  |  | 
|  | return hres; | 
|  | } | 
|  |  | 
|  | #undef INF_SET_CLSID | 
|  |  | 
|  | /*********************************************************************** | 
|  | *          DllRegisterServer (shdocvw.@) | 
|  | */ | 
|  | HRESULT WINAPI DllRegisterServer(void) | 
|  | { | 
|  | ITypeLib *typelib; | 
|  | HRESULT hres; | 
|  |  | 
|  | static const WCHAR shdocvwW[] = {'s','h','d','o','c','v','w','.','d','l','l',0}; | 
|  |  | 
|  | hres = register_server(TRUE); | 
|  | if(FAILED(hres)) | 
|  | return hres; | 
|  |  | 
|  | hres = LoadTypeLibEx(shdocvwW, REGKIND_REGISTER, &typelib); | 
|  | if(FAILED(hres)) { | 
|  | ERR("Could not load typelib: %08x\n", hres); | 
|  | return hres; | 
|  | } | 
|  |  | 
|  | ITypeLib_Release(typelib); | 
|  |  | 
|  | return hres; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *          DllUnregisterServer (shdocvw.@) | 
|  | */ | 
|  | HRESULT WINAPI DllUnregisterServer(void) | 
|  | { | 
|  | HRESULT hres; | 
|  |  | 
|  | hres = register_server(FALSE); | 
|  | if(FAILED(hres)) | 
|  | return hres; | 
|  |  | 
|  | return UnRegisterTypeLib(&LIBID_SHDocVw, 1, 1, LOCALE_SYSTEM_DEFAULT, SYS_WIN32); | 
|  | } | 
|  |  | 
|  | static BOOL check_native_ie(void) | 
|  | { | 
|  | static const WCHAR cszPath[] = {'b','r','o','w','s','e','u','i','.','d','l','l',0}; | 
|  | DWORD handle,size; | 
|  | BOOL ret = TRUE; | 
|  |  | 
|  | size = GetFileVersionInfoSizeW(cszPath,&handle); | 
|  | if (size) | 
|  | { | 
|  | LPVOID buf; | 
|  | LPWSTR lpFileDescription; | 
|  | UINT dwBytes; | 
|  | static const WCHAR cszFD[] = {'\\','S','t','r','i','n','g','F','i','l','e','I','n','f','o','\\','0','4','0','9','0','4','e','4','\\','F','i','l','e','D','e','s','c','r','i','p','t','i','o','n',0}; | 
|  | static const WCHAR cszWine[] = {'W','i','n','e',0}; | 
|  |  | 
|  | buf = HeapAlloc(GetProcessHeap(),0,size); | 
|  | GetFileVersionInfoW(cszPath,0,size,buf); | 
|  |  | 
|  | if (VerQueryValueW(buf, cszFD, (LPVOID*)&lpFileDescription, &dwBytes) && | 
|  | strstrW(lpFileDescription,cszWine)) | 
|  | ret = FALSE; | 
|  |  | 
|  | HeapFree(GetProcessHeap(), 0, buf); | 
|  | } | 
|  |  | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | DWORD register_iexplore(BOOL doregister) | 
|  | { | 
|  | HRESULT hres; | 
|  | if (check_native_ie()) | 
|  | { | 
|  | TRACE("Native IE detected, not doing registration\n"); | 
|  | return S_OK; | 
|  | } | 
|  | hres = reg_install(doregister ? "RegisterIE" : "UnregisterIE", NULL); | 
|  | return FAILED(hres); | 
|  | } |