[1/2] wininet: Implement InternetReadFileExW.

Hans Leidekker hans at codeweavers.com
Thu Jan 15 09:41:42 CST 2009


I chose not to forward InternetReadFileExA because conversion of the
buffer list seemed too expensive to me.

IE7 calls this function.

 -Hans

diff --git a/dlls/wininet/ftp.c b/dlls/wininet/ftp.c
index 21ce434..0289300 100644
--- a/dlls/wininet/ftp.c
+++ b/dlls/wininet/ftp.c
@@ -1267,6 +1267,7 @@ static const HANDLEHEADERVtbl FTPFILEVtbl = {
     NULL,
     FTPFILE_ReadFile,
     NULL,
+    NULL,
     FTPFILE_WriteFile,
     NULL,
     NULL
@@ -3312,6 +3313,7 @@ static const HANDLEHEADERVtbl FTPFINDNEXTVtbl = {
     NULL,
     NULL,
     NULL,
+    NULL,
     FTPFINDNEXT_FindNextFileW
 };
 
diff --git a/dlls/wininet/http.c b/dlls/wininet/http.c
index a5352e4..ea4e456 100644
--- a/dlls/wininet/http.c
+++ b/dlls/wininet/http.c
@@ -1795,7 +1795,7 @@ static DWORD HTTPREQ_ReadFile(WININETHANDLEHEADER *hdr, void *buffer, DWORD size
     return HTTPREQ_Read(req, buffer, size, read, TRUE);
 }
 
-static void HTTPREQ_AsyncReadFileExProc(WORKREQUEST *workRequest)
+static void HTTPREQ_AsyncReadFileExAProc(WORKREQUEST *workRequest)
 {
     struct WORKREQ_INTERNETREADFILEEXA const *data = &workRequest->u.InternetReadFileExA;
     WININETHTTPREQW *req = (WININETHTTPREQW*)workRequest->hdr;
@@ -1838,7 +1838,7 @@ static DWORD HTTPREQ_ReadFileExA(WININETHANDLEHEADER *hdr, INTERNET_BUFFERSA *bu
         {
             WORKREQUEST workRequest;
 
-            workRequest.asyncproc = HTTPREQ_AsyncReadFileExProc;
+            workRequest.asyncproc = HTTPREQ_AsyncReadFileExAProc;
             workRequest.hdr = WININET_AddRef(&req->hdr);
             workRequest.u.InternetReadFileExA.lpBuffersOut = buffers;
 
@@ -1860,6 +1860,71 @@ static DWORD HTTPREQ_ReadFileExA(WININETHANDLEHEADER *hdr, INTERNET_BUFFERSA *bu
     return res;
 }
 
+static void HTTPREQ_AsyncReadFileExWProc(WORKREQUEST *workRequest)
+{
+    struct WORKREQ_INTERNETREADFILEEXW const *data = &workRequest->u.InternetReadFileExW;
+    WININETHTTPREQW *req = (WININETHTTPREQW*)workRequest->hdr;
+    INTERNET_ASYNC_RESULT iar;
+    DWORD res;
+
+    TRACE("INTERNETREADFILEEXW %p\n", workRequest->hdr);
+
+    res = HTTPREQ_Read(req, data->lpBuffersOut->lpvBuffer,
+            data->lpBuffersOut->dwBufferLength, &data->lpBuffersOut->dwBufferLength, TRUE);
+
+    iar.dwResult = res == ERROR_SUCCESS;
+    iar.dwError = res;
+
+    INTERNET_SendCallback(&req->hdr, req->hdr.dwContext,
+                          INTERNET_STATUS_REQUEST_COMPLETE, &iar,
+                          sizeof(INTERNET_ASYNC_RESULT));
+}
+
+static DWORD HTTPREQ_ReadFileExW(WININETHANDLEHEADER *hdr, INTERNET_BUFFERSW *buffers,
+        DWORD flags, DWORD_PTR context)
+{
+
+    WININETHTTPREQW *req = (WININETHTTPREQW*)hdr;
+    DWORD res;
+
+    if (flags & ~(IRF_ASYNC|IRF_NO_WAIT))
+        FIXME("these dwFlags aren't implemented: 0x%x\n", flags & ~(IRF_ASYNC|IRF_NO_WAIT));
+
+    if (buffers->dwStructSize != sizeof(*buffers))
+        return ERROR_INVALID_PARAMETER;
+
+    INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
+
+    if (hdr->dwFlags & INTERNET_FLAG_ASYNC) {
+        DWORD available = 0;
+
+        NETCON_query_data_available(&req->netConnection, &available);
+        if (!available)
+        {
+            WORKREQUEST workRequest;
+
+            workRequest.asyncproc = HTTPREQ_AsyncReadFileExWProc;
+            workRequest.hdr = WININET_AddRef(&req->hdr);
+            workRequest.u.InternetReadFileExW.lpBuffersOut = buffers;
+
+            INTERNET_AsyncCall(&workRequest);
+
+            return ERROR_IO_PENDING;
+        }
+    }
+
+    res = HTTPREQ_Read(req, buffers->lpvBuffer, buffers->dwBufferLength, &buffers->dwBufferLength,
+            !(flags & IRF_NO_WAIT));
+
+    if (res == ERROR_SUCCESS) {
+        DWORD size = buffers->dwBufferLength;
+        INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RESPONSE_RECEIVED,
+                &size, sizeof(size));
+    }
+
+    return res;
+}
+
 static BOOL HTTPREQ_WriteFile(WININETHANDLEHEADER *hdr, const void *buffer, DWORD size, DWORD *written)
 {
     LPWININETHTTPREQW lpwhr = (LPWININETHTTPREQW)hdr;
@@ -1915,6 +1980,7 @@ static const HANDLEHEADERVtbl HTTPREQVtbl = {
     HTTPREQ_SetOption,
     HTTPREQ_ReadFile,
     HTTPREQ_ReadFileExA,
+    HTTPREQ_ReadFileExW,
     HTTPREQ_WriteFile,
     HTTPREQ_QueryDataAvailable,
     NULL
diff --git a/dlls/wininet/internet.c b/dlls/wininet/internet.c
index 03e9e74..6f67c3d 100644
--- a/dlls/wininet/internet.c
+++ b/dlls/wininet/internet.c
@@ -2005,29 +2005,34 @@ BOOL WINAPI InternetReadFileExA(HINTERNET hFile, LPINTERNET_BUFFERSA lpBuffersOu
 
 /***********************************************************************
  *           InternetReadFileExW (WININET.@)
- *
- * Read data from an open internet file.
- *
- * PARAMS
- *  hFile         [I] Handle returned by InternetOpenUrl() or HttpOpenRequest().
- *  lpBuffersOut  [I/O] Buffer.
- *  dwFlags       [I] Flags.
- *  dwContext     [I] Context for callbacks.
- *
- * RETURNS
- *    FALSE, last error is set to ERROR_CALL_NOT_IMPLEMENTED
- *
- * NOTES
- *  Not implemented in Wine or native either (as of IE6 SP2).
- *
+ * SEE
+ *  InternetReadFileExA()
  */
 BOOL WINAPI InternetReadFileExW(HINTERNET hFile, LPINTERNET_BUFFERSW lpBuffer,
 	DWORD dwFlags, DWORD_PTR dwContext)
 {
-  ERR("(%p, %p, 0x%x, 0x%lx): not implemented in native\n", hFile, lpBuffer, dwFlags, dwContext);
+    LPWININETHANDLEHEADER hdr;
+    DWORD res = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
+
+    TRACE("(%p %p 0x%x 0x%lx)\n", hFile, lpBuffer, dwFlags, dwContext);
 
-  INTERNET_SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-  return FALSE;
+    hdr = WININET_GetObject(hFile);
+    if (!hdr) {
+        INTERNET_SetLastError(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+
+    if(hdr->vtbl->ReadFileExW)
+        res = hdr->vtbl->ReadFileExW(hdr, lpBuffer, dwFlags, dwContext);
+
+    WININET_Release(hdr);
+
+    TRACE("-- %s (%u, bytes read: %d)\n", res == ERROR_SUCCESS ? "TRUE": "FALSE",
+          res, lpBuffer->dwBufferLength);
+
+    if(res != ERROR_SUCCESS)
+        SetLastError(res);
+    return res == ERROR_SUCCESS;
 }
 
 DWORD INET_QueryOption(DWORD option, void *buffer, DWORD *size, BOOL unicode)
diff --git a/dlls/wininet/internet.h b/dlls/wininet/internet.h
index 8de85ff..dc57214 100644
--- a/dlls/wininet/internet.h
+++ b/dlls/wininet/internet.h
@@ -124,6 +124,7 @@ typedef struct {
     DWORD (*SetOption)(WININETHANDLEHEADER*,DWORD,void*,DWORD);
     DWORD (*ReadFile)(WININETHANDLEHEADER*,void*,DWORD,DWORD*);
     DWORD (*ReadFileExA)(WININETHANDLEHEADER*,INTERNET_BUFFERSA*,DWORD,DWORD_PTR);
+    DWORD (*ReadFileExW)(WININETHANDLEHEADER*,INTERNET_BUFFERSW*,DWORD,DWORD_PTR);
     BOOL (*WriteFile)(WININETHANDLEHEADER*,const void*,DWORD,DWORD*);
     DWORD (*QueryDataAvailable)(WININETHANDLEHEADER*,DWORD*,DWORD,DWORD_PTR);
     DWORD (*FindNextFileW)(WININETHANDLEHEADER*,void*);
@@ -311,6 +312,11 @@ struct WORKREQ_INTERNETREADFILEEXA
     LPINTERNET_BUFFERSA lpBuffersOut;
 };
 
+struct WORKREQ_INTERNETREADFILEEXW
+{
+    LPINTERNET_BUFFERSW lpBuffersOut;
+};
+
 typedef struct WORKREQ
 {
     void (*asyncproc)(struct WORKREQ*);
@@ -330,8 +336,9 @@ typedef struct WORKREQ
         struct WORKREQ_FTPFINDNEXTW             FtpFindNextW;
         struct WORKREQ_HTTPSENDREQUESTW         HttpSendRequestW;
         struct WORKREQ_SENDCALLBACK             SendCallback;
-	struct WORKREQ_INTERNETOPENURLW         InternetOpenUrlW;
+        struct WORKREQ_INTERNETOPENURLW         InternetOpenUrlW;
         struct WORKREQ_INTERNETREADFILEEXA      InternetReadFileExA;
+        struct WORKREQ_INTERNETREADFILEEXW      InternetReadFileExW;
     } u;
 
 } WORKREQUEST, *LPWORKREQUEST;



More information about the wine-patches mailing list