mshtml: Always return the custom user agent if it has been set.

This uses the undocumented MapBrowserEmulationModeToUserAgent and only the
first field of the unknown struct, but it is enough for this purpose. It
is important for some apps (e.g. FFXIV Launcher) which expects it to work
like this.

Signed-off-by: Gabriel Ivăncescu <gabrielopcode@gmail.com>
Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Gabriel Ivăncescu 2022-04-11 18:58:48 +03:00 committed by Alexandre Julliard
parent 735ac6eb8f
commit 0badd67e70
3 changed files with 87 additions and 33 deletions

View file

@ -1162,77 +1162,80 @@ static HRESULT WINAPI OmNavigator_get_appName(IOmNavigator *iface, BSTR *p)
return S_OK;
}
static unsigned int get_ua_version(OmNavigator *navigator)
/* undocumented, added in IE8 */
extern HRESULT WINAPI MapBrowserEmulationModeToUserAgent(const void*,WCHAR**);
/* Retrieves allocated user agent via CoTaskMemAlloc */
static HRESULT get_user_agent(OmNavigator *navigator, WCHAR **user_agent)
{
DWORD version;
switch(dispex_compat_mode(&navigator->dispex)) {
case COMPAT_MODE_QUIRKS:
case COMPAT_MODE_IE5:
case COMPAT_MODE_IE7:
return 7;
version = 7;
break;
case COMPAT_MODE_IE8:
return 8;
version = 8;
break;
case COMPAT_MODE_IE9:
return 9;
version = 9;
break;
case COMPAT_MODE_IE10:
return 10;
version = 10;
break;
case COMPAT_MODE_IE11:
return 11;
version = 11;
break;
default:
assert(0);
return E_FAIL;
}
assert(0);
return 0;
return MapBrowserEmulationModeToUserAgent(&version, user_agent);
}
static HRESULT WINAPI OmNavigator_get_appVersion(IOmNavigator *iface, BSTR *p)
{
OmNavigator *This = impl_from_IOmNavigator(iface);
char user_agent[512];
DWORD size;
WCHAR *user_agent;
unsigned len;
HRESULT hres;
const unsigned skip_prefix = 8; /* strlen("Mozilla/") */
TRACE("(%p)->(%p)\n", This, p);
size = sizeof(user_agent);
hres = ObtainUserAgentString(get_ua_version(This), user_agent, &size);
hres = get_user_agent(This, &user_agent);
if(FAILED(hres))
return hres;
len = wcslen(user_agent);
if(size <= skip_prefix) {
if(len < skip_prefix) {
CoTaskMemFree(user_agent);
*p = NULL;
return S_OK;
}
size = MultiByteToWideChar(CP_ACP, 0, user_agent + skip_prefix, -1, NULL, 0);
*p = SysAllocStringLen(NULL, size-1);
if(!*p)
return E_OUTOFMEMORY;
MultiByteToWideChar(CP_ACP, 0, user_agent + skip_prefix, -1, *p, size);
return S_OK;
*p = SysAllocStringLen(user_agent + skip_prefix, len - skip_prefix);
CoTaskMemFree(user_agent);
return *p ? S_OK : E_OUTOFMEMORY;
}
static HRESULT WINAPI OmNavigator_get_userAgent(IOmNavigator *iface, BSTR *p)
{
OmNavigator *This = impl_from_IOmNavigator(iface);
char user_agent[512];
DWORD size;
WCHAR *user_agent;
HRESULT hres;
TRACE("(%p)->(%p)\n", This, p);
size = sizeof(user_agent);
hres = ObtainUserAgentString(get_ua_version(This), user_agent, &size);
hres = get_user_agent(This, &user_agent);
if(FAILED(hres))
return hres;
size = MultiByteToWideChar(CP_ACP, 0, user_agent, -1, NULL, 0);
*p = SysAllocStringLen(NULL, size-1);
if(!*p)
return E_OUTOFMEMORY;
MultiByteToWideChar(CP_ACP, 0, user_agent, -1, *p, size);
return S_OK;
*p = SysAllocString(user_agent);
CoTaskMemFree(user_agent);
return *p ? S_OK : E_OUTOFMEMORY;
}
static HRESULT WINAPI OmNavigator_javaEnabled(IOmNavigator *iface, VARIANT_BOOL *enabled)

View file

@ -6479,6 +6479,11 @@ static void test_navigator(IHTMLDocument2 *doc)
ok(!lstrcmpW(bstr, buf+8), "appVersion returned %s, expected \"%s\"\n", wine_dbgstr_w(bstr), wine_dbgstr_w(buf+8));
SysFreeString(bstr);
hres = IOmNavigator_get_userAgent(navigator, &bstr);
ok(hres == S_OK, "get_userAgent failed: %08lx\n", hres);
ok(!lstrcmpW(bstr, buf), "userAgent returned %s, expected %s\n", wine_dbgstr_w(bstr), wine_dbgstr_w(buf));
SysFreeString(bstr);
hres = UrlMkSetSessionOption(URLMON_OPTION_USERAGENT, buf, lstrlenW(buf), 0);
ok(hres == S_OK, "UrlMkSetSessionOption failed: %08lx\n", hres);
@ -11294,6 +11299,42 @@ static void test_quirks_mode(void)
"</html>", test_document_mode);
}
static void test_custom_user_agent(IHTMLDocument2 *doc)
{
static const WCHAR ua[] = L"1234567890xxxABC";
static char ua_ascii[] = "1234567890xxxABC";
IOmNavigator *navigator;
IHTMLWindow2 *window;
HRESULT hres;
BSTR bstr;
/* Set it only first time, to test it doesn't get reset on compat mode change */
if(compat_mode == COMPAT_NONE) {
hres = UrlMkSetSessionOption(URLMON_OPTION_USERAGENT, ua_ascii, sizeof(ua_ascii), 0);
ok(hres == S_OK, "UrlMkSetSessionOption failed: %08lx\n", hres);
}
hres = IHTMLDocument2_get_parentWindow(doc, &window);
ok(hres == S_OK, "parentWidnow failed: %08lx\n", hres);
hres = IHTMLWindow2_get_navigator(window, &navigator);
ok(hres == S_OK, "get_navigator failed: %08lx\n", hres);
ok(navigator != NULL, "navigator == NULL\n");
IHTMLWindow2_Release(window);
hres = IOmNavigator_get_appVersion(navigator, &bstr);
ok(hres == S_OK, "get_appVersion failed: %08lx\n", hres);
ok(!lstrcmpW(bstr, ua+8), "appVersion returned %s, expected %s\n", wine_dbgstr_w(bstr), wine_dbgstr_w(ua+8));
SysFreeString(bstr);
hres = IOmNavigator_get_userAgent(navigator, &bstr);
ok(hres == S_OK, "get_userAgent failed: %08lx\n", hres);
ok(!lstrcmpW(bstr, ua), "userAgent returned %s, expected %s\n", wine_dbgstr_w(bstr), wine_dbgstr_w(ua));
SysFreeString(bstr);
IOmNavigator_Release(navigator);
}
static void check_ie(void)
{
IHTMLDocument2 *doc;
@ -11356,6 +11397,16 @@ START_TEST(dom)
test_quirks_mode();
/* Run this last since it messes with the process-wide user agent */
if (winetest_interactive || ! is_ie_hardened()) {
run_domtest(doc_blank, test_custom_user_agent);
if(is_ie9plus) {
compat_mode = COMPAT_IE9;
run_domtest(doc_blank_ie9, test_custom_user_agent);
compat_mode = COMPAT_NONE;
}
}
DestroyWindow(container_hwnd);
CoUninitialize();
}

View file

@ -110,6 +110,6 @@
410 stdcall @(long long) LogSqmBits
423 stdcall @(long long long long) LogSqmUXCommandOffsetInternal
444 stdcall @(long long long) MapUriToBrowserEmulationState
445 stdcall @(ptr ptr) MapBrowserEmulationModeToUserAgent
445 stdcall -noname MapBrowserEmulationModeToUserAgent(ptr ptr)
446 stdcall @(long) CoInternetGetBrowserProfile
455 stdcall @() FlushUrlmonZonesCache