|  | /* | 
|  | * Copyright 2005-2006 Jacek Caban 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 "config.h" | 
|  |  | 
|  | #include <stdarg.h> | 
|  |  | 
|  | #define COBJMACROS | 
|  |  | 
|  | #include "windef.h" | 
|  | #include "winbase.h" | 
|  | #include "winuser.h" | 
|  | #include "winreg.h" | 
|  | #include "ole2.h" | 
|  |  | 
|  | #include "wine/debug.h" | 
|  | #include "wine/unicode.h" | 
|  |  | 
|  | #include "mshtml_private.h" | 
|  |  | 
|  | WINE_DEFAULT_DEBUG_CHANNEL(mshtml); | 
|  |  | 
|  | #define NS_APPSTARTUPNOTIFIER_CONTRACTID "@mozilla.org/embedcomp/appstartup-notifier;1" | 
|  | #define NS_WEBBROWSER_CONTRACTID "@mozilla.org/embedding/browser/nsWebBrowser;1" | 
|  | #define NS_PROFILE_CONTRACTID "@mozilla.org/profile/manager;1" | 
|  | #define NS_MEMORY_CONTRACTID "@mozilla.org/xpcom/memory-service;1" | 
|  | #define NS_STRINGSTREAM_CONTRACTID "@mozilla.org/io/string-input-stream;1" | 
|  | #define NS_COMMANDPARAMS_CONTRACTID "@mozilla.org/embedcomp/command-params;1" | 
|  | #define NS_HTMLSERIALIZER_CONTRACTID "@mozilla.org/layout/contentserializer;1?mimetype=text/html" | 
|  |  | 
|  | #define APPSTARTUP_TOPIC "app-startup" | 
|  |  | 
|  | #define PR_UINT32_MAX 0xffffffff | 
|  |  | 
|  | struct nsCStringContainer { | 
|  | void *v; | 
|  | void *d1; | 
|  | PRUint32 d2; | 
|  | void *d3; | 
|  | }; | 
|  |  | 
|  | static nsresult (*NS_InitXPCOM2)(nsIServiceManager**,void*,void*); | 
|  | static nsresult (*NS_ShutdownXPCOM)(nsIServiceManager*); | 
|  | static nsresult (*NS_GetComponentRegistrar)(nsIComponentRegistrar**); | 
|  | static nsresult (*NS_StringContainerInit)(nsStringContainer*); | 
|  | static nsresult (*NS_CStringContainerInit)(nsCStringContainer*); | 
|  | static nsresult (*NS_StringContainerFinish)(nsStringContainer*); | 
|  | static nsresult (*NS_CStringContainerFinish)(nsCStringContainer*); | 
|  | static nsresult (*NS_StringSetData)(nsAString*,const PRUnichar*,PRUint32); | 
|  | static nsresult (*NS_CStringSetData)(nsACString*,const char*,PRUint32); | 
|  | static nsresult (*NS_NewLocalFile)(const nsAString*,PRBool,nsIFile**); | 
|  | static PRUint32 (*NS_StringGetData)(const nsAString*,const PRUnichar **,PRBool*); | 
|  | static PRUint32 (*NS_CStringGetData)(const nsACString*,const char**,PRBool*); | 
|  |  | 
|  | static HINSTANCE hXPCOM = NULL; | 
|  |  | 
|  | static nsIServiceManager *pServMgr = NULL; | 
|  | static nsIComponentManager *pCompMgr = NULL; | 
|  | static nsIMemory *nsmem = NULL; | 
|  |  | 
|  | static const WCHAR wszNsContainer[] = {'N','s','C','o','n','t','a','i','n','e','r',0}; | 
|  |  | 
|  | static ATOM nscontainer_class; | 
|  |  | 
|  | static LRESULT WINAPI nsembed_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) | 
|  | { | 
|  | NSContainer *This; | 
|  | nsresult nsres; | 
|  |  | 
|  | static const WCHAR wszTHIS[] = {'T','H','I','S',0}; | 
|  |  | 
|  | if(msg == WM_CREATE) { | 
|  | This = *(NSContainer**)lParam; | 
|  | SetPropW(hwnd, wszTHIS, This); | 
|  | }else { | 
|  | This = (NSContainer*)GetPropW(hwnd, wszTHIS); | 
|  | } | 
|  |  | 
|  | switch(msg) { | 
|  | case WM_SIZE: | 
|  | TRACE("(%p)->(WM_SIZE)\n", This); | 
|  |  | 
|  | nsres = nsIBaseWindow_SetSize(This->window, | 
|  | LOWORD(lParam), HIWORD(lParam), TRUE); | 
|  | if(NS_FAILED(nsres)) | 
|  | WARN("SetSize failed: %08x\n", nsres); | 
|  | } | 
|  |  | 
|  | return DefWindowProcW(hwnd, msg, wParam, lParam); | 
|  | } | 
|  |  | 
|  |  | 
|  | static void register_nscontainer_class(void) | 
|  | { | 
|  | static WNDCLASSEXW wndclass = { | 
|  | sizeof(WNDCLASSEXW), | 
|  | CS_DBLCLKS, | 
|  | nsembed_proc, | 
|  | 0, 0, NULL, NULL, NULL, NULL, NULL, | 
|  | wszNsContainer, | 
|  | NULL, | 
|  | }; | 
|  | wndclass.hInstance = hInst; | 
|  | nscontainer_class = RegisterClassExW(&wndclass); | 
|  | } | 
|  |  | 
|  | static BOOL load_xpcom(PRUnichar *gre_path) | 
|  | { | 
|  | WCHAR path_env[MAX_PATH]; | 
|  | int len; | 
|  |  | 
|  | static const WCHAR wszPATH[] = {'P','A','T','H',0}; | 
|  | static const WCHAR strXPCOM[] = {'x','p','c','o','m','.','d','l','l',0}; | 
|  |  | 
|  | TRACE("(%s)\n", debugstr_w(gre_path)); | 
|  |  | 
|  | /* We have to modify PATH as XPCOM loads other DLLs from this directory. */ | 
|  | GetEnvironmentVariableW(wszPATH, path_env, sizeof(path_env)/sizeof(WCHAR)); | 
|  | len = strlenW(path_env); | 
|  | path_env[len++] = ';'; | 
|  | strcpyW(path_env+len, gre_path); | 
|  | SetEnvironmentVariableW(wszPATH, path_env); | 
|  |  | 
|  | hXPCOM = LoadLibraryW(strXPCOM); | 
|  | if(!hXPCOM) { | 
|  | WARN("Could not load XPCOM: %d\n", GetLastError()); | 
|  | return FALSE; | 
|  | } | 
|  |  | 
|  | #define NS_DLSYM(func) \ | 
|  | func = (typeof(func))GetProcAddress(hXPCOM, #func); \ | 
|  | if(!func) \ | 
|  | ERR("Could not GetProcAddress(" #func ") failed\n") | 
|  |  | 
|  | NS_DLSYM(NS_InitXPCOM2); | 
|  | NS_DLSYM(NS_ShutdownXPCOM); | 
|  | NS_DLSYM(NS_GetComponentRegistrar); | 
|  | NS_DLSYM(NS_StringContainerInit); | 
|  | NS_DLSYM(NS_CStringContainerInit); | 
|  | NS_DLSYM(NS_StringContainerFinish); | 
|  | NS_DLSYM(NS_CStringContainerFinish); | 
|  | NS_DLSYM(NS_StringSetData); | 
|  | NS_DLSYM(NS_CStringSetData); | 
|  | NS_DLSYM(NS_NewLocalFile); | 
|  | NS_DLSYM(NS_StringGetData); | 
|  | NS_DLSYM(NS_CStringGetData); | 
|  |  | 
|  | #undef NS_DLSYM | 
|  |  | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  | static BOOL load_mozilla(PRUnichar *gre_path) | 
|  | { | 
|  | DWORD res, type, i, size = MAX_PATH; | 
|  | HKEY mozilla_key, hkey; | 
|  | WCHAR key_name[100]; | 
|  | BOOL ret = FALSE; | 
|  |  | 
|  | static const WCHAR wszGreKey[] = | 
|  | {'S','o','f','t','w','a','r','e','\\', | 
|  | 'm','o','z','i','l','l','a','.','o','r','g','\\', | 
|  | 'G','R','E',0}; | 
|  |  | 
|  | static const WCHAR wszGreHome[] = {'G','r','e','H','o','m','e',0}; | 
|  |  | 
|  | res = RegOpenKeyW(HKEY_LOCAL_MACHINE, wszGreKey, &mozilla_key); | 
|  | if(res != ERROR_SUCCESS) { | 
|  | TRACE("Could not open key %s\n", debugstr_w(wszGreKey)); | 
|  | return FALSE; | 
|  | } | 
|  |  | 
|  | for(i=0; !ret && RegEnumKeyW(mozilla_key, i, key_name, sizeof(key_name)/sizeof(WCHAR)) == ERROR_SUCCESS; i++) { | 
|  | RegOpenKeyW(mozilla_key, key_name, &hkey); | 
|  | res = RegQueryValueExW(hkey, wszGreHome, NULL, &type, (LPBYTE)gre_path, &size); | 
|  | if(res == ERROR_SUCCESS) | 
|  | ret = TRUE; | 
|  | RegCloseKey(hkey); | 
|  | } | 
|  |  | 
|  | RegCloseKey(mozilla_key); | 
|  | return ret ? load_xpcom(gre_path) : FALSE; | 
|  | } | 
|  |  | 
|  | static BOOL load_mozctl(PRUnichar *gre_path) | 
|  | { | 
|  | HKEY hkey; | 
|  | DWORD res, type, size = MAX_PATH; | 
|  |  | 
|  | static const WCHAR wszMozCtlKey[] = | 
|  | {'S','o','f','t','w','a','r','e','\\','M','o','z','i','l','l','a',0}; | 
|  | static const WCHAR wszBinDirectoryPath[] = | 
|  | {'B','i','n','D','i','r','e','c','t','o','r','y','P','a','t','h',0}; | 
|  | static const WCHAR wszMozCtlClsidKey[] = | 
|  | {'C','L','S','I','D','\\', | 
|  | '{','1','3','3','9','B','5','4','C','-','3','4','5','3','-','1','1','D','2', | 
|  | '-','9','3','B','9','-','0','0','0','0','0','0','0','0','0','0','0','0','}','\\', | 
|  | 'I','n','p','r','o','c','S','e','r','v','e','r','3','2',0}; | 
|  |  | 
|  | res = RegOpenKeyW(HKEY_LOCAL_MACHINE, wszMozCtlKey, &hkey); | 
|  | if(res == ERROR_SUCCESS) { | 
|  | res = RegQueryValueExW(hkey, wszBinDirectoryPath, NULL, &type, (LPBYTE)gre_path, &size); | 
|  | if(res == ERROR_SUCCESS) | 
|  | return load_xpcom(gre_path); | 
|  | else | 
|  | ERR("Could not get value %s\n", debugstr_w(wszBinDirectoryPath)); | 
|  | } | 
|  |  | 
|  | res = RegOpenKeyW(HKEY_CLASSES_ROOT, wszMozCtlClsidKey, &hkey); | 
|  | if(res == ERROR_SUCCESS) { | 
|  | res = RegQueryValueExW(hkey, NULL, NULL, &type, (LPBYTE)gre_path, &size); | 
|  | if(res == ERROR_SUCCESS) { | 
|  | WCHAR *ptr; | 
|  | if((ptr = strrchrW(gre_path, '\\'))) | 
|  | ptr[1] = 0; | 
|  | load_xpcom(gre_path); | 
|  | }else { | 
|  | ERR("Could not get value of %s\n", debugstr_w(wszMozCtlClsidKey)); | 
|  | } | 
|  | } | 
|  |  | 
|  | TRACE("Could not find Mozilla ActiveX Control\n"); | 
|  |  | 
|  | return FALSE; | 
|  | } | 
|  |  | 
|  | static BOOL load_wine_gecko(PRUnichar *gre_path) | 
|  | { | 
|  | HKEY hkey; | 
|  | DWORD res, type, size = MAX_PATH; | 
|  |  | 
|  | static const WCHAR wszMshtmlKey[] = { | 
|  | 'S','o','f','t','w','a','r','e','\\','W','i','n','e', | 
|  | '\\','M','S','H','T','M','L',0}; | 
|  | static const WCHAR wszGeckoPath[] = | 
|  | {'G','e','c','k','o','P','a','t','h',0}; | 
|  |  | 
|  | /* @@ Wine registry key: HKCU\Software\Wine\MSHTML */ | 
|  | res = RegOpenKeyW(HKEY_CURRENT_USER, wszMshtmlKey, &hkey); | 
|  | if(res != ERROR_SUCCESS) | 
|  | return FALSE; | 
|  |  | 
|  | res = RegQueryValueExW(hkey, wszGeckoPath, NULL, &type, (LPBYTE)gre_path, &size); | 
|  | if(res != ERROR_SUCCESS || type != REG_SZ) | 
|  | return FALSE; | 
|  |  | 
|  | return load_xpcom(gre_path); | 
|  | } | 
|  |  | 
|  | static void set_profile(void) | 
|  | { | 
|  | nsIProfile *profile; | 
|  | PRBool exists = FALSE; | 
|  | nsresult nsres; | 
|  |  | 
|  | static const WCHAR wszMSHTML[] = {'M','S','H','T','M','L',0}; | 
|  |  | 
|  | nsres = nsIServiceManager_GetServiceByContactID(pServMgr, NS_PROFILE_CONTRACTID, | 
|  | &IID_nsIProfile, (void**)&profile); | 
|  | if(NS_FAILED(nsres)) { | 
|  | ERR("Could not get profile service: %08x\n", nsres); | 
|  | return; | 
|  | } | 
|  |  | 
|  | nsres = nsIProfile_ProfileExists(profile, wszMSHTML, &exists); | 
|  | if(!exists) { | 
|  | nsres = nsIProfile_CreateNewProfile(profile, wszMSHTML, NULL, NULL, FALSE); | 
|  | if(NS_FAILED(nsres)) | 
|  | ERR("CreateNewProfile failed: %08x\n", nsres); | 
|  | } | 
|  |  | 
|  | nsres = nsIProfile_SetCurrentProfile(profile, wszMSHTML); | 
|  | if(NS_FAILED(nsres)) | 
|  | ERR("SetCurrentProfile failed: %08x\n", nsres); | 
|  |  | 
|  | nsIProfile_Release(profile); | 
|  | } | 
|  |  | 
|  | static BOOL load_gecko(void) | 
|  | { | 
|  | nsresult nsres; | 
|  | nsIObserver *pStartNotif; | 
|  | nsIComponentRegistrar *registrar = NULL; | 
|  | nsAString path; | 
|  | nsIFile *gre_dir; | 
|  | PRUnichar gre_path[MAX_PATH]; | 
|  |  | 
|  | static BOOL tried_load = FALSE; | 
|  |  | 
|  | TRACE("()\n"); | 
|  |  | 
|  | if(tried_load) | 
|  | return pCompMgr != NULL; | 
|  | tried_load = TRUE; | 
|  |  | 
|  | if(!load_wine_gecko(gre_path) && !load_mozctl(gre_path) && !load_mozilla(gre_path)) { | 
|  | install_wine_gecko(); | 
|  | if(!load_wine_gecko(gre_path)) { | 
|  | MESSAGE("Could not load Mozilla. HTML rendering will be disabled.\n"); | 
|  | return FALSE; | 
|  | } | 
|  | } | 
|  |  | 
|  | nsAString_Init(&path, gre_path); | 
|  | nsres = NS_NewLocalFile(&path, FALSE, &gre_dir); | 
|  | nsAString_Finish(&path); | 
|  | if(NS_FAILED(nsres)) { | 
|  | ERR("NS_NewLocalFile failed: %08x\n", nsres); | 
|  | FreeLibrary(hXPCOM); | 
|  | return FALSE; | 
|  | } | 
|  |  | 
|  | nsres = NS_InitXPCOM2(&pServMgr, gre_dir, NULL); | 
|  | if(NS_FAILED(nsres)) { | 
|  | ERR("NS_InitXPCOM2 failed: %08x\n", nsres); | 
|  | FreeLibrary(hXPCOM); | 
|  | return FALSE; | 
|  | } | 
|  |  | 
|  | nsres = nsIServiceManager_QueryInterface(pServMgr, &IID_nsIComponentManager, (void**)&pCompMgr); | 
|  | if(NS_FAILED(nsres)) | 
|  | ERR("Could not get nsIComponentManager: %08x\n", nsres); | 
|  |  | 
|  | nsres = NS_GetComponentRegistrar(®istrar); | 
|  | if(NS_SUCCEEDED(nsres)) { | 
|  | nsres = nsIComponentRegistrar_AutoRegister(registrar, NULL); | 
|  | if(NS_FAILED(nsres)) | 
|  | ERR("AutoRegister(NULL) failed: %08x\n", nsres); | 
|  |  | 
|  | nsres = nsIComponentRegistrar_AutoRegister(registrar, gre_dir); | 
|  | if(NS_FAILED(nsres)) | 
|  | ERR("AutoRegister(gre_dir) failed: %08x\n", nsres); | 
|  |  | 
|  | init_nsio(pCompMgr, registrar); | 
|  | }else { | 
|  | ERR("NS_GetComponentRegistrar failed: %08x\n", nsres); | 
|  | } | 
|  |  | 
|  | nsres = nsIComponentManager_CreateInstanceByContractID(pCompMgr, NS_APPSTARTUPNOTIFIER_CONTRACTID, | 
|  | NULL, &IID_nsIObserver, (void**)&pStartNotif); | 
|  | if(NS_SUCCEEDED(nsres)) { | 
|  | nsres = nsIObserver_Observe(pStartNotif, NULL, APPSTARTUP_TOPIC, NULL); | 
|  | if(NS_FAILED(nsres)) | 
|  | ERR("Observe failed: %08x\n", nsres); | 
|  |  | 
|  | nsIObserver_Release(pStartNotif); | 
|  | }else { | 
|  | ERR("could not get appstartup-notifier: %08x\n", nsres); | 
|  | } | 
|  |  | 
|  | set_profile(); | 
|  |  | 
|  | nsres = nsIComponentManager_CreateInstanceByContractID(pCompMgr, NS_MEMORY_CONTRACTID, | 
|  | NULL, &IID_nsIMemory, (void**)&nsmem); | 
|  | if(NS_FAILED(nsres)) | 
|  | ERR("Could not get nsIMemory: %08x\n", nsres); | 
|  |  | 
|  | if(registrar) { | 
|  | register_nsservice(registrar, pServMgr); | 
|  | nsIComponentRegistrar_Release(registrar); | 
|  | } | 
|  |  | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  | void *nsalloc(size_t size) | 
|  | { | 
|  | return nsIMemory_Alloc(nsmem, size); | 
|  | } | 
|  |  | 
|  | void nsfree(void *mem) | 
|  | { | 
|  | nsIMemory_Free(nsmem, mem); | 
|  | } | 
|  |  | 
|  | void nsACString_Init(nsACString *str, const char *data) | 
|  | { | 
|  | NS_CStringContainerInit(str); | 
|  | if(data) | 
|  | NS_CStringSetData(str, data, PR_UINT32_MAX); | 
|  | } | 
|  |  | 
|  | PRUint32 nsACString_GetData(const nsACString *str, const char **data, PRBool *termited) | 
|  | { | 
|  | return NS_CStringGetData(str, data, termited); | 
|  | } | 
|  |  | 
|  | void nsACString_Finish(nsACString *str) | 
|  | { | 
|  | NS_CStringContainerFinish(str); | 
|  | } | 
|  |  | 
|  | void nsAString_Init(nsAString *str, const PRUnichar *data) | 
|  | { | 
|  | NS_StringContainerInit(str); | 
|  | if(data) | 
|  | NS_StringSetData(str, data, PR_UINT32_MAX); | 
|  | } | 
|  |  | 
|  | PRUint32 nsAString_GetData(const nsAString *str, const PRUnichar **data, PRBool *termited) | 
|  | { | 
|  | return NS_StringGetData(str, data, termited); | 
|  | } | 
|  |  | 
|  | void nsAString_Finish(nsAString *str) | 
|  | { | 
|  | NS_StringContainerFinish(str); | 
|  | } | 
|  |  | 
|  | nsIInputStream *create_nsstream(const char *data, PRInt32 data_len) | 
|  | { | 
|  | nsIStringInputStream *ret; | 
|  | nsresult nsres; | 
|  |  | 
|  | if(!pCompMgr) | 
|  | return NULL; | 
|  |  | 
|  | nsres = nsIComponentManager_CreateInstanceByContractID(pCompMgr, | 
|  | NS_STRINGSTREAM_CONTRACTID, NULL, &IID_nsIStringInputStream, | 
|  | (void**)&ret); | 
|  | if(NS_FAILED(nsres)) { | 
|  | ERR("Could not get nsIStringInputStream\n"); | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | nsres = nsIStringInputStream_SetData(ret, data, data_len); | 
|  | if(NS_FAILED(nsres)) { | 
|  | ERR("AdoptData failed: %08x\n", nsres); | 
|  | nsIStringInputStream_Release(ret); | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | return (nsIInputStream*)ret; | 
|  | } | 
|  |  | 
|  | nsICommandParams *create_nscommand_params(void) | 
|  | { | 
|  | nsICommandParams *ret = NULL; | 
|  | nsresult nsres; | 
|  |  | 
|  | if(!pCompMgr) | 
|  | return NULL; | 
|  |  | 
|  | nsres = nsIComponentManager_CreateInstanceByContractID(pCompMgr, | 
|  | NS_COMMANDPARAMS_CONTRACTID, NULL, &IID_nsICommandParams, | 
|  | (void**)&ret); | 
|  | if(NS_FAILED(nsres)) | 
|  | ERR("Could not get nsICommandParams\n"); | 
|  |  | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | static void nsnode_to_nsstring_rec(nsIContentSerializer *serializer, nsIDOMNode *nsnode, nsAString *str) | 
|  | { | 
|  | nsIDOMNodeList *node_list = NULL; | 
|  | PRBool has_children = FALSE; | 
|  | PRUint16 type; | 
|  | nsresult nsres; | 
|  |  | 
|  | nsIDOMNode_HasChildNodes(nsnode, &has_children); | 
|  |  | 
|  | nsres = nsIDOMNode_GetNodeType(nsnode, &type); | 
|  | if(NS_FAILED(nsres)) { | 
|  | ERR("GetType failed: %08x\n", nsres); | 
|  | return; | 
|  | } | 
|  |  | 
|  | switch(type) { | 
|  | case ELEMENT_NODE: { | 
|  | nsIDOMElement *nselem; | 
|  | nsIDOMNode_QueryInterface(nsnode, &IID_nsIDOMElement, (void**)&nselem); | 
|  | nsIContentSerializer_AppendElementStart(serializer, nselem, has_children, str); | 
|  | nsIDOMElement_Release(nselem); | 
|  | break; | 
|  | } | 
|  | case TEXT_NODE: { | 
|  | nsIDOMText *nstext; | 
|  | nsIDOMNode_QueryInterface(nsnode, &IID_nsIDOMText, (void**)&nstext); | 
|  | nsIContentSerializer_AppendText(serializer, nstext, 0, -1, str); | 
|  | nsIDOMText_Release(nstext); | 
|  | break; | 
|  | } | 
|  | case DOCUMENT_NODE: { | 
|  | nsIDOMDocument *nsdoc; | 
|  | nsIDOMNode_QueryInterface(nsnode, &IID_nsIDOMDocument, (void**)&nsdoc); | 
|  | nsIContentSerializer_AppendDocumentStart(serializer, nsdoc, str); | 
|  | nsIDOMDocument_Release(nsdoc); | 
|  | } | 
|  | default: | 
|  | FIXME("Unhandled type %u\n", type); | 
|  | } | 
|  |  | 
|  | if(has_children) { | 
|  | PRUint32 child_cnt, i; | 
|  | nsIDOMNode *child_node; | 
|  |  | 
|  | nsIDOMNode_GetChildNodes(nsnode, &node_list); | 
|  | nsIDOMNodeList_GetLength(node_list, &child_cnt); | 
|  |  | 
|  | for(i=0; i<child_cnt; i++) { | 
|  | nsres = nsIDOMNodeList_Item(node_list, i, &child_node); | 
|  | if(NS_SUCCEEDED(nsres)) { | 
|  | nsnode_to_nsstring_rec(serializer, child_node, str); | 
|  | nsIDOMNode_Release(child_node); | 
|  | }else { | 
|  | ERR("Item failed: %08x\n", nsres); | 
|  | } | 
|  | } | 
|  |  | 
|  | nsIDOMNodeList_Release(node_list); | 
|  | } | 
|  |  | 
|  | if(type == ELEMENT_NODE) { | 
|  | nsIDOMElement *nselem; | 
|  | nsIDOMNode_QueryInterface(nsnode, &IID_nsIDOMElement, (void**)&nselem); | 
|  | nsIContentSerializer_AppendElementEnd(serializer, nselem, str); | 
|  | nsIDOMElement_Release(nselem); | 
|  | } | 
|  | } | 
|  |  | 
|  | void nsnode_to_nsstring(nsIDOMNode *nsdoc, nsAString *str) | 
|  | { | 
|  | nsIContentSerializer *serializer; | 
|  | nsIDOMNode *nsnode; | 
|  | nsresult nsres; | 
|  |  | 
|  | nsres = nsIComponentManager_CreateInstanceByContractID(pCompMgr, | 
|  | NS_HTMLSERIALIZER_CONTRACTID, NULL, &IID_nsIContentSerializer, | 
|  | (void**)&serializer); | 
|  | if(NS_FAILED(nsres)) { | 
|  | ERR("Could not get nsIContentSerializer: %08x\n", nsres); | 
|  | return; | 
|  | } | 
|  |  | 
|  | nsres = nsIContentSerializer_Init(serializer, 0, 100, NULL, FALSE); | 
|  | if(NS_FAILED(nsres)) | 
|  | ERR("Init failed: %08x\n", nsres); | 
|  |  | 
|  | nsIDOMDocument_QueryInterface(nsdoc, &IID_nsIDOMNode, (void**)&nsnode); | 
|  | nsnode_to_nsstring_rec(serializer, nsnode, str); | 
|  | nsIDOMNode_Release(nsnode); | 
|  |  | 
|  | nsres = nsIContentSerializer_Flush(serializer, str); | 
|  | if(NS_FAILED(nsres)) | 
|  | ERR("Flush failed: %08x\n", nsres); | 
|  |  | 
|  | nsIContentSerializer_Release(serializer); | 
|  | } | 
|  |  | 
|  | void close_gecko() | 
|  | { | 
|  | TRACE("()\n"); | 
|  |  | 
|  | if(pCompMgr) | 
|  | nsIComponentManager_Release(pCompMgr); | 
|  |  | 
|  | if(pServMgr) | 
|  | nsIServiceManager_Release(pServMgr); | 
|  |  | 
|  | if(nsmem) | 
|  | nsIMemory_Release(nsmem); | 
|  |  | 
|  | if(hXPCOM) | 
|  | FreeLibrary(hXPCOM); | 
|  | } | 
|  |  | 
|  | /********************************************************** | 
|  | *      nsIWebBrowserChrome interface | 
|  | */ | 
|  |  | 
|  | #define NSWBCHROME_THIS(iface) DEFINE_THIS(NSContainer, WebBrowserChrome, iface) | 
|  |  | 
|  | static nsresult NSAPI nsWebBrowserChrome_QueryInterface(nsIWebBrowserChrome *iface, | 
|  | nsIIDRef riid, nsQIResult result) | 
|  | { | 
|  | NSContainer *This = NSWBCHROME_THIS(iface); | 
|  |  | 
|  | *result = NULL; | 
|  | if(IsEqualGUID(&IID_nsISupports, riid)) { | 
|  | TRACE("(%p)->(IID_nsISupports, %p)\n", This, result); | 
|  | *result = NSWBCHROME(This); | 
|  | }else if(IsEqualGUID(&IID_nsIWebBrowserChrome, riid)) { | 
|  | TRACE("(%p)->(IID_nsIWebBrowserChrome, %p)\n", This, result); | 
|  | *result = NSWBCHROME(This); | 
|  | }else if(IsEqualGUID(&IID_nsIContextMenuListener, riid)) { | 
|  | TRACE("(%p)->(IID_nsIContextMenuListener, %p)\n", This, result); | 
|  | *result = NSCML(This); | 
|  | }else if(IsEqualGUID(&IID_nsIURIContentListener, riid)) { | 
|  | TRACE("(%p)->(IID_nsIURIContentListener %p)\n", This, result); | 
|  | *result = NSURICL(This); | 
|  | }else if(IsEqualGUID(&IID_nsIEmbeddingSiteWindow, riid)) { | 
|  | TRACE("(%p)->(IID_nsIEmbeddingSiteWindow %p)\n", This, result); | 
|  | *result = NSEMBWNDS(This); | 
|  | }else if(IsEqualGUID(&IID_nsITooltipListener, riid)) { | 
|  | TRACE("(%p)->(IID_nsITooltipListener %p)\n", This, result); | 
|  | *result = NSTOOLTIP(This); | 
|  | }else if(IsEqualGUID(&IID_nsIInterfaceRequestor, riid)) { | 
|  | TRACE("(%p)->(IID_nsIInterfaceRequestor %p)\n", This, result); | 
|  | *result = NSIFACEREQ(This); | 
|  | }else if(IsEqualGUID(&IID_nsIWeakReference, riid)) { | 
|  | TRACE("(%p)->(IID_nsIWeakReference %p)\n", This, result); | 
|  | *result = NSWEAKREF(This); | 
|  | }else if(IsEqualGUID(&IID_nsISupportsWeakReference, riid)) { | 
|  | TRACE("(%p)->(IID_nsISupportsWeakReference %p)\n", This, result); | 
|  | *result = NSSUPWEAKREF(This); | 
|  | } | 
|  |  | 
|  | if(*result) { | 
|  | nsIWebBrowserChrome_AddRef(NSWBCHROME(This)); | 
|  | return NS_OK; | 
|  | } | 
|  |  | 
|  | TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), result); | 
|  | return NS_NOINTERFACE; | 
|  | } | 
|  |  | 
|  | static nsrefcnt NSAPI nsWebBrowserChrome_AddRef(nsIWebBrowserChrome *iface) | 
|  | { | 
|  | NSContainer *This = NSWBCHROME_THIS(iface); | 
|  | LONG ref = InterlockedIncrement(&This->ref); | 
|  |  | 
|  | TRACE("(%p) ref=%d\n", This, ref); | 
|  |  | 
|  | return ref; | 
|  | } | 
|  |  | 
|  | static nsrefcnt NSAPI nsWebBrowserChrome_Release(nsIWebBrowserChrome *iface) | 
|  | { | 
|  | NSContainer *This = NSWBCHROME_THIS(iface); | 
|  | LONG ref = InterlockedDecrement(&This->ref); | 
|  |  | 
|  | TRACE("(%p) ref=%d\n", This, ref); | 
|  |  | 
|  | if(!ref) { | 
|  | if(This->parent) | 
|  | nsIWebBrowserChrome_Release(NSWBCHROME(This->parent)); | 
|  | mshtml_free(This); | 
|  | } | 
|  |  | 
|  | return ref; | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsWebBrowserChrome_SetStatus(nsIWebBrowserChrome *iface, | 
|  | PRUint32 statusType, const PRUnichar *status) | 
|  | { | 
|  | NSContainer *This = NSWBCHROME_THIS(iface); | 
|  | TRACE("(%p)->(%d %s)\n", This, statusType, debugstr_w(status)); | 
|  | return NS_ERROR_NOT_IMPLEMENTED; | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsWebBrowserChrome_GetWebBrowser(nsIWebBrowserChrome *iface, | 
|  | nsIWebBrowser **aWebBrowser) | 
|  | { | 
|  | NSContainer *This = NSWBCHROME_THIS(iface); | 
|  |  | 
|  | TRACE("(%p)->(%p)\n", This, aWebBrowser); | 
|  |  | 
|  | if(!aWebBrowser) | 
|  | return NS_ERROR_INVALID_ARG; | 
|  |  | 
|  | if(This->webbrowser) | 
|  | nsIWebBrowser_AddRef(This->webbrowser); | 
|  | *aWebBrowser = This->webbrowser; | 
|  | return S_OK; | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsWebBrowserChrome_SetWebBrowser(nsIWebBrowserChrome *iface, | 
|  | nsIWebBrowser *aWebBrowser) | 
|  | { | 
|  | NSContainer *This = NSWBCHROME_THIS(iface); | 
|  |  | 
|  | TRACE("(%p)->(%p)\n", This, aWebBrowser); | 
|  |  | 
|  | if(aWebBrowser != This->webbrowser) | 
|  | ERR("Wrong nsWebBrowser!\n"); | 
|  |  | 
|  | return NS_OK; | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsWebBrowserChrome_GetChromeFlags(nsIWebBrowserChrome *iface, | 
|  | PRUint32 *aChromeFlags) | 
|  | { | 
|  | NSContainer *This = NSWBCHROME_THIS(iface); | 
|  | WARN("(%p)->(%p)\n", This, aChromeFlags); | 
|  | return NS_ERROR_NOT_IMPLEMENTED; | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsWebBrowserChrome_SetChromeFlags(nsIWebBrowserChrome *iface, | 
|  | PRUint32 aChromeFlags) | 
|  | { | 
|  | NSContainer *This = NSWBCHROME_THIS(iface); | 
|  | WARN("(%p)->(%08x)\n", This, aChromeFlags); | 
|  | return NS_ERROR_NOT_IMPLEMENTED; | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsWebBrowserChrome_DestroyBrowserWindow(nsIWebBrowserChrome *iface) | 
|  | { | 
|  | NSContainer *This = NSWBCHROME_THIS(iface); | 
|  | TRACE("(%p)\n", This); | 
|  | return NS_ERROR_NOT_IMPLEMENTED; | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsWebBrowserChrome_SizeBrowserTo(nsIWebBrowserChrome *iface, | 
|  | PRInt32 aCX, PRInt32 aCY) | 
|  | { | 
|  | NSContainer *This = NSWBCHROME_THIS(iface); | 
|  | WARN("(%p)->(%d %d)\n", This, aCX, aCY); | 
|  | return NS_ERROR_NOT_IMPLEMENTED; | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsWebBrowserChrome_ShowAsModal(nsIWebBrowserChrome *iface) | 
|  | { | 
|  | NSContainer *This = NSWBCHROME_THIS(iface); | 
|  | WARN("(%p)\n", This); | 
|  | return NS_ERROR_NOT_IMPLEMENTED; | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsWebBrowserChrome_IsWindowModal(nsIWebBrowserChrome *iface, PRBool *_retval) | 
|  | { | 
|  | NSContainer *This = NSWBCHROME_THIS(iface); | 
|  | WARN("(%p)->(%p)\n", This, _retval); | 
|  | return NS_ERROR_NOT_IMPLEMENTED; | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsWebBrowserChrome_ExitModalEventLoop(nsIWebBrowserChrome *iface, | 
|  | nsresult aStatus) | 
|  | { | 
|  | NSContainer *This = NSWBCHROME_THIS(iface); | 
|  | WARN("(%p)->(%08x)\n", This, aStatus); | 
|  | return NS_ERROR_NOT_IMPLEMENTED; | 
|  | } | 
|  |  | 
|  | #undef NSWBCHROME_THIS | 
|  |  | 
|  | static const nsIWebBrowserChromeVtbl nsWebBrowserChromeVtbl = { | 
|  | nsWebBrowserChrome_QueryInterface, | 
|  | nsWebBrowserChrome_AddRef, | 
|  | nsWebBrowserChrome_Release, | 
|  | nsWebBrowserChrome_SetStatus, | 
|  | nsWebBrowserChrome_GetWebBrowser, | 
|  | nsWebBrowserChrome_SetWebBrowser, | 
|  | nsWebBrowserChrome_GetChromeFlags, | 
|  | nsWebBrowserChrome_SetChromeFlags, | 
|  | nsWebBrowserChrome_DestroyBrowserWindow, | 
|  | nsWebBrowserChrome_SizeBrowserTo, | 
|  | nsWebBrowserChrome_ShowAsModal, | 
|  | nsWebBrowserChrome_IsWindowModal, | 
|  | nsWebBrowserChrome_ExitModalEventLoop | 
|  | }; | 
|  |  | 
|  | /********************************************************** | 
|  | *      nsIContextMenuListener interface | 
|  | */ | 
|  |  | 
|  | #define NSCML_THIS(iface) DEFINE_THIS(NSContainer, ContextMenuListener, iface) | 
|  |  | 
|  | static nsresult NSAPI nsContextMenuListener_QueryInterface(nsIContextMenuListener *iface, | 
|  | nsIIDRef riid, nsQIResult result) | 
|  | { | 
|  | NSContainer *This = NSCML_THIS(iface); | 
|  | return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result); | 
|  | } | 
|  |  | 
|  | static nsrefcnt NSAPI nsContextMenuListener_AddRef(nsIContextMenuListener *iface) | 
|  | { | 
|  | NSContainer *This = NSCML_THIS(iface); | 
|  | return nsIWebBrowserChrome_AddRef(NSWBCHROME(This)); | 
|  | } | 
|  |  | 
|  | static nsrefcnt NSAPI nsContextMenuListener_Release(nsIContextMenuListener *iface) | 
|  | { | 
|  | NSContainer *This = NSCML_THIS(iface); | 
|  | return nsIWebBrowserChrome_Release(NSWBCHROME(This)); | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsContextMenuListener_OnShowContextMenu(nsIContextMenuListener *iface, | 
|  | PRUint32 aContextFlags, nsIDOMEvent *aEvent, nsIDOMNode *aNode) | 
|  | { | 
|  | NSContainer *This = NSCML_THIS(iface); | 
|  | nsIDOMMouseEvent *event; | 
|  | POINT pt; | 
|  | DWORD dwID = CONTEXT_MENU_DEFAULT; | 
|  | nsresult nsres; | 
|  |  | 
|  | TRACE("(%p)->(%08x %p %p)\n", This, aContextFlags, aEvent, aNode); | 
|  |  | 
|  | nsres = nsIDOMEvent_QueryInterface(aEvent, &IID_nsIDOMMouseEvent, (void**)&event); | 
|  | if(NS_FAILED(nsres)) { | 
|  | ERR("Could not get nsIDOMMouseEvent interface: %08x\n", nsres); | 
|  | return nsres; | 
|  | } | 
|  |  | 
|  | nsIDOMMouseEvent_GetScreenX(event, &pt.x); | 
|  | nsIDOMMouseEvent_GetScreenY(event, &pt.y); | 
|  | nsIDOMMouseEvent_Release(event); | 
|  |  | 
|  | switch(aContextFlags) { | 
|  | case CONTEXT_NONE: | 
|  | case CONTEXT_DOCUMENT: | 
|  | case CONTEXT_TEXT: | 
|  | dwID = CONTEXT_MENU_DEFAULT; | 
|  | break; | 
|  | case CONTEXT_IMAGE: | 
|  | case CONTEXT_IMAGE|CONTEXT_LINK: | 
|  | dwID = CONTEXT_MENU_IMAGE; | 
|  | break; | 
|  | case CONTEXT_LINK: | 
|  | dwID = CONTEXT_MENU_ANCHOR; | 
|  | break; | 
|  | case CONTEXT_INPUT: | 
|  | dwID = CONTEXT_MENU_CONTROL; | 
|  | break; | 
|  | default: | 
|  | FIXME("aContextFlags=%08x\n", aContextFlags); | 
|  | }; | 
|  |  | 
|  | HTMLDocument_ShowContextMenu(This->doc, dwID, &pt); | 
|  |  | 
|  | return NS_OK; | 
|  | } | 
|  |  | 
|  | #undef NSCML_THIS | 
|  |  | 
|  | static const nsIContextMenuListenerVtbl nsContextMenuListenerVtbl = { | 
|  | nsContextMenuListener_QueryInterface, | 
|  | nsContextMenuListener_AddRef, | 
|  | nsContextMenuListener_Release, | 
|  | nsContextMenuListener_OnShowContextMenu | 
|  | }; | 
|  |  | 
|  | /********************************************************** | 
|  | *      nsIURIContentListener interface | 
|  | */ | 
|  |  | 
|  | #define NSURICL_THIS(iface) DEFINE_THIS(NSContainer, URIContentListener, iface) | 
|  |  | 
|  | static nsresult NSAPI nsURIContentListener_QueryInterface(nsIURIContentListener *iface, | 
|  | nsIIDRef riid, nsQIResult result) | 
|  | { | 
|  | NSContainer *This = NSURICL_THIS(iface); | 
|  | return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result); | 
|  | } | 
|  |  | 
|  | static nsrefcnt NSAPI nsURIContentListener_AddRef(nsIURIContentListener *iface) | 
|  | { | 
|  | NSContainer *This = NSURICL_THIS(iface); | 
|  | return nsIWebBrowserChrome_AddRef(NSWBCHROME(This)); | 
|  | } | 
|  |  | 
|  | static nsrefcnt NSAPI nsURIContentListener_Release(nsIURIContentListener *iface) | 
|  | { | 
|  | NSContainer *This = NSURICL_THIS(iface); | 
|  | return nsIWebBrowserChrome_Release(NSWBCHROME(This)); | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsURIContentListener_OnStartURIOpen(nsIURIContentListener *iface, | 
|  | nsIURI *aURI, PRBool *_retval) | 
|  | { | 
|  | NSContainer *This = NSURICL_THIS(iface); | 
|  | nsIWineURI *wine_uri; | 
|  | nsACString spec_str; | 
|  | const char *spec; | 
|  | nsresult nsres; | 
|  |  | 
|  | nsACString_Init(&spec_str, NULL); | 
|  | nsIURI_GetSpec(aURI, &spec_str); | 
|  | nsACString_GetData(&spec_str, &spec, NULL); | 
|  |  | 
|  | TRACE("(%p)->(%p(%s) %p)\n", This, aURI, debugstr_a(spec), _retval); | 
|  |  | 
|  | nsACString_Finish(&spec_str); | 
|  |  | 
|  | nsres = nsIURI_QueryInterface(aURI, &IID_nsIWineURI, (void**)&wine_uri); | 
|  | if(NS_FAILED(nsres)) { | 
|  | WARN("Could not get nsIWineURI interface: %08x\n", nsres); | 
|  | return NS_ERROR_NOT_IMPLEMENTED; | 
|  | } | 
|  |  | 
|  | nsIWineURI_SetNSContainer(wine_uri, This); | 
|  |  | 
|  | if(This->bscallback && This->bscallback->mon) { | 
|  | LPWSTR url = NULL; | 
|  | HRESULT hres; | 
|  |  | 
|  | hres = IMoniker_GetDisplayName(This->bscallback->mon, NULL, 0, &url); | 
|  | if(SUCCEEDED(hres)) { | 
|  | IMoniker *mon = NULL; | 
|  |  | 
|  | hres = CreateURLMoniker(NULL, url, &mon); | 
|  | if(SUCCEEDED(hres)) { | 
|  | nsIWineURI_SetMoniker(wine_uri, mon); | 
|  | IMoniker_Release(mon); | 
|  | }else { | 
|  | WARN("CreateURLMoniker failed: %08x\n", hres); | 
|  | } | 
|  | }else { | 
|  | WARN("GetDisplayName failed: %08x\n", hres); | 
|  | } | 
|  | } | 
|  |  | 
|  | nsIWineURI_Release(wine_uri); | 
|  |  | 
|  | *_retval = FALSE; | 
|  | return This->content_listener | 
|  | ? nsIURIContentListener_OnStartURIOpen(This->content_listener, aURI, _retval) | 
|  | : NS_OK; | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsURIContentListener_DoContent(nsIURIContentListener *iface, | 
|  | const char *aContentType, PRBool aIsContentPreferred, nsIRequest *aRequest, | 
|  | nsIStreamListener **aContentHandler, PRBool *_retval) | 
|  | { | 
|  | NSContainer *This = NSURICL_THIS(iface); | 
|  |  | 
|  | TRACE("(%p)->(%s %x %p %p %p)\n", This, debugstr_a(aContentType), aIsContentPreferred, | 
|  | aRequest, aContentHandler, _retval); | 
|  |  | 
|  | return This->content_listener | 
|  | ? nsIURIContentListener_DoContent(This->content_listener, aContentType, | 
|  | aIsContentPreferred, aRequest, aContentHandler, _retval) | 
|  | : NS_ERROR_NOT_IMPLEMENTED; | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsURIContentListener_IsPreferred(nsIURIContentListener *iface, | 
|  | const char *aContentType, char **aDesiredContentType, PRBool *_retval) | 
|  | { | 
|  | NSContainer *This = NSURICL_THIS(iface); | 
|  |  | 
|  | TRACE("(%p)->(%s %p %p)\n", This, debugstr_a(aContentType), aDesiredContentType, _retval); | 
|  |  | 
|  | /* FIXME: Should we do something here? */ | 
|  | *_retval = TRUE; | 
|  |  | 
|  | return This->content_listener | 
|  | ? nsIURIContentListener_IsPreferred(This->content_listener, aContentType, | 
|  | aDesiredContentType, _retval) | 
|  | : NS_OK; | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsURIContentListener_CanHandleContent(nsIURIContentListener *iface, | 
|  | const char *aContentType, PRBool aIsContentPreferred, char **aDesiredContentType, | 
|  | PRBool *_retval) | 
|  | { | 
|  | NSContainer *This = NSURICL_THIS(iface); | 
|  |  | 
|  | TRACE("(%p)->(%s %x %p %p)\n", This, debugstr_a(aContentType), aIsContentPreferred, | 
|  | aDesiredContentType, _retval); | 
|  |  | 
|  | return This->content_listener | 
|  | ? nsIURIContentListener_CanHandleContent(This->content_listener, aContentType, | 
|  | aIsContentPreferred, aDesiredContentType, _retval) | 
|  | : NS_ERROR_NOT_IMPLEMENTED; | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsURIContentListener_GetLoadCookie(nsIURIContentListener *iface, | 
|  | nsISupports **aLoadCookie) | 
|  | { | 
|  | NSContainer *This = NSURICL_THIS(iface); | 
|  |  | 
|  | WARN("(%p)->(%p)\n", This, aLoadCookie); | 
|  |  | 
|  | return This->content_listener | 
|  | ? nsIURIContentListener_GetLoadCookie(This->content_listener, aLoadCookie) | 
|  | : NS_ERROR_NOT_IMPLEMENTED; | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsURIContentListener_SetLoadCookie(nsIURIContentListener *iface, | 
|  | nsISupports *aLoadCookie) | 
|  | { | 
|  | NSContainer *This = NSURICL_THIS(iface); | 
|  |  | 
|  | WARN("(%p)->(%p)\n", This, aLoadCookie); | 
|  |  | 
|  | return This->content_listener | 
|  | ? nsIURIContentListener_SetLoadCookie(This->content_listener, aLoadCookie) | 
|  | : NS_ERROR_NOT_IMPLEMENTED; | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsURIContentListener_GetParentContentListener(nsIURIContentListener *iface, | 
|  | nsIURIContentListener **aParentContentListener) | 
|  | { | 
|  | NSContainer *This = NSURICL_THIS(iface); | 
|  |  | 
|  | TRACE("(%p)->(%p)\n", This, aParentContentListener); | 
|  |  | 
|  | if(This->content_listener) | 
|  | nsIURIContentListener_AddRef(This->content_listener); | 
|  |  | 
|  | *aParentContentListener = This->content_listener; | 
|  | return NS_OK; | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsURIContentListener_SetParentContentListener(nsIURIContentListener *iface, | 
|  | nsIURIContentListener *aParentContentListener) | 
|  | { | 
|  | NSContainer *This = NSURICL_THIS(iface); | 
|  |  | 
|  | TRACE("(%p)->(%p)\n", This, aParentContentListener); | 
|  |  | 
|  | if(aParentContentListener == NSURICL(This)) | 
|  | return NS_OK; | 
|  |  | 
|  | if(This->content_listener) | 
|  | nsIURIContentListener_Release(This->content_listener); | 
|  |  | 
|  | This->content_listener = aParentContentListener; | 
|  | if(This->content_listener) | 
|  | nsIURIContentListener_AddRef(This->content_listener); | 
|  |  | 
|  | return NS_OK; | 
|  | } | 
|  |  | 
|  | #undef NSURICL_THIS | 
|  |  | 
|  | static const nsIURIContentListenerVtbl nsURIContentListenerVtbl = { | 
|  | nsURIContentListener_QueryInterface, | 
|  | nsURIContentListener_AddRef, | 
|  | nsURIContentListener_Release, | 
|  | nsURIContentListener_OnStartURIOpen, | 
|  | nsURIContentListener_DoContent, | 
|  | nsURIContentListener_IsPreferred, | 
|  | nsURIContentListener_CanHandleContent, | 
|  | nsURIContentListener_GetLoadCookie, | 
|  | nsURIContentListener_SetLoadCookie, | 
|  | nsURIContentListener_GetParentContentListener, | 
|  | nsURIContentListener_SetParentContentListener | 
|  | }; | 
|  |  | 
|  | /********************************************************** | 
|  | *      nsIEmbeddinSiteWindow interface | 
|  | */ | 
|  |  | 
|  | #define NSEMBWNDS_THIS(iface) DEFINE_THIS(NSContainer, EmbeddingSiteWindow, iface) | 
|  |  | 
|  | static nsresult NSAPI nsEmbeddingSiteWindow_QueryInterface(nsIEmbeddingSiteWindow *iface, | 
|  | nsIIDRef riid, nsQIResult result) | 
|  | { | 
|  | NSContainer *This = NSEMBWNDS_THIS(iface); | 
|  | return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result); | 
|  | } | 
|  |  | 
|  | static nsrefcnt NSAPI nsEmbeddingSiteWindow_AddRef(nsIEmbeddingSiteWindow *iface) | 
|  | { | 
|  | NSContainer *This = NSEMBWNDS_THIS(iface); | 
|  | return nsIWebBrowserChrome_AddRef(NSWBCHROME(This)); | 
|  | } | 
|  |  | 
|  | static nsrefcnt NSAPI nsEmbeddingSiteWindow_Release(nsIEmbeddingSiteWindow *iface) | 
|  | { | 
|  | NSContainer *This = NSEMBWNDS_THIS(iface); | 
|  | return nsIWebBrowserChrome_Release(NSWBCHROME(This)); | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsEmbeddingSiteWindow_SetDimensions(nsIEmbeddingSiteWindow *iface, | 
|  | PRUint32 flags, PRInt32 x, PRInt32 y, PRInt32 cx, PRInt32 cy) | 
|  | { | 
|  | NSContainer *This = NSEMBWNDS_THIS(iface); | 
|  | WARN("(%p)->(%08x %d %d %d %d)\n", This, flags, x, y, cx, cy); | 
|  | return NS_ERROR_NOT_IMPLEMENTED; | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsEmbeddingSiteWindow_GetDimensions(nsIEmbeddingSiteWindow *iface, | 
|  | PRUint32 flags, PRInt32 *x, PRInt32 *y, PRInt32 *cx, PRInt32 *cy) | 
|  | { | 
|  | NSContainer *This = NSEMBWNDS_THIS(iface); | 
|  | WARN("(%p)->(%08x %p %p %p %p)\n", This, flags, x, y, cx, cy); | 
|  | return NS_ERROR_NOT_IMPLEMENTED; | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsEmbeddingSiteWindow_SetFocus(nsIEmbeddingSiteWindow *iface) | 
|  | { | 
|  | NSContainer *This = NSEMBWNDS_THIS(iface); | 
|  | WARN("(%p)\n", This); | 
|  | return NS_ERROR_NOT_IMPLEMENTED; | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsEmbeddingSiteWindow_GetVisibility(nsIEmbeddingSiteWindow *iface, | 
|  | PRBool *aVisibility) | 
|  | { | 
|  | NSContainer *This = NSEMBWNDS_THIS(iface); | 
|  | WARN("(%p)->(%p)\n", This, aVisibility); | 
|  | return NS_ERROR_NOT_IMPLEMENTED; | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsEmbeddingSiteWindow_SetVisibility(nsIEmbeddingSiteWindow *iface, | 
|  | PRBool aVisibility) | 
|  | { | 
|  | NSContainer *This = NSEMBWNDS_THIS(iface); | 
|  | WARN("(%p)->(%x)\n", This, aVisibility); | 
|  | return NS_ERROR_NOT_IMPLEMENTED; | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsEmbeddingSiteWindow_GetTitle(nsIEmbeddingSiteWindow *iface, | 
|  | PRUnichar **aTitle) | 
|  | { | 
|  | NSContainer *This = NSEMBWNDS_THIS(iface); | 
|  | WARN("(%p)->(%p)\n", This, aTitle); | 
|  | return NS_ERROR_NOT_IMPLEMENTED; | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsEmbeddingSiteWindow_SetTitle(nsIEmbeddingSiteWindow *iface, | 
|  | const PRUnichar *aTitle) | 
|  | { | 
|  | NSContainer *This = NSEMBWNDS_THIS(iface); | 
|  | WARN("(%p)->(%s)\n", This, debugstr_w(aTitle)); | 
|  | return NS_ERROR_NOT_IMPLEMENTED; | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsEmbeddingSiteWindow_GetSiteWindow(nsIEmbeddingSiteWindow *iface, | 
|  | void **aSiteWindow) | 
|  | { | 
|  | NSContainer *This = NSEMBWNDS_THIS(iface); | 
|  |  | 
|  | TRACE("(%p)->(%p)\n", This, aSiteWindow); | 
|  |  | 
|  | *aSiteWindow = This->hwnd; | 
|  | return NS_OK; | 
|  | } | 
|  |  | 
|  | static const nsIEmbeddingSiteWindowVtbl nsEmbeddingSiteWindowVtbl = { | 
|  | nsEmbeddingSiteWindow_QueryInterface, | 
|  | nsEmbeddingSiteWindow_AddRef, | 
|  | nsEmbeddingSiteWindow_Release, | 
|  | nsEmbeddingSiteWindow_SetDimensions, | 
|  | nsEmbeddingSiteWindow_GetDimensions, | 
|  | nsEmbeddingSiteWindow_SetFocus, | 
|  | nsEmbeddingSiteWindow_GetVisibility, | 
|  | nsEmbeddingSiteWindow_SetVisibility, | 
|  | nsEmbeddingSiteWindow_GetTitle, | 
|  | nsEmbeddingSiteWindow_SetTitle, | 
|  | nsEmbeddingSiteWindow_GetSiteWindow | 
|  | }; | 
|  |  | 
|  | #define NSTOOLTIP_THIS(iface) DEFINE_THIS(NSContainer, TooltipListener, iface) | 
|  |  | 
|  | static nsresult NSAPI nsTooltipListener_QueryInterface(nsITooltipListener *iface, nsIIDRef riid, | 
|  | nsQIResult result) | 
|  | { | 
|  | NSContainer *This = NSTOOLTIP_THIS(iface); | 
|  | return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result); | 
|  | } | 
|  |  | 
|  | static nsrefcnt NSAPI nsTooltipListener_AddRef(nsITooltipListener *iface) | 
|  | { | 
|  | NSContainer *This = NSTOOLTIP_THIS(iface); | 
|  | return nsIWebBrowserChrome_AddRef(NSWBCHROME(This)); | 
|  | } | 
|  |  | 
|  | static nsrefcnt NSAPI nsTooltipListener_Release(nsITooltipListener *iface) | 
|  | { | 
|  | NSContainer *This = NSTOOLTIP_THIS(iface); | 
|  | return nsIWebBrowserChrome_AddRef(NSWBCHROME(This)); | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsTooltipListener_OnShowTooltip(nsITooltipListener *iface, | 
|  | PRInt32 aXCoord, PRInt32 aYCoord, const PRUnichar *aTipText) | 
|  | { | 
|  | NSContainer *This = NSTOOLTIP_THIS(iface); | 
|  |  | 
|  | show_tooltip(This->doc, aXCoord, aYCoord, aTipText); | 
|  |  | 
|  | return NS_OK; | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsTooltipListener_OnHideTooltip(nsITooltipListener *iface) | 
|  | { | 
|  | NSContainer *This = NSTOOLTIP_THIS(iface); | 
|  |  | 
|  | hide_tooltip(This->doc); | 
|  |  | 
|  | return NS_OK; | 
|  | } | 
|  |  | 
|  | #undef NSTOOLTIM_THIS | 
|  |  | 
|  | static const nsITooltipListenerVtbl nsTooltipListenerVtbl = { | 
|  | nsTooltipListener_QueryInterface, | 
|  | nsTooltipListener_AddRef, | 
|  | nsTooltipListener_Release, | 
|  | nsTooltipListener_OnShowTooltip, | 
|  | nsTooltipListener_OnHideTooltip | 
|  | }; | 
|  |  | 
|  | #define NSIFACEREQ_THIS(iface) DEFINE_THIS(NSContainer, InterfaceRequestor, iface) | 
|  |  | 
|  | static nsresult NSAPI nsInterfaceRequestor_QueryInterface(nsIInterfaceRequestor *iface, | 
|  | nsIIDRef riid, nsQIResult result) | 
|  | { | 
|  | NSContainer *This = NSIFACEREQ_THIS(iface); | 
|  | return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result); | 
|  | } | 
|  |  | 
|  | static nsrefcnt NSAPI nsInterfaceRequestor_AddRef(nsIInterfaceRequestor *iface) | 
|  | { | 
|  | NSContainer *This = NSIFACEREQ_THIS(iface); | 
|  | return nsIWebBrowserChrome_AddRef(NSWBCHROME(This)); | 
|  | } | 
|  |  | 
|  | static nsrefcnt NSAPI nsInterfaceRequestor_Release(nsIInterfaceRequestor *iface) | 
|  | { | 
|  | NSContainer *This = NSIFACEREQ_THIS(iface); | 
|  | return nsIWebBrowserChrome_Release(NSWBCHROME(This)); | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsInterfaceRequestor_GetInterface(nsIInterfaceRequestor *iface, | 
|  | nsIIDRef riid, nsQIResult result) | 
|  | { | 
|  | NSContainer *This = NSIFACEREQ_THIS(iface); | 
|  |  | 
|  | if(IsEqualGUID(&IID_nsIDOMWindow, riid)) { | 
|  | TRACE("(%p)->(IID_nsIDOMWindow %p)\n", This, result); | 
|  | return nsIWebBrowser_GetContentDOMWindow(This->webbrowser, (nsIDOMWindow**)result); | 
|  | } | 
|  |  | 
|  | return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result); | 
|  | } | 
|  |  | 
|  | #undef NSIFACEREQ_THIS | 
|  |  | 
|  | static const nsIInterfaceRequestorVtbl nsInterfaceRequestorVtbl = { | 
|  | nsInterfaceRequestor_QueryInterface, | 
|  | nsInterfaceRequestor_AddRef, | 
|  | nsInterfaceRequestor_Release, | 
|  | nsInterfaceRequestor_GetInterface | 
|  | }; | 
|  |  | 
|  | #define NSWEAKREF_THIS(iface) DEFINE_THIS(NSContainer, WeakReference, iface) | 
|  |  | 
|  | static nsresult NSAPI nsWeakReference_QueryInterface(nsIWeakReference *iface, | 
|  | nsIIDRef riid, nsQIResult result) | 
|  | { | 
|  | NSContainer *This = NSWEAKREF_THIS(iface); | 
|  | return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result); | 
|  | } | 
|  |  | 
|  | static nsrefcnt NSAPI nsWeakReference_AddRef(nsIWeakReference *iface) | 
|  | { | 
|  | NSContainer *This = NSWEAKREF_THIS(iface); | 
|  | return nsIWebBrowserChrome_AddRef(NSWBCHROME(This)); | 
|  | } | 
|  |  | 
|  | static nsrefcnt NSAPI nsWeakReference_Release(nsIWeakReference *iface) | 
|  | { | 
|  | NSContainer *This = NSWEAKREF_THIS(iface); | 
|  | return nsIWebBrowserChrome_Release(NSWBCHROME(This)); | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsWeakReference_QueryReferent(nsIWeakReference *iface, | 
|  | const nsIID *riid, void **result) | 
|  | { | 
|  | NSContainer *This = NSWEAKREF_THIS(iface); | 
|  | return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result); | 
|  | } | 
|  |  | 
|  | #undef NSWEAKREF_THIS | 
|  |  | 
|  | static const nsIWeakReferenceVtbl nsWeakReferenceVtbl = { | 
|  | nsWeakReference_QueryInterface, | 
|  | nsWeakReference_AddRef, | 
|  | nsWeakReference_Release, | 
|  | nsWeakReference_QueryReferent | 
|  | }; | 
|  |  | 
|  | #define NSSUPWEAKREF_THIS(iface) DEFINE_THIS(NSContainer, SupportsWeakReference, iface) | 
|  |  | 
|  | static nsresult NSAPI nsSupportsWeakReference_QueryInterface(nsISupportsWeakReference *iface, | 
|  | nsIIDRef riid, nsQIResult result) | 
|  | { | 
|  | NSContainer *This = NSSUPWEAKREF_THIS(iface); | 
|  | return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result); | 
|  | } | 
|  |  | 
|  | static nsrefcnt NSAPI nsSupportsWeakReference_AddRef(nsISupportsWeakReference *iface) | 
|  | { | 
|  | NSContainer *This = NSSUPWEAKREF_THIS(iface); | 
|  | return nsIWebBrowserChrome_AddRef(NSWBCHROME(This)); | 
|  | } | 
|  |  | 
|  | static nsrefcnt NSAPI nsSupportsWeakReference_Release(nsISupportsWeakReference *iface) | 
|  | { | 
|  | NSContainer *This = NSSUPWEAKREF_THIS(iface); | 
|  | return nsIWebBrowserChrome_Release(NSWBCHROME(This)); | 
|  | } | 
|  |  | 
|  | static nsresult NSAPI nsSupportsWeakReference_GetWeakReference(nsISupportsWeakReference *iface, | 
|  | nsIWeakReference **_retval) | 
|  | { | 
|  | NSContainer *This = NSSUPWEAKREF_THIS(iface); | 
|  |  | 
|  | TRACE("(%p)->(%p)\n", This, _retval); | 
|  |  | 
|  | nsIWeakReference_AddRef(NSWEAKREF(This)); | 
|  | *_retval = NSWEAKREF(This); | 
|  | return NS_OK; | 
|  | } | 
|  |  | 
|  | #undef NSWEAKREF_THIS | 
|  |  | 
|  | const nsISupportsWeakReferenceVtbl nsSupportsWeakReferenceVtbl = { | 
|  | nsSupportsWeakReference_QueryInterface, | 
|  | nsSupportsWeakReference_AddRef, | 
|  | nsSupportsWeakReference_Release, | 
|  | nsSupportsWeakReference_GetWeakReference | 
|  | }; | 
|  |  | 
|  |  | 
|  | NSContainer *NSContainer_Create(HTMLDocument *doc, NSContainer *parent) | 
|  | { | 
|  | nsIWebBrowserSetup *wbsetup; | 
|  | NSContainer *ret; | 
|  | nsresult nsres; | 
|  |  | 
|  | if(!load_gecko()) | 
|  | return NULL; | 
|  |  | 
|  | ret = mshtml_alloc(sizeof(NSContainer)); | 
|  |  | 
|  | ret->lpWebBrowserChromeVtbl      = &nsWebBrowserChromeVtbl; | 
|  | ret->lpContextMenuListenerVtbl   = &nsContextMenuListenerVtbl; | 
|  | ret->lpURIContentListenerVtbl    = &nsURIContentListenerVtbl; | 
|  | ret->lpEmbeddingSiteWindowVtbl   = &nsEmbeddingSiteWindowVtbl; | 
|  | ret->lpTooltipListenerVtbl       = &nsTooltipListenerVtbl; | 
|  | ret->lpInterfaceRequestorVtbl    = &nsInterfaceRequestorVtbl; | 
|  | ret->lpWeakReferenceVtbl         = &nsWeakReferenceVtbl; | 
|  | ret->lpSupportsWeakReferenceVtbl = &nsSupportsWeakReferenceVtbl; | 
|  |  | 
|  |  | 
|  | ret->doc = doc; | 
|  | ret->ref = 1; | 
|  | ret->bscallback = NULL; | 
|  | ret->content_listener = NULL; | 
|  |  | 
|  | if(parent) | 
|  | nsIWebBrowserChrome_AddRef(NSWBCHROME(parent)); | 
|  | ret->parent = parent; | 
|  |  | 
|  | nsres = nsIComponentManager_CreateInstanceByContractID(pCompMgr, NS_WEBBROWSER_CONTRACTID, | 
|  | NULL, &IID_nsIWebBrowser, (void**)&ret->webbrowser); | 
|  | if(NS_FAILED(nsres)) | 
|  | ERR("Creating WebBrowser failed: %08x\n", nsres); | 
|  |  | 
|  | nsres = nsIWebBrowser_SetContainerWindow(ret->webbrowser, NSWBCHROME(ret)); | 
|  | if(NS_FAILED(nsres)) | 
|  | ERR("SetContainerWindow failed: %08x\n", nsres); | 
|  |  | 
|  | nsres = nsIWebBrowser_QueryInterface(ret->webbrowser, &IID_nsIBaseWindow, | 
|  | (void**)&ret->window); | 
|  | if(NS_FAILED(nsres)) | 
|  | ERR("Could not get nsIBaseWindow interface: %08x\n", nsres); | 
|  |  | 
|  | nsres = nsIWebBrowser_QueryInterface(ret->webbrowser, &IID_nsIWebBrowserSetup, | 
|  | (void**)&wbsetup); | 
|  | if(NS_SUCCEEDED(nsres)) { | 
|  | nsres = nsIWebBrowserSetup_SetProperty(wbsetup, SETUP_IS_CHROME_WRAPPER, TRUE); | 
|  | nsIWebBrowserSetup_Release(wbsetup); | 
|  | if(NS_FAILED(nsres)) | 
|  | ERR("SetProperty(SETUP_IS_CHROME_WRAPPER) failed: %08x\n", nsres); | 
|  | }else { | 
|  | ERR("Could not get nsIWebBrowserSetup interface\n"); | 
|  | } | 
|  |  | 
|  | nsres = nsIWebBrowser_QueryInterface(ret->webbrowser, &IID_nsIWebNavigation, | 
|  | (void**)&ret->navigation); | 
|  | if(NS_FAILED(nsres)) | 
|  | ERR("Could not get nsIWebNavigation interface: %08x\n", nsres); | 
|  |  | 
|  | nsres = nsIWebBrowserFocus_QueryInterface(ret->webbrowser, &IID_nsIWebBrowserFocus, | 
|  | (void**)&ret->focus); | 
|  | if(NS_FAILED(nsres)) | 
|  | ERR("Could not get nsIWebBrowserFocus interface: %08x\n", nsres); | 
|  |  | 
|  | if(!nscontainer_class) | 
|  | register_nscontainer_class(); | 
|  |  | 
|  | ret->hwnd = CreateWindowExW(0, wszNsContainer, NULL, | 
|  | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0, 0, 100, 100, | 
|  | GetDesktopWindow(), NULL, hInst, ret); | 
|  |  | 
|  | nsres = nsIBaseWindow_InitWindow(ret->window, ret->hwnd, NULL, 0, 0, 100, 100); | 
|  | if(NS_SUCCEEDED(nsres)) { | 
|  | nsres = nsIBaseWindow_Create(ret->window); | 
|  | if(NS_FAILED(nsres)) | 
|  | WARN("Creating window failed: %08x\n", nsres); | 
|  |  | 
|  | nsIBaseWindow_SetVisibility(ret->window, FALSE); | 
|  | nsIBaseWindow_SetEnabled(ret->window, FALSE); | 
|  | }else { | 
|  | ERR("InitWindow failed: %08x\n", nsres); | 
|  | } | 
|  |  | 
|  | nsres = nsIWebBrowser_SetParentURIContentListener(ret->webbrowser, NSURICL(ret)); | 
|  | if(NS_FAILED(nsres)) | 
|  | ERR("SetParentURIContentListener failed: %08x\n", nsres); | 
|  |  | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | void NSContainer_Release(NSContainer *This) | 
|  | { | 
|  | TRACE("(%p)\n", This); | 
|  |  | 
|  | ShowWindow(This->hwnd, SW_HIDE); | 
|  | SetParent(This->hwnd, NULL); | 
|  |  | 
|  | nsIBaseWindow_SetVisibility(This->window, FALSE); | 
|  | nsIBaseWindow_Destroy(This->window); | 
|  |  | 
|  | nsIWebBrowser_SetContainerWindow(This->webbrowser, NULL); | 
|  |  | 
|  | nsIWebBrowser_Release(This->webbrowser); | 
|  | This->webbrowser = NULL; | 
|  |  | 
|  | nsIWebNavigation_Release(This->navigation); | 
|  | This->navigation = NULL; | 
|  |  | 
|  | nsIBaseWindow_Release(This->window); | 
|  | This->window = NULL; | 
|  |  | 
|  | nsIWebBrowserFocus_Release(This->focus); | 
|  | This->focus = NULL; | 
|  |  | 
|  | if(This->content_listener) { | 
|  | nsIURIContentListener_Release(This->content_listener); | 
|  | This->content_listener = NULL; | 
|  | } | 
|  |  | 
|  | if(This->hwnd) { | 
|  | DestroyWindow(This->hwnd); | 
|  | This->hwnd = NULL; | 
|  | } | 
|  |  | 
|  | nsIWebBrowserChrome_Release(NSWBCHROME(This)); | 
|  | } |