[URLMON_WINETEST] Sync with Wine Staging 4.18. CORE-16441
authorAmine Khaldi <amine.khaldi@reactos.org>
Sun, 1 Dec 2019 18:39:54 +0000 (19:39 +0100)
committerAmine Khaldi <amine.khaldi@reactos.org>
Sun, 1 Dec 2019 18:39:54 +0000 (19:39 +0100)
modules/rostests/winetests/urlmon/CMakeLists.txt
modules/rostests/winetests/urlmon/misc.c
modules/rostests/winetests/urlmon/protocol.c
modules/rostests/winetests/urlmon/url.c

index a7595f5..e0f2e49 100644 (file)
@@ -14,5 +14,5 @@ list(APPEND SOURCE
 add_executable(urlmon_winetest ${SOURCE})
 target_link_libraries(urlmon_winetest uuid)
 set_module_type(urlmon_winetest win32cui)
-add_importlibs(urlmon_winetest urlmon wininet ole32 oleaut32 user32 advapi32 msvcrt kernel32)
+add_importlibs(urlmon_winetest urlmon wininet ole32 oleaut32 shlwapi user32 advapi32 msvcrt kernel32)
 add_rostests_file(TARGET urlmon_winetest)
index ff0f24e..6f4da47 100644 (file)
@@ -61,6 +61,8 @@ DEFINE_GUID(CLSID_AboutProtocol, 0x3050F406, 0x98B5, 0x11CF, 0xBB,0x82, 0x00,0xA
     }while(0)
 
 DEFINE_EXPECT(ParseUrl);
+DEFINE_EXPECT(ParseUrl_ENCODE);
+DEFINE_EXPECT(ParseUrl_UNESCAPE);
 DEFINE_EXPECT(QI_IInternetProtocolInfo);
 DEFINE_EXPECT(CreateInstance);
 DEFINE_EXPECT(unk_Release);
@@ -381,6 +383,13 @@ static void test_CoInternetParseUrl(void)
         ok(size == lstrlenW(parse_tests[i].encoded_url), "[%d] wrong size\n", i);
         ok(!lstrcmpW(parse_tests[i].encoded_url, buf), "[%d] wrong encoded url\n", i);
 
+        memset(buf, 0xf0, sizeof(buf));
+        hres = pCoInternetParseUrl(parse_tests[i].url, PARSE_UNESCAPE, 0, buf,
+                ARRAY_SIZE(buf), &size, 0);
+        ok(hres == S_OK, "[%d] encoding failed: %08x\n", i, hres);
+        ok(size == lstrlenW(parse_tests[i].encoded_url), "[%d] wrong size\n", i);
+        ok(!lstrcmpW(parse_tests[i].encoded_url, buf), "[%d] wrong encoded url\n", i);
+
         memset(buf, 0xf0, sizeof(buf));
         hres = pCoInternetParseUrl(parse_tests[i].url, PARSE_PATH_FROM_URL, 0, buf,
                 ARRAY_SIZE(buf), &size, 0);
@@ -875,9 +884,9 @@ static HRESULT WINAPI InternetProtocolInfo_ParseUrl(IInternetProtocolInfo *iface
         PARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult,
         DWORD *pcchResult, DWORD dwReserved)
 {
-    CHECK_EXPECT2(ParseUrl);
-
-    if(ParseAction == PARSE_SECURITY_URL) {
+    switch(ParseAction) {
+    case PARSE_SECURITY_URL:
+        CHECK_EXPECT2(ParseUrl);
         if(pcchResult)
             *pcchResult = ARRAY_SIZE(url1);
 
@@ -886,6 +895,17 @@ static HRESULT WINAPI InternetProtocolInfo_ParseUrl(IInternetProtocolInfo *iface
 
         memcpy(pwzResult, url1, sizeof(url1));
         return S_OK;
+    case PARSE_ENCODE:
+        CHECK_EXPECT2(ParseUrl_ENCODE);
+        break;
+
+    case PARSE_UNESCAPE:
+        CHECK_EXPECT2(ParseUrl_UNESCAPE);
+        break;
+
+    default:
+        CHECK_EXPECT2(ParseUrl);
+        break;
     }
 
     return E_NOTIMPL;
@@ -1030,24 +1050,34 @@ static void test_NameSpace(void)
     expect_cf = &test_protocol_cf;
     SET_EXPECT(QI_IInternetProtocolInfo);
     SET_EXPECT(CreateInstance);
-    SET_EXPECT(ParseUrl);
+    SET_EXPECT(ParseUrl_ENCODE);
 
     hres = pCoInternetParseUrl(url8, PARSE_ENCODE, 0, buf, ARRAY_SIZE(buf), &size, 0);
     ok(hres == S_OK, "CoInternetParseUrl failed: %08x\n", hres);
 
     CHECK_CALLED(QI_IInternetProtocolInfo);
     CHECK_CALLED(CreateInstance);
-    CHECK_CALLED(ParseUrl);
+    CHECK_CALLED(ParseUrl_ENCODE);
 
     qiret = S_OK;
     SET_EXPECT(QI_IInternetProtocolInfo);
-    SET_EXPECT(ParseUrl);
+    SET_EXPECT(ParseUrl_ENCODE);
 
     hres = pCoInternetParseUrl(url8, PARSE_ENCODE, 0, buf, ARRAY_SIZE(buf), &size, 0);
     ok(hres == S_OK, "CoInternetParseUrl failed: %08x\n", hres);
 
     CHECK_CALLED(QI_IInternetProtocolInfo);
-    CHECK_CALLED(ParseUrl);
+    CHECK_CALLED(ParseUrl_ENCODE);
+
+    qiret = S_OK;
+    SET_EXPECT(QI_IInternetProtocolInfo);
+    SET_EXPECT(ParseUrl_UNESCAPE);
+
+    hres = pCoInternetParseUrl(url8, PARSE_UNESCAPE, 0, buf, ARRAY_SIZE(buf), &size, 0);
+    ok(hres == S_OK, "CoInternetParseUrl failed: %08x\n", hres);
+
+    CHECK_CALLED(QI_IInternetProtocolInfo);
+    CHECK_CALLED(ParseUrl_UNESCAPE);
 
     SET_EXPECT(QI_IInternetProtocolInfo);
     SET_EXPECT(ParseUrl);
@@ -1097,38 +1127,38 @@ static void test_NameSpace(void)
     ok(hres == S_OK, "RegisterNameSpace failed: %08x\n", hres);
 
     SET_EXPECT(QI_IInternetProtocolInfo);
-    SET_EXPECT(ParseUrl);
+    SET_EXPECT(ParseUrl_ENCODE);
 
     hres = pCoInternetParseUrl(url8, PARSE_ENCODE, 0, buf, ARRAY_SIZE(buf), &size, 0);
     ok(hres == S_OK, "CoInternetParseUrl failed: %08x\n", hres);
 
     CHECK_CALLED(QI_IInternetProtocolInfo);
-    CHECK_CALLED(ParseUrl);
+    CHECK_CALLED(ParseUrl_ENCODE);
 
     hres = IInternetSession_UnregisterNameSpace(session, &test_protocol_cf, wszTest);
     ok(hres == S_OK, "UnregisterNameSpace failed: %08x\n", hres);
 
     SET_EXPECT(QI_IInternetProtocolInfo);
-    SET_EXPECT(ParseUrl);
+    SET_EXPECT(ParseUrl_ENCODE);
 
     hres = pCoInternetParseUrl(url8, PARSE_ENCODE, 0, buf, ARRAY_SIZE(buf), &size, 0);
     ok(hres == S_OK, "CoInternetParseUrl failed: %08x\n", hres);
 
     CHECK_CALLED(QI_IInternetProtocolInfo);
-    CHECK_CALLED(ParseUrl);
+    CHECK_CALLED(ParseUrl_ENCODE);
 
     hres = IInternetSession_UnregisterNameSpace(session, &test_protocol_cf, wszTest);
     ok(hres == S_OK, "UnregisterNameSpace failed: %08x\n", hres);
 
     expect_cf = &test_protocol_cf2;
     SET_EXPECT(QI_IInternetProtocolInfo);
-    SET_EXPECT(ParseUrl);
+    SET_EXPECT(ParseUrl_ENCODE);
 
     hres = pCoInternetParseUrl(url8, PARSE_ENCODE, 0, buf, ARRAY_SIZE(buf), &size, 0);
     ok(hres == S_OK, "CoInternetParseUrl failed: %08x\n", hres);
 
     CHECK_CALLED(QI_IInternetProtocolInfo);
-    CHECK_CALLED(ParseUrl);
+    CHECK_CALLED(ParseUrl_ENCODE);
 
     hres = IInternetSession_UnregisterNameSpace(session, &test_protocol_cf, wszTest);
     ok(hres == S_OK, "UnregisterNameSpace failed: %08x\n", hres);
index 6162a94..3f8a999 100644 (file)
@@ -104,6 +104,7 @@ DEFINE_EXPECT(OnResponse);
 DEFINE_EXPECT(Switch);
 DEFINE_EXPECT(Continue);
 DEFINE_EXPECT(CreateInstance);
+DEFINE_EXPECT(CreateInstance_no_aggregation);
 DEFINE_EXPECT(Start);
 DEFINE_EXPECT(StartEx);
 DEFINE_EXPECT(Terminate);
@@ -159,6 +160,7 @@ static DWORD prot_read, filter_state, http_post_test, thread_id;
 static BOOL security_problem, test_async_req, impl_protex;
 static BOOL async_read_pending, mimefilter_test, direct_read, wait_for_switch, emulate_prot, short_read, test_abort;
 static BOOL empty_file, no_mime, bind_from_cache, file_with_hash, reuse_protocol_thread;
+static BOOL no_aggregation;
 
 enum {
     STATE_CONNECTING,
@@ -214,6 +216,12 @@ static const WCHAR binding_urls[][130] = {
 
 static const CHAR post_data[] = "mode=Test";
 
+static LONG obj_refcount(void *obj)
+{
+    IUnknown_AddRef((IUnknown *)obj);
+    return IUnknown_Release((IUnknown *)obj);
+}
+
 static int strcmp_wa(LPCWSTR strw, const char *stra)
 {
     CHAR buf[512];
@@ -1538,15 +1546,23 @@ static HRESULT WINAPI InternetPriority_QueryInterface(IInternetPriority *iface,
 static ULONG WINAPI InternetPriority_AddRef(IInternetPriority *iface)
 {
     Protocol *This = impl_from_IInternetPriority(iface);
-    This->outer_ref++;
-    return IUnknown_AddRef(This->outer);
+    if (This->outer)
+    {
+        This->outer_ref++;
+        return IUnknown_AddRef(This->outer);
+    }
+    return IUnknown_AddRef(&This->IUnknown_inner);
 }
 
 static ULONG WINAPI InternetPriority_Release(IInternetPriority *iface)
 {
     Protocol *This = impl_from_IInternetPriority(iface);
-    This->outer_ref--;
-    return IUnknown_Release(This->outer);
+    if (This->outer)
+    {
+        This->outer_ref--;
+        return IUnknown_Release(This->outer);
+    }
+    return IUnknown_Release(&This->IUnknown_inner);
 }
 
 static HRESULT WINAPI InternetPriority_SetPriority(IInternetPriority *iface, LONG nPriority)
@@ -1627,6 +1643,12 @@ static HRESULT WINAPI ProtocolEmul_QueryInterface(IInternetProtocolEx *iface, RE
     static const IID unknown_iid = {0x7daf9908,0x8415,0x4005,{0x95,0xae, 0xbd,0x27,0xf6,0xe3,0xdc,0x00}};
     static const IID unknown_iid2 = {0x5b7ebc0c,0xf630,0x4cea,{0x89,0xd3,0x5a,0xf0,0x38,0xed,0x05,0x5c}};
 
+    if(IsEqualGUID(riid, &IID_IInternetProtocolEx)) {
+        *ppv = &This->IInternetProtocolEx_iface;
+        IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
+        return S_OK;
+    }
+
     /* FIXME: Why is it calling here instead of outer IUnknown? */
     if(IsEqualGUID(riid, &IID_IInternetPriority)) {
         *ppv = &This->IInternetPriority_iface;
@@ -1642,15 +1664,23 @@ static HRESULT WINAPI ProtocolEmul_QueryInterface(IInternetProtocolEx *iface, RE
 static ULONG WINAPI ProtocolEmul_AddRef(IInternetProtocolEx *iface)
 {
     Protocol *This = impl_from_IInternetProtocolEx(iface);
-    This->outer_ref++;
-    return IUnknown_AddRef(This->outer);
+    if (This->outer)
+    {
+        This->outer_ref++;
+        return IUnknown_AddRef(This->outer);
+    }
+    return IUnknown_AddRef(&This->IUnknown_inner);
 }
 
 static ULONG WINAPI ProtocolEmul_Release(IInternetProtocolEx *iface)
 {
     Protocol *This = impl_from_IInternetProtocolEx(iface);
-    This->outer_ref--;
-    return IUnknown_Release(This->outer);
+    if (This->outer)
+    {
+        This->outer_ref--;
+        return IUnknown_Release(This->outer);
+    }
+    return IUnknown_Release(&This->IUnknown_inner);
 }
 
 static DWORD WINAPI thread_proc(PVOID arg)
@@ -2221,6 +2251,7 @@ static Protocol *impl_from_IUnknown(IUnknown *iface)
 
 static HRESULT WINAPI ProtocolUnk_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
 {
+    static const IID IID_undocumentedIE10 = {0x7daf9908,0x8415,0x4005,{0x95,0xae,0xbd,0x27,0xf6,0xe3,0xdc,0x00}};
     Protocol *This = impl_from_IUnknown(iface);
 
     if(IsEqualGUID(&IID_IUnknown, riid)) {
@@ -2249,6 +2280,10 @@ static HRESULT WINAPI ProtocolUnk_QueryInterface(IUnknown *iface, REFIID riid, v
         CHECK_EXPECT(QueryInterface_IWinInetHttpInfo);
         *ppv = NULL;
         return E_NOINTERFACE;
+    }else if(IsEqualGUID(&IID_undocumentedIE10, riid)) {
+        trace("QI(%s)\n", wine_dbgstr_guid(riid));
+        *ppv = NULL;
+        return E_NOINTERFACE;
     }else {
         ok(0, "unexpected call %s\n", wine_dbgstr_guid(riid));
         *ppv = NULL;
@@ -2575,12 +2610,21 @@ static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown
 {
     Protocol *ret;
 
-    CHECK_EXPECT(CreateInstance);
-
-    ok(pOuter == (IUnknown*)prot_bind_info, "pOuter != protocol_unk\n");
-    ok(IsEqualGUID(&IID_IUnknown, riid), "unexpected riid %s\n", wine_dbgstr_guid(riid));
     ok(ppv != NULL, "ppv == NULL\n");
 
+    if(!pOuter) {
+        CHECK_EXPECT(CreateInstance_no_aggregation);
+        ok(IsEqualGUID(&IID_IInternetProtocol, riid), "unexpected riid %s\n", wine_dbgstr_guid(riid));
+    }else {
+        CHECK_EXPECT(CreateInstance);
+        ok(pOuter == (IUnknown*)prot_bind_info, "pOuter != protocol_unk\n");
+        ok(IsEqualGUID(&IID_IUnknown, riid), "unexpected riid %s\n", wine_dbgstr_guid(riid));
+        if (no_aggregation) {
+            *ppv = NULL;
+            return CLASS_E_NOAGGREGATION;
+        }
+    }
+
     ret = heap_alloc(sizeof(*ret));
     ret->IUnknown_inner.lpVtbl = &ProtocolUnkVtbl;
     ret->IInternetProtocolEx_iface.lpVtbl = &ProtocolVtbl;
@@ -2590,7 +2634,10 @@ static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown
     ret->outer_ref = 0;
 
     protocol_emul = ret;
-    *ppv = &ret->IUnknown_inner;
+    if (!pOuter)
+        *ppv = &ret->IInternetProtocolEx_iface;
+    else
+        *ppv = &ret->IUnknown_inner;
     return S_OK;
 }
 
@@ -3769,7 +3816,7 @@ static void test_CreateBinding(void)
         {'t','e','s','t',':','/','/','f','i','l','e','.','h','t','m','l',0};
     static const WCHAR wsz_test[] = {'t','e','s','t',0};
 
-    trace("Testing CreateBinding...\n");
+    trace("Testing CreateBinding%s...\n", no_aggregation ? "(no aggregation)" : "");
     init_test(BIND_TEST, TEST_BINDING);
 
     hres = pCoInternetGetSession(0, &session, 0);
@@ -3817,10 +3864,19 @@ static void test_CreateBinding(void)
     ok(hres == E_NOINTERFACE, "Could not get IWinInetInfo protocol: %08x\n", hres);
 
     SET_EXPECT(QueryService_InternetProtocol);
+
     SET_EXPECT(CreateInstance);
+    if(no_aggregation) {
+        SET_EXPECT(CreateInstance_no_aggregation);
+        SET_EXPECT(StartEx);
+    }else {
+        SET_EXPECT(Start);
+    }
+
     SET_EXPECT(ReportProgress_PROTOCOLCLASSID);
     SET_EXPECT(SetPriority);
-    SET_EXPECT(Start);
+
+    ok(obj_refcount(protocol) == 4, "wrong protocol refcount %d\n", obj_refcount(protocol));
 
     trace("Start >\n");
     expect_hrResult = S_OK;
@@ -3829,25 +3885,46 @@ static void test_CreateBinding(void)
     trace("Start <\n");
 
     CHECK_CALLED(QueryService_InternetProtocol);
+
     CHECK_CALLED(CreateInstance);
+    if(no_aggregation) {
+        CHECK_CALLED(CreateInstance_no_aggregation);
+        ok(obj_refcount(protocol) == 4, "wrong protocol refcount %d\n", obj_refcount(protocol));
+        ok(protocol_emul->outer_ref == 0, "protocol_outer_ref = %u\n", protocol_emul->outer_ref);
+    }else {
+        ok(obj_refcount(protocol) == 5 || broken(obj_refcount(protocol) == 4) /* before win7 */, "wrong protocol refcount %d\n",
+           obj_refcount(protocol));
+        ok(protocol_emul->outer_ref == 1 || broken(protocol_emul->outer_ref == 0) /* before win7 */, "protocol_outer_ref = %u\n",
+           protocol_emul->outer_ref);
+    }
+
     CHECK_CALLED(ReportProgress_PROTOCOLCLASSID);
     CHECK_CALLED(SetPriority);
-    CHECK_CALLED(Start);
+    if(no_aggregation)
+        CHECK_CALLED(StartEx);
+    else
+        CHECK_CALLED(Start);
 
-    SET_EXPECT(QueryInterface_IWinInetInfo);
+    if(!no_aggregation)
+        SET_EXPECT(QueryInterface_IWinInetInfo);
     hres = IInternetProtocol_QueryInterface(protocol, &IID_IWinInetInfo, (void**)&inet_info);
     ok(hres == E_NOINTERFACE, "Could not get IWinInetInfo protocol: %08x\n", hres);
-    CHECK_CALLED(QueryInterface_IWinInetInfo);
+    if(!no_aggregation)
+        CHECK_CALLED(QueryInterface_IWinInetInfo);
 
-    SET_EXPECT(QueryInterface_IWinInetInfo);
+    if(!no_aggregation)
+        SET_EXPECT(QueryInterface_IWinInetInfo);
     hres = IInternetProtocol_QueryInterface(protocol, &IID_IWinInetInfo, (void**)&inet_info);
     ok(hres == E_NOINTERFACE, "Could not get IWinInetInfo protocol: %08x\n", hres);
-    CHECK_CALLED(QueryInterface_IWinInetInfo);
+    if(!no_aggregation)
+        CHECK_CALLED(QueryInterface_IWinInetInfo);
 
-    SET_EXPECT(QueryInterface_IWinInetHttpInfo);
+    if(!no_aggregation)
+        SET_EXPECT(QueryInterface_IWinInetHttpInfo);
     hres = IInternetProtocol_QueryInterface(protocol, &IID_IWinInetHttpInfo, (void**)&http_info);
     ok(hres == E_NOINTERFACE, "Could not get IWinInetInfo protocol: %08x\n", hres);
-    CHECK_CALLED(QueryInterface_IWinInetHttpInfo);
+    if(!no_aggregation)
+        CHECK_CALLED(QueryInterface_IWinInetHttpInfo);
 
     SET_EXPECT(Read);
     read = 0xdeadbeef;
@@ -3871,11 +3948,20 @@ static void test_CreateBinding(void)
     hres = IInternetPriority_SetPriority(priority, 101);
     ok(hres == S_OK, "SetPriority failed: %08x\n", hres);
 
+    if(no_aggregation) {
+        ok(obj_refcount(protocol) == 4, "wrong protocol refcount %d\n", obj_refcount(protocol));
+        ok(protocol_emul->outer_ref == 0, "protocol_outer_ref = %u\n", protocol_emul->outer_ref);
+    }else {
+        ok(obj_refcount(protocol) == 5 || broken(obj_refcount(protocol) == 4) /* before win7 */, "wrong protocol refcount %d\n", obj_refcount(protocol));
+        ok(protocol_emul->outer_ref == 1 || broken(protocol_emul->outer_ref == 0) /* before win7 */, "protocol_outer_ref = %u\n", protocol_emul->outer_ref);
+    }
+
     SET_EXPECT(Terminate);
     hres = IInternetProtocol_Terminate(protocol, 0xdeadbeef);
     ok(hres == S_OK, "Terminate failed: %08x\n", hres);
     CHECK_CALLED(Terminate);
 
+    ok(obj_refcount(protocol) == 4, "wrong protocol refcount %d\n", obj_refcount(protocol));
     ok(protocol_emul->outer_ref == 0, "protocol_outer_ref = %u\n", protocol_emul->outer_ref);
 
     SET_EXPECT(Continue);
@@ -3886,12 +3972,18 @@ static void test_CreateBinding(void)
     SET_EXPECT(Read);
     read = 0xdeadbeef;
     hres = IInternetProtocol_Read(protocol, expect_pv = buf, sizeof(buf), &read);
-    todo_wine
-    ok(hres == E_ABORT, "Read failed: %08x\n", hres);
-    todo_wine
-    ok(read == 0, "read = %d\n", read);
-    todo_wine
-    CHECK_NOT_CALLED(Read);
+    if(no_aggregation) {
+        ok(hres == S_OK, "Read failed: %08x\n", hres);
+        ok(read == 100, "read = %d\n", read);
+        CHECK_CALLED(Read);
+    }else {
+        todo_wine
+        ok(hres == E_ABORT, "Read failed: %08x\n", hres);
+        todo_wine
+        ok(read == 0, "read = %d\n", read);
+        todo_wine
+        CHECK_NOT_CALLED(Read);
+    }
 
     hres = IInternetProtocolSink_ReportProgress(binding_sink,
             BINDSTATUS_CACHEFILENAMEAVAILABLE, expect_wsz = emptyW);
@@ -3907,6 +3999,8 @@ static void test_CreateBinding(void)
     IInternetPriority_Release(priority);
     IInternetBindInfo_Release(prot_bind_info);
 
+    ok(obj_refcount(protocol) == 1, "wrong protocol refcount %d\n", obj_refcount(protocol));
+
     SET_EXPECT(Protocol_destructor);
     IInternetProtocol_Release(protocol);
     CHECK_CALLED(Protocol_destructor);
@@ -4192,6 +4286,9 @@ START_TEST(protocol)
     test_gopher_protocol();
     test_mk_protocol();
     test_CreateBinding();
+    no_aggregation = TRUE;
+    test_CreateBinding();
+    no_aggregation = FALSE;
 
     bindf &= ~BINDF_FROMURLMON;
     trace("Testing file binding (mime verification, emulate prot)...\n");
index ada78c9..1aef981 100644 (file)
@@ -32,6 +32,7 @@
 #include "urlmon.h"
 #include "wininet.h"
 #include "mshtml.h"
+#include "shlwapi.h"
 
 #include "wine/test.h"
 
@@ -2905,7 +2906,7 @@ static void init_bind_test(int protocol, DWORD flags, DWORD t)
         url_a = (flags & BINDTEST_INVALID_CN) ? "https://4.15.184.77/favicon.ico" : "https://test.winehq.org/tests/hello.html";
         break;
     case FTP_TEST:
-        url_a = "ftp://ftp.winehq.org/welcome.msg";
+        url_a = "ftp://ftp.winehq.org/welcome%2emsg";
         break;
     default:
         url_a = "winetest:test";
@@ -2969,6 +2970,13 @@ static void test_BindToStorage(int protocol, DWORD flags, DWORD t)
     if(FAILED(hres))
         return;
 
+    if(protocol == FTP_TEST)
+    {
+        /* FTP urls don't have any escape characters so convert the url to what is expected */
+        DWORD size = 0;
+        UrlUnescapeW(current_url, NULL, &size, URL_UNESCAPE_INPLACE);
+    }
+
     hres = IMoniker_QueryInterface(mon, &IID_IBinding, (void**)&bind);
     ok(hres == E_NOINTERFACE, "IMoniker should not have IBinding interface\n");
     if(SUCCEEDED(hres))