mshtml: Support registry configuration for maximal allowed compatibility mode.
Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
66e446c5ec
commit
5489529f4e
|
@ -36,6 +36,7 @@
|
|||
#include "rpcproxy.h"
|
||||
#include "shlguid.h"
|
||||
#include "mlang.h"
|
||||
#include "wininet.h"
|
||||
|
||||
#include "wine/debug.h"
|
||||
|
||||
|
@ -53,6 +54,14 @@ DWORD mshtml_tls = TLS_OUT_OF_INDEXES;
|
|||
static HINSTANCE shdoclc = NULL;
|
||||
static WCHAR *status_strings[IDS_STATUS_LAST-IDS_STATUS_FIRST+1];
|
||||
static IMultiLanguage2 *mlang;
|
||||
static unsigned global_max_compat_mode = COMPAT_MODE_IE11;
|
||||
static struct list compat_config = LIST_INIT(compat_config);
|
||||
|
||||
typedef struct {
|
||||
struct list entry;
|
||||
compat_mode_t max_compat_mode;
|
||||
WCHAR host[1];
|
||||
} compat_config_t;
|
||||
|
||||
static BOOL ensure_mlang(void)
|
||||
{
|
||||
|
@ -109,6 +118,114 @@ BSTR charset_string_from_cp(UINT cp)
|
|||
return SysAllocString(info.wszWebCharset);
|
||||
}
|
||||
|
||||
static BOOL read_compat_mode(HKEY key, compat_mode_t *r)
|
||||
{
|
||||
WCHAR version[32];
|
||||
DWORD type, size;
|
||||
LSTATUS status;
|
||||
|
||||
static const WCHAR max_compat_modeW[] = {'M','a','x','C','o','m','p','a','t','M','o','d','e',0};
|
||||
|
||||
size = sizeof(version);
|
||||
status = RegQueryValueExW(key, max_compat_modeW, NULL, &type, (BYTE*)version, &size);
|
||||
if(status != ERROR_SUCCESS || type != REG_SZ)
|
||||
return FALSE;
|
||||
|
||||
return parse_compat_version(version, r);
|
||||
}
|
||||
|
||||
static BOOL WINAPI load_compat_settings(INIT_ONCE *once, void *param, void **context)
|
||||
{
|
||||
WCHAR key_name[INTERNET_MAX_HOST_NAME_LENGTH];
|
||||
DWORD index = 0, name_size;
|
||||
compat_config_t *new_entry;
|
||||
compat_mode_t max_compat_mode;
|
||||
HKEY key, host_key;
|
||||
DWORD res;
|
||||
|
||||
static const WCHAR key_nameW[] = {
|
||||
'S','o','f','t','w','a','r','e',
|
||||
'\\','W','i','n','e',
|
||||
'\\','M','S','H','T','M','L',
|
||||
'\\','C','o','m','p','a','t','M','o','d','e',0};
|
||||
|
||||
/* @@ Wine registry key: HKCU\Software\Wine\MSHTML\CompatMode */
|
||||
res = RegOpenKeyW(HKEY_CURRENT_USER, key_nameW, &key);
|
||||
if(res != ERROR_SUCCESS)
|
||||
return TRUE;
|
||||
|
||||
if(read_compat_mode(key, &max_compat_mode)) {
|
||||
TRACE("Setting global max compat mode to %u\n", max_compat_mode);
|
||||
global_max_compat_mode = max_compat_mode;
|
||||
}
|
||||
|
||||
while(1) {
|
||||
res = RegEnumKeyW(key, index, key_name, ARRAY_SIZE(key_name));
|
||||
if(res == ERROR_NO_MORE_ITEMS)
|
||||
break;
|
||||
index++;
|
||||
if(res != ERROR_SUCCESS) {
|
||||
WARN("RegEnumKey failed: %u\n", GetLastError());
|
||||
continue;
|
||||
}
|
||||
|
||||
name_size = strlenW(key_name) + 1;
|
||||
new_entry = heap_alloc(FIELD_OFFSET(compat_config_t, host[name_size]));
|
||||
if(!new_entry)
|
||||
continue;
|
||||
|
||||
new_entry->max_compat_mode = COMPAT_MODE_IE11;
|
||||
memcpy(new_entry->host, key_name, name_size * sizeof(WCHAR));
|
||||
list_add_tail(&compat_config, &new_entry->entry);
|
||||
|
||||
res = RegOpenKeyW(key, key_name, &host_key);
|
||||
if(res != ERROR_SUCCESS)
|
||||
continue;
|
||||
|
||||
if(read_compat_mode(host_key, &max_compat_mode)) {
|
||||
TRACE("Setting max compat mode for %s to %u\n", debugstr_w(key_name), max_compat_mode);
|
||||
new_entry->max_compat_mode = max_compat_mode;
|
||||
}
|
||||
|
||||
RegCloseKey(host_key);
|
||||
}
|
||||
|
||||
RegCloseKey(key);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
compat_mode_t get_max_compat_mode(IUri *uri)
|
||||
{
|
||||
compat_config_t *iter;
|
||||
size_t len, iter_len;
|
||||
BSTR host;
|
||||
HRESULT hres;
|
||||
|
||||
static INIT_ONCE init_once = INIT_ONCE_STATIC_INIT;
|
||||
InitOnceExecuteOnce(&init_once, load_compat_settings, NULL, NULL);
|
||||
|
||||
if(!uri)
|
||||
return global_max_compat_mode;
|
||||
hres = IUri_GetHost(uri, &host);
|
||||
if(FAILED(hres))
|
||||
return global_max_compat_mode;
|
||||
len = SysStringLen(host);
|
||||
|
||||
LIST_FOR_EACH_ENTRY(iter, &compat_config, compat_config_t, entry) {
|
||||
iter_len = strlenW(iter->host);
|
||||
/* If configured host starts with '.', we also match subdomains */
|
||||
if((len == iter_len || (iter->host[0] == '.' && len > iter_len))
|
||||
&& !memcmp(host + len - iter_len, iter->host, iter_len * sizeof(WCHAR))) {
|
||||
TRACE("Found max mode %u\n", iter->max_compat_mode);
|
||||
return iter->max_compat_mode;
|
||||
}
|
||||
}
|
||||
|
||||
SysFreeString(host);
|
||||
TRACE("Using global max mode %u\n", global_max_compat_mode);
|
||||
return global_max_compat_mode;
|
||||
}
|
||||
|
||||
static void thread_detach(void)
|
||||
{
|
||||
thread_data_t *thread_data;
|
||||
|
@ -132,9 +249,17 @@ static void free_strings(void)
|
|||
|
||||
static void process_detach(void)
|
||||
{
|
||||
compat_config_t *config;
|
||||
|
||||
close_gecko();
|
||||
release_typelib();
|
||||
|
||||
while(!list_empty(&compat_config)) {
|
||||
config = LIST_ENTRY(list_head(&compat_config), compat_config_t, entry);
|
||||
list_remove(&config->entry);
|
||||
heap_free(config);
|
||||
}
|
||||
|
||||
if(shdoclc)
|
||||
FreeLibrary(shdoclc);
|
||||
if(mshtml_tls != TLS_OUT_OF_INDEXES)
|
||||
|
|
|
@ -1167,6 +1167,8 @@ void remove_target_tasks(LONG) DECLSPEC_HIDDEN;
|
|||
HRESULT set_task_timer(HTMLInnerWindow*,LONG,BOOL,IDispatch*,LONG*) DECLSPEC_HIDDEN;
|
||||
HRESULT clear_task_timer(HTMLInnerWindow*,DWORD) DECLSPEC_HIDDEN;
|
||||
|
||||
BOOL parse_compat_version(const WCHAR*,compat_mode_t*) DECLSPEC_HIDDEN;
|
||||
|
||||
const char *debugstr_mshtml_guid(const GUID*) DECLSPEC_HIDDEN;
|
||||
|
||||
DEFINE_GUID(CLSID_AboutProtocol, 0x3050F406, 0x98B5, 0x11CF, 0xBB,0x82, 0x00,0xAA,0x00,0xBD,0xCE,0x0B);
|
||||
|
@ -1337,6 +1339,7 @@ static inline VARIANT_BOOL variant_bool(BOOL b)
|
|||
extern void *call_thiscall_func;
|
||||
#endif
|
||||
|
||||
compat_mode_t get_max_compat_mode(IUri*) DECLSPEC_HIDDEN;
|
||||
UINT cp_from_charset_string(BSTR) DECLSPEC_HIDDEN;
|
||||
BSTR charset_string_from_cp(UINT) DECLSPEC_HIDDEN;
|
||||
HINSTANCE get_shdoclc(void) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -377,6 +377,8 @@ compat_mode_t lock_document_mode(HTMLDocumentNode *doc)
|
|||
|
||||
static void set_document_mode(HTMLDocumentNode *doc, compat_mode_t document_mode, BOOL lock)
|
||||
{
|
||||
compat_mode_t max_compat_mode;
|
||||
|
||||
if(doc->document_mode_locked) {
|
||||
WARN("attempting to set document mode %d on locked document %p\n", document_mode, doc);
|
||||
return;
|
||||
|
@ -384,35 +386,31 @@ static void set_document_mode(HTMLDocumentNode *doc, compat_mode_t document_mode
|
|||
|
||||
TRACE("%p: %d\n", doc, document_mode);
|
||||
|
||||
max_compat_mode = doc->window && doc->window->base.outer_window
|
||||
? get_max_compat_mode(doc->window->base.outer_window->uri)
|
||||
: COMPAT_MODE_IE11;
|
||||
if(max_compat_mode < document_mode) {
|
||||
WARN("Tried to set compat mode %u higher than maximal configured %u\n",
|
||||
document_mode, max_compat_mode);
|
||||
document_mode = max_compat_mode;
|
||||
}
|
||||
|
||||
doc->document_mode = document_mode;
|
||||
if(lock)
|
||||
lock_document_mode(doc);
|
||||
}
|
||||
|
||||
static BOOL parse_ua_compatible(const WCHAR *p, compat_mode_t *r)
|
||||
BOOL parse_compat_version(const WCHAR *version_string, compat_mode_t *r)
|
||||
{
|
||||
int v = 0;
|
||||
DWORD version = 0;
|
||||
const WCHAR *p;
|
||||
|
||||
static const WCHAR ie_eqW[] = {'I','E','='};
|
||||
static const WCHAR edgeW[] = {'e','d','g','e',0};
|
||||
|
||||
TRACE("%s\n", debugstr_w(p));
|
||||
|
||||
if(strncmpiW(ie_eqW, p, ARRAY_SIZE(ie_eqW)))
|
||||
return FALSE;
|
||||
p += 3;
|
||||
|
||||
if(!strcmpiW(p, edgeW)) {
|
||||
*r = COMPAT_MODE_IE11;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
while('0' <= *p && *p <= '9')
|
||||
v = v*10 + *(p++)-'0';
|
||||
if(*p || !v)
|
||||
for(p = version_string; '0' <= *p && *p <= '9'; p++)
|
||||
version = version * 10 + *p-'0';
|
||||
if(*p || p == version_string)
|
||||
return FALSE;
|
||||
|
||||
switch(v){
|
||||
switch(version){
|
||||
case 5:
|
||||
case 6:
|
||||
*r = COMPAT_MODE_IE5;
|
||||
|
@ -430,10 +428,28 @@ static BOOL parse_ua_compatible(const WCHAR *p, compat_mode_t *r)
|
|||
*r = COMPAT_MODE_IE10;
|
||||
break;
|
||||
default:
|
||||
*r = v < 5 ? COMPAT_MODE_QUIRKS : COMPAT_MODE_IE11;
|
||||
*r = version < 5 ? COMPAT_MODE_QUIRKS : COMPAT_MODE_IE11;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL parse_ua_compatible(const WCHAR *p, compat_mode_t *r)
|
||||
{
|
||||
static const WCHAR ie_eqW[] = {'I','E','='};
|
||||
static const WCHAR edgeW[] = {'e','d','g','e',0};
|
||||
|
||||
TRACE("%s\n", debugstr_w(p));
|
||||
|
||||
if(strncmpiW(ie_eqW, p, ARRAY_SIZE(ie_eqW)))
|
||||
return FALSE;
|
||||
p += 3;
|
||||
|
||||
if(!strcmpiW(p, edgeW)) {
|
||||
*r = COMPAT_MODE_IE11;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return parse_compat_version(p, r);
|
||||
}
|
||||
|
||||
void process_document_response_headers(HTMLDocumentNode *doc, IBinding *binding)
|
||||
|
|
Loading…
Reference in New Issue