mshtml: Refactor Gecko loading code.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
stable
Jacek Caban 2019-12-09 17:04:22 +01:00 committed by Alexandre Julliard
parent d393681e41
commit ba462a0660
1 changed files with 132 additions and 139 deletions

View File

@ -432,6 +432,8 @@ static BOOL install_wine_gecko(void)
CloseHandle(pi.hThread);
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
}else {
WARN("installation failed\n");
}
return ret;
@ -483,139 +485,6 @@ static void set_environment(LPCWSTR gre_path)
heap_free(path);
}
static BOOL load_xul(const PRUnichar *gre_path)
{
static const WCHAR xul_dllW[] = {'\\','x','u','l','.','d','l','l',0};
WCHAR file_name[MAX_PATH];
lstrcpyW(file_name, gre_path);
lstrcatW(file_name, xul_dllW);
TRACE("(%s)\n", debugstr_w(file_name));
set_environment(gre_path);
xul_handle = LoadLibraryExW(file_name, 0, LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR);
if(!xul_handle) {
WARN("Could not load XUL: %d\n", GetLastError());
return FALSE;
}
#define NS_DLSYM(func) \
func = (void *)GetProcAddress(xul_handle, #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_StringContainerInit2);
NS_DLSYM(NS_CStringContainerInit2);
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);
NS_DLSYM(NS_StringGetIsVoid);
NS_DLSYM(NS_Alloc);
NS_DLSYM(NS_Free);
NS_DLSYM(ccref_incr);
NS_DLSYM(ccref_decr);
NS_DLSYM(ccref_init);
NS_DLSYM(ccp_init);
NS_DLSYM(describe_cc_node);
NS_DLSYM(note_cc_edge);
#undef NS_DLSYM
return TRUE;
}
static BOOL check_version(LPCWSTR gre_path, const char *version_string)
{
WCHAR file_name[MAX_PATH];
char version[128];
DWORD read=0;
HANDLE hfile;
static const WCHAR wszVersion[] = {'\\','V','E','R','S','I','O','N',0};
lstrcpyW(file_name, gre_path);
lstrcatW(file_name, wszVersion);
hfile = CreateFileW(file_name, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(hfile == INVALID_HANDLE_VALUE) {
ERR("Could not open VERSION file\n");
return FALSE;
}
ReadFile(hfile, version, sizeof(version), &read, NULL);
version[read] = 0;
CloseHandle(hfile);
TRACE("%s\n", debugstr_a(version));
if(strcmp(version, version_string)) {
ERR("Unexpected version %s, expected %s\n", debugstr_a(version),
debugstr_a(version_string));
return FALSE;
}
return TRUE;
}
static BOOL load_wine_gecko_v(PRUnichar *gre_path, HKEY mshtml_key,
const char *version, const char *version_string)
{
DWORD res, type, size = MAX_PATH;
HKEY hkey = mshtml_key;
static const WCHAR wszGeckoPath[] =
{'G','e','c','k','o','P','a','t','h',0};
if(version) {
/* @@ Wine registry key: HKLM\Software\Wine\MSHTML\<version> */
res = RegOpenKeyA(mshtml_key, version, &hkey);
if(res != ERROR_SUCCESS)
return FALSE;
}
res = RegQueryValueExW(hkey, wszGeckoPath, NULL, &type, (LPBYTE)gre_path, &size);
if(hkey != mshtml_key)
RegCloseKey(hkey);
if(res != ERROR_SUCCESS || type != REG_SZ)
return FALSE;
if(!check_version(gre_path, version_string))
return FALSE;
return load_xul(gre_path);
}
static BOOL load_wine_gecko(PRUnichar *gre_path)
{
HKEY hkey;
DWORD res;
BOOL ret;
static const WCHAR wszMshtmlKey[] = {
'S','o','f','t','w','a','r','e','\\','W','i','n','e',
'\\','M','S','H','T','M','L',0};
/* @@ Wine registry key: HKLM\Software\Wine\MSHTML */
res = RegOpenKeyW(HKEY_LOCAL_MACHINE, wszMshtmlKey, &hkey);
if(res != ERROR_SUCCESS)
return FALSE;
ret = load_wine_gecko_v(gre_path, hkey, GECKO_VERSION, GECKO_VERSION_STRING);
RegCloseKey(hkey);
return ret;
}
static void set_bool_pref(nsIPrefBranch *pref, const char *pref_name, BOOL val)
{
nsresult nsres;
@ -743,6 +612,124 @@ static BOOL init_xpcom(const PRUnichar *gre_path)
return TRUE;
}
static BOOL load_xul(WCHAR *gecko_path)
{
size_t len;
set_environment(gecko_path);
TRACE("(%s)\n", debugstr_w(gecko_path));
len = wcslen(gecko_path);
wcscpy(gecko_path + len, L"\\xul.dll");
xul_handle = LoadLibraryExW(gecko_path, 0, LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR);
gecko_path[len] = 0;
if(!xul_handle) {
WARN("Could not load XUL: %d\n", GetLastError());
return FALSE;
}
#define NS_DLSYM(func) \
func = (void *)GetProcAddress(xul_handle, #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_StringContainerInit2);
NS_DLSYM(NS_CStringContainerInit2);
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);
NS_DLSYM(NS_StringGetIsVoid);
NS_DLSYM(NS_Alloc);
NS_DLSYM(NS_Free);
NS_DLSYM(ccref_incr);
NS_DLSYM(ccref_decr);
NS_DLSYM(ccref_init);
NS_DLSYM(ccp_init);
NS_DLSYM(describe_cc_node);
NS_DLSYM(note_cc_edge);
#undef NS_DLSYM
return init_xpcom(gecko_path);
}
static WCHAR *check_version(const WCHAR *path)
{
WCHAR *file_name;
char version[128];
DWORD read=0;
size_t len;
HANDLE hfile;
if(!wcsncmp(path, L"\\??\\", 4))
path += 4;
if(path[1] != ':') {
TRACE("Skipping %s\n", debugstr_w(path));
return FALSE; /* Gecko needs to be accessible via dos path */
}
len = wcslen(path);
file_name = heap_alloc((len + 12) * sizeof(WCHAR));
if(!file_name)
return NULL;
PathCanonicalizeW(file_name, path);
len = lstrlenW(file_name);
wcscpy(file_name + len, L"\\VERSION");
hfile = CreateFileW(file_name, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
file_name[len] = 0;
if(hfile == INVALID_HANDLE_VALUE) {
TRACE("%s not found\n", debugstr_w(file_name));
heap_free(file_name);
return NULL;
}
ReadFile(hfile, version, sizeof(version), &read, NULL);
version[read] = 0;
CloseHandle(hfile);
TRACE("%s: %s\n", debugstr_w(file_name), debugstr_a(version));
if(strcmp(version, GECKO_VERSION_STRING)) {
ERR("Unexpected version %s, expected \"%s\"\n", debugstr_a(version),
GECKO_VERSION_STRING);
heap_free(file_name);
return NULL;
}
return file_name;
}
static WCHAR *find_wine_gecko_reg(void)
{
WCHAR buffer[MAX_PATH];
DWORD res, type, size;
HKEY hkey;
/* @@ Wine registry key: HKLM\Software\Wine\MSHTML\<version> */
res = RegOpenKeyW(HKEY_LOCAL_MACHINE, L"Software\\Wine\\MSHTML\\" GECKO_VERSION, &hkey);
if(res != ERROR_SUCCESS)
return NULL;
size = ARRAY_SIZE(buffer);
res = RegQueryValueExW(hkey, L"GeckoPath", NULL, &type, (LPBYTE)buffer, &size);
RegCloseKey(hkey);
if(res != ERROR_SUCCESS || type != REG_SZ)
return FALSE;
return check_version(buffer);
}
static CRITICAL_SECTION cs_load_gecko;
static CRITICAL_SECTION_DEBUG cs_load_gecko_dbg =
{
@ -754,7 +741,6 @@ static CRITICAL_SECTION cs_load_gecko = { &cs_load_gecko_dbg, -1, 0, 0, 0, 0 };
BOOL load_gecko(void)
{
PRUnichar gre_path[MAX_PATH];
BOOL ret = FALSE;
static DWORD loading_thread;
@ -768,13 +754,20 @@ BOOL load_gecko(void)
EnterCriticalSection(&cs_load_gecko);
if(!loading_thread) {
WCHAR *gecko_path;
loading_thread = GetCurrentThreadId();
if(load_wine_gecko(gre_path)
|| (install_wine_gecko() && load_wine_gecko(gre_path)))
ret = init_xpcom(gre_path);
else
MESSAGE("Could not load wine-gecko. HTML rendering will be disabled.\n");
if(!(gecko_path = find_wine_gecko_reg())
&& install_wine_gecko())
gecko_path = find_wine_gecko_reg();
if(gecko_path) {
ret = load_xul(gecko_path);
heap_free(gecko_path);
}else {
MESSAGE("Could not find Wine Gecko. HTML rendering will be disabled.\n");
}
}else {
ret = pCompMgr != NULL;
}