[WININET]
authorAmine Khaldi <amine.khaldi@reactos.org>
Sat, 26 Apr 2014 17:50:05 +0000 (17:50 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Sat, 26 Apr 2014 17:50:05 +0000 (17:50 +0000)
* Sync with Wine 1.7.17.
CORE-8080

svn path=/trunk/; revision=62993

reactos/dll/win32/wininet/dialogs.c
reactos/dll/win32/wininet/ftp.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/utility.c
reactos/media/doc/README.WINE

index 872022f..b849d47 100644 (file)
@@ -433,7 +433,7 @@ static INT_PTR WINAPI WININET_InvalidCertificateDialog(
                 /* FIXME: Use helper function */
                 flags |= SECURITY_FLAG_SECURE;
                 req->security_flags |= flags;
-                if(req->netconn)
+                if(is_valid_netconn(req->netconn))
                     req->netconn->security_flags |= flags;
             }
 
index 21d0863..df7becf 100644 (file)
@@ -489,7 +489,7 @@ static BOOL FTP_FtpSetCurrentDirectoryW(ftp_session_t *lpwfs, LPCWSTR lpszDirect
 {
     INT nResCode;
     appinfo_t *hIC = NULL;
-    DWORD bSuccess = FALSE;
+    BOOL bSuccess = FALSE;
 
     TRACE("lpszDirectory(%s)\n", debugstr_w(lpszDirectory));
 
@@ -1004,7 +1004,7 @@ static BOOL FTP_FtpGetCurrentDirectoryW(ftp_session_t *lpwfs, LPWSTR lpszCurrent
 {
     INT nResCode;
     appinfo_t *hIC = NULL;
-    DWORD bSuccess = FALSE;
+    BOOL bSuccess = FALSE;
 
     /* Clear any error information */
     INTERNET_SetLastError(0);
@@ -1249,6 +1249,12 @@ static DWORD FTPFILE_QueryDataAvailable(object_header_t *hdr, DWORD *available,
     return ERROR_SUCCESS;
 }
 
+static DWORD FTPFILE_LockRequestFile(object_header_t *hdr, req_file_t **ret)
+{
+    ftp_file_t *file = (ftp_file_t*)hdr;
+    FIXME("%p\n", file);
+    return ERROR_NOT_SUPPORTED;
+}
 
 static const object_vtbl_t FTPFILEVtbl = {
     FTPFILE_Destroy,
@@ -1259,7 +1265,8 @@ static const object_vtbl_t FTPFILEVtbl = {
     FTPFILE_ReadFileEx,
     FTPFILE_WriteFile,
     FTPFILE_QueryDataAvailable,
-    NULL
+    NULL,
+    FTPFILE_LockRequestFile
 };
 
 /***********************************************************************
index 240533c..7e7bd33 100644 (file)
@@ -351,16 +351,10 @@ static LPHTTPHEADERW HTTP_GetHeader(http_request_t *req, LPCWSTR head)
         return &req->custHeaders[HeaderIndex];
 }
 
-typedef enum {
-    READMODE_SYNC,
-    READMODE_ASYNC,
-    READMODE_NOBLOCK
-} read_mode_t;
-
 struct data_stream_vtbl_t {
     DWORD (*get_avail_data)(data_stream_t*,http_request_t*);
     BOOL (*end_of_data)(data_stream_t*,http_request_t*);
-    DWORD (*read)(data_stream_t*,http_request_t*,BYTE*,DWORD,DWORD*,read_mode_t);
+    DWORD (*read)(data_stream_t*,http_request_t*,BYTE*,DWORD,DWORD*,blocking_mode_t);
     BOOL (*drain_content)(data_stream_t*,http_request_t*);
     void (*destroy)(data_stream_t*);
 };
@@ -372,6 +366,7 @@ typedef struct {
     DWORD buf_size;
     DWORD buf_pos;
     DWORD chunk_size;
+    BOOL end_of_data;
 } chunked_stream_t;
 
 static inline void destroy_data_stream(data_stream_t *stream)
@@ -408,47 +403,45 @@ static DWORD gzip_get_avail_data(data_stream_t *stream, http_request_t *req)
 static BOOL gzip_end_of_data(data_stream_t *stream, http_request_t *req)
 {
     gzip_stream_t *gzip_stream = (gzip_stream_t*)stream;
-    return gzip_stream->end_of_data;
+    return gzip_stream->end_of_data
+        || (!gzip_stream->buf_size && gzip_stream->parent_stream->vtbl->end_of_data(gzip_stream->parent_stream, req));
 }
 
 static DWORD gzip_read(data_stream_t *stream, http_request_t *req, BYTE *buf, DWORD size,
-        DWORD *read, read_mode_t read_mode)
+        DWORD *read, blocking_mode_t blocking_mode)
 {
     gzip_stream_t *gzip_stream = (gzip_stream_t*)stream;
     z_stream *zstream = &gzip_stream->zstream;
     DWORD current_read, ret_read = 0;
-    BOOL end;
     int zres;
     DWORD res = ERROR_SUCCESS;
 
-    while(size && !gzip_stream->end_of_data) {
-        end = gzip_stream->parent_stream->vtbl->end_of_data(gzip_stream->parent_stream, req);
+    TRACE("(%d %d)\n", size, blocking_mode);
 
-        if(gzip_stream->buf_size <= 64 && !end) {
+    while(size && !gzip_stream->end_of_data) {
+        if(!gzip_stream->buf_size) {
             if(gzip_stream->buf_pos) {
                 if(gzip_stream->buf_size)
                     memmove(gzip_stream->buf, gzip_stream->buf+gzip_stream->buf_pos, gzip_stream->buf_size);
                 gzip_stream->buf_pos = 0;
             }
             res = gzip_stream->parent_stream->vtbl->read(gzip_stream->parent_stream, req, gzip_stream->buf+gzip_stream->buf_size,
-                    sizeof(gzip_stream->buf)-gzip_stream->buf_size, &current_read, read_mode);
+                    sizeof(gzip_stream->buf)-gzip_stream->buf_size, &current_read, blocking_mode);
             gzip_stream->buf_size += current_read;
             if(res != ERROR_SUCCESS)
                 break;
-            end = gzip_stream->parent_stream->vtbl->end_of_data(gzip_stream->parent_stream, req);
-            if(!current_read && !end) {
-                if(read_mode != READMODE_NOBLOCK) {
+
+            if(!current_read) {
+                if(blocking_mode != BLOCKING_DISALLOW) {
                     WARN("unexpected end of data\n");
                     gzip_stream->end_of_data = TRUE;
                 }
                 break;
             }
-            if(gzip_stream->buf_size <= 64 && !end)
-                continue;
         }
 
         zstream->next_in = gzip_stream->buf+gzip_stream->buf_pos;
-        zstream->avail_in = gzip_stream->buf_size-(end ? 0 : 64);
+        zstream->avail_in = gzip_stream->buf_size;
         zstream->next_out = buf+ret_read;
         zstream->avail_out = size;
         zres = inflate(&gzip_stream->zstream, 0);
@@ -468,8 +461,8 @@ static DWORD gzip_read(data_stream_t *stream, http_request_t *req, BYTE *buf, DW
             break;
         }
 
-        if(ret_read && read_mode == READMODE_ASYNC)
-            read_mode = READMODE_NOBLOCK;
+        if(ret_read && blocking_mode == BLOCKING_ALLOW)
+            blocking_mode = BLOCKING_DISALLOW;
     }
 
     TRACE("read %u bytes\n", ret_read);
@@ -512,7 +505,7 @@ static void wininet_zfree(voidpf opaque, voidpf address)
     heap_free(address);
 }
 
-static DWORD init_gzip_stream(http_request_t *req)
+static DWORD init_gzip_stream(http_request_t *req, BOOL is_gzip)
 {
     gzip_stream_t *gzip_stream;
     int index, zres;
@@ -525,7 +518,7 @@ static DWORD init_gzip_stream(http_request_t *req)
     gzip_stream->zstream.zalloc = wininet_zalloc;
     gzip_stream->zstream.zfree = wininet_zfree;
 
-    zres = inflateInit2(&gzip_stream->zstream, 0x1f);
+    zres = inflateInit2(&gzip_stream->zstream, is_gzip ? 0x1f : -15);
     if(zres != Z_OK) {
         ERR("inflateInit failed: %d\n", zres);
         heap_free(gzip_stream);
@@ -550,7 +543,7 @@ static DWORD init_gzip_stream(http_request_t *req)
 
 #else
 
-static DWORD init_gzip_stream(http_request_t *req)
+static DWORD init_gzip_stream(http_request_t *req, BOOL is_gzip)
 {
     ERR("gzip stream not supported, missing zlib.\n");
     return ERROR_SUCCESS;
@@ -1422,7 +1415,7 @@ HINTERNET WINAPI HttpOpenRequestA(HINTERNET hHttpSession,
 {
     LPWSTR szVerb = NULL, szObjectName = NULL;
     LPWSTR szVersion = NULL, szReferrer = NULL, *szAcceptTypes = NULL;
-    HINTERNET rc = FALSE;
+    HINTERNET rc = NULL;
 
     TRACE("(%p, %s, %s, %s, %s, %p, %08x, %08lx)\n", hHttpSession,
           debugstr_a(lpszVerb), debugstr_a(lpszObjectName),
@@ -1883,11 +1876,10 @@ static void HTTPREQ_Destroy(object_header_t *hdr)
 
     TRACE("\n");
 
-    if(request->hCacheFile) {
+    if(request->hCacheFile)
         CloseHandle(request->hCacheFile);
-        DeleteFileW(request->cacheFile);
-    }
-    heap_free(request->cacheFile);
+    if(request->req_file)
+        req_file_release(request->req_file);
 
     request->read_section.DebugInfo->Spare[0] = 0;
     DeleteCriticalSection( &request->read_section );
@@ -1917,9 +1909,9 @@ static void HTTPREQ_Destroy(object_header_t *hdr)
 
 static void http_release_netconn(http_request_t *req, BOOL reuse)
 {
-    TRACE("%p %p\n",req, req->netconn);
+    TRACE("%p %p %x\n",req, req->netconn, reuse);
 
-    if(!req->netconn)
+    if(!is_valid_netconn(req->netconn))
         return;
 
 #ifndef __REACTOS__
@@ -1965,8 +1957,7 @@ static void http_release_netconn(http_request_t *req, BOOL reuse)
     INTERNET_SendCallback(&req->hdr, req->hdr.dwContext,
                           INTERNET_STATUS_CLOSING_CONNECTION, 0, 0);
 
-    free_netconn(req->netconn);
-    req->netconn = NULL;
+    close_netconn(req->netconn);
 
     INTERNET_SendCallback(&req->hdr, req->hdr.dwContext,
                           INTERNET_STATUS_CONNECTION_CLOSED, 0, 0);
@@ -2069,7 +2060,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 && req->netconn->secure)
+        if (is_valid_netconn(req->netconn) && req->netconn->secure)
             info->Flags |= IDSI_FLAG_SECURE;
 
         return ERROR_SUCCESS;
@@ -2086,7 +2077,7 @@ static DWORD HTTPREQ_QueryOption(object_header_t *hdr, DWORD option, void *buffe
             return ERROR_INSUFFICIENT_BUFFER;
 
         *size = sizeof(DWORD);
-        flags = req->netconn ? req->netconn->security_flags : req->security_flags | req->server->security_flags;
+        flags = is_valid_netconn(req->netconn) ? req->netconn->security_flags : req->security_flags | req->server->security_flags;
         *(DWORD *)buffer = flags;
 
         TRACE("INTERNET_OPTION_SECURITY_FLAGS %x\n", flags);
@@ -2170,25 +2161,25 @@ static DWORD HTTPREQ_QueryOption(object_header_t *hdr, DWORD option, void *buffe
 
         TRACE("INTERNET_OPTION_DATAFILE_NAME\n");
 
-        if(!req->cacheFile) {
+        if(!req->req_file) {
             *size = 0;
             return ERROR_INTERNET_ITEM_NOT_FOUND;
         }
 
         if(unicode) {
-            req_size = (lstrlenW(req->cacheFile)+1) * sizeof(WCHAR);
+            req_size = (lstrlenW(req->req_file->file_name)+1) * sizeof(WCHAR);
             if(*size < req_size)
                 return ERROR_INSUFFICIENT_BUFFER;
 
             *size = req_size;
-            memcpy(buffer, req->cacheFile, *size);
+            memcpy(buffer, req->req_file->file_name, *size);
             return ERROR_SUCCESS;
         }else {
-            req_size = WideCharToMultiByte(CP_ACP, 0, req->cacheFile, -1, NULL, 0, NULL, NULL);
+            req_size = WideCharToMultiByte(CP_ACP, 0, req->req_file->file_name, -1, NULL, 0, NULL, NULL);
             if (req_size > *size)
                 return ERROR_INSUFFICIENT_BUFFER;
 
-            *size = WideCharToMultiByte(CP_ACP, 0, req->cacheFile,
+            *size = WideCharToMultiByte(CP_ACP, 0, req->req_file->file_name,
                     -1, buffer, *size, NULL, NULL);
             return ERROR_SUCCESS;
         }
@@ -2291,7 +2282,7 @@ static DWORD HTTPREQ_SetOption(object_header_t *hdr, DWORD option, void *buffer,
         TRACE("INTERNET_OPTION_SECURITY_FLAGS %08x\n", flags);
         flags &= SECURITY_SET_MASK;
         req->security_flags |= flags;
-        if(req->netconn)
+        if(is_valid_netconn(req->netconn))
             req->netconn->security_flags |= flags;
         return ERROR_SUCCESS;
     }
@@ -2352,12 +2343,17 @@ static void commit_cache_entry(http_request_t *req)
     if(HTTP_GetRequestURL(req, url)) {
         WCHAR *header;
         DWORD header_len;
+        BOOL res;
 
         header = build_response_header(req, TRUE);
         header_len = (header ? strlenW(header) : 0);
-        CommitUrlCacheEntryW(url, req->cacheFile, req->expires,
+        res = CommitUrlCacheEntryW(url, req->req_file->file_name, req->expires,
                 req->last_modified, NORMAL_CACHE_ENTRY,
                 header, header_len, NULL, 0);
+        if(res)
+            req->req_file->is_committed = TRUE;
+        else
+            WARN("CommitUrlCacheEntry failed: %u\n", GetLastError());
         heap_free(header);
     }
 }
@@ -2372,9 +2368,14 @@ static void create_cache_entry(http_request_t *req)
     BOOL b = TRUE;
 
     /* FIXME: We should free previous cache file earlier */
-    heap_free(req->cacheFile);
-    CloseHandle(req->hCacheFile);
-    req->hCacheFile = NULL;
+    if(req->req_file) {
+        req_file_release(req->req_file);
+        req->req_file = NULL;
+    }
+    if(req->hCacheFile) {
+        CloseHandle(req->hCacheFile);
+        req->hCacheFile = NULL;
+    }
 
     if(req->hdr.dwFlags & INTERNET_FLAG_NO_CACHE_WRITE)
         b = FALSE;
@@ -2426,8 +2427,9 @@ static void create_cache_entry(http_request_t *req)
         return;
     }
 
-    req->cacheFile = heap_strdupW(file_name);
-    req->hCacheFile = CreateFileW(req->cacheFile, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
+    create_req_file(file_name, &req->req_file);
+
+    req->hCacheFile = CreateFileW(file_name, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
               NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
     if(req->hCacheFile == INVALID_HANDLE_VALUE) {
         WARN("Could not create file: %u\n", GetLastError());
@@ -2464,7 +2466,7 @@ static DWORD read_more_data( http_request_t *req, int maxlen )
     if (maxlen == -1) maxlen = sizeof(req->read_buf);
 
     res = NETCON_recv( req->netconn, req->read_buf + req->read_size,
-                       maxlen - req->read_size, 0, &len );
+                       maxlen - req->read_size, BLOCKING_ALLOW, &len );
     if(res == ERROR_SUCCESS)
         req->read_size += len;
 
@@ -2533,11 +2535,11 @@ static BOOL end_of_read_data( http_request_t *req )
     return !req->read_size && req->data_stream->vtbl->end_of_data(req->data_stream, req);
 }
 
-static DWORD read_http_stream(http_request_t *req, BYTE *buf, DWORD size, DWORD *read, read_mode_t read_mode)
+static DWORD read_http_stream(http_request_t *req, BYTE *buf, DWORD size, DWORD *read, blocking_mode_t blocking_mode)
 {
     DWORD res;
 
-    res = req->data_stream->vtbl->read(req->data_stream, req, buf, size, read, read_mode);
+    res = req->data_stream->vtbl->read(req->data_stream, req, buf, size, read, blocking_mode);
     assert(*read <= size);
 
     if(req->hCacheFile) {
@@ -2558,7 +2560,7 @@ static DWORD read_http_stream(http_request_t *req, BYTE *buf, DWORD size, DWORD
 }
 
 /* fetch some more data into the read buffer (the read section must be held) */
-static DWORD refill_read_buffer(http_request_t *req, read_mode_t read_mode, DWORD *read_bytes)
+static DWORD refill_read_buffer(http_request_t *req, blocking_mode_t blocking_mode, DWORD *read_bytes)
 {
     DWORD res, read=0;
 
@@ -2572,7 +2574,7 @@ static DWORD refill_read_buffer(http_request_t *req, read_mode_t read_mode, DWOR
     }
 
     res = read_http_stream(req, req->read_buf+req->read_size, sizeof(req->read_buf) - req->read_size,
-            &read, read_mode);
+            &read, blocking_mode);
     req->read_size += read;
 
     TRACE("read %u bytes, read_size %u\n", read, req->read_size);
@@ -2592,7 +2594,7 @@ static DWORD netconn_get_avail_data(data_stream_t *stream, http_request_t *req)
     netconn_stream_t *netconn_stream = (netconn_stream_t*)stream;
     DWORD avail = 0;
 
-    if(req->netconn)
+    if(is_valid_netconn(req->netconn))
         NETCON_query_data_available(req->netconn, &avail);
     return netconn_stream->content_length == ~0u
         ? avail
@@ -2602,11 +2604,11 @@ static DWORD netconn_get_avail_data(data_stream_t *stream, http_request_t *req)
 static BOOL netconn_end_of_data(data_stream_t *stream, http_request_t *req)
 {
     netconn_stream_t *netconn_stream = (netconn_stream_t*)stream;
-    return netconn_stream->content_read == netconn_stream->content_length || !req->netconn;
+    return netconn_stream->content_read == netconn_stream->content_length || !is_valid_netconn(req->netconn);
 }
 
 static DWORD netconn_read(data_stream_t *stream, http_request_t *req, BYTE *buf, DWORD size,
-        DWORD *read, read_mode_t read_mode)
+        DWORD *read, blocking_mode_t blocking_mode)
 {
     netconn_stream_t *netconn_stream = (netconn_stream_t*)stream;
     DWORD res = ERROR_SUCCESS;
@@ -2614,17 +2616,16 @@ static DWORD netconn_read(data_stream_t *stream, http_request_t *req, BYTE *buf,
 
     size = min(size, netconn_stream->content_length-netconn_stream->content_read);
 
-    if(read_mode == READMODE_NOBLOCK) {
-        DWORD avail = netconn_get_avail_data(stream, req);
-        if (size > avail)
-            size = avail;
-    }
-
-    if(size && req->netconn) {
-        if((res = NETCON_recv(req->netconn, buf, size, read_mode == READMODE_SYNC ? MSG_WAITALL : 0, &len)))
+    if(size && is_valid_netconn(req->netconn)) {
+        if((res = NETCON_recv(req->netconn, buf, size, blocking_mode, &len))) {
             len = 0;
-        if(!len)
+            if(blocking_mode == BLOCKING_DISALLOW && res == WSAEWOULDBLOCK)
+                res = ERROR_SUCCESS;
+            else
+                netconn_stream->content_length = netconn_stream->content_read;
+        }else if(!len) {
             netconn_stream->content_length = netconn_stream->content_read;
+        }
     }
 
     netconn_stream->content_read += *read = len;
@@ -2636,18 +2637,13 @@ static BOOL netconn_drain_content(data_stream_t *stream, http_request_t *req)
 {
     netconn_stream_t *netconn_stream = (netconn_stream_t*)stream;
     BYTE buf[1024];
-    DWORD avail;
     int len;
 
     if(netconn_end_of_data(stream, req))
         return TRUE;
 
     do {
-        avail = netconn_get_avail_data(stream, req);
-        if(!avail)
-            return FALSE;
-
-        if(NETCON_recv(req->netconn, buf, min(avail, sizeof(buf)), 0, &len) != ERROR_SUCCESS)
+        if(NETCON_recv(req->netconn, buf, sizeof(buf), BLOCKING_DISALLOW, &len) != ERROR_SUCCESS)
             return FALSE;
 
         netconn_stream->content_read += len;
@@ -2674,6 +2670,8 @@ static DWORD read_more_chunked_data(chunked_stream_t *stream, http_request_t *re
     DWORD res;
     int len;
 
+    assert(!stream->end_of_data);
+
     if (stream->buf_pos)
     {
         /* move existing data to the start of the buffer */
@@ -2685,7 +2683,7 @@ static DWORD read_more_chunked_data(chunked_stream_t *stream, http_request_t *re
     if (maxlen == -1) maxlen = sizeof(stream->buf);
 
     res = NETCON_recv( req->netconn, stream->buf + stream->buf_size,
-                       maxlen - stream->buf_size, 0, &len );
+                       maxlen - stream->buf_size, BLOCKING_ALLOW, &len );
     if(res == ERROR_SUCCESS)
         stream->buf_size += len;
 
@@ -2721,10 +2719,14 @@ static DWORD discard_chunked_eol(chunked_stream_t *stream, http_request_t *req)
 /* read the size of the next chunk (the read section must be held) */
 static DWORD start_next_chunk(chunked_stream_t *stream, http_request_t *req)
 {
-    /* TODOO */
     DWORD chunk_size = 0, res;
 
-    if(stream->chunk_size != ~0u && (res = discard_chunked_eol(stream, req)) != ERROR_SUCCESS)
+    assert(!stream->chunk_size || stream->chunk_size == ~0u);
+
+    if (stream->end_of_data) return ERROR_SUCCESS;
+
+    /* read terminator for the previous chunk */
+    if(!stream->chunk_size && (res = discard_chunked_eol(stream, req)) != ERROR_SUCCESS)
         return res;
 
     for (;;)
@@ -2739,7 +2741,10 @@ static DWORD start_next_chunk(chunked_stream_t *stream, http_request_t *req)
             {
                 TRACE( "reading %u byte chunk\n", chunk_size );
                 stream->chunk_size = chunk_size;
-                req->contentLength += chunk_size;
+                if (req->contentLength == ~0u) req->contentLength = chunk_size;
+                else req->contentLength += chunk_size;
+
+                if (!chunk_size) stream->end_of_data = TRUE;
                 return discard_chunked_eol(stream, req);
             }
             remove_chunked_data(stream, 1);
@@ -2762,27 +2767,27 @@ static DWORD chunked_get_avail_data(data_stream_t *stream, http_request_t *req)
 static BOOL chunked_end_of_data(data_stream_t *stream, http_request_t *req)
 {
     chunked_stream_t *chunked_stream = (chunked_stream_t*)stream;
-    return !chunked_stream->chunk_size;
+    return chunked_stream->end_of_data;
 }
 
 static DWORD chunked_read(data_stream_t *stream, http_request_t *req, BYTE *buf, DWORD size,
-        DWORD *read, read_mode_t read_mode)
+        DWORD *read, blocking_mode_t blocking_mode)
 {
     chunked_stream_t *chunked_stream = (chunked_stream_t*)stream;
     DWORD read_bytes = 0, ret_read = 0, res = ERROR_SUCCESS;
 
-    if(chunked_stream->chunk_size == ~0u) {
+    if(!chunked_stream->chunk_size || chunked_stream->chunk_size == ~0u) {
         res = start_next_chunk(chunked_stream, req);
         if(res != ERROR_SUCCESS)
             return res;
     }
 
-    while(size && chunked_stream->chunk_size) {
+    while(size && chunked_stream->chunk_size && !chunked_stream->end_of_data) {
         if(chunked_stream->buf_size) {
             read_bytes = min(size, min(chunked_stream->buf_size, chunked_stream->chunk_size));
 
             /* this could block */
-            if(read_mode == READMODE_NOBLOCK && read_bytes == chunked_stream->chunk_size)
+            if(blocking_mode == BLOCKING_DISALLOW && read_bytes == chunked_stream->chunk_size)
                 break;
 
             memcpy(buf+ret_read, chunked_stream->buf+chunked_stream->buf_pos, read_bytes);
@@ -2790,10 +2795,10 @@ static DWORD chunked_read(data_stream_t *stream, http_request_t *req, BYTE *buf,
         }else {
             read_bytes = min(size, chunked_stream->chunk_size);
 
-            if(read_mode == READMODE_NOBLOCK) {
+            if(blocking_mode == BLOCKING_DISALLOW) {
                 DWORD avail;
 
-                if(!req->netconn || !NETCON_query_data_available(req->netconn, &avail) || !avail)
+                if(!is_valid_netconn(req->netconn) || !NETCON_query_data_available(req->netconn, &avail) || !avail)
                     break;
                 if(read_bytes > avail)
                     read_bytes = avail;
@@ -2803,7 +2808,7 @@ static DWORD chunked_read(data_stream_t *stream, http_request_t *req, BYTE *buf,
                     break;
             }
 
-            res = NETCON_recv(req->netconn, (char *)buf+ret_read, read_bytes, 0, (int*)&read_bytes);
+            res = NETCON_recv(req->netconn, (char *)buf+ret_read, read_bytes, BLOCKING_ALLOW, (int*)&read_bytes);
             if(res != ERROR_SUCCESS)
                 break;
         }
@@ -2811,15 +2816,15 @@ static DWORD chunked_read(data_stream_t *stream, http_request_t *req, BYTE *buf,
         chunked_stream->chunk_size -= read_bytes;
         size -= read_bytes;
         ret_read += read_bytes;
-        if(!chunked_stream->chunk_size) {
-            assert(read_mode != READMODE_NOBLOCK);
+        if(size && !chunked_stream->chunk_size) {
+            assert(blocking_mode != BLOCKING_DISALLOW);
             res = start_next_chunk(chunked_stream, req);
             if(res != ERROR_SUCCESS)
                 break;
         }
 
-        if(read_mode == READMODE_ASYNC)
-            read_mode = READMODE_NOBLOCK;
+        if(blocking_mode == BLOCKING_ALLOW)
+            blocking_mode = BLOCKING_DISALLOW;
     }
 
     TRACE("read %u bytes\n", ret_read);
@@ -2831,8 +2836,8 @@ static BOOL chunked_drain_content(data_stream_t *stream, http_request_t *req)
 {
     chunked_stream_t *chunked_stream = (chunked_stream_t*)stream;
 
-    /* FIXME: we can do better */
-    return !chunked_stream->chunk_size;
+    remove_chunked_data(chunked_stream, chunked_stream->buf_size);
+    return chunked_stream->end_of_data;
 }
 
 static void chunked_destroy(data_stream_t *stream)
@@ -2881,6 +2886,7 @@ static DWORD set_content_length(http_request_t *request)
         chunked_stream->data_stream.vtbl = &chunked_stream_vtbl;
         chunked_stream->buf_size = chunked_stream->buf_pos = 0;
         chunked_stream->chunk_size = ~0u;
+        chunked_stream->end_of_data = FALSE;
 
         if(request->read_size) {
             memcpy(chunked_stream->buf, request->read_buf+request->read_pos, request->read_size);
@@ -2896,12 +2902,19 @@ static DWORD set_content_length(http_request_t *request)
     if(request->decoding) {
         int encoding_idx;
 
+        static const WCHAR deflateW[] = {'d','e','f','l','a','t','e',0};
         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)) {
-            HTTP_DeleteCustomHeader(request, encoding_idx);
-            return init_gzip_stream(request);
+        if(encoding_idx != -1) {
+            if(!strcmpiW(request->custHeaders[encoding_idx].lpszValue, gzipW)) {
+                HTTP_DeleteCustomHeader(request, encoding_idx);
+                return init_gzip_stream(request, TRUE);
+            }
+            if(!strcmpiW(request->custHeaders[encoding_idx].lpszValue, deflateW)) {
+                HTTP_DeleteCustomHeader(request, encoding_idx);
+                return init_gzip_stream(request, FALSE);
+            }
         }
     }
 
@@ -2922,20 +2935,20 @@ static void send_request_complete(http_request_t *req, DWORD_PTR result, DWORD e
 static void HTTP_ReceiveRequestData(http_request_t *req, BOOL first_notif, DWORD *ret_size)
 {
     DWORD res, read = 0, avail = 0;
-    read_mode_t mode;
+    blocking_mode_t mode;
 
     TRACE("%p\n", req);
 
     EnterCriticalSection( &req->read_section );
 
-    mode = first_notif && req->read_size ? READMODE_NOBLOCK : READMODE_ASYNC;
+    mode = first_notif && req->read_size ? BLOCKING_DISALLOW : BLOCKING_ALLOW;
     res = refill_read_buffer(req, mode, &read);
     if(res == ERROR_SUCCESS)
         avail = get_avail_data(req);
 
     LeaveCriticalSection( &req->read_section );
 
-    if(res != ERROR_SUCCESS || (mode != READMODE_NOBLOCK && !read)) {
+    if(res != ERROR_SUCCESS || (mode != BLOCKING_DISALLOW && !read)) {
         WARN("res %u read %u, closing connection\n", res, read);
         http_release_netconn(req, FALSE);
     }
@@ -2957,10 +2970,10 @@ static void HTTP_ReceiveRequestData(http_request_t *req, BOOL first_notif, DWORD
 static DWORD HTTPREQ_Read(http_request_t *req, void *buffer, DWORD size, DWORD *read, BOOL sync)
 {
     DWORD current_read = 0, ret_read = 0;
-    read_mode_t read_mode;
+    blocking_mode_t blocking_mode;
     DWORD res = ERROR_SUCCESS;
 
-    read_mode = req->session->appInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC ? READMODE_ASYNC : READMODE_SYNC;
+    blocking_mode = req->session->appInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC ? BLOCKING_ALLOW : BLOCKING_WAITALL;
 
     EnterCriticalSection( &req->read_section );
 
@@ -2969,12 +2982,12 @@ static DWORD HTTPREQ_Read(http_request_t *req, void *buffer, DWORD size, DWORD *
         memcpy(buffer, req->read_buf+req->read_pos, ret_read);
         req->read_size -= ret_read;
         req->read_pos += ret_read;
-        if(read_mode == READMODE_ASYNC)
-            read_mode = READMODE_NOBLOCK;
+        if(blocking_mode == BLOCKING_ALLOW)
+            blocking_mode = BLOCKING_DISALLOW;
     }
 
     if(ret_read < size) {
-        res = read_http_stream(req, (BYTE*)buffer+ret_read, size-ret_read, &current_read, read_mode);
+        res = read_http_stream(req, (BYTE*)buffer+ret_read, size-ret_read, &current_read, blocking_mode);
         ret_read += current_read;
     }
 
@@ -2993,7 +3006,7 @@ static BOOL drain_content(http_request_t *req, BOOL blocking)
 {
     BOOL ret;
 
-    if(!req->netconn || req->contentLength == -1)
+    if(!is_valid_netconn(req->netconn) || req->contentLength == -1)
         return FALSE;
 
     if(!strcmpW(req->verb, szHEAD))
@@ -3181,7 +3194,7 @@ static DWORD HTTPREQ_QueryDataAvailable(object_header_t *hdr, DWORD *available,
         /* never wait, if we can't enter the section we queue an async request right away */
         if (TryEnterCriticalSection( &req->read_section ))
         {
-            refill_read_buffer(req, READMODE_NOBLOCK, NULL);
+            refill_read_buffer(req, BLOCKING_DISALLOW, NULL);
             if ((*available = get_avail_data( req ))) goto done;
             if (end_of_read_data( req )) goto done;
             LeaveCriticalSection( &req->read_section );
@@ -3197,7 +3210,7 @@ static DWORD HTTPREQ_QueryDataAvailable(object_header_t *hdr, DWORD *available,
 
     if (!(*available = get_avail_data( req )) && !end_of_read_data( req ))
     {
-        refill_read_buffer( req, READMODE_ASYNC, NULL );
+        refill_read_buffer( req, BLOCKING_ALLOW, NULL );
         *available = get_avail_data( req );
     }
 
@@ -3208,6 +3221,21 @@ done:
     return ERROR_SUCCESS;
 }
 
+static DWORD HTTPREQ_LockRequestFile(object_header_t *hdr, req_file_t **ret)
+{
+    http_request_t *req = (http_request_t*)hdr;
+
+    TRACE("(%p)\n", req);
+
+    if(!req->req_file) {
+        WARN("No cache file name available\n");
+        return ERROR_FILE_NOT_FOUND;
+    }
+
+    *ret = req_file_addref(req->req_file);
+    return ERROR_SUCCESS;
+}
+
 static const object_vtbl_t HTTPREQVtbl = {
     HTTPREQ_Destroy,
     HTTPREQ_CloseConnection,
@@ -3217,7 +3245,8 @@ static const object_vtbl_t HTTPREQVtbl = {
     HTTPREQ_ReadFileEx,
     HTTPREQ_WriteFile,
     HTTPREQ_QueryDataAvailable,
-    NULL
+    NULL,
+    HTTPREQ_LockRequestFile
 };
 
 /***********************************************************************
@@ -3237,7 +3266,7 @@ static DWORD HTTP_HttpOpenRequestW(http_session_t *session,
 {
     appinfo_t *hIC = session->appInfo;
     http_request_t *request;
-    DWORD len, res = ERROR_SUCCESS;
+    DWORD len;
 
     TRACE("-->\n");
 
@@ -3326,13 +3355,7 @@ static DWORD HTTP_HttpOpenRequestW(http_session_t *session,
                           INTERNET_STATUS_HANDLE_CREATED, &request->hdr.hInternet,
                           sizeof(HINTERNET));
 
-    TRACE("<-- %u (%p)\n", res, request);
-
-    if(res != ERROR_SUCCESS) {
-        WININET_Release( &request->hdr );
-        *ret = NULL;
-        return res;
-    }
+    TRACE("<-- (%p)\n", request);
 
     *ret = request->hdr.hInternet;
     return ERROR_SUCCESS;
@@ -3999,8 +4022,8 @@ static DWORD HTTP_HandleRedirect(http_request_t *request, LPCWSTR lpszUrl)
         WCHAR userName[INTERNET_MAX_USER_NAME_LENGTH];
         BOOL custom_port = FALSE;
 
-        static WCHAR httpW[] = {'h','t','t','p',0};
-        static WCHAR httpsW[] = {'h','t','t','p','s',0};
+        static const WCHAR httpW[] = {'h','t','t','p',0};
+        static const WCHAR httpsW[] = {'h','t','t','p','s',0};
 
         userName[0] = 0;
         hostName[0] = 0;
@@ -4726,9 +4749,22 @@ static DWORD open_http_connection(http_request_t *request, BOOL *reusing)
     netconn_t *netconn = NULL;
     DWORD res;
 
-    assert(!request->netconn);
     reset_data_stream(request);
 
+    if (request->netconn)
+    {
+        if (is_valid_netconn(request->netconn) && NETCON_is_alive(request->netconn))
+        {
+            *reusing = TRUE;
+            return ERROR_SUCCESS;
+        }
+        else
+        {
+            free_netconn(request->netconn);
+            request->netconn = NULL;
+        }
+    }
+
     res = HTTP_ResolveName(request);
     if(res != ERROR_SUCCESS)
         return res;
@@ -4739,7 +4775,7 @@ static DWORD open_http_connection(http_request_t *request, BOOL *reusing)
         netconn = LIST_ENTRY(list_head(&request->server->conn_pool), netconn_t, pool_entry);
         list_remove(&netconn->pool_entry);
 
-        if(NETCON_is_alive(netconn))
+        if(is_valid_netconn(netconn) && NETCON_is_alive(netconn))
             break;
 
         TRACE("connection %p closed during idle\n", netconn);
@@ -4875,7 +4911,6 @@ static DWORD HTTP_HttpSendRequestW(http_request_t *request, LPCWSTR lpszHeaders,
         char *ascii_req;
 
         loop_next = FALSE;
-        reusing_connection = request->netconn != NULL;
 
         if(redirected) {
             request->contentLength = ~0u;
@@ -4911,7 +4946,8 @@ static DWORD HTTP_HttpSendRequestW(http_request_t *request, LPCWSTR lpszHeaders,
  
         TRACE("Request header -> %s\n", debugstr_w(requestString) );
 
-        if (!reusing_connection && (res = open_http_connection(request, &reusing_connection)) != ERROR_SUCCESS)
+        res = open_http_connection(request, &reusing_connection);
+        if (res != ERROR_SUCCESS)
             break;
 
         /* send the request as ASCII, tack on the optional data */
@@ -5146,7 +5182,7 @@ static DWORD HTTP_HttpEndRequestW(http_request_t *request, DWORD dwFlags, DWORD_
     INT responseLen;
     DWORD res = ERROR_SUCCESS;
 
-    if(!request->netconn) {
+    if(!is_valid_netconn(request->netconn)) {
         WARN("Not connected\n");
         send_request_complete(request, 0, ERROR_INTERNET_OPERATION_CANCELLED);
         return ERROR_INTERNET_OPERATION_CANCELLED;
@@ -5818,7 +5854,7 @@ static DWORD HTTP_GetResponseHeaders(http_request_t *request, INT *len)
 
     TRACE("-->\n");
 
-    if(!request->netconn)
+    if(!is_valid_netconn(request->netconn))
         goto lend;
 
     /* clear old response headers (eg. from a redirect response) */
index 84adb26..b78e44f 100644 (file)
@@ -1177,7 +1177,7 @@ BOOL WINAPI InternetGetConnectedStateExW(LPDWORD lpdwStatus, LPWSTR lpszConnecti
         WARN("always returning LAN connection.\n");
         *lpdwStatus = INTERNET_CONNECTION_LAN;
     }
-    return LoadStringW(WININET_hModule, IDS_LANCONNECTION, lpszConnectionName, dwNameLen);
+    return LoadStringW(WININET_hModule, IDS_LANCONNECTION, lpszConnectionName, dwNameLen) > 0;
 }
 
 
@@ -1723,7 +1723,7 @@ BOOL WINAPI InternetCrackUrlW(LPCWSTR lpszUrl_orig, DWORD dwUrlLength_orig, DWOR
 
     if(!found_colon){
         SetLastError(ERROR_INTERNET_UNRECOGNIZED_SCHEME);
-        return 0;
+        return FALSE;
     }
 
     lpUC->nScheme = INTERNET_SCHEME_UNKNOWN;
@@ -2870,13 +2870,17 @@ BOOL WINAPI InternetSetOptionW(HINTERNET hInternet, DWORD dwOption,
                 }
                 break;
 
+            case INTERNET_PER_CONN_PROXY_BYPASS:
+                heap_free(pi.proxyBypass);
+                pi.proxyBypass = heap_strdupW(option->Value.pszValue);
+                break;
+
             case INTERNET_PER_CONN_AUTOCONFIG_URL:
             case INTERNET_PER_CONN_AUTODISCOVERY_FLAGS:
             case INTERNET_PER_CONN_AUTOCONFIG_SECONDARY_URL:
             case INTERNET_PER_CONN_AUTOCONFIG_RELOAD_DELAY_MINS:
             case INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_TIME:
             case INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_URL:
-            case INTERNET_PER_CONN_PROXY_BYPASS:
                 FIXME("Unhandled dwOption %d\n", option->dwOption);
                 break;
 
@@ -3863,21 +3867,84 @@ BOOL WINAPI InternetQueryDataAvailable( HINTERNET hFile,
     return res == ERROR_SUCCESS;
 }
 
+DWORD create_req_file(const WCHAR *file_name, req_file_t **ret)
+{
+    req_file_t *req_file;
+
+    req_file = heap_alloc_zero(sizeof(*req_file));
+    if(!req_file)
+        return ERROR_NOT_ENOUGH_MEMORY;
+
+    req_file->ref = 1;
+
+    req_file->file_name = heap_strdupW(file_name);
+    if(!req_file->file_name) {
+        heap_free(req_file);
+        return ERROR_NOT_ENOUGH_MEMORY;
+    }
+
+    req_file->file_handle = CreateFileW(req_file->file_name, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
+              NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+    if(req_file->file_handle == INVALID_HANDLE_VALUE) {
+        req_file_release(req_file);
+        return GetLastError();
+    }
+
+    *ret = req_file;
+    return ERROR_SUCCESS;
+}
+
+void req_file_release(req_file_t *req_file)
+{
+    if(InterlockedDecrement(&req_file->ref))
+        return;
+
+    if(!req_file->is_committed)
+        DeleteFileW(req_file->file_name);
+    if(req_file->file_handle && req_file->file_handle != INVALID_HANDLE_VALUE)
+        CloseHandle(req_file->file_handle);
+    heap_free(req_file->file_name);
+    heap_free(req_file);
+}
 
 /***********************************************************************
  *      InternetLockRequestFile (WININET.@)
  */
-BOOL WINAPI InternetLockRequestFile( HINTERNET hInternet, HANDLE
-*lphLockReqHandle)
+BOOL WINAPI InternetLockRequestFile(HINTERNET hInternet, HANDLE *lphLockReqHandle)
 {
-    FIXME("STUB\n");
-    return FALSE;
+    req_file_t *req_file = NULL;
+    object_header_t *hdr;
+    DWORD res;
+
+    TRACE("(%p %p)\n", hInternet, lphLockReqHandle);
+
+    hdr = get_handle_object(hInternet);
+    if (!hdr) {
+        SetLastError(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+
+    if(hdr->vtbl->LockRequestFile) {
+        res = hdr->vtbl->LockRequestFile(hdr, &req_file);
+    }else {
+        WARN("wrong handle\n");
+        res = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
+    }
+
+    WININET_Release(hdr);
+
+    *lphLockReqHandle = req_file;
+    if(res != ERROR_SUCCESS)
+        SetLastError(res);
+    return res == ERROR_SUCCESS;
 }
 
-BOOL WINAPI InternetUnlockRequestFile( HANDLE hLockHandle)
+BOOL WINAPI InternetUnlockRequestFile(HANDLE hLockHandle)
 {
-    FIXME("STUB\n");
-    return FALSE;
+    TRACE("(%p)\n", hLockHandle);
+
+    req_file_release(hLockHandle);
+    return TRUE;
 }
 
 
@@ -4526,7 +4593,7 @@ BOOL WINAPI ResumeSuspendedDownload( HINTERNET hInternet, DWORD dwError )
 BOOL WINAPI InternetQueryFortezzaStatus(DWORD *a, DWORD_PTR b)
 {
     FIXME("(%p, %08lx) stub\n", a, b);
-    return 0;
+    return FALSE;
 }
 
 DWORD WINAPI ShowClientAuthCerts(HWND parent)
index 85d4652..08a0ccf 100644 (file)
@@ -146,6 +146,9 @@ typedef struct
     struct list pool_entry;
 } netconn_t;
 
+BOOL is_valid_netconn(netconn_t *) DECLSPEC_HIDDEN;
+void close_netconn(netconn_t *) DECLSPEC_HIDDEN;
+
 static inline void * __WINE_ALLOC_SIZE(1) heap_alloc(size_t len)
 {
     return HeapAlloc(GetProcessHeap(), 0, len);
@@ -285,6 +288,14 @@ typedef enum
 #define INET_OPENURL 0x0001
 #define INET_CALLBACKW 0x0002
 
+typedef struct
+{
+    LONG ref;
+    HANDLE file_handle;
+    WCHAR *file_name;
+    BOOL is_committed;
+} req_file_t;
+
 typedef struct _object_header_t object_header_t;
 
 typedef struct {
@@ -297,6 +308,7 @@ typedef struct {
     DWORD (*WriteFile)(object_header_t*,const void*,DWORD,DWORD*);
     DWORD (*QueryDataAvailable)(object_header_t*,DWORD*,DWORD,DWORD_PTR);
     DWORD (*FindNextFileW)(object_header_t*,void*);
+    DWORD (*LockRequestFile)(object_header_t*,req_file_t**);
 } object_vtbl_t;
 
 #define INTERNET_HANDLE_IN_USE 1
@@ -318,7 +330,6 @@ struct _object_header_t
     struct list children;
 };
 
-
 typedef struct
 {
     object_header_t hdr;
@@ -395,7 +406,7 @@ typedef struct
     DWORD nCustHeaders;
     FILETIME last_modified;
     HANDLE hCacheFile;
-    LPWSTR cacheFile;
+    req_file_t *req_file;
     FILETIME expires;
     struct HttpAuthInfo *authInfo;
     struct HttpAuthInfo *proxyAuthInfo;
@@ -465,14 +476,19 @@ VOID INTERNET_SendCallback(object_header_t *hdr, DWORD_PTR dwContext,
                            DWORD dwStatusInfoLength) DECLSPEC_HIDDEN;
 BOOL INTERNET_FindProxyForProtocol(LPCWSTR szProxy, LPCWSTR proto, WCHAR *foundProxy, DWORD *foundProxyLen) DECLSPEC_HIDDEN;
 
+typedef enum {
+    BLOCKING_ALLOW,
+    BLOCKING_DISALLOW,
+    BLOCKING_WAITALL
+} blocking_mode_t;
+
 DWORD create_netconn(BOOL,server_t*,DWORD,BOOL,DWORD,netconn_t**) DECLSPEC_HIDDEN;
 void free_netconn(netconn_t*) DECLSPEC_HIDDEN;
 void NETCON_unload(void) DECLSPEC_HIDDEN;
 DWORD NETCON_secure_connect(netconn_t*,server_t*) DECLSPEC_HIDDEN;
 DWORD NETCON_send(netconn_t *connection, const void *msg, size_t len, int flags,
                int *sent /* out */) DECLSPEC_HIDDEN;
-DWORD NETCON_recv(netconn_t *connection, void *buf, size_t len, int flags,
-               int *recvd /* out */) DECLSPEC_HIDDEN;
+DWORD NETCON_recv(netconn_t*,void*,size_t,blocking_mode_t,int*) DECLSPEC_HIDDEN;
 BOOL NETCON_query_data_available(netconn_t *connection, DWORD *available) DECLSPEC_HIDDEN;
 BOOL NETCON_is_alive(netconn_t*) DECLSPEC_HIDDEN;
 LPCVOID NETCON_GetCert(netconn_t *connection) DECLSPEC_HIDDEN;
@@ -505,6 +521,15 @@ static inline int unix_getsockopt(int socket, int level, int option_name, void *
 
 server_t *get_server(const WCHAR*,INTERNET_PORT,BOOL,BOOL);
 
+DWORD create_req_file(const WCHAR*,req_file_t**) DECLSPEC_HIDDEN;
+void req_file_release(req_file_t*) DECLSPEC_HIDDEN;
+
+static inline req_file_t *req_file_addref(req_file_t *req_file)
+{
+    InterlockedIncrement(&req_file->ref);
+    return req_file;
+}
+
 BOOL init_urlcache(void) DECLSPEC_HIDDEN;
 void free_urlcache(void) DECLSPEC_HIDDEN;
 void free_cookie(void) DECLSPEC_HIDDEN;
index d7c6c61..f58c553 100644 (file)
 # include <netinet/tcp.h>
 #endif
 
+#include <errno.h>
+
 #define RESPONSE_TIMEOUT        30            /* FROM internet.c */
 
+#ifdef MSG_DONTWAIT
+#define WINE_MSG_DONTWAIT MSG_DONTWAIT
+#else
+#define WINE_MSG_DONTWAIT 0
+#endif
+
 /* FIXME!!!!!!
  *    This should use winsock - To use winsock the functions will have to change a bit
  *        as they are designed for unix sockets.
@@ -284,7 +292,10 @@ static DWORD create_netconn_socket(server_t *server, netconn_t *netconn, DWORD t
             }
         }
         if(result == -1)
+        {
             closesocket(netconn->socket);
+            netconn->socket = -1;
+        }
         else {
             flag = 0;
             ioctlsocket(netconn->socket, FIONBIO, &flag);
@@ -316,6 +327,7 @@ DWORD create_netconn(BOOL useSSL, server_t *server, DWORD security_flags, BOOL m
     netconn->security_flags = security_flags | server->security_flags;
     netconn->mask_errors = mask_errors;
     list_init(&netconn->pool_entry);
+    SecInvalidateHandle(&netconn->ssl_ctx);
 
     result = create_netconn_socket(server, netconn, timeout);
     if (result != ERROR_SUCCESS) {
@@ -329,6 +341,17 @@ DWORD create_netconn(BOOL useSSL, server_t *server, DWORD security_flags, BOOL m
     return result;
 }
 
+BOOL is_valid_netconn(netconn_t *netconn)
+{
+    return netconn && netconn->socket != -1;
+}
+
+void close_netconn(netconn_t *netconn)
+{
+    closesocket(netconn->socket);
+    netconn->socket = -1;
+}
+
 void free_netconn(netconn_t *netconn)
 {
     server_release(netconn->server);
@@ -343,10 +366,10 @@ void free_netconn(netconn_t *netconn)
         heap_free(netconn->extra_buf);
         netconn->extra_buf = NULL;
         netconn->extra_len = 0;
-        DeleteSecurityContext(&netconn->ssl_ctx);
+        if (SecIsValidHandle(&netconn->ssl_ctx))
+            DeleteSecurityContext(&netconn->ssl_ctx);
     }
 
-    closesocket(netconn->socket);
     heap_free(netconn);
 }
 
@@ -428,6 +451,14 @@ int sock_get_error( int err )
 }
 #endif
 
+static void set_socket_blocking(int socket, blocking_mode_t mode)
+{
+#if defined(__MINGW32__) || defined (_MSC_VER)
+    ULONG arg = mode == BLOCKING_DISALLOW;
+    ioctlsocket(socket, FIONBIO, &arg);
+#endif
+}
+
 static DWORD netcon_secure_connect_setup(netconn_t *connection, BOOL compat_mode)
 {
     SecBuffer out_buf = {0, SECBUFFER_TOKEN, NULL}, in_bufs[2] = {{0, SECBUFFER_TOKEN}, {0, SECBUFFER_EMPTY}};
@@ -447,7 +478,7 @@ static DWORD netcon_secure_connect_setup(netconn_t *connection, BOOL compat_mode
         |ISC_REQ_SEQUENCE_DETECT|ISC_REQ_REPLAY_DETECT|ISC_REQ_MANUAL_CRED_VALIDATION;
 
     if(!ensure_cred_handle())
-        return FALSE;
+        return ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
 
     if(compat_mode) {
         if(!have_compat_cred_handle)
@@ -525,6 +556,10 @@ static DWORD netcon_secure_connect_setup(netconn_t *connection, BOOL compat_mode
         TRACE("InitializeSecurityContext ret %08x\n", status);
 
         if(status == SEC_E_OK) {
+            if(SecIsValidHandle(&connection->ssl_ctx))
+                DeleteSecurityContext(&connection->ssl_ctx);
+            connection->ssl_ctx = ctx;
+
             if(in_bufs[1].BufferType == SECBUFFER_EXTRA)
                 FIXME("SECBUFFER_EXTRA not supported\n");
 
@@ -556,19 +591,14 @@ static DWORD netcon_secure_connect_setup(netconn_t *connection, BOOL compat_mode
         }
     }
 
-
     if(status != SEC_E_OK || res != ERROR_SUCCESS) {
-        WARN("Failed to initialize security context failed: %08x\n", status);
+        WARN("Failed to establish SSL connection: %08x (%u)\n", status, res);
         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;
 
@@ -685,37 +715,53 @@ DWORD NETCON_send(netconn_t *connection, const void *msg, size_t len, int flags,
     }
 }
 
-static BOOL read_ssl_chunk(netconn_t *conn, void *buf, SIZE_T buf_size, SIZE_T *ret_size, BOOL *eof)
+static BOOL read_ssl_chunk(netconn_t *conn, void *buf, SIZE_T buf_size, blocking_mode_t mode, 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;
+    SSIZE_T size, buf_len = 0;
+    blocking_mode_t tmp_mode;
     int i;
     SECURITY_STATUS res;
 
     assert(conn->extra_len < ssl_buf_size);
 
+    /* BLOCKING_WAITALL is handled by caller */
+    if(mode == BLOCKING_WAITALL)
+        mode = BLOCKING_ALLOW;
+
     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;
-        }
+    }
 
+    tmp_mode = buf_len ? BLOCKING_DISALLOW : mode;
+    set_socket_blocking(conn->socket, tmp_mode);
+    size = recv(conn->socket, conn->ssl_buf+buf_len, ssl_buf_size-buf_len, tmp_mode == BLOCKING_ALLOW ? 0 : WINE_MSG_DONTWAIT);
+    if(size < 0) {
         if(!buf_len) {
-            *eof = TRUE;
-            return TRUE;
+            if(errno == EAGAIN || errno == EWOULDBLOCK) {
+                TRACE("would block\n");
+                return WSAEWOULDBLOCK;
+            }
+            WARN("recv failed\n");
+            return ERROR_INTERNET_CONNECTION_ABORTED;
         }
+    }else {
+        buf_len += size;
+    }
+
+    *ret_size = buf_len;
+
+    if(!buf_len) {
+        *eof = TRUE;
+        return ERROR_SUCCESS;
     }
 
-    *ret_size = 0;
     *eof = FALSE;
 
     do {
@@ -731,19 +777,34 @@ static BOOL read_ssl_chunk(netconn_t *conn, void *buf, SIZE_T buf_size, SIZE_T *
         case SEC_I_CONTEXT_EXPIRED:
             TRACE("context expired\n");
             *eof = TRUE;
-            return TRUE;
+            return ERROR_SUCCESS;
         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;
+            set_socket_blocking(conn->socket, mode);
+            size = recv(conn->socket, conn->ssl_buf+buf_len, ssl_buf_size-buf_len, mode == BLOCKING_ALLOW ? 0 : WINE_MSG_DONTWAIT);
+            if(size < 1) {
+                if(size < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
+                    TRACE("would block\n");
+
+                    /* FIXME: Optimize extra_buf usage. */
+                    conn->extra_buf = heap_alloc(buf_len);
+                    if(!conn->extra_buf)
+                        return ERROR_NOT_ENOUGH_MEMORY;
+
+                    conn->extra_len = buf_len;
+                    memcpy(conn->extra_buf, conn->ssl_buf, conn->extra_len);
+                    return WSAEWOULDBLOCK;
+                }
+
+                return ERROR_INTERNET_CONNECTION_ABORTED;
+            }
 
             buf_len += size;
             continue;
         default:
             WARN("failed: %08x\n", res);
-            return FALSE;
+            return ERROR_INTERNET_CONNECTION_ABORTED;
         }
     } while(res != SEC_E_OK);
 
@@ -755,7 +816,7 @@ static BOOL read_ssl_chunk(netconn_t *conn, void *buf, SIZE_T buf_size, SIZE_T *
                 assert(!conn->peek_len);
                 conn->peek_msg_mem = conn->peek_msg = heap_alloc(bufs[i].cbBuffer - size);
                 if(!conn->peek_msg)
-                    return FALSE;
+                    return ERROR_NOT_ENOUGH_MEMORY;
                 conn->peek_len = bufs[i].cbBuffer-size;
                 memcpy(conn->peek_msg, (char*)bufs[i].pvBuffer+size, conn->peek_len);
             }
@@ -768,14 +829,14 @@ static BOOL read_ssl_chunk(netconn_t *conn, void *buf, SIZE_T buf_size, SIZE_T *
         if(bufs[i].BufferType == SECBUFFER_EXTRA) {
             conn->extra_buf = heap_alloc(bufs[i].cbBuffer);
             if(!conn->extra_buf)
-                return FALSE;
+                return ERROR_NOT_ENOUGH_MEMORY;
 
             conn->extra_len = bufs[i].cbBuffer;
             memcpy(conn->extra_buf, bufs[i].pvBuffer, conn->extra_len);
         }
     }
 
-    return TRUE;
+    return ERROR_SUCCESS;
 }
 
 /******************************************************************************
@@ -783,7 +844,7 @@ static BOOL read_ssl_chunk(netconn_t *conn, void *buf, SIZE_T buf_size, SIZE_T *
  * Basically calls 'recv()' unless we should use SSL
  * number of chars received is put in *recvd
  */
-DWORD NETCON_recv(netconn_t *connection, void *buf, size_t len, int flags, int *recvd)
+DWORD NETCON_recv(netconn_t *connection, void *buf, size_t len, blocking_mode_t mode, int *recvd)
 {
     *recvd = 0;
     if (!len)
@@ -791,13 +852,28 @@ DWORD NETCON_recv(netconn_t *connection, void *buf, size_t len, int flags, int *
 
     if (!connection->secure)
     {
+        int flags = 0;
+
+        switch(mode) {
+        case BLOCKING_ALLOW:
+            break;
+        case BLOCKING_DISALLOW:
+            flags = WINE_MSG_DONTWAIT;
+            break;
+        case BLOCKING_WAITALL:
+            flags = MSG_WAITALL;
+            break;
+        }
+
+        set_socket_blocking(connection->socket, mode);
        *recvd = recv(connection->socket, buf, len, flags);
        return *recvd == -1 ? sock_get_error(errno) :  ERROR_SUCCESS;
     }
     else
     {
         SIZE_T size = 0, cread;
-        BOOL res, eof;
+        BOOL eof;
+        DWORD res;
 
         if(connection->peek_msg) {
             size = min(len, connection->peek_len);
@@ -810,18 +886,23 @@ DWORD NETCON_recv(netconn_t *connection, void *buf, size_t len, int flags, int *
                 connection->peek_msg_mem = connection->peek_msg = NULL;
             }
             /* check if we have enough data from the peek buffer */
-            if(!(flags & MSG_WAITALL) || size == len) {
+            if(mode != BLOCKING_WAITALL || size == len) {
                 *recvd = size;
                 return ERROR_SUCCESS;
             }
+
+            mode = BLOCKING_DISALLOW;
         }
 
         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;
+            res = read_ssl_chunk(connection, (BYTE*)buf+size, len-size, mode, &cread, &eof);
+            if(res != ERROR_SUCCESS) {
+                if(res == WSAEWOULDBLOCK) {
+                    if(size)
+                        res = ERROR_SUCCESS;
+                }else {
+                    WARN("read_ssl_chunk failed\n");
+                }
                 break;
             }
 
@@ -831,11 +912,11 @@ DWORD NETCON_recv(netconn_t *connection, void *buf, size_t len, int flags, int *
             }
 
             size += cread;
-        }while(!size || ((flags & MSG_WAITALL) && size < len));
+        }while(!size || (mode == BLOCKING_WAITALL && size < len));
 
         TRACE("received %ld bytes\n", size);
         *recvd = size;
-        return ERROR_SUCCESS;
+        return res;
     }
 }
 
@@ -902,9 +983,6 @@ LPCVOID NETCON_GetCert(netconn_t *connection)
     const CERT_CONTEXT *ret;
     SECURITY_STATUS res;
 
-    if (!connection->secure)
-        return NULL;
-
     res = QueryContextAttributesW(&connection->ssl_ctx, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (void*)&ret);
     return res == SEC_E_OK ? ret : NULL;
 }
index b378395..826418d 100644 (file)
@@ -141,7 +141,7 @@ BOOL GetAddress(LPCWSTR lpszServerName, INTERNET_PORT nServerPort,
     TRACE("%s\n", debugstr_w(lpszServerName));
 
     /* Validate server name first
-     * Check if there is sth. like
+     * Check if there is something like
      * pinger.macromedia.com:80
      * if yes, eliminate the :80....
      */
index a2863a1..06635bf 100644 (file)
@@ -208,7 +208,7 @@ reactos/dll/win32/windowscodecsext    # 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.17
-reactos/dll/win32/wininet             # Synced to Wine-1.7.1
+reactos/dll/win32/wininet             # Synced to Wine-1.7.17
 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