Gabriel Ivăncescu : mshtml: Always return the custom user agent if it has been set.

Alexandre Julliard julliard at winehq.org
Mon Apr 11 15:55:00 CDT 2022


Module: wine
Branch: master
Commit: 0badd67e7013de47e3e01446b2be379819c99019
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=0badd67e7013de47e3e01446b2be379819c99019

Author: Gabriel Ivăncescu <gabrielopcode at gmail.com>
Date:   Mon Apr 11 18:58:48 2022 +0300

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 at gmail.com>
Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/mshtml/omnavigator.c | 67 +++++++++++++++++++++++++----------------------
 dlls/mshtml/tests/dom.c   | 51 ++++++++++++++++++++++++++++++++++++
 dlls/urlmon/urlmon.spec   |  2 +-
 3 files changed, 87 insertions(+), 33 deletions(-)

diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c
index 0a2a6bb58cd..9962cc20dc7 100644
--- a/dlls/mshtml/omnavigator.c
+++ b/dlls/mshtml/omnavigator.c
@@ -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)
diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c
index b66073f632a..4af0e9bcfc4 100644
--- a/dlls/mshtml/tests/dom.c
+++ b/dlls/mshtml/tests/dom.c
@@ -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();
 }
diff --git a/dlls/urlmon/urlmon.spec b/dlls/urlmon/urlmon.spec
index 2fda69e1d79..8725c8c5aeb 100644
--- a/dlls/urlmon/urlmon.spec
+++ b/dlls/urlmon/urlmon.spec
@@ -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




More information about the wine-cvs mailing list