Jacek Caban : urlmon: Correctly handle hash part in file protocol handler.

Alexandre Julliard julliard at wine.codeweavers.com
Wed May 20 10:04:11 CDT 2015


Module: wine
Branch: master
Commit: 16274e78b658816531df4d670ac89b62329130f7
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=16274e78b658816531df4d670ac89b62329130f7

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Tue May 19 16:36:48 2015 +0200

urlmon: Correctly handle hash part in file protocol handler.

---

 dlls/urlmon/file.c           | 51 +++++++++++++++++++++-----------------------
 dlls/urlmon/tests/protocol.c | 32 ++++++++++++++++++++++++---
 2 files changed, 53 insertions(+), 30 deletions(-)

diff --git a/dlls/urlmon/file.c b/dlls/urlmon/file.c
index 80d9dd6..bba7be1 100644
--- a/dlls/urlmon/file.c
+++ b/dlls/urlmon/file.c
@@ -217,35 +217,14 @@ static inline HRESULT report_result(IInternetProtocolSink *protocol_sink, HRESUL
     return hres;
 }
 
-static HRESULT open_file(FileProtocol *This, const WCHAR *path, IInternetProtocolSink *protocol_sink)
-{
-    LARGE_INTEGER size;
-    HANDLE file;
-
-    file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL,
-            OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
-    if(file == INVALID_HANDLE_VALUE)
-        return report_result(protocol_sink, INET_E_RESOURCE_NOT_FOUND, GetLastError());
-
-    if(!GetFileSizeEx(file, &size)) {
-        CloseHandle(file);
-        return report_result(protocol_sink, INET_E_RESOURCE_NOT_FOUND, GetLastError());
-    }
-
-    This->file = file;
-    This->size = size.u.LowPart;
-
-    IInternetProtocolSink_ReportProgress(protocol_sink,
-            BINDSTATUS_CACHEFILENAMEAVAILABLE, path);
-    return S_OK;
-}
-
 static HRESULT WINAPI FileProtocol_StartEx(IInternetProtocolEx *iface, IUri *pUri,
         IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
         DWORD grfPI, HANDLE *dwReserved)
 {
     FileProtocol *This = impl_from_IInternetProtocolEx(iface);
-    WCHAR path[MAX_PATH];
+    WCHAR path[MAX_PATH], *ptr;
+    LARGE_INTEGER file_size;
+    HANDLE file_handle;
     BINDINFO bindinfo;
     DWORD grfBINDF = 0;
     DWORD scheme, size;
@@ -296,13 +275,31 @@ static HRESULT WINAPI FileProtocol_StartEx(IInternetProtocolEx *iface, IUri *pUr
         return report_result(pOIProtSink, hres, 0);
     }
 
-    hres = open_file(This, path, pOIProtSink);
-    if(FAILED(hres))
-        return hres;
+    file_handle = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL,
+            OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+    if(file_handle == INVALID_HANDLE_VALUE && (ptr = strrchrW(path, '#'))) {
+        /* If path contains fragment part, try without it. */
+        *ptr = 0;
+        file_handle = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL,
+                OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+    }
+    if(file_handle == INVALID_HANDLE_VALUE)
+        return report_result(pOIProtSink, INET_E_RESOURCE_NOT_FOUND, GetLastError());
+
+    if(!GetFileSizeEx(file_handle, &file_size)) {
+        CloseHandle(file_handle);
+        return report_result(pOIProtSink, INET_E_RESOURCE_NOT_FOUND, GetLastError());
+    }
+
+    This->file = file_handle;
+    This->size = file_size.u.LowPart;
+    IInternetProtocolSink_ReportProgress(pOIProtSink,  BINDSTATUS_CACHEFILENAMEAVAILABLE, path);
 
     hres = IUri_GetExtension(pUri, &ext);
     if(SUCCEEDED(hres)) {
         if(hres == S_OK && *ext) {
+            if((ptr = strchrW(ext, '#')))
+                *ptr = 0;
             hres = find_mime_from_ext(ext, &mime);
             if(SUCCEEDED(hres)) {
                 IInternetProtocolSink_ReportProgress(pOIProtSink,
diff --git a/dlls/urlmon/tests/protocol.c b/dlls/urlmon/tests/protocol.c
index bfe4439..c50d356 100644
--- a/dlls/urlmon/tests/protocol.c
+++ b/dlls/urlmon/tests/protocol.c
@@ -153,7 +153,7 @@ static PROTOCOLDATA protocoldata, *pdata, continue_protdata;
 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;
+static BOOL empty_file, no_mime, bind_from_cache, file_with_hash;
 
 enum {
     STATE_CONNECTING,
@@ -907,7 +907,8 @@ static HRESULT WINAPI ProtocolSink_ReportData(IInternetProtocolSink *iface, DWOR
 
         ok(ulProgress == ulProgressMax, "ulProgress (%d) != ulProgressMax (%d)\n",
            ulProgress, ulProgressMax);
-        ok(ulProgressMax == 13, "ulProgressMax=%d, expected 13\n", ulProgressMax);
+        if(!file_with_hash)
+            ok(ulProgressMax == 13, "ulProgressMax=%d, expected 13\n", ulProgressMax);
         /* BSCF_SKIPDRAINDATAFORFILEURLS added in IE8 */
         if(tested_protocol == FILE_TEST)
             ok((grfBSCF == (BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION)) ||
@@ -2396,6 +2397,7 @@ static void init_test(int prot, DWORD flags)
     impl_protex = (flags & TEST_IMPLPROTEX) != 0;
     empty_file = (flags & TEST_EMPTY) != 0;
     bind_from_cache = (flags & TEST_FROMCACHE) != 0;
+    file_with_hash = FALSE;
 
     register_filter(mimefilter_test);
 }
@@ -2530,6 +2532,8 @@ static void test_file_protocol_url(LPCWSTR url)
             hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
             ok(hres == S_OK, "Read failed: %08x\n", hres);
             ok(cb == 2, "cb=%u expected 2\n", cb);
+            buf[2] = 0;
+            ok(!memcmp(buf, file_with_hash ? "XX" : "<H", 2), "Unexpected data %s\n", buf);
             hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
             ok(hres == S_FALSE, "Read failed: %08x\n", hres);
             hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
@@ -2564,7 +2568,10 @@ static void test_file_protocol_url(LPCWSTR url)
             hres = IInternetProtocol_UnlockRequest(protocol);
             ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
             hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
-            ok(hres == S_OK, "Read failed: %08x\n", hres);
+            if(file_with_hash) /* FIXME: An effect of UnlockRequest call? */
+                todo_wine ok(hres == S_OK, "Read failed: %08x\n", hres);
+            else
+                ok(hres == S_OK, "Read failed: %08x\n", hres);
             hres = IInternetProtocol_Terminate(protocol, 0);
             ok(hres == S_OK, "Terminate failed: %08x\n", hres);
         }
@@ -2717,6 +2724,7 @@ static void test_file_protocol(void) {
     static const WCHAR wszFile3[] = {'f','i','l','e',':','/','/','/',0};
     static const WCHAR wszFile4[] = {'f','i','l','e',':','\\','\\',0};
     static const char html_doc[] = "<HTML></HTML>";
+    static const WCHAR fragmentW[] = {'#','f','r','a','g',0};
 
     trace("Testing file protocol...\n");
     init_test(FILE_TEST, 0);
@@ -2790,7 +2798,25 @@ static void test_file_protocol(void) {
     buf[sizeof(wszFile4)/sizeof(WCHAR)] = '|';
     test_file_protocol_url(buf);
 
+    /* Fragment part of URL is skipped if the file doesn't exist. */
+    lstrcatW(buf, fragmentW);
+    test_file_protocol_url(buf);
+
+    /* Fragment part is considered a part of the file name, if the file exsists. */
+    len = lstrlenW(file_name_buf);
+    lstrcpyW(file_name_buf+len, fragmentW);
+    file = CreateFileW(wszIndexHtml, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
+            FILE_ATTRIBUTE_NORMAL, NULL);
+    ok(file != INVALID_HANDLE_VALUE, "CreateFile failed\n");
+    WriteFile(file, "XXX", 3, &size, NULL);
+    CloseHandle(file);
+    file_name_buf[len] = 0;
+
+    file_with_hash = TRUE;
+    test_file_protocol_url(buf);
+
     DeleteFileW(wszIndexHtml);
+    DeleteFileW(file_name_buf);
 
     bindf = 0;
     test_file_protocol_fail();




More information about the wine-cvs mailing list