Module: wine Branch: master Commit: 56267608f1a5c1a582e3faffd1b717d08abfbd9a URL: http://source.winehq.org/git/wine.git/?a=commit;h=56267608f1a5c1a582e3faffd1...
Author: Rob Shearman rob@codeweavers.com Date: Mon May 28 11:16:06 2007 +0100
wininet: Add a new NETCON_query_data_available function.
Use it to implement the behaviour where InternetReadFileExA does a synchronous request if the data is available and asynchronous otherwise.
---
dlls/wininet/internet.c | 49 +++++++++++++++++++++++++++-------------- dlls/wininet/internet.h | 1 + dlls/wininet/netconnection.c | 32 +++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 17 deletions(-)
diff --git a/dlls/wininet/internet.c b/dlls/wininet/internet.c index 4d48089..305392a 100644 --- a/dlls/wininet/internet.c +++ b/dlls/wininet/internet.c @@ -1855,26 +1855,32 @@ BOOL WINAPI InternetReadFileExA(HINTERNET hFile, LPINTERNET_BUFFERSA lpBuffersOu return FALSE; }
- /* FIXME: native only does it asynchronously if the amount of data - * requested isn't available. See NtReadFile. */ /* FIXME: IRF_ASYNC may not be the right thing to test here; - * hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC is probably better, but - * we should implement the above first */ + * hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC is probably better */ if (dwFlags & IRF_ASYNC) { - WORKREQUEST workRequest; - struct WORKREQ_INTERNETREADFILEEXA *req; + DWORD dwDataAvailable = 0; + + if (lpwh->htype == WH_HHTTPREQ) + NETCON_query_data_available(&((LPWININETHTTPREQW)lpwh)->netConnection, + &dwDataAvailable);
- workRequest.asyncproc = AsyncInternetReadFileExProc; - workRequest.hdr = WININET_AddRef( lpwh ); - req = &workRequest.u.InternetReadFileExA; - req->lpBuffersOut = lpBuffersOut; + if (!dwDataAvailable) + { + WORKREQUEST workRequest; + struct WORKREQ_INTERNETREADFILEEXA *req;
- retval = INTERNET_AsyncCall(&workRequest); - if (!retval) return FALSE; + workRequest.asyncproc = AsyncInternetReadFileExProc; + workRequest.hdr = WININET_AddRef( lpwh ); + req = &workRequest.u.InternetReadFileExA; + req->lpBuffersOut = lpBuffersOut;
- INTERNET_SetLastError(ERROR_IO_PENDING); - return FALSE; + retval = INTERNET_AsyncCall(&workRequest); + if (!retval) return FALSE; + + INTERNET_SetLastError(ERROR_IO_PENDING); + return FALSE; + } }
retval = INTERNET_ReadFile(lpwh, lpBuffersOut->lpvBuffer, @@ -3258,15 +3264,24 @@ BOOL WINAPI InternetQueryDataAvailable( HINTERNET hFile, switch (lpwhr->hdr.htype) { case WH_HHTTPREQ: - if (!NETCON_recv(&lpwhr->netConnection, buffer, + if (NETCON_query_data_available(&lpwhr->netConnection, + lpdwNumberOfBytesAvailble)) + { + if (!*lpdwNumberOfBytesAvailble && + !NETCON_recv(&lpwhr->netConnection, buffer, min(sizeof(buffer), lpwhr->dwContentLength - lpwhr->dwContentRead), MSG_PEEK, (int *)lpdwNumberOfBytesAvailble)) + { + INTERNET_SetLastError(ERROR_NO_MORE_FILES); + retval = FALSE; + } + retval = TRUE; + } + else { INTERNET_SetLastError(ERROR_NO_MORE_FILES); retval = FALSE; } - else - retval = TRUE; break;
default: diff --git a/dlls/wininet/internet.h b/dlls/wininet/internet.h index c1476de..4bb7a88 100644 --- a/dlls/wininet/internet.h +++ b/dlls/wininet/internet.h @@ -459,6 +459,7 @@ BOOL NETCON_send(WININET_NETCONNECTION *connection, const void *msg, size_t len, int *sent /* out */); BOOL NETCON_recv(WININET_NETCONNECTION *connection, void *buf, size_t len, int flags, int *recvd /* out */); +BOOL NETCON_query_data_available(WININET_NETCONNECTION *connection, DWORD *available); BOOL NETCON_getNextLine(WININET_NETCONNECTION *connection, LPSTR lpszBuffer, LPDWORD dwBuffer); LPCVOID NETCON_GetCert(WININET_NETCONNECTION *connection); BOOL NETCON_set_timeout(WININET_NETCONNECTION *connection, BOOL send, int value); diff --git a/dlls/wininet/netconnection.c b/dlls/wininet/netconnection.c index ec2b18d..125a90b 100644 --- a/dlls/wininet/netconnection.c +++ b/dlls/wininet/netconnection.c @@ -33,6 +33,9 @@ #ifdef HAVE_UNISTD_H # include <unistd.h> #endif +#ifdef HAVE_SYS_IOCTL_H +# include <sys/ioctl.h> +#endif #include <stdarg.h> #include <stdlib.h> #include <string.h> @@ -570,6 +573,35 @@ BOOL NETCON_recv(WININET_NETCONNECTION *connection, void *buf, size_t len, int f }
/****************************************************************************** + * NETCON_query_data_available + * Returns the number of bytes of peeked data plus the number of bytes of + * queued, but unread data. + */ +BOOL NETCON_query_data_available(WININET_NETCONNECTION *connection, DWORD *available) +{ + if (!NETCON_connected(connection)) + return FALSE; + + if (connection->peek_msg) + *available = connection->peek_len; + else + *available = 0; +#ifdef FIONREAD + if (!connection->useSSL) + { + int unread; + int retval = ioctl(connection->socketFD, FIONREAD, &unread); + if (!retval) + { + TRACE("%d bytes of queued, but unread data\n", unread); + *available += unread; + } + } +#endif + return TRUE; +} + +/****************************************************************************** * NETCON_getNextLine */ BOOL NETCON_getNextLine(WININET_NETCONNECTION *connection, LPSTR lpszBuffer, LPDWORD dwBuffer)