The function is implemented by setting cache file pointer to fill read_buf. Consequently, when HTTPREQ_ReadFile is called, it will try reading data from cache after read_buf is depleted, before continuing reading from http stream.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=26570
-- v2: wininet: Implement InternetSetFilePointer wininet/tests: Add InternetSetFilePointer tests.
From: Jason Kuo j20001970@gmail.com
--- dlls/wininet/tests/http.c | 97 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+)
diff --git a/dlls/wininet/tests/http.c b/dlls/wininet/tests/http.c index 8fcb9df293a..03f92223ce8 100644 --- a/dlls/wininet/tests/http.c +++ b/dlls/wininet/tests/http.c @@ -581,6 +581,102 @@ static void close_async_handle(HINTERNET handle, int handle_cnt) CHECK_NOTIFIED2(INTERNET_STATUS_HANDLE_CLOSING, handle_cnt); }
+static void InternetSetFilePointer_test() +{ + HINTERNET hi = 0, hic = 0, hor = 0; + BOOL res, expect; + DWORD i, pos, err; + + hi = InternetOpenA("Winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0); + ok((hi != 0x0), "InternetOpen failed with error %lu\n", GetLastError()); + if(hi == 0x0) goto abort; + + hic = InternetConnectA(hi, "test.winehq.org", INTERNET_DEFAULT_HTTP_PORT, + NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0); + ok((hic != 0x0), "InternetConnect failed with error %lu\n", GetLastError()); + if(hic == 0x0) goto abort; + + hor = HttpOpenRequestA(hic, NULL, "/favicon.ico", NULL, NULL, NULL, + INTERNET_FLAG_RELOAD|INTERNET_FLAG_DONT_CACHE, + 0x0); + ok((hor != 0x0), "HttpOpenRequest failed with error %lu\n", GetLastError()); + if(hor == 0x0) goto abort; + + pos = InternetSetFilePointer(hor, 0, NULL, FILE_BEGIN, 0); + err = GetLastError(); + expect = pos == INVALID_SET_FILE_POINTER && err == ERROR_INTERNET_INVALID_OPERATION; + ok(expect, "Expected position %#lx. Got %#lx. GetLastError() %lu\n", INVALID_SET_FILE_POINTER, pos, err); + if(hor) InternetCloseHandle(hor); + + hor = HttpOpenRequestA(hic, NULL, "/favicon.ico", NULL, NULL, NULL, + INTERNET_FLAG_RELOAD, + 0x0); + ok((hor != 0x0), "HttpOpenRequest failed with error %lu\n", GetLastError()); + if(hor == 0x0) goto abort; + + res = HttpSendRequestW(hor, NULL, 0, NULL, 0); + ok(res, "HttpSendRequest failed with error %lu\n", GetLastError()); + + i = 0; + while(i < 4) { + pos = InternetSetFilePointer(hor, i, NULL, FILE_BEGIN, 0); + err = GetLastError(); + expect = pos == i && err == NO_ERROR; + ok(expect, "Expected position %#lx. Got %#lx. GetLastError() %lu\n", i, pos, err); + i = i + 1; + } + while(i > 0) { + pos = InternetSetFilePointer(hor, i, NULL, FILE_BEGIN, 0); + err = GetLastError(); + expect = pos == i && err == NO_ERROR; + ok(expect, "Expected position %#lx. Got %#lx. GetLastError() %lu\n", i, pos, err); + i = i - 1; + } + + InternetSetFilePointer(hor, 0, NULL, FILE_BEGIN, 0); + i = 0; + while(i < 4) { + i = i + 1; + pos = InternetSetFilePointer(hor, 1, NULL, FILE_CURRENT, 0); + err = GetLastError(); + expect = pos == i && err == NO_ERROR; + ok(expect, "Expected position %#lx. Got %#lx. GetLastError() %lu\n", i, pos, err); + } + while(i > 0) { + i = i - 1; + pos = InternetSetFilePointer(hor, -1, NULL, FILE_CURRENT, 0); + err = GetLastError(); + expect = pos == INVALID_SET_FILE_POINTER && err == ERROR_NEGATIVE_SEEK; + ok(expect, "Expected position %#lx. Got %#lx. GetLastError() %lu\n", INVALID_SET_FILE_POINTER, pos, err); + } + + pos = InternetSetFilePointer(hor, INT_MAX, NULL, FILE_BEGIN, 0); + err = GetLastError(); + expect = pos == INT_MAX && err == NO_ERROR; + ok(expect, "Expected position %#lx. Got %#lx. GetLastError() %lu\n", INT_MAX, pos, err); + pos = InternetSetFilePointer(hor, 1, NULL, FILE_CURRENT, 0); + err = GetLastError(); + expect = pos == INT_MAX+1 && err == NO_ERROR; + ok(expect, "Expected position %#lx. Got %#lx. GetLastError() %lu\n", INT_MAX+1, pos, err); + + pos = InternetSetFilePointer(hor, INT_MAX, NULL, FILE_BEGIN, 0); + err = GetLastError(); + expect = pos == INT_MAX && err == NO_ERROR; + ok(expect, "Expected position %#lx. Got %#lx. GetLastError() %lu\n", INT_MAX, pos, err); + pos = InternetSetFilePointer(hor, -1, NULL, FILE_CURRENT, 0); + err = GetLastError(); + expect = pos == INVALID_SET_FILE_POINTER && err == ERROR_NEGATIVE_SEEK; + ok(expect, "Expected position %#lx. Got %#lx. GetLastError() %lu\n", INVALID_SET_FILE_POINTER, pos, err); + +abort: + if(hor) + InternetCloseHandle(hor); + if(hic) + InternetCloseHandle(hic); + if(hi) + InternetCloseHandle(hi); +} + static void InternetReadFile_test(int flags, const test_data_t *test) { char *post_data = NULL; @@ -7946,6 +8042,7 @@ START_TEST(http) InternetReadFile_chunked_test(); HttpSendRequestEx_test(); InternetReadFile_test(INTERNET_FLAG_ASYNC, &test_data[3]); + InternetSetFilePointer_test(); test_connection_failure(); test_default_service_port(); test_concurrent_header_access();
From: Jason Kuo j20001970@gmail.com
The function is implemented by setting cache file pointer to fill read_buf. Consequently, when HTTPREQ_ReadFile is called, it will try reading data from cache after read_buf is depleted, before continuing reading from http stream.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=26570 --- dlls/wininet/http.c | 9 ++++++ dlls/wininet/internet.c | 61 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 67 insertions(+), 3 deletions(-)
diff --git a/dlls/wininet/http.c b/dlls/wininet/http.c index c9d1c463982..a672ae7fd8f 100644 --- a/dlls/wininet/http.c +++ b/dlls/wininet/http.c @@ -3184,6 +3184,15 @@ static DWORD HTTPREQ_ReadFile(object_header_t *hdr, void *buf, DWORD size, DWORD req->read_pos += read; }
+ if(read < size && SetFilePointer(req->hCacheFile, 0, NULL, FILE_CURRENT) < GetFileSize(req->hCacheFile, NULL)) { + while(read < size) { + res = ReadFile(req->hCacheFile, buf+read, size-read, &cread, NULL); + read += cread; + if(res != ERROR_SUCCESS || !cread) + break; + } + } + if(read < size && (!read || !(flags & IRF_NO_WAIT)) && !end_of_read_data(req)) { LeaveCriticalSection(&req->read_section); INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0); diff --git a/dlls/wininet/internet.c b/dlls/wininet/internet.c index 292fd44dd8e..5d54919a479 100644 --- a/dlls/wininet/internet.c +++ b/dlls/wininet/internet.c @@ -2154,14 +2154,69 @@ INTERNET_STATUS_CALLBACK WINAPI InternetSetStatusCallbackW(
/*********************************************************************** * InternetSetFilePointer (WININET.@) + * Sets read position for an open internet file. + * + * RETURNS + * Current position of the file on success + * INVALID_SET_FILE_POINTER on failure */ DWORD WINAPI InternetSetFilePointer(HINTERNET hFile, LONG lDistanceToMove, PVOID pReserved, DWORD dwMoveContext, DWORD_PTR dwContext) { - FIXME("(%p %ld %p %ld %Ix): stub\n", hFile, lDistanceToMove, pReserved, dwMoveContext, dwContext); + DWORD cache_pos, read, cread; + DWORD err = ERROR_INTERNET_INVALID_OPERATION, res = INVALID_SET_FILE_POINTER; + http_request_t *request; + + TRACE("(%p %ld %p %ld %Ix)\n", hFile, lDistanceToMove, pReserved, dwMoveContext, dwContext); + + request = (http_request_t*)get_handle_object(hFile); + + if(request->hdr.dwFlags & (INTERNET_FLAG_DONT_CACHE|INTERNET_FLAG_NO_CACHE_WRITE)) + goto lend;
- SetLastError(ERROR_INTERNET_INVALID_OPERATION); - return INVALID_SET_FILE_POINTER; + cache_pos = SetFilePointer(request->hCacheFile, 0, NULL, FILE_CURRENT); + switch (dwMoveContext) { + case FILE_BEGIN: + cache_pos = lDistanceToMove; + break; + case FILE_CURRENT: + if(cache_pos && lDistanceToMove < 0) { + err = ERROR_NEGATIVE_SEEK; + goto lend; + } + cache_pos += lDistanceToMove; + break; + case FILE_END: + FIXME("Unhandled dwMoveContext %ld\n", dwMoveContext); + goto lend; + } + + if(GetFileSize(request->hCacheFile, NULL) < cache_pos) { + BYTE buf[1024]; + while(GetFileSize(request->hCacheFile, NULL) < cache_pos) { + res = InternetReadFile(hFile, buf, 1024, &cread); + if(res != ERROR_SUCCESS || !cread) + break; + } + } + + res = cache_pos; + cache_pos = SetFilePointer(request->hCacheFile, lDistanceToMove, NULL, dwMoveContext); + EnterCriticalSection(&request->read_section); + read = min(READ_BUFFER_SIZE, GetFileSize(request->hCacheFile, NULL)-cache_pos); + if(ReadFile(request->hCacheFile, request->read_buf, read, &cread, NULL)) { + request->read_size = cread; + request->read_pos = 0; + } + LeaveCriticalSection(&request->read_section); + err = NO_ERROR; + +lend: + SetLastError(err); + TRACE("returning %ld\n", res); + if(request) + WININET_Release( &request->hdr ); + return res; }
/***********************************************************************
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=125842
Your paranoid android.
=== debian11 (32 bit report) ===
ddraw: ddraw7.c:15681: Test failed: Expected unsynchronised map for flags 0x1000. ddraw7.c:15681: Test failed: Expected unsynchronised map for flags 0x3000.
=== debian11 (32 bit ja:JP report) ===
wininet: http.c:643: Test failed: Expected position 0x1. Got 0. GetLastError() 0 http.c:643: Test failed: Expected position 0x2. Got 0. GetLastError() 0 http.c:643: Test failed: Expected position 0x3. Got 0. GetLastError() 0 http.c:643: Test failed: Expected position 0x4. Got 0. GetLastError() 0 http.c:660: Test failed: Expected position 0x80000000. Got 0. GetLastError() 0
=== debian11b (32 bit WoW report) ===
wininet: http.c:643: Test failed: Expected position 0x1. Got 0. GetLastError() 0 http.c:643: Test failed: Expected position 0x2. Got 0. GetLastError() 0 http.c:643: Test failed: Expected position 0x3. Got 0. GetLastError() 0 http.c:643: Test failed: Expected position 0x4. Got 0. GetLastError() 0 http.c:660: Test failed: Expected position 0x80000000. Got 0. GetLastError() 0
=== debian11b (64 bit WoW report) ===
wininet: http.c:643: Test failed: Expected position 0x1. Got 0. GetLastError() 0 http.c:643: Test failed: Expected position 0x2. Got 0. GetLastError() 0 http.c:643: Test failed: Expected position 0x3. Got 0. GetLastError() 0 http.c:643: Test failed: Expected position 0x4. Got 0. GetLastError() 0 http.c:660: Test failed: Expected position 0x80000000. Got 0. GetLastError() 0