[WININET] Sync with Wine Staging 1.9.11. CORE-11368
[reactos.git] / reactos / dll / win32 / wininet / internet.c
index 5fc251d..dd3a83d 100644 (file)
@@ -351,15 +351,15 @@ static LONG INTERNET_SaveProxySettings( proxyinfo_t *lpwpi )
  *     *foundProxyLen is set to the required size in WCHARs, including the
  *     NULL terminator, and the last error is set to ERROR_INSUFFICIENT_BUFFER.
  */
-BOOL INTERNET_FindProxyForProtocol(LPCWSTR szProxy, LPCWSTR proto, WCHAR *foundProxy, DWORD *foundProxyLen)
+WCHAR *INTERNET_FindProxyForProtocol(LPCWSTR szProxy, LPCWSTR proto)
 {
-    LPCWSTR ptr;
-    BOOL ret = FALSE;
+    WCHAR *ret = NULL;
+    const WCHAR *ptr;
 
     TRACE("(%s, %s)\n", debugstr_w(szProxy), debugstr_w(proto));
 
     /* First, look for the specified protocol (proto=scheme://host:port) */
-    for (ptr = szProxy; !ret && ptr && *ptr; )
+    for (ptr = szProxy; ptr && *ptr; )
     {
         LPCWSTR end, equal;
 
@@ -369,60 +369,36 @@ BOOL INTERNET_FindProxyForProtocol(LPCWSTR szProxy, LPCWSTR proto, WCHAR *foundP
              equal - ptr == strlenW(proto) &&
              !strncmpiW(proto, ptr, strlenW(proto)))
         {
-            if (end - equal > *foundProxyLen)
-            {
-                WARN("buffer too short for %s\n",
-                     debugstr_wn(equal + 1, end - equal - 1));
-                *foundProxyLen = end - equal;
-                SetLastError(ERROR_INSUFFICIENT_BUFFER);
-            }
-            else
-            {
-                memcpy(foundProxy, equal + 1, (end - equal) * sizeof(WCHAR));
-                foundProxy[end - equal] = 0;
-                ret = TRUE;
-            }
+            ret = heap_strndupW(equal + 1, end - equal - 1);
+            TRACE("found proxy for %s: %s\n", debugstr_w(proto), debugstr_w(ret));
+            return ret;
         }
         if (*end == ' ')
             ptr = end + 1;
         else
             ptr = end;
     }
-    if (!ret)
+
+    /* It wasn't found: look for no protocol */
+    for (ptr = szProxy; ptr && *ptr; )
     {
-        /* It wasn't found: look for no protocol */
-        for (ptr = szProxy; !ret && ptr && *ptr; )
-        {
-            LPCWSTR end;
+        LPCWSTR end;
 
-            if (!(end = strchrW(ptr, ' ')))
-                end = ptr + strlenW(ptr);
-            if (!strchrW(ptr, '='))
-            {
-                if (end - ptr + 1 > *foundProxyLen)
-                {
-                    WARN("buffer too short for %s\n",
-                         debugstr_wn(ptr, end - ptr));
-                    *foundProxyLen = end - ptr + 1;
-                    SetLastError(ERROR_INSUFFICIENT_BUFFER);
-                }
-                else
-                {
-                    memcpy(foundProxy, ptr, (end - ptr) * sizeof(WCHAR));
-                    foundProxy[end - ptr] = 0;
-                    ret = TRUE;
-                }
-            }
-            if (*end == ' ')
-                ptr = end + 1;
-            else
-                ptr = end;
+        if (!(end = strchrW(ptr, ' ')))
+            end = ptr + strlenW(ptr);
+        if (!strchrW(ptr, '='))
+        {
+            ret = heap_strndupW(ptr, end - ptr);
+            TRACE("found proxy for %s: %s\n", debugstr_w(proto), debugstr_w(ret));
+            return ret;
         }
+        if (*end == ' ')
+            ptr = end + 1;
+        else
+            ptr = end;
     }
-    if (ret)
-        TRACE("found proxy for %s: %s\n", debugstr_w(proto),
-              debugstr_w(foundProxy));
-    return ret;
+
+    return NULL;
 }
 
 /***********************************************************************
@@ -484,41 +460,32 @@ static void free_global_proxy( void )
 
 static BOOL parse_proxy_url( proxyinfo_t *info, const WCHAR *url )
 {
-    static const WCHAR fmt[] = {'%','s',':','%','u',0};
-    WCHAR hostname[INTERNET_MAX_HOST_NAME_LENGTH];
-    WCHAR username[INTERNET_MAX_USER_NAME_LENGTH];
-    WCHAR password[INTERNET_MAX_PASSWORD_LENGTH];
-    URL_COMPONENTSW uc;
-
-    hostname[0] = username[0] = password[0] = 0;
-    memset( &uc, 0, sizeof(uc) );
-    uc.dwStructSize      = sizeof(uc);
-    uc.lpszHostName      = hostname;
-    uc.dwHostNameLength  = INTERNET_MAX_HOST_NAME_LENGTH;
-    uc.lpszUserName      = username;
-    uc.dwUserNameLength  = INTERNET_MAX_USER_NAME_LENGTH;
-    uc.lpszPassword      = password;
-    uc.dwPasswordLength  = INTERNET_MAX_PASSWORD_LENGTH;
+    static const WCHAR fmt[] = {'%','.','*','s',':','%','u',0};
+    URL_COMPONENTSW uc = {sizeof(uc)};
+
+    uc.dwHostNameLength = 1;
+    uc.dwUserNameLength = 1;
+    uc.dwPasswordLength = 1;
 
     if (!InternetCrackUrlW( url, 0, 0, &uc )) return FALSE;
-    if (!hostname[0])
+    if (!uc.dwHostNameLength)
     {
         if (!(info->proxy = heap_strdupW( url ))) return FALSE;
         info->proxyUsername = NULL;
         info->proxyPassword = NULL;
         return TRUE;
     }
-    if (!(info->proxy = heap_alloc( (strlenW(hostname) + 12) * sizeof(WCHAR) ))) return FALSE;
-    sprintfW( info->proxy, fmt, hostname, uc.nPort );
+    if (!(info->proxy = heap_alloc( (uc.dwHostNameLength + 12) * sizeof(WCHAR) ))) return FALSE;
+    sprintfW( info->proxy, fmt, uc.dwHostNameLength, uc.lpszHostName, uc.nPort );
 
-    if (!username[0]) info->proxyUsername = NULL;
-    else if (!(info->proxyUsername = heap_strdupW( username )))
+    if (!uc.dwUserNameLength) info->proxyUsername = NULL;
+    else if (!(info->proxyUsername = heap_strndupW( uc.lpszUserName, uc.dwUserNameLength )))
     {
         heap_free( info->proxy );
         return FALSE;
     }
-    if (!password[0]) info->proxyPassword = NULL;
-    else if (!(info->proxyPassword = heap_strdupW( password )))
+    if (!uc.dwPasswordLength) info->proxyPassword = NULL;
+    else if (!(info->proxyPassword = heap_strndupW( uc.lpszPassword, uc.dwPasswordLength )))
     {
         heap_free( info->proxyUsername );
         heap_free( info->proxy );
@@ -1448,169 +1415,147 @@ BOOL WINAPI InternetCloseHandle(HINTERNET hInternet)
     return TRUE;
 }
 
+static BOOL set_url_component(WCHAR **component, DWORD *component_length, const WCHAR *value, DWORD len)
+{
+    TRACE("%s (%d)\n", debugstr_wn(value, len), len);
 
-/***********************************************************************
- *           ConvertUrlComponentValue (Internal)
- *
- * Helper function for InternetCrackUrlA
- *
- */
-static void ConvertUrlComponentValue(LPSTR* lppszComponent, LPDWORD dwComponentLen,
-                                     LPWSTR lpwszComponent, DWORD dwwComponentLen,
-                                     LPCSTR lpszStart, LPCWSTR lpwszStart)
+    if (!*component_length)
+        return TRUE;
+
+    if (!*component) {
+        *(const WCHAR**)component = value;
+        *component_length = len;
+        return TRUE;
+    }
+
+    if (*component_length < len+1) {
+        SetLastError(ERROR_INSUFFICIENT_BUFFER);
+        return FALSE;
+    }
+
+    *component_length = len;
+    if(len)
+        memcpy(*component, value, len*sizeof(WCHAR));
+    (*component)[len] = 0;
+    return TRUE;
+}
+
+static BOOL set_url_component_WtoA(const WCHAR *comp_w, DWORD length, const WCHAR *url_w, char **comp, DWORD *ret_length,
+                                   const char *url_a)
 {
-    TRACE("%p %d %p %d %p %p\n", *lppszComponent, *dwComponentLen, lpwszComponent, dwwComponentLen, lpszStart, lpwszStart);
-    if (*dwComponentLen != 0)
-    {
-        DWORD nASCIILength=WideCharToMultiByte(CP_ACP,0,lpwszComponent,dwwComponentLen,NULL,0,NULL,NULL);
-        if (*lppszComponent == NULL)
-        {
-            if (lpwszComponent)
-            {
-                int offset = WideCharToMultiByte(CP_ACP, 0, lpwszStart, lpwszComponent-lpwszStart, NULL, 0, NULL, NULL);
-                *lppszComponent = (LPSTR)lpszStart + offset;
-            }
-            else
-                *lppszComponent = NULL;
+    size_t size, ret_size = *ret_length;
 
-            *dwComponentLen = nASCIILength;
-        }
-        else
-        {
-            DWORD ncpylen = min((*dwComponentLen)-1, nASCIILength);
-            WideCharToMultiByte(CP_ACP,0,lpwszComponent,dwwComponentLen,*lppszComponent,ncpylen+1,NULL,NULL);
-            (*lppszComponent)[ncpylen]=0;
-            *dwComponentLen = ncpylen;
-        }
+    if (!*ret_length)
+        return TRUE;
+    size = WideCharToMultiByte(CP_ACP, 0, comp_w, length, NULL, 0, NULL, NULL);
+
+    if (!*comp) {
+        *comp = comp_w ? (char*)url_a + WideCharToMultiByte(CP_ACP, 0, url_w, comp_w-url_w, NULL, 0, NULL, NULL) : NULL;
+        *ret_length = size;
+        return TRUE;
+    }
+
+    if (size+1 > ret_size) {
+        SetLastError(ERROR_INSUFFICIENT_BUFFER);
+        *ret_length = size+1;
+        return FALSE;
     }
+
+    *ret_length = size;
+    WideCharToMultiByte(CP_ACP, 0, comp_w, length, *comp, ret_size-1, NULL, NULL);
+    (*comp)[size] = 0;
+    return TRUE;
 }
 
+static BOOL set_url_component_AtoW(const char *comp_a, DWORD len_a, WCHAR **comp_w, DWORD *len_w, WCHAR **buf)
+{
+    *len_w = len_a;
+
+    if(!comp_a) {
+        *comp_w = NULL;
+        return TRUE;
+    }
+
+    if(!(*comp_w = *buf = heap_alloc(len_a*sizeof(WCHAR)))) {
+        SetLastError(ERROR_OUTOFMEMORY);
+        return FALSE;
+    }
+
+    return TRUE;
+}
 
 /***********************************************************************
  *           InternetCrackUrlA (WININET.@)
  *
  * See InternetCrackUrlW.
  */
-BOOL WINAPI InternetCrackUrlA(LPCSTR lpszUrl, DWORD dwUrlLength, DWORD dwFlags,
-    LPURL_COMPONENTSA lpUrlComponents)
+BOOL WINAPI InternetCrackUrlA(const char *url, DWORD url_length, DWORD flags, URL_COMPONENTSA *ret_comp)
 {
-  DWORD nLength;
-  URL_COMPONENTSW UCW;
-  BOOL ret = FALSE;
-  WCHAR *lpwszUrl, *hostname = NULL, *username = NULL, *password = NULL, *path = NULL,
-        *scheme = NULL, *extra = NULL;
-
-  TRACE("(%s %u %x %p)\n",
-        lpszUrl ? debugstr_an(lpszUrl, dwUrlLength ? dwUrlLength : strlen(lpszUrl)) : "(null)",
-        dwUrlLength, dwFlags, lpUrlComponents);
-
-  if (!lpszUrl || !*lpszUrl || !lpUrlComponents ||
-          lpUrlComponents->dwStructSize != sizeof(URL_COMPONENTSA))
-  {
-      INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
-      return FALSE;
-  }
+    WCHAR *host = NULL, *user = NULL, *pass = NULL, *path = NULL, *scheme = NULL, *extra = NULL;
+    URL_COMPONENTSW comp;
+    WCHAR *url_w = NULL;
+    BOOL ret;
 
-  if(dwUrlLength<=0)
-      dwUrlLength=-1;
-  nLength=MultiByteToWideChar(CP_ACP,0,lpszUrl,dwUrlLength,NULL,0);
+    TRACE("(%s %u %x %p)\n", url_length ? debugstr_an(url, url_length) : debugstr_a(url), url_length, flags, ret_comp);
 
-  /* if dwUrlLength=-1 then nLength includes null but length to 
-       InternetCrackUrlW should not include it                  */
-  if (dwUrlLength == -1) nLength--;
+    if (!url || !*url || !ret_comp || ret_comp->dwStructSize != sizeof(URL_COMPONENTSA)) {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
 
-  lpwszUrl = heap_alloc((nLength + 1) * sizeof(WCHAR));
-  MultiByteToWideChar(CP_ACP,0,lpszUrl,dwUrlLength,lpwszUrl,nLength + 1);
-  lpwszUrl[nLength] = '\0';
+    comp.dwStructSize = sizeof(comp);
 
-  memset(&UCW,0,sizeof(UCW));
-  UCW.dwStructSize = sizeof(URL_COMPONENTSW);
-  if (lpUrlComponents->dwHostNameLength)
-  {
-    UCW.dwHostNameLength = lpUrlComponents->dwHostNameLength;
-    if (lpUrlComponents->lpszHostName)
-    {
-      hostname = heap_alloc(UCW.dwHostNameLength * sizeof(WCHAR));
-      UCW.lpszHostName = hostname;
-    }
-  }
-  if (lpUrlComponents->dwUserNameLength)
-  {
-    UCW.dwUserNameLength = lpUrlComponents->dwUserNameLength;
-    if (lpUrlComponents->lpszUserName)
-    {
-      username = heap_alloc(UCW.dwUserNameLength * sizeof(WCHAR));
-      UCW.lpszUserName = username;
-    }
-  }
-  if (lpUrlComponents->dwPasswordLength)
-  {
-    UCW.dwPasswordLength = lpUrlComponents->dwPasswordLength;
-    if (lpUrlComponents->lpszPassword)
-    {
-      password = heap_alloc(UCW.dwPasswordLength * sizeof(WCHAR));
-      UCW.lpszPassword = password;
-    }
-  }
-  if (lpUrlComponents->dwUrlPathLength)
-  {
-    UCW.dwUrlPathLength = lpUrlComponents->dwUrlPathLength;
-    if (lpUrlComponents->lpszUrlPath)
-    {
-      path = heap_alloc(UCW.dwUrlPathLength * sizeof(WCHAR));
-      UCW.lpszUrlPath = path;
-    }
-  }
-  if (lpUrlComponents->dwSchemeLength)
-  {
-    UCW.dwSchemeLength = lpUrlComponents->dwSchemeLength;
-    if (lpUrlComponents->lpszScheme)
-    {
-      scheme = heap_alloc(UCW.dwSchemeLength * sizeof(WCHAR));
-      UCW.lpszScheme = scheme;
-    }
-  }
-  if (lpUrlComponents->dwExtraInfoLength)
-  {
-    UCW.dwExtraInfoLength = lpUrlComponents->dwExtraInfoLength;
-    if (lpUrlComponents->lpszExtraInfo)
-    {
-      extra = heap_alloc(UCW.dwExtraInfoLength * sizeof(WCHAR));
-      UCW.lpszExtraInfo = extra;
+    ret = set_url_component_AtoW(ret_comp->lpszHostName, ret_comp->dwHostNameLength,
+                                 &comp.lpszHostName, &comp.dwHostNameLength, &host)
+        && set_url_component_AtoW(ret_comp->lpszUserName, ret_comp->dwUserNameLength,
+                                  &comp.lpszUserName, &comp.dwUserNameLength, &user)
+        && set_url_component_AtoW(ret_comp->lpszPassword, ret_comp->dwPasswordLength,
+                                  &comp.lpszPassword, &comp.dwPasswordLength, &pass)
+        && set_url_component_AtoW(ret_comp->lpszUrlPath, ret_comp->dwUrlPathLength,
+                                  &comp.lpszUrlPath, &comp.dwUrlPathLength, &path)
+        && set_url_component_AtoW(ret_comp->lpszScheme, ret_comp->dwSchemeLength,
+                                  &comp.lpszScheme, &comp.dwSchemeLength, &scheme)
+        && set_url_component_AtoW(ret_comp->lpszExtraInfo, ret_comp->dwExtraInfoLength,
+                                  &comp.lpszExtraInfo, &comp.dwExtraInfoLength, &extra);
+
+    if(ret && !(url_w = heap_strndupAtoW(url, url_length ? url_length : -1, &url_length))) {
+        SetLastError(ERROR_OUTOFMEMORY);
+        ret = FALSE;
     }
-  }
-  if ((ret = InternetCrackUrlW(lpwszUrl, nLength, dwFlags, &UCW)))
-  {
-    ConvertUrlComponentValue(&lpUrlComponents->lpszHostName, &lpUrlComponents->dwHostNameLength,
-                             UCW.lpszHostName, UCW.dwHostNameLength, lpszUrl, lpwszUrl);
-    ConvertUrlComponentValue(&lpUrlComponents->lpszUserName, &lpUrlComponents->dwUserNameLength,
-                             UCW.lpszUserName, UCW.dwUserNameLength, lpszUrl, lpwszUrl);
-    ConvertUrlComponentValue(&lpUrlComponents->lpszPassword, &lpUrlComponents->dwPasswordLength,
-                             UCW.lpszPassword, UCW.dwPasswordLength, lpszUrl, lpwszUrl);
-    ConvertUrlComponentValue(&lpUrlComponents->lpszUrlPath, &lpUrlComponents->dwUrlPathLength,
-                             UCW.lpszUrlPath, UCW.dwUrlPathLength, lpszUrl, lpwszUrl);
-    ConvertUrlComponentValue(&lpUrlComponents->lpszScheme, &lpUrlComponents->dwSchemeLength,
-                             UCW.lpszScheme, UCW.dwSchemeLength, lpszUrl, lpwszUrl);
-    ConvertUrlComponentValue(&lpUrlComponents->lpszExtraInfo, &lpUrlComponents->dwExtraInfoLength,
-                             UCW.lpszExtraInfo, UCW.dwExtraInfoLength, lpszUrl, lpwszUrl);
-
-    lpUrlComponents->nScheme = UCW.nScheme;
-    lpUrlComponents->nPort = UCW.nPort;
-
-    TRACE("%s: scheme(%s) host(%s) path(%s) extra(%s)\n", debugstr_a(lpszUrl),
-          debugstr_an(lpUrlComponents->lpszScheme, lpUrlComponents->dwSchemeLength),
-          debugstr_an(lpUrlComponents->lpszHostName, lpUrlComponents->dwHostNameLength),
-          debugstr_an(lpUrlComponents->lpszUrlPath, lpUrlComponents->dwUrlPathLength),
-          debugstr_an(lpUrlComponents->lpszExtraInfo, lpUrlComponents->dwExtraInfoLength));
-  }
-  heap_free(lpwszUrl);
-  heap_free(hostname);
-  heap_free(username);
-  heap_free(password);
-  heap_free(path);
-  heap_free(scheme);
-  heap_free(extra);
-  return ret;
+
+    if (ret && (ret = InternetCrackUrlW(url_w, url_length, flags, &comp))) {
+        ret_comp->nScheme = comp.nScheme;
+        ret_comp->nPort = comp.nPort;
+
+        ret = set_url_component_WtoA(comp.lpszHostName, comp.dwHostNameLength, url_w,
+                                     &ret_comp->lpszHostName, &ret_comp->dwHostNameLength, url)
+            && set_url_component_WtoA(comp.lpszUserName, comp.dwUserNameLength, url_w,
+                                      &ret_comp->lpszUserName, &ret_comp->dwUserNameLength, url)
+            && set_url_component_WtoA(comp.lpszPassword, comp.dwPasswordLength, url_w,
+                                      &ret_comp->lpszPassword, &ret_comp->dwPasswordLength, url)
+            && set_url_component_WtoA(comp.lpszUrlPath, comp.dwUrlPathLength, url_w,
+                                      &ret_comp->lpszUrlPath, &ret_comp->dwUrlPathLength, url)
+            && set_url_component_WtoA(comp.lpszScheme, comp.dwSchemeLength, url_w,
+                                      &ret_comp->lpszScheme, &ret_comp->dwSchemeLength, url)
+            && set_url_component_WtoA(comp.lpszExtraInfo, comp.dwExtraInfoLength, url_w,
+                                      &ret_comp->lpszExtraInfo, &ret_comp->dwExtraInfoLength, url);
+
+        if(ret)
+            TRACE("%s: scheme(%s) host(%s) path(%s) extra(%s)\n", debugstr_a(url),
+                  debugstr_an(ret_comp->lpszScheme, ret_comp->dwSchemeLength),
+                  debugstr_an(ret_comp->lpszHostName, ret_comp->dwHostNameLength),
+                  debugstr_an(ret_comp->lpszUrlPath, ret_comp->dwUrlPathLength),
+                  debugstr_an(ret_comp->lpszExtraInfo, ret_comp->dwExtraInfoLength));
+    }
+
+    heap_free(host);
+    heap_free(user);
+    heap_free(pass);
+    heap_free(path);
+    heap_free(scheme);
+    heap_free(extra);
+    heap_free(url_w);
+    return ret;
 }
 
 static const WCHAR url_schemes[][7] =
@@ -1651,49 +1596,6 @@ static INTERNET_SCHEME GetInternetSchemeW(LPCWSTR lpszScheme, DWORD nMaxCmp)
     return INTERNET_SCHEME_UNKNOWN;
 }
 
-/***********************************************************************
- *           SetUrlComponentValueW (Internal)
- *
- * Helper function for InternetCrackUrlW
- *
- * PARAMS
- *     lppszComponent [O] Holds the returned string
- *     dwComponentLen [I] Holds the size of lppszComponent
- *                    [O] Holds the length of the string in lppszComponent without '\0'
- *     lpszStart      [I] Holds the string to copy from
- *     len            [I] Holds the length of lpszStart without '\0'
- *
- * RETURNS
- *    TRUE on success
- *    FALSE on failure
- *
- */
-static BOOL SetUrlComponentValueW(LPWSTR* lppszComponent, LPDWORD dwComponentLen, LPCWSTR lpszStart, DWORD len)
-{
-    TRACE("%s (%d)\n", debugstr_wn(lpszStart,len), len);
-
-    if ( (*dwComponentLen == 0) && (*lppszComponent == NULL) )
-        return FALSE;
-
-    if (*dwComponentLen != 0 || *lppszComponent == NULL)
-    {
-        if (*lppszComponent == NULL)
-        {
-            *lppszComponent = (LPWSTR)lpszStart;
-            *dwComponentLen = len;
-        }
-        else
-        {
-            DWORD ncpylen = min((*dwComponentLen)-1, len);
-            memcpy(*lppszComponent, lpszStart, ncpylen*sizeof(WCHAR));
-            (*lppszComponent)[ncpylen] = '\0';
-            *dwComponentLen = ncpylen;
-        }
-    }
-
-    return TRUE;
-}
-
 /***********************************************************************
  *           InternetCrackUrlW   (WININET.@)
  *
@@ -1703,8 +1605,7 @@ static BOOL SetUrlComponentValueW(LPWSTR* lppszComponent, LPDWORD dwComponentLen
  *    TRUE on success
  *    FALSE on failure
  */
-BOOL WINAPI InternetCrackUrlW(LPCWSTR lpszUrl_orig, DWORD dwUrlLength_orig, DWORD dwFlags,
-                              LPURL_COMPONENTSW lpUC)
+BOOL WINAPI InternetCrackUrlW(const WCHAR *lpszUrl, DWORD dwUrlLength, DWORD dwFlags, URL_COMPONENTSW *lpUC)
 {
   /*
    * RFC 1808
@@ -1713,46 +1614,51 @@ BOOL WINAPI InternetCrackUrlW(LPCWSTR lpszUrl_orig, DWORD dwUrlLength_orig, DWOR
    */
     LPCWSTR lpszParam    = NULL;
     BOOL  found_colon = FALSE;
-    LPCWSTR lpszap, lpszUrl = lpszUrl_orig;
+    LPCWSTR lpszap;
     LPCWSTR lpszcp = NULL, lpszNetLoc;
-    LPWSTR  lpszUrl_decode = NULL;
-    DWORD dwUrlLength = dwUrlLength_orig;
 
     TRACE("(%s %u %x %p)\n",
           lpszUrl ? debugstr_wn(lpszUrl, dwUrlLength ? dwUrlLength : strlenW(lpszUrl)) : "(null)",
           dwUrlLength, dwFlags, lpUC);
 
-    if (!lpszUrl_orig || !*lpszUrl_orig || !lpUC)
+    if (!lpszUrl || !*lpszUrl || !lpUC)
     {
-        INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
+        SetLastError(ERROR_INVALID_PARAMETER);
         return FALSE;
     }
     if (!dwUrlLength) dwUrlLength = strlenW(lpszUrl);
 
     if (dwFlags & ICU_DECODE)
     {
-        WCHAR *url_tmp;
+        WCHAR *url_tmp, *buffer;
         DWORD len = dwUrlLength + 1;
+        BOOL ret;
 
-        if (!(url_tmp = heap_alloc(len * sizeof(WCHAR))))
+        if (!(url_tmp = heap_strndupW(lpszUrl, dwUrlLength)))
         {
-            INTERNET_SetLastError(ERROR_OUTOFMEMORY);
+            SetLastError(ERROR_OUTOFMEMORY);
             return FALSE;
         }
-        memcpy(url_tmp, lpszUrl_orig, dwUrlLength * sizeof(WCHAR));
-        url_tmp[dwUrlLength] = 0;
-        if (!(lpszUrl_decode = heap_alloc(len * sizeof(WCHAR))))
-        {
-            heap_free(url_tmp);
-            INTERNET_SetLastError(ERROR_OUTOFMEMORY);
-            return FALSE;
-        }
-        if (InternetCanonicalizeUrlW(url_tmp, lpszUrl_decode, &len, ICU_DECODE | ICU_NO_ENCODE))
+
+        buffer = url_tmp;
+        ret = InternetCanonicalizeUrlW(url_tmp, buffer, &len, ICU_DECODE | ICU_NO_ENCODE);
+        if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
         {
-            dwUrlLength = len;
-            lpszUrl = lpszUrl_decode;
+            buffer = heap_alloc(len * sizeof(WCHAR));
+            if (!buffer)
+            {
+                SetLastError(ERROR_OUTOFMEMORY);
+                heap_free(url_tmp);
+                return FALSE;
+            }
+            ret = InternetCanonicalizeUrlW(url_tmp, buffer, &len, ICU_DECODE | ICU_NO_ENCODE);
         }
+        if (ret)
+            ret = InternetCrackUrlW(buffer, len, dwFlags & ~ICU_DECODE, lpUC);
+
+        if (buffer != url_tmp) heap_free(buffer);
         heap_free(url_tmp);
+        return ret;
     }
     lpszap = lpszUrl;
     
@@ -1790,14 +1696,15 @@ BOOL WINAPI InternetCrackUrlW(LPCWSTR lpszUrl_orig, DWORD dwUrlLength_orig, DWOR
     if(!lpszParam)
         lpszParam = memchrW(lpszap, '#', dwUrlLength - (lpszap - lpszUrl));
 
-    SetUrlComponentValueW(&lpUC->lpszExtraInfo, &lpUC->dwExtraInfoLength,
-                          lpszParam, lpszParam ? dwUrlLength-(lpszParam-lpszUrl) : 0);
+    if(!set_url_component(&lpUC->lpszExtraInfo, &lpUC->dwExtraInfoLength,
+                          lpszParam, lpszParam ? dwUrlLength-(lpszParam-lpszUrl) : 0))
+        return FALSE;
 
 
     /* Get scheme first. */
     lpUC->nScheme = GetInternetSchemeW(lpszUrl, lpszcp - lpszUrl);
-    SetUrlComponentValueW(&lpUC->lpszScheme, &lpUC->dwSchemeLength,
-                               lpszUrl, lpszcp - lpszUrl);
+    if(!set_url_component(&lpUC->lpszScheme, &lpUC->dwSchemeLength, lpszUrl, lpszcp - lpszUrl))
+        return FALSE;
 
     /* Eat ':' in protocol. */
     lpszcp++;
@@ -1831,8 +1738,8 @@ BOOL WINAPI InternetCrackUrlW(LPCWSTR lpszUrl_orig, DWORD dwUrlLength_orig, DWOR
             if (lpszHost == NULL || lpszHost > lpszNetLoc)
             {
                 /* username and password not specified. */
-                SetUrlComponentValueW(&lpUC->lpszUserName, &lpUC->dwUserNameLength, NULL, 0);
-                SetUrlComponentValueW(&lpUC->lpszPassword, &lpUC->dwPasswordLength, NULL, 0);
+                set_url_component(&lpUC->lpszUserName, &lpUC->dwUserNameLength, NULL, 0);
+                set_url_component(&lpUC->lpszPassword, &lpUC->dwPasswordLength, NULL, 0);
             }
             else /* Parse out username and password */
             {
@@ -1847,14 +1754,14 @@ BOOL WINAPI InternetCrackUrlW(LPCWSTR lpszUrl_orig, DWORD dwUrlLength_orig, DWOR
                     lpszcp++;
                 }
 
-                SetUrlComponentValueW(&lpUC->lpszUserName, &lpUC->dwUserNameLength,
-                                      lpszUser, lpszPasswd - lpszUser);
+                if(!set_url_component(&lpUC->lpszUserName, &lpUC->dwUserNameLength, lpszUser, lpszPasswd - lpszUser))
+                    return FALSE;
 
                 if (lpszPasswd != lpszHost)
                     lpszPasswd++;
-                SetUrlComponentValueW(&lpUC->lpszPassword, &lpUC->dwPasswordLength,
-                                      lpszPasswd == lpszHost ? NULL : lpszPasswd,
-                                      lpszHost - lpszPasswd);
+                if(!set_url_component(&lpUC->lpszPassword, &lpUC->dwPasswordLength,
+                                      lpszPasswd == lpszHost ? NULL : lpszPasswd, lpszHost - lpszPasswd))
+                    return FALSE;
 
                 lpszcp++; /* Advance to beginning of host */
             }
@@ -1868,8 +1775,8 @@ BOOL WINAPI InternetCrackUrlW(LPCWSTR lpszUrl_orig, DWORD dwUrlLength_orig, DWOR
                entire string up to the first '/' */
             if(lpUC->nScheme==INTERNET_SCHEME_RES)
             {
-                SetUrlComponentValueW(&lpUC->lpszHostName, &lpUC->dwHostNameLength,
-                                      lpszHost, lpszPort - lpszHost);
+                if(!set_url_component(&lpUC->lpszHostName, &lpUC->dwHostNameLength, lpszHost, lpszPort - lpszHost))
+                    return FALSE;
                 lpszcp=lpszNetLoc;
             }
             else
@@ -1886,13 +1793,12 @@ BOOL WINAPI InternetCrackUrlW(LPCWSTR lpszUrl_orig, DWORD dwUrlLength_orig, DWOR
                 if(lpUC->nScheme==INTERNET_SCHEME_FILE && lpszPort <= lpszHost+1)
                 {
                     lpszcp=lpszHost;
-                    SetUrlComponentValueW(&lpUC->lpszHostName, &lpUC->dwHostNameLength,
-                                          NULL, 0);
+                    set_url_component(&lpUC->lpszHostName, &lpUC->dwHostNameLength, NULL, 0);
                 }
                 else
                 {
-                    SetUrlComponentValueW(&lpUC->lpszHostName, &lpUC->dwHostNameLength,
-                                          lpszHost, lpszPort - lpszHost);
+                    if(!set_url_component(&lpUC->lpszHostName, &lpUC->dwHostNameLength, lpszHost, lpszPort - lpszHost))
+                        return FALSE;
                     if (lpszPort != lpszNetLoc)
                         lpUC->nPort = atoiW(++lpszPort);
                     else switch (lpUC->nScheme)
@@ -1918,9 +1824,9 @@ BOOL WINAPI InternetCrackUrlW(LPCWSTR lpszUrl_orig, DWORD dwUrlLength_orig, DWOR
     }
     else
     {
-        SetUrlComponentValueW(&lpUC->lpszUserName, &lpUC->dwUserNameLength, NULL, 0);
-        SetUrlComponentValueW(&lpUC->lpszPassword, &lpUC->dwPasswordLength, NULL, 0);
-        SetUrlComponentValueW(&lpUC->lpszHostName, &lpUC->dwHostNameLength, NULL, 0);
+        set_url_component(&lpUC->lpszUserName, &lpUC->dwUserNameLength, NULL, 0);
+        set_url_component(&lpUC->lpszPassword, &lpUC->dwPasswordLength, NULL, 0);
+        set_url_component(&lpUC->lpszHostName, &lpUC->dwHostNameLength, NULL, 0);
     }
 
     /* Here lpszcp points to:
@@ -1955,7 +1861,7 @@ BOOL WINAPI InternetCrackUrlW(LPCWSTR lpszUrl_orig, DWORD dwUrlLength_orig, DWOR
             if (*lpszcp == '/')
             {
                 len = MAX_PATH;
-                PathCreateFromUrlW(lpszUrl_orig, tmppath, &len, 0);
+                PathCreateFromUrlW(lpszUrl, tmppath, &len, 0);
             }
             else
             {
@@ -1982,17 +1888,18 @@ BOOL WINAPI InternetCrackUrlW(LPCWSTR lpszUrl_orig, DWORD dwUrlLength_orig, DWOR
                     ++len;
                 }
             }
-            SetUrlComponentValueW(&lpUC->lpszUrlPath, &lpUC->dwUrlPathLength,
-                                       tmppath, len);
+            if(!set_url_component(&lpUC->lpszUrlPath, &lpUC->dwUrlPathLength, tmppath, len))
+                return FALSE;
         }
-        else
-            SetUrlComponentValueW(&lpUC->lpszUrlPath, &lpUC->dwUrlPathLength,
-                                       lpszcp, len);
+        else if(!set_url_component(&lpUC->lpszUrlPath, &lpUC->dwUrlPathLength, lpszcp, len))
+            return FALSE;
     }
     else
     {
         if (lpUC->lpszUrlPath && (lpUC->dwUrlPathLength > 0))
             lpUC->lpszUrlPath[0] = 0;
+        else if (lpUC->dwUrlPathLength > 0)
+            lpUC->lpszUrlPath = (WCHAR*)lpszcp;
         lpUC->dwUrlPathLength = 0;
     }
 
@@ -2002,7 +1909,6 @@ BOOL WINAPI InternetCrackUrlW(LPCWSTR lpszUrl_orig, DWORD dwUrlLength_orig, DWOR
              debugstr_wn(lpUC->lpszUrlPath,lpUC->dwUrlPathLength),
              debugstr_wn(lpUC->lpszExtraInfo,lpUC->dwExtraInfoLength));
 
-    heap_free( lpszUrl_decode );
     return TRUE;
 }
 
@@ -2333,7 +2239,7 @@ BOOL WINAPI InternetReadFileExW(HINTERNET hFile, LPINTERNET_BUFFERSW lpBuffer,
 
     TRACE("(%p %p 0x%x 0x%lx)\n", hFile, lpBuffer, dwFlags, dwContext);
 
-    if (lpBuffer->dwStructSize != sizeof(*lpBuffer)) {
+    if (!lpBuffer || lpBuffer->dwStructSize != sizeof(*lpBuffer)) {
         SetLastError(ERROR_INVALID_PARAMETER);
         return FALSE;
     }
@@ -2358,32 +2264,37 @@ BOOL WINAPI InternetReadFileExW(HINTERNET hFile, LPINTERNET_BUFFERSW lpBuffer,
     return res == ERROR_SUCCESS;
 }
 
-static BOOL get_proxy_autoconfig_url( char *buf, DWORD buflen )
+static WCHAR *get_proxy_autoconfig_url(void)
 {
 #if defined(MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
 
     CFDictionaryRef settings = CFNetworkCopySystemProxySettings();
+    WCHAR *ret = NULL;
+    SIZE_T len;
     const void *ref;
-    BOOL ret = FALSE;
 
-    if (!settings) return FALSE;
+    if (!settings) return NULL;
 
     if (!(ref = CFDictionaryGetValue( settings, kCFNetworkProxiesProxyAutoConfigURLString )))
     {
         CFRelease( settings );
-        return FALSE;
+        return NULL;
     }
-    if (CFStringGetCString( ref, buf, buflen, kCFStringEncodingASCII ))
+    len = CFStringGetLength( ref );
+    if (len)
+        ret = heap_alloc( (len+1) * sizeof(WCHAR) );
+    if (ret)
     {
-        TRACE( "returning %s\n", debugstr_a(buf) );
-        ret = TRUE;
+        CFStringGetCharacters( ref, CFRangeMake(0, len), ret );
+        ret[len] = 0;
     }
+    TRACE( "returning %s\n", debugstr_w(ret) );
     CFRelease( settings );
     return ret;
 #else
     static int once;
     if (!once++) FIXME( "no support on this platform\n" );
-    return FALSE;
+    return NULL;
 #endif
 }
 
@@ -2470,20 +2381,17 @@ static DWORD query_global_option(DWORD option, void *buffer, DWORD *size, BOOL u
     }
 
     case INTERNET_OPTION_PER_CONNECTION_OPTION: {
-        char url[INTERNET_MAX_URL_LENGTH + 1];
+        WCHAR *url;
         INTERNET_PER_CONN_OPTION_LISTW *con = buffer;
         INTERNET_PER_CONN_OPTION_LISTA *conA = buffer;
         DWORD res = ERROR_SUCCESS, i;
         proxyinfo_t pi;
-        BOOL have_url;
         LONG ret;
 
         TRACE("Getting global proxy info\n");
         if((ret = INTERNET_LoadProxySettings(&pi)))
             return ret;
 
-        have_url = get_proxy_autoconfig_url(url, sizeof(url));
-
         FIXME("INTERNET_OPTION_PER_CONNECTION_OPTION stub\n");
 
         if (*size < sizeof(INTERNET_PER_CONN_OPTION_LISTW)) {
@@ -2491,6 +2399,8 @@ static DWORD query_global_option(DWORD option, void *buffer, DWORD *size, BOOL u
             return ERROR_INSUFFICIENT_BUFFER;
         }
 
+        url = get_proxy_autoconfig_url();
+
         for (i = 0; i < con->dwOptionCount; i++) {
             INTERNET_PER_CONN_OPTIONW *optionW = con->pOptions + i;
             INTERNET_PER_CONN_OPTIONA *optionA = conA->pOptions + i;
@@ -2501,7 +2411,7 @@ static DWORD query_global_option(DWORD option, void *buffer, DWORD *size, BOOL u
                     optionW->Value.dwValue = PROXY_TYPE_PROXY;
                 else
                     optionW->Value.dwValue = PROXY_TYPE_DIRECT;
-                if (have_url)
+                if (url)
                     /* native includes PROXY_TYPE_DIRECT even if PROXY_TYPE_PROXY is set */
                     optionW->Value.dwValue |= PROXY_TYPE_DIRECT|PROXY_TYPE_AUTO_PROXY_URL;
                 break;
@@ -2521,12 +2431,12 @@ static DWORD query_global_option(DWORD option, void *buffer, DWORD *size, BOOL u
                 break;
 
             case INTERNET_PER_CONN_AUTOCONFIG_URL:
-                if (!have_url)
+                if (!url)
                     optionW->Value.pszValue = NULL;
                 else if (unicode)
-                    optionW->Value.pszValue = heap_strdupAtoW(url);
+                    optionW->Value.pszValue = heap_strdupW(url);
                 else
-                    optionA->Value.pszValue = heap_strdupA(url);
+                    optionA->Value.pszValue = heap_strdupWtoA(url);
                 break;
 
             case INTERNET_PER_CONN_AUTODISCOVERY_FLAGS:
@@ -2547,6 +2457,7 @@ static DWORD query_global_option(DWORD option, void *buffer, DWORD *size, BOOL u
                 break;
             }
         }
+        heap_free(url);
         FreeProxyInfo(&pi);
 
         return res;
@@ -3390,13 +3301,12 @@ BOOL WINAPI InternetCheckConnectionW( LPCWSTR lpszUrl, DWORD dwFlags, DWORD dwRe
   BOOL   rc = FALSE;
   static const CHAR ping[] = "ping -c 1 ";
   static const CHAR redirect[] = " >/dev/null 2>/dev/null";
-  CHAR *command = NULL;
-  WCHAR hostW[INTERNET_MAX_HOST_NAME_LENGTH];
-  DWORD len;
+  WCHAR *host;
+  DWORD len, host_len;
   INTERNET_PORT port;
   int status = -1;
 
-  FIXME("\n");
+  FIXME("(%s %x %x)\n", debugstr_w(lpszUrl), dwFlags, dwReserved);
 
   /*
    * Crack or set the Address
@@ -3415,27 +3325,34 @@ BOOL WINAPI InternetCheckConnectionW( LPCWSTR lpszUrl, DWORD dwFlags, DWORD dwRe
   }
   else
   {
-     URL_COMPONENTSW components;
+     URL_COMPONENTSW components = {sizeof(components)};
 
-     ZeroMemory(&components,sizeof(URL_COMPONENTSW));
-     components.lpszHostName = (LPWSTR)hostW;
-     components.dwHostNameLength = INTERNET_MAX_HOST_NAME_LENGTH;
+     components.dwHostNameLength = 1;
 
      if (!InternetCrackUrlW(lpszUrl,0,0,&components))
        goto End;
 
-     TRACE("host name : %s\n",debugstr_w(components.lpszHostName));
+     host = components.lpszHostName;
+     host_len = components.dwHostNameLength;
      port = components.nPort;
-     TRACE("port: %d\n", port);
+     TRACE("host name: %s port: %d\n",debugstr_wn(host, host_len), port);
   }
 
   if (dwFlags & FLAG_ICC_FORCE_CONNECTION)
   {
       struct sockaddr_storage saddr;
-      socklen_t sa_len = sizeof(saddr);
+      int sa_len = sizeof(saddr);
+      WCHAR *host_z;
       int fd;
+      BOOL b;
+
+      host_z = heap_strndupW(host, host_len);
+      if (!host_z)
+          return FALSE;
 
-      if (!GetAddress(hostW, port, (struct sockaddr *)&saddr, &sa_len, NULL))
+      b = GetAddress(host_z, port, (struct sockaddr *)&saddr, &sa_len, NULL);
+      heap_free(host_z);
+      if(!b)
           goto End;
       init_winsock();
       fd = socket(saddr.ss_family, SOCK_STREAM, 0);
@@ -3451,15 +3368,18 @@ BOOL WINAPI InternetCheckConnectionW( LPCWSTR lpszUrl, DWORD dwFlags, DWORD dwRe
       /*
        * Build our ping command
        */
-      len = WideCharToMultiByte(CP_UNIXCP, 0, hostW, -1, NULL, 0, NULL, NULL);
-      command = heap_alloc(strlen(ping)+len+strlen(redirect));
-      strcpy(command,ping);
-      WideCharToMultiByte(CP_UNIXCP, 0, hostW, -1, command+strlen(ping), len, NULL, NULL);
-      strcat(command,redirect);
+      char *command;
+
+      len = WideCharToMultiByte(CP_UNIXCP, 0, host, host_len, NULL, 0, NULL, NULL);
+      command = heap_alloc(strlen(ping)+len+strlen(redirect)+1);
+      strcpy(command, ping);
+      WideCharToMultiByte(CP_UNIXCP, 0, host, host_len, command+sizeof(ping)-1, len, NULL, NULL);
+      strcpy(command+sizeof(ping)-1+len, redirect);
 
       TRACE("Ping command is : %s\n",command);
 
       status = system(command);
+      heap_free( command );
 
       TRACE("Ping returned a code of %i\n",status);
 
@@ -3469,7 +3389,6 @@ BOOL WINAPI InternetCheckConnectionW( LPCWSTR lpszUrl, DWORD dwFlags, DWORD dwRe
   }
 
 End:
-  heap_free( command );
   if (rc == FALSE)
     INTERNET_SetLastError(ERROR_NOT_CONNECTED);
 
@@ -3516,40 +3435,38 @@ BOOL WINAPI InternetCheckConnectionA(LPCSTR lpszUrl, DWORD dwFlags, DWORD dwRese
 static HINTERNET INTERNET_InternetOpenUrlW(appinfo_t *hIC, LPCWSTR lpszUrl,
     LPCWSTR lpszHeaders, DWORD dwHeadersLength, DWORD dwFlags, DWORD_PTR dwContext)
 {
-    URL_COMPONENTSW urlComponents;
-    WCHAR protocol[INTERNET_MAX_SCHEME_LENGTH];
-    WCHAR hostName[INTERNET_MAX_HOST_NAME_LENGTH];
-    WCHAR userName[INTERNET_MAX_USER_NAME_LENGTH];
-    WCHAR password[INTERNET_MAX_PASSWORD_LENGTH];
-    WCHAR path[INTERNET_MAX_PATH_LENGTH];
-    WCHAR extra[1024];
+    URL_COMPONENTSW urlComponents = { sizeof(urlComponents) };
+    WCHAR *host, *user = NULL, *pass = NULL, *path;
     HINTERNET client = NULL, client1 = NULL;
     DWORD res;
     
     TRACE("(%p, %s, %s, %08x, %08x, %08lx)\n", hIC, debugstr_w(lpszUrl), debugstr_w(lpszHeaders),
          dwHeadersLength, dwFlags, dwContext);
     
-    urlComponents.dwStructSize = sizeof(URL_COMPONENTSW);
-    urlComponents.lpszScheme = protocol;
-    urlComponents.dwSchemeLength = INTERNET_MAX_SCHEME_LENGTH;
-    urlComponents.lpszHostName = hostName;
-    urlComponents.dwHostNameLength = INTERNET_MAX_HOST_NAME_LENGTH;
-    urlComponents.lpszUserName = userName;
-    urlComponents.dwUserNameLength = INTERNET_MAX_USER_NAME_LENGTH;
-    urlComponents.lpszPassword = password;
-    urlComponents.dwPasswordLength = INTERNET_MAX_PASSWORD_LENGTH;
-    urlComponents.lpszUrlPath = path;
-    urlComponents.dwUrlPathLength = INTERNET_MAX_PATH_LENGTH;
-    urlComponents.lpszExtraInfo = extra;
-    urlComponents.dwExtraInfoLength = 1024;
+    urlComponents.dwHostNameLength = 1;
+    urlComponents.dwUserNameLength = 1;
+    urlComponents.dwPasswordLength = 1;
+    urlComponents.dwUrlPathLength = 1;
+    urlComponents.dwExtraInfoLength = 1;
     if(!InternetCrackUrlW(lpszUrl, strlenW(lpszUrl), 0, &urlComponents))
        return NULL;
+
+    if(urlComponents.nScheme == INTERNET_SCHEME_HTTP && urlComponents.dwExtraInfoLength) {
+        assert(urlComponents.lpszUrlPath + urlComponents.dwUrlPathLength == urlComponents.lpszExtraInfo);
+        urlComponents.dwUrlPathLength += urlComponents.dwExtraInfoLength;
+    }
+
+    host = heap_strndupW(urlComponents.lpszHostName, urlComponents.dwHostNameLength);
+    path = heap_strndupW(urlComponents.lpszUrlPath, urlComponents.dwUrlPathLength);
+    if(urlComponents.dwUserNameLength)
+        user = heap_strndupW(urlComponents.lpszUserName, urlComponents.dwUserNameLength);
+    if(urlComponents.dwPasswordLength)
+        pass = heap_strndupW(urlComponents.lpszPassword, urlComponents.dwPasswordLength);
+
     switch(urlComponents.nScheme) {
     case INTERNET_SCHEME_FTP:
-       if(urlComponents.nPort == 0)
-           urlComponents.nPort = INTERNET_DEFAULT_FTP_PORT;
-       client = FTP_Connect(hIC, hostName, urlComponents.nPort,
-                            userName, password, dwFlags, dwContext, INET_OPENURL);
+       client = FTP_Connect(hIC, host, urlComponents.nPort,
+                            user, pass, dwFlags, dwContext, INET_OPENURL);
        if(client == NULL)
            break;
        client1 = FtpOpenFileW(client, path, GENERIC_READ, dwFlags, dwContext);
@@ -3563,39 +3480,18 @@ static HINTERNET INTERNET_InternetOpenUrlW(appinfo_t *hIC, LPCWSTR lpszUrl,
     case INTERNET_SCHEME_HTTPS: {
        static const WCHAR szStars[] = { '*','/','*', 0 };
        LPCWSTR accept[2] = { szStars, NULL };
-       if(urlComponents.nPort == 0) {
-           if(urlComponents.nScheme == INTERNET_SCHEME_HTTP)
-               urlComponents.nPort = INTERNET_DEFAULT_HTTP_PORT;
-           else
-               urlComponents.nPort = INTERNET_DEFAULT_HTTPS_PORT;
-       }
+
         if (urlComponents.nScheme == INTERNET_SCHEME_HTTPS) dwFlags |= INTERNET_FLAG_SECURE;
 
         /* FIXME: should use pointers, not handles, as handles are not thread-safe */
-       res = HTTP_Connect(hIC, hostName, urlComponents.nPort,
-                           userName, password, dwFlags, dwContext, INET_OPENURL, &client);
+       res = HTTP_Connect(hIC, host, urlComponents.nPort,
+                           user, pass, dwFlags, dwContext, INET_OPENURL, &client);
         if(res != ERROR_SUCCESS) {
             INTERNET_SetLastError(res);
            break;
         }
 
-       if (urlComponents.dwExtraInfoLength) {
-               WCHAR *path_extra;
-               DWORD len = urlComponents.dwUrlPathLength + urlComponents.dwExtraInfoLength + 1;
-
-               if (!(path_extra = heap_alloc(len * sizeof(WCHAR))))
-               {
-                       InternetCloseHandle(client);
-                       break;
-               }
-               strcpyW(path_extra, urlComponents.lpszUrlPath);
-               strcatW(path_extra, urlComponents.lpszExtraInfo);
-               client1 = HttpOpenRequestW(client, NULL, path_extra, NULL, NULL, accept, dwFlags, dwContext);
-               heap_free(path_extra);
-       }
-       else
-               client1 = HttpOpenRequestW(client, NULL, path, NULL, NULL, accept, dwFlags, dwContext);
-
+        client1 = HttpOpenRequestW(client, NULL, path, NULL, NULL, accept, dwFlags, dwContext);
        if(client1 == NULL) {
            InternetCloseHandle(client);
            break;
@@ -3617,7 +3513,11 @@ static HINTERNET INTERNET_InternetOpenUrlW(appinfo_t *hIC, LPCWSTR lpszUrl,
     }
 
     TRACE(" %p <--\n", client1);
-    
+
+    heap_free(host);
+    heap_free(path);
+    heap_free(user);
+    heap_free(pass);
     return client1;
 }
 
@@ -3711,9 +3611,8 @@ HINTERNET WINAPI InternetOpenUrlA(HINTERNET hInternet, LPCSTR lpszUrl,
     LPCSTR lpszHeaders, DWORD dwHeadersLength, DWORD dwFlags, DWORD_PTR dwContext)
 {
     HINTERNET rc = NULL;
-    DWORD lenHeaders = 0;
     LPWSTR szUrl = NULL;
-    LPWSTR szHeaders = NULL;
+    WCHAR *headers = NULL;
 
     TRACE("\n");
 
@@ -3724,20 +3623,17 @@ HINTERNET WINAPI InternetOpenUrlA(HINTERNET hInternet, LPCSTR lpszUrl,
     }
 
     if(lpszHeaders) {
-        lenHeaders = MultiByteToWideChar(CP_ACP, 0, lpszHeaders, dwHeadersLength, NULL, 0 );
-        szHeaders = heap_alloc(lenHeaders*sizeof(WCHAR));
-        if(!szHeaders) {
+        headers = heap_strndupAtoW(lpszHeaders, dwHeadersLength, &dwHeadersLength);
+        if(!headers) {
             heap_free(szUrl);
             return NULL;
         }
-        MultiByteToWideChar(CP_ACP, 0, lpszHeaders, dwHeadersLength, szHeaders, lenHeaders);
     }
     
-    rc = InternetOpenUrlW(hInternet, szUrl, szHeaders,
-        lenHeaders, dwFlags, dwContext);
+    rc = InternetOpenUrlW(hInternet, szUrl, headers, dwHeadersLength, dwFlags, dwContext);
 
     heap_free(szUrl);
-    heap_free(szHeaders);
+    heap_free(headers);
     return rc;
 }
 
@@ -3957,6 +3853,7 @@ void req_file_release(req_file_t *req_file)
     if(req_file->file_handle && req_file->file_handle != INVALID_HANDLE_VALUE)
         CloseHandle(req_file->file_handle);
     heap_free(req_file->file_name);
+    heap_free(req_file->url);
     heap_free(req_file);
 }
 
@@ -4554,23 +4451,20 @@ BOOL WINAPI InternetGetSecurityInfoByURLA(LPSTR lpszURL, PCCERT_CHAIN_CONTEXT *p
  */
 BOOL WINAPI InternetGetSecurityInfoByURLW(LPCWSTR lpszURL, PCCERT_CHAIN_CONTEXT *ppCertChain, DWORD *pdwSecureFlags)
 {
-    WCHAR hostname[INTERNET_MAX_HOST_NAME_LENGTH];
     URL_COMPONENTSW url = {sizeof(url)};
     server_t *server;
-    BOOL res = FALSE;
+    BOOL res;
 
     TRACE("(%s %p %p)\n", debugstr_w(lpszURL), ppCertChain, pdwSecureFlags);
 
-    url.lpszHostName = hostname;
-    url.dwHostNameLength = sizeof(hostname)/sizeof(WCHAR);
-
+    url.dwHostNameLength = 1;
     res = InternetCrackUrlW(lpszURL, 0, 0, &url);
     if(!res || url.nScheme != INTERNET_SCHEME_HTTPS) {
         SetLastError(ERROR_INTERNET_ITEM_NOT_FOUND);
         return FALSE;
     }
 
-    server = get_server(hostname, url.nPort, TRUE, FALSE);
+    server = get_server(substr(url.lpszHostName, url.dwHostNameLength), url.nPort, TRUE, FALSE);
     if(!server) {
         SetLastError(ERROR_INTERNET_ITEM_NOT_FOUND);
         return FALSE;