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