From 698bb7c11c348fc1861cd47d2cc60ea7a402f9c1 Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Sat, 26 Apr 2014 17:50:05 +0000 Subject: [PATCH] [WININET] * Sync with Wine 1.7.17. CORE-8080 svn path=/trunk/; revision=62993 --- reactos/dll/win32/wininet/dialogs.c | 2 +- reactos/dll/win32/wininet/ftp.c | 13 +- reactos/dll/win32/wininet/http.c | 276 ++++++++++++---------- reactos/dll/win32/wininet/internet.c | 89 ++++++- reactos/dll/win32/wininet/internet.h | 33 ++- reactos/dll/win32/wininet/netconnection.c | 166 +++++++++---- reactos/dll/win32/wininet/utility.c | 2 +- reactos/media/doc/README.WINE | 2 +- 8 files changed, 398 insertions(+), 185 deletions(-) diff --git a/reactos/dll/win32/wininet/dialogs.c b/reactos/dll/win32/wininet/dialogs.c index 872022f82e8..b849d470cb7 100644 --- a/reactos/dll/win32/wininet/dialogs.c +++ b/reactos/dll/win32/wininet/dialogs.c @@ -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; } diff --git a/reactos/dll/win32/wininet/ftp.c b/reactos/dll/win32/wininet/ftp.c index 21d086342ef..df7becf2392 100644 --- a/reactos/dll/win32/wininet/ftp.c +++ b/reactos/dll/win32/wininet/ftp.c @@ -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 }; /*********************************************************************** diff --git a/reactos/dll/win32/wininet/http.c b/reactos/dll/win32/wininet/http.c index 240533cc9bf..7e7bd33efab 100644 --- a/reactos/dll/win32/wininet/http.c +++ b/reactos/dll/win32/wininet/http.c @@ -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, ¤t_read, read_mode); + sizeof(gzip_stream->buf)-gzip_stream->buf_size, ¤t_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, ¤t_read, read_mode); + res = read_http_stream(req, (BYTE*)buffer+ret_read, size-ret_read, ¤t_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) */ diff --git a/reactos/dll/win32/wininet/internet.c b/reactos/dll/win32/wininet/internet.c index 84adb264e1e..b78e44f2e13 100644 --- a/reactos/dll/win32/wininet/internet.c +++ b/reactos/dll/win32/wininet/internet.c @@ -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) diff --git a/reactos/dll/win32/wininet/internet.h b/reactos/dll/win32/wininet/internet.h index 85d4652aeb1..08a0ccf6a14 100644 --- a/reactos/dll/win32/wininet/internet.h +++ b/reactos/dll/win32/wininet/internet.h @@ -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; diff --git a/reactos/dll/win32/wininet/netconnection.c b/reactos/dll/win32/wininet/netconnection.c index d7c6c613ba3..f58c553abf7 100644 --- a/reactos/dll/win32/wininet/netconnection.c +++ b/reactos/dll/win32/wininet/netconnection.c @@ -34,8 +34,16 @@ # include #endif +#include + #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; - } - - if(!buf_len) { - *eof = TRUE; - return TRUE; - } } - *ret_size = 0; + 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) { + 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; + } + *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; } diff --git a/reactos/dll/win32/wininet/utility.c b/reactos/dll/win32/wininet/utility.c index b3783959a1a..826418daefd 100644 --- a/reactos/dll/win32/wininet/utility.c +++ b/reactos/dll/win32/wininet/utility.c @@ -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.... */ diff --git a/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE index a2863a1b389..06635bfe6f7 100644 --- a/reactos/media/doc/README.WINE +++ b/reactos/media/doc/README.WINE @@ -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