[SHLWAPI] Sync with Wine Staging 2.9. CORE-13362
[reactos.git] / reactos / dll / win32 / shlwapi / url.c
index 62ee506..9bb8df4 100644 (file)
@@ -123,7 +123,7 @@ static DWORD get_scheme_code(LPCWSTR scheme, DWORD scheme_len)
 
     for(i=0; i < sizeof(shlwapi_schemes)/sizeof(shlwapi_schemes[0]); i++) {
         if(scheme_len == strlenW(shlwapi_schemes[i].scheme_name)
-           && !memcmp(scheme, shlwapi_schemes[i].scheme_name, scheme_len*sizeof(WCHAR)))
+           && !memicmpW(scheme, shlwapi_schemes[i].scheme_name, scheme_len))
             return shlwapi_schemes[i].scheme_number;
     }
 
@@ -357,6 +357,9 @@ HRESULT WINAPI UrlCanonicalizeW(LPCWSTR pszUrl, LPWSTR pszCanonicalized,
             dwFlags |= URL_ESCAPE_UNSAFE;
         state = 5;
         is_file_url = TRUE;
+    } else if(url[0] == '/') {
+        state = 5;
+        is_file_url = TRUE;
     }
 
     while (*wk1) {
@@ -791,7 +794,7 @@ HRESULT WINAPI UrlCombineW(LPCWSTR pszBase, LPCWSTR pszRelative,
                process_case = 1;
                break;
            }
-            if (isalnum(*mrelative) && (*(mrelative + 1) == ':')) {
+            if (isalnumW(*mrelative) && (*(mrelative + 1) == ':')) {
                /* case that becomes "file:///" */
                strcpyW(preliminary, myfilestr);
                process_case = 1;
@@ -911,7 +914,7 @@ HRESULT WINAPI UrlCombineW(LPCWSTR pszBase, LPCWSTR pszRelative,
     }
 
     if (ret == S_OK) {
-       /* Reuse mrelative as temp storage as its already allocated and not needed anymore */
+        /* Reuse mrelative as temp storage as it's already allocated and not needed anymore */
         if(*pcchCombined == 0)
             *pcchCombined = 1;
        ret = UrlCanonicalizeW(preliminary, mrelative, pcchCombined, (dwFlags & ~URL_FILE_USE_PATHURL));
@@ -946,6 +949,10 @@ HRESULT WINAPI UrlEscapeA(
 
     if(!RtlCreateUnicodeStringFromAsciiz(&urlW, pszUrl))
         return E_INVALIDARG;
+    if(dwFlags & URL_ESCAPE_AS_UTF8) {
+        RtlFreeUnicodeString(&urlW);
+        return E_NOTIMPL;
+    }
     if((ret = UrlEscapeW(urlW.Buffer, escapedW, &lenW, dwFlags)) == E_POINTER) {
         escapedW = HeapAlloc(GetProcessHeap(), 0, lenW * sizeof(WCHAR));
         ret = UrlEscapeW(urlW.Buffer, escapedW, &lenW, dwFlags);
@@ -982,6 +989,9 @@ static inline BOOL URL_NeedEscapeW(WCHAR ch, DWORD flags, DWORD int_flags)
     if ((flags & URL_ESCAPE_PERCENT) && (ch == '%'))
        return TRUE;
 
+    if ((flags & URL_ESCAPE_AS_UTF8) && (ch >= 0x80))
+       return TRUE;
+
     if (ch <= 31 || (ch >= 127 && ch <= 255) )
        return TRUE;
 
@@ -1057,8 +1067,8 @@ HRESULT WINAPI UrlEscapeW(
     LPCWSTR src;
     DWORD needed = 0, ret;
     BOOL stop_escaping = FALSE;
-    WCHAR next[5], *dst, *dst_ptr;
-    INT len;
+    WCHAR next[12], *dst, *dst_ptr;
+    INT i, len;
     PARSEDURLW parsed_url;
     DWORD int_flags;
     DWORD slashes = 0;
@@ -1067,13 +1077,14 @@ HRESULT WINAPI UrlEscapeW(
     TRACE("(%p(%s) %p %p 0x%08x)\n", pszUrl, debugstr_w(pszUrl),
             pszEscaped, pcchEscaped, dwFlags);
 
-    if(!pszUrl || !pcchEscaped)
+    if(!pszUrl || !pcchEscaped || !pszEscaped || *pcchEscaped == 0)
         return E_INVALIDARG;
 
     if(dwFlags & ~(URL_ESCAPE_SPACES_ONLY |
                   URL_ESCAPE_SEGMENT_ONLY |
                   URL_DONT_ESCAPE_EXTRA_INFO |
-                  URL_ESCAPE_PERCENT))
+                  URL_ESCAPE_PERCENT |
+                  URL_ESCAPE_AS_UTF8))
         FIXME("Unimplemented flags: %08x\n", dwFlags);
 
     dst_ptr = dst = HeapAlloc(GetProcessHeap(), 0, *pcchEscaped*sizeof(WCHAR));
@@ -1176,10 +1187,49 @@ HRESULT WINAPI UrlEscapeW(
             if(cur == '\\' && (int_flags & WINE_URL_BASH_AS_SLASH) && !stop_escaping) cur = '/';
 
             if(URL_NeedEscapeW(cur, dwFlags, int_flags) && stop_escaping == FALSE) {
-                next[0] = '%';
-                next[1] = hexDigits[(cur >> 4) & 0xf];
-                next[2] = hexDigits[cur & 0xf];
-                len = 3;
+                if(dwFlags & URL_ESCAPE_AS_UTF8) {
+                    char utf[16];
+
+                    if ((cur >= 0xd800 && cur <= 0xdfff) &&
+                        (src[1] >= 0xdc00 && src[1] <= 0xdfff))
+                    {
+#ifdef __REACTOS__
+                        len = WideCharToMultiByte( CP_UTF8, 0, src, 2,
+                                                   utf, sizeof(utf), NULL, NULL );
+#else
+                        len = WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS, src, 2,
+                                                   utf, sizeof(utf), NULL, NULL );
+#endif
+                        src++;
+                    }
+                    else
+#ifdef __REACTOS__
+                        len = WideCharToMultiByte( CP_UTF8, 0, &cur, 1,
+                                                   utf, sizeof(utf), NULL, NULL );
+#else
+                        len = WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS, &cur, 1,
+                                                   utf, sizeof(utf), NULL, NULL );
+#endif
+
+                    if (!len) {
+                        utf[0] = 0xef;
+                        utf[1] = 0xbf;
+                        utf[2] = 0xbd;
+                        len = 3;
+                    }
+
+                    for(i = 0; i < len; i++) {
+                        next[i*3+0] = '%';
+                        next[i*3+1] = hexDigits[(utf[i] >> 4) & 0xf];
+                        next[i*3+2] = hexDigits[utf[i] & 0xf];
+                    }
+                    len *= 3;
+                } else {
+                    next[0] = '%';
+                    next[1] = hexDigits[(cur >> 4) & 0xf];
+                    next[2] = hexDigits[cur & 0xf];
+                    len = 3;
+                }
             } else {
                 next[0] = cur;
                 len = 1;