[WININET]
authorAmine Khaldi <amine.khaldi@reactos.org>
Sat, 28 Sep 2013 15:25:41 +0000 (15:25 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Sat, 28 Sep 2013 15:25:41 +0000 (15:25 +0000)
* Sync with Wine 1.7.1.
CORE-7469

svn path=/trunk/; revision=60428

reactos/dll/win32/wininet/CMakeLists.txt
reactos/dll/win32/wininet/cookie.c
reactos/dll/win32/wininet/http.c
reactos/dll/win32/wininet/internet.c
reactos/dll/win32/wininet/internet.h
reactos/dll/win32/wininet/netconnection.c
reactos/dll/win32/wininet/rsrc.rc
reactos/dll/win32/wininet/urlcache.c
reactos/dll/win32/wininet/version.rc
reactos/media/doc/README.WINE

index 9819057..f7e449c 100644 (file)
@@ -20,13 +20,10 @@ list(APPEND SOURCE
     urlcache.c
     utility.c
     wininet_main.c
-    rsrc.rc
-    version.rc
     ${CMAKE_CURRENT_BINARY_DIR}/wininet_stubs.c
     ${CMAKE_CURRENT_BINARY_DIR}/wininet.def)
 
-add_library(wininet SHARED ${SOURCE})
-
+add_library(wininet SHARED ${SOURCE} rsrc.rc)
 set_module_type(wininet win32dll)
 target_link_libraries(wininet wine ${PSEH_LIB} zlib)
 add_delay_importlibs(wininet secur32 crypt32 cryptui)
index 443d7a6..642e009 100644 (file)
@@ -238,6 +238,7 @@ static BOOL load_persistent_cookie(LPCWSTR domain, LPCWSTR path)
         heap_free(name);
         heap_free(data);
     }
+    heap_free(str);
     heap_free(name);
     heap_free(data);
 
@@ -537,8 +538,11 @@ static void COOKIE_deleteDomain(cookie_domain *deadDomain)
 
 DWORD get_cookie(const WCHAR *host, const WCHAR *path, WCHAR *cookie_data, DWORD *size)
 {
+    static const WCHAR empty_path[] = { '/',0 };
+
     unsigned cnt = 0, len, name_len, domain_count = 0, cookie_count = 0;
-    WCHAR *ptr = cookie_data;
+    WCHAR *ptr, subpath[INTERNET_MAX_PATH_LENGTH];
+    const WCHAR *p;
     cookie_domain *domain;
     FILETIME tm;
 
@@ -546,8 +550,30 @@ DWORD get_cookie(const WCHAR *host, const WCHAR *path, WCHAR *cookie_data, DWORD
 
     EnterCriticalSection(&cookie_cs);
 
-    load_persistent_cookie(host, path);
+    len = strlenW(host);
+    p = host+len;
+    while(p>host && p[-1]!='.') p--;
+    while(p != host) {
+        p--;
+        while(p>host && p[-1]!='.') p--;
+        if(p == host) break;
+
+        load_persistent_cookie(p, empty_path);
+    }
+
+    len = strlenW(path);
+    assert(len+1 < INTERNET_MAX_PATH_LENGTH);
+    memcpy(subpath, path, (len+1)*sizeof(WCHAR));
+    ptr = subpath+len;
+    do {
+        *ptr = 0;
+        load_persistent_cookie(host, subpath);
+
+        ptr--;
+        while(ptr>subpath && ptr[-1]!='/') ptr--;
+    }while(ptr != subpath);
 
+    ptr = cookie_data;
     LIST_FOR_EACH_ENTRY(domain, &domain_list, cookie_domain, entry) {
         struct list *cursor, *cursor2;
 
index 6ba6d26..d1fc6d5 100644 (file)
@@ -148,6 +148,8 @@ static const WCHAR szVia[] = { 'V','i','a',0 };
 static const WCHAR szWarning[] = { 'W','a','r','n','i','n','g',0 };
 static const WCHAR szWWW_Authenticate[] = { 'W','W','W','-','A','u','t','h','e','n','t','i','c','a','t','e',0 };
 
+static const WCHAR emptyW[] = {0};
+
 #define HTTP_REFERER    szReferer
 #define HTTP_ACCEPT     szAccept
 #define HTTP_USERAGENT  szUser_Agent
@@ -214,7 +216,7 @@ static CRITICAL_SECTION_DEBUG critsect_debug =
 };
 static CRITICAL_SECTION authcache_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
 
-static BOOL HTTP_GetResponseHeaders(http_request_t *req, BOOL clear);
+static DWORD HTTP_GetResponseHeaders(http_request_t *req, INT *len);
 static DWORD HTTP_ProcessHeader(http_request_t *req, LPCWSTR field, LPCWSTR value, DWORD dwModifier);
 static LPWSTR * HTTP_InterpretHttpHeader(LPCWSTR buffer);
 static DWORD HTTP_InsertCustomHeader(http_request_t *req, LPHTTPHEADERW lpHdr);
@@ -597,62 +599,10 @@ static DWORD init_gzip_stream(http_request_t *req)
 
 #endif
 
-/***********************************************************************
- *           HTTP_Tokenize (internal)
- *
- *  Tokenize a string, allocating memory for the tokens.
- */
-static LPWSTR * HTTP_Tokenize(LPCWSTR string, LPCWSTR token_string)
-{
-    LPWSTR * token_array;
-    int tokens = 0;
-    int i;
-    LPCWSTR next_token;
-
-    if (string)
-    {
-        /* empty string has no tokens */
-        if (*string)
-            tokens++;
-        /* count tokens */
-        for (i = 0; string[i]; i++)
-        {
-            if (!strncmpW(string+i, token_string, strlenW(token_string)))
-            {
-                DWORD j;
-                tokens++;
-                /* we want to skip over separators, but not the null terminator */
-                for (j = 0; j < strlenW(token_string) - 1; j++)
-                    if (!string[i+j])
-                        break;
-                i += j;
-            }
-        }
-    }
-
-    /* add 1 for terminating NULL */
-    token_array = heap_alloc((tokens+1) * sizeof(*token_array));
-    token_array[tokens] = NULL;
-    if (!tokens)
-        return token_array;
-    for (i = 0; i < tokens; i++)
-    {
-        int len;
-        next_token = strstrW(string, token_string);
-        if (!next_token) next_token = string+strlenW(string);
-        len = next_token - string;
-        token_array[i] = heap_alloc((len+1)*sizeof(WCHAR));
-        memcpy(token_array[i], string, len*sizeof(WCHAR));
-        token_array[i][len] = '\0';
-        string = next_token+strlenW(token_string);
-    }
-    return token_array;
-}
-
 /***********************************************************************
  *           HTTP_FreeTokens (internal)
  *
- *  Frees memory returned from HTTP_Tokenize.
+ *  Frees table of pointers.
  */
 static void HTTP_FreeTokens(LPWSTR * token_array)
 {
@@ -696,20 +646,21 @@ static void HTTP_FixURL(http_request_t *request)
     }
 }
 
-static LPWSTR HTTP_BuildHeaderRequestString( http_request_t *request, LPCWSTR verb, LPCWSTR path, LPCWSTR version )
+static WCHAR* build_request_header(http_request_t *request, const WCHAR *verb,
+        const WCHAR *path, const WCHAR *version, BOOL use_cr)
 {
     LPWSTR requestString;
     DWORD len, n;
     LPCWSTR *req;
     UINT i;
-    LPWSTR p;
 
     static const WCHAR szSpace[] = { ' ',0 };
     static const WCHAR szColon[] = { ':',' ',0 };
-    static const WCHAR sztwocrlf[] = {'\r','\n','\r','\n', 0};
+    static const WCHAR szCr[] = { '\r',0 };
+    static const WCHAR szLf[] = { '\n',0 };
 
     /* allocate space for an array of all the string pointers to be added */
-    len = (request->nCustHeaders)*4 + 10;
+    len = (request->nCustHeaders)*5 + 10;
     req = heap_alloc(len*sizeof(LPCWSTR));
 
     /* add the verb, path and HTTP version string */
@@ -719,42 +670,90 @@ static LPWSTR HTTP_BuildHeaderRequestString( http_request_t *request, LPCWSTR ve
     req[n++] = path;
     req[n++] = szSpace;
     req[n++] = version;
+    if (use_cr)
+        req[n++] = szCr;
+    req[n++] = szLf;
 
     /* Append custom request headers */
     for (i = 0; i < request->nCustHeaders; i++)
     {
         if (request->custHeaders[i].wFlags & HDR_ISREQUEST)
         {
-            req[n++] = szCrLf;
             req[n++] = request->custHeaders[i].lpszField;
             req[n++] = szColon;
             req[n++] = request->custHeaders[i].lpszValue;
+            if (use_cr)
+                req[n++] = szCr;
+            req[n++] = szLf;
 
             TRACE("Adding custom header %s (%s)\n",
                    debugstr_w(request->custHeaders[i].lpszField),
                    debugstr_w(request->custHeaders[i].lpszValue));
         }
     }
-
-    if( n >= len )
-        ERR("oops. buffer overrun\n");
-
+    if (use_cr)
+        req[n++] = szCr;
+    req[n++] = szLf;
     req[n] = NULL;
+
     requestString = HTTP_build_req( req, 4 );
     heap_free( req );
-
-    /*
-     * Set (header) termination string for request
-     * Make sure there's exactly two new lines at the end of the request
-     */
-    p = &requestString[strlenW(requestString)-1];
-    while ( (*p == '\n') || (*p == '\r') )
-       p--;
-    strcpyW( p+1, sztwocrlf );
-    
     return requestString;
 }
 
+static WCHAR* build_response_header(http_request_t *request, BOOL use_cr)
+{
+    static const WCHAR colonW[] = { ':',' ',0 };
+    static const WCHAR crW[] = { '\r',0 };
+    static const WCHAR lfW[] = { '\n',0 };
+    static const WCHAR status_fmt[] = { ' ','%','u',' ',0 };
+
+    const WCHAR **req;
+    WCHAR *ret, buf[14];
+    DWORD i, n = 0;
+
+    req = heap_alloc((request->nCustHeaders*5+8)*sizeof(WCHAR*));
+    if(!req)
+        return NULL;
+
+    if (request->status_code)
+    {
+        req[n++] = request->version;
+        sprintfW(buf, status_fmt, request->status_code);
+        req[n++] = buf;
+        req[n++] = request->statusText;
+        if (use_cr)
+            req[n++] = crW;
+        req[n++] = lfW;
+    }
+
+    for(i = 0; i < request->nCustHeaders; i++)
+    {
+        if(!(request->custHeaders[i].wFlags & HDR_ISREQUEST)
+                && strcmpW(request->custHeaders[i].lpszField, szStatus))
+        {
+            req[n++] = request->custHeaders[i].lpszField;
+            req[n++] = colonW;
+            req[n++] = request->custHeaders[i].lpszValue;
+            if(use_cr)
+                req[n++] = crW;
+            req[n++] = lfW;
+
+            TRACE("Adding custom header %s (%s)\n",
+                    debugstr_w(request->custHeaders[i].lpszField),
+                    debugstr_w(request->custHeaders[i].lpszValue));
+        }
+    }
+    if(use_cr)
+        req[n++] = crW;
+    req[n++] = lfW;
+    req[n] = NULL;
+
+    ret = HTTP_build_req(req, 0);
+    heap_free(req);
+    return ret;
+}
+
 static void HTTP_ProcessCookies( http_request_t *request )
 {
     int HeaderIndex;
@@ -1714,6 +1713,88 @@ static WCHAR *build_proxy_path_url(http_request_t *req)
     return url;
 }
 
+static BOOL HTTP_DomainMatches(LPCWSTR server, LPCWSTR domain)
+{
+    static const WCHAR localW[] = { '<','l','o','c','a','l','>',0 };
+    BOOL ret = FALSE;
+
+    if (!strcmpiW( domain, localW ) && !strchrW( server, '.' ))
+        ret = TRUE;
+    else if (*domain == '*')
+    {
+        if (domain[1] == '.')
+        {
+            LPCWSTR dot;
+
+            /* For a hostname to match a wildcard, the last domain must match
+             * the wildcard exactly.  E.g. if the wildcard is *.a.b, and the
+             * hostname is www.foo.a.b, it matches, but a.b does not.
+             */
+            dot = strchrW( server, '.' );
+            if (dot)
+            {
+                int len = strlenW( dot + 1 );
+
+                if (len > strlenW( domain + 2 ))
+                {
+                    LPCWSTR ptr;
+
+                    /* The server's domain is longer than the wildcard, so it
+                     * could be a subdomain.  Compare the last portion of the
+                     * server's domain.
+                     */
+                    ptr = dot + len + 1 - strlenW( domain + 2 );
+                    if (!strcmpiW( ptr, domain + 2 ))
+                    {
+                        /* This is only a match if the preceding character is
+                         * a '.', i.e. that it is a matching domain.  E.g.
+                         * if domain is '*.b.c' and server is 'www.ab.c' they
+                         * do not match.
+                         */
+                        ret = *(ptr - 1) == '.';
+                    }
+                }
+                else
+                    ret = !strcmpiW( dot + 1, domain + 2 );
+            }
+        }
+    }
+    else
+        ret = !strcmpiW( server, domain );
+    return ret;
+}
+
+static BOOL HTTP_ShouldBypassProxy(appinfo_t *lpwai, LPCWSTR server)
+{
+    LPCWSTR ptr;
+    BOOL ret = FALSE;
+
+    if (!lpwai->proxyBypass) return FALSE;
+    ptr = lpwai->proxyBypass;
+    do {
+        LPCWSTR tmp = ptr;
+
+        ptr = strchrW( ptr, ';' );
+        if (!ptr)
+            ptr = strchrW( tmp, ' ' );
+        if (ptr)
+        {
+            if (ptr - tmp < INTERNET_MAX_HOST_NAME_LENGTH)
+            {
+                WCHAR domain[INTERNET_MAX_HOST_NAME_LENGTH];
+
+                memcpy( domain, tmp, (ptr - tmp) * sizeof(WCHAR) );
+                domain[ptr - tmp] = 0;
+                ret = HTTP_DomainMatches( server, domain );
+            }
+            ptr += 1;
+        }
+        else if (*tmp)
+            ret = HTTP_DomainMatches( server, tmp );
+    } while (ptr && !ret);
+    return ret;
+}
+
 /***********************************************************************
  *           HTTP_DealWithProxy
  */
@@ -1863,7 +1944,6 @@ static void HTTPREQ_Destroy(object_header_t *hdr)
 
     heap_free(request->path);
     heap_free(request->verb);
-    heap_free(request->rawHeaders);
     heap_free(request->version);
     heap_free(request->statusText);
 
@@ -1965,6 +2045,45 @@ static void HTTPREQ_CloseConnection(object_header_t *hdr)
     http_release_netconn(req, drain_content(req, FALSE));
 }
 
+static DWORD str_to_buffer(const WCHAR *str, void *buffer, DWORD *size, BOOL unicode)
+{
+    int len;
+    if (unicode)
+    {
+        WCHAR *buf = buffer;
+
+        if (str) len = strlenW(str);
+        else len = 0;
+        if (*size < (len + 1) * sizeof(WCHAR))
+        {
+            *size = (len + 1) * sizeof(WCHAR);
+            return ERROR_INSUFFICIENT_BUFFER;
+        }
+        if (str) strcpyW(buf, str);
+        else buf[0] = 0;
+
+        *size = len;
+        return ERROR_SUCCESS;
+    }
+    else
+    {
+        char *buf = buffer;
+
+        if (str) len = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0, NULL, NULL);
+        else len = 1;
+        if (*size < len)
+        {
+            *size = len;
+            return ERROR_INSUFFICIENT_BUFFER;
+        }
+        if (str) WideCharToMultiByte(CP_ACP, 0, str, -1, buf, *size, NULL, NULL);
+        else buf[0] = 0;
+
+        *size = len - 1;
+        return ERROR_SUCCESS;
+    }
+}
+
 static DWORD HTTPREQ_QueryOption(object_header_t *hdr, DWORD option, void *buffer, DWORD *size, BOOL unicode)
 {
     http_request_t *req = (http_request_t*)hdr;
@@ -1991,7 +2110,7 @@ static DWORD HTTPREQ_QueryOption(object_header_t *hdr, DWORD option, void *buffe
             info->Flags |= IDSI_FLAG_KEEP_ALIVE;
         if (req->proxy)
             info->Flags |= IDSI_FLAG_PROXY;
-        if (req->netconn->secure)
+        if (req->netconn && req->netconn->secure)
             info->Flags |= IDSI_FLAG_SECURE;
 
         return ERROR_SUCCESS;
@@ -2028,8 +2147,6 @@ static DWORD HTTPREQ_QueryOption(object_header_t *hdr, DWORD option, void *buffe
     case INTERNET_OPTION_URL: {
         WCHAR url[INTERNET_MAX_URL_LENGTH];
         HTTPHEADERW *host;
-        DWORD len;
-        WCHAR *pch;
 
         static const WCHAR httpW[] = {'h','t','t','p',':','/','/',0};
 
@@ -2038,29 +2155,21 @@ static DWORD HTTPREQ_QueryOption(object_header_t *hdr, DWORD option, void *buffe
         host = HTTP_GetHeader(req, hostW);
         strcpyW(url, httpW);
         strcatW(url, host->lpszValue);
-        if (NULL != (pch = strchrW(url + strlenW(httpW), ':')))
-            *pch = 0;
         strcatW(url, req->path);
 
         TRACE("INTERNET_OPTION_URL: %s\n",debugstr_w(url));
-
-        if(unicode) {
-            len = (strlenW(url)+1) * sizeof(WCHAR);
-            if(*size < len)
-                return ERROR_INSUFFICIENT_BUFFER;
-
-            *size = len;
-            strcpyW(buffer, url);
-            return ERROR_SUCCESS;
-        }else {
-            len = WideCharToMultiByte(CP_ACP, 0, url, -1, buffer, *size, NULL, NULL);
-            if(len > *size)
-                return ERROR_INSUFFICIENT_BUFFER;
-
-            *size = len;
-            return ERROR_SUCCESS;
-        }
+        return str_to_buffer(url, buffer, size, unicode);
     }
+    case INTERNET_OPTION_USER_AGENT:
+        return str_to_buffer(req->session->appInfo->agent, buffer, size, unicode);
+    case INTERNET_OPTION_USERNAME:
+        return str_to_buffer(req->session->userName, buffer, size, unicode);
+    case INTERNET_OPTION_PASSWORD:
+        return str_to_buffer(req->session->password, buffer, size, unicode);
+    case INTERNET_OPTION_PROXY_USERNAME:
+        return str_to_buffer(req->session->appInfo->proxyUsername, buffer, size, unicode);
+    case INTERNET_OPTION_PROXY_PASSWORD:
+        return str_to_buffer(req->session->appInfo->proxyPassword, buffer, size, unicode);
 
     case INTERNET_OPTION_CACHE_TIMESTAMPS: {
         INTERNET_CACHE_ENTRY_INFOW *info;
@@ -2129,6 +2238,9 @@ static DWORD HTTPREQ_QueryOption(object_header_t *hdr, DWORD option, void *buffe
     case INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT: {
         PCCERT_CONTEXT context;
 
+        if(!req->netconn)
+            return ERROR_INTERNET_INVALID_OPERATION;
+
         if(*size < sizeof(INTERNET_CERTIFICATE_INFOA)) {
             *size = sizeof(INTERNET_CERTIFICATE_INFOA);
             return ERROR_INSUFFICIENT_BUFFER;
@@ -2182,7 +2294,7 @@ static DWORD HTTPREQ_QueryOption(object_header_t *hdr, DWORD option, void *buffe
 
         if(req->proxy)
             flags |= INTERNET_REQFLAG_VIA_PROXY;
-        if(!req->rawHeaders)
+        if(!req->status_code)
             flags |= INTERNET_REQFLAG_NO_HEADERS;
 
         TRACE("INTERNET_OPTION_REQUEST_FLAGS returning %x\n", flags);
@@ -2248,6 +2360,17 @@ static DWORD HTTPREQ_SetOption(object_header_t *hdr, DWORD option, void *buffer,
         heap_free(req->session->password);
         if (!(req->session->password = heap_strdupW(buffer))) return ERROR_OUTOFMEMORY;
         return ERROR_SUCCESS;
+
+    case INTERNET_OPTION_PROXY_USERNAME:
+        heap_free(req->session->appInfo->proxyUsername);
+        if (!(req->session->appInfo->proxyUsername = heap_strdupW(buffer))) return ERROR_OUTOFMEMORY;
+        return ERROR_SUCCESS;
+
+    case INTERNET_OPTION_PROXY_PASSWORD:
+        heap_free(req->session->appInfo->proxyPassword);
+        if (!(req->session->appInfo->proxyPassword = heap_strdupW(buffer))) return ERROR_OUTOFMEMORY;
+        return ERROR_SUCCESS;
+
     case INTERNET_OPTION_HTTP_DECODING:
         if(size != sizeof(BOOL))
             return ERROR_INVALID_PARAMETER;
@@ -2268,12 +2391,15 @@ static void commit_cache_entry(http_request_t *req)
     req->hCacheFile = NULL;
 
     if(HTTP_GetRequestURL(req, url)) {
-        DWORD headersLen;
+        WCHAR *header;
+        DWORD header_len;
 
-        headersLen = req->rawHeaders ? strlenW(req->rawHeaders) : 0;
+        header = build_response_header(req, TRUE);
+        header_len = (header ? strlenW(header) : 0);
         CommitUrlCacheEntryW(url, req->cacheFile, req->expires,
                 req->last_modified, NORMAL_CACHE_ENTRY,
-                req->rawHeaders, headersLen, NULL, 0);
+                header, header_len, NULL, 0);
+        heap_free(header);
     }
 }
 
@@ -2296,9 +2422,30 @@ static void create_cache_entry(http_request_t *req)
 
     if(b) {
         int header_idx = HTTP_GetCustomHeaderIndex(req, szCache_Control, 0, FALSE);
-        if(header_idx!=-1 && (!strcmpiW(req->custHeaders[header_idx].lpszValue, no_cacheW)
-                    || !strcmpiW(req->custHeaders[header_idx].lpszValue, no_storeW)))
-            b = FALSE;
+        if(header_idx != -1) {
+            WCHAR *ptr;
+
+            for(ptr=req->custHeaders[header_idx].lpszValue; *ptr; ) {
+                WCHAR *end;
+
+                while(*ptr==' ' || *ptr=='\t')
+                    ptr++;
+
+                end = strchrW(ptr, ',');
+                if(!end)
+                    end = ptr + strlenW(ptr);
+
+                if(!strncmpiW(ptr, no_cacheW, sizeof(no_cacheW)/sizeof(*no_cacheW)-1)
+                        || !strncmpiW(ptr, no_storeW, sizeof(no_storeW)/sizeof(*no_storeW)-1)) {
+                    b = FALSE;
+                    break;
+                }
+
+                ptr = end;
+                if(*ptr == ',')
+                    ptr++;
+            }
+        }
     }
 
     if(!b) {
@@ -2372,7 +2519,7 @@ static void remove_data( http_request_t *req, int count )
     else req->read_pos += count;
 }
 
-static BOOL read_line( http_request_t *req, LPSTR buffer, DWORD *len )
+static DWORD read_line( http_request_t *req, LPSTR buffer, DWORD *len )
 {
     int count, bytes_read, pos = 0;
     DWORD res;
@@ -2395,13 +2542,18 @@ static BOOL read_line( http_request_t *req, LPSTR buffer, DWORD *len )
         remove_data( req, bytes_read );
         if (eol) break;
 
-        if ((res = read_more_data( req, -1 )) != ERROR_SUCCESS || !req->read_size)
+        if ((res = read_more_data( req, -1 )))
+        {
+            WARN( "read failed %u\n", res );
+            LeaveCriticalSection( &req->read_section );
+            return res;
+        }
+        if (!req->read_size)
         {
             *len = 0;
-            TRACE( "returning empty string %u\n", res);
+            TRACE( "returning empty string\n" );
             LeaveCriticalSection( &req->read_section );
-            INTERNET_SetLastError(res);
-            return FALSE;
+            return ERROR_SUCCESS;
         }
     }
     LeaveCriticalSection( &req->read_section );
@@ -2413,7 +2565,7 @@ static BOOL read_line( http_request_t *req, LPSTR buffer, DWORD *len )
     }
     buffer[*len - 1] = 0;
     TRACE( "returning %s\n", debugstr_a(buffer));
-    return TRUE;
+    return ERROR_SUCCESS;
 }
 
 /* check if we have reached the end of the data to read (the read section must be held) */
@@ -2498,6 +2650,7 @@ static DWORD netconn_read(data_stream_t *stream, http_request_t *req, BYTE *buf,
         DWORD *read, read_mode_t read_mode)
 {
     netconn_stream_t *netconn_stream = (netconn_stream_t*)stream;
+    DWORD res = ERROR_SUCCESS;
     int len = 0;
 
     size = min(size, netconn_stream->content_length-netconn_stream->content_read);
@@ -2509,7 +2662,7 @@ static DWORD netconn_read(data_stream_t *stream, http_request_t *req, BYTE *buf,
     }
 
     if(size && req->netconn) {
-        if(NETCON_recv(req->netconn, buf, size, read_mode == READMODE_SYNC ? MSG_WAITALL : 0, &len) != ERROR_SUCCESS)
+        if((res = NETCON_recv(req->netconn, buf, size, read_mode == READMODE_SYNC ? MSG_WAITALL : 0, &len)))
             len = 0;
         if(!len)
             netconn_stream->content_length = netconn_stream->content_read;
@@ -2517,7 +2670,7 @@ static DWORD netconn_read(data_stream_t *stream, http_request_t *req, BYTE *buf,
 
     netconn_stream->content_read += *read = len;
     TRACE("read %u bytes\n", len);
-    return ERROR_SUCCESS;
+    return res;
 }
 
 static BOOL netconn_drain_content(data_stream_t *stream, http_request_t *req)
@@ -2787,8 +2940,10 @@ static DWORD set_content_length(http_request_t *request)
         static const WCHAR gzipW[] = {'g','z','i','p',0};
 
         encoding_idx = HTTP_GetCustomHeaderIndex(request, szContent_Encoding, 0, FALSE);
-        if(encoding_idx != -1 && !strcmpiW(request->custHeaders[encoding_idx].lpszValue, gzipW))
+        if(encoding_idx != -1 && !strcmpiW(request->custHeaders[encoding_idx].lpszValue, gzipW)) {
+            HTTP_DeleteCustomHeader(request, encoding_idx);
             return init_gzip_stream(request);
+        }
     }
 
     return ERROR_SUCCESS;
@@ -3205,7 +3360,7 @@ static DWORD HTTP_HttpOpenRequestW(http_session_t *session,
     if (session->hostPort == INTERNET_INVALID_PORT_NUMBER)
         session->hostPort = INTERNET_DEFAULT_HTTP_PORT;
 
-    if (hIC->proxy && hIC->proxy[0])
+    if (hIC->proxy && hIC->proxy[0] && !HTTP_ShouldBypassProxy(hIC, session->hostName))
         HTTP_DealWithProxy( hIC, session, request );
 
     INTERNET_SendCallback(&session->hdr, dwContext,
@@ -3382,13 +3537,13 @@ static DWORD HTTP_HttpQueryInfoW(http_request_t *request, DWORD dwInfoLevel,
             DWORD res = ERROR_INVALID_PARAMETER;
 
             if (request_only)
-                headers = HTTP_BuildHeaderRequestString(request, request->verb, request->path, request->version);
+                headers = build_request_header(request, request->verb, request->path, request->version, TRUE);
             else
-                headers = request->rawHeaders;
-
-            if (headers)
-                len = strlenW(headers) * sizeof(WCHAR);
+                headers = build_response_header(request, TRUE);
+            if (!headers)
+                return ERROR_OUTOFMEMORY;
 
+            len = strlenW(headers) * sizeof(WCHAR);
             if (len + sizeof(WCHAR) > *lpdwBufferLength)
             {
                 len += sizeof(WCHAR);
@@ -3396,50 +3551,51 @@ static DWORD HTTP_HttpQueryInfoW(http_request_t *request, DWORD dwInfoLevel,
             }
             else if (lpBuffer)
             {
-                if (headers)
-                    memcpy(lpBuffer, headers, len + sizeof(WCHAR));
-                else
-                {
-                    len = strlenW(szCrLf) * sizeof(WCHAR);
-                    memcpy(lpBuffer, szCrLf, sizeof(szCrLf));
-                }
+                memcpy(lpBuffer, headers, len + sizeof(WCHAR));
                 TRACE("returning data: %s\n", debugstr_wn(lpBuffer, len / sizeof(WCHAR)));
                 res = ERROR_SUCCESS;
             }
             *lpdwBufferLength = len;
 
-            if (request_only) heap_free(headers);
+            heap_free(headers);
             return res;
         }
     case HTTP_QUERY_RAW_HEADERS:
         {
-            LPWSTR * ppszRawHeaderLines = HTTP_Tokenize(request->rawHeaders, szCrLf);
-            DWORD i, size = 0;
-            LPWSTR pszString = lpBuffer;
+            LPWSTR headers;
+            DWORD len;
 
-            for (i = 0; ppszRawHeaderLines[i]; i++)
-                size += strlenW(ppszRawHeaderLines[i]) + 1;
+            if (request_only)
+                headers = build_request_header(request, request->verb, request->path, request->version, FALSE);
+            else
+                headers = build_response_header(request, FALSE);
+            if (!headers)
+                return ERROR_OUTOFMEMORY;
 
-            if (size + 1 > *lpdwBufferLength/sizeof(WCHAR))
+            len = strlenW(headers) * sizeof(WCHAR);
+            if (len > *lpdwBufferLength)
             {
-                HTTP_FreeTokens(ppszRawHeaderLines);
-                *lpdwBufferLength = (size + 1) * sizeof(WCHAR);
+                *lpdwBufferLength = len;
+                heap_free(headers);
                 return ERROR_INSUFFICIENT_BUFFER;
             }
-            if (pszString)
+
+            if (lpBuffer)
             {
-                for (i = 0; ppszRawHeaderLines[i]; i++)
+                DWORD i;
+
+                TRACE("returning data: %s\n", debugstr_wn(headers, len / sizeof(WCHAR)));
+
+                for (i=0; i<len; i++)
                 {
-                    DWORD len = strlenW(ppszRawHeaderLines[i]);
-                    memcpy(pszString, ppszRawHeaderLines[i], (len+1)*sizeof(WCHAR));
-                    pszString += len+1;
+                    if (headers[i] == '\n')
+                        headers[i] = 0;
                 }
-                *pszString = '\0';
-                TRACE("returning data: %s\n", debugstr_wn(lpBuffer, size));
+                memcpy(lpBuffer, headers, len + sizeof(WCHAR));
             }
-            *lpdwBufferLength = size * sizeof(WCHAR);
-            HTTP_FreeTokens(ppszRawHeaderLines);
+            *lpdwBufferLength = len - sizeof(WCHAR);
 
+            heap_free(headers);
             return ERROR_SUCCESS;
         }
     case HTTP_QUERY_STATUS_TEXT:
@@ -3559,7 +3715,7 @@ static DWORD HTTP_HttpQueryInfoW(http_request_t *request, DWORD dwInfoLevel,
         STHook->wDayOfWeek = tmpTM.tm_wday;
         STHook->wMonth = tmpTM.tm_mon + 1;
         STHook->wSecond = tmpTM.tm_sec;
-        STHook->wYear = tmpTM.tm_year;
+        STHook->wYear = 1900+tmpTM.tm_year;
 
         TRACE(" returning time: %04d/%02d/%02d - %d - %02d:%02d:%02d.%02d\n",
               STHook->wYear, STHook->wMonth, STHook->wDay, STHook->wDayOfWeek,
@@ -3749,6 +3905,8 @@ BOOL WINAPI HttpQueryInfoA(HINTERNET hHttpRequest, DWORD dwInfoLevel,
     DWORD len;
     WCHAR* bufferW;
 
+    TRACE("%p %x\n", hHttpRequest, dwInfoLevel);
+
     if((dwInfoLevel & HTTP_QUERY_FLAG_NUMBER) ||
        (dwInfoLevel & HTTP_QUERY_FLAG_SYSTEMTIME))
     {
@@ -4027,7 +4185,7 @@ static DWORD HTTP_SecureProxyConnect(http_request_t *request)
 
     TRACE("\n");
 
-    requestString = HTTP_BuildHeaderRequestString( request, connectW, server->host_port, g_szHttp1_1 );
+    requestString = build_request_header( request, connectW, server->host_port, g_szHttp1_1, TRUE );
 
     len = WideCharToMultiByte( CP_ACP, 0, requestString, -1,
                                 NULL, 0, NULL, NULL );
@@ -4044,8 +4202,7 @@ static DWORD HTTP_SecureProxyConnect(http_request_t *request)
     if (res != ERROR_SUCCESS)
         return res;
 
-    responseLen = HTTP_GetResponseHeaders( request, TRUE );
-    if (!responseLen)
+    if (HTTP_GetResponseHeaders( request, &responseLen ) || !responseLen)
         return ERROR_HTTP_INVALID_HEADER;
 
     return ERROR_SUCCESS;
@@ -4596,8 +4753,9 @@ static void http_process_keep_alive(http_request_t *req)
 {
     int index;
 
-    index = HTTP_GetCustomHeaderIndex(req, szConnection, 0, FALSE);
-    if(index != -1)
+    if ((index = HTTP_GetCustomHeaderIndex(req, szConnection, 0, FALSE)) != -1)
+        req->netconn->keep_alive = !strcmpiW(req->custHeaders[index].lpszValue, szKeepAlive);
+    else if ((index = HTTP_GetCustomHeaderIndex(req, szProxy_Connection, 0, FALSE)) != -1)
         req->netconn->keep_alive = !strcmpiW(req->custHeaders[index].lpszValue, szKeepAlive);
     else
         req->netconn->keep_alive = !strcmpiW(req->version, g_szHttp1_1);
@@ -4703,7 +4861,6 @@ static DWORD HTTP_HttpSendRequestW(http_request_t *request, LPCWSTR lpszHeaders,
     LPWSTR requestString = NULL;
     INT responseLen;
     BOOL loop_next;
-    static const WCHAR szPost[] = { 'P','O','S','T',0 };
     static const WCHAR szContentLength[] =
         { 'C','o','n','t','e','n','t','-','L','e','n','g','t','h',':',' ','%','l','i','\r','\n',0 };
     WCHAR contentLengthStr[sizeof szContentLength/2 /* includes \r\n */ + 20 /* int */ ];
@@ -4741,7 +4898,7 @@ static DWORD HTTP_HttpSendRequestW(http_request_t *request, LPCWSTR lpszHeaders,
         static const WCHAR pragma_nocache[] = {'P','r','a','g','m','a',':',' ','n','o','-','c','a','c','h','e','\r','\n',0};
         HTTP_HttpAddRequestHeadersW(request, pragma_nocache, strlenW(pragma_nocache), HTTP_ADDREQ_FLAG_ADD_IF_NEW);
     }
-    if ((request->hdr.dwFlags & INTERNET_FLAG_NO_CACHE_WRITE) && !strcmpW(request->verb, szPost))
+    if ((request->hdr.dwFlags & INTERNET_FLAG_NO_CACHE_WRITE) && strcmpW(request->verb, szGET))
     {
         static const WCHAR cache_control[] = {'C','a','c','h','e','-','C','o','n','t','r','o','l',':',
                                               ' ','n','o','-','c','a','c','h','e','\r','\n',0};
@@ -4786,11 +4943,11 @@ static DWORD HTTP_HttpSendRequestW(http_request_t *request, LPCWSTR lpszHeaders,
         if (request->proxy)
         {
             WCHAR *url = build_proxy_path_url(request);
-            requestString = HTTP_BuildHeaderRequestString(request, request->verb, url, request->version);
+            requestString = build_request_header(request, request->verb, url, request->version, TRUE);
             heap_free(url);
         }
         else
-            requestString = HTTP_BuildHeaderRequestString(request, request->verb, request->path, request->version);
+            requestString = build_request_header(request, request->verb, request->path, request->version, TRUE);
 
  
         TRACE("Request header -> %s\n", debugstr_w(requestString) );
@@ -4840,7 +4997,12 @@ static DWORD HTTP_HttpSendRequestW(http_request_t *request, LPCWSTR lpszHeaders,
             INTERNET_SendCallback(&request->hdr, request->hdr.dwContext,
                                 INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
     
-            responseLen = HTTP_GetResponseHeaders(request, TRUE);
+            if (HTTP_GetResponseHeaders(request, &responseLen))
+            {
+                http_release_netconn(request, FALSE);
+                res = ERROR_INTERNET_CONNECTION_ABORTED;
+                goto lend;
+            }
             /* FIXME: We should know that connection is closed before sending
              * headers. Otherwise wrong callbacks are executed */
             if(!responseLen && reusing_connection) {
@@ -4942,6 +5104,7 @@ static DWORD HTTP_HttpSendRequestW(http_request_t *request, LPCWSTR lpszHeaders,
                                                  request->session->appInfo->proxyPassword,
                                                  NULL))
                         {
+                            heap_free(requestString);
                             if(!drain_content(request, TRUE)) {
                                 FIXME("Could not drain content\n");
                                 http_release_netconn(request, FALSE);
@@ -5033,8 +5196,7 @@ static DWORD HTTP_HttpEndRequestW(http_request_t *request, DWORD dwFlags, DWORD_
     INTERNET_SendCallback(&request->hdr, request->hdr.dwContext,
                   INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
 
-    responseLen = HTTP_GetResponseHeaders(request, TRUE);
-    if (!responseLen)
+    if (HTTP_GetResponseHeaders(request, &responseLen) || !responseLen)
         res = ERROR_HTTP_HEADER_NOT_FOUND;
 
     INTERNET_SendCallback(&request->hdr, request->hdr.dwContext,
@@ -5533,6 +5695,18 @@ static DWORD HTTPSESSION_SetOption(object_header_t *hdr, DWORD option, void *buf
         if (!(ses->password = heap_strdupW(buffer))) return ERROR_OUTOFMEMORY;
         return ERROR_SUCCESS;
     }
+    case INTERNET_OPTION_PROXY_USERNAME:
+    {
+        heap_free(ses->appInfo->proxyUsername);
+        if (!(ses->appInfo->proxyUsername = heap_strdupW(buffer))) return ERROR_OUTOFMEMORY;
+        return ERROR_SUCCESS;
+    }
+    case INTERNET_OPTION_PROXY_PASSWORD:
+    {
+        heap_free(ses->appInfo->proxyPassword);
+        if (!(ses->appInfo->proxyPassword = heap_strdupW(buffer))) return ERROR_OUTOFMEMORY;
+        return ERROR_SUCCESS;
+    }
     case INTERNET_OPTION_CONNECT_TIMEOUT:
     {
         if (!buffer || size != sizeof(DWORD)) return ERROR_INVALID_PARAMETER;
@@ -5611,10 +5785,6 @@ DWORD HTTP_Connect(appinfo_t *hIC, LPCWSTR lpszServerName,
     session->appInfo = hIC;
     list_add_head( &hIC->hdr.children, &session->hdr.entry );
 
-    if(hIC->proxy && hIC->accessType == INTERNET_OPEN_TYPE_PROXY) {
-        if(hIC->proxyBypass)
-            FIXME("Proxy bypass is ignored.\n");
-    }
     session->hostName = heap_strdupW(lpszServerName);
     if (lpszUserName && lpszUserName[0])
         session->userName = heap_strdupW(lpszUserName);
@@ -5676,19 +5846,15 @@ static void HTTP_clear_response_headers( http_request_t *request )
  *   TRUE  on success
  *   FALSE on error
  */
-static INT HTTP_GetResponseHeaders(http_request_t *request, BOOL clear)
+static DWORD HTTP_GetResponseHeaders(http_request_t *request, INT *len)
 {
     INT cbreaks = 0;
     WCHAR buffer[MAX_REPLY_LEN];
     DWORD buflen = MAX_REPLY_LEN;
-    BOOL bSuccess = FALSE;
     INT  rc = 0;
     char bufferA[MAX_REPLY_LEN];
     LPWSTR status_code = NULL, status_text = NULL;
-    DWORD cchMaxRawHeaders = 1024;
-    LPWSTR lpszRawHeaders = NULL;
-    LPWSTR temp;
-    DWORD cchRawHeaders = 0;
+    DWORD res = ERROR_HTTP_INVALID_SERVER_RESPONSE;
     BOOL codeHundred = FALSE;
 
     TRACE("-->\n");
@@ -5696,20 +5862,19 @@ static INT HTTP_GetResponseHeaders(http_request_t *request, BOOL clear)
     if(!request->netconn)
         goto lend;
 
+    /* clear old response headers (eg. from a redirect response) */
+    HTTP_clear_response_headers( request );
+
     NETCON_set_timeout( request->netconn, FALSE, request->receive_timeout );
     do {
         /*
          * We should first receive 'HTTP/1.x nnn OK' where nnn is the status code.
          */
         buflen = MAX_REPLY_LEN;
-        if (!read_line(request, bufferA, &buflen))
+        if ((res = read_line(request, bufferA, &buflen)))
             goto lend;
 
-        /* clear old response headers (eg. from a redirect response) */
-        if (clear) {
-            HTTP_clear_response_headers( request );
-            clear = FALSE;
-        }
+        if (!buflen) goto lend;
 
         rc += buflen;
         MultiByteToWideChar( CP_ACP, 0, bufferA, buflen, buffer, MAX_REPLY_LEN );
@@ -5724,9 +5889,8 @@ static INT HTTP_GetResponseHeaders(http_request_t *request, BOOL clear)
 
             /* split the status code from the status text */
             status_text = strchrW( status_code, ' ' );
-            if( !status_text )
-                goto lend;
-            *status_text++=0;
+            if( status_text )
+                *status_text++=0;
 
             request->status_code = atoiW(status_code);
 
@@ -5746,10 +5910,6 @@ static INT HTTP_GetResponseHeaders(http_request_t *request, BOOL clear)
             request->version = heap_strdupW(g_szHttp1_0);
             request->statusText = heap_strdupW(szOK);
 
-            heap_free(request->rawHeaders);
-            request->rawHeaders = heap_strdupW(szDefaultHeader);
-
-            bSuccess = TRUE;
             goto lend;
         }
     } while (codeHundred);
@@ -5762,32 +5922,18 @@ static INT HTTP_GetResponseHeaders(http_request_t *request, BOOL clear)
     heap_free(request->statusText);
 
     request->version = heap_strdupW(buffer);
-    request->statusText = heap_strdupW(status_text);
+    request->statusText = heap_strdupW(status_text ? status_text : emptyW);
 
     /* Restore the spaces */
     *(status_code-1) = ' ';
-    *(status_text-1) = ' ';
-
-    /* regenerate raw headers */
-    lpszRawHeaders = heap_alloc((cchMaxRawHeaders + 1) * sizeof(WCHAR));
-    if (!lpszRawHeaders) goto lend;
-
-    while (cchRawHeaders + buflen + strlenW(szCrLf) > cchMaxRawHeaders)
-        cchMaxRawHeaders *= 2;
-    temp = heap_realloc(lpszRawHeaders, (cchMaxRawHeaders+1)*sizeof(WCHAR));
-    if (temp == NULL) goto lend;
-    lpszRawHeaders = temp;
-    memcpy(lpszRawHeaders+cchRawHeaders, buffer, (buflen-1)*sizeof(WCHAR));
-    cchRawHeaders += (buflen-1);
-    memcpy(lpszRawHeaders+cchRawHeaders, szCrLf, sizeof(szCrLf));
-    cchRawHeaders += sizeof(szCrLf)/sizeof(szCrLf[0])-1;
-    lpszRawHeaders[cchRawHeaders] = '\0';
+    if (status_text)
+        *(status_text-1) = ' ';
 
     /* Parse each response line */
     do
     {
-       buflen = MAX_REPLY_LEN;
-        if (read_line(request, bufferA, &buflen))
+        buflen = MAX_REPLY_LEN;
+        if (!read_line(request, bufferA, &buflen) && buflen)
         {
             LPWSTR * pFieldAndValue;
 
@@ -5799,59 +5945,26 @@ static INT HTTP_GetResponseHeaders(http_request_t *request, BOOL clear)
             pFieldAndValue = HTTP_InterpretHttpHeader(buffer);
             if (pFieldAndValue)
             {
-                while (cchRawHeaders + buflen + strlenW(szCrLf) > cchMaxRawHeaders)
-                    cchMaxRawHeaders *= 2;
-                temp = heap_realloc(lpszRawHeaders, (cchMaxRawHeaders+1)*sizeof(WCHAR));
-                if (temp == NULL) goto lend;
-                lpszRawHeaders = temp;
-                memcpy(lpszRawHeaders+cchRawHeaders, buffer, (buflen-1)*sizeof(WCHAR));
-                cchRawHeaders += (buflen-1);
-                memcpy(lpszRawHeaders+cchRawHeaders, szCrLf, sizeof(szCrLf));
-                cchRawHeaders += sizeof(szCrLf)/sizeof(szCrLf[0])-1;
-                lpszRawHeaders[cchRawHeaders] = '\0';
-
                 HTTP_ProcessHeader(request, pFieldAndValue[0], pFieldAndValue[1],
                                    HTTP_ADDREQ_FLAG_ADD );
-
                 HTTP_FreeTokens(pFieldAndValue);
             }
         }
-       else
-       {
-           cbreaks++;
-           if (cbreaks >= 2)
-              break;
-       }
+        else
+        {
+            cbreaks++;
+            if (cbreaks >= 2)
+                break;
+        }
     }while(1);
 
-    /* make sure the response header is terminated with an empty line.  Some apps really
-       truly care about that empty line being there for some reason.  Just add it to the
-       header. */
-    if (cchRawHeaders + strlenW(szCrLf) > cchMaxRawHeaders)
-    {
-        cchMaxRawHeaders = cchRawHeaders + strlenW(szCrLf);
-        temp = heap_realloc(lpszRawHeaders, (cchMaxRawHeaders + 1) * sizeof(WCHAR));
-        if (temp == NULL) goto lend;
-        lpszRawHeaders = temp;
-    }
-
-    memcpy(&lpszRawHeaders[cchRawHeaders], szCrLf, sizeof(szCrLf));
-
-    heap_free(request->rawHeaders);
-    request->rawHeaders = lpszRawHeaders;
-    TRACE("raw headers: %s\n", debugstr_w(lpszRawHeaders));
-    bSuccess = TRUE;
+    res = ERROR_SUCCESS;
 
 lend:
 
+    *len = rc;
     TRACE("<--\n");
-    if (bSuccess)
-        return rc;
-    else
-    {
-        heap_free(lpszRawHeaders);
-        return 0;
-    }
+    return res;
 }
 
 /***********************************************************************
@@ -5967,7 +6080,7 @@ static DWORD HTTP_ProcessHeader(http_request_t *request, LPCWSTR field, LPCWSTR
     {
         HTTP_DeleteCustomHeader( request, index );
 
-        if (value)
+        if (value && value[0])
         {
             HTTPHEADERW hdr;
 
index 4dbd838..c1ed10d 100644 (file)
@@ -121,6 +121,7 @@ static const WCHAR szInternetSettings[] =
       'I','n','t','e','r','n','e','t',' ','S','e','t','t','i','n','g','s',0 };
 static const WCHAR szProxyServer[] = { 'P','r','o','x','y','S','e','r','v','e','r', 0 };
 static const WCHAR szProxyEnable[] = { 'P','r','o','x','y','E','n','a','b','l','e', 0 };
+static const WCHAR szProxyOverride[] = { 'P','r','o','x','y','O','v','e','r','r','i','d','e', 0 };
 
 void *alloc_object(object_header_t *parent, const object_vtbl_t *vtbl, size_t size)
 {
@@ -315,6 +316,7 @@ BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
             break;
 
         case DLL_PROCESS_DETACH:
+            if (lpvReserved) break;
             collect_connections(COLLECT_CLEANUP);
             NETCON_unload();
             free_urlcache();
@@ -613,9 +615,49 @@ static LONG INTERNET_LoadProxySettings( proxyinfo_t *lpwpi )
 
         TRACE("http proxy (from environment) = %s\n", debugstr_w(lpwpi->proxy));
     }
-    RegCloseKey( key );
 
     lpwpi->proxyBypass = NULL;
+    if (lpwpi->proxyEnabled)
+    {
+        if (!(envproxy = getenv( "no_proxy" )))
+        {
+            /* figure out how much memory the proxy setting takes */
+            if (!RegQueryValueExW( key, szProxyOverride, NULL, &type, NULL, &len ) && len && (type == REG_SZ))
+            {
+                LPWSTR szProxy;
+
+                if (!(szProxy = heap_alloc(len)))
+                {
+                    RegCloseKey( key );
+                    return ERROR_OUTOFMEMORY;
+                }
+                RegQueryValueExW( key, szProxyOverride, NULL, &type, (BYTE*)szProxy, &len );
+
+                lpwpi->proxyBypass = szProxy;
+
+                TRACE("http proxy bypass = %s\n", debugstr_w(lpwpi->proxyBypass));
+            }
+            else
+            {
+                TRACE("No proxy bypass server settings in registry.\n");
+            }
+        }
+        else if (envproxy)
+        {
+            WCHAR *envproxyW;
+
+            len = MultiByteToWideChar( CP_UNIXCP, 0, envproxy, -1, NULL, 0 );
+            if (!(envproxyW = heap_alloc(len * sizeof(WCHAR))))
+                return ERROR_OUTOFMEMORY;
+            MultiByteToWideChar( CP_UNIXCP, 0, envproxy, -1, envproxyW, len );
+
+            lpwpi->proxyBypass = envproxyW;
+
+            TRACE("http proxy bypass (from environment) = %s\n", debugstr_w(lpwpi->proxyBypass));
+        }
+    }
+
+    RegCloseKey( key );
 
     return ERROR_SUCCESS;
 }
@@ -625,7 +667,7 @@ static LONG INTERNET_LoadProxySettings( proxyinfo_t *lpwpi )
  */
 static BOOL INTERNET_ConfigureProxy( appinfo_t *lpwai )
 {
-    proxyinfo_t wpi;
+    proxyinfo_t wpi = {0};
 
     if (INTERNET_LoadProxySettings( &wpi ))
         return FALSE;
@@ -659,13 +701,15 @@ static BOOL INTERNET_ConfigureProxy( appinfo_t *lpwai )
 
             lpwai->accessType = INTERNET_OPEN_TYPE_PROXY;
             lpwai->proxy = heap_strdupW(proxyurl);
+            lpwai->proxyBypass = heap_strdupW(wpi.proxyBypass);
             if (UrlComponents.dwUserNameLength)
             {
                 lpwai->proxyUsername = heap_strdupW(UrlComponents.lpszUserName);
                 lpwai->proxyPassword = heap_strdupW(UrlComponents.lpszPassword);
             }
 
-            TRACE("http proxy = %s\n", debugstr_w(lpwai->proxy));
+            TRACE("http proxy = %s bypass = %s\n", debugstr_w(lpwai->proxy), debugstr_w(lpwai->proxyBypass));
+            FreeProxyInfo(&wpi);
             return TRUE;
         }
         else
@@ -676,6 +720,7 @@ static BOOL INTERNET_ConfigureProxy( appinfo_t *lpwai )
     }
 
     lpwai->accessType = INTERNET_OPEN_TYPE_DIRECT;
+    FreeProxyInfo(&wpi);
     return FALSE;
 }
 
@@ -794,7 +839,7 @@ static DWORD APPINFO_QueryOption(object_header_t *hdr, DWORD option, void *buffe
             /* If the buffer is copied, the returned length doesn't include
              * the NULL terminator.
              */
-            *size = len * sizeof(WCHAR);
+            *size = len;
         }else {
             if (ai->agent)
                 *size = WideCharToMultiByte(CP_ACP, 0, ai->agent, -1, NULL, 0, NULL, NULL);
@@ -985,6 +1030,11 @@ HINTERNET WINAPI InternetOpenW(LPCWSTR lpszAgent, DWORD dwAccessType,
     /* Clear any error information */
     INTERNET_SetLastError(0);
 
+    if((dwAccessType == INTERNET_OPEN_TYPE_PROXY) && !lpszProxy) {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return NULL;
+    }
+
     lpwai = alloc_object(NULL, &APPINFOVtbl, sizeof(appinfo_t));
     if (!lpwai) {
         SetLastError(ERROR_OUTOFMEMORY);
@@ -1001,9 +1051,10 @@ HINTERNET WINAPI InternetOpenW(LPCWSTR lpszAgent, DWORD dwAccessType,
     lpwai->agent = heap_strdupW(lpszAgent);
     if(dwAccessType == INTERNET_OPEN_TYPE_PRECONFIG)
         INTERNET_ConfigureProxy( lpwai );
-    else
+    else if(dwAccessType == INTERNET_OPEN_TYPE_PROXY) {
         lpwai->proxy = heap_strdupW(lpszProxy);
-    lpwai->proxyBypass = heap_strdupW(lpszProxyBypass);
+        lpwai->proxyBypass = heap_strdupW(lpszProxyBypass);
+    }
 
     TRACE("returning %p\n", lpwai);
 
@@ -1591,7 +1642,7 @@ static INTERNET_SCHEME GetInternetSchemeW(LPCWSTR lpszScheme, DWORD nMaxCmp)
         return INTERNET_SCHEME_UNKNOWN;
 
     for (i = 0; i < sizeof(url_schemes)/sizeof(url_schemes[0]); i++)
-        if (!strncmpW(lpszScheme, url_schemes[i], nMaxCmp))
+        if (!strncmpiW(lpszScheme, url_schemes[i], nMaxCmp))
             return INTERNET_SCHEME_FIRST + i;
 
     return INTERNET_SCHEME_UNKNOWN;
@@ -2954,11 +3005,11 @@ BOOL WINAPI InternetSetOptionA(HINTERNET hInternet, DWORD dwOption,
     case INTERNET_OPTION_USER_AGENT:
     case INTERNET_OPTION_USERNAME:
     case INTERNET_OPTION_PASSWORD:
-        wlen = MultiByteToWideChar( CP_ACP, 0, lpBuffer, dwBufferLength,
-                                   NULL, 0 );
-        wbuffer = heap_alloc(wlen*sizeof(WCHAR) );
-        MultiByteToWideChar( CP_ACP, 0, lpBuffer, dwBufferLength,
-                                   wbuffer, wlen );
+    case INTERNET_OPTION_PROXY_USERNAME:
+    case INTERNET_OPTION_PROXY_PASSWORD:
+        wlen = MultiByteToWideChar( CP_ACP, 0, lpBuffer, -1, NULL, 0 );
+        if (!(wbuffer = heap_alloc( wlen * sizeof(WCHAR) ))) return ERROR_OUTOFMEMORY;
+        MultiByteToWideChar( CP_ACP, 0, lpBuffer, -1, wbuffer, wlen );
         break;
     case INTERNET_OPTION_PER_CONNECTION_OPTION: {
         unsigned int i;
index 50bc2bb..1b6dd26 100644 (file)
@@ -91,8 +91,15 @@ typedef struct
 {
     int socket;
     BOOL secure;
-    void *ssl_s;
+    CtxtHandle ssl_ctx;
+    SecPkgContext_StreamSizes ssl_sizes;
     server_t *server;
+    char *ssl_buf;
+    char *extra_buf;
+    size_t extra_len;
+    char *peek_msg;
+    char *peek_msg_mem;
+    size_t peek_len;
     DWORD security_flags;
     BOOL mask_errors;
 
@@ -142,6 +149,21 @@ static inline LPWSTR heap_strdupW(LPCWSTR str)
     return ret;
 }
 
+static inline char *heap_strdupA(const char *str)
+{
+    char *ret = NULL;
+
+    if(str) {
+        DWORD size = strlen(str)+1;
+
+        ret = heap_alloc(size);
+        if(ret)
+            memcpy(ret, str, size);
+    }
+
+    return ret;
+}
+
 static inline LPWSTR heap_strndupW(LPCWSTR str, UINT max_len)
 {
     LPWSTR ret;
@@ -321,7 +343,6 @@ typedef struct
     server_t *proxy;
     LPWSTR path;
     LPWSTR verb;
-    LPWSTR rawHeaders;
     netconn_t *netconn;
     DWORD security_flags;
     DWORD connect_timeout;
index 6a2ee46..96efeaf 100644 (file)
@@ -1,7 +1,8 @@
 /*
- * Wininet - networking layer. Uses unix sockets or OpenSSL.
+ * Wininet - networking layer. Uses unix sockets.
  *
  * Copyright 2002 TransGaming Technologies Inc.
+ * Copyright 2013 Jacek Caban for CodeWeavers
  *
  * David Hammerton
  *
 #ifdef HAVE_NETINET_TCP_H
 # include <netinet/tcp.h>
 #endif
-#ifdef HAVE_OPENSSL_SSL_H
-# include <openssl/ssl.h>
-# include <openssl/opensslv.h>
-#undef FAR
-#undef DSA
-#endif
 
 #include <stdarg.h>
 //#include <stdlib.h>
@@ -102,124 +97,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(wininet);
 /* FIXME!!!!!!
  *    This should use winsock - To use winsock the functions will have to change a bit
  *        as they are designed for unix sockets.
- *    SSL stuff should use crypt32.dll
  */
 
-#ifdef SONAME_LIBSSL
-
-#include <openssl/err.h>
-
-static void *OpenSSL_ssl_handle;
-static void *OpenSSL_crypto_handle;
-
-#if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER > 0x10000000)
-static const SSL_METHOD *meth;
-#else
-static SSL_METHOD *meth;
-#endif
-static SSL_CTX *ctx;
-static int error_idx;
-static int conn_idx;
-
-#define MAKE_FUNCPTR(f) static typeof(f) * p##f
-
-/* OpenSSL functions that we use */
-MAKE_FUNCPTR(SSL_library_init);
-MAKE_FUNCPTR(SSL_load_error_strings);
-MAKE_FUNCPTR(SSLv23_method);
-MAKE_FUNCPTR(SSL_CTX_free);
-MAKE_FUNCPTR(SSL_CTX_new);
-MAKE_FUNCPTR(SSL_CTX_ctrl);
-MAKE_FUNCPTR(SSL_new);
-MAKE_FUNCPTR(SSL_free);
-MAKE_FUNCPTR(SSL_ctrl);
-MAKE_FUNCPTR(SSL_set_fd);
-MAKE_FUNCPTR(SSL_connect);
-MAKE_FUNCPTR(SSL_shutdown);
-MAKE_FUNCPTR(SSL_write);
-MAKE_FUNCPTR(SSL_read);
-MAKE_FUNCPTR(SSL_pending);
-MAKE_FUNCPTR(SSL_get_error);
-MAKE_FUNCPTR(SSL_get_ex_new_index);
-MAKE_FUNCPTR(SSL_get_ex_data);
-MAKE_FUNCPTR(SSL_set_ex_data);
-MAKE_FUNCPTR(SSL_get_ex_data_X509_STORE_CTX_idx);
-MAKE_FUNCPTR(SSL_get_peer_certificate);
-MAKE_FUNCPTR(SSL_CTX_get_timeout);
-MAKE_FUNCPTR(SSL_CTX_set_timeout);
-MAKE_FUNCPTR(SSL_CTX_set_default_verify_paths);
-MAKE_FUNCPTR(SSL_CTX_set_verify);
-MAKE_FUNCPTR(SSL_get_current_cipher);
-MAKE_FUNCPTR(SSL_CIPHER_get_bits);
-
-/* OpenSSL's libcrypto functions that we use */
-MAKE_FUNCPTR(BIO_new_fp);
-MAKE_FUNCPTR(CRYPTO_num_locks);
-MAKE_FUNCPTR(CRYPTO_set_id_callback);
-MAKE_FUNCPTR(CRYPTO_set_locking_callback);
-MAKE_FUNCPTR(ERR_free_strings);
-MAKE_FUNCPTR(ERR_get_error);
-MAKE_FUNCPTR(ERR_error_string);
-MAKE_FUNCPTR(X509_STORE_CTX_get_ex_data);
-MAKE_FUNCPTR(X509_STORE_CTX_get_chain);
-MAKE_FUNCPTR(i2d_X509);
-MAKE_FUNCPTR(sk_num);
-MAKE_FUNCPTR(sk_value);
-#undef MAKE_FUNCPTR
-
-static CRITICAL_SECTION *ssl_locks;
-static unsigned int num_ssl_locks;
-
-static unsigned long ssl_thread_id(void)
-{
-    return GetCurrentThreadId();
-}
-
-static void ssl_lock_callback(int mode, int type, const char *file, int line)
-{
-    if (mode & CRYPTO_LOCK)
-        EnterCriticalSection(&ssl_locks[type]);
-    else
-        LeaveCriticalSection(&ssl_locks[type]);
-}
-
-static PCCERT_CONTEXT X509_to_cert_context(X509 *cert)
-{
-    unsigned char* buffer,*p;
-    INT len;
-    BOOL malloced = FALSE;
-    PCCERT_CONTEXT ret;
-
-    p = NULL;
-    len = pi2d_X509(cert,&p);
-    /*
-     * SSL 0.9.7 and above malloc the buffer if it is null.
-     * however earlier version do not and so we would need to alloc the buffer.
-     *
-     * see the i2d_X509 man page for more details.
-     */
-    if (!p)
-    {
-        buffer = heap_alloc(len);
-        p = buffer;
-        len = pi2d_X509(cert,&p);
-    }
-    else
-    {
-        buffer = p;
-        malloced = TRUE;
-    }
-
-    ret = CertCreateCertificateContext(X509_ASN_ENCODING,buffer,len);
-
-    if (malloced)
-        free(buffer);
-    else
-        heap_free(buffer);
-
-    return ret;
-}
-
 static DWORD netconn_verify_cert(netconn_t *conn, PCCERT_CONTEXT cert, HCERTSTORE store)
 {
     BOOL ret;
@@ -377,238 +256,52 @@ static DWORD netconn_verify_cert(netconn_t *conn, PCCERT_CONTEXT cert, HCERTSTOR
     return ERROR_SUCCESS;
 }
 
-static int netconn_secure_verify(int preverify_ok, X509_STORE_CTX *ctx)
-{
-    SSL *ssl;
-    BOOL ret = FALSE;
-    HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
-        CERT_STORE_CREATE_NEW_FLAG, NULL);
-    netconn_t *conn;
-
-    ssl = pX509_STORE_CTX_get_ex_data(ctx,
-        pSSL_get_ex_data_X509_STORE_CTX_idx());
-    conn = pSSL_get_ex_data(ssl, conn_idx);
-    if (store)
-    {
-        X509 *cert;
-        int i;
-        PCCERT_CONTEXT endCert = NULL;
-        struct stack_st *chain = (struct stack_st *)pX509_STORE_CTX_get_chain( ctx );
-
-        ret = TRUE;
-        for (i = 0; ret && i < psk_num(chain); i++)
-        {
-            PCCERT_CONTEXT context;
-
-            cert = (X509 *)psk_value(chain, i);
-            if ((context = X509_to_cert_context(cert)))
-            {
-                ret = CertAddCertificateContextToStore(store, context,
-                        CERT_STORE_ADD_ALWAYS, i ? NULL : &endCert);
-                CertFreeCertificateContext(context);
-            }
-        }
-        if (!endCert) ret = FALSE;
-        if (ret)
-        {
-            DWORD_PTR err = netconn_verify_cert(conn, endCert, store);
-
-            if (err)
-            {
-                pSSL_set_ex_data(ssl, error_idx, (void *)err);
-                ret = FALSE;
-            }
-        }
-        CertFreeCertificateContext(endCert);
-        CertCloseStore(store, 0);
-    }
-    return ret;
-}
-
-static long get_tls_option(void) {
-    long tls_option = SSL_OP_NO_SSLv2; /* disable SSLv2 for security reason, secur32/Schannel(GnuTLS) don't support it */
-#ifdef SSL_OP_NO_TLSv1_2
-    DWORD type, val, size;
-    HKEY hkey,tls12_client,tls11_client;
-    LONG res;
-    const WCHAR Schannel_Prot[] = {  /* SYSTEM\\CurrentControlSet\\Control\\SecurityProviders\\SCANNEL\\Protocols */
-              'S','Y','S','T','E','M','\\',
-              'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
-              'C','o','n','t','r','o','l','\\',
-              'S','e','c','u','r','i','t','y','P','r','o','v','i','d','e','r','s','\\',
-              'S','C','H','A','N','N','E','L','\\',
-              'P','r','o','t','o','c','o','l','s',0 };
-     const WCHAR TLS12_Client[] = {'T','L','S',' ','1','.','2','\\','C','l','i','e','n','t',0};
-     const WCHAR TLS11_Client[] = {'T','L','S',' ','1','.','1','\\','C','l','i','e','n','t',0};
-     const WCHAR DisabledByDefault[] = {'D','i','s','a','b','l','e','d','B','y','D','e','f','a','u','l','t',0};
-
-    res = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
-          Schannel_Prot,
-          0, KEY_READ, &hkey);
-    if (res != ERROR_SUCCESS) { /* enabled TLSv1.1/1.2 when no registry entry */
-        return tls_option;
-    }
-    if (RegOpenKeyExW(hkey, TLS12_Client, 0, KEY_READ, &tls12_client) == ERROR_SUCCESS) {
-        size = sizeof(DWORD);
-        if (RegQueryValueExW(tls12_client, DisabledByDefault, NULL, &type,  (LPBYTE) &val, &size) == ERROR_SUCCESS
-            && type == REG_DWORD) {
-            tls_option |= val?SSL_OP_NO_TLSv1_2:0;
-        }
-        RegCloseKey(tls12_client);
-    }
-    if (RegOpenKeyExW(hkey, TLS11_Client, 0, KEY_READ, &tls11_client) == ERROR_SUCCESS) {
-        size = sizeof(DWORD);
-        if (RegQueryValueExW(tls11_client, DisabledByDefault, NULL, &type,  (LPBYTE) &val, &size) == ERROR_SUCCESS
-            && type == REG_DWORD) {
-            tls_option |= val?SSL_OP_NO_TLSv1_1:0;
-        }
-        RegCloseKey(tls11_client);
-    }
-    RegCloseKey(hkey);
-#endif
-    return tls_option;
-}
+static SecHandle cred_handle, compat_cred_handle;
+static BOOL cred_handle_initialized, have_compat_cred_handle;
 
-static CRITICAL_SECTION init_ssl_cs;
-static CRITICAL_SECTION_DEBUG init_ssl_cs_debug =
-{
-    0, 0, &init_ssl_cs,
-    { &init_ssl_cs_debug.ProcessLocksList,
-      &init_ssl_cs_debug.ProcessLocksList },
-    0, 0, { (DWORD_PTR)(__FILE__ ": init_ssl_cs") }
+static CRITICAL_SECTION init_sechandle_cs;
+static CRITICAL_SECTION_DEBUG init_sechandle_cs_debug = {
+    0, 0, &init_sechandle_cs,
+    { &init_sechandle_cs_debug.ProcessLocksList,
+      &init_sechandle_cs_debug.ProcessLocksList },
+    0, 0, { (DWORD_PTR)(__FILE__ ": init_sechandle_cs") }
 };
-static CRITICAL_SECTION init_ssl_cs = { &init_ssl_cs_debug, -1, 0, 0, 0, 0 };
+static CRITICAL_SECTION init_sechandle_cs = { &init_sechandle_cs_debug, -1, 0, 0, 0, 0 };
 
-static DWORD init_openssl(void)
+static BOOL ensure_cred_handle(void)
 {
-#ifdef SONAME_LIBCRYPTO
-    unsigned int i;
-
-    if(OpenSSL_ssl_handle)
-        return ERROR_SUCCESS;
-
-    OpenSSL_ssl_handle = wine_dlopen(SONAME_LIBSSL, RTLD_NOW, NULL, 0);
-    if(!OpenSSL_ssl_handle) {
-        ERR("trying to use a SSL connection, but couldn't load %s. Expect trouble.\n", SONAME_LIBSSL);
-        return ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
-    }
-
-    OpenSSL_crypto_handle = wine_dlopen(SONAME_LIBCRYPTO, RTLD_NOW, NULL, 0);
-    if(!OpenSSL_crypto_handle) {
-        ERR("trying to use a SSL connection, but couldn't load %s. Expect trouble.\n", SONAME_LIBCRYPTO);
-        return ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
-    }
-
-    /* mmm nice ugly macroness */
-#define DYNSSL(x) \
-    p##x = wine_dlsym(OpenSSL_ssl_handle, #x, NULL, 0); \
-    if (!p##x) { \
-        ERR("failed to load symbol %s\n", #x); \
-        return ERROR_INTERNET_SECURITY_CHANNEL_ERROR; \
-    }
-
-    DYNSSL(SSL_library_init);
-    DYNSSL(SSL_load_error_strings);
-    DYNSSL(SSLv23_method);
-    DYNSSL(SSL_CTX_free);
-    DYNSSL(SSL_CTX_new);
-    DYNSSL(SSL_CTX_ctrl);
-    DYNSSL(SSL_new);
-    DYNSSL(SSL_free);
-    DYNSSL(SSL_ctrl);
-    DYNSSL(SSL_set_fd);
-    DYNSSL(SSL_connect);
-    DYNSSL(SSL_shutdown);
-    DYNSSL(SSL_write);
-    DYNSSL(SSL_read);
-    DYNSSL(SSL_pending);
-    DYNSSL(SSL_get_error);
-    DYNSSL(SSL_get_ex_new_index);
-    DYNSSL(SSL_get_ex_data);
-    DYNSSL(SSL_set_ex_data);
-    DYNSSL(SSL_get_ex_data_X509_STORE_CTX_idx);
-    DYNSSL(SSL_get_peer_certificate);
-    DYNSSL(SSL_CTX_get_timeout);
-    DYNSSL(SSL_CTX_set_timeout);
-    DYNSSL(SSL_CTX_set_default_verify_paths);
-    DYNSSL(SSL_CTX_set_verify);
-    DYNSSL(SSL_get_current_cipher);
-    DYNSSL(SSL_CIPHER_get_bits);
-#undef DYNSSL
-
-#define DYNCRYPTO(x) \
-    p##x = wine_dlsym(OpenSSL_crypto_handle, #x, NULL, 0); \
-    if (!p##x) { \
-        ERR("failed to load symbol %s\n", #x); \
-        return ERROR_INTERNET_SECURITY_CHANNEL_ERROR; \
-    }
-
-    DYNCRYPTO(BIO_new_fp);
-    DYNCRYPTO(CRYPTO_num_locks);
-    DYNCRYPTO(CRYPTO_set_id_callback);
-    DYNCRYPTO(CRYPTO_set_locking_callback);
-    DYNCRYPTO(ERR_free_strings);
-    DYNCRYPTO(ERR_get_error);
-    DYNCRYPTO(ERR_error_string);
-    DYNCRYPTO(X509_STORE_CTX_get_ex_data);
-    DYNCRYPTO(X509_STORE_CTX_get_chain);
-    DYNCRYPTO(i2d_X509);
-    DYNCRYPTO(sk_num);
-    DYNCRYPTO(sk_value);
-#undef DYNCRYPTO
-
-#define pSSL_CTX_set_options(ctx,op) \
-       pSSL_CTX_ctrl((ctx),SSL_CTRL_OPTIONS,(op),NULL)
-#define pSSL_set_options(ssl,op) \
-       pSSL_ctrl((ssl),SSL_CTRL_OPTIONS,(op),NULL)
-
-    pSSL_library_init();
-    pSSL_load_error_strings();
-    pBIO_new_fp(stderr, BIO_NOCLOSE); /* FIXME: should use winedebug stuff */
-
-    meth = pSSLv23_method();
-    ctx = pSSL_CTX_new(meth);
-    pSSL_CTX_set_options(ctx, get_tls_option());
-    if(!pSSL_CTX_set_default_verify_paths(ctx)) {
-        ERR("SSL_CTX_set_default_verify_paths failed: %s\n",
-            pERR_error_string(pERR_get_error(), 0));
-        return ERROR_OUTOFMEMORY;
-    }
-
-    error_idx = pSSL_get_ex_new_index(0, (void *)"error index", NULL, NULL, NULL);
-    if(error_idx == -1) {
-        ERR("SSL_get_ex_new_index failed; %s\n", pERR_error_string(pERR_get_error(), 0));
-        return ERROR_OUTOFMEMORY;
-    }
+    SECURITY_STATUS res = SEC_E_OK;
+
+    EnterCriticalSection(&init_sechandle_cs);
+
+    if(!cred_handle_initialized) {
+        SCHANNEL_CRED cred = {SCHANNEL_CRED_VERSION};
+        SecPkgCred_SupportedProtocols prots;
+
+        res = AcquireCredentialsHandleW(NULL, (WCHAR*)UNISP_NAME_W, SECPKG_CRED_OUTBOUND, NULL, &cred,
+                NULL, NULL, &cred_handle, NULL);
+        if(res == SEC_E_OK) {
+            res = QueryCredentialsAttributesA(&cred_handle, SECPKG_ATTR_SUPPORTED_PROTOCOLS, &prots);
+            if(res != SEC_E_OK || (prots.grbitProtocol & SP_PROT_TLS1_1PLUS_CLIENT)) {
+                cred.grbitEnabledProtocols = prots.grbitProtocol & ~SP_PROT_TLS1_1PLUS_CLIENT;
+                res = AcquireCredentialsHandleW(NULL, (WCHAR*)UNISP_NAME_W, SECPKG_CRED_OUTBOUND, NULL, &cred,
+                       NULL, NULL, &compat_cred_handle, NULL);
+                have_compat_cred_handle = res == SEC_E_OK;
+            }
+        }
 
-    conn_idx = pSSL_get_ex_new_index(0, (void *)"netconn index", NULL, NULL, NULL);
-    if(conn_idx == -1) {
-        ERR("SSL_get_ex_new_index failed; %s\n", pERR_error_string(pERR_get_error(), 0));
-        return ERROR_OUTOFMEMORY;
+        cred_handle_initialized = res == SEC_E_OK;
     }
 
-    pSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, netconn_secure_verify);
+    LeaveCriticalSection(&init_sechandle_cs);
 
-    pCRYPTO_set_id_callback(ssl_thread_id);
-    num_ssl_locks = pCRYPTO_num_locks();
-    ssl_locks = heap_alloc(num_ssl_locks * sizeof(CRITICAL_SECTION));
-    if(!ssl_locks)
-        return ERROR_OUTOFMEMORY;
-
-    for(i = 0; i < num_ssl_locks; i++)
-    {
-        InitializeCriticalSection(&ssl_locks[i]);
-        ssl_locks[i].DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ssl_locks");
+    if(res != SEC_E_OK) {
+        WARN("Failed: %08x\n", res);
+        return FALSE;
     }
-    pCRYPTO_set_locking_callback(ssl_lock_callback);
 
-    return ERROR_SUCCESS;
-#else
-    FIXME("can't use SSL, libcrypto not compiled in.\n");
-    return ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
-#endif
+    return TRUE;
 }
-#endif /* SONAME_LIBSSL */
 
 static DWORD create_netconn_socket(server_t *server, netconn_t *netconn, DWORD timeout)
 {
@@ -673,20 +366,6 @@ DWORD create_netconn(BOOL useSSL, server_t *server, DWORD security_flags, BOOL m
     netconn_t *netconn;
     int result;
 
-#ifdef SONAME_LIBSSL
-    if(useSSL) {
-        DWORD res;
-
-        TRACE("using SSL connection\n");
-
-        EnterCriticalSection(&init_ssl_cs);
-        res = init_openssl();
-        LeaveCriticalSection(&init_ssl_cs);
-        if(res != ERROR_SUCCESS)
-            return res;
-    }
-#endif
-
     netconn = heap_alloc_zero(sizeof(*netconn));
     if(!netconn)
         return ERROR_OUTOFMEMORY;
@@ -713,10 +392,16 @@ void free_netconn(netconn_t *netconn)
     server_release(netconn->server);
 
     if (netconn->secure) {
-#ifdef SONAME_LIBSSL
-        pSSL_shutdown(netconn->ssl_s);
-        pSSL_free(netconn->ssl_s);
-#endif
+        heap_free(netconn->peek_msg_mem);
+        netconn->peek_msg_mem = NULL;
+        netconn->peek_msg = NULL;
+        netconn->peek_len = 0;
+        heap_free(netconn->ssl_buf);
+        netconn->ssl_buf = NULL;
+        heap_free(netconn->extra_buf);
+        netconn->extra_buf = NULL;
+        netconn->extra_len = 0;
+        DeleteSecurityContext(&netconn->ssl_ctx);
     }
 
     closesocket(netconn->socket);
@@ -725,29 +410,11 @@ void free_netconn(netconn_t *netconn)
 
 void NETCON_unload(void)
 {
-#if defined(SONAME_LIBSSL) && defined(SONAME_LIBCRYPTO)
-    if (OpenSSL_crypto_handle)
-    {
-        pERR_free_strings();
-        wine_dlclose(OpenSSL_crypto_handle, NULL, 0);
-    }
-    if (OpenSSL_ssl_handle)
-    {
-        if (ctx)
-            pSSL_CTX_free(ctx);
-        wine_dlclose(OpenSSL_ssl_handle, NULL, 0);
-    }
-    if (ssl_locks)
-    {
-        unsigned int i;
-        for (i = 0; i < num_ssl_locks; i++)
-        {
-            ssl_locks[i].DebugInfo->Spare[0] = 0;
-            DeleteCriticalSection(&ssl_locks[i]);
-        }
-        heap_free(ssl_locks);
-    }
-#endif
+    if(cred_handle_initialized)
+        FreeCredentialsHandle(&cred_handle);
+    if(have_compat_cred_handle)
+        FreeCredentialsHandle(&compat_cred_handle);
+    DeleteCriticalSection(&init_sechandle_cs);
 }
 
 #ifndef __REACTOS__
@@ -819,48 +486,149 @@ int sock_get_error( int err )
 }
 #endif
 
-#ifdef SONAME_LIBSSL
-static DWORD netcon_secure_connect_setup(netconn_t *connection, long tls_option)
+static DWORD netcon_secure_connect_setup(netconn_t *connection, BOOL compat_mode)
 {
-    void *ssl_s;
-    DWORD res;
+    SecBuffer out_buf = {0, SECBUFFER_TOKEN, NULL}, in_bufs[2] = {{0, SECBUFFER_TOKEN}, {0, SECBUFFER_EMPTY}};
+    SecBufferDesc out_desc = {SECBUFFER_VERSION, 1, &out_buf}, in_desc = {SECBUFFER_VERSION, 2, in_bufs};
+    SecHandle *cred = &cred_handle;
+    BYTE *read_buf;
+    SIZE_T read_buf_size = 2048;
+    ULONG attrs = 0;
+    CtxtHandle ctx;
+    SSIZE_T size;
     int bits;
+    const CERT_CONTEXT *cert;
+    SECURITY_STATUS status;
+    DWORD res = ERROR_SUCCESS;
 
-    ssl_s = pSSL_new(ctx);
-    if (!ssl_s)
-    {
-        ERR("SSL_new failed: %s\n",
-            pERR_error_string(pERR_get_error(), 0));
-        return ERROR_OUTOFMEMORY;
-    }
+    const DWORD isc_req_flags = ISC_REQ_ALLOCATE_MEMORY|ISC_REQ_USE_SESSION_KEY|ISC_REQ_CONFIDENTIALITY
+        |ISC_REQ_SEQUENCE_DETECT|ISC_REQ_REPLAY_DETECT|ISC_REQ_MANUAL_CRED_VALIDATION;
 
-    pSSL_set_options(ssl_s, tls_option);
-    if (!pSSL_set_fd(ssl_s, connection->socket))
-    {
-        ERR("SSL_set_fd failed: %s\n",
-            pERR_error_string(pERR_get_error(), 0));
-        res = ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
-        goto fail;
-    }
+    if(!ensure_cred_handle())
+        return FALSE;
 
-    if (!pSSL_set_ex_data(ssl_s, conn_idx, connection))
-    {
-        ERR("SSL_set_ex_data failed: %s\n",
-            pERR_error_string(pERR_get_error(), 0));
-        res = ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
-        goto fail;
+    if(compat_mode) {
+        if(!have_compat_cred_handle)
+            return ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
+        cred = &compat_cred_handle;
     }
-    if (pSSL_connect(ssl_s) <= 0)
-    {
-        res = (DWORD_PTR)pSSL_get_ex_data(ssl_s, error_idx);
-        if (!res)
+
+    read_buf = heap_alloc(read_buf_size);
+    if(!read_buf)
+        return ERROR_OUTOFMEMORY;
+
+    status = InitializeSecurityContextW(cred, NULL, connection->server->name, isc_req_flags, 0, 0, NULL, 0,
+            &ctx, &out_desc, &attrs, NULL);
+
+    assert(status != SEC_E_OK);
+
+    while(status == SEC_I_CONTINUE_NEEDED || status == SEC_E_INCOMPLETE_MESSAGE) {
+        if(out_buf.cbBuffer) {
+            assert(status == SEC_I_CONTINUE_NEEDED);
+
+            TRACE("sending %u bytes\n", out_buf.cbBuffer);
+
+            size = send(connection->socket, out_buf.pvBuffer, out_buf.cbBuffer, 0);
+            if(size != out_buf.cbBuffer) {
+                ERR("send failed\n");
+                status = ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
+                break;
+            }
+
+            FreeContextBuffer(out_buf.pvBuffer);
+            out_buf.pvBuffer = NULL;
+            out_buf.cbBuffer = 0;
+        }
+
+        if(status == SEC_I_CONTINUE_NEEDED) {
+            assert(in_bufs[1].cbBuffer < read_buf_size);
+
+            memmove(read_buf, (BYTE*)in_bufs[0].pvBuffer+in_bufs[0].cbBuffer-in_bufs[1].cbBuffer, in_bufs[1].cbBuffer);
+            in_bufs[0].cbBuffer = in_bufs[1].cbBuffer;
+
+            in_bufs[1].BufferType = SECBUFFER_EMPTY;
+            in_bufs[1].cbBuffer = 0;
+            in_bufs[1].pvBuffer = NULL;
+        }
+
+        assert(in_bufs[0].BufferType == SECBUFFER_TOKEN);
+        assert(in_bufs[1].BufferType == SECBUFFER_EMPTY);
+
+        if(in_bufs[0].cbBuffer + 1024 > read_buf_size) {
+            BYTE *new_read_buf;
+
+            new_read_buf = heap_realloc(read_buf, read_buf_size + 1024);
+            if(!new_read_buf) {
+                status = E_OUTOFMEMORY;
+                break;
+            }
+
+            in_bufs[0].pvBuffer = read_buf = new_read_buf;
+            read_buf_size += 1024;
+        }
+
+        size = recv(connection->socket, read_buf+in_bufs[0].cbBuffer, read_buf_size-in_bufs[0].cbBuffer, 0);
+        if(size < 1) {
+            WARN("recv error\n");
             res = ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
-        ERR("SSL_connect failed: %d\n", res);
-        goto fail;
+            break;
+        }
+
+        TRACE("recv %lu bytes\n", size);
+
+        in_bufs[0].cbBuffer += size;
+        in_bufs[0].pvBuffer = read_buf;
+        status = InitializeSecurityContextW(cred, &ctx, connection->server->name,  isc_req_flags, 0, 0, &in_desc,
+                0, NULL, &out_desc, &attrs, NULL);
+        TRACE("InitializeSecurityContext ret %08x\n", status);
+
+        if(status == SEC_E_OK) {
+            if(in_bufs[1].BufferType == SECBUFFER_EXTRA)
+                FIXME("SECBUFFER_EXTRA not supported\n");
+
+            status = QueryContextAttributesW(&ctx, SECPKG_ATTR_STREAM_SIZES, &connection->ssl_sizes);
+            if(status != SEC_E_OK) {
+                WARN("Could not get sizes\n");
+                break;
+            }
+
+            status = QueryContextAttributesW(&ctx, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (void*)&cert);
+            if(status == SEC_E_OK) {
+                res = netconn_verify_cert(connection, cert, cert->hCertStore);
+                CertFreeCertificateContext(cert);
+                if(res != ERROR_SUCCESS) {
+                    WARN("cert verify failed: %u\n", res);
+                    break;
+                }
+            }else {
+                WARN("Could not get cert\n");
+                break;
+            }
+
+            connection->ssl_buf = heap_alloc(connection->ssl_sizes.cbHeader + connection->ssl_sizes.cbMaximumMessage
+                    + connection->ssl_sizes.cbTrailer);
+            if(!connection->ssl_buf) {
+                res = GetLastError();
+                break;
+            }
+        }
     }
 
-    connection->ssl_s = ssl_s;
+
+    if(status != SEC_E_OK || res != ERROR_SUCCESS) {
+        WARN("Failed to initialize security context failed: %08x\n", status);
+        heap_free(connection->ssl_buf);
+        connection->ssl_buf = NULL;
+        DeleteSecurityContext(&ctx);
+        return res ? res : ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
+    }
+
+
+    TRACE("established SSL connection\n");
+    connection->ssl_ctx = ctx;
+
     connection->secure = TRUE;
+    connection->security_flags |= SECURITY_FLAG_SECURE;
 
     bits = NETCON_GetCipherStrength(connection);
     if (bits >= 128)
@@ -869,21 +637,11 @@ static DWORD netcon_secure_connect_setup(netconn_t *connection, long tls_option)
         connection->security_flags |= SECURITY_FLAG_STRENGTH_MEDIUM;
     else
         connection->security_flags |= SECURITY_FLAG_STRENGTH_WEAK;
-    connection->security_flags |= SECURITY_FLAG_SECURE;
 
     if(connection->mask_errors)
         connection->server->security_flags = connection->security_flags;
     return ERROR_SUCCESS;
-
-fail:
-    if (ssl_s)
-    {
-        pSSL_shutdown(ssl_s);
-        pSSL_free(ssl_s);
-    }
-    return res;
 }
-#endif
 
 /******************************************************************************
  * NETCON_secure_connect
@@ -891,7 +649,7 @@ fail:
  */
 DWORD NETCON_secure_connect(netconn_t *connection, server_t *server)
 {
-    DWORD res = ERROR_NOT_SUPPORTED;
+    DWORD res;
 
     /* can't connect if we are already connected */
     if(connection->secure) {
@@ -905,31 +663,50 @@ DWORD NETCON_secure_connect(netconn_t *connection, server_t *server)
         connection->server = server;
     }
 
-#ifdef SONAME_LIBSSL
     /* connect with given TLS options */
-    res = netcon_secure_connect_setup(connection, get_tls_option());
+    res = netcon_secure_connect_setup(connection, FALSE);
     if (res == ERROR_SUCCESS)
         return res;
 
-#ifdef SSL_OP_NO_TLSv1_2
     /* FIXME: when got version alert and FIN from server */
     /* fallback to connect without TLSv1.1/TLSv1.2        */
-    if (res == ERROR_INTERNET_SECURITY_CHANNEL_ERROR)
+    if (res == ERROR_INTERNET_SECURITY_CHANNEL_ERROR && have_compat_cred_handle)
     {
         closesocket(connection->socket);
-        pSSL_CTX_set_options(ctx,SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1_2);
         res = create_netconn_socket(connection->server, connection, 500);
         if (res != ERROR_SUCCESS)
             return res;
-        res = netcon_secure_connect_setup(connection, get_tls_option()|SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1_2);
+        res = netcon_secure_connect_setup(connection, TRUE);
     }
-#endif
-#else
-    FIXME("Cannot connect, OpenSSL not available.\n");
-#endif
     return res;
 }
 
+static BOOL send_ssl_chunk(netconn_t *conn, const void *msg, size_t size)
+{
+    SecBuffer bufs[4] = {
+        {conn->ssl_sizes.cbHeader, SECBUFFER_STREAM_HEADER, conn->ssl_buf},
+        {size,  SECBUFFER_DATA, conn->ssl_buf+conn->ssl_sizes.cbHeader},
+        {conn->ssl_sizes.cbTrailer, SECBUFFER_STREAM_TRAILER, conn->ssl_buf+conn->ssl_sizes.cbHeader+size},
+        {0, SECBUFFER_EMPTY, NULL}
+    };
+    SecBufferDesc buf_desc = {SECBUFFER_VERSION, sizeof(bufs)/sizeof(*bufs), bufs};
+    SECURITY_STATUS res;
+
+    memcpy(bufs[1].pvBuffer, msg, size);
+    res = EncryptMessage(&conn->ssl_ctx, 0, &buf_desc, 0);
+    if(res != SEC_E_OK) {
+        WARN("EncryptMessage failed\n");
+        return FALSE;
+    }
+
+    if(send(conn->socket, conn->ssl_buf, bufs[0].cbBuffer+bufs[1].cbBuffer+bufs[2].cbBuffer, 0) < 1) {
+        WARN("send failed\n");
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
 /******************************************************************************
  * NETCON_send
  * Basically calls 'send()' unless we should use SSL
@@ -947,24 +724,118 @@ DWORD NETCON_send(netconn_t *connection, const void *msg, size_t len, int flags,
     }
     else
     {
-#ifdef SONAME_LIBSSL
-        if(!connection->secure) {
-            FIXME("not connected\n");
-            return ERROR_NOT_SUPPORTED;
+        const BYTE *ptr = msg;
+        size_t chunk_size;
+
+        *sent = 0;
+
+        while(len) {
+            chunk_size = min(len, connection->ssl_sizes.cbMaximumMessage);
+            if(!send_ssl_chunk(connection, ptr, chunk_size))
+                return ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
+
+            *sent += chunk_size;
+            ptr += chunk_size;
+            len -= chunk_size;
         }
-       if (flags)
-            FIXME("SSL_write doesn't support any flags (%08x)\n", flags);
-       *sent = pSSL_write(connection->ssl_s, msg, len);
-       if (*sent < 1 && len)
-           return ERROR_INTERNET_CONNECTION_ABORTED;
+
         return ERROR_SUCCESS;
-#else
-        FIXME("not supported on this platform\n");
-       return ERROR_NOT_SUPPORTED;
-#endif
     }
 }
 
+static BOOL read_ssl_chunk(netconn_t *conn, void *buf, SIZE_T buf_size, SIZE_T *ret_size, BOOL *eof)
+{
+    const SIZE_T ssl_buf_size = conn->ssl_sizes.cbHeader+conn->ssl_sizes.cbMaximumMessage+conn->ssl_sizes.cbTrailer;
+    SecBuffer bufs[4];
+    SecBufferDesc buf_desc = {SECBUFFER_VERSION, sizeof(bufs)/sizeof(*bufs), bufs};
+    SSIZE_T size, buf_len;
+    int i;
+    SECURITY_STATUS res;
+
+    assert(conn->extra_len < ssl_buf_size);
+
+    if(conn->extra_len) {
+        memcpy(conn->ssl_buf, conn->extra_buf, conn->extra_len);
+        buf_len = conn->extra_len;
+        conn->extra_len = 0;
+        heap_free(conn->extra_buf);
+        conn->extra_buf = NULL;
+    }else {
+        buf_len = recv(conn->socket, conn->ssl_buf+conn->extra_len, ssl_buf_size-conn->extra_len, 0);
+        if(buf_len < 0) {
+            WARN("recv failed\n");
+            return FALSE;
+        }
+
+        if(!buf_len) {
+            *eof = TRUE;
+            return TRUE;
+        }
+    }
+
+    *ret_size = 0;
+    *eof = FALSE;
+
+    do {
+        memset(bufs, 0, sizeof(bufs));
+        bufs[0].BufferType = SECBUFFER_DATA;
+        bufs[0].cbBuffer = buf_len;
+        bufs[0].pvBuffer = conn->ssl_buf;
+
+        res = DecryptMessage(&conn->ssl_ctx, &buf_desc, 0, NULL);
+        switch(res) {
+        case SEC_E_OK:
+            break;
+        case SEC_I_CONTEXT_EXPIRED:
+            TRACE("context expired\n");
+            *eof = TRUE;
+            return TRUE;
+        case SEC_E_INCOMPLETE_MESSAGE:
+            assert(buf_len < ssl_buf_size);
+
+            size = recv(conn->socket, conn->ssl_buf+buf_len, ssl_buf_size-buf_len, 0);
+            if(size < 1)
+                return FALSE;
+
+            buf_len += size;
+            continue;
+        default:
+            WARN("failed: %08x\n", res);
+            return FALSE;
+        }
+    } while(res != SEC_E_OK);
+
+    for(i=0; i < sizeof(bufs)/sizeof(*bufs); i++) {
+        if(bufs[i].BufferType == SECBUFFER_DATA) {
+            size = min(buf_size, bufs[i].cbBuffer);
+            memcpy(buf, bufs[i].pvBuffer, size);
+            if(size < bufs[i].cbBuffer) {
+                assert(!conn->peek_len);
+                conn->peek_msg_mem = conn->peek_msg = heap_alloc(bufs[i].cbBuffer - size);
+                if(!conn->peek_msg)
+                    return FALSE;
+                conn->peek_len = bufs[i].cbBuffer-size;
+                memcpy(conn->peek_msg, (char*)bufs[i].pvBuffer+size, conn->peek_len);
+            }
+
+            *ret_size = size;
+        }
+    }
+
+    for(i=0; i < sizeof(bufs)/sizeof(*bufs); i++) {
+        if(bufs[i].BufferType == SECBUFFER_EXTRA) {
+            conn->extra_buf = heap_alloc(bufs[i].cbBuffer);
+            if(!conn->extra_buf)
+                return FALSE;
+
+            conn->extra_len = bufs[i].cbBuffer;
+            memcpy(conn->extra_buf, bufs[i].pvBuffer, conn->extra_len);
+        }
+    }
+
+    return TRUE;
+}
+
 /******************************************************************************
  * NETCON_recv
  * Basically calls 'recv()' unless we should use SSL
@@ -983,23 +854,46 @@ DWORD NETCON_recv(netconn_t *connection, void *buf, size_t len, int flags, int *
     }
     else
     {
-#ifdef SONAME_LIBSSL
-        if(!connection->secure) {
-            FIXME("not connected\n");
-            return ERROR_NOT_SUPPORTED;
+        SIZE_T size = 0, cread;
+        BOOL res, eof;
+
+        if(connection->peek_msg) {
+            size = min(len, connection->peek_len);
+            memcpy(buf, connection->peek_msg, size);
+            connection->peek_len -= size;
+            connection->peek_msg += size;
+
+            if(!connection->peek_len) {
+                heap_free(connection->peek_msg_mem);
+                connection->peek_msg_mem = connection->peek_msg = NULL;
+            }
+            /* check if we have enough data from the peek buffer */
+            if(!(flags & MSG_WAITALL) || size == len) {
+                *recvd = size;
+                return ERROR_SUCCESS;
+            }
         }
-       *recvd = pSSL_read(connection->ssl_s, buf, len);
 
-        /* Check if EOF was received */
-        if(!*recvd && (pSSL_get_error(connection->ssl_s, *recvd)==SSL_ERROR_ZERO_RETURN
-                    || pSSL_get_error(connection->ssl_s, *recvd)==SSL_ERROR_SYSCALL))
-            return ERROR_SUCCESS;
+        do {
+            res = read_ssl_chunk(connection, (BYTE*)buf+size, len-size, &cread, &eof);
+            if(!res) {
+                WARN("read_ssl_chunk failed\n");
+                if(!size)
+                    return ERROR_INTERNET_CONNECTION_ABORTED;
+                break;
+            }
 
-        return *recvd > 0 ? ERROR_SUCCESS : ERROR_INTERNET_CONNECTION_ABORTED;
-#else
-        FIXME("not supported on this platform\n");
-       return ERROR_NOT_SUPPORTED;
-#endif
+            if(eof) {
+                TRACE("EOF\n");
+                break;
+            }
+
+            size += cread;
+        }while(!size || ((flags & MSG_WAITALL) && size < len));
+
+        TRACE("received %ld bytes\n", size);
+        *recvd = size;
+        return ERROR_SUCCESS;
     }
 }
 
@@ -1026,12 +920,7 @@ BOOL NETCON_query_data_available(netconn_t *connection, DWORD *available)
     }
     else
     {
-#ifdef SONAME_LIBSSL
-        *available = pSSL_pending(connection->ssl_s);
-#else
-        FIXME("not supported on this platform\n");
-        return FALSE;
-#endif
+        *available = connection->peek_len;
     }
     return TRUE;
 }
@@ -1068,43 +957,28 @@ BOOL NETCON_is_alive(netconn_t *netconn)
 
 LPCVOID NETCON_GetCert(netconn_t *connection)
 {
-#ifdef SONAME_LIBSSL
-    X509* cert;
-    LPCVOID r = NULL;
+    const CERT_CONTEXT *ret;
+    SECURITY_STATUS res;
 
     if (!connection->secure)
         return NULL;
 
-    cert = pSSL_get_peer_certificate(connection->ssl_s);
-    r = X509_to_cert_context(cert);
-    return r;
-#else
-    FIXME("not supported on this platform\n");
-    return NULL;
-#endif
+    res = QueryContextAttributesW(&connection->ssl_ctx, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (void*)&ret);
+    return res == SEC_E_OK ? ret : NULL;
 }
 
 int NETCON_GetCipherStrength(netconn_t *connection)
 {
-#ifdef SONAME_LIBSSL
-#if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x0090707f)
-    const SSL_CIPHER *cipher;
-#else
-    SSL_CIPHER *cipher;
-#endif
-    int bits = 0;
+    SecPkgContext_ConnectionInfo conn_info;
+    SECURITY_STATUS res;
 
     if (!connection->secure)
         return 0;
-    cipher = pSSL_get_current_cipher(connection->ssl_s);
-    if (!cipher)
-        return 0;
-    pSSL_CIPHER_get_bits(cipher, &bits);
-    return bits;
-#else
-    FIXME("not supported on this platform\n");
-    return 0;
-#endif
+
+    res = QueryContextAttributesW(&connection->ssl_ctx, SECPKG_ATTR_CONNECTION_INFO, (void*)&conn_info);
+    if(res != SEC_E_OK)
+        WARN("QueryContextAttributesW failed: %08x\n", res);
+    return res == SEC_E_OK ? conn_info.dwCipherStrength : 0;
 }
 
 DWORD NETCON_set_timeout(netconn_t *connection, BOOL send, DWORD value)
index 6ca5a85..040a63e 100644 (file)
 #ifdef LANGUAGE_ZH_CN
     #include "lang/wininet_Zh.rc"
 #endif
+
+#include "version.rc"
index 166f780..ae94478 100644 (file)
@@ -67,6 +67,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(wininet);
 static const char urlcache_ver_prefix[] = "WINE URLCache Ver ";
 static const char urlcache_ver[] = "0.2012001";
 
+#ifndef CHAR_BIT
+#define CHAR_BIT    (8 * sizeof(CHAR))
+#endif
+
 #define ENTRY_START_OFFSET      0x4000
 #define DIR_LENGTH              8
 #define MAX_DIR_NO              0x20
@@ -77,7 +81,7 @@ static const char urlcache_ver[] = "0.2012001";
 #define ALLOCATION_TABLE_OFFSET 0x250
 #define ALLOCATION_TABLE_SIZE   (ENTRY_START_OFFSET - ALLOCATION_TABLE_OFFSET)
 #define MIN_BLOCK_NO            0x80
-#define MAX_BLOCK_NO            (ALLOCATION_TABLE_SIZE * 8)
+#define MAX_BLOCK_NO            (ALLOCATION_TABLE_SIZE * CHAR_BIT)
 #define FILE_SIZE(blocks)       ((blocks) * BLOCKSIZE + ENTRY_START_OFFSET)
 
 #define HASHTABLE_URL           0
@@ -104,6 +108,8 @@ static const char urlcache_ver[] = "0.2012001";
 
 #define DWORD_ALIGN(x) ( (DWORD)(((DWORD)(x)+sizeof(DWORD)-1)/sizeof(DWORD))*sizeof(DWORD) )
 
+#define URLCACHE_FIND_ENTRY_HANDLE_MAGIC 0xF389ABCD
+
 typedef struct
 {
     DWORD signature;
@@ -147,71 +153,243 @@ typedef struct
     /* CHAR szHeaderInfo[]; (header info) */
 } entry_url;
 
-struct _HASH_ENTRY
+struct hash_entry
 {
-    DWORD dwHashKey;
-    DWORD dwOffsetEntry;
+    DWORD key;
+    DWORD offset;
 };
 
-typedef struct _HASH_CACHEFILE_ENTRY
-{
-    entry_header CacheFileEntry;
-    DWORD dwAddressNext;
-    DWORD dwHashTableNumber;
-    struct _HASH_ENTRY HashTable[HASHTABLE_SIZE];
-} HASH_CACHEFILE_ENTRY;
-
-typedef struct _DIRECTORY_DATA
+typedef struct
 {
-    DWORD dwNumFiles;
-    char filename[DIR_LENGTH];
-} DIRECTORY_DATA;
+    entry_header header;
+    DWORD next;
+    DWORD id;
+    struct hash_entry hash_table[HASHTABLE_SIZE];
+} entry_hash_table;
 
-typedef struct _URLCACHE_HEADER
+typedef struct
 {
-    char szSignature[28];
-    DWORD dwFileSize;
-    DWORD dwOffsetFirstHashTable;
-    DWORD dwIndexCapacityInBlocks;
-    DWORD dwBlocksInUse;
-    DWORD dwUnknown1;
-    ULARGE_INTEGER CacheLimit;
-    ULARGE_INTEGER CacheUsage;
-    ULARGE_INTEGER ExemptUsage;
-    DWORD DirectoryCount;
-    DIRECTORY_DATA directory_data[MAX_DIR_NO];
+    char signature[28];
+    DWORD size;
+    DWORD hash_table_off;
+    DWORD capacity_in_blocks;
+    DWORD blocks_in_use;
+    DWORD unk1;
+    ULARGE_INTEGER cache_limit;
+    ULARGE_INTEGER cache_usage;
+    ULARGE_INTEGER exempt_usage;
+    DWORD dirs_no;
+    struct _directory_data
+    {
+        DWORD files_no;
+        char name[DIR_LENGTH];
+    } directory_data[MAX_DIR_NO];
     DWORD options[0x21];
     BYTE allocation_table[ALLOCATION_TABLE_SIZE];
-} URLCACHE_HEADER, *LPURLCACHE_HEADER;
-typedef const URLCACHE_HEADER *LPCURLCACHE_HEADER;
+} urlcache_header;
 
-typedef struct _STREAM_HANDLE
+typedef struct
 {
-    HANDLE hFile;
-    CHAR lpszUrl[1];
-} STREAM_HANDLE;
+    HANDLE file;
+    CHAR url[1];
+} stream_handle;
 
-typedef struct _URLCACHECONTAINER
+typedef struct
 {
     struct list entry; /* part of a list */
-    LPWSTR cache_prefix; /* string that has to be prefixed for this container to be used */
+    char *cache_prefix; /* string that has to be prefixed for this container to be used */
     LPWSTR path; /* path to url container directory */
-    HANDLE hMapping; /* handle of file mapping */
+    HANDLE mapping; /* handle of file mapping */
     DWORD file_size; /* size of file when mapping was opened */
-    HANDLE hMutex; /* handle of mutex */
+    HANDLE mutex; /* handle of mutex */
     DWORD default_entry_type;
-} URLCACHECONTAINER;
+} cache_container;
 
+typedef struct
+{
+    DWORD magic;
+    char *url_search_pattern;
+    DWORD container_idx;
+    DWORD hash_table_idx;
+    DWORD hash_entry_idx;
+} find_handle;
 
 /* List of all containers available */
 static struct list UrlContainers = LIST_INIT(UrlContainers);
 // ReactOS r54992
 BOOL bDefaultContainersAdded = FALSE;
 
-static DWORD URLCache_CreateHashTable(LPURLCACHE_HEADER pHeader, HASH_CACHEFILE_ENTRY *pPrevHash, HASH_CACHEFILE_ENTRY **ppHash);
+static inline char *heap_strdupWtoUTF8(LPCWSTR str)
+{
+    char *ret = NULL;
+
+    if(str) {
+        DWORD size = WideCharToMultiByte(CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL);
+        ret = heap_alloc(size);
+        if(ret)
+            WideCharToMultiByte(CP_UTF8, 0, str, -1, ret, size, NULL, NULL);
+    }
+
+    return ret;
+}
+
+/***********************************************************************
+ *           urlcache_block_is_free (Internal)
+ *
+ *  Is the specified block number free?
+ *
+ * RETURNS
+ *    zero if free
+ *    non-zero otherwise
+ *
+ */
+static inline BYTE urlcache_block_is_free(BYTE *allocation_table, DWORD block_number)
+{
+    BYTE mask = 1 << (block_number%CHAR_BIT);
+    return (allocation_table[block_number/CHAR_BIT] & mask) == 0;
+}
+
+/***********************************************************************
+ *           urlcache_block_free (Internal)
+ *
+ *  Marks the specified block as free
+ *
+ * CAUTION
+ *    this function is not updating used blocks count
+ *
+ * RETURNS
+ *    nothing
+ *
+ */
+static inline void urlcache_block_free(BYTE *allocation_table, DWORD block_number)
+{
+    BYTE mask = ~(1 << (block_number%CHAR_BIT));
+    allocation_table[block_number/CHAR_BIT] &= mask;
+}
+
+/***********************************************************************
+ *           urlcache_block_alloc (Internal)
+ *
+ *  Marks the specified block as allocated
+ *
+ * CAUTION
+ *     this function is not updating used blocks count
+ *
+ * RETURNS
+ *    nothing
+ *
+ */
+static inline void urlcache_block_alloc(BYTE *allocation_table, DWORD block_number)
+{
+    BYTE mask = 1 << (block_number%CHAR_BIT);
+    allocation_table[block_number/CHAR_BIT] |= mask;
+}
+
+/***********************************************************************
+ *           urlcache_entry_alloc (Internal)
+ *
+ *  Finds and allocates the first block of free space big enough and
+ * sets entry to point to it.
+ *
+ * RETURNS
+ *    ERROR_SUCCESS when free memory block was found
+ *    Any other Win32 error code if the entry could not be added
+ *
+ */
+static DWORD urlcache_entry_alloc(urlcache_header *header, DWORD blocks_needed, entry_header **entry)
+{
+    DWORD block, block_size;
+
+    for(block=0; block<header->capacity_in_blocks; block+=block_size+1)
+    {
+        block_size = 0;
+        while(block_size<blocks_needed && block_size+block<header->capacity_in_blocks
+                && urlcache_block_is_free(header->allocation_table, block+block_size))
+            block_size++;
+
+        if(block_size == blocks_needed)
+        {
+            DWORD index;
+
+            TRACE("Found free blocks starting at no. %d (0x%x)\n", block, ENTRY_START_OFFSET+block*BLOCKSIZE);
+
+            for(index=0; index<blocks_needed; index++)
+                urlcache_block_alloc(header->allocation_table, block+index);
+
+            *entry = (entry_header*)((BYTE*)header+ENTRY_START_OFFSET+block*BLOCKSIZE);
+            for(index=0; index<blocks_needed*BLOCKSIZE/sizeof(DWORD); index++)
+                ((DWORD*)*entry)[index] = 0xdeadbeef;
+            (*entry)->blocks_used = blocks_needed;
+
+            header->blocks_in_use += blocks_needed;
+            return ERROR_SUCCESS;
+        }
+    }
+
+    return ERROR_HANDLE_DISK_FULL;
+}
+
+/***********************************************************************
+ *           urlcache_entry_free (Internal)
+ *
+ *  Deletes the specified entry and frees the space allocated to it
+ *
+ * RETURNS
+ *    TRUE if it succeeded
+ *    FALSE if it failed
+ *
+ */
+static BOOL urlcache_entry_free(urlcache_header *header, entry_header *entry)
+{
+    DWORD start_block, block;
+
+    /* update allocation table */
+    start_block = ((DWORD)((BYTE*)entry - (BYTE*)header) - ENTRY_START_OFFSET) / BLOCKSIZE;
+    for(block = start_block; block < start_block+entry->blocks_used; block++)
+        urlcache_block_free(header->allocation_table, block);
+
+    header->blocks_in_use -= entry->blocks_used;
+    return TRUE;
+}
+
+/***********************************************************************
+ *           urlcache_create_hash_table (Internal)
+ *
+ *  Creates a new hash table in free space and adds it to the chain of existing
+ * hash tables.
+ *
+ * RETURNS
+ *    ERROR_SUCCESS if the hash table was created
+ *    ERROR_DISK_FULL if the hash table could not be created
+ *
+ */
+static DWORD urlcache_create_hash_table(urlcache_header *header, entry_hash_table *hash_table_prev, entry_hash_table **hash_table)
+{
+    DWORD dwOffset, error;
+    int i;
+
+    if((error = urlcache_entry_alloc(header, 0x20, (entry_header**)hash_table)) != ERROR_SUCCESS)
+        return error;
+
+    dwOffset = (BYTE*)*hash_table-(BYTE*)header;
+
+    if(hash_table_prev)
+        hash_table_prev->next = dwOffset;
+    else
+        header->hash_table_off = dwOffset;
+
+    (*hash_table)->header.signature = HASH_SIGNATURE;
+    (*hash_table)->next = 0;
+    (*hash_table)->id = hash_table_prev ? hash_table_prev->id+1 : 0;
+    for(i = 0; i < HASHTABLE_SIZE; i++) {
+        (*hash_table)->hash_table[i].offset = HASHTABLE_FREE;
+        (*hash_table)->hash_table[i].key = HASHTABLE_FREE;
+    }
+    return ERROR_SUCCESS;
+}
 
 /***********************************************************************
- *           URLCache_PathToObjectName (Internal)
+ *           cache_container_create_object_name (Internal)
  *
  *  Converts a path to a name suitable for use as a Win32 object name.
  * Replaces '\\' characters in-place with the specified character
@@ -221,7 +399,7 @@ static DWORD URLCache_CreateHashTable(LPURLCACHE_HEADER pHeader, HASH_CACHEFILE_
  *    nothing
  *
  */
-static void URLCache_PathToObjectName(LPWSTR lpszPath, WCHAR replace)
+static void cache_container_create_object_name(LPWSTR lpszPath, WCHAR replace)
 {
     for (; *lpszPath; lpszPath++)
     {
@@ -239,7 +417,7 @@ static HANDLE cache_container_map_index(HANDLE file, const WCHAR *path, DWORD si
     HANDLE mapping;
 
     wsprintfW(mapping_name, mapping_name_format, path, size);
-    URLCache_PathToObjectName(mapping_name, '_');
+    cache_container_create_object_name(mapping_name, '_');
 
     mapping = OpenFileMappingW(FILE_MAP_WRITE, FALSE, mapping_name);
     if(mapping) {
@@ -252,7 +430,7 @@ static HANDLE cache_container_map_index(HANDLE file, const WCHAR *path, DWORD si
 }
 
 /* Caller must hold container lock */
-static DWORD cache_container_set_size(URLCACHECONTAINER *container, HANDLE file, DWORD blocks_no)
+static DWORD cache_container_set_size(cache_container *container, HANDLE file, DWORD blocks_no)
 {
     static const WCHAR cache_content_key[] = {'S','o','f','t','w','a','r','e','\\',
         'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
@@ -263,8 +441,8 @@ static DWORD cache_container_set_size(URLCACHECONTAINER *container, HANDLE file,
 
     DWORD file_size = FILE_SIZE(blocks_no);
     WCHAR dir_path[MAX_PATH], *dir_name;
-    HASH_CACHEFILE_ENTRY *hash_entry;
-    URLCACHE_HEADER *header;
+    entry_hash_table *hashtable_entry;
+    urlcache_header *header;
     HANDLE mapping;
     FILETIME ft;
     HKEY key;
@@ -287,28 +465,28 @@ static DWORD cache_container_set_size(URLCACHECONTAINER *container, HANDLE file,
     }
 
     if(blocks_no != MIN_BLOCK_NO) {
-        if(file_size > header->dwFileSize)
-            memset((char*)header+header->dwFileSize, 0, file_size-header->dwFileSize);
-        header->dwFileSize = file_size;
-        header->dwIndexCapacityInBlocks = blocks_no;
+        if(file_size > header->size)
+            memset((char*)header+header->size, 0, file_size-header->size);
+        header->size = file_size;
+        header->capacity_in_blocks = blocks_no;
 
         UnmapViewOfFile(header);
-        CloseHandle(container->hMapping);
-        container->hMapping = mapping;
+        CloseHandle(container->mapping);
+        container->mapping = mapping;
         container->file_size = file_size;
         return ERROR_SUCCESS;
     }
 
     memset(header, 0, file_size);
     /* First set some constants and defaults in the header */
-    memcpy(header->szSignature, urlcache_ver_prefix, sizeof(urlcache_ver_prefix)-1);
-    memcpy(header->szSignature+sizeof(urlcache_ver_prefix)-1, urlcache_ver, sizeof(urlcache_ver)-1);
-    header->dwFileSize = file_size;
-    header->dwIndexCapacityInBlocks = blocks_no;
+    memcpy(header->signature, urlcache_ver_prefix, sizeof(urlcache_ver_prefix)-1);
+    memcpy(header->signature+sizeof(urlcache_ver_prefix)-1, urlcache_ver, sizeof(urlcache_ver)-1);
+    header->size = file_size;
+    header->capacity_in_blocks = blocks_no;
     /* 127MB - taken from default for Windows 2000 */
-    header->CacheLimit.QuadPart = 0x07ff5400;
+    header->cache_limit.QuadPart = 0x07ff5400;
     /* Copied from a Windows 2000 cache index */
-    header->DirectoryCount = container->default_entry_type==NORMAL_CACHE_ENTRY ? 4 : 0;
+    header->dirs_no = container->default_entry_type==NORMAL_CACHE_ENTRY ? 4 : 0;
 
     /* If the registry has a cache size set, use the registry value */
     if(RegOpenKeyW(HKEY_CURRENT_USER, cache_content_key, &key) == ERROR_SUCCESS) {
@@ -316,11 +494,11 @@ static DWORD cache_container_set_size(URLCACHECONTAINER *container, HANDLE file,
 
         if(RegQueryValueExW(key, cache_limit, NULL, &keytype, (BYTE*)&dw, &len) == ERROR_SUCCESS &&
                 keytype == REG_DWORD)
-            header->CacheLimit.QuadPart = (ULONGLONG)dw * 1024;
+            header->cache_limit.QuadPart = (ULONGLONG)dw * 1024;
         RegCloseKey(key);
     }
 
-    URLCache_CreateHashTable(header, NULL, &hash_entry);
+    urlcache_create_hash_table(header, NULL, &hashtable_entry);
 
     /* Last step - create the directories */
     strcpyW(dir_path, container->path);
@@ -329,8 +507,8 @@ static DWORD cache_container_set_size(URLCACHECONTAINER *container, HANDLE file,
 
     GetSystemTimeAsFileTime(&ft);
 
-    for(i=0; i<header->DirectoryCount; ++i) {
-        header->directory_data[i].dwNumFiles = 0;
+    for(i=0; i<header->dirs_no; ++i) {
+        header->directory_data[i].files_no = 0;
         for(j=0;; ++j) {
             ULONGLONG n = ft.dwHighDateTime;
             int k;
@@ -365,7 +543,7 @@ static DWORD cache_container_set_size(URLCACHECONTAINER *container, HANDLE file,
                  * pages and for UTF-16
                  */
                 for (k = 0; k < 8; ++k)
-                    header->directory_data[i].filename[k] = dir_name[k];
+                    header->directory_data[i].name[k] = dir_name[k];
                 break;
             }else if(j >= 255) {
                 /* Give up. The most likely cause of this
@@ -381,37 +559,37 @@ static DWORD cache_container_set_size(URLCACHECONTAINER *container, HANDLE file,
     }
 
     UnmapViewOfFile(header);
-    CloseHandle(container->hMapping);
-    container->hMapping = mapping;
+    CloseHandle(container->mapping);
+    container->mapping = mapping;
     container->file_size = file_size;
     return ERROR_SUCCESS;
 }
 
-static BOOL cache_container_is_valid(URLCACHE_HEADER *header, DWORD file_size)
+static BOOL cache_container_is_valid(urlcache_header *header, DWORD file_size)
 {
     DWORD allocation_size, count_bits, i;
 
     if(file_size < FILE_SIZE(MIN_BLOCK_NO))
         return FALSE;
 
-    if(file_size != header->dwFileSize)
+    if(file_size != header->size)
         return FALSE;
 
-    if (!memcmp(header->szSignature, urlcache_ver_prefix, sizeof(urlcache_ver_prefix)-1) &&
-            memcmp(header->szSignature+sizeof(urlcache_ver_prefix)-1, urlcache_ver, sizeof(urlcache_ver)-1))
+    if (!memcmp(header->signature, urlcache_ver_prefix, sizeof(urlcache_ver_prefix)-1) &&
+            memcmp(header->signature+sizeof(urlcache_ver_prefix)-1, urlcache_ver, sizeof(urlcache_ver)-1))
         return FALSE;
 
-    if(FILE_SIZE(header->dwIndexCapacityInBlocks) != file_size)
+    if(FILE_SIZE(header->capacity_in_blocks) != file_size)
         return FALSE;
 
     allocation_size = 0;
-    for(i=0; i<header->dwIndexCapacityInBlocks/8; i++) {
+    for(i=0; i<header->capacity_in_blocks/8; i++) {
         for(count_bits = header->allocation_table[i]; count_bits!=0; count_bits>>=1) {
             if(count_bits & 1)
                 allocation_size++;
         }
     }
-    if(allocation_size != header->dwBlocksInUse)
+    if(allocation_size != header->blocks_in_use)
         return FALSE;
 
     for(; i<ALLOCATION_TABLE_SIZE; i++) {
@@ -425,14 +603,14 @@ static BOOL cache_container_is_valid(URLCACHE_HEADER *header, DWORD file_size)
 /***********************************************************************
  *           cache_container_open_index (Internal)
  *
- *  Opens the index file and saves mapping handle in hMapping
+ *  Opens the index file and saves mapping handle
  *
  * RETURNS
  *    ERROR_SUCCESS if succeeded
  *    Any other Win32 error code if failed
  *
  */
-static DWORD cache_container_open_index(URLCACHECONTAINER *container, DWORD blocks_no)
+static DWORD cache_container_open_index(cache_container *container, DWORD blocks_no)
 {
     static const WCHAR index_dat[] = {'i','n','d','e','x','.','d','a','t',0};
 
@@ -441,10 +619,10 @@ static DWORD cache_container_open_index(URLCACHECONTAINER *container, DWORD bloc
     DWORD file_size;
     BOOL validate;
 
-    WaitForSingleObject(container->hMutex, INFINITE);
+    WaitForSingleObject(container->mutex, INFINITE);
 
-    if(container->hMapping) {
-        ReleaseMutex(container->hMutex);
+    if(container->mapping) {
+        ReleaseMutex(container->mutex);
         return ERROR_SUCCESS;
     }
 
@@ -459,14 +637,14 @@ static DWORD cache_container_open_index(URLCACHECONTAINER *container, DWORD bloc
     }
     if(file == INVALID_HANDLE_VALUE) {
         TRACE("Could not open or create cache index file \"%s\"\n", debugstr_w(index_path));
-        ReleaseMutex(container->hMutex);
+        ReleaseMutex(container->mutex);
         return GetLastError();
     }
 
     file_size = GetFileSize(file, NULL);
     if(file_size == INVALID_FILE_SIZE) {
         CloseHandle(file);
-       ReleaseMutex(container->hMutex);
+       ReleaseMutex(container->mutex);
         return GetLastError();
     }
 
@@ -478,15 +656,15 @@ static DWORD cache_container_open_index(URLCACHECONTAINER *container, DWORD bloc
     if(file_size < FILE_SIZE(blocks_no)) {
         DWORD ret = cache_container_set_size(container, file, blocks_no);
         CloseHandle(file);
-        ReleaseMutex(container->hMutex);
+        ReleaseMutex(container->mutex);
         return ret;
     }
 
     container->file_size = file_size;
-    container->hMapping = cache_container_map_index(file, container->path, file_size, &validate);
+    container->mapping = cache_container_map_index(file, container->path, file_size, &validate);
     CloseHandle(file);
-    if(container->hMapping && validate) {
-        URLCACHE_HEADER *header = MapViewOfFile(container->hMapping, FILE_MAP_WRITE, 0, 0, 0);
+    if(container->mapping && validate) {
+        urlcache_header *header = MapViewOfFile(container->mapping, FILE_MAP_WRITE, 0, 0, 0);
 
         if(header && !cache_container_is_valid(header, file_size)) {
             WARN("detected old or broken index.dat file\n");
@@ -495,19 +673,19 @@ static DWORD cache_container_open_index(URLCACHECONTAINER *container, DWORD bloc
         }else if(header) {
             UnmapViewOfFile(header);
         }else {
-            CloseHandle(container->hMapping);
-            container->hMapping = NULL;
+            CloseHandle(container->mapping);
+            container->mapping = NULL;
         }
     }
 
-    if(!container->hMapping)
+    if(!container->mapping)
     {
         ERR("Couldn't create file mapping (error is %d)\n", GetLastError());
-        ReleaseMutex(container->hMutex);
+        ReleaseMutex(container->mutex);
         return GetLastError();
     }
 
-    ReleaseMutex(container->hMutex);
+    ReleaseMutex(container->mutex);
     return ERROR_SUCCESS;
 }
 
@@ -520,24 +698,24 @@ static DWORD cache_container_open_index(URLCACHECONTAINER *container, DWORD bloc
  *    nothing
  *
  */
-static void cache_container_close_index(URLCACHECONTAINER * pContainer)
+static void cache_container_close_index(cache_container *pContainer)
 {
-    CloseHandle(pContainer->hMapping);
-    pContainer->hMapping = NULL;
+    CloseHandle(pContainer->mapping);
+    pContainer->mapping = NULL;
 }
 
-static BOOL URLCacheContainers_AddContainer(LPCWSTR cache_prefix,
-        LPCWSTR path, DWORD default_entry_type, LPWSTR mutex_name)
+static BOOL cache_containers_add(const char *cache_prefix, LPCWSTR path,
+        DWORD default_entry_type, LPWSTR mutex_name)
 {
-    URLCACHECONTAINER * pContainer = heap_alloc(sizeof(URLCACHECONTAINER));
-    int cache_prefix_len = strlenW(cache_prefix);
+    cache_container *pContainer = heap_alloc(sizeof(cache_container));
+    int cache_prefix_len = strlen(cache_prefix);
 
     if (!pContainer)
     {
         return FALSE;
     }
 
-    pContainer->hMapping = NULL;
+    pContainer->mapping = NULL;
     pContainer->file_size = 0;
     pContainer->default_entry_type = default_entry_type;
 
@@ -548,7 +726,7 @@ static BOOL URLCacheContainers_AddContainer(LPCWSTR cache_prefix,
         return FALSE;
     }
 
-    pContainer->cache_prefix = heap_alloc((cache_prefix_len + 1) * sizeof(WCHAR));
+    pContainer->cache_prefix = heap_alloc(cache_prefix_len+1);
     if (!pContainer->cache_prefix)
     {
         heap_free(pContainer->path);
@@ -556,12 +734,12 @@ static BOOL URLCacheContainers_AddContainer(LPCWSTR cache_prefix,
         return FALSE;
     }
 
-    memcpy(pContainer->cache_prefix, cache_prefix, (cache_prefix_len + 1) * sizeof(WCHAR));
+    memcpy(pContainer->cache_prefix, cache_prefix, cache_prefix_len+1);
 
     CharLowerW(mutex_name);
-    URLCache_PathToObjectName(mutex_name, '!');
+    cache_container_create_object_name(mutex_name, '!');
 
-    if ((pContainer->hMutex = CreateMutexW(NULL, FALSE, mutex_name)) == NULL)
+    if ((pContainer->mutex = CreateMutexW(NULL, FALSE, mutex_name)) == NULL)
     {
         ERR("couldn't create mutex (error is %d)\n", GetLastError());
         heap_free(pContainer->path);
@@ -574,38 +752,35 @@ static BOOL URLCacheContainers_AddContainer(LPCWSTR cache_prefix,
     return TRUE;
 }
 
-static void cache_container_delete_container(URLCACHECONTAINER * pContainer)
+static void cache_container_delete_container(cache_container *pContainer)
 {
     list_remove(&pContainer->entry);
 
     cache_container_close_index(pContainer);
-    CloseHandle(pContainer->hMutex);
+    CloseHandle(pContainer->mutex);
     heap_free(pContainer->path);
     heap_free(pContainer->cache_prefix);
     heap_free(pContainer);
 }
 
-static void URLCacheContainers_CreateDefaults(void)
+static void cache_containers_init(void)
 {
     static const WCHAR UrlSuffix[] = {'C','o','n','t','e','n','t','.','I','E','5',0};
-    static const WCHAR UrlPrefix[] = {0};
     static const WCHAR HistorySuffix[] = {'H','i','s','t','o','r','y','.','I','E','5',0};
-    static const WCHAR HistoryPrefix[] = {'V','i','s','i','t','e','d',':',0};
     static const WCHAR CookieSuffix[] = {0};
-    static const WCHAR CookiePrefix[] = {'C','o','o','k','i','e',':',0};
     // ReactOS r50916
     static const WCHAR UserProfile[] = {'U','S','E','R','P','R','O','F','I','L','E',0};
     static const struct
     {
         int nFolder; /* CSIDL_* constant */
-        const WCHAR * shpath_suffix; /* suffix on path returned by SHGetSpecialFolderPath */
-        const WCHAR * cache_prefix; /* prefix used to reference the container */
+        const WCHAR *shpath_suffix; /* suffix on path returned by SHGetSpecialFolderPath */
+        const char *cache_prefix; /* prefix used to reference the container */
         DWORD default_entry_type;
     } DefaultContainerData[] = 
     {
-        { CSIDL_INTERNET_CACHE, UrlSuffix, UrlPrefix, NORMAL_CACHE_ENTRY },
-        { CSIDL_HISTORY, HistorySuffix, HistoryPrefix, URLHISTORY_CACHE_ENTRY },
-        { CSIDL_COOKIES, CookieSuffix, CookiePrefix, COOKIE_CACHE_ENTRY },
+        { CSIDL_INTERNET_CACHE, UrlSuffix, "", NORMAL_CACHE_ENTRY },
+        { CSIDL_HISTORY, HistorySuffix, "Visited:", URLHISTORY_CACHE_ENTRY },
+        { CSIDL_COOKIES, CookieSuffix, "Cookie:", COOKIE_CACHE_ENTRY },
     };
     DWORD i;
 
@@ -621,6 +796,7 @@ static void URLCacheContainers_CreateDefaults(void)
         WCHAR wszCachePath[MAX_PATH];
         WCHAR wszMutexName[MAX_PATH];
         int path_len, suffix_len;
+        BOOL def_char;
 
         if (!SHGetSpecialFolderPathW(NULL, wszCachePath, DefaultContainerData[i].nFolder, TRUE))
         {
@@ -648,91 +824,93 @@ static void URLCacheContainers_CreateDefaults(void)
             wszCachePath[path_len + suffix_len + 2] = '\0';
         }
 
-        URLCacheContainers_AddContainer(DefaultContainerData[i].cache_prefix, wszCachePath,
+        if (!WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, wszCachePath, path_len,
+                    NULL, 0, NULL, &def_char) || def_char)
+        {
+            WCHAR tmp[MAX_PATH];
+
+            /* cannot convert path to ANSI code page */
+            if (!(path_len = GetShortPathNameW(wszCachePath, tmp, MAX_PATH)) ||
+                !WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, tmp, path_len,
+                    NULL, 0, NULL, &def_char) || def_char)
+                ERR("Can't create container path accessible by ANSI functions\n");
+            else
+                memcpy(wszCachePath, tmp, (path_len+1)*sizeof(WCHAR));
+        }
+
+        cache_containers_add(DefaultContainerData[i].cache_prefix, wszCachePath,
                 DefaultContainerData[i].default_entry_type, wszMutexName);
     }
 }
 
-static void URLCacheContainers_DeleteAll(void)
+static void cache_containers_free(void)
 {
     while(!list_empty(&UrlContainers))
         cache_container_delete_container(
-            LIST_ENTRY(list_head(&UrlContainers), URLCACHECONTAINER, entry)
+            LIST_ENTRY(list_head(&UrlContainers), cache_container, entry)
         );
 }
 
-static DWORD URLCacheContainers_FindContainerW(LPCWSTR lpwszUrl, URLCACHECONTAINER ** ppContainer)
+static DWORD cache_containers_find(const char *url, cache_container **ret)
 {
-    URLCACHECONTAINER * pContainer;
+    cache_container *container;
 
-    TRACE("searching for prefix for URL: %s\n", debugstr_w(lpwszUrl));
+    TRACE("searching for prefix for URL: %s\n", debugstr_a(url));
 
-    if(!lpwszUrl)
+    if(!url)
         return ERROR_INVALID_PARAMETER;
 
     // ReactOS r54992
     if (!bDefaultContainersAdded)
-        URLCacheContainers_CreateDefaults();
+        cache_containers_init();
 
-    LIST_FOR_EACH_ENTRY(pContainer, &UrlContainers, URLCACHECONTAINER, entry)
+    LIST_FOR_EACH_ENTRY(container, &UrlContainers, cache_container, entry)
     {
-        int prefix_len = strlenW(pContainer->cache_prefix);
-        if (!strncmpW(pContainer->cache_prefix, lpwszUrl, prefix_len))
-        {
-            TRACE("found container with prefix %s for URL %s\n", debugstr_w(pContainer->cache_prefix), debugstr_w(lpwszUrl));
-            *ppContainer = pContainer;
+        int prefix_len = strlen(container->cache_prefix);
+
+        if(!strncmp(container->cache_prefix, url, prefix_len)) {
+            TRACE("found container with prefix %s\n", debugstr_a(container->cache_prefix));
+            *ret = container;
             return ERROR_SUCCESS;
         }
     }
+
     ERR("no container found\n");
     return ERROR_FILE_NOT_FOUND;
 }
 
-static DWORD URLCacheContainers_FindContainerA(LPCSTR lpszUrl, URLCACHECONTAINER ** ppContainer)
-{
-    LPWSTR url = NULL;
-    DWORD ret;
-
-    if (lpszUrl && !(url = heap_strdupAtoW(lpszUrl)))
-        return ERROR_OUTOFMEMORY;
-
-    ret = URLCacheContainers_FindContainerW(url, ppContainer);
-    heap_free(url);
-    return ret;
-}
-
-static BOOL URLCacheContainers_Enum(LPCWSTR lpwszSearchPattern, DWORD dwIndex, URLCACHECONTAINER ** ppContainer)
+static BOOL cache_containers_enum(char *search_pattern, DWORD index, cache_container **ret)
 {
     DWORD i = 0;
-    URLCACHECONTAINER * pContainer;
+    cache_container *container;
 
-    TRACE("searching for prefix: %s\n", debugstr_w(lpwszSearchPattern));
+    TRACE("searching for prefix: %s\n", debugstr_a(search_pattern));
 
     /* non-NULL search pattern only returns one container ever */
-    if (lpwszSearchPattern && dwIndex > 0)
+    if (search_pattern && index > 0)
         return FALSE;
 
     // ReactOS r54992
     if (!bDefaultContainersAdded)
-        URLCacheContainers_CreateDefaults();
+        cache_containers_init();
 
-    LIST_FOR_EACH_ENTRY(pContainer, &UrlContainers, URLCACHECONTAINER, entry)
+    LIST_FOR_EACH_ENTRY(container, &UrlContainers, cache_container, entry)
     {
-        if (lpwszSearchPattern)
+        if (search_pattern)
         {
-            if (!strcmpW(pContainer->cache_prefix, lpwszSearchPattern))
+            if (!strcmp(container->cache_prefix, search_pattern))
             {
-                TRACE("found container with prefix %s\n", debugstr_w(pContainer->cache_prefix));
-                *ppContainer = pContainer;
+                TRACE("found container with prefix %s\n", debugstr_a(container->cache_prefix));
+                *ret = container;
                 return TRUE;
             }
         }
         else
         {
-            if (i == dwIndex)
+            if (i == index)
             {
-                TRACE("found container with prefix %s\n", debugstr_w(pContainer->cache_prefix));
-                *ppContainer = pContainer;
+                TRACE("found container with prefix %s\n", debugstr_a(container->cache_prefix));
+                *ret = container;
                 return TRUE;
             }
         }
@@ -750,56 +928,56 @@ static BOOL URLCacheContainers_Enum(LPCWSTR lpwszSearchPattern, DWORD dwIndex, U
  *  Cache file header if successful
  *  NULL if failed and calls SetLastError.
  */
-static LPURLCACHE_HEADER cache_container_lock_index(URLCACHECONTAINER * pContainer)
+static urlcache_header* cache_container_lock_index(cache_container *pContainer)
 {
     BYTE index;
     LPVOID pIndexData;
-    URLCACHE_HEADER * pHeader;
+    urlcache_header* pHeader;
     DWORD error;
 
     /* acquire mutex */
-    WaitForSingleObject(pContainer->hMutex, INFINITE);
+    WaitForSingleObject(pContainer->mutex, INFINITE);
 
-    pIndexData = MapViewOfFile(pContainer->hMapping, FILE_MAP_WRITE, 0, 0, 0);
+    pIndexData = MapViewOfFile(pContainer->mapping, FILE_MAP_WRITE, 0, 0, 0);
 
     if (!pIndexData)
     {
-        ReleaseMutex(pContainer->hMutex);
+        ReleaseMutex(pContainer->mutex);
         ERR("Couldn't MapViewOfFile. Error: %d\n", GetLastError());
         return NULL;
     }
-    pHeader = (URLCACHE_HEADER *)pIndexData;
+    pHeader = (urlcache_header*)pIndexData;
 
     /* file has grown - we need to remap to prevent us getting
      * access violations when we try and access beyond the end
      * of the memory mapped file */
-    if (pHeader->dwFileSize != pContainer->file_size)
+    if (pHeader->size != pContainer->file_size)
     {
         UnmapViewOfFile( pHeader );
         cache_container_close_index(pContainer);
         error = cache_container_open_index(pContainer, MIN_BLOCK_NO);
         if (error != ERROR_SUCCESS)
         {
-            ReleaseMutex(pContainer->hMutex);
+            ReleaseMutex(pContainer->mutex);
             SetLastError(error);
             return NULL;
         }
-        pIndexData = MapViewOfFile(pContainer->hMapping, FILE_MAP_WRITE, 0, 0, 0);
+        pIndexData = MapViewOfFile(pContainer->mapping, FILE_MAP_WRITE, 0, 0, 0);
 
         if (!pIndexData)
         {
-            ReleaseMutex(pContainer->hMutex);
+            ReleaseMutex(pContainer->mutex);
             ERR("Couldn't MapViewOfFile. Error: %d\n", GetLastError());
             return NULL;
         }
-        pHeader = (URLCACHE_HEADER *)pIndexData;
+        pHeader = (urlcache_header*)pIndexData;
     }
 
-    TRACE("Signature: %s, file size: %d bytes\n", pHeader->szSignature, pHeader->dwFileSize);
+    TRACE("Signature: %s, file size: %d bytes\n", pHeader->signature, pHeader->size);
 
-    for (index = 0; index < pHeader->DirectoryCount; index++)
+    for (index = 0; index < pHeader->dirs_no; index++)
     {
-        TRACE("Directory[%d] = \"%.8s\"\n", index, pHeader->directory_data[index].filename);
+        TRACE("Directory[%d] = \"%.8s\"\n", index, pHeader->directory_data[index].name);
     }
     
     return pHeader;
@@ -809,137 +987,15 @@ static LPURLCACHE_HEADER cache_container_lock_index(URLCACHECONTAINER * pContain
  *           cache_container_unlock_index (Internal)
  *
  */
-static BOOL cache_container_unlock_index(URLCACHECONTAINER * pContainer, LPURLCACHE_HEADER pHeader)
+static BOOL cache_container_unlock_index(cache_container *pContainer, urlcache_header *pHeader)
 {
     /* release mutex */
-    ReleaseMutex(pContainer->hMutex);
+    ReleaseMutex(pContainer->mutex);
     return UnmapViewOfFile(pHeader);
 }
 
-#ifndef CHAR_BIT
-#define CHAR_BIT    (8 * sizeof(CHAR))
-#endif
-
-/***********************************************************************
- *           URLCache_Allocation_BlockIsFree (Internal)
- *
- *  Is the specified block number free?
- *
- * RETURNS
- *    zero if free
- *    non-zero otherwise
- *
- */
-static inline BYTE URLCache_Allocation_BlockIsFree(BYTE * AllocationTable, DWORD dwBlockNumber)
-{
-    BYTE mask = 1 << (dwBlockNumber % CHAR_BIT);
-    return (AllocationTable[dwBlockNumber / CHAR_BIT] & mask) == 0;
-}
-
-/***********************************************************************
- *           URLCache_Allocation_BlockFree (Internal)
- *
- *  Marks the specified block as free
- *
- * CAUTION
- *    this function is not updating used blocks count
- *
- * RETURNS
- *    nothing
- *
- */
-static inline void URLCache_Allocation_BlockFree(BYTE * AllocationTable, DWORD dwBlockNumber)
-{
-    BYTE mask = ~(1 << (dwBlockNumber % CHAR_BIT));
-    AllocationTable[dwBlockNumber / CHAR_BIT] &= mask;
-}
-
-/***********************************************************************
- *           URLCache_Allocation_BlockAllocate (Internal)
- *
- *  Marks the specified block as allocated
- *
- * CAUTION
- *     this function is not updating used blocks count
- *
- * RETURNS
- *    nothing
- *
- */
-static inline void URLCache_Allocation_BlockAllocate(BYTE * AllocationTable, DWORD dwBlockNumber)
-{
-    BYTE mask = 1 << (dwBlockNumber % CHAR_BIT);
-    AllocationTable[dwBlockNumber / CHAR_BIT] |= mask;
-}
-
-/***********************************************************************
- *           URLCache_FindFirstFreeEntry (Internal)
- *
- *  Finds and allocates the first block of free space big enough and
- * sets ppEntry to point to it.
- *
- * RETURNS
- *    ERROR_SUCCESS when free memory block was found
- *    Any other Win32 error code if the entry could not be added
- *
- */
-static DWORD URLCache_FindFirstFreeEntry(URLCACHE_HEADER * pHeader, DWORD dwBlocksNeeded, entry_header **ppEntry)
-{
-    DWORD dwBlockNumber;
-    DWORD dwFreeCounter;
-    for (dwBlockNumber = 0; dwBlockNumber < pHeader->dwIndexCapacityInBlocks; dwBlockNumber++)
-    {
-        for (dwFreeCounter = 0; 
-            dwFreeCounter < dwBlocksNeeded &&
-              dwFreeCounter + dwBlockNumber < pHeader->dwIndexCapacityInBlocks &&
-              URLCache_Allocation_BlockIsFree(pHeader->allocation_table, dwBlockNumber + dwFreeCounter);
-            dwFreeCounter++)
-                TRACE("Found free block at no. %d (0x%x)\n", dwBlockNumber, ENTRY_START_OFFSET + dwBlockNumber * BLOCKSIZE);
-
-        if (dwFreeCounter == dwBlocksNeeded)
-        {
-            DWORD index;
-            TRACE("Found free blocks starting at no. %d (0x%x)\n", dwBlockNumber, ENTRY_START_OFFSET + dwBlockNumber * BLOCKSIZE);
-            for (index = 0; index < dwBlocksNeeded; index++)
-                URLCache_Allocation_BlockAllocate(pHeader->allocation_table, dwBlockNumber + index);
-            *ppEntry = (entry_header*)((LPBYTE)pHeader + ENTRY_START_OFFSET + dwBlockNumber * BLOCKSIZE);
-            for (index = 0; index < dwBlocksNeeded * BLOCKSIZE / sizeof(DWORD); index++)
-                ((DWORD*)*ppEntry)[index] = 0xdeadbeef;
-            (*ppEntry)->blocks_used = dwBlocksNeeded;
-            pHeader->dwBlocksInUse += dwBlocksNeeded;
-            return ERROR_SUCCESS;
-        }
-    }
-
-    return ERROR_HANDLE_DISK_FULL;
-}
-
-/***********************************************************************
- *           URLCache_DeleteEntry (Internal)
- *
- *  Deletes the specified entry and frees the space allocated to it
- *
- * RETURNS
- *    TRUE if it succeeded
- *    FALSE if it failed
- *
- */
-static BOOL URLCache_DeleteEntry(LPURLCACHE_HEADER pHeader, entry_header *pEntry)
-{
-    DWORD dwStartBlock;
-    DWORD dwBlock;
-
-    /* update allocation table */
-    dwStartBlock = ((DWORD)((BYTE *)pEntry - (BYTE *)pHeader) - ENTRY_START_OFFSET) / BLOCKSIZE;
-    for (dwBlock = dwStartBlock; dwBlock < dwStartBlock + pEntry->blocks_used; dwBlock++)
-        URLCache_Allocation_BlockFree(pHeader->allocation_table, dwBlock);
-
-    pHeader->dwBlocksInUse -= pEntry->blocks_used;
-    return TRUE;
-}
-
 /***********************************************************************
- *           URLCache_LocalFileNameToPathW (Internal)
+ *           urlcache_create_file_pathW (Internal)
  *
  *  Copies the full path to the specified buffer given the local file
  * name and the index of the directory it is in. Always sets value in
@@ -950,9 +1006,9 @@ static BOOL URLCache_DeleteEntry(LPURLCACHE_HEADER pHeader, entry_header *pEntry
  *    FALSE if the buffer was too small
  *
  */
-static BOOL URLCache_LocalFileNameToPathW(
-    const URLCACHECONTAINER * pContainer,
-    LPCURLCACHE_HEADER pHeader,
+static BOOL urlcache_create_file_pathW(
+    const cache_container *pContainer,
+    const urlcache_header *pHeader,
     LPCSTR szLocalFileName,
     BYTE Directory,
     LPWSTR wszPath,
@@ -961,7 +1017,7 @@ static BOOL URLCache_LocalFileNameToPathW(
     LONG nRequired;
     int path_len = strlenW(pContainer->path);
     int file_name_len = MultiByteToWideChar(CP_ACP, 0, szLocalFileName, -1, NULL, 0);
-    if (Directory!=CACHE_CONTAINER_NO_SUBDIR && Directory>=pHeader->DirectoryCount)
+    if (Directory!=CACHE_CONTAINER_NO_SUBDIR && Directory>=pHeader->dirs_no)
     {
         *lpBufferSize = 0;
         return FALSE;
@@ -977,7 +1033,7 @@ static BOOL URLCache_LocalFileNameToPathW(
         memcpy(wszPath, pContainer->path, path_len * sizeof(WCHAR));
         if (Directory != CACHE_CONTAINER_NO_SUBDIR)
         {
-            dir_len = MultiByteToWideChar(CP_ACP, 0, pHeader->directory_data[Directory].filename, DIR_LENGTH, wszPath + path_len, DIR_LENGTH);
+            dir_len = MultiByteToWideChar(CP_ACP, 0, pHeader->directory_data[Directory].name, DIR_LENGTH, wszPath + path_len, DIR_LENGTH);
             wszPath[dir_len + path_len] = '\\';
             dir_len++;
         }
@@ -994,7 +1050,7 @@ static BOOL URLCache_LocalFileNameToPathW(
 }
 
 /***********************************************************************
- *           URLCache_LocalFileNameToPathA (Internal)
+ *           urlcache_create_file_pathA (Internal)
  *
  *  Copies the full path to the specified buffer given the local file
  * name and the index of the directory it is in. Always sets value in
@@ -1005,9 +1061,9 @@ static BOOL URLCache_LocalFileNameToPathW(
  *    FALSE if the buffer was too small
  *
  */
-static BOOL URLCache_LocalFileNameToPathA(
-    const URLCACHECONTAINER * pContainer,
-    LPCURLCACHE_HEADER pHeader,
+static BOOL urlcache_create_file_pathA(
+    const cache_container *pContainer,
+    const urlcache_header *pHeader,
     LPCSTR szLocalFileName,
     BYTE Directory,
     LPSTR szPath,
@@ -1016,7 +1072,7 @@ static BOOL URLCache_LocalFileNameToPathA(
     LONG nRequired;
     int path_len, file_name_len, dir_len;
 
-    if (Directory!=CACHE_CONTAINER_NO_SUBDIR && Directory>=pHeader->DirectoryCount)
+    if (Directory!=CACHE_CONTAINER_NO_SUBDIR && Directory>=pHeader->dirs_no)
     {
         *lpBufferSize = 0;
         return FALSE;
@@ -1030,11 +1086,11 @@ static BOOL URLCache_LocalFileNameToPathA(
         dir_len = 0;
 
     nRequired = (path_len + dir_len + file_name_len) * sizeof(char);
-    if (nRequired < *lpBufferSize)
+    if (nRequired <= *lpBufferSize)
     {
         WideCharToMultiByte(CP_ACP, 0, pContainer->path, -1, szPath, path_len, NULL, NULL);
         if(dir_len) {
-            memcpy(szPath+path_len, pHeader->directory_data[Directory].filename, dir_len-1);
+            memcpy(szPath+path_len, pHeader->directory_data[Directory].name, dir_len-1);
             szPath[path_len + dir_len-1] = '\\';
         }
         memcpy(szPath + path_len + dir_len, szLocalFileName, file_name_len);
@@ -1048,7 +1104,7 @@ static BOOL URLCache_LocalFileNameToPathA(
 /* Just like FileTimeToDosDateTime, except that it also maps the special
  * case of a filetime of (0,0) to a DOS date/time of (0,0).
  */
-static void URLCache_FileTimeToDosDateTime(const FILETIME *ft, WORD *fatdate,
+static void file_time_to_dos_date_time(const FILETIME *ft, WORD *fatdate,
                                            WORD *fattime)
 {
     if (!ft->dwLowDateTime && !ft->dwHighDateTime)
@@ -1058,10 +1114,10 @@ static void URLCache_FileTimeToDosDateTime(const FILETIME *ft, WORD *fatdate,
 }
 
 /***********************************************************************
- *           URLCache_DeleteFile (Internal)
+ *           urlcache_delete_file (Internal)
  */
-static DWORD URLCache_DeleteFile(const URLCACHECONTAINER *container,
-        URLCACHE_HEADER *header, entry_url *url_entry)
+static DWORD urlcache_delete_file(const cache_container *container,
+        urlcache_header *header, entry_url *url_entry)
 {
     WIN32_FILE_ATTRIBUTE_DATA attr;
     WCHAR path[MAX_PATH];
@@ -1072,14 +1128,14 @@ static DWORD URLCache_DeleteFile(const URLCACHECONTAINER *container,
     if(!url_entry->local_name_off)
         goto succ;
 
-    if(!URLCache_LocalFileNameToPathW(container, header,
+    if(!urlcache_create_file_pathW(container, header,
                 (LPCSTR)url_entry+url_entry->local_name_off,
                 url_entry->cache_dir, path, &path_size))
         goto succ;
 
     if(!GetFileAttributesExW(path, GetFileExInfoStandard, &attr))
         goto succ;
-    URLCache_FileTimeToDosDateTime(&attr.ftLastWriteTime, &date, &time);
+    file_time_to_dos_date_time(&attr.ftLastWriteTime, &date, &time);
     if(date != url_entry->write_date || time != url_entry->write_time)
         goto succ;
 
@@ -1088,30 +1144,30 @@ static DWORD URLCache_DeleteFile(const URLCACHECONTAINER *container,
         return err;
 
 succ:
-    if (url_entry->cache_dir < header->DirectoryCount)
+    if (url_entry->cache_dir < header->dirs_no)
     {
-        if (header->directory_data[url_entry->cache_dir].dwNumFiles)
-            header->directory_data[url_entry->cache_dir].dwNumFiles--;
+        if (header->directory_data[url_entry->cache_dir].files_no)
+            header->directory_data[url_entry->cache_dir].files_no--;
     }
     if (url_entry->cache_entry_type & STICKY_CACHE_ENTRY)
     {
-        if (url_entry->size.QuadPart < header->ExemptUsage.QuadPart)
-            header->ExemptUsage.QuadPart -= url_entry->size.QuadPart;
+        if (url_entry->size.QuadPart < header->exempt_usage.QuadPart)
+            header->exempt_usage.QuadPart -= url_entry->size.QuadPart;
         else
-            header->ExemptUsage.QuadPart = 0;
+            header->exempt_usage.QuadPart = 0;
     }
     else
     {
-        if (url_entry->size.QuadPart < header->CacheUsage.QuadPart)
-            header->CacheUsage.QuadPart -= url_entry->size.QuadPart;
+        if (url_entry->size.QuadPart < header->cache_usage.QuadPart)
+            header->cache_usage.QuadPart -= url_entry->size.QuadPart;
         else
-            header->CacheUsage.QuadPart = 0;
+            header->cache_usage.QuadPart = 0;
     }
 
     return ERROR_SUCCESS;
 }
 
-static BOOL urlcache_clean_leaked_entries(URLCACHECONTAINER *container, URLCACHE_HEADER *header)
+static BOOL urlcache_clean_leaked_entries(cache_container *container, urlcache_header *header)
 {
     DWORD *leak_off;
     BOOL freed = FALSE;
@@ -1120,9 +1176,9 @@ static BOOL urlcache_clean_leaked_entries(URLCACHECONTAINER *container, URLCACHE
     while(*leak_off) {
         entry_url *url_entry = (entry_url*)((LPBYTE)header + *leak_off);
 
-        if(SUCCEEDED(URLCache_DeleteFile(container, header, url_entry))) {
+        if(SUCCEEDED(urlcache_delete_file(container, header, url_entry))) {
             *leak_off = url_entry->exempt_delta;
-            URLCache_DeleteEntry(header, &url_entry->header);
+            urlcache_entry_free(header, &url_entry->header);
             freed = TRUE;
         }else {
             leak_off = &url_entry->exempt_delta;
@@ -1144,26 +1200,26 @@ static BOOL urlcache_clean_leaked_entries(URLCACHECONTAINER *container, URLCACHE
  *     ERROR_SUCCESS when new memory is available
  *     error code otherwise
  */
-static DWORD cache_container_clean_index(URLCACHECONTAINER *container, URLCACHE_HEADER **file_view)
+static DWORD cache_container_clean_index(cache_container *container, urlcache_header **file_view)
 {
-    URLCACHE_HEADER *header = *file_view;
+    urlcache_header *header = *file_view;
     DWORD ret;
 
-    TRACE("(%s %s)\n", debugstr_w(container->cache_prefix), debugstr_w(container->path));
+    TRACE("(%s %s)\n", debugstr_a(container->cache_prefix), debugstr_w(container->path));
 
     if(urlcache_clean_leaked_entries(container, header))
         return ERROR_SUCCESS;
 
-    if(header->dwFileSize >= ALLOCATION_TABLE_SIZE*8*BLOCKSIZE + ENTRY_START_OFFSET) {
+    if(header->size >= ALLOCATION_TABLE_SIZE*8*BLOCKSIZE + ENTRY_START_OFFSET) {
         WARN("index file has maximal size\n");
         return ERROR_NOT_ENOUGH_MEMORY;
     }
 
     cache_container_close_index(container);
-    ret = cache_container_open_index(container, header->dwIndexCapacityInBlocks*2);
+    ret = cache_container_open_index(container, header->capacity_in_blocks*2);
     if(ret != ERROR_SUCCESS)
         return ret;
-    header = MapViewOfFile(container->hMapping, FILE_MAP_WRITE, 0, 0, 0);
+    header = MapViewOfFile(container->mapping, FILE_MAP_WRITE, 0, 0, 0);
     if(!header)
         return GetLastError();
 
@@ -1175,7 +1231,7 @@ static DWORD cache_container_clean_index(URLCACHECONTAINER *container, URLCACHE_
 /* Just like DosDateTimeToFileTime, except that it also maps the special
  * case of a DOS date/time of (0,0) to a filetime of (0,0).
  */
-static void URLCache_DosDateTimeToFileTime(WORD fatdate, WORD fattime,
+static void dos_date_time_to_file_time(WORD fatdate, WORD fattime,
                                            FILETIME *ft)
 {
     if (!fatdate && !fattime)
@@ -1184,8 +1240,65 @@ static void URLCache_DosDateTimeToFileTime(WORD fatdate, WORD fattime,
         DosDateTimeToFileTime(fatdate, fattime, ft);
 }
 
+static int urlcache_decode_url(const char *url, WCHAR *decoded_url, int decoded_len)
+{
+#ifndef __REACTOS__ /* FIXME: Vista+ */
+    URL_COMPONENTSA uc;
+    DWORD len, part_len;
+    WCHAR *host_name;
+
+    memset(&uc, 0, sizeof(uc));
+    uc.dwStructSize = sizeof(uc);
+    uc.dwHostNameLength = 1;
+    if(!InternetCrackUrlA(url, 0, 0, &uc))
+        uc.nScheme = INTERNET_SCHEME_UNKNOWN;
+
+    if(uc.nScheme!=INTERNET_SCHEME_HTTP && uc.nScheme!=INTERNET_SCHEME_HTTPS)
+#endif
+        return MultiByteToWideChar(CP_UTF8, 0, url, -1, decoded_url, decoded_len);
+
+#ifndef __REACTOS__ /* FIXME: Vista+ */
+    if(!decoded_url)
+        decoded_len = 0;
+
+    len = MultiByteToWideChar(CP_UTF8, 0, url, uc.lpszHostName-url, decoded_url, decoded_len);
+    if(!len)
+        return 0;
+    if(decoded_url)
+        decoded_len -= len;
+
+    host_name = heap_alloc(uc.dwHostNameLength*sizeof(WCHAR));
+    if(!host_name)
+        return 0;
+    if(!MultiByteToWideChar(CP_UTF8, 0, uc.lpszHostName, uc.dwHostNameLength,
+                host_name, uc.dwHostNameLength)) {
+        heap_free(host_name);
+        return 0;
+    }
+    part_len = IdnToUnicode(0, host_name, uc.dwHostNameLength,
+            decoded_url ? decoded_url+len : NULL, decoded_len);
+    heap_free(host_name);
+    if(!part_len) {
+        SetLastError(ERROR_INTERNET_INVALID_URL);
+        return 0;
+    }
+    len += part_len;
+    if(decoded_url)
+        decoded_len -= part_len;
+
+    part_len = MultiByteToWideChar(CP_UTF8, 0,
+            uc.lpszHostName+uc.dwHostNameLength,
+            -1, decoded_url ? decoded_url+len : NULL, decoded_len);
+    if(!part_len)
+        return 0;
+    len += part_len;
+
+    return len;
+#endif /* !__REACTOS__ */
+}
+
 /***********************************************************************
- *           URLCache_CopyEntry (Internal)
+ *           urlcache_copy_entry (Internal)
  *
  *  Copies an entry from the cache index file to the Win32 structure
  *
@@ -1194,159 +1307,160 @@ static void URLCache_DosDateTimeToFileTime(WORD fatdate, WORD fattime,
  *    ERROR_INSUFFICIENT_BUFFER if the buffer was too small
  *
  */
-static DWORD URLCache_CopyEntry(
-    URLCACHECONTAINER * pContainer,
-    LPCURLCACHE_HEADER pHeader, 
-    LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo, 
-    LPDWORD lpdwBufferSize, 
-    const entry_url * pUrlEntry,
-    BOOL bUnicode)
+static DWORD urlcache_copy_entry(cache_container *container, const urlcache_header *header,
+        INTERNET_CACHE_ENTRY_INFOA *entry_info, DWORD *info_size, const entry_url *url_entry, BOOL unicode)
 {
-    int lenUrl;
-    DWORD dwRequiredSize = sizeof(*lpCacheEntryInfo);
-
-    if (*lpdwBufferSize >= dwRequiredSize)
-    {
-        lpCacheEntryInfo->lpHeaderInfo = NULL;
-        lpCacheEntryInfo->lpszFileExtension = NULL;
-        lpCacheEntryInfo->lpszLocalFileName = NULL;
-        lpCacheEntryInfo->lpszSourceUrlName = NULL;
-        lpCacheEntryInfo->CacheEntryType = pUrlEntry->cache_entry_type;
-        lpCacheEntryInfo->u.dwExemptDelta = pUrlEntry->exempt_delta;
-        lpCacheEntryInfo->dwHeaderInfoSize = pUrlEntry->header_info_size;
-        lpCacheEntryInfo->dwHitRate = pUrlEntry->hit_rate;
-        lpCacheEntryInfo->dwSizeHigh = pUrlEntry->size.u.HighPart;
-        lpCacheEntryInfo->dwSizeLow = pUrlEntry->size.u.LowPart;
-        lpCacheEntryInfo->dwStructSize = sizeof(*lpCacheEntryInfo);
-        lpCacheEntryInfo->dwUseCount = pUrlEntry->use_count;
-        URLCache_DosDateTimeToFileTime(pUrlEntry->expire_date, pUrlEntry->expire_time, &lpCacheEntryInfo->ExpireTime);
-        lpCacheEntryInfo->LastAccessTime = pUrlEntry->access_time;
-        lpCacheEntryInfo->LastModifiedTime = pUrlEntry->modification_time;
-        URLCache_DosDateTimeToFileTime(pUrlEntry->sync_date, pUrlEntry->sync_time, &lpCacheEntryInfo->LastSyncTime);
-    }
-
-    if ((dwRequiredSize % 4) && (dwRequiredSize < *lpdwBufferSize))
-        ZeroMemory((LPBYTE)lpCacheEntryInfo + dwRequiredSize, 4 - (dwRequiredSize % 4));
-    dwRequiredSize = DWORD_ALIGN(dwRequiredSize);
-    if (bUnicode)
-        lenUrl = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pUrlEntry + pUrlEntry->url_off, -1, NULL, 0);
+    int url_len;
+    DWORD size = sizeof(*entry_info);
+
+    if(*info_size >= size) {
+        entry_info->lpHeaderInfo = NULL;
+        entry_info->lpszFileExtension = NULL;
+        entry_info->lpszLocalFileName = NULL;
+        entry_info->lpszSourceUrlName = NULL;
+        entry_info->CacheEntryType = url_entry->cache_entry_type;
+        entry_info->u.dwExemptDelta = url_entry->exempt_delta;
+        entry_info->dwHeaderInfoSize = url_entry->header_info_size;
+        entry_info->dwHitRate = url_entry->hit_rate;
+        entry_info->dwSizeHigh = url_entry->size.u.HighPart;
+        entry_info->dwSizeLow = url_entry->size.u.LowPart;
+        entry_info->dwStructSize = sizeof(*entry_info);
+        entry_info->dwUseCount = url_entry->use_count;
+        dos_date_time_to_file_time(url_entry->expire_date, url_entry->expire_time, &entry_info->ExpireTime);
+        entry_info->LastAccessTime = url_entry->access_time;
+        entry_info->LastModifiedTime = url_entry->modification_time;
+        dos_date_time_to_file_time(url_entry->sync_date, url_entry->sync_time, &entry_info->LastSyncTime);
+    }
+
+    if(size%4 && size<*info_size)
+        ZeroMemory((LPBYTE)entry_info+size, 4-size%4);
+    size = DWORD_ALIGN(size);
+    if(unicode)
+        url_len = urlcache_decode_url((const char*)url_entry+url_entry->url_off, NULL, 0);
     else
-        lenUrl = strlen((LPCSTR)pUrlEntry + pUrlEntry->url_off);
-    dwRequiredSize += (lenUrl + 1) * (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
+        url_len = strlen((LPCSTR)url_entry+url_entry->url_off) + 1;
+    size += url_len * (unicode ? sizeof(WCHAR) : sizeof(CHAR));
 
-    /* FIXME: is source url optional? */
-    if (*lpdwBufferSize >= dwRequiredSize)
-    {
-        DWORD lenUrlBytes = (lenUrl+1) * (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
+    if(*info_size >= size) {
+        DWORD url_size = url_len * (unicode ? sizeof(WCHAR) : sizeof(CHAR));
 
-        lpCacheEntryInfo->lpszSourceUrlName = (LPSTR)lpCacheEntryInfo + dwRequiredSize - lenUrlBytes;
-        if (bUnicode)
-            MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pUrlEntry + pUrlEntry->url_off, -1, (LPWSTR)lpCacheEntryInfo->lpszSourceUrlName, lenUrl + 1);
+        entry_info->lpszSourceUrlName = (LPSTR)entry_info+size-url_size;
+        if(unicode)
+            urlcache_decode_url((const char*)url_entry+url_entry->url_off, (WCHAR*)entry_info->lpszSourceUrlName, url_len);
         else
-            memcpy(lpCacheEntryInfo->lpszSourceUrlName, (LPCSTR)pUrlEntry + pUrlEntry->url_off, lenUrlBytes);
+            memcpy(entry_info->lpszSourceUrlName, (LPCSTR)url_entry+url_entry->url_off, url_size);
     }
 
-    if ((dwRequiredSize % 4) && (dwRequiredSize < *lpdwBufferSize))
-        ZeroMemory((LPBYTE)lpCacheEntryInfo + dwRequiredSize, 4 - (dwRequiredSize % 4));
-    dwRequiredSize = DWORD_ALIGN(dwRequiredSize);
+    if(size%4 && size<*info_size)
+        ZeroMemory((LPBYTE)entry_info+size, 4-size%4);
+    size = DWORD_ALIGN(size);
 
-    if (pUrlEntry->local_name_off)
-    {
-        LONG nLocalFilePathSize;
-        LPSTR lpszLocalFileName;
-        lpszLocalFileName = (LPSTR)lpCacheEntryInfo + dwRequiredSize;
-        nLocalFilePathSize = *lpdwBufferSize - dwRequiredSize;
-        if ((bUnicode && URLCache_LocalFileNameToPathW(pContainer, pHeader, (LPCSTR)pUrlEntry + pUrlEntry->local_name_off, pUrlEntry->cache_dir, (LPWSTR)lpszLocalFileName, &nLocalFilePathSize)) ||
-            (!bUnicode && URLCache_LocalFileNameToPathA(pContainer, pHeader, (LPCSTR)pUrlEntry + pUrlEntry->local_name_off, pUrlEntry->cache_dir, lpszLocalFileName, &nLocalFilePathSize)))
-        {
-            lpCacheEntryInfo->lpszLocalFileName = lpszLocalFileName;
+    if(url_entry->local_name_off) {
+        LONG file_name_size;
+        LPSTR file_name;
+        file_name = (LPSTR)entry_info+size;
+        file_name_size = *info_size-size;
+        if((unicode && urlcache_create_file_pathW(container, header, (LPCSTR)url_entry+url_entry->local_name_off, url_entry->cache_dir, (LPWSTR)file_name, &file_name_size)) ||
+            (!unicode && urlcache_create_file_pathA(container, header, (LPCSTR)url_entry+url_entry->local_name_off, url_entry->cache_dir, file_name, &file_name_size))) {
+            entry_info->lpszLocalFileName = file_name;
         }
-        dwRequiredSize += nLocalFilePathSize * (bUnicode ? sizeof(WCHAR) : sizeof(CHAR)) ;
+        size += file_name_size;
 
-        if ((dwRequiredSize % 4) && (dwRequiredSize < *lpdwBufferSize))
-            ZeroMemory((LPBYTE)lpCacheEntryInfo + dwRequiredSize, 4 - (dwRequiredSize % 4));
-        dwRequiredSize = DWORD_ALIGN(dwRequiredSize);
+        if(size%4 && size<*info_size)
+            ZeroMemory((LPBYTE)entry_info+size, 4-size%4);
+        size = DWORD_ALIGN(size);
     }
-    dwRequiredSize += pUrlEntry->header_info_size + 1;
 
-    if (*lpdwBufferSize >= dwRequiredSize)
-    {
-        lpCacheEntryInfo->lpHeaderInfo = (LPBYTE)lpCacheEntryInfo + dwRequiredSize - pUrlEntry->header_info_size - 1;
-        memcpy(lpCacheEntryInfo->lpHeaderInfo, (LPCSTR)pUrlEntry + pUrlEntry->header_info_off, pUrlEntry->header_info_size);
-        ((LPBYTE)lpCacheEntryInfo)[dwRequiredSize - 1] = '\0';
+    if(url_entry->header_info_off) {
+        DWORD header_len;
+
+        if(unicode)
+            header_len = MultiByteToWideChar(CP_UTF8, 0, (const char*)url_entry+url_entry->header_info_off,
+                    url_entry->header_info_size, NULL, 0);
+        else
+            header_len = url_entry->header_info_size;
+        size += header_len * (unicode ? sizeof(WCHAR) : sizeof(CHAR));
+
+        if(*info_size >= size) {
+            DWORD header_size = header_len * (unicode ? sizeof(WCHAR) : sizeof(CHAR));
+            entry_info->lpHeaderInfo = (LPBYTE)entry_info+size-header_size;
+            if(unicode)
+                MultiByteToWideChar(CP_UTF8, 0, (const char*)url_entry+url_entry->header_info_off,
+                        url_entry->header_info_size, (LPWSTR)entry_info->lpHeaderInfo, header_len);
+            else
+                memcpy(entry_info->lpHeaderInfo, (LPCSTR)url_entry+url_entry->header_info_off, header_len);
+        }
+        if(size%4 && size<*info_size)
+            ZeroMemory((LPBYTE)entry_info+size, 4-size%4);
+        size = DWORD_ALIGN(size);
     }
-    if ((dwRequiredSize % 4) && (dwRequiredSize < *lpdwBufferSize))
-        ZeroMemory((LPBYTE)lpCacheEntryInfo + dwRequiredSize, 4 - (dwRequiredSize % 4));
-    dwRequiredSize = DWORD_ALIGN(dwRequiredSize);
 
-    if (pUrlEntry->file_extension_off)
-    {
-        int lenExtension;
+    if(url_entry->file_extension_off) {
+        int ext_len;
 
-        if (bUnicode)
-            lenExtension = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pUrlEntry + pUrlEntry->file_extension_off, -1, NULL, 0);
+        if(unicode)
+            ext_len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)url_entry+url_entry->file_extension_off, -1, NULL, 0);
         else
-            lenExtension = strlen((LPCSTR)pUrlEntry + pUrlEntry->file_extension_off) + 1;
-        dwRequiredSize += lenExtension * (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
-
-        if (*lpdwBufferSize >= dwRequiredSize)
-        {
-            lpCacheEntryInfo->lpszFileExtension = (LPSTR)lpCacheEntryInfo + dwRequiredSize - lenExtension;
-            if (bUnicode)
-                MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pUrlEntry + pUrlEntry->file_extension_off, -1, (LPWSTR)lpCacheEntryInfo->lpszSourceUrlName, lenExtension);
+            ext_len = strlen((LPCSTR)url_entry+url_entry->file_extension_off) + 1;
+        size += ext_len * (unicode ? sizeof(WCHAR) : sizeof(CHAR));
+
+        if(*info_size >= size) {
+            DWORD ext_size = ext_len * (unicode ? sizeof(WCHAR) : sizeof(CHAR));
+            entry_info->lpszFileExtension = (LPSTR)entry_info+size-ext_size;
+            if(unicode)
+                MultiByteToWideChar(CP_ACP, 0, (LPCSTR)url_entry+url_entry->file_extension_off, -1, (LPWSTR)entry_info->lpszFileExtension, ext_len);
             else
-                memcpy(lpCacheEntryInfo->lpszFileExtension, (LPCSTR)pUrlEntry + pUrlEntry->file_extension_off, lenExtension * sizeof(CHAR));
+                memcpy(entry_info->lpszFileExtension, (LPCSTR)url_entry+url_entry->file_extension_off, ext_len*sizeof(CHAR));
         }
 
-        if ((dwRequiredSize % 4) && (dwRequiredSize < *lpdwBufferSize))
-            ZeroMemory((LPBYTE)lpCacheEntryInfo + dwRequiredSize, 4 - (dwRequiredSize % 4));
-        dwRequiredSize = DWORD_ALIGN(dwRequiredSize);
+        if(size%4 && size<*info_size)
+            ZeroMemory((LPBYTE)entry_info+size, 4-size%4);
+        size = DWORD_ALIGN(size);
     }
 
-    if (dwRequiredSize > *lpdwBufferSize)
-    {
-        *lpdwBufferSize = dwRequiredSize;
+    if(size > *info_size) {
+        *info_size = size;
         return ERROR_INSUFFICIENT_BUFFER;
     }
-    *lpdwBufferSize = dwRequiredSize;
+    *info_size = size;
     return ERROR_SUCCESS;
 }
 
 /***********************************************************************
- *           URLCache_SetEntryInfo (Internal)
+ *           urlcache_set_entry_info (Internal)
  *
  *  Helper for SetUrlCacheEntryInfo{A,W}. Sets fields in URL entry
- * according to the flags set by dwFieldControl.
+ * according to the flags set by field_control.
  *
  * RETURNS
  *    ERROR_SUCCESS if the buffer was big enough
  *    ERROR_INSUFFICIENT_BUFFER if the buffer was too small
  *
  */
-static DWORD URLCache_SetEntryInfo(entry_url * pUrlEntry, const INTERNET_CACHE_ENTRY_INFOW * lpCacheEntryInfo, DWORD dwFieldControl)
+static DWORD urlcache_set_entry_info(entry_url *url_entry, const INTERNET_CACHE_ENTRY_INFOA *entry_info, DWORD field_control)
 {
-    if (dwFieldControl & CACHE_ENTRY_ACCTIME_FC)
-        pUrlEntry->access_time = lpCacheEntryInfo->LastAccessTime;
-    if (dwFieldControl & CACHE_ENTRY_ATTRIBUTE_FC)
-        pUrlEntry->cache_entry_type = lpCacheEntryInfo->CacheEntryType;
-    if (dwFieldControl & CACHE_ENTRY_EXEMPT_DELTA_FC)
-        pUrlEntry->exempt_delta = lpCacheEntryInfo->u.dwExemptDelta;
-    if (dwFieldControl & CACHE_ENTRY_EXPTIME_FC)
-        URLCache_FileTimeToDosDateTime(&lpCacheEntryInfo->ExpireTime, &pUrlEntry->expire_date, &pUrlEntry->expire_time);
-    if (dwFieldControl & CACHE_ENTRY_HEADERINFO_FC)
+    if (field_control & CACHE_ENTRY_ACCTIME_FC)
+        url_entry->access_time = entry_info->LastAccessTime;
+    if (field_control & CACHE_ENTRY_ATTRIBUTE_FC)
+        url_entry->cache_entry_type = entry_info->CacheEntryType;
+    if (field_control & CACHE_ENTRY_EXEMPT_DELTA_FC)
+        url_entry->exempt_delta = entry_info->u.dwExemptDelta;
+    if (field_control & CACHE_ENTRY_EXPTIME_FC)
+        file_time_to_dos_date_time(&entry_info->ExpireTime, &url_entry->expire_date, &url_entry->expire_time);
+    if (field_control & CACHE_ENTRY_HEADERINFO_FC)
         FIXME("CACHE_ENTRY_HEADERINFO_FC unimplemented\n");
-    if (dwFieldControl & CACHE_ENTRY_HITRATE_FC)
-        pUrlEntry->hit_rate = lpCacheEntryInfo->dwHitRate;
-    if (dwFieldControl & CACHE_ENTRY_MODTIME_FC)
-        pUrlEntry->modification_time = lpCacheEntryInfo->LastModifiedTime;
-    if (dwFieldControl & CACHE_ENTRY_SYNCTIME_FC)
-        URLCache_FileTimeToDosDateTime(&lpCacheEntryInfo->LastAccessTime, &pUrlEntry->sync_date, &pUrlEntry->sync_time);
+    if (field_control & CACHE_ENTRY_HITRATE_FC)
+        url_entry->hit_rate = entry_info->dwHitRate;
+    if (field_control & CACHE_ENTRY_MODTIME_FC)
+        url_entry->modification_time = entry_info->LastModifiedTime;
+    if (field_control & CACHE_ENTRY_SYNCTIME_FC)
+        file_time_to_dos_date_time(&entry_info->LastAccessTime, &url_entry->sync_date, &url_entry->sync_time);
 
     return ERROR_SUCCESS;
 }
 
 /***********************************************************************
- *           URLCache_HashKey (Internal)
+ *           urlcache_hash_key (Internal)
  *
  *  Returns the hash key for a given string
  *
@@ -1354,7 +1468,7 @@ static DWORD URLCache_SetEntryInfo(entry_url * pUrlEntry, const INTERNET_CACHE_E
  *    hash key for the string
  *
  */
-static DWORD URLCache_HashKey(LPCSTR lpszKey)
+static DWORD urlcache_hash_key(LPCSTR lpszKey)
 {
     /* NOTE: this uses the same lookup table as SHLWAPI.UrlHash{A,W}
      * but the algorithm and result are not the same!
@@ -1409,19 +1523,14 @@ static DWORD URLCache_HashKey(LPCSTR lpszKey)
     return *(DWORD *)key;
 }
 
-static inline HASH_CACHEFILE_ENTRY * URLCache_HashEntryFromOffset(LPCURLCACHE_HEADER pHeader, DWORD dwOffset)
+static inline entry_hash_table* urlcache_get_hash_table(const urlcache_header *pHeader, DWORD dwOffset)
 {
-    return (HASH_CACHEFILE_ENTRY *)((LPBYTE)pHeader + dwOffset);
+    if(!dwOffset)
+        return NULL;
+    return (entry_hash_table*)((LPBYTE)pHeader + dwOffset);
 }
 
-static inline BOOL URLCache_IsHashEntryValid(LPCURLCACHE_HEADER pHeader, const HASH_CACHEFILE_ENTRY *pHashEntry)
-{
-    /* check pHashEntry located within acceptable bounds in the URL cache mapping */
-    return ((DWORD)((const BYTE*)pHashEntry - (const BYTE*)pHeader) >= ENTRY_START_OFFSET) &&
-           ((DWORD)((const BYTE*)pHashEntry - (const BYTE*)pHeader) < pHeader->dwFileSize);
-}
-
-static BOOL URLCache_FindHash(LPCURLCACHE_HEADER pHeader, LPCSTR lpszUrl, struct _HASH_ENTRY ** ppHashEntry)
+static BOOL urlcache_find_hash_entry(const urlcache_header *pHeader, LPCSTR lpszUrl, struct hash_entry **ppHashEntry)
 {
     /* structure of hash table:
      *  448 entries divided into 64 blocks
@@ -1435,34 +1544,33 @@ static BOOL URLCache_FindHash(LPCURLCACHE_HEADER pHeader, LPCSTR lpszUrl, struct
      *  there can be multiple hash tables in the file and the offset to
      *  the next one is stored in the header of the hash table
      */
-    DWORD key = URLCache_HashKey(lpszUrl);
+    DWORD key = urlcache_hash_key(lpszUrl);
     DWORD offset = (key & (HASHTABLE_NUM_ENTRIES-1)) * HASHTABLE_BLOCKSIZE;
-    HASH_CACHEFILE_ENTRY * pHashEntry;
-    DWORD dwHashTableNumber = 0;
+    entry_hash_table* pHashEntry;
+    DWORD id = 0;
 
     key >>= HASHTABLE_FLAG_BITS;
 
-    for (pHashEntry = URLCache_HashEntryFromOffset(pHeader, pHeader->dwOffsetFirstHashTable);
-         URLCache_IsHashEntryValid(pHeader, pHashEntry);
-         pHashEntry = URLCache_HashEntryFromOffset(pHeader, pHashEntry->dwAddressNext))
+    for (pHashEntry = urlcache_get_hash_table(pHeader, pHeader->hash_table_off);
+         pHashEntry; pHashEntry = urlcache_get_hash_table(pHeader, pHashEntry->next))
     {
         int i;
-        if (pHashEntry->dwHashTableNumber != dwHashTableNumber++)
+        if (pHashEntry->id != id++)
         {
-            ERR("Error: not right hash table number (%d) expected %d\n", pHashEntry->dwHashTableNumber, dwHashTableNumber);
+            ERR("Error: not right hash table number (%d) expected %d\n", pHashEntry->id, id);
             continue;
         }
         /* make sure that it is in fact a hash entry */
-        if (pHashEntry->CacheFileEntry.signature != HASH_SIGNATURE)
+        if (pHashEntry->header.signature != HASH_SIGNATURE)
         {
-            ERR("Error: not right signature (\"%.4s\") - expected \"HASH\"\n", (LPCSTR)&pHashEntry->CacheFileEntry.signature);
+            ERR("Error: not right signature (\"%.4s\") - expected \"HASH\"\n", (LPCSTR)&pHashEntry->header.signature);
             continue;
         }
 
         for (i = 0; i < HASHTABLE_BLOCKSIZE; i++)
         {
-            struct _HASH_ENTRY * pHashElement = &pHashEntry->HashTable[offset + i];
-            if (key == pHashElement->dwHashKey>>HASHTABLE_FLAG_BITS)
+            struct hash_entry *pHashElement = &pHashEntry->hash_table[offset + i];
+            if (key == pHashElement->key>>HASHTABLE_FLAG_BITS)
             {
                 /* FIXME: we should make sure that this is the right element
                  * before returning and claiming that it is. We can do this
@@ -1478,25 +1586,8 @@ static BOOL URLCache_FindHash(LPCURLCACHE_HEADER pHeader, LPCSTR lpszUrl, struct
     return FALSE;
 }
 
-static BOOL URLCache_FindHashW(LPCURLCACHE_HEADER pHeader, LPCWSTR lpszUrl, struct _HASH_ENTRY ** ppHashEntry)
-{
-    LPSTR urlA;
-    BOOL ret;
-
-    urlA = heap_strdupWtoA(lpszUrl);
-    if (!urlA)
-    {
-        SetLastError(ERROR_OUTOFMEMORY);
-        return FALSE;
-    }
-
-    ret = URLCache_FindHash(pHeader, urlA, ppHashEntry);
-    heap_free(urlA);
-    return ret;
-}
-
 /***********************************************************************
- *           URLCache_HashEntrySetFlags (Internal)
+ *           urlcache_hash_entry_set_flags (Internal)
  *
  *  Sets special bits in hash key
  *
@@ -1504,13 +1595,13 @@ static BOOL URLCache_FindHashW(LPCURLCACHE_HEADER pHeader, LPCWSTR lpszUrl, stru
  *    nothing
  *
  */
-static void URLCache_HashEntrySetFlags(struct _HASH_ENTRY * pHashEntry, DWORD dwFlag)
+static void urlcache_hash_entry_set_flags(struct hash_entry *pHashEntry, DWORD dwFlag)
 {
-    pHashEntry->dwHashKey = (pHashEntry->dwHashKey >> HASHTABLE_FLAG_BITS << HASHTABLE_FLAG_BITS) | dwFlag;
+    pHashEntry->key = (pHashEntry->key >> HASHTABLE_FLAG_BITS << HASHTABLE_FLAG_BITS) | dwFlag;
 }
 
 /***********************************************************************
- *           URLCache_DeleteEntryFromHash (Internal)
+ *           urlcache_hash_entry_delete (Internal)
  *
  *  Searches all the hash tables in the index for the given URL and
  * then if found deletes the entry.
@@ -1520,14 +1611,14 @@ static void URLCache_HashEntrySetFlags(struct _HASH_ENTRY * pHashEntry, DWORD dw
  *    FALSE if the entry could not be found
  *
  */
-static BOOL URLCache_DeleteEntryFromHash(struct _HASH_ENTRY * pHashEntry)
+static BOOL urlcache_hash_entry_delete(struct hash_entry *pHashEntry)
 {
-    pHashEntry->dwHashKey = HASHTABLE_DEL;
+    pHashEntry->key = HASHTABLE_DEL;
     return TRUE;
 }
 
 /***********************************************************************
- *           URLCache_AddEntryToHash (Internal)
+ *           urlcache_hash_entry_create (Internal)
  *
  *  Searches all the hash tables for a free slot based on the offset
  * generated from the hash key. If a free slot is found, the offset and
@@ -1538,96 +1629,58 @@ static BOOL URLCache_DeleteEntryFromHash(struct _HASH_ENTRY * pHashEntry)
  *    Any other Win32 error code if the entry could not be added
  *
  */
-static DWORD URLCache_AddEntryToHash(LPURLCACHE_HEADER pHeader, LPCSTR lpszUrl, DWORD dwOffsetEntry, DWORD dwFieldType)
+static DWORD urlcache_hash_entry_create(urlcache_header *pHeader, LPCSTR lpszUrl, DWORD dwOffsetEntry, DWORD dwFieldType)
 {
-    /* see URLCache_FindEntryInHash for structure of hash tables */
+    /* see urlcache_find_hash_entry for structure of hash tables */
 
-    DWORD key = URLCache_HashKey(lpszUrl);
+    DWORD key = urlcache_hash_key(lpszUrl);
     DWORD offset = (key & (HASHTABLE_NUM_ENTRIES-1)) * HASHTABLE_BLOCKSIZE;
-    HASH_CACHEFILE_ENTRY * pHashEntry, *pHashPrev = NULL;
-    DWORD dwHashTableNumber = 0;
+    entry_hash_table* pHashEntry, *pHashPrev = NULL;
+    DWORD id = 0;
     DWORD error;
 
     key = ((key >> HASHTABLE_FLAG_BITS) << HASHTABLE_FLAG_BITS) + dwFieldType;
 
-    for (pHashEntry = URLCache_HashEntryFromOffset(pHeader, pHeader->dwOffsetFirstHashTable);
-         URLCache_IsHashEntryValid(pHeader, pHashEntry);
-         pHashEntry = URLCache_HashEntryFromOffset(pHeader, pHashEntry->dwAddressNext))
+    for (pHashEntry = urlcache_get_hash_table(pHeader, pHeader->hash_table_off);
+         pHashEntry; pHashEntry = urlcache_get_hash_table(pHeader, pHashEntry->next))
     {
         int i;
         pHashPrev = pHashEntry;
 
-        if (pHashEntry->dwHashTableNumber != dwHashTableNumber++)
+        if (pHashEntry->id != id++)
         {
-            ERR("not right hash table number (%d) expected %d\n", pHashEntry->dwHashTableNumber, dwHashTableNumber);
+            ERR("not right hash table number (%d) expected %d\n", pHashEntry->id, id);
             break;
         }
         /* make sure that it is in fact a hash entry */
-        if (pHashEntry->CacheFileEntry.signature != HASH_SIGNATURE)
+        if (pHashEntry->header.signature != HASH_SIGNATURE)
         {
-            ERR("not right signature (\"%.4s\") - expected \"HASH\"\n", (LPCSTR)&pHashEntry->CacheFileEntry.signature);
+            ERR("not right signature (\"%.4s\") - expected \"HASH\"\n", (LPCSTR)&pHashEntry->header.signature);
             break;
         }
 
         for (i = 0; i < HASHTABLE_BLOCKSIZE; i++)
         {
-            struct _HASH_ENTRY * pHashElement = &pHashEntry->HashTable[offset + i];
-            if (pHashElement->dwHashKey==HASHTABLE_FREE || pHashElement->dwHashKey==HASHTABLE_DEL) /* if the slot is free */
+            struct hash_entry *pHashElement = &pHashEntry->hash_table[offset + i];
+            if (pHashElement->key==HASHTABLE_FREE || pHashElement->key==HASHTABLE_DEL) /* if the slot is free */
             {
-                pHashElement->dwHashKey = key;
-                pHashElement->dwOffsetEntry = dwOffsetEntry;
+                pHashElement->key = key;
+                pHashElement->offset = dwOffsetEntry;
                 return ERROR_SUCCESS;
             }
         }
     }
-    error = URLCache_CreateHashTable(pHeader, pHashPrev, &pHashEntry);
+    error = urlcache_create_hash_table(pHeader, pHashPrev, &pHashEntry);
     if (error != ERROR_SUCCESS)
         return error;
 
-    pHashEntry->HashTable[offset].dwHashKey = key;
-    pHashEntry->HashTable[offset].dwOffsetEntry = dwOffsetEntry;
+    pHashEntry->hash_table[offset].key = key;
+    pHashEntry->hash_table[offset].offset = dwOffsetEntry;
     return ERROR_SUCCESS;
 }
 
 /***********************************************************************
- *           URLCache_CreateHashTable (Internal)
- *
- *  Creates a new hash table in free space and adds it to the chain of existing
- * hash tables.
- *
- * RETURNS
- *    ERROR_SUCCESS if the hash table was created
- *    ERROR_DISK_FULL if the hash table could not be created
- *
- */
-static DWORD URLCache_CreateHashTable(LPURLCACHE_HEADER pHeader, HASH_CACHEFILE_ENTRY *pPrevHash, HASH_CACHEFILE_ENTRY **ppHash)
-{
-    DWORD dwOffset, error;
-    int i;
-
-    if ((error = URLCache_FindFirstFreeEntry(pHeader, 0x20, (entry_header**)ppHash)) != ERROR_SUCCESS)
-        return error;
-
-    dwOffset = (BYTE *)*ppHash - (BYTE *)pHeader;
-
-    if (pPrevHash)
-        pPrevHash->dwAddressNext = dwOffset;
-    else
-        pHeader->dwOffsetFirstHashTable = dwOffset;
-    (*ppHash)->CacheFileEntry.signature = HASH_SIGNATURE;
-    (*ppHash)->CacheFileEntry.blocks_used = 0x20;
-    (*ppHash)->dwAddressNext = 0;
-    (*ppHash)->dwHashTableNumber = pPrevHash ? pPrevHash->dwHashTableNumber + 1 : 0;
-    for (i = 0; i < HASHTABLE_SIZE; i++)
-    {
-        (*ppHash)->HashTable[i].dwOffsetEntry = HASHTABLE_FREE;
-        (*ppHash)->HashTable[i].dwHashKey = HASHTABLE_FREE;
-    }
-    return ERROR_SUCCESS;
-}
-
-/***********************************************************************
- *           URLCache_EnumHashTables (Internal)
+ *           urlcache_enum_hash_tables (Internal)
  *
  *  Enumerates the hash tables in a container.
  *
@@ -1636,31 +1689,30 @@ static DWORD URLCache_CreateHashTable(LPURLCACHE_HEADER pHeader, HASH_CACHEFILE_
  *    FALSE if there are no more tables to enumerate.
  *
  */
-static BOOL URLCache_EnumHashTables(LPCURLCACHE_HEADER pHeader, DWORD *pdwHashTableNumber, HASH_CACHEFILE_ENTRY ** ppHashEntry)
+static BOOL urlcache_enum_hash_tables(const urlcache_header *pHeader, DWORD *id, entry_hash_table **ppHashEntry)
 {
-    for (*ppHashEntry = URLCache_HashEntryFromOffset(pHeader, pHeader->dwOffsetFirstHashTable);
-         URLCache_IsHashEntryValid(pHeader, *ppHashEntry);
-         *ppHashEntry = URLCache_HashEntryFromOffset(pHeader, (*ppHashEntry)->dwAddressNext))
+    for (*ppHashEntry = urlcache_get_hash_table(pHeader, pHeader->hash_table_off);
+         *ppHashEntry; *ppHashEntry = urlcache_get_hash_table(pHeader, (*ppHashEntry)->next))
     {
-        TRACE("looking at hash table number %d\n", (*ppHashEntry)->dwHashTableNumber);
-        if ((*ppHashEntry)->dwHashTableNumber != *pdwHashTableNumber)
+        TRACE("looking at hash table number %d\n", (*ppHashEntry)->id);
+        if ((*ppHashEntry)->id != *id)
             continue;
         /* make sure that it is in fact a hash entry */
-        if ((*ppHashEntry)->CacheFileEntry.signature != HASH_SIGNATURE)
+        if ((*ppHashEntry)->header.signature != HASH_SIGNATURE)
         {
-            ERR("Error: not right signature (\"%.4s\") - expected \"HASH\"\n", (LPCSTR)&(*ppHashEntry)->CacheFileEntry.signature);
-            (*pdwHashTableNumber)++;
+            ERR("Error: not right signature (\"%.4s\") - expected \"HASH\"\n", (LPCSTR)&(*ppHashEntry)->header.signature);
+            (*id)++;
             continue;
         }
 
-        TRACE("hash table number %d found\n", *pdwHashTableNumber);
+        TRACE("hash table number %d found\n", *id);
         return TRUE;
     }
     return FALSE;
 }
 
 /***********************************************************************
- *           URLCache_EnumHashTableEntries (Internal)
+ *           urlcache_enum_hash_table_entries (Internal)
  *
  *  Enumerates entries in a hash table and returns the next non-free entry.
  *
@@ -1670,15 +1722,15 @@ static BOOL URLCache_EnumHashTables(LPCURLCACHE_HEADER pHeader, DWORD *pdwHashTa
  *     enumerate.
  *
  */
-static BOOL URLCache_EnumHashTableEntries(LPCURLCACHE_HEADER pHeader, const HASH_CACHEFILE_ENTRY * pHashEntry,
-                                          DWORD * index, const struct _HASH_ENTRY ** ppHashEntry)
+static BOOL urlcache_enum_hash_table_entries(const urlcache_header *pHeader, const entry_hash_table *pHashEntry,
+                                          DWORD * index, const struct hash_entry **ppHashEntry)
 {
     for (; *index < HASHTABLE_SIZE ; (*index)++)
     {
-        if (pHashEntry->HashTable[*index].dwHashKey==HASHTABLE_FREE || pHashEntry->HashTable[*index].dwHashKey==HASHTABLE_DEL)
+        if (pHashEntry->hash_table[*index].key==HASHTABLE_FREE || pHashEntry->hash_table[*index].key==HASHTABLE_DEL)
             continue;
 
-        *ppHashEntry = &pHashEntry->HashTable[*index];
+        *ppHashEntry = &pHashEntry->hash_table[*index];
         TRACE("entry found %d\n", *index);
         return TRUE;
     }
@@ -1687,7 +1739,7 @@ static BOOL URLCache_EnumHashTableEntries(LPCURLCACHE_HEADER pHeader, const HASH
 }
 
 /***********************************************************************
- *           URLCache_DeleteCacheDirectory (Internal)
+ *           cache_container_delete_dir (Internal)
  *
  *  Erase a directory containing an URL cache.
  *
@@ -1695,7 +1747,7 @@ static BOOL URLCache_EnumHashTableEntries(LPCURLCACHE_HEADER pHeader, const HASH
  *    TRUE success, FALSE failure/aborted.
  *
  */
-static BOOL URLCache_DeleteCacheDirectory(LPCWSTR lpszPath)
+static BOOL cache_container_delete_dir(LPCWSTR lpszPath)
 {
     DWORD path_len;
     WCHAR path[MAX_PATH + 1];
@@ -1721,16 +1773,16 @@ static BOOL URLCache_DeleteCacheDirectory(LPCWSTR lpszPath)
 }
 
 /***********************************************************************
- *           URLCache_IsLocked (Internal)
+ *           urlcache_hash_entry_is_locked (Internal)
  *
  *  Checks if entry is locked. Unlocks it if possible.
  */
-static BOOL URLCache_IsLocked(struct _HASH_ENTRY *hash_entry, entry_url *url_entry)
+static BOOL urlcache_hash_entry_is_locked(struct hash_entry *hash_entry, entry_url *url_entry)
 {
     FILETIME cur_time;
     ULARGE_INTEGER acc_time, time;
 
-    if ((hash_entry->dwHashKey & ((1<<HASHTABLE_FLAG_BITS)-1)) != HASHTABLE_LOCK)
+    if ((hash_entry->key & ((1<<HASHTABLE_FLAG_BITS)-1)) != HASHTABLE_LOCK)
         return FALSE;
 
     GetSystemTimeAsFileTime(&cur_time);
@@ -1744,7 +1796,7 @@ static BOOL URLCache_IsLocked(struct _HASH_ENTRY *hash_entry, entry_url *url_ent
 
     /* check if entry was locked for at least a day */
     if(time.QuadPart > (ULONGLONG)24*60*60*FILETIME_SECOND) {
-        URLCache_HashEntrySetFlags(hash_entry, HASHTABLE_URL);
+        urlcache_hash_entry_set_flags(hash_entry, HASHTABLE_URL);
         url_entry->use_count = 0;
         return FALSE;
     }
@@ -1752,273 +1804,254 @@ static BOOL URLCache_IsLocked(struct _HASH_ENTRY *hash_entry, entry_url *url_ent
     return TRUE;
 }
 
-/***********************************************************************
- *           GetUrlCacheEntryInfoExA (WININET.@)
- *
- */
-BOOL WINAPI GetUrlCacheEntryInfoExA(
-    LPCSTR lpszUrl,
-    LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo,
-    LPDWORD lpdwCacheEntryInfoBufSize,
-    LPSTR lpszReserved,
-    LPDWORD lpdwReserved,
-    LPVOID lpReserved,
-    DWORD dwFlags)
+static BOOL urlcache_get_entry_info(const char *url, void *entry_info,
+        DWORD *size, DWORD flags, BOOL unicode)
 {
-    LPURLCACHE_HEADER pHeader;
-    struct _HASH_ENTRY * pHashEntry;
-    const entry_header *pEntry;
-    const entry_url * pUrlEntry;
-    URLCACHECONTAINER * pContainer;
+    urlcache_header *header;
+    struct hash_entry *hash_entry;
+    const entry_url *url_entry;
+    cache_container *container;
     DWORD error;
 
-    TRACE("(%s, %p, %p, %p, %p, %p, %x)\n",
-        debugstr_a(lpszUrl), 
-        lpCacheEntryInfo,
-        lpdwCacheEntryInfoBufSize,
-        lpszReserved,
-        lpdwReserved,
-        lpReserved,
-        dwFlags);
-
-    if ((lpszReserved != NULL) ||
-        (lpdwReserved != NULL) ||
-        (lpReserved != NULL))
-    {
-        ERR("Reserved value was not 0\n");
-        SetLastError(ERROR_INVALID_PARAMETER);
-        return FALSE;
-    }
-    if (dwFlags & ~GET_INSTALLED_ENTRY)
-        FIXME("ignoring unsupported flags: %x\n", dwFlags);
+    TRACE("(%s, %p, %p, %x, %x)\n", debugstr_a(url), entry_info, size, flags, unicode);
 
-    error = URLCacheContainers_FindContainerA(lpszUrl, &pContainer);
-    if (error != ERROR_SUCCESS)
-    {
+    if(flags & ~GET_INSTALLED_ENTRY)
+        FIXME("ignoring unsupported flags: %x\n", flags);
+
+    error = cache_containers_find(url, &container);
+    if(error != ERROR_SUCCESS) {
         SetLastError(error);
         return FALSE;
     }
 
-    error = cache_container_open_index(pContainer, MIN_BLOCK_NO);
-    if (error != ERROR_SUCCESS)
-    {
+    error = cache_container_open_index(container, MIN_BLOCK_NO);
+    if(error != ERROR_SUCCESS) {
         SetLastError(error);
         return FALSE;
     }
 
-    if (!(pHeader = cache_container_lock_index(pContainer)))
+    if(!(header = cache_container_lock_index(container)))
         return FALSE;
 
-    if (!URLCache_FindHash(pHeader, lpszUrl, &pHashEntry))
-    {
-        cache_container_unlock_index(pContainer, pHeader);
-        WARN("entry %s not found!\n", debugstr_a(lpszUrl));
+    if(!urlcache_find_hash_entry(header, url, &hash_entry)) {
+        cache_container_unlock_index(container, header);
+        WARN("entry %s not found!\n", debugstr_a(url));
         SetLastError(ERROR_FILE_NOT_FOUND);
         return FALSE;
     }
 
-    pEntry = (const entry_header*)((LPBYTE)pHeader + pHashEntry->dwOffsetEntry);
-    if (pEntry->signature != URL_SIGNATURE)
-    {
-        cache_container_unlock_index(pContainer, pHeader);
+    url_entry = (const entry_url*)((LPBYTE)header + hash_entry->offset);
+    if(url_entry->header.signature != URL_SIGNATURE) {
+        cache_container_unlock_index(container, header);
         FIXME("Trying to retrieve entry of unknown format %s\n",
-                debugstr_an((LPCSTR)&pEntry->signature, sizeof(DWORD)));
+                debugstr_an((LPCSTR)&url_entry->header.signature, sizeof(DWORD)));
         SetLastError(ERROR_FILE_NOT_FOUND);
         return FALSE;
     }
 
-    pUrlEntry = (const entry_url *)pEntry;
-    TRACE("Found URL: %s\n", debugstr_a((LPCSTR)pUrlEntry + pUrlEntry->url_off));
-    TRACE("Header info: %s\n", debugstr_an((LPCSTR)pUrlEntry +
-                pUrlEntry->header_info_off, pUrlEntry->header_info_size));
+    TRACE("Found URL: %s\n", debugstr_a((LPCSTR)url_entry + url_entry->url_off));
+    TRACE("Header info: %s\n", debugstr_an((LPCSTR)url_entry +
+                url_entry->header_info_off, url_entry->header_info_size));
 
-    if((dwFlags & GET_INSTALLED_ENTRY) && !(pUrlEntry->cache_entry_type & INSTALLED_CACHE_ENTRY))
-    {
-        cache_container_unlock_index(pContainer, pHeader);
+    if((flags & GET_INSTALLED_ENTRY) && !(url_entry->cache_entry_type & INSTALLED_CACHE_ENTRY)) {
+        cache_container_unlock_index(container, header);
         SetLastError(ERROR_FILE_NOT_FOUND);
         return FALSE;
     }
 
-    if (lpdwCacheEntryInfoBufSize)
-    {
-        if (!lpCacheEntryInfo)
-            *lpdwCacheEntryInfoBufSize = 0;
-
-        error = URLCache_CopyEntry(
-            pContainer,
-            pHeader,
-            lpCacheEntryInfo,
-            lpdwCacheEntryInfoBufSize,
-            pUrlEntry,
-            FALSE /* ANSI */);
-        if (error != ERROR_SUCCESS)
-        {
-            cache_container_unlock_index(pContainer, pHeader);
+    if(size) {
+        if(!entry_info)
+            *size = 0;
+
+        error = urlcache_copy_entry(container, header, entry_info, size, url_entry, unicode);
+        if(error != ERROR_SUCCESS) {
+            cache_container_unlock_index(container, header);
             SetLastError(error);
             return FALSE;
         }
-        if(pUrlEntry->local_name_off)
-            TRACE("Local File Name: %s\n", debugstr_a((LPCSTR)pUrlEntry + pUrlEntry->local_name_off));
+        if(url_entry->local_name_off)
+            TRACE("Local File Name: %s\n", debugstr_a((LPCSTR)url_entry + url_entry->local_name_off));
     }
 
-    cache_container_unlock_index(pContainer, pHeader);
-
+    cache_container_unlock_index(container, header);
     return TRUE;
 }
 
 /***********************************************************************
- *           GetUrlCacheEntryInfoA (WININET.@)
+ *           GetUrlCacheEntryInfoExA (WININET.@)
  *
  */
-BOOL WINAPI GetUrlCacheEntryInfoA(
-    IN LPCSTR lpszUrlName,
-    IN LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo,
-    IN OUT LPDWORD lpdwCacheEntryInfoBufferSize
-)
+BOOL WINAPI GetUrlCacheEntryInfoExA(LPCSTR lpszUrl,
+        LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo,
+        LPDWORD lpdwCacheEntryInfoBufSize, LPSTR lpszReserved,
+        LPDWORD lpdwReserved, LPVOID lpReserved, DWORD dwFlags)
 {
-    return GetUrlCacheEntryInfoExA(lpszUrlName, lpCacheEntryInfo,
-            lpdwCacheEntryInfoBufferSize, NULL, NULL, NULL, 0);
+    if(lpszReserved!=NULL || lpdwReserved!=NULL || lpReserved!=NULL) {
+        ERR("Reserved value was not 0\n");
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    return urlcache_get_entry_info(lpszUrl, lpCacheEntryInfo,
+            lpdwCacheEntryInfoBufSize, dwFlags, FALSE);
 }
 
 /***********************************************************************
- *           GetUrlCacheEntryInfoW (WININET.@)
+ *           GetUrlCacheEntryInfoA (WININET.@)
  *
  */
-BOOL WINAPI GetUrlCacheEntryInfoW(LPCWSTR lpszUrl,
-  LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo,
-  LPDWORD lpdwCacheEntryInfoBufferSize)
+BOOL WINAPI GetUrlCacheEntryInfoA(LPCSTR lpszUrlName,
+    LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo,
+    LPDWORD lpdwCacheEntryInfoBufferSize)
 {
-    return GetUrlCacheEntryInfoExW(lpszUrl, lpCacheEntryInfo,
+    return GetUrlCacheEntryInfoExA(lpszUrlName, lpCacheEntryInfo,
             lpdwCacheEntryInfoBufferSize, NULL, NULL, NULL, 0);
 }
 
-/***********************************************************************
- *           GetUrlCacheEntryInfoExW (WININET.@)
- *
- */
-BOOL WINAPI GetUrlCacheEntryInfoExW(
-    LPCWSTR lpszUrl,
-    LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo,
-    LPDWORD lpdwCacheEntryInfoBufSize,
-    LPWSTR lpszReserved,
-    LPDWORD lpdwReserved,
-    LPVOID lpReserved,
-    DWORD dwFlags)
+static int urlcache_encode_url(const WCHAR *url, char *encoded_url, int encoded_len)
 {
-    LPURLCACHE_HEADER pHeader;
-    struct _HASH_ENTRY * pHashEntry;
-    const entry_header *pEntry;
-    const entry_url * pUrlEntry;
-    URLCACHECONTAINER * pContainer;
-    DWORD error;
+#ifndef __REACTOS__ /* FIXME: Vista+ */
+    URL_COMPONENTSW uc;
+    DWORD len, part_len;
+    WCHAR *punycode;
 
-    TRACE("(%s, %p, %p, %p, %p, %p, %x)\n",
-        debugstr_w(lpszUrl),
-        lpCacheEntryInfo,
-        lpdwCacheEntryInfoBufSize,
-        lpszReserved,
-        lpdwReserved,
-        lpReserved,
-        dwFlags);
+    TRACE("%s\n", debugstr_w(url));
 
-    /* Ignore GET_INSTALLED_ENTRY flag in unicode version of function */
-    dwFlags &= ~GET_INSTALLED_ENTRY;
+    memset(&uc, 0, sizeof(uc));
+    uc.dwStructSize = sizeof(uc);
+    uc.dwHostNameLength = 1;
+    if(!InternetCrackUrlW(url, 0, 0, &uc))
+        uc.nScheme = INTERNET_SCHEME_UNKNOWN;
 
-    if ((lpszReserved != NULL) ||
-        (lpdwReserved != NULL) ||
-        (lpReserved != NULL))
-    {
-        ERR("Reserved value was not 0\n");
-        SetLastError(ERROR_INVALID_PARAMETER);
-        return FALSE;
+    if(uc.nScheme!=INTERNET_SCHEME_HTTP && uc.nScheme!=INTERNET_SCHEME_HTTPS)
+#endif
+        return WideCharToMultiByte(CP_UTF8, 0, url, -1, encoded_url, encoded_len, NULL, NULL);
+
+#ifndef __REACTOS__ /* FIXME: Vista+ */
+    len = WideCharToMultiByte(CP_UTF8, 0, url, uc.lpszHostName-url,
+            encoded_url, encoded_len, NULL, NULL);
+    if(!len)
+        return 0;
+    if(encoded_url)
+        encoded_len -= len;
+
+    part_len = IdnToAscii(0, uc.lpszHostName, uc.dwHostNameLength, NULL, 0);
+    if(!part_len) {
+        SetLastError(ERROR_INTERNET_INVALID_URL);
+        return 0;
     }
-    if (dwFlags)
-        FIXME("ignoring unsupported flags: %x\n", dwFlags);
 
-    error = URLCacheContainers_FindContainerW(lpszUrl, &pContainer);
-    if (error != ERROR_SUCCESS)
-    {
-        SetLastError(error);
-        return FALSE;
+    punycode = heap_alloc(part_len*sizeof(WCHAR));
+    if(!punycode)
+        return 0;
+
+    part_len = IdnToAscii(0, uc.lpszHostName, uc.dwHostNameLength, punycode, part_len);
+    if(!part_len) {
+        heap_free(punycode);
+        return 0;
     }
 
-    error = cache_container_open_index(pContainer, MIN_BLOCK_NO);
-    if (error != ERROR_SUCCESS)
-    {
-        SetLastError(error);
+    part_len = WideCharToMultiByte(CP_UTF8, 0, punycode, part_len,
+            encoded_url ? encoded_url+len : NULL, encoded_len, NULL, NULL);
+    heap_free(punycode);
+    if(!part_len)
+        return 0;
+    if(encoded_url)
+        encoded_len -= part_len;
+    len += part_len;
+
+    part_len = WideCharToMultiByte(CP_UTF8, 0, uc.lpszHostName+uc.dwHostNameLength,
+            -1, encoded_url ? encoded_url+len : NULL, encoded_len, NULL, NULL);
+    if(!part_len)
+        return 0;
+    len += part_len;
+
+    TRACE("got (%d)%s\n", len, debugstr_a(encoded_url));
+    return len;
+#endif /* !__REACTOS__ */
+}
+
+static BOOL urlcache_encode_url_alloc(const WCHAR *url, char **encoded_url)
+{
+    DWORD encoded_len;
+    char *ret;
+
+    encoded_len = urlcache_encode_url(url, NULL, 0);
+    if(!encoded_len)
         return FALSE;
-    }
 
-    if (!(pHeader = cache_container_lock_index(pContainer)))
+    ret = heap_alloc(encoded_len*sizeof(WCHAR));
+    if(!ret)
         return FALSE;
 
-    if (!URLCache_FindHashW(pHeader, lpszUrl, &pHashEntry))
-    {
-        cache_container_unlock_index(pContainer, pHeader);
-        WARN("entry %s not found!\n", debugstr_w(lpszUrl));
-        SetLastError(ERROR_FILE_NOT_FOUND);
+    encoded_len = urlcache_encode_url(url, ret, encoded_len);
+    if(!encoded_len) {
+        heap_free(ret);
         return FALSE;
     }
 
-    pEntry = (const entry_header*)((LPBYTE)pHeader + pHashEntry->dwOffsetEntry);
-    if (pEntry->signature != URL_SIGNATURE)
-    {
-        cache_container_unlock_index(pContainer, pHeader);
-        FIXME("Trying to retrieve entry of unknown format %s\n",
-                debugstr_an((LPCSTR)&pEntry->signature, sizeof(DWORD)));
-        SetLastError(ERROR_FILE_NOT_FOUND);
+    *encoded_url = ret;
+    return TRUE;
+}
+
+/***********************************************************************
+ *           GetUrlCacheEntryInfoExW (WININET.@)
+ *
+ */
+BOOL WINAPI GetUrlCacheEntryInfoExW(LPCWSTR lpszUrl,
+        LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo,
+        LPDWORD lpdwCacheEntryInfoBufSize, LPWSTR lpszReserved,
+        LPDWORD lpdwReserved, LPVOID lpReserved, DWORD dwFlags)
+{
+    char *url;
+    BOOL ret;
+
+    if(lpszReserved!=NULL || lpdwReserved!=NULL || lpReserved!=NULL) {
+        ERR("Reserved value was not 0\n");
+        SetLastError(ERROR_INVALID_PARAMETER);
         return FALSE;
     }
 
-    pUrlEntry = (const entry_url *)pEntry;
-    TRACE("Found URL: %s\n", debugstr_a((LPCSTR)pUrlEntry + pUrlEntry->url_off));
-    TRACE("Header info: %s\n", debugstr_an((LPCSTR)pUrlEntry +
-                pUrlEntry->header_info_off, pUrlEntry->header_info_size));
+    /* Ignore GET_INSTALLED_ENTRY flag in unicode version of function */
+    dwFlags &= ~GET_INSTALLED_ENTRY;
 
-    if (lpdwCacheEntryInfoBufSize)
-    {
-        if (!lpCacheEntryInfo)
-            *lpdwCacheEntryInfoBufSize = 0;
-
-        error = URLCache_CopyEntry(
-                pContainer,
-                pHeader,
-                (LPINTERNET_CACHE_ENTRY_INFOA)lpCacheEntryInfo,
-                lpdwCacheEntryInfoBufSize,
-                pUrlEntry,
-                TRUE /* UNICODE */);
-        if (error != ERROR_SUCCESS)
-        {
-            cache_container_unlock_index(pContainer, pHeader);
-            SetLastError(error);
-            return FALSE;
-        }
-        if(pUrlEntry->local_name_off)
-            TRACE("Local File Name: %s\n", debugstr_a((LPCSTR)pUrlEntry + pUrlEntry->local_name_off));
-    }
+    if(!urlcache_encode_url_alloc(lpszUrl, &url))
+        return FALSE;
 
-    cache_container_unlock_index(pContainer, pHeader);
+    ret = urlcache_get_entry_info(url, lpCacheEntryInfo,
+            lpdwCacheEntryInfoBufSize, dwFlags, TRUE);
+    heap_free(url);
+    return ret;
+}
 
-    return TRUE;
+/***********************************************************************
+ *           GetUrlCacheEntryInfoW (WININET.@)
+ *
+ */
+BOOL WINAPI GetUrlCacheEntryInfoW(LPCWSTR lpszUrl,
+        LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo,
+        LPDWORD lpdwCacheEntryInfoBufferSize)
+{
+    return GetUrlCacheEntryInfoExW(lpszUrl, lpCacheEntryInfo,
+            lpdwCacheEntryInfoBufferSize, NULL, NULL, NULL, 0);
 }
 
 /***********************************************************************
  *           SetUrlCacheEntryInfoA (WININET.@)
  */
-BOOL WINAPI SetUrlCacheEntryInfoA(
-    LPCSTR lpszUrlName,
-    LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo,
-    DWORD dwFieldControl)
+BOOL WINAPI SetUrlCacheEntryInfoA(LPCSTR lpszUrlName,
+        LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo,
+        DWORD dwFieldControl)
 {
-    LPURLCACHE_HEADER pHeader;
-    struct _HASH_ENTRY * pHashEntry;
+    urlcache_header *pHeader;
+    struct hash_entry *pHashEntry;
     entry_header *pEntry;
-    URLCACHECONTAINER * pContainer;
+    cache_container *pContainer;
     DWORD error;
 
     TRACE("(%s, %p, 0x%08x)\n", debugstr_a(lpszUrlName), lpCacheEntryInfo, dwFieldControl);
 
-    error = URLCacheContainers_FindContainerA(lpszUrlName, &pContainer);
+    error = cache_containers_find(lpszUrlName, &pContainer);
     if (error != ERROR_SUCCESS)
     {
         SetLastError(error);
@@ -2035,7 +2068,7 @@ BOOL WINAPI SetUrlCacheEntryInfoA(
     if (!(pHeader = cache_container_lock_index(pContainer)))
         return FALSE;
 
-    if (!URLCache_FindHash(pHeader, lpszUrlName, &pHashEntry))
+    if (!urlcache_find_hash_entry(pHeader, lpszUrlName, &pHashEntry))
     {
         cache_container_unlock_index(pContainer, pHeader);
         WARN("entry %s not found!\n", debugstr_a(lpszUrlName));
@@ -2043,7 +2076,7 @@ BOOL WINAPI SetUrlCacheEntryInfoA(
         return FALSE;
     }
 
-    pEntry = (entry_header*)((LPBYTE)pHeader + pHashEntry->dwOffsetEntry);
+    pEntry = (entry_header*)((LPBYTE)pHeader + pHashEntry->offset);
     if (pEntry->signature != URL_SIGNATURE)
     {
         cache_container_unlock_index(pContainer, pHeader);
@@ -2052,10 +2085,7 @@ BOOL WINAPI SetUrlCacheEntryInfoA(
         return FALSE;
     }
 
-    URLCache_SetEntryInfo(
-        (entry_url *)pEntry,
-        (const INTERNET_CACHE_ENTRY_INFOW *)lpCacheEntryInfo,
-        dwFieldControl);
+    urlcache_set_entry_info((entry_url*)pEntry, lpCacheEntryInfo, dwFieldControl);
 
     cache_container_unlock_index(pContainer, pHeader);
 
@@ -2065,267 +2095,135 @@ BOOL WINAPI SetUrlCacheEntryInfoA(
 /***********************************************************************
  *           SetUrlCacheEntryInfoW (WININET.@)
  */
-BOOL WINAPI SetUrlCacheEntryInfoW(LPCWSTR lpszUrl, LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo, DWORD dwFieldControl)
+BOOL WINAPI SetUrlCacheEntryInfoW(LPCWSTR lpszUrl,
+        LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo,
+        DWORD dwFieldControl)
 {
-    LPURLCACHE_HEADER pHeader;
-    struct _HASH_ENTRY * pHashEntry;
-    entry_header *pEntry;
-    URLCACHECONTAINER * pContainer;
-    DWORD error;
-
-    TRACE("(%s, %p, 0x%08x)\n", debugstr_w(lpszUrl), lpCacheEntryInfo, dwFieldControl);
-
-    error = URLCacheContainers_FindContainerW(lpszUrl, &pContainer);
-    if (error != ERROR_SUCCESS)
-    {
-        SetLastError(error);
-        return FALSE;
-    }
-
-    error = cache_container_open_index(pContainer, MIN_BLOCK_NO);
-    if (error != ERROR_SUCCESS)
-    {
-        SetLastError(error);
-        return FALSE;
-    }
-
-    if (!(pHeader = cache_container_lock_index(pContainer)))
-        return FALSE;
-
-    if (!URLCache_FindHashW(pHeader, lpszUrl, &pHashEntry))
-    {
-        cache_container_unlock_index(pContainer, pHeader);
-        WARN("entry %s not found!\n", debugstr_w(lpszUrl));
-        SetLastError(ERROR_FILE_NOT_FOUND);
-        return FALSE;
-    }
+    char *url;
+    BOOL ret;
 
-    pEntry = (entry_header*)((LPBYTE)pHeader + pHashEntry->dwOffsetEntry);
-    if (pEntry->signature != URL_SIGNATURE)
-    {
-        cache_container_unlock_index(pContainer, pHeader);
-        FIXME("Trying to retrieve entry of unknown format %s\n", debugstr_an((LPSTR)&pEntry->signature, sizeof(DWORD)));
-        SetLastError(ERROR_FILE_NOT_FOUND);
+    if(!urlcache_encode_url_alloc(lpszUrl, &url))
         return FALSE;
-    }
-
-    URLCache_SetEntryInfo(
-        (entry_url *)pEntry,
-        lpCacheEntryInfo,
-        dwFieldControl);
-
-    cache_container_unlock_index(pContainer, pHeader);
 
-    return TRUE;
+    ret = SetUrlCacheEntryInfoA(url, (INTERNET_CACHE_ENTRY_INFOA*)lpCacheEntryInfo, dwFieldControl);
+    heap_free(url);
+    return ret;
 }
 
-/***********************************************************************
- *           RetrieveUrlCacheEntryFileA (WININET.@)
- *
- */
-BOOL WINAPI RetrieveUrlCacheEntryFileA(
-    IN LPCSTR lpszUrlName,
-    OUT LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo, 
-    IN OUT LPDWORD lpdwCacheEntryInfoBufferSize,
-    IN DWORD dwReserved
-    )
+static BOOL urlcache_entry_get_file(const char *url, void *entry_info, DWORD *size, BOOL unicode)
 {
-    LPURLCACHE_HEADER pHeader;
-    struct _HASH_ENTRY * pHashEntry;
-    entry_header *pEntry;
-    entry_url * pUrlEntry;
-    URLCACHECONTAINER * pContainer;
+    urlcache_header *header;
+    struct hash_entry *hash_entry;
+    entry_url *url_entry;
+    cache_container *container;
     DWORD error;
 
-    TRACE("(%s, %p, %p, 0x%08x)\n",
-        debugstr_a(lpszUrlName),
-        lpCacheEntryInfo,
-        lpdwCacheEntryInfoBufferSize,
-        dwReserved);
+    TRACE("(%s, %p, %p, %x)\n", debugstr_a(url), entry_info, size, unicode);
 
-    if (!lpszUrlName || !lpdwCacheEntryInfoBufferSize ||
-        (!lpCacheEntryInfo && *lpdwCacheEntryInfoBufferSize))
-    {
+    if(!url || !size || (!entry_info && *size)) {
         SetLastError(ERROR_INVALID_PARAMETER);
         return FALSE;
     }
 
-    error = URLCacheContainers_FindContainerA(lpszUrlName, &pContainer);
-    if (error != ERROR_SUCCESS)
-    {
+    error = cache_containers_find(url, &container);
+    if(error != ERROR_SUCCESS) {
         SetLastError(error);
         return FALSE;
     }
 
-    error = cache_container_open_index(pContainer, MIN_BLOCK_NO);
-    if (error != ERROR_SUCCESS)
-    {
+    error = cache_container_open_index(container, MIN_BLOCK_NO);
+    if (error != ERROR_SUCCESS) {
         SetLastError(error);
         return FALSE;
     }
 
-    if (!(pHeader = cache_container_lock_index(pContainer)))
+    if (!(header = cache_container_lock_index(container)))
         return FALSE;
 
-    if (!URLCache_FindHash(pHeader, lpszUrlName, &pHashEntry))
-    {
-        cache_container_unlock_index(pContainer, pHeader);
-        TRACE("entry %s not found!\n", lpszUrlName);
+    if (!urlcache_find_hash_entry(header, url, &hash_entry)) {
+        cache_container_unlock_index(container, header);
+        TRACE("entry %s not found!\n", url);
         SetLastError(ERROR_FILE_NOT_FOUND);
         return FALSE;
     }
 
-    pEntry = (entry_header*)((LPBYTE)pHeader + pHashEntry->dwOffsetEntry);
-    if (pEntry->signature != URL_SIGNATURE)
-    {
-        cache_container_unlock_index(pContainer, pHeader);
-        FIXME("Trying to retrieve entry of unknown format %s\n", debugstr_an((LPSTR)&pEntry->signature, sizeof(DWORD)));
+    url_entry = (entry_url*)((LPBYTE)header + hash_entry->offset);
+    if(url_entry->header.signature != URL_SIGNATURE) {
+        cache_container_unlock_index(container, header);
+        FIXME("Trying to retrieve entry of unknown format %s\n",
+                debugstr_an((LPSTR)&url_entry->header.signature, sizeof(DWORD)));
         SetLastError(ERROR_FILE_NOT_FOUND);
         return FALSE;
     }
 
-    pUrlEntry = (entry_url *)pEntry;
-    if (!pUrlEntry->local_name_off)
-    {
-        cache_container_unlock_index(pContainer, pHeader);
+    if(!url_entry->local_name_off) {
+        cache_container_unlock_index(container, header);
         SetLastError(ERROR_INVALID_DATA);
         return FALSE;
     }
 
-    TRACE("Found URL: %s\n", debugstr_a((LPCSTR)pUrlEntry + pUrlEntry->url_off));
-    TRACE("Header info: %s\n", debugstr_an((LPCSTR)pUrlEntry + pUrlEntry->header_info_off,
-                pUrlEntry->header_info_size));
+    TRACE("Found URL: %s\n", debugstr_a((LPCSTR)url_entry + url_entry->url_off));
+    TRACE("Header info: %s\n", debugstr_an((LPCSTR)url_entry + url_entry->header_info_off,
+                url_entry->header_info_size));
 
-    error = URLCache_CopyEntry(pContainer, pHeader, lpCacheEntryInfo,
-                               lpdwCacheEntryInfoBufferSize, pUrlEntry,
-                               FALSE);
-    if (error != ERROR_SUCCESS)
-    {
-        cache_container_unlock_index(pContainer, pHeader);
+    error = urlcache_copy_entry(container, header, entry_info,
+            size, url_entry, unicode);
+    if(error != ERROR_SUCCESS) {
+        cache_container_unlock_index(container, header);
         SetLastError(error);
         return FALSE;
     }
-    TRACE("Local File Name: %s\n", debugstr_a((LPCSTR)pUrlEntry + pUrlEntry->local_name_off));
+    TRACE("Local File Name: %s\n", debugstr_a((LPCSTR)url_entry + url_entry->local_name_off));
 
-    pUrlEntry->hit_rate++;
-    pUrlEntry->use_count++;
-    URLCache_HashEntrySetFlags(pHashEntry, HASHTABLE_LOCK);
-    GetSystemTimeAsFileTime(&pUrlEntry->access_time);
+    url_entry->hit_rate++;
+    url_entry->use_count++;
+    urlcache_hash_entry_set_flags(hash_entry, HASHTABLE_LOCK);
+    GetSystemTimeAsFileTime(&url_entry->access_time);
 
-    cache_container_unlock_index(pContainer, pHeader);
+    cache_container_unlock_index(container, header);
 
     return TRUE;
 }
 
 /***********************************************************************
- *           RetrieveUrlCacheEntryFileW (WININET.@)
+ *           RetrieveUrlCacheEntryFileA (WININET.@)
  *
  */
-BOOL WINAPI RetrieveUrlCacheEntryFileW(
-    IN LPCWSTR lpszUrlName,
-    OUT LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo,
-    IN OUT LPDWORD lpdwCacheEntryInfoBufferSize,
-    IN DWORD dwReserved
-    )
+BOOL WINAPI RetrieveUrlCacheEntryFileA(LPCSTR lpszUrlName,
+        LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo,
+        LPDWORD lpdwCacheEntryInfoBufferSize, DWORD dwReserved)
 {
-    LPURLCACHE_HEADER pHeader;
-    struct _HASH_ENTRY * pHashEntry;
-    entry_header *pEntry;
-    entry_url * pUrlEntry;
-    URLCACHECONTAINER * pContainer;
-    DWORD error;
-
-    TRACE("(%s, %p, %p, 0x%08x)\n",
-        debugstr_w(lpszUrlName),
-        lpCacheEntryInfo,
-        lpdwCacheEntryInfoBufferSize,
-        dwReserved);
-
-    if (!lpszUrlName || !lpdwCacheEntryInfoBufferSize ||
-        (!lpCacheEntryInfo && *lpdwCacheEntryInfoBufferSize))
-    {
-        SetLastError(ERROR_INVALID_PARAMETER);
-        return FALSE;
-    }
-
-    error = URLCacheContainers_FindContainerW(lpszUrlName, &pContainer);
-    if (error != ERROR_SUCCESS)
-    {
-        SetLastError(error);
-        return FALSE;
-    }
-
-    error = cache_container_open_index(pContainer, MIN_BLOCK_NO);
-    if (error != ERROR_SUCCESS)
-    {
-        SetLastError(error);
-        return FALSE;
-    }
-
-    if (!(pHeader = cache_container_lock_index(pContainer)))
-        return FALSE;
-
-    if (!URLCache_FindHashW(pHeader, lpszUrlName, &pHashEntry))
-    {
-        cache_container_unlock_index(pContainer, pHeader);
-        TRACE("entry %s not found!\n", debugstr_w(lpszUrlName));
-        SetLastError(ERROR_FILE_NOT_FOUND);
-        return FALSE;
-    }
-
-    pEntry = (entry_header*)((LPBYTE)pHeader + pHashEntry->dwOffsetEntry);
-    if (pEntry->signature != URL_SIGNATURE)
-    {
-        cache_container_unlock_index(pContainer, pHeader);
-        FIXME("Trying to retrieve entry of unknown format %s\n", debugstr_an((LPSTR)&pEntry->signature, sizeof(DWORD)));
-        SetLastError(ERROR_FILE_NOT_FOUND);
-        return FALSE;
-    }
-
-    pUrlEntry = (entry_url *)pEntry;
-    if (!pUrlEntry->local_name_off)
-    {
-        cache_container_unlock_index(pContainer, pHeader);
-        SetLastError(ERROR_INVALID_DATA);
-        return FALSE;
-    }
+    return urlcache_entry_get_file(lpszUrlName, lpCacheEntryInfo,
+            lpdwCacheEntryInfoBufferSize, FALSE);
+}
 
-    TRACE("Found URL: %s\n", debugstr_a((LPCSTR)pUrlEntry + pUrlEntry->url_off));
-    TRACE("Header info: %s\n", debugstr_an((LPCSTR)pUrlEntry + pUrlEntry->header_info_off,
-            pUrlEntry->header_info_size));
+/***********************************************************************
+ *           RetrieveUrlCacheEntryFileW (WININET.@)
+ *
+ */
+BOOL WINAPI RetrieveUrlCacheEntryFileW(LPCWSTR lpszUrlName,
+        LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo,
+        LPDWORD lpdwCacheEntryInfoBufferSize, DWORD dwReserved)
+{
+    char *url;
+    BOOL ret;
 
-    error = URLCache_CopyEntry(
-        pContainer,
-        pHeader,
-        (LPINTERNET_CACHE_ENTRY_INFOA)lpCacheEntryInfo,
-        lpdwCacheEntryInfoBufferSize,
-        pUrlEntry,
-        TRUE /* UNICODE */);
-    if (error != ERROR_SUCCESS)
-    {
-        cache_container_unlock_index(pContainer, pHeader);
-        SetLastError(error);
+    if(!urlcache_encode_url_alloc(lpszUrlName, &url))
         return FALSE;
-    }
-    TRACE("Local File Name: %s\n", debugstr_a((LPCSTR)pUrlEntry + pUrlEntry->local_name_off));
-
-    pUrlEntry->hit_rate++;
-    pUrlEntry->use_count++;
-    URLCache_HashEntrySetFlags(pHashEntry, HASHTABLE_LOCK);
-    GetSystemTimeAsFileTime(&pUrlEntry->access_time);
-
-    cache_container_unlock_index(pContainer, pHeader);
 
-    return TRUE;
+    ret = urlcache_entry_get_file(url, lpCacheEntryInfo,
+            lpdwCacheEntryInfoBufferSize, TRUE);
+    heap_free(url);
+    return ret;
 }
 
-static BOOL DeleteUrlCacheEntryInternal(const URLCACHECONTAINER * pContainer,
-        LPURLCACHE_HEADER pHeader, struct _HASH_ENTRY *pHashEntry)
+static BOOL urlcache_entry_delete(const cache_container *pContainer,
+        urlcache_header *pHeader, struct hash_entry *pHashEntry)
 {
     entry_header *pEntry;
     entry_url * pUrlEntry;
 
-    pEntry = (entry_header*)((LPBYTE)pHeader + pHashEntry->dwOffsetEntry);
+    pEntry = (entry_header*)((LPBYTE)pHeader + pHashEntry->offset);
     if (pEntry->signature != URL_SIGNATURE)
     {
         FIXME("Trying to delete entry of unknown format %s\n",
@@ -2335,7 +2233,7 @@ static BOOL DeleteUrlCacheEntryInternal(const URLCACHECONTAINER * pContainer,
     }
 
     pUrlEntry = (entry_url *)pEntry;
-    if(URLCache_IsLocked(pHashEntry, pUrlEntry))
+    if(urlcache_hash_entry_is_locked(pHashEntry, pUrlEntry))
     {
         TRACE("Trying to delete locked entry\n");
         pUrlEntry->cache_entry_type |= PENDING_DELETE_CACHE_ENTRY;
@@ -2343,19 +2241,19 @@ static BOOL DeleteUrlCacheEntryInternal(const URLCACHECONTAINER * pContainer,
         return FALSE;
     }
 
-    if(!URLCache_DeleteFile(pContainer, pHeader, pUrlEntry))
+    if(!urlcache_delete_file(pContainer, pHeader, pUrlEntry))
     {
-        URLCache_DeleteEntry(pHeader, pEntry);
+        urlcache_entry_free(pHeader, pEntry);
     }
     else
     {
         /* Add entry to leaked files list */
         pUrlEntry->header.signature = LEAK_SIGNATURE;
         pUrlEntry->exempt_delta = pHeader->options[CACHE_HEADER_DATA_ROOT_LEAK_OFFSET];
-        pHeader->options[CACHE_HEADER_DATA_ROOT_LEAK_OFFSET] = pHashEntry->dwOffsetEntry;
+        pHeader->options[CACHE_HEADER_DATA_ROOT_LEAK_OFFSET] = pHashEntry->offset;
     }
 
-    URLCache_DeleteEntryFromHash(pHashEntry);
+    urlcache_hash_entry_delete(pHashEntry);
     return TRUE;
 }
 
@@ -2377,49 +2275,49 @@ static void handle_full_cache(void)
 }
 
 /* Enumerates entries in cache, allows cache unlocking between calls. */
-static BOOL urlcache_next_entry(URLCACHE_HEADER *header, DWORD *hash_table_off, DWORD *hash_table_entry,
-        struct _HASH_ENTRY **hash_entry, entry_header **entry)
+static BOOL urlcache_next_entry(urlcache_header *header, DWORD *hash_table_off, DWORD *hash_table_entry,
+        struct hash_entry **hash_entry, entry_header **entry)
 {
-    HASH_CACHEFILE_ENTRY *hashtable_entry;
+    entry_hash_table *hashtable_entry;
 
     *hash_entry = NULL;
     *entry = NULL;
 
     if(!*hash_table_off) {
-        *hash_table_off = header->dwOffsetFirstHashTable;
+        *hash_table_off = header->hash_table_off;
         *hash_table_entry = 0;
 
-        hashtable_entry = URLCache_HashEntryFromOffset(header, *hash_table_off);
+        hashtable_entry = urlcache_get_hash_table(header, *hash_table_off);
     }else {
-        if(*hash_table_off >= header->dwFileSize) {
+        if(*hash_table_off >= header->size) {
             *hash_table_off = 0;
             return FALSE;
         }
 
-        hashtable_entry = URLCache_HashEntryFromOffset(header, *hash_table_off);
+        hashtable_entry = urlcache_get_hash_table(header, *hash_table_off);
     }
 
-    if(hashtable_entry->CacheFileEntry.signature != HASH_SIGNATURE) {
+    if(hashtable_entry->header.signature != HASH_SIGNATURE) {
         *hash_table_off = 0;
         return FALSE;
     }
 
     while(1) {
         if(*hash_table_entry >= HASHTABLE_SIZE) {
-            *hash_table_off = hashtable_entry->dwAddressNext;
+            *hash_table_off = hashtable_entry->next;
             if(!*hash_table_off) {
                 *hash_table_off = 0;
                 return FALSE;
             }
 
-            hashtable_entry = URLCache_HashEntryFromOffset(header, *hash_table_off);
+            hashtable_entry = urlcache_get_hash_table(header, *hash_table_off);
             *hash_table_entry = 0;
         }
 
-        if(hashtable_entry->HashTable[*hash_table_entry].dwHashKey != HASHTABLE_DEL &&
-            hashtable_entry->HashTable[*hash_table_entry].dwHashKey != HASHTABLE_FREE) {
-            *hash_entry = &hashtable_entry->HashTable[*hash_table_entry];
-            *entry = (entry_header*)((LPBYTE)header + hashtable_entry->HashTable[*hash_table_entry].dwOffsetEntry);
+        if(hashtable_entry->hash_table[*hash_table_entry].key != HASHTABLE_DEL &&
+            hashtable_entry->hash_table[*hash_table_entry].key != HASHTABLE_FREE) {
+            *hash_entry = &hashtable_entry->hash_table[*hash_table_entry];
+            *entry = (entry_header*)((LPBYTE)header + hashtable_entry->hash_table[*hash_table_entry].offset);
             (*hash_table_entry)++;
             return TRUE;
         }
@@ -2494,7 +2392,7 @@ static int dword_cmp(const void *p1, const void *p2)
  */
 BOOL WINAPI FreeUrlCacheSpaceW(LPCWSTR cache_path, DWORD size, DWORD filter)
 {
-    URLCACHECONTAINER *container;
+    cache_container *container;
     DWORD path_len, err;
 
     TRACE("(%s, %x, %x)\n", debugstr_w(cache_path), size, filter);
@@ -2513,7 +2411,7 @@ BOOL WINAPI FreeUrlCacheSpaceW(LPCWSTR cache_path, DWORD size, DWORD filter)
     }
 
     if(size==100 && !filter) {
-        LIST_FOR_EACH_ENTRY(container, &UrlContainers, URLCACHECONTAINER, entry)
+        LIST_FOR_EACH_ENTRY(container, &UrlContainers, cache_container, entry)
         {
             /* When cache_path==NULL only clean Temporary Internet Files */
             if((!path_len && container->cache_prefix[0]==0) ||
@@ -2522,14 +2420,14 @@ BOOL WINAPI FreeUrlCacheSpaceW(LPCWSTR cache_path, DWORD size, DWORD filter)
             {
                 BOOL ret_del;
 
-                WaitForSingleObject(container->hMutex, INFINITE);
+                WaitForSingleObject(container->mutex, INFINITE);
 
                 /* unlock, delete, recreate and lock cache */
                 cache_container_close_index(container);
-                ret_del = URLCache_DeleteCacheDirectory(container->path);
+                ret_del = cache_container_delete_dir(container->path);
                 err = cache_container_open_index(container, MIN_BLOCK_NO);
 
-                ReleaseMutex(container->hMutex);
+                ReleaseMutex(container->mutex);
                 if(!ret_del || (err != ERROR_SUCCESS))
                     return FALSE;
             }
@@ -2538,10 +2436,10 @@ BOOL WINAPI FreeUrlCacheSpaceW(LPCWSTR cache_path, DWORD size, DWORD filter)
         return TRUE;
     }
 
-    LIST_FOR_EACH_ENTRY(container, &UrlContainers, URLCACHECONTAINER, entry)
+    LIST_FOR_EACH_ENTRY(container, &UrlContainers, cache_container, entry)
     {
-        URLCACHE_HEADER *header;
-        struct _HASH_ENTRY *hash_entry;
+        urlcache_header *header;
+        struct hash_entry *hash_entry;
         entry_header *entry;
         entry_url *url_entry;
         ULONGLONG desired_size, cur_size;
@@ -2564,8 +2462,8 @@ BOOL WINAPI FreeUrlCacheSpaceW(LPCWSTR cache_path, DWORD size, DWORD filter)
 
         urlcache_clean_leaked_entries(container, header);
 
-        desired_size = header->CacheLimit.QuadPart*(100-size)/100;
-        cur_size = header->CacheUsage.QuadPart+header->ExemptUsage.QuadPart;
+        desired_size = header->cache_limit.QuadPart*(100-size)/100;
+        cur_size = header->cache_usage.QuadPart+header->exempt_usage.QuadPart;
         if(cur_size <= desired_size)
             delete_factor = 0;
         else
@@ -2619,9 +2517,9 @@ BOOL WINAPI FreeUrlCacheSpaceW(LPCWSTR cache_path, DWORD size, DWORD filter)
 
             if(urlcache_rate_entry(url_entry, &cur_time) <= delete_factor) {
                 TRACE("deleting file: %s\n", debugstr_a((char*)url_entry+url_entry->local_name_off));
-                DeleteUrlCacheEntryInternal(container, header, hash_entry);
+                urlcache_entry_delete(container, header, hash_entry);
 
-                if(header->CacheUsage.QuadPart+header->ExemptUsage.QuadPart <= desired_size)
+                if(header->cache_usage.QuadPart+header->exempt_usage.QuadPart <= desired_size)
                     break;
 
                 /* Allow other threads to use cache while cleaning */
@@ -2636,8 +2534,8 @@ BOOL WINAPI FreeUrlCacheSpaceW(LPCWSTR cache_path, DWORD size, DWORD filter)
         }
 
         TRACE("cache size after cleaning 0x%s/0x%s\n",
-                wine_dbgstr_longlong(header->CacheUsage.QuadPart+header->ExemptUsage.QuadPart),
-                wine_dbgstr_longlong(header->CacheLimit.QuadPart));
+                wine_dbgstr_longlong(header->cache_usage.QuadPart+header->exempt_usage.QuadPart),
+                wine_dbgstr_longlong(header->cache_limit.QuadPart));
         cache_container_unlock_index(container, header);
     }
 
@@ -2663,16 +2561,13 @@ BOOL WINAPI FreeUrlCacheSpaceA(LPCSTR lpszCachePath, DWORD dwSize, DWORD dwFilte
  *           UnlockUrlCacheEntryFileA (WININET.@)
  *
  */
-BOOL WINAPI UnlockUrlCacheEntryFileA(
-    IN LPCSTR lpszUrlName, 
-    IN DWORD dwReserved
-    )
+BOOL WINAPI UnlockUrlCacheEntryFileA(LPCSTR lpszUrlName, DWORD dwReserved)
 {
-    LPURLCACHE_HEADER pHeader;
-    struct _HASH_ENTRY * pHashEntry;
+    urlcache_header *pHeader;
+    struct hash_entry *pHashEntry;
     entry_header *pEntry;
     entry_url * pUrlEntry;
-    URLCACHECONTAINER * pContainer;
+    cache_container *pContainer;
     DWORD error;
 
     TRACE("(%s, 0x%08x)\n", debugstr_a(lpszUrlName), dwReserved);
@@ -2684,7 +2579,7 @@ BOOL WINAPI UnlockUrlCacheEntryFileA(
         return FALSE;
     }
 
-    error = URLCacheContainers_FindContainerA(lpszUrlName, &pContainer);
+    error = cache_containers_find(lpszUrlName, &pContainer);
     if (error != ERROR_SUCCESS)
     {
        SetLastError(error);
@@ -2701,7 +2596,7 @@ BOOL WINAPI UnlockUrlCacheEntryFileA(
     if (!(pHeader = cache_container_lock_index(pContainer)))
         return FALSE;
 
-    if (!URLCache_FindHash(pHeader, lpszUrlName, &pHashEntry))
+    if (!urlcache_find_hash_entry(pHeader, lpszUrlName, &pHashEntry))
     {
         cache_container_unlock_index(pContainer, pHeader);
         TRACE("entry %s not found!\n", lpszUrlName);
@@ -2709,7 +2604,7 @@ BOOL WINAPI UnlockUrlCacheEntryFileA(
         return FALSE;
     }
 
-    pEntry = (entry_header*)((LPBYTE)pHeader + pHashEntry->dwOffsetEntry);
+    pEntry = (entry_header*)((LPBYTE)pHeader + pHashEntry->offset);
     if (pEntry->signature != URL_SIGNATURE)
     {
         cache_container_unlock_index(pContainer, pHeader);
@@ -2728,9 +2623,9 @@ BOOL WINAPI UnlockUrlCacheEntryFileA(
     pUrlEntry->use_count--;
     if (!pUrlEntry->use_count)
     {
-        URLCache_HashEntrySetFlags(pHashEntry, HASHTABLE_URL);
+        urlcache_hash_entry_set_flags(pHashEntry, HASHTABLE_URL);
         if (pUrlEntry->cache_entry_type & PENDING_DELETE_CACHE_ENTRY)
-            DeleteUrlCacheEntryInternal(pContainer, pHeader, pHashEntry);
+            urlcache_entry_delete(pContainer, pHeader, pHashEntry);
     }
 
     cache_container_unlock_index(pContainer, pHeader);
@@ -2742,324 +2637,162 @@ BOOL WINAPI UnlockUrlCacheEntryFileA(
  *           UnlockUrlCacheEntryFileW (WININET.@)
  *
  */
-BOOL WINAPI UnlockUrlCacheEntryFileW( LPCWSTR lpszUrlName, DWORD dwReserved )
+BOOL WINAPI UnlockUrlCacheEntryFileW(LPCWSTR lpszUrlName, DWORD dwReserved)
 {
-    LPURLCACHE_HEADER pHeader;
-    struct _HASH_ENTRY * pHashEntry;
-    entry_header *pEntry;
-    entry_url * pUrlEntry;
-    URLCACHECONTAINER * pContainer;
-    DWORD error;
-
-    TRACE("(%s, 0x%08x)\n", debugstr_w(lpszUrlName), dwReserved);
-
-    if (dwReserved)
-    {
-        ERR("dwReserved != 0\n");
-        SetLastError(ERROR_INVALID_PARAMETER);
-        return FALSE;
-    }
-
-    error = URLCacheContainers_FindContainerW(lpszUrlName, &pContainer);
-    if (error != ERROR_SUCCESS)
-    {
-        SetLastError(error);
-        return FALSE;
-    }
-
-    error = cache_container_open_index(pContainer, MIN_BLOCK_NO);
-    if (error != ERROR_SUCCESS)
-    {
-        SetLastError(error);
-        return FALSE;
-    }
-
-    if (!(pHeader = cache_container_lock_index(pContainer)))
-        return FALSE;
-
-    if (!URLCache_FindHashW(pHeader, lpszUrlName, &pHashEntry))
-    {
-        cache_container_unlock_index(pContainer, pHeader);
-        TRACE("entry %s not found!\n", debugstr_w(lpszUrlName));
-        SetLastError(ERROR_FILE_NOT_FOUND);
-        return FALSE;
-    }
-
-    pEntry = (entry_header*)((LPBYTE)pHeader + pHashEntry->dwOffsetEntry);
-    if (pEntry->signature != URL_SIGNATURE)
-    {
-        cache_container_unlock_index(pContainer, pHeader);
-        FIXME("Trying to retrieve entry of unknown format %s\n", debugstr_an((LPSTR)&pEntry->signature, sizeof(DWORD)));
-        SetLastError(ERROR_FILE_NOT_FOUND);
-        return FALSE;
-    }
-
-    pUrlEntry = (entry_url *)pEntry;
+    char *url;
+    BOOL ret;
 
-    if (pUrlEntry->use_count == 0)
-    {
-        cache_container_unlock_index(pContainer, pHeader);
+    if(!urlcache_encode_url_alloc(lpszUrlName, &url))
         return FALSE;
-    }
-    pUrlEntry->use_count--;
-    if (!pUrlEntry->use_count)
-        URLCache_HashEntrySetFlags(pHashEntry, HASHTABLE_URL);
 
-    cache_container_unlock_index(pContainer, pHeader);
-
-    return TRUE;
+    ret = UnlockUrlCacheEntryFileA(url, dwReserved);
+    heap_free(url);
+    return ret;
 }
 
-/***********************************************************************
- *           CreateUrlCacheEntryA (WININET.@)
- *
- */
-BOOL WINAPI CreateUrlCacheEntryA(
-    IN LPCSTR lpszUrlName,
-    IN DWORD dwExpectedFileSize,
-    IN LPCSTR lpszFileExtension,
-    OUT LPSTR lpszFileName,
-    IN DWORD dwReserved
-)
-{
-    WCHAR *url_name;
-    WCHAR *file_extension = NULL;
-    WCHAR file_name[MAX_PATH];
-    BOOL bSuccess = FALSE;
-    DWORD dwError = 0;
-
-    TRACE("(%s %d %s %p %d)\n", debugstr_a(lpszUrlName), dwExpectedFileSize,
-            debugstr_a(lpszFileExtension), lpszFileName, dwReserved);
-
-    if (lpszUrlName && (url_name = heap_strdupAtoW(lpszUrlName)))
-    {
-        if (!lpszFileExtension || (file_extension = heap_strdupAtoW(lpszFileExtension)))
-        {
-            if (CreateUrlCacheEntryW(url_name, dwExpectedFileSize, file_extension, file_name, dwReserved))
-            {
-                if (WideCharToMultiByte(CP_ACP, 0, file_name, -1, lpszFileName, MAX_PATH, NULL, NULL) < MAX_PATH)
-                {
-                    bSuccess = TRUE;
-                }
-                else
-                {
-                    dwError = GetLastError();
-                }
-            }
-            else
-            {
-                dwError = GetLastError();
-            }
-            heap_free(file_extension);
-        }
-        else
-        {
-            dwError = GetLastError();
-        }
-        heap_free(url_name);
-        if (!bSuccess) SetLastError(dwError);
-    }
-    return bSuccess;
-}
-/***********************************************************************
- *           CreateUrlCacheEntryW (WININET.@)
- *
- */
-BOOL WINAPI CreateUrlCacheEntryW(
-    IN LPCWSTR lpszUrlName,
-    IN DWORD dwExpectedFileSize,
-    IN LPCWSTR lpszFileExtension,
-    OUT LPWSTR lpszFileName,
-    IN DWORD dwReserved
-)
+static BOOL urlcache_entry_create(const char *url, const char *ext, WCHAR *full_path)
 {
-    URLCACHECONTAINER * pContainer;
-    LPURLCACHE_HEADER pHeader;
-    CHAR szFile[MAX_PATH];
-    WCHAR szExtension[MAX_PATH];
-    LPCWSTR lpszUrlPart;
-    LPCWSTR lpszUrlEnd;
-    LPCWSTR lpszFileNameExtension;
-    LPWSTR lpszFileNameNoPath;
-    int i;
-    int countnoextension;
-    BYTE CacheDir;
-    LONG lBufferSize;
-    BOOL bFound = FALSE;
+    cache_container *container;
+    urlcache_header *header;
+    char file_name[MAX_PATH];
+    WCHAR extW[MAX_PATH];
+    BYTE cache_dir;
+    LONG full_path_len;
     BOOL generate_name = FALSE;
-    int count;
     DWORD error;
-    HANDLE hFile;
+    HANDLE file;
     FILETIME ft;
+    URL_COMPONENTSA uc;
+    int i;
 
-    static const WCHAR szWWW[] = {'w','w','w',0};
-
-    TRACE("(%s, 0x%08x, %s, %p, 0x%08x)\n",
-        debugstr_w(lpszUrlName),
-        dwExpectedFileSize,
-        debugstr_w(lpszFileExtension),
-        lpszFileName,
-        dwReserved);
+    TRACE("(%s, %s, %p)\n", debugstr_a(url), debugstr_a(ext), full_path);
 
-    if (dwReserved)
-        FIXME("dwReserved 0x%08x\n", dwReserved);
+    memset(&uc, 0, sizeof(uc));
+    uc.dwStructSize = sizeof(uc);
+    uc.dwUrlPathLength = 1;
+    uc.dwExtraInfoLength = 1;
+    if(!InternetCrackUrlA(url, 0, 0, &uc))
+        uc.dwUrlPathLength = 0;
 
-    lpszUrlEnd = lpszUrlName + strlenW(lpszUrlName);
-    
-    if (((lpszUrlEnd - lpszUrlName) > 1) && (*(lpszUrlEnd - 1) == '/' || *(lpszUrlEnd - 1) == '\\'))
-        lpszUrlEnd--;
-
-    lpszUrlPart = memchrW(lpszUrlName, '?', lpszUrlEnd - lpszUrlName);
-    if (!lpszUrlPart)
-        lpszUrlPart = memchrW(lpszUrlName, '#', lpszUrlEnd - lpszUrlName);
-    if (lpszUrlPart)
-        lpszUrlEnd = lpszUrlPart;
-
-    for (lpszUrlPart = lpszUrlEnd; 
-        (lpszUrlPart >= lpszUrlName); 
-        lpszUrlPart--)
-    {
-        if ((*lpszUrlPart == '/' || *lpszUrlPart == '\\') && ((lpszUrlEnd - lpszUrlPart) > 1))
-        {
-            bFound = TRUE;
-            lpszUrlPart++;
-            break;
+    if(!uc.dwUrlPathLength) {
+        file_name[0] = 0;
+    }else {
+        char *p, *e;
+
+        p = e = uc.lpszUrlPath+uc.dwUrlPathLength;
+        while(p>uc.lpszUrlPath && *(p-1)!='/' && *(p-1)!='\\' && *(p-1)!='.')
+            p--;
+        if(p>uc.lpszUrlPath && *(p-1)=='.') {
+            e = p-1;
+            while(p>uc.lpszUrlPath && *(p-1)!='/' && *(p-1)!='\\')
+                p--;
         }
-    }
-    if(!bFound)
-        lpszUrlPart++;
 
-    if (!lstrcmpW(lpszUrlPart, szWWW))
-    {
-        lpszUrlPart += lstrlenW(szWWW);
-    }
-
-    count = lpszUrlEnd - lpszUrlPart;
-
-    if (bFound && (count < MAX_PATH))
-    {
-       int len = WideCharToMultiByte(CP_ACP, 0, lpszUrlPart, count, szFile, sizeof(szFile) - 1, NULL, NULL);
-       if (!len)
-           return FALSE;
-        szFile[len] = '\0';
-        while(len && szFile[--len] == '/') szFile[len] = '\0';
+        memcpy(file_name, p, e-p);
+        file_name[e-p] = 0;
 
-        /* FIXME: get rid of illegal characters like \, / and : */
-        TRACE("File name: %s\n", debugstr_a(szFile));
+        for(p=file_name; *p; p++) {
+            switch(*p) {
+            case '<': case '>':
+            case ':': case '"':
+            case '|': case '?':
+            case '*':
+                *p = '_'; break;
+            default: break;
+            }
+        }
     }
-    else
-    {
+
+    if(!file_name[0])
         generate_name = TRUE;
-        szFile[0] = 0;
-    }
 
-    error = URLCacheContainers_FindContainerW(lpszUrlName, &pContainer);
-    if (error != ERROR_SUCCESS)
-    {
+    error = cache_containers_find(url, &container);
+    if(error != ERROR_SUCCESS) {
         SetLastError(error);
         return FALSE;
     }
 
-    error = cache_container_open_index(pContainer, MIN_BLOCK_NO);
-    if (error != ERROR_SUCCESS)
-    {
+    error = cache_container_open_index(container, MIN_BLOCK_NO);
+    if(error != ERROR_SUCCESS) {
         SetLastError(error);
         return FALSE;
     }
 
-    if (!(pHeader = cache_container_lock_index(pContainer)))
+    if(!(header = cache_container_lock_index(container)))
         return FALSE;
 
-    if(pHeader->DirectoryCount)
-        CacheDir = (BYTE)(rand() % pHeader->DirectoryCount);
+    if(header->dirs_no)
+        cache_dir = (BYTE)(rand() % header->dirs_no);
     else
-        CacheDir = CACHE_CONTAINER_NO_SUBDIR;
+        cache_dir = CACHE_CONTAINER_NO_SUBDIR;
 
-    lBufferSize = MAX_PATH * sizeof(WCHAR);
-    if (!URLCache_LocalFileNameToPathW(pContainer, pHeader, szFile, CacheDir, lpszFileName, &lBufferSize))
-    {
+    full_path_len = MAX_PATH * sizeof(WCHAR);
+    if(!urlcache_create_file_pathW(container, header, file_name, cache_dir, full_path, &full_path_len)) {
         WARN("Failed to get full path for filename %s, needed %u bytes.\n",
-                debugstr_a(szFile), lBufferSize);
-        cache_container_unlock_index(pContainer, pHeader);
+                debugstr_a(file_name), full_path_len);
+        cache_container_unlock_index(container, header);
         return FALSE;
     }
+    full_path_len = full_path_len/sizeof(WCHAR) - 1;
 
-    cache_container_unlock_index(pContainer, pHeader);
-
-    for (lpszFileNameNoPath = lpszFileName + lBufferSize / sizeof(WCHAR) - 2;
-        lpszFileNameNoPath >= lpszFileName; 
-        --lpszFileNameNoPath)
-    {
-        if (*lpszFileNameNoPath == '/' || *lpszFileNameNoPath == '\\')
-            break;
-    }
-
-    countnoextension = lstrlenW(lpszFileNameNoPath);
-    lpszFileNameExtension = PathFindExtensionW(lpszFileNameNoPath);
-    if (lpszFileNameExtension)
-        countnoextension -= lstrlenW(lpszFileNameExtension);
-    *szExtension = '\0';
-
-    if (lpszFileExtension)
-    {
-        szExtension[0] = '.';
-        lstrcpyW(szExtension+1, lpszFileExtension);
-    }
+    cache_container_unlock_index(container, header);
 
-    for (i = 0; i<255 && !generate_name; i++)
-    {
-        static const WCHAR szFormat[] = {'[','%','u',']','%','s',0};
+    if(ext) {
         WCHAR *p;
 
-        wsprintfW(lpszFileNameNoPath + countnoextension, szFormat, i, szExtension);
-        for (p = lpszFileNameNoPath + 1; *p; p++)
-        {
-            switch (*p)
-            {
+        extW[0] = '.';
+        MultiByteToWideChar(CP_ACP, 0, ext, -1, extW+1, MAX_PATH-1);
+
+        for(p=extW; *p; p++) {
+            switch(*p) {
             case '<': case '>':
             case ':': case '"':
-            case '/': case '\\':
             case '|': case '?':
             case '*':
                 *p = '_'; break;
             default: break;
             }
         }
-        if (p[-1] == ' ' || p[-1] == '.') p[-1] = '_';
+        if(p[-1]==' ' || p[-1]=='.')
+            p[-1] = '_';
+    }else {
+        extW[0] = '\0';
+    }
 
-        TRACE("Trying: %s\n", debugstr_w(lpszFileName));
-        hFile = CreateFileW(lpszFileName, GENERIC_READ, 0, NULL, CREATE_NEW, 0, NULL);
-        if (hFile != INVALID_HANDLE_VALUE)
-        {
-            CloseHandle(hFile);
+    for(i=0; i<255 && !generate_name; i++) {
+        static const WCHAR format[] = {'[','%','u',']','%','s',0};
+
+        wsprintfW(full_path+full_path_len, format, i, extW);
+
+        TRACE("Trying: %s\n", debugstr_w(full_path));
+        file = CreateFileW(full_path, GENERIC_READ, 0, NULL, CREATE_NEW, 0, NULL);
+        if(file != INVALID_HANDLE_VALUE) {
+            CloseHandle(file);
             return TRUE;
         }
     }
 
     /* Try to generate random name */
     GetSystemTimeAsFileTime(&ft);
-    strcpyW(lpszFileNameNoPath+countnoextension+8, szExtension);
+    strcpyW(full_path+full_path_len+8, extW);
 
-    for(i=0; i<255; i++)
-    {
+    for(i=0; i<255; i++) {
         int j;
         ULONGLONG n = ft.dwHighDateTime;
         n <<= 32;
         n += ft.dwLowDateTime;
         n ^= (ULONGLONG)i<<48;
 
-        for(j=0; j<8; j++)
-        {
+        for(j=0; j<8; j++) {
             int r = (n % 36);
             n /= 37;
-            lpszFileNameNoPath[countnoextension+j] = (r < 10 ? '0' + r : 'A' + r - 10);
+            full_path[full_path_len+j] = (r < 10 ? '0' + r : 'A' + r - 10);
         }
 
-        TRACE("Trying: %s\n", debugstr_w(lpszFileName));
-        hFile = CreateFileW(lpszFileName, GENERIC_READ, 0, NULL, CREATE_NEW, 0, NULL);
-        if (hFile != INVALID_HANDLE_VALUE)
-        {
-            CloseHandle(hFile);
+        TRACE("Trying: %s\n", debugstr_w(full_path));
+        file = CreateFileW(full_path, GENERIC_READ, 0, NULL, CREATE_NEW, 0, NULL);
+        if(file != INVALID_HANDLE_VALUE) {
+            CloseHandle(file);
             return TRUE;
         }
     }
@@ -3069,403 +2802,340 @@ BOOL WINAPI CreateUrlCacheEntryW(
 }
 
 /***********************************************************************
- *           CommitUrlCacheEntryInternal (Compensates for an MS bug)
+ *           CreateUrlCacheEntryA (WININET.@)
  *
- *   The bug we are compensating for is that some drongo at Microsoft
- *   used lpHeaderInfo to pass binary data to CommitUrlCacheEntryA.
- *   As a consequence, CommitUrlCacheEntryA has been effectively
- *   redefined as LPBYTE rather than LPCSTR. But CommitUrlCacheEntryW
- *   is still defined as LPCWSTR. The result (other than madness) is
- *   that we always need to store lpHeaderInfo in CP_ACP rather than
- *   in UTF16, and we need to avoid converting lpHeaderInfo in
- *   CommitUrlCacheEntryA to UTF16 and then back to CP_ACP, since the
- *   result will lose data for arbitrary binary data.
+ */
+BOOL WINAPI CreateUrlCacheEntryA(LPCSTR lpszUrlName, DWORD dwExpectedFileSize,
+        LPCSTR lpszFileExtension, LPSTR lpszFileName, DWORD dwReserved)
+{
+    WCHAR file_name[MAX_PATH];
+
+    if(dwReserved)
+        FIXME("dwReserved 0x%08x\n", dwReserved);
+
+    if(!urlcache_entry_create(lpszUrlName, lpszFileExtension, file_name))
+        return FALSE;
+
+    if(!WideCharToMultiByte(CP_ACP, 0, file_name, -1, lpszFileName, MAX_PATH, NULL, NULL))
+        return FALSE;
+    return TRUE;
+}
+/***********************************************************************
+ *           CreateUrlCacheEntryW (WININET.@)
  *
  */
-static BOOL CommitUrlCacheEntryInternal(
-    IN LPCWSTR lpszUrlName,
-    IN LPCWSTR lpszLocalFileName,
-    IN FILETIME ExpireTime,
-    IN FILETIME LastModifiedTime,
-    IN DWORD CacheEntryType,
-    IN LPBYTE lpHeaderInfo,
-    IN DWORD dwHeaderSize,
-    IN LPCWSTR lpszFileExtension,
-    IN LPCWSTR lpszOriginalUrl
-    )
+BOOL WINAPI CreateUrlCacheEntryW(LPCWSTR lpszUrlName, DWORD dwExpectedFileSize,
+        LPCWSTR lpszFileExtension, LPWSTR lpszFileName, DWORD dwReserved)
 {
-    URLCACHECONTAINER * pContainer;
-    LPURLCACHE_HEADER pHeader;
-    struct _HASH_ENTRY * pHashEntry;
-    entry_header *pEntry;
-    entry_url * pUrlEntry;
+    char *url, *ext = NULL;
+    BOOL ret;
+
+    if(dwReserved)
+        FIXME("dwReserved 0x%08x\n", dwReserved);
+
+    if(lpszFileExtension) {
+        ext = heap_strdupWtoUTF8(lpszFileExtension);
+        if(!ext)
+            return FALSE;
+    }
+
+    if(!urlcache_encode_url_alloc(lpszUrlName, &url)) {
+        heap_free(ext);
+        return FALSE;
+    }
+
+    ret = urlcache_entry_create(url, ext, lpszFileName);
+    heap_free(ext);
+    heap_free(url);
+    return ret;
+}
+
+static BOOL urlcache_entry_commit(const char *url, const WCHAR *file_name,
+    FILETIME expire_time, FILETIME modify_time, DWORD entry_type,
+    BYTE *header_info, DWORD header_size, const char *file_ext,
+    const char *original_url)
+{
+    cache_container *container;
+    urlcache_header *header;
+    struct hash_entry *hash_entry;
+    entry_header *entry;
+    entry_url *url_entry;
     DWORD url_entry_offset;
-    DWORD dwBytesNeeded = DWORD_ALIGN(sizeof(*pUrlEntry));
-    DWORD dwOffsetLocalFileName = 0;
-    DWORD dwOffsetHeader = 0;
-    DWORD dwOffsetFileExtension = 0;
+    DWORD size = DWORD_ALIGN(sizeof(*url_entry));
+    DWORD file_name_off = 0;
+    DWORD header_info_off = 0;
+    DWORD file_ext_off = 0;
     WIN32_FILE_ATTRIBUTE_DATA file_attr;
     LARGE_INTEGER file_size;
-    BYTE cDirectory;
-    char achFile[MAX_PATH];
-    LPSTR lpszUrlNameA = NULL;
-    LPSTR lpszFileExtensionA = NULL;
-    char *pchLocalFileName = 0;
+    BYTE dir_id;
+    char file_name_no_container[MAX_PATH];
+    char *local_file_name = 0;
     DWORD hit_rate = 0;
     DWORD exempt_delta = 0;
     DWORD error;
 
-    TRACE("(%s, %s, ..., ..., %x, %p, %d, %s, %s)\n",
-        debugstr_w(lpszUrlName),
-        debugstr_w(lpszLocalFileName),
-        CacheEntryType,
-        lpHeaderInfo,
-        dwHeaderSize,
-        debugstr_w(lpszFileExtension),
-        debugstr_w(lpszOriginalUrl));
+    TRACE("(%s, %s, ..., ..., %x, %p, %d, %s, %s)\n", debugstr_a(url), debugstr_w(file_name),
+            entry_type, header_info, header_size, debugstr_a(file_ext), debugstr_a(original_url));
 
-    if (CacheEntryType & STICKY_CACHE_ENTRY && !lpszLocalFileName)
-    {
+    if(entry_type & STICKY_CACHE_ENTRY && !file_name) {
         SetLastError(ERROR_INVALID_PARAMETER);
         return FALSE;
     }
-    if (lpszOriginalUrl)
-        WARN(": lpszOriginalUrl ignored\n");
+    if(original_url)
+        WARN(": original_url ignored\n");
 
     memset(&file_attr, 0, sizeof(file_attr));
-    if (lpszLocalFileName)
-    {
-        if(!GetFileAttributesExW(lpszLocalFileName, GetFileExInfoStandard, &file_attr))
+    if(file_name) {
+        if(!GetFileAttributesExW(file_name, GetFileExInfoStandard, &file_attr))
             return FALSE;
     }
     file_size.u.LowPart = file_attr.nFileSizeLow;
     file_size.u.HighPart = file_attr.nFileSizeHigh;
 
-    error = URLCacheContainers_FindContainerW(lpszUrlName, &pContainer);
-    if (error != ERROR_SUCCESS)
-    {
+    error = cache_containers_find(url, &container);
+    if(error != ERROR_SUCCESS) {
         SetLastError(error);
         return FALSE;
     }
 
-    error = cache_container_open_index(pContainer, MIN_BLOCK_NO);
-    if (error != ERROR_SUCCESS)
-    {
+    error = cache_container_open_index(container, MIN_BLOCK_NO);
+    if(error != ERROR_SUCCESS) {
         SetLastError(error);
         return FALSE;
     }
 
-    if (!(pHeader = cache_container_lock_index(pContainer)))
+    if(!(header = cache_container_lock_index(container)))
         return FALSE;
 
-    lpszUrlNameA = heap_strdupWtoA(lpszUrlName);
-    if (!lpszUrlNameA)
-    {
-        error = GetLastError();
-        goto cleanup;
-    }
-
-    if (lpszFileExtension && !(lpszFileExtensionA = heap_strdupWtoA(lpszFileExtension)))
-    {
-        error = GetLastError();
-        goto cleanup;
-    }
+    if(urlcache_find_hash_entry(header, url, &hash_entry)) {
+        entry_url *url_entry = (entry_url*)((LPBYTE)header + hash_entry->offset);
 
-    if (URLCache_FindHash(pHeader, lpszUrlNameA, &pHashEntry))
-    {
-        entry_url *pUrlEntry = (entry_url*)((LPBYTE)pHeader + pHashEntry->dwOffsetEntry);
-        if (URLCache_IsLocked(pHashEntry, pUrlEntry))
-        {
+        if(urlcache_hash_entry_is_locked(hash_entry, url_entry)) {
             TRACE("Trying to overwrite locked entry\n");
-            error = ERROR_SHARING_VIOLATION;
-            goto cleanup;
+            cache_container_unlock_index(container, header);
+            SetLastError(ERROR_SHARING_VIOLATION);
+            return FALSE;
         }
 
-        hit_rate = pUrlEntry->hit_rate;
-        exempt_delta = pUrlEntry->exempt_delta;
-        DeleteUrlCacheEntryInternal(pContainer, pHeader, pHashEntry);
+        hit_rate = url_entry->hit_rate;
+        exempt_delta = url_entry->exempt_delta;
+        urlcache_entry_delete(container, header, hash_entry);
     }
 
-    if (pHeader->DirectoryCount)
-        cDirectory = 0;
+    if(header->dirs_no)
+        dir_id = 0;
     else
-        cDirectory = CACHE_CONTAINER_NO_SUBDIR;
+        dir_id = CACHE_CONTAINER_NO_SUBDIR;
 
-    if (lpszLocalFileName)
-    {
+    if(file_name) {
         BOOL bFound = FALSE;
 
-        if (strncmpW(lpszLocalFileName, pContainer->path, lstrlenW(pContainer->path)))
-        {
-            ERR("path %s must begin with cache content path %s\n", debugstr_w(lpszLocalFileName), debugstr_w(pContainer->path));
-            error = ERROR_INVALID_PARAMETER;
-            goto cleanup;
+        if(strncmpW(file_name, container->path, lstrlenW(container->path))) {
+            ERR("path %s must begin with cache content path %s\n", debugstr_w(file_name), debugstr_w(container->path));
+            cache_container_unlock_index(container, header);
+            SetLastError(ERROR_INVALID_PARAMETER);
+            return FALSE;
         }
 
         /* skip container path prefix */
-        lpszLocalFileName += lstrlenW(pContainer->path);
+        file_name += lstrlenW(container->path);
 
-        WideCharToMultiByte(CP_ACP, 0, lpszLocalFileName, -1, achFile, MAX_PATH, NULL, NULL);
-       pchLocalFileName = achFile;
+        WideCharToMultiByte(CP_ACP, 0, file_name, -1, file_name_no_container, MAX_PATH, NULL, NULL);
+       local_file_name = file_name_no_container;
 
-        if(pHeader->DirectoryCount)
-        {
-            for (cDirectory = 0; cDirectory < pHeader->DirectoryCount; cDirectory++)
-            {
-                if (!strncmp(pHeader->directory_data[cDirectory].filename, pchLocalFileName, DIR_LENGTH))
-                {
+        if(header->dirs_no) {
+            for(dir_id = 0; dir_id < header->dirs_no; dir_id++) {
+                if(!strncmp(header->directory_data[dir_id].name, local_file_name, DIR_LENGTH)) {
                     bFound = TRUE;
                     break;
                 }
             }
 
-            if (!bFound)
-            {
-                ERR("cache directory not found in path %s\n", debugstr_w(lpszLocalFileName));
-                error = ERROR_INVALID_PARAMETER;
-                goto cleanup;
+            if(!bFound) {
+                ERR("cache directory not found in path %s\n", debugstr_w(file_name));
+                cache_container_unlock_index(container, header);
+                SetLastError(ERROR_INVALID_PARAMETER);
+                return FALSE;
             }
 
-            lpszLocalFileName += DIR_LENGTH + 1;
-            pchLocalFileName += DIR_LENGTH + 1;
+            file_name += DIR_LENGTH + 1;
+            local_file_name += DIR_LENGTH + 1;
         }
     }
 
-    dwBytesNeeded = DWORD_ALIGN(dwBytesNeeded + strlen(lpszUrlNameA) + 1);
-    if (lpszLocalFileName)
-    {
-        dwOffsetLocalFileName = dwBytesNeeded;
-        dwBytesNeeded = DWORD_ALIGN(dwBytesNeeded + strlen(pchLocalFileName) + 1);
+    size = DWORD_ALIGN(size + strlen(url) + 1);
+    if(file_name) {
+        file_name_off = size;
+        size = DWORD_ALIGN(size + strlen(local_file_name) + 1);
     }
-    if (lpHeaderInfo)
-    {
-        dwOffsetHeader = dwBytesNeeded;
-        dwBytesNeeded = DWORD_ALIGN(dwBytesNeeded + dwHeaderSize);
+    if(header_info && header_size) {
+        header_info_off = size;
+        size = DWORD_ALIGN(size + header_size);
     }
-    if (lpszFileExtensionA)
-    {
-        dwOffsetFileExtension = dwBytesNeeded;
-        dwBytesNeeded = DWORD_ALIGN(dwBytesNeeded + strlen(lpszFileExtensionA) + 1);
+    if(file_ext && (file_ext_off = strlen(file_ext))) {
+        DWORD len = file_ext_off;
+
+        file_ext_off = size;
+        size = DWORD_ALIGN(size + len + 1);
     }
 
     /* round up to next block */
-    if (dwBytesNeeded % BLOCKSIZE)
-    {
-        dwBytesNeeded -= dwBytesNeeded % BLOCKSIZE;
-        dwBytesNeeded += BLOCKSIZE;
+    if(size % BLOCKSIZE) {
+        size -= size % BLOCKSIZE;
+        size += BLOCKSIZE;
     }
 
-    error = URLCache_FindFirstFreeEntry(pHeader, dwBytesNeeded / BLOCKSIZE, &pEntry);
-    while (error == ERROR_HANDLE_DISK_FULL)
-    {
-        error = cache_container_clean_index(pContainer, &pHeader);
-        if (error == ERROR_SUCCESS)
-            error = URLCache_FindFirstFreeEntry(pHeader, dwBytesNeeded / BLOCKSIZE, &pEntry);
+    error = urlcache_entry_alloc(header, size / BLOCKSIZE, &entry);
+    while(error == ERROR_HANDLE_DISK_FULL) {
+        error = cache_container_clean_index(container, &header);
+        if(error == ERROR_SUCCESS)
+            error = urlcache_entry_alloc(header, size / BLOCKSIZE, &entry);
+    }
+    if(error != ERROR_SUCCESS) {
+        cache_container_unlock_index(container, header);
+        SetLastError(error);
+        return FALSE;
     }
-    if (error != ERROR_SUCCESS)
-        goto cleanup;
 
     /* FindFirstFreeEntry fills in blocks used */
-    pUrlEntry = (entry_url *)pEntry;
-    url_entry_offset = (LPBYTE)pUrlEntry - (LPBYTE)pHeader;
-    pUrlEntry->header.signature = URL_SIGNATURE;
-    pUrlEntry->cache_dir = cDirectory;
-    pUrlEntry->cache_entry_type = CacheEntryType | pContainer->default_entry_type;
-    pUrlEntry->header_info_size = dwHeaderSize;
-    if ((CacheEntryType & STICKY_CACHE_ENTRY) && !exempt_delta)
-    {
+    url_entry = (entry_url *)entry;
+    url_entry_offset = (LPBYTE)url_entry - (LPBYTE)header;
+    url_entry->header.signature = URL_SIGNATURE;
+    url_entry->cache_dir = dir_id;
+    url_entry->cache_entry_type = entry_type | container->default_entry_type;
+    url_entry->header_info_size = header_size;
+    if((entry_type & STICKY_CACHE_ENTRY) && !exempt_delta) {
         /* Sticky entries have a default exempt time of one day */
         exempt_delta = 86400;
     }
-    pUrlEntry->exempt_delta = exempt_delta;
-    pUrlEntry->hit_rate = hit_rate+1;
-    pUrlEntry->file_extension_off = dwOffsetFileExtension;
-    pUrlEntry->header_info_off = dwOffsetHeader;
-    pUrlEntry->local_name_off = dwOffsetLocalFileName;
-    pUrlEntry->url_off = DWORD_ALIGN(sizeof(*pUrlEntry));
-    pUrlEntry->size.QuadPart = file_size.QuadPart;
-    pUrlEntry->use_count = 0;
-    GetSystemTimeAsFileTime(&pUrlEntry->access_time);
-    pUrlEntry->modification_time = LastModifiedTime;
-    URLCache_FileTimeToDosDateTime(&pUrlEntry->access_time, &pUrlEntry->sync_date, &pUrlEntry->sync_time);
-    URLCache_FileTimeToDosDateTime(&ExpireTime, &pUrlEntry->expire_date, &pUrlEntry->expire_time);
-    URLCache_FileTimeToDosDateTime(&file_attr.ftLastWriteTime, &pUrlEntry->write_date, &pUrlEntry->write_time);
+    url_entry->exempt_delta = exempt_delta;
+    url_entry->hit_rate = hit_rate+1;
+    url_entry->file_extension_off = file_ext_off;
+    url_entry->header_info_off = header_info_off;
+    url_entry->local_name_off = file_name_off;
+    url_entry->url_off = DWORD_ALIGN(sizeof(*url_entry));
+    url_entry->size.QuadPart = file_size.QuadPart;
+    url_entry->use_count = 0;
+    GetSystemTimeAsFileTime(&url_entry->access_time);
+    url_entry->modification_time = modify_time;
+    file_time_to_dos_date_time(&url_entry->access_time, &url_entry->sync_date, &url_entry->sync_time);
+    file_time_to_dos_date_time(&expire_time, &url_entry->expire_date, &url_entry->expire_time);
+    file_time_to_dos_date_time(&file_attr.ftLastWriteTime, &url_entry->write_date, &url_entry->write_time);
 
     /*** Unknowns ***/
-    pUrlEntry->unk1 = 0;
-    pUrlEntry->unk2 = 0;
-    pUrlEntry->unk3 = 0x60;
-    pUrlEntry->unk4 = 0;
-    pUrlEntry->unk5 = 0x1010;
-    pUrlEntry->unk7 = 0;
-    pUrlEntry->unk8 = 0;
-
-
-    strcpy((LPSTR)pUrlEntry + pUrlEntry->url_off, lpszUrlNameA);
-    if (dwOffsetLocalFileName)
-        strcpy((LPSTR)((LPBYTE)pUrlEntry + dwOffsetLocalFileName), pchLocalFileName);
-    if (dwOffsetHeader)
-        memcpy((LPBYTE)pUrlEntry + dwOffsetHeader, lpHeaderInfo, dwHeaderSize);
-    if (dwOffsetFileExtension)
-        strcpy((LPSTR)((LPBYTE)pUrlEntry + dwOffsetFileExtension), lpszFileExtensionA);
-
-    error = URLCache_AddEntryToHash(pHeader, lpszUrlNameA, url_entry_offset, HASHTABLE_URL);
-    while (error == ERROR_HANDLE_DISK_FULL)
-    {
-        error = cache_container_clean_index(pContainer, &pHeader);
-        if (error == ERROR_SUCCESS)
-        {
-            pUrlEntry = (entry_url *)((LPBYTE)pHeader + url_entry_offset);
-            error = URLCache_AddEntryToHash(pHeader, lpszUrlNameA,
+    url_entry->unk1 = 0;
+    url_entry->unk2 = 0;
+    url_entry->unk3 = 0x60;
+    url_entry->unk4 = 0;
+    url_entry->unk5 = 0x1010;
+    url_entry->unk7 = 0;
+    url_entry->unk8 = 0;
+
+
+    strcpy((LPSTR)url_entry + url_entry->url_off, url);
+    if(file_name_off)
+        strcpy((LPSTR)((LPBYTE)url_entry + file_name_off), local_file_name);
+    if(header_info_off)
+        memcpy((LPBYTE)url_entry + header_info_off, header_info, header_size);
+    if(file_ext_off)
+        strcpy((LPSTR)((LPBYTE)url_entry + file_ext_off), file_ext);
+
+    error = urlcache_hash_entry_create(header, url, url_entry_offset, HASHTABLE_URL);
+    while(error == ERROR_HANDLE_DISK_FULL) {
+        error = cache_container_clean_index(container, &header);
+        if(error == ERROR_SUCCESS) {
+            url_entry = (entry_url *)((LPBYTE)header + url_entry_offset);
+            error = urlcache_hash_entry_create(header, url,
                     url_entry_offset, HASHTABLE_URL);
         }
     }
-    if (error != ERROR_SUCCESS)
-        URLCache_DeleteEntry(pHeader, &pUrlEntry->header);
-    else
-    {
-        if (pUrlEntry->cache_dir < pHeader->DirectoryCount)
-            pHeader->directory_data[pUrlEntry->cache_dir].dwNumFiles++;
-        if (CacheEntryType & STICKY_CACHE_ENTRY)
-            pHeader->ExemptUsage.QuadPart += file_size.QuadPart;
-        else
-            pHeader->CacheUsage.QuadPart += file_size.QuadPart;
-        if (pHeader->CacheUsage.QuadPart + pHeader->ExemptUsage.QuadPart >
-            pHeader->CacheLimit.QuadPart)
-            handle_full_cache();
-    }
-
-cleanup:
-    cache_container_unlock_index(pContainer, pHeader);
-    heap_free(lpszUrlNameA);
-    heap_free(lpszFileExtensionA);
-
-    if (error == ERROR_SUCCESS)
-        return TRUE;
-    else
-    {
+    if(error != ERROR_SUCCESS) {
+        urlcache_entry_free(header, &url_entry->header);
+        cache_container_unlock_index(container, header);
         SetLastError(error);
         return FALSE;
     }
+
+    if(url_entry->cache_dir < header->dirs_no)
+        header->directory_data[url_entry->cache_dir].files_no++;
+    if(entry_type & STICKY_CACHE_ENTRY)
+        header->exempt_usage.QuadPart += file_size.QuadPart;
+    else
+        header->cache_usage.QuadPart += file_size.QuadPart;
+    if(header->cache_usage.QuadPart+header->exempt_usage.QuadPart > header->cache_limit.QuadPart)
+            handle_full_cache();
+
+    cache_container_unlock_index(container, header);
+    return TRUE;
 }
 
 /***********************************************************************
  *           CommitUrlCacheEntryA (WININET.@)
- *
  */
-BOOL WINAPI CommitUrlCacheEntryA(
-    IN LPCSTR lpszUrlName,
-    IN LPCSTR lpszLocalFileName,
-    IN FILETIME ExpireTime,
-    IN FILETIME LastModifiedTime,
-    IN DWORD CacheEntryType,
-    IN LPBYTE lpHeaderInfo,
-    IN DWORD dwHeaderSize,
-    IN LPCSTR lpszFileExtension,
-    IN LPCSTR lpszOriginalUrl
-    )
+BOOL WINAPI CommitUrlCacheEntryA(LPCSTR lpszUrlName, LPCSTR lpszLocalFileName,
+        FILETIME ExpireTime, FILETIME LastModifiedTime, DWORD CacheEntryType,
+        LPBYTE lpHeaderInfo, DWORD dwHeaderSize, LPCSTR lpszFileExtension, LPCSTR lpszOriginalUrl)
 {
-    WCHAR *url_name = NULL;
-    WCHAR *local_file_name = NULL;
-    WCHAR *original_url = NULL;
-    WCHAR *file_extension = NULL;
-    BOOL bSuccess = FALSE;
-
-    TRACE("(%s, %s, ..., ..., %x, %p, %d, %s, %s)\n",
-        debugstr_a(lpszUrlName),
-        debugstr_a(lpszLocalFileName),
-        CacheEntryType,
-        lpHeaderInfo,
-        dwHeaderSize,
-        debugstr_a(lpszFileExtension),
-        debugstr_a(lpszOriginalUrl));
-
-    url_name = heap_strdupAtoW(lpszUrlName);
-    if (!url_name)
-        goto cleanup;
-
-    if (lpszLocalFileName)
-    {
-        local_file_name = heap_strdupAtoW(lpszLocalFileName);
-        if (!local_file_name)
-            goto cleanup;
-    }
-    if (lpszFileExtension)
-    {
-        file_extension = heap_strdupAtoW(lpszFileExtension);
-        if (!file_extension)
-            goto cleanup;
-    }
-    if (lpszOriginalUrl)
-    {
-        original_url = heap_strdupAtoW(lpszOriginalUrl);
-        if (!original_url)
-            goto cleanup;
-    }
+    WCHAR *file_name = NULL;
+    BOOL ret;
 
-    bSuccess = CommitUrlCacheEntryInternal(url_name, local_file_name, ExpireTime, LastModifiedTime,
-                                           CacheEntryType, lpHeaderInfo, dwHeaderSize,
-                                           file_extension, original_url);
+    if(lpszLocalFileName) {
+        file_name = heap_strdupAtoW(lpszLocalFileName);
+        if(!file_name)
+            return FALSE;
+    }
 
-cleanup:
-    heap_free(original_url);
-    heap_free(file_extension);
-    heap_free(local_file_name);
-    heap_free(url_name);
-    return bSuccess;
+    ret = urlcache_entry_commit(lpszUrlName, file_name, ExpireTime, LastModifiedTime,
+            CacheEntryType, lpHeaderInfo, dwHeaderSize, lpszFileExtension, lpszOriginalUrl);
+    heap_free(file_name);
+    return ret;
 }
 
 /***********************************************************************
  *           CommitUrlCacheEntryW (WININET.@)
- *
  */
-BOOL WINAPI CommitUrlCacheEntryW(
-    IN LPCWSTR lpszUrlName,
-    IN LPCWSTR lpszLocalFileName,
-    IN FILETIME ExpireTime,
-    IN FILETIME LastModifiedTime,
-    IN DWORD CacheEntryType,
-    IN LPWSTR lpHeaderInfo,
-    IN DWORD dwHeaderSize,
-    IN LPCWSTR lpszFileExtension,
-    IN LPCWSTR lpszOriginalUrl
-    )
+BOOL WINAPI CommitUrlCacheEntryW(LPCWSTR lpszUrlName, LPCWSTR lpszLocalFileName,
+        FILETIME ExpireTime, FILETIME LastModifiedTime, DWORD CacheEntryType,
+        LPWSTR lpHeaderInfo, DWORD dwHeaderSize, LPCWSTR lpszFileExtension, LPCWSTR lpszOriginalUrl)
 {
-    DWORD dwError = 0;
-    BOOL bSuccess = FALSE;
-    DWORD len = 0;
-    CHAR *header_info = NULL;
-
-    TRACE("(%s, %s, ..., ..., %x, %p, %d, %s, %s)\n",
-        debugstr_w(lpszUrlName),
-        debugstr_w(lpszLocalFileName),
-        CacheEntryType,
-        lpHeaderInfo,
-        dwHeaderSize,
-        debugstr_w(lpszFileExtension),
-        debugstr_w(lpszOriginalUrl));
-
-    if (!lpHeaderInfo || (header_info = heap_strdupWtoA(lpHeaderInfo)))
-    {
-        if(header_info)
-            len = strlen(header_info);
-       if (CommitUrlCacheEntryInternal(lpszUrlName, lpszLocalFileName, ExpireTime, LastModifiedTime,
-                               CacheEntryType, (LPBYTE)header_info, len, lpszFileExtension, lpszOriginalUrl))
-       {
-               bSuccess = TRUE;
-       }
-       else
-       {
-               dwError = GetLastError();
-       }
-       if (header_info)
-       {
-           heap_free(header_info);
-           if (!bSuccess)
-               SetLastError(dwError);
-       }
-    }
-    return bSuccess;
+    char *url, *original_url=NULL, *file_ext=NULL, *header_info=NULL;
+    BOOL ret;
+
+    if(!urlcache_encode_url_alloc(lpszUrlName, &url))
+        return FALSE;
+
+    if(lpHeaderInfo) {
+        header_info = heap_strdupWtoUTF8(lpHeaderInfo);
+        if(!header_info) {
+            heap_free(url);
+            return FALSE;
+        }
+        dwHeaderSize = strlen(header_info);
+    }
+
+    if(lpszFileExtension) {
+        file_ext = heap_strdupWtoA(lpszFileExtension);
+        if(!file_ext) {
+            heap_free(url);
+            heap_free(header_info);
+            return FALSE;
+        }
+    }
+
+    if(lpszOriginalUrl && !urlcache_encode_url_alloc(lpszOriginalUrl, &original_url)) {
+        heap_free(url);
+        heap_free(header_info);
+        heap_free(file_ext);
+        return FALSE;
+    }
+
+    ret = urlcache_entry_commit(url, lpszLocalFileName, ExpireTime, LastModifiedTime,
+            CacheEntryType, (BYTE*)header_info, dwHeaderSize, file_ext, original_url);
+    heap_free(url);
+    heap_free(header_info);
+    heap_free(file_ext);
+    heap_free(original_url);
+    return ret;
 }
 
 /***********************************************************************
@@ -3481,7 +3151,7 @@ BOOL WINAPI ReadUrlCacheEntryStream(
     )
 {
     /* Get handle to file from 'stream' */
-    STREAM_HANDLE * pStream = (STREAM_HANDLE *)hUrlCacheStream;
+    stream_handle *pStream = (stream_handle*)hUrlCacheStream;
 
     if (dwReserved != 0)
     {
@@ -3490,28 +3160,24 @@ BOOL WINAPI ReadUrlCacheEntryStream(
         return FALSE;
     }
 
-    if (IsBadReadPtr(pStream, sizeof(*pStream)) || IsBadStringPtrA(pStream->lpszUrl, INTERNET_MAX_URL_LENGTH))
+    if (IsBadReadPtr(pStream, sizeof(*pStream)) || IsBadStringPtrA(pStream->url, INTERNET_MAX_URL_LENGTH))
     {
         SetLastError(ERROR_INVALID_HANDLE);
         return FALSE;
     }
 
-    if (SetFilePointer(pStream->hFile, dwLocation, NULL, FILE_CURRENT) == INVALID_SET_FILE_POINTER)
+    if (SetFilePointer(pStream->file, dwLocation, NULL, FILE_CURRENT) == INVALID_SET_FILE_POINTER)
         return FALSE;
-    return ReadFile(pStream->hFile, lpBuffer, *lpdwLen, lpdwLen, NULL);
+    return ReadFile(pStream->file, lpBuffer, *lpdwLen, lpdwLen, NULL);
 }
 
 /***********************************************************************
  *           RetrieveUrlCacheEntryStreamA (WININET.@)
  *
  */
-HANDLE WINAPI RetrieveUrlCacheEntryStreamA(
-    IN LPCSTR lpszUrlName,
-    OUT LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo,
-    IN OUT LPDWORD lpdwCacheEntryInfoBufferSize,
-    IN BOOL fRandomRead,
-    IN DWORD dwReserved
-    )
+HANDLE WINAPI RetrieveUrlCacheEntryStreamA(LPCSTR lpszUrlName,
+        LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo,
+        LPDWORD lpdwCacheEntryInfoBufferSize, BOOL fRandomRead, DWORD dwReserved)
 {
     /* NOTE: this is not the same as the way that the native
      * version allocates 'stream' handles. I did it this way
@@ -3519,103 +3185,89 @@ HANDLE WINAPI RetrieveUrlCacheEntryStreamA(
      * on this behaviour. (Native version appears to allocate
      * indices into a table)
      */
-    STREAM_HANDLE * pStream;
-    HANDLE hFile;
+    stream_handle *stream;
+    HANDLE file;
 
-    TRACE( "(%s, %p, %p, %x, 0x%08x)\n", debugstr_a(lpszUrlName), lpCacheEntryInfo,
-           lpdwCacheEntryInfoBufferSize, fRandomRead, dwReserved );
+    TRACE("(%s, %p, %p, %x, 0x%08x)\n", debugstr_a(lpszUrlName), lpCacheEntryInfo,
+            lpdwCacheEntryInfoBufferSize, fRandomRead, dwReserved);
 
-    if (!RetrieveUrlCacheEntryFileA(lpszUrlName,
-        lpCacheEntryInfo,
-        lpdwCacheEntryInfoBufferSize,
-        dwReserved))
-    {
+    if(!RetrieveUrlCacheEntryFileA(lpszUrlName, lpCacheEntryInfo,
+                lpdwCacheEntryInfoBufferSize, dwReserved))
+        return NULL;
+
+    file = CreateFileA(lpCacheEntryInfo->lpszLocalFileName, GENERIC_READ, FILE_SHARE_READ,
+            NULL, OPEN_EXISTING, fRandomRead ? FILE_FLAG_RANDOM_ACCESS : 0, NULL);
+    if(file == INVALID_HANDLE_VALUE) {
+        UnlockUrlCacheEntryFileA(lpszUrlName, 0);
         return NULL;
     }
 
-    hFile = CreateFileA(lpCacheEntryInfo->lpszLocalFileName,
-        GENERIC_READ,
-        FILE_SHARE_READ,
-        NULL,
-        OPEN_EXISTING,
-        fRandomRead ? FILE_FLAG_RANDOM_ACCESS : 0,
-        NULL);
-    if (hFile == INVALID_HANDLE_VALUE)
-        return FALSE;
-    
     /* allocate handle storage space */
-    pStream = heap_alloc(sizeof(STREAM_HANDLE) + strlen(lpszUrlName) * sizeof(CHAR));
-    if (!pStream)
-    {
-        CloseHandle(hFile);
+    stream = heap_alloc(sizeof(stream_handle) + strlen(lpszUrlName) * sizeof(CHAR));
+    if(!stream) {
+        CloseHandle(file);
+        UnlockUrlCacheEntryFileA(lpszUrlName, 0);
         SetLastError(ERROR_OUTOFMEMORY);
-        return FALSE;
+        return NULL;
     }
 
-    pStream->hFile = hFile;
-    strcpy(pStream->lpszUrl, lpszUrlName);
-    return pStream;
+    stream->file = file;
+    strcpy(stream->url, lpszUrlName);
+    return stream;
 }
 
 /***********************************************************************
  *           RetrieveUrlCacheEntryStreamW (WININET.@)
  *
  */
-HANDLE WINAPI RetrieveUrlCacheEntryStreamW(
-    IN LPCWSTR lpszUrlName,
-    OUT LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo,
-    IN OUT LPDWORD lpdwCacheEntryInfoBufferSize,
-    IN BOOL fRandomRead,
-    IN DWORD dwReserved
-    )
+HANDLE WINAPI RetrieveUrlCacheEntryStreamW(LPCWSTR lpszUrlName,
+        LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo,
+        LPDWORD lpdwCacheEntryInfoBufferSize, BOOL fRandomRead, DWORD dwReserved)
 {
-    DWORD size;
-    int url_len;
+    DWORD len;
     /* NOTE: this is not the same as the way that the native
      * version allocates 'stream' handles. I did it this way
      * as it is much easier and no applications should depend
      * on this behaviour. (Native version appears to allocate
      * indices into a table)
      */
-    STREAM_HANDLE * pStream;
-    HANDLE hFile;
+    stream_handle *stream;
+    HANDLE file;
 
-    TRACE( "(%s, %p, %p, %x, 0x%08x)\n", debugstr_w(lpszUrlName), lpCacheEntryInfo,
-           lpdwCacheEntryInfoBufferSize, fRandomRead, dwReserved );
+    TRACE("(%s, %p, %p, %x, 0x%08x)\n", debugstr_w(lpszUrlName), lpCacheEntryInfo,
+            lpdwCacheEntryInfoBufferSize, fRandomRead, dwReserved);
 
-    if (!RetrieveUrlCacheEntryFileW(lpszUrlName,
-        lpCacheEntryInfo,
-        lpdwCacheEntryInfoBufferSize,
-        dwReserved))
-    {
+    if(!(len = urlcache_encode_url(lpszUrlName, NULL, 0)))
         return NULL;
-    }
 
-    hFile = CreateFileW(lpCacheEntryInfo->lpszLocalFileName,
-        GENERIC_READ,
-        FILE_SHARE_READ,
-        NULL,
-        OPEN_EXISTING,
-        fRandomRead ? FILE_FLAG_RANDOM_ACCESS : 0,
-        NULL);
-    if (hFile == INVALID_HANDLE_VALUE)
-        return FALSE;
+    if(!RetrieveUrlCacheEntryFileW(lpszUrlName, lpCacheEntryInfo,
+                lpdwCacheEntryInfoBufferSize, dwReserved))
+        return NULL;
+
+    file = CreateFileW(lpCacheEntryInfo->lpszLocalFileName, GENERIC_READ, FILE_SHARE_READ,
+            NULL, OPEN_EXISTING, fRandomRead ? FILE_FLAG_RANDOM_ACCESS : 0, NULL);
+    if(file == INVALID_HANDLE_VALUE) {
+        UnlockUrlCacheEntryFileW(lpszUrlName, 0);
+        return NULL;
+    }
 
     /* allocate handle storage space */
-    size = sizeof(STREAM_HANDLE);
-    url_len = WideCharToMultiByte(CP_ACP, 0, lpszUrlName, -1, NULL, 0, NULL, NULL);
-    size += url_len;
-    pStream = heap_alloc(size);
-    if (!pStream)
-    {
-        CloseHandle(hFile);
+    stream = heap_alloc(sizeof(stream_handle) + len*sizeof(WCHAR));
+    if(!stream) {
+        CloseHandle(file);
+        UnlockUrlCacheEntryFileW(lpszUrlName, 0);
         SetLastError(ERROR_OUTOFMEMORY);
-        return FALSE;
+        return NULL;
     }
 
-    pStream->hFile = hFile;
-    WideCharToMultiByte(CP_ACP, 0, lpszUrlName, -1, pStream->lpszUrl, url_len, NULL, NULL);
-    return pStream;
+    stream->file = file;
+    if(!urlcache_encode_url(lpszUrlName, stream->url, len)) {
+        CloseHandle(file);
+        UnlockUrlCacheEntryFileW(lpszUrlName, 0);
+        heap_free(stream);
+        return NULL;
+    }
+    return stream;
 }
 
 /***********************************************************************
@@ -3627,7 +3279,7 @@ BOOL WINAPI UnlockUrlCacheEntryStream(
     IN DWORD dwReserved
 )
 {
-    STREAM_HANDLE * pStream = (STREAM_HANDLE *)hUrlCacheStream;
+    stream_handle *pStream = (stream_handle*)hUrlCacheStream;
 
     if (dwReserved != 0)
     {
@@ -3636,16 +3288,16 @@ BOOL WINAPI UnlockUrlCacheEntryStream(
         return FALSE;
     }
 
-    if (IsBadReadPtr(pStream, sizeof(*pStream)) || IsBadStringPtrA(pStream->lpszUrl, INTERNET_MAX_URL_LENGTH))
+    if (IsBadReadPtr(pStream, sizeof(*pStream)) || IsBadStringPtrA(pStream->url, INTERNET_MAX_URL_LENGTH))
     {
         SetLastError(ERROR_INVALID_HANDLE);
         return FALSE;
     }
 
-    if (!UnlockUrlCacheEntryFileA(pStream->lpszUrl, 0))
+    if (!UnlockUrlCacheEntryFileA(pStream->url, 0))
         return FALSE;
 
-    CloseHandle(pStream->hFile);
+    CloseHandle(pStream->file);
     heap_free(pStream);
     return TRUE;
 }
@@ -3657,15 +3309,15 @@ BOOL WINAPI UnlockUrlCacheEntryStream(
  */
 BOOL WINAPI DeleteUrlCacheEntryA(LPCSTR lpszUrlName)
 {
-    URLCACHECONTAINER * pContainer;
-    LPURLCACHE_HEADER pHeader;
-    struct _HASH_ENTRY * pHashEntry;
+    cache_container *pContainer;
+    urlcache_header *pHeader;
+    struct hash_entry *pHashEntry;
     DWORD error;
     BOOL ret;
 
     TRACE("(%s)\n", debugstr_a(lpszUrlName));
 
-    error = URLCacheContainers_FindContainerA(lpszUrlName, &pContainer);
+    error = cache_containers_find(lpszUrlName, &pContainer);
     if (error != ERROR_SUCCESS)
     {
         SetLastError(error);
@@ -3682,7 +3334,7 @@ BOOL WINAPI DeleteUrlCacheEntryA(LPCSTR lpszUrlName)
     if (!(pHeader = cache_container_lock_index(pContainer)))
         return FALSE;
 
-    if (!URLCache_FindHash(pHeader, lpszUrlName, &pHashEntry))
+    if (!urlcache_find_hash_entry(pHeader, lpszUrlName, &pHashEntry))
     {
         cache_container_unlock_index(pContainer, pHeader);
         TRACE("entry %s not found!\n", lpszUrlName);
@@ -3690,7 +3342,7 @@ BOOL WINAPI DeleteUrlCacheEntryA(LPCSTR lpszUrlName)
         return FALSE;
     }
 
-    ret = DeleteUrlCacheEntryInternal(pContainer, pHeader, pHashEntry);
+    ret = urlcache_entry_delete(pContainer, pHeader, pHashEntry);
 
     cache_container_unlock_index(pContainer, pHeader);
 
@@ -3703,57 +3355,14 @@ BOOL WINAPI DeleteUrlCacheEntryA(LPCSTR lpszUrlName)
  */
 BOOL WINAPI DeleteUrlCacheEntryW(LPCWSTR lpszUrlName)
 {
-    URLCACHECONTAINER * pContainer;
-    LPURLCACHE_HEADER pHeader;
-    struct _HASH_ENTRY * pHashEntry;
-    LPSTR urlA;
-    DWORD error;
+    char *url;
     BOOL ret;
 
-    TRACE("(%s)\n", debugstr_w(lpszUrlName));
-
-    urlA = heap_strdupWtoA(lpszUrlName);
-    if (!urlA)
-    {
-        SetLastError(ERROR_OUTOFMEMORY);
-        return FALSE;
-    }
-
-    error = URLCacheContainers_FindContainerW(lpszUrlName, &pContainer);
-    if (error != ERROR_SUCCESS)
-    {
-        heap_free(urlA);
-        SetLastError(error);
-        return FALSE;
-    }
-
-    error = cache_container_open_index(pContainer, MIN_BLOCK_NO);
-    if (error != ERROR_SUCCESS)
-    {
-        heap_free(urlA);
-        SetLastError(error);
-        return FALSE;
-    }
-
-    if (!(pHeader = cache_container_lock_index(pContainer)))
-    {
-        heap_free(urlA);
-        return FALSE;
-    }
-
-    if (!URLCache_FindHash(pHeader, urlA, &pHashEntry))
-    {
-        cache_container_unlock_index(pContainer, pHeader);
-        TRACE("entry %s not found!\n", debugstr_a(urlA));
-        heap_free(urlA);
-        SetLastError(ERROR_FILE_NOT_FOUND);
+    if(!urlcache_encode_url_alloc(lpszUrlName, &url))
         return FALSE;
-    }
-
-    ret = DeleteUrlCacheEntryInternal(pContainer, pHeader, pHashEntry);
 
-    cache_container_unlock_index(pContainer, pHeader);
-    heap_free(urlA);
+    ret = DeleteUrlCacheEntryA(url);
+    heap_free(url);
     return ret;
 }
 
@@ -3865,17 +3474,6 @@ HANDLE WINAPI FindFirstUrlCacheEntryExW(
     return NULL;
 }
 
-#define URLCACHE_FIND_ENTRY_HANDLE_MAGIC 0xF389ABCD
-
-typedef struct URLCacheFindEntryHandle
-{
-    DWORD dwMagic;
-    LPWSTR lpszUrlSearchPattern;
-    DWORD dwContainerIndex;
-    DWORD dwHashTableIndex;
-    DWORD dwHashEntryIndex;
-} URLCacheFindEntryHandle;
-
 /***********************************************************************
  *           FindFirstUrlCacheEntryA (WININET.@)
  *
@@ -3883,7 +3481,7 @@ typedef struct URLCacheFindEntryHandle
 INTERNETAPI HANDLE WINAPI FindFirstUrlCacheEntryA(LPCSTR lpszUrlSearchPattern,
  LPINTERNET_CACHE_ENTRY_INFOA lpFirstCacheEntryInfo, LPDWORD lpdwFirstCacheEntryInfoBufferSize)
 {
-    URLCacheFindEntryHandle *pEntryHandle;
+    find_handle *pEntryHandle;
 
     TRACE("(%s, %p, %p)\n", debugstr_a(lpszUrlSearchPattern), lpFirstCacheEntryInfo, lpdwFirstCacheEntryInfoBufferSize);
 
@@ -3891,21 +3489,21 @@ INTERNETAPI HANDLE WINAPI FindFirstUrlCacheEntryA(LPCSTR lpszUrlSearchPattern,
     if (!pEntryHandle)
         return NULL;
 
-    pEntryHandle->dwMagic = URLCACHE_FIND_ENTRY_HANDLE_MAGIC;
+    pEntryHandle->magic = URLCACHE_FIND_ENTRY_HANDLE_MAGIC;
     if (lpszUrlSearchPattern)
     {
-        pEntryHandle->lpszUrlSearchPattern = heap_strdupAtoW(lpszUrlSearchPattern);
-        if (!pEntryHandle->lpszUrlSearchPattern)
+        pEntryHandle->url_search_pattern = heap_strdupA(lpszUrlSearchPattern);
+        if (!pEntryHandle->url_search_pattern)
         {
             heap_free(pEntryHandle);
             return NULL;
         }
     }
     else
-        pEntryHandle->lpszUrlSearchPattern = NULL;
-    pEntryHandle->dwContainerIndex = 0;
-    pEntryHandle->dwHashTableIndex = 0;
-    pEntryHandle->dwHashEntryIndex = 0;
+        pEntryHandle->url_search_pattern = NULL;
+    pEntryHandle->container_idx = 0;
+    pEntryHandle->hash_table_idx = 0;
+    pEntryHandle->hash_entry_idx = 0;
 
     if (!FindNextUrlCacheEntryA(pEntryHandle, lpFirstCacheEntryInfo, lpdwFirstCacheEntryInfoBufferSize))
     {
@@ -3922,7 +3520,7 @@ INTERNETAPI HANDLE WINAPI FindFirstUrlCacheEntryA(LPCSTR lpszUrlSearchPattern,
 INTERNETAPI HANDLE WINAPI FindFirstUrlCacheEntryW(LPCWSTR lpszUrlSearchPattern,
  LPINTERNET_CACHE_ENTRY_INFOW lpFirstCacheEntryInfo, LPDWORD lpdwFirstCacheEntryInfoBufferSize)
 {
-    URLCacheFindEntryHandle *pEntryHandle;
+    find_handle *pEntryHandle;
 
     TRACE("(%s, %p, %p)\n", debugstr_w(lpszUrlSearchPattern), lpFirstCacheEntryInfo, lpdwFirstCacheEntryInfoBufferSize);
 
@@ -3930,21 +3528,21 @@ INTERNETAPI HANDLE WINAPI FindFirstUrlCacheEntryW(LPCWSTR lpszUrlSearchPattern,
     if (!pEntryHandle)
         return NULL;
 
-    pEntryHandle->dwMagic = URLCACHE_FIND_ENTRY_HANDLE_MAGIC;
+    pEntryHandle->magic = URLCACHE_FIND_ENTRY_HANDLE_MAGIC;
     if (lpszUrlSearchPattern)
     {
-        pEntryHandle->lpszUrlSearchPattern = heap_strdupW(lpszUrlSearchPattern);
-        if (!pEntryHandle->lpszUrlSearchPattern)
+        pEntryHandle->url_search_pattern = heap_strdupWtoA(lpszUrlSearchPattern);
+        if (!pEntryHandle->url_search_pattern)
         {
             heap_free(pEntryHandle);
             return NULL;
         }
     }
     else
-        pEntryHandle->lpszUrlSearchPattern = NULL;
-    pEntryHandle->dwContainerIndex = 0;
-    pEntryHandle->dwHashTableIndex = 0;
-    pEntryHandle->dwHashEntryIndex = 0;
+        pEntryHandle->url_search_pattern = NULL;
+    pEntryHandle->container_idx = 0;
+    pEntryHandle->hash_table_idx = 0;
+    pEntryHandle->hash_entry_idx = 0;
 
     if (!FindNextUrlCacheEntryW(pEntryHandle, lpFirstCacheEntryInfo, lpdwFirstCacheEntryInfoBufferSize))
     {
@@ -3954,26 +3552,26 @@ INTERNETAPI HANDLE WINAPI FindFirstUrlCacheEntryW(LPCWSTR lpszUrlSearchPattern,
     return pEntryHandle;
 }
 
-static BOOL FindNextUrlCacheEntryInternal(
+static BOOL urlcache_find_next_entry(
   HANDLE hEnumHandle,
   LPINTERNET_CACHE_ENTRY_INFOA lpNextCacheEntryInfo,
   LPDWORD lpdwNextCacheEntryInfoBufferSize,
   BOOL unicode)
 {
-    URLCacheFindEntryHandle *pEntryHandle = (URLCacheFindEntryHandle *)hEnumHandle;
-    URLCACHECONTAINER * pContainer;
+    find_handle *pEntryHandle = (find_handle*)hEnumHandle;
+    cache_container *pContainer;
 
-    if (pEntryHandle->dwMagic != URLCACHE_FIND_ENTRY_HANDLE_MAGIC)
+    if (pEntryHandle->magic != URLCACHE_FIND_ENTRY_HANDLE_MAGIC)
     {
         SetLastError(ERROR_INVALID_HANDLE);
         return FALSE;
     }
 
-    for (; URLCacheContainers_Enum(pEntryHandle->lpszUrlSearchPattern, pEntryHandle->dwContainerIndex, &pContainer);
-         pEntryHandle->dwContainerIndex++, pEntryHandle->dwHashTableIndex = 0)
+    for (; cache_containers_enum(pEntryHandle->url_search_pattern, pEntryHandle->container_idx, &pContainer);
+         pEntryHandle->container_idx++, pEntryHandle->hash_table_idx = 0)
     {
-        LPURLCACHE_HEADER pHeader;
-        HASH_CACHEFILE_ENTRY *pHashTableEntry;
+        urlcache_header *pHeader;
+        entry_hash_table *pHashTableEntry;
         DWORD error;
 
         error = cache_container_open_index(pContainer, MIN_BLOCK_NO);
@@ -3986,15 +3584,15 @@ static BOOL FindNextUrlCacheEntryInternal(
         if (!(pHeader = cache_container_lock_index(pContainer)))
             return FALSE;
 
-        for (; URLCache_EnumHashTables(pHeader, &pEntryHandle->dwHashTableIndex, &pHashTableEntry);
-             pEntryHandle->dwHashTableIndex++, pEntryHandle->dwHashEntryIndex = 0)
+        for (; urlcache_enum_hash_tables(pHeader, &pEntryHandle->hash_table_idx, &pHashTableEntry);
+             pEntryHandle->hash_table_idx++, pEntryHandle->hash_entry_idx = 0)
         {
-            const struct _HASH_ENTRY *pHashEntry = NULL;
-            for (; URLCache_EnumHashTableEntries(pHeader, pHashTableEntry, &pEntryHandle->dwHashEntryIndex, &pHashEntry);
-                 pEntryHandle->dwHashEntryIndex++)
+            const struct hash_entry *pHashEntry = NULL;
+            for (; urlcache_enum_hash_table_entries(pHeader, pHashTableEntry, &pEntryHandle->hash_entry_idx, &pHashEntry);
+                 pEntryHandle->hash_entry_idx++)
             {
                 const entry_url *pUrlEntry;
-                const entry_header *pEntry = (const entry_header*)((LPBYTE)pHeader + pHashEntry->dwOffsetEntry);
+                const entry_header *pEntry = (const entry_header*)((LPBYTE)pHeader + pHashEntry->offset);
 
                 if (pEntry->signature != URL_SIGNATURE)
                     continue;
@@ -4006,7 +3604,7 @@ static BOOL FindNextUrlCacheEntryInternal(
                         debugstr_an((LPCSTR)pUrlEntry + pUrlEntry->header_info_off,
                             pUrlEntry->header_info_size));
 
-                error = URLCache_CopyEntry(
+                error = urlcache_copy_entry(
                     pContainer,
                     pHeader,
                     lpNextCacheEntryInfo,
@@ -4024,7 +3622,7 @@ static BOOL FindNextUrlCacheEntryInternal(
 
                 /* increment the current index so that next time the function
                  * is called the next entry is returned */
-                pEntryHandle->dwHashEntryIndex++;
+                pEntryHandle->hash_entry_idx++;
                 cache_container_unlock_index(pContainer, pHeader);
                 return TRUE;
             }
@@ -4047,7 +3645,7 @@ BOOL WINAPI FindNextUrlCacheEntryA(
 {
     TRACE("(%p, %p, %p)\n", hEnumHandle, lpNextCacheEntryInfo, lpdwNextCacheEntryInfoBufferSize);
 
-    return FindNextUrlCacheEntryInternal(hEnumHandle, lpNextCacheEntryInfo,
+    return urlcache_find_next_entry(hEnumHandle, lpNextCacheEntryInfo,
             lpdwNextCacheEntryInfoBufferSize, FALSE /* not UNICODE */);
 }
 
@@ -4062,7 +3660,7 @@ BOOL WINAPI FindNextUrlCacheEntryW(
 {
     TRACE("(%p, %p, %p)\n", hEnumHandle, lpNextCacheEntryInfo, lpdwNextCacheEntryInfoBufferSize);
 
-    return FindNextUrlCacheEntryInternal(hEnumHandle,
+    return urlcache_find_next_entry(hEnumHandle,
             (LPINTERNET_CACHE_ENTRY_INFOA)lpNextCacheEntryInfo,
             lpdwNextCacheEntryInfoBufferSize, TRUE /* UNICODE */);
 }
@@ -4072,18 +3670,18 @@ BOOL WINAPI FindNextUrlCacheEntryW(
  */
 BOOL WINAPI FindCloseUrlCache(HANDLE hEnumHandle)
 {
-    URLCacheFindEntryHandle *pEntryHandle = (URLCacheFindEntryHandle *)hEnumHandle;
+    find_handle *pEntryHandle = (find_handle*)hEnumHandle;
 
     TRACE("(%p)\n", hEnumHandle);
 
-    if (!pEntryHandle || pEntryHandle->dwMagic != URLCACHE_FIND_ENTRY_HANDLE_MAGIC)
+    if (!pEntryHandle || pEntryHandle->magic != URLCACHE_FIND_ENTRY_HANDLE_MAGIC)
     {
         SetLastError(ERROR_INVALID_HANDLE);
         return FALSE;
     }
 
-    pEntryHandle->dwMagic = 0;
-    heap_free(pEntryHandle->lpszUrlSearchPattern);
+    pEntryHandle->magic = 0;
+    heap_free(pEntryHandle->url_search_pattern);
     heap_free(pEntryHandle);
     return TRUE;
 }
@@ -4276,7 +3874,7 @@ DWORD WINAPI DeleteIE3Cache(HWND hWnd, HINSTANCE hInst, LPSTR lpszCmdLine, int n
     return 0;
 }
 
-static BOOL IsUrlCacheEntryExpiredInternal(const entry_url *pUrlEntry,
+static BOOL urlcache_entry_is_expired(const entry_url *pUrlEntry,
         FILETIME *pftLastModified)
 {
     BOOL ret;
@@ -4284,7 +3882,7 @@ static BOOL IsUrlCacheEntryExpiredInternal(const entry_url *pUrlEntry,
 
     *pftLastModified = pUrlEntry->modification_time;
     GetSystemTimeAsFileTime(&now);
-    URLCache_DosDateTimeToFileTime(pUrlEntry->expire_date,
+    dos_date_time_to_file_time(pUrlEntry->expire_date,
             pUrlEntry->expire_time, &expired);
     /* If the expired time is 0, it's interpreted as not expired */
     if (!expired.dwLowDateTime && !expired.dwHighDateTime)
@@ -4302,13 +3900,13 @@ static BOOL IsUrlCacheEntryExpiredInternal(const entry_url *pUrlEntry,
  *   dwFlags         [I] Unknown
  *   pftLastModified [O] Last modified time
  */
-BOOL WINAPI IsUrlCacheEntryExpiredA( LPCSTR url, DWORD dwFlags, FILETIME* pftLastModified )
+BOOL WINAPI IsUrlCacheEntryExpiredA(LPCSTR url, DWORD dwFlags, FILETIME* pftLastModified)
 {
-    LPURLCACHE_HEADER pHeader;
-    struct _HASH_ENTRY * pHashEntry;
+    urlcache_header *pHeader;
+    struct hash_entry *pHashEntry;
     const entry_header *pEntry;
     const entry_url * pUrlEntry;
-    URLCACHECONTAINER * pContainer;
+    cache_container *pContainer;
     BOOL expired;
 
     TRACE("(%s, %08x, %p)\n", debugstr_a(url), dwFlags, pftLastModified);
@@ -4319,7 +3917,7 @@ BOOL WINAPI IsUrlCacheEntryExpiredA( LPCSTR url, DWORD dwFlags, FILETIME* pftLas
         FIXME("unknown flags 0x%08x\n", dwFlags);
 
     /* Any error implies that the URL is expired, i.e. not in the cache */
-    if (URLCacheContainers_FindContainerA(url, &pContainer))
+    if (cache_containers_find(url, &pContainer))
     {
         memset(pftLastModified, 0, sizeof(*pftLastModified));
         return TRUE;
@@ -4337,7 +3935,7 @@ BOOL WINAPI IsUrlCacheEntryExpiredA( LPCSTR url, DWORD dwFlags, FILETIME* pftLas
         return TRUE;
     }
 
-    if (!URLCache_FindHash(pHeader, url, &pHashEntry))
+    if (!urlcache_find_hash_entry(pHeader, url, &pHashEntry))
     {
         cache_container_unlock_index(pContainer, pHeader);
         memset(pftLastModified, 0, sizeof(*pftLastModified));
@@ -4345,7 +3943,7 @@ BOOL WINAPI IsUrlCacheEntryExpiredA( LPCSTR url, DWORD dwFlags, FILETIME* pftLas
         return TRUE;
     }
 
-    pEntry = (const entry_header*)((LPBYTE)pHeader + pHashEntry->dwOffsetEntry);
+    pEntry = (const entry_header*)((LPBYTE)pHeader + pHashEntry->offset);
     if (pEntry->signature != URL_SIGNATURE)
     {
         cache_container_unlock_index(pContainer, pHeader);
@@ -4355,7 +3953,7 @@ BOOL WINAPI IsUrlCacheEntryExpiredA( LPCSTR url, DWORD dwFlags, FILETIME* pftLas
     }
 
     pUrlEntry = (const entry_url *)pEntry;
-    expired = IsUrlCacheEntryExpiredInternal(pUrlEntry, pftLastModified);
+    expired = urlcache_entry_is_expired(pUrlEntry, pftLastModified);
 
     cache_container_unlock_index(pContainer, pHeader);
 
@@ -4370,72 +3968,17 @@ BOOL WINAPI IsUrlCacheEntryExpiredA( LPCSTR url, DWORD dwFlags, FILETIME* pftLas
  *   dwFlags         [I] Unknown
  *   pftLastModified [O] Last modified time
  */
-BOOL WINAPI IsUrlCacheEntryExpiredW( LPCWSTR url, DWORD dwFlags, FILETIME* pftLastModified )
+BOOL WINAPI IsUrlCacheEntryExpiredW(LPCWSTR url, DWORD dwFlags, FILETIME* pftLastModified)
 {
-    LPURLCACHE_HEADER pHeader;
-    struct _HASH_ENTRY * pHashEntry;
-    const entry_header *pEntry;
-    const entry_url * pUrlEntry;
-    URLCACHECONTAINER * pContainer;
-    BOOL expired;
-
-    TRACE("(%s, %08x, %p)\n", debugstr_w(url), dwFlags, pftLastModified);
-
-    if (!url || !pftLastModified)
-        return TRUE;
-    if (dwFlags)
-        FIXME("unknown flags 0x%08x\n", dwFlags);
-
-    /* Any error implies that the URL is expired, i.e. not in the cache */
-    if (URLCacheContainers_FindContainerW(url, &pContainer))
-    {
-        memset(pftLastModified, 0, sizeof(*pftLastModified));
-        return TRUE;
-    }
-
-    if (cache_container_open_index(pContainer, MIN_BLOCK_NO))
-    {
-        memset(pftLastModified, 0, sizeof(*pftLastModified));
-        return TRUE;
-    }
-
-    if (!(pHeader = cache_container_lock_index(pContainer)))
-    {
-        memset(pftLastModified, 0, sizeof(*pftLastModified));
-        return TRUE;
-    }
-
-    if (!URLCache_FindHashW(pHeader, url, &pHashEntry))
-    {
-        cache_container_unlock_index(pContainer, pHeader);
-        memset(pftLastModified, 0, sizeof(*pftLastModified));
-        TRACE("entry %s not found!\n", debugstr_w(url));
-        return TRUE;
-    }
-
-    if (!URLCache_FindHashW(pHeader, url, &pHashEntry))
-    {
-        cache_container_unlock_index(pContainer, pHeader);
-        memset(pftLastModified, 0, sizeof(*pftLastModified));
-        TRACE("entry %s not found!\n", debugstr_w(url));
-        return TRUE;
-    }
-
-    pEntry = (const entry_header*)((LPBYTE)pHeader + pHashEntry->dwOffsetEntry);
-    if (pEntry->signature != URL_SIGNATURE)
-    {
-        cache_container_unlock_index(pContainer, pHeader);
-        memset(pftLastModified, 0, sizeof(*pftLastModified));
-        FIXME("Trying to retrieve entry of unknown format %s\n", debugstr_an((LPCSTR)&pEntry->signature, sizeof(DWORD)));
-        return TRUE;
-    }
-
-    pUrlEntry = (const entry_url *)pEntry;
-    expired = IsUrlCacheEntryExpiredInternal(pUrlEntry, pftLastModified);
+    char *encoded_url;
+    BOOL ret;
 
-    cache_container_unlock_index(pContainer, pHeader);
+    if(!urlcache_encode_url_alloc(url, &encoded_url))
+        return FALSE;
 
-    return expired;
+    ret = IsUrlCacheEntryExpiredA(encoded_url, dwFlags, pftLastModified);
+    heap_free(encoded_url);
+    return ret;
 }
 
 /***********************************************************************
@@ -4503,7 +4046,7 @@ BOOL init_urlcache(void)
         return FALSE;
     }
 
-    URLCacheContainers_CreateDefaults();
+    cache_containers_init();
     return TRUE;
 }
 
@@ -4515,7 +4058,7 @@ void free_urlcache(void)
     CloseHandle(free_cache_running);
     CloseHandle(dll_unload_event);
 
-    URLCacheContainers_DeleteAll();
+    cache_containers_free();
 }
 
 /***********************************************************************
index bc37bd8..2e6d49d 100644 (file)
@@ -25,4 +25,4 @@
 #define WINE_PRODUCTVERSION 6,0,2800,1106
 #define WINE_PRODUCTVERSION_STR "6.0.2800.1106"
 
-#include "wine/wine_common_ver.rc"
+#include <wine/wine_common_ver.rc>
index f64550a..00db97a 100644 (file)
@@ -203,7 +203,7 @@ reactos/dll/win32/windowscodecs   # Synced to Wine-1.7.1
 reactos/dll/win32/winemp3.acm     # Synced to Wine-1.7.1
 reactos/dll/win32/wing32          # Out of sync
 reactos/dll/win32/winhttp         # Synced to Wine-1.7.1
-reactos/dll/win32/wininet         # Synced to Wine-1.5.26
+reactos/dll/win32/wininet         # Synced to Wine-1.7.1
 reactos/dll/win32/winmm           # Forked at Wine-20050628
 reactos/dll/win32/winmm/midimap   # Forked at Wine-20050628
 reactos/dll/win32/winmm/wavemap   # Forked at Wine-20050628