Rob Shearman : wininet: Add a new NETCON_query_data_available
function.
Alexandre Julliard
julliard at wine.codeweavers.com
Tue May 29 08:05:48 CDT 2007
Module: wine
Branch: master
Commit: 56267608f1a5c1a582e3faffd1b717d08abfbd9a
URL: http://source.winehq.org/git/wine.git/?a=commit;h=56267608f1a5c1a582e3faffd1b717d08abfbd9a
Author: Rob Shearman <rob at 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)
More information about the wine-cvs
mailing list