From bdec9df44c9252214a301fbe65558d39f6e009da Mon Sep 17 00:00:00 2001 From: Colin Finck Date: Sat, 31 May 2008 13:02:59 +0000 Subject: [PATCH] Sync wininet with Wine. This fixes the Download! issue. As we implement some more functions in the network stack now, I could remove some hacks from the "wininet_ros.diff" file. Anyways, the following things still needed to be changed: - Pass a variable to WriteFile for receiving the number of bytes written. This parameter is not checked for NULL in ReactOS and Windows, when lpOverlapped is also NULL. I'll submit a patch about this to Wine as well. - Replace Unix poll() calls by equivalent select() calls - Bypass sock_get_error(), directly call WSAGetLastError() as we don't have to translate Unix socket errors. See issue #3197 for more details. svn path=/trunk/; revision=33788 --- reactos/dll/win32/wininet/cookie.c | 24 +- reactos/dll/win32/wininet/ftp.c | 490 ++++--- reactos/dll/win32/wininet/http.c | 1397 ++++++++++++++------ reactos/dll/win32/wininet/internet.c | 866 +++++------- reactos/dll/win32/wininet/internet.h | 94 +- reactos/dll/win32/wininet/netconnection.c | 32 +- reactos/dll/win32/wininet/rsrc.rc | 3 +- reactos/dll/win32/wininet/urlcache.c | 626 ++++++--- reactos/dll/win32/wininet/utility.c | 4 +- reactos/dll/win32/wininet/wininet.spec | 4 +- reactos/dll/win32/wininet/wininet_Da.rc | 44 + reactos/dll/win32/wininet/wininet_Ru.rc | 7 +- reactos/dll/win32/wininet/wininet_Si.rc | 25 +- reactos/dll/win32/wininet/wininet_Sv.rc | 2 +- reactos/dll/win32/wininet/wininet_ros.diff | 426 ++---- reactos/include/psdk/wininet.h | 223 +++- 16 files changed, 2478 insertions(+), 1789 deletions(-) create mode 100644 reactos/dll/win32/wininet/wininet_Da.rc diff --git a/reactos/dll/win32/wininet/cookie.c b/reactos/dll/win32/wininet/cookie.c index 2eef2d99748..bd22bc625c4 100644 --- a/reactos/dll/win32/wininet/cookie.c +++ b/reactos/dll/win32/wininet/cookie.c @@ -544,10 +544,12 @@ BOOL WINAPI InternetSetCookieA(LPCSTR lpszUrl, LPCSTR lpszCookieName, DWORD WINAPI InternetSetCookieExA( LPCSTR lpszURL, LPCSTR lpszCookieName, LPCSTR lpszCookieData, DWORD dwFlags, DWORD_PTR dwReserved) { - FIXME("(%s, %s, %s, 0x%08x, 0x%08lx) stub\n", + TRACE("(%s, %s, %s, 0x%08x, 0x%08lx)\n", debugstr_a(lpszURL), debugstr_a(lpszCookieName), debugstr_a(lpszCookieData), dwFlags, dwReserved); - return TRUE; + + if (dwFlags) FIXME("flags 0x%08x not supported\n", dwFlags); + return InternetSetCookieA(lpszURL, lpszCookieName, lpszCookieData); } /*********************************************************************** @@ -563,10 +565,12 @@ DWORD WINAPI InternetSetCookieExA( LPCSTR lpszURL, LPCSTR lpszCookieName, LPCSTR DWORD WINAPI InternetSetCookieExW( LPCWSTR lpszURL, LPCWSTR lpszCookieName, LPCWSTR lpszCookieData, DWORD dwFlags, DWORD_PTR dwReserved) { - FIXME("(%s, %s, %s, 0x%08x, 0x%08lx) stub\n", + TRACE("(%s, %s, %s, 0x%08x, 0x%08lx)\n", debugstr_w(lpszURL), debugstr_w(lpszCookieName), debugstr_w(lpszCookieData), dwFlags, dwReserved); - return TRUE; + + if (dwFlags) FIXME("flags 0x%08x not supported\n", dwFlags); + return InternetSetCookieW(lpszURL, lpszCookieName, lpszCookieData); } /*********************************************************************** @@ -577,10 +581,12 @@ DWORD WINAPI InternetSetCookieExW( LPCWSTR lpszURL, LPCWSTR lpszCookieName, LPCW BOOL WINAPI InternetGetCookieExA( LPCSTR pchURL, LPCSTR pchCookieName, LPSTR pchCookieData, LPDWORD pcchCookieData, DWORD dwFlags, LPVOID lpReserved) { - FIXME("(%s, %s, %s, %p, 0x%08x, %p) stub\n", + TRACE("(%s, %s, %s, %p, 0x%08x, %p)\n", debugstr_a(pchURL), debugstr_a(pchCookieName), debugstr_a(pchCookieData), pcchCookieData, dwFlags, lpReserved); - return FALSE; + + if (dwFlags) FIXME("flags 0x%08x not supported\n", dwFlags); + return InternetGetCookieA(pchURL, pchCookieName, pchCookieData, pcchCookieData); } /*********************************************************************** @@ -596,10 +602,12 @@ BOOL WINAPI InternetGetCookieExA( LPCSTR pchURL, LPCSTR pchCookieName, LPSTR pch BOOL WINAPI InternetGetCookieExW( LPCWSTR pchURL, LPCWSTR pchCookieName, LPWSTR pchCookieData, LPDWORD pcchCookieData, DWORD dwFlags, LPVOID lpReserved) { - FIXME("(%s, %s, %s, %p, 0x%08x, %p) stub\n", + TRACE("(%s, %s, %s, %p, 0x%08x, %p)\n", debugstr_w(pchURL), debugstr_w(pchCookieName), debugstr_w(pchCookieData), pcchCookieData, dwFlags, lpReserved); - return FALSE; + + if (dwFlags) FIXME("flags 0x%08x not supported\n", dwFlags); + return InternetGetCookieW(pchURL, pchCookieName, pchCookieData, pcchCookieData); } /*********************************************************************** diff --git a/reactos/dll/win32/wininet/ftp.c b/reactos/dll/win32/wininet/ftp.c index bec4596c550..36e90057008 100644 --- a/reactos/dll/win32/wininet/ftp.c +++ b/reactos/dll/win32/wininet/ftp.c @@ -58,10 +58,51 @@ #include "wine/debug.h" #include "internet.h" -typedef size_t socklen_t; WINE_DEFAULT_DEBUG_CHANNEL(wininet); +typedef struct _WININETFTPSESSIONW WININETFTPSESSIONW; + +typedef struct +{ + WININETHANDLEHEADER hdr; + WININETFTPSESSIONW *lpFtpSession; + BOOL session_deleted; + int nDataSocket; +} WININETFTPFILE, *LPWININETFTPFILE; + +typedef struct _WININETFTPSESSIONW +{ + WININETHANDLEHEADER hdr; + WININETAPPINFOW *lpAppInfo; + int sndSocket; + int lstnSocket; + int pasvSocket; /* data socket connected by us in case of passive FTP */ + LPWININETFTPFILE download_in_progress; + struct sockaddr_in socketAddress; + struct sockaddr_in lstnSocketAddress; + LPWSTR lpszPassword; + LPWSTR lpszUserName; +} *LPWININETFTPSESSIONW; + +typedef struct +{ + BOOL bIsDirectory; + LPWSTR lpszName; + DWORD nSize; + struct tm tmLastModified; + unsigned short permissions; +} FILEPROPERTIESW, *LPFILEPROPERTIESW; + +typedef struct +{ + WININETHANDLEHEADER hdr; + WININETFTPSESSIONW *lpFtpSession; + DWORD index; + DWORD size; + LPFILEPROPERTIESW lpafp; +} WININETFTPFINDNEXTW, *LPWININETFTPFINDNEXTW; + #define DATA_PACKET_SIZE 0x2000 #define szCRLF "\r\n" #define MAX_BACKLOG 5 @@ -123,10 +164,6 @@ static const CHAR *const szFtpCommands[] = { static const CHAR szMonths[] = "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC"; static const WCHAR szNoAccount[] = {'n','o','a','c','c','o','u','n','t','\0'}; -static void FTP_CloseFileTransferHandle(LPWININETHANDLEHEADER hdr); -static void FTP_CloseSessionHandle(LPWININETHANDLEHEADER hdr); -static void FTP_CloseConnection(LPWININETHANDLEHEADER hdr); -static void FTP_CloseFindNextHandle(LPWININETHANDLEHEADER hdr); static BOOL FTP_SendCommand(INT nSocket, FTP_COMMAND ftpCmd, LPCWSTR lpszParam, INTERNET_STATUS_CALLBACK lpfnStatusCB, LPWININETHANDLEHEADER hdr, DWORD_PTR dwContext); static BOOL FTP_SendStore(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszRemoteFile, DWORD dwType); @@ -146,10 +183,28 @@ static BOOL FTP_SendPortOrPasv(LPWININETFTPSESSIONW lpwfs); static BOOL FTP_ParsePermission(LPCSTR lpszPermission, LPFILEPROPERTIESW lpfp); static BOOL FTP_ParseNextFile(INT nSocket, LPCWSTR lpszSearchFile, LPFILEPROPERTIESW fileprop); static BOOL FTP_ParseDirectory(LPWININETFTPSESSIONW lpwfs, INT nSocket, LPCWSTR lpszSearchFile, - LPFILEPROPERTIESW *lpafp, LPDWORD dwfp); + LPFILEPROPERTIESW *lpafp, LPDWORD dwfp); static HINTERNET FTP_ReceiveFileList(LPWININETFTPSESSIONW lpwfs, INT nSocket, LPCWSTR lpszSearchFile, - LPWIN32_FIND_DATAW lpFindFileData, DWORD_PTR dwContext); + LPWIN32_FIND_DATAW lpFindFileData, DWORD_PTR dwContext); static DWORD FTP_SetResponseError(DWORD dwResponse); +static BOOL FTP_ConvertFileProp(LPFILEPROPERTIESW lpafp, LPWIN32_FIND_DATAW lpFindFileData); +static BOOL FTP_FtpPutFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszLocalFile, + LPCWSTR lpszNewRemoteFile, DWORD dwFlags, DWORD_PTR dwContext); +static BOOL FTP_FtpSetCurrentDirectoryW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszDirectory); +static BOOL FTP_FtpCreateDirectoryW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszDirectory); +static HINTERNET FTP_FtpFindFirstFileW(LPWININETFTPSESSIONW lpwfs, + LPCWSTR lpszSearchFile, LPWIN32_FIND_DATAW lpFindFileData, DWORD dwFlags, DWORD_PTR dwContext); +static BOOL FTP_FtpGetCurrentDirectoryW(LPWININETFTPSESSIONW lpwfs, LPWSTR lpszCurrentDirectory, + LPDWORD lpdwCurrentDirectory); +static BOOL FTP_FtpRenameFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszSrc, LPCWSTR lpszDest); +static BOOL FTP_FtpRemoveDirectoryW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszDirectory); +static BOOL FTP_FtpDeleteFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszFileName); +static HINTERNET FTP_FtpOpenFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszFileName, + DWORD fdwAccess, DWORD dwFlags, DWORD_PTR dwContext); +static BOOL FTP_FtpGetFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszRemoteFile, LPCWSTR lpszNewFile, + BOOL fFailIfExists, DWORD dwLocalFlagsAttribute, DWORD dwInternetFlags, + DWORD_PTR dwContext); + /*********************************************************************** * FtpPutFileA (WININET.@) @@ -276,7 +331,7 @@ lend: * FALSE on failure * */ -BOOL WINAPI FTP_FtpPutFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszLocalFile, +static BOOL FTP_FtpPutFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszLocalFile, LPCWSTR lpszNewRemoteFile, DWORD dwFlags, DWORD_PTR dwContext) { HANDLE hFile; @@ -444,7 +499,7 @@ lend: * FALSE on failure * */ -BOOL WINAPI FTP_FtpSetCurrentDirectoryW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszDirectory) +static BOOL FTP_FtpSetCurrentDirectoryW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszDirectory) { INT nResCode; LPWININETAPPINFOW hIC = NULL; @@ -475,7 +530,7 @@ lend: { INTERNET_ASYNC_RESULT iar; - iar.dwResult = (DWORD)bSuccess; + iar.dwResult = bSuccess; iar.dwError = bSuccess ? ERROR_SUCCESS : ERROR_INTERNET_EXTENDED_ERROR; SendAsyncCallback(&lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE, &iar, sizeof(INTERNET_ASYNC_RESULT)); @@ -592,7 +647,7 @@ lend: * FALSE on failure * */ -BOOL WINAPI FTP_FtpCreateDirectoryW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszDirectory) +static BOOL FTP_FtpCreateDirectoryW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszDirectory) { INT nResCode; BOOL bSuccess = FALSE; @@ -742,7 +797,7 @@ lend: * NULL on failure * */ -HINTERNET WINAPI FTP_FtpFindFirstFileW(LPWININETFTPSESSIONW lpwfs, +static HINTERNET FTP_FtpFindFirstFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszSearchFile, LPWIN32_FIND_DATAW lpFindFileData, DWORD dwFlags, DWORD_PTR dwContext) { INT nResCode; @@ -882,7 +937,7 @@ BOOL WINAPI FtpGetCurrentDirectoryW(HINTERNET hFtpSession, LPWSTR lpszCurrentDir LPWININETAPPINFOW hIC = NULL; BOOL r = FALSE; - TRACE("len(%d)\n", *lpdwCurrentDirectory); + TRACE("%p %p %p\n", hFtpSession, lpszCurrentDirectory, lpdwCurrentDirectory); lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hFtpSession ); if (NULL == lpwfs) @@ -953,15 +1008,13 @@ lend: * FALSE on failure * */ -BOOL WINAPI FTP_FtpGetCurrentDirectoryW(LPWININETFTPSESSIONW lpwfs, LPWSTR lpszCurrentDirectory, +static BOOL FTP_FtpGetCurrentDirectoryW(LPWININETFTPSESSIONW lpwfs, LPWSTR lpszCurrentDirectory, LPDWORD lpdwCurrentDirectory) { INT nResCode; LPWININETAPPINFOW hIC = NULL; DWORD bSuccess = FALSE; - TRACE("len(%d)\n", *lpdwCurrentDirectory); - /* Clear any error information */ INTERNET_SetLastError(0); @@ -1009,13 +1062,13 @@ lend: { INTERNET_ASYNC_RESULT iar; - iar.dwResult = (DWORD)bSuccess; + iar.dwResult = bSuccess; iar.dwError = bSuccess ? ERROR_SUCCESS : ERROR_INTERNET_EXTENDED_ERROR; SendAsyncCallback(&lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE, &iar, sizeof(INTERNET_ASYNC_RESULT)); } - return (DWORD) bSuccess; + return bSuccess; } /*********************************************************************** @@ -1131,6 +1184,91 @@ lend: } +/*********************************************************************** + * FTPFILE_Destroy(internal) + * + * Closes the file transfer handle. This also 'cleans' the data queue of + * the 'transfer complete' message (this is a bit of a hack though :-/ ) + * + */ +static void FTPFILE_Destroy(WININETHANDLEHEADER *hdr) +{ + LPWININETFTPFILE lpwh = (LPWININETFTPFILE) hdr; + LPWININETFTPSESSIONW lpwfs = lpwh->lpFtpSession; + INT nResCode; + + TRACE("\n"); + + WININET_Release(&lpwh->lpFtpSession->hdr); + + if (!lpwh->session_deleted) + lpwfs->download_in_progress = NULL; + + if (lpwh->nDataSocket != -1) + closesocket(lpwh->nDataSocket); + + nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext); + if (nResCode > 0 && nResCode != 226) WARN("server reports failed transfer\n"); + + HeapFree(GetProcessHeap(), 0, lpwh); +} + +static DWORD FTPFILE_QueryOption(WININETHANDLEHEADER *hdr, DWORD option, void *buffer, DWORD *size, BOOL unicode) +{ + switch(option) { + case INTERNET_OPTION_HANDLE_TYPE: + TRACE("INTERNET_OPTION_HANDLE_TYPE\n"); + + if (*size < sizeof(ULONG)) + return ERROR_INSUFFICIENT_BUFFER; + + *size = sizeof(DWORD); + *(DWORD*)buffer = INTERNET_HANDLE_TYPE_FTP_FILE; + return ERROR_SUCCESS; + } + + FIXME("Not implemented option %d\n", option); + return ERROR_INTERNET_INVALID_OPTION; +} + +static DWORD FTPFILE_ReadFile(WININETHANDLEHEADER *hdr, void *buffer, DWORD size, DWORD *read) +{ + WININETFTPFILE *file = (WININETFTPFILE*)hdr; + int res; + + if (file->nDataSocket == -1) + return ERROR_INTERNET_DISCONNECTED; + + /* FIXME: FTP should use NETCON_ stuff */ + res = recv(file->nDataSocket, buffer, size, MSG_WAITALL); + *read = res>0 ? res : 0; + + return res>=0 ? ERROR_SUCCESS : INTERNET_ERROR_BASE; /* FIXME*/ +} + +static BOOL FTPFILE_WriteFile(WININETHANDLEHEADER *hdr, const void *buffer, DWORD size, DWORD *written) +{ + LPWININETFTPFILE lpwh = (LPWININETFTPFILE) hdr; + int res; + + res = send(lpwh->nDataSocket, buffer, size, 0); + + *written = res>0 ? res : 0; + return res >= 0; +} + +static const HANDLEHEADERVtbl FTPFILEVtbl = { + FTPFILE_Destroy, + NULL, + FTPFILE_QueryOption, + NULL, + FTPFILE_ReadFile, + NULL, + FTPFILE_WriteFile, + NULL, + NULL +}; + /*********************************************************************** * FTP_FtpOpenFileW (Internal) * @@ -1172,11 +1310,10 @@ HINTERNET FTP_FtpOpenFileW(LPWININETFTPSESSIONW lpwfs, { lpwh = HeapAlloc(GetProcessHeap(), 0, sizeof(WININETFTPFILE)); lpwh->hdr.htype = WH_HFILE; + lpwh->hdr.vtbl = &FTPFILEVtbl; lpwh->hdr.dwFlags = dwFlags; lpwh->hdr.dwContext = dwContext; - lpwh->hdr.dwRefCount = 1; - lpwh->hdr.close_connection = NULL; - lpwh->hdr.destroy = FTP_CloseFileTransferHandle; + lpwh->hdr.refs = 1; lpwh->hdr.lpfnStatusCB = lpwfs->hdr.lpfnStatusCB; lpwh->nDataSocket = nDataSocket; lpwh->session_deleted = FALSE; @@ -1356,7 +1493,7 @@ lend: * FALSE on failure * */ -BOOL WINAPI FTP_FtpGetFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszRemoteFile, LPCWSTR lpszNewFile, +static BOOL FTP_FtpGetFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszRemoteFile, LPCWSTR lpszNewFile, BOOL fFailIfExists, DWORD dwLocalFlagsAttribute, DWORD dwInternetFlags, DWORD_PTR dwContext) { @@ -1999,6 +2136,81 @@ lend: return r; } + +/*********************************************************************** + * FTPSESSION_Destroy (internal) + * + * Deallocate session handle + */ +static void FTPSESSION_Destroy(WININETHANDLEHEADER *hdr) +{ + LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) hdr; + + TRACE("\n"); + + WININET_Release(&lpwfs->lpAppInfo->hdr); + + HeapFree(GetProcessHeap(), 0, lpwfs->lpszPassword); + HeapFree(GetProcessHeap(), 0, lpwfs->lpszUserName); + HeapFree(GetProcessHeap(), 0, lpwfs); +} + +static void FTPSESSION_CloseConnection(WININETHANDLEHEADER *hdr) +{ + LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) hdr; + + TRACE("\n"); + + SendAsyncCallback(&lpwfs->hdr, lpwfs->hdr.dwContext, + INTERNET_STATUS_CLOSING_CONNECTION, 0, 0); + + if (lpwfs->download_in_progress != NULL) + lpwfs->download_in_progress->session_deleted = TRUE; + + if (lpwfs->sndSocket != -1) + closesocket(lpwfs->sndSocket); + + if (lpwfs->lstnSocket != -1) + closesocket(lpwfs->lstnSocket); + + if (lpwfs->pasvSocket != -1) + closesocket(lpwfs->pasvSocket); + + SendAsyncCallback(&lpwfs->hdr, lpwfs->hdr.dwContext, + INTERNET_STATUS_CONNECTION_CLOSED, 0, 0); +} + +static DWORD FTPSESSION_QueryOption(WININETHANDLEHEADER *hdr, DWORD option, void *buffer, DWORD *size, BOOL unicode) +{ + switch(option) { + case INTERNET_OPTION_HANDLE_TYPE: + TRACE("INTERNET_OPTION_HANDLE_TYPE\n"); + + if (*size < sizeof(ULONG)) + return ERROR_INSUFFICIENT_BUFFER; + + *size = sizeof(DWORD); + *(DWORD*)buffer = INTERNET_HANDLE_TYPE_CONNECT_FTP; + return ERROR_SUCCESS; + } + + FIXME("Not implemented option %d\n", option); + return ERROR_INTERNET_INVALID_OPTION; +} + +static const HANDLEHEADERVtbl FTPSESSIONVtbl = { + FTPSESSION_Destroy, + FTPSESSION_CloseConnection, + FTPSESSION_QueryOption, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL +}; + + /*********************************************************************** * FTP_Connect (internal) * @@ -2062,12 +2274,11 @@ HINTERNET FTP_Connect(LPWININETAPPINFOW hIC, LPCWSTR lpszServerName, nServerPort = INTERNET_DEFAULT_FTP_PORT; lpwfs->hdr.htype = WH_HFTPSESSION; + lpwfs->hdr.vtbl = &FTPSESSIONVtbl; lpwfs->hdr.dwFlags = dwFlags; lpwfs->hdr.dwContext = dwContext; lpwfs->hdr.dwInternalFlags = dwInternalFlags; - lpwfs->hdr.dwRefCount = 1; - lpwfs->hdr.close_connection = FTP_CloseConnection; - lpwfs->hdr.destroy = FTP_CloseSessionHandle; + lpwfs->hdr.refs = 1; lpwfs->hdr.lpfnStatusCB = hIC->hdr.lpfnStatusCB; lpwfs->download_in_progress = NULL; lpwfs->sndSocket = -1; @@ -2336,11 +2547,9 @@ INT FTP_ReceiveResponse(LPWININETFTPSESSIONW lpwfs, DWORD_PTR dwContext) INT rc = 0; char firstprefix[5]; BOOL multiline = FALSE; - LPWININETAPPINFOW hIC = NULL; TRACE("socket(%d)\n", lpwfs->sndSocket); - hIC = lpwfs->lpAppInfo; SendAsyncCallback(&lpwfs->hdr, dwContext, INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0); while(1) @@ -2957,7 +3166,6 @@ lend: static BOOL FTP_RetrieveFileData(LPWININETFTPSESSIONW lpwfs, INT nDataSocket, HANDLE hFile) { DWORD nBytesWritten; - DWORD nBytesReceived = 0; INT nRC = 0; CHAR *lpszBuffer; @@ -2979,7 +3187,6 @@ static BOOL FTP_RetrieveFileData(LPWININETFTPSESSIONW lpwfs, INT nDataSocket, HA if (nRC == 0) goto recv_end; WriteFile(hFile, lpszBuffer, nRC, &nBytesWritten, NULL); - nBytesReceived += nRC; } } @@ -2992,122 +3199,11 @@ recv_end: } /*********************************************************************** - * FTP_CloseConnection (internal) - * - * Close connections - */ -static void FTP_CloseConnection(LPWININETHANDLEHEADER hdr) -{ - LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) hdr; - - TRACE("\n"); - - SendAsyncCallback(&lpwfs->hdr, lpwfs->hdr.dwContext, - INTERNET_STATUS_CLOSING_CONNECTION, 0, 0); - - if (lpwfs->download_in_progress != NULL) - lpwfs->download_in_progress->session_deleted = TRUE; - - if (lpwfs->sndSocket != -1) - closesocket(lpwfs->sndSocket); - - if (lpwfs->lstnSocket != -1) - closesocket(lpwfs->lstnSocket); - - if (lpwfs->pasvSocket != -1) - closesocket(lpwfs->pasvSocket); - - SendAsyncCallback(&lpwfs->hdr, lpwfs->hdr.dwContext, - INTERNET_STATUS_CONNECTION_CLOSED, 0, 0); -} - - -/*********************************************************************** - * FTP_CloseSessionHandle (internal) + * FTPFINDNEXT_Destroy (internal) * * Deallocate session handle */ -static void FTP_CloseSessionHandle(LPWININETHANDLEHEADER hdr) -{ - LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) hdr; - - TRACE("\n"); - - WININET_Release(&lpwfs->lpAppInfo->hdr); - - HeapFree(GetProcessHeap(), 0, lpwfs->lpszPassword); - HeapFree(GetProcessHeap(), 0, lpwfs->lpszUserName); - HeapFree(GetProcessHeap(), 0, lpwfs); -} - - -/*********************************************************************** - * FTP_FindNextFileW (Internal) - * - * Continues a file search from a previous call to FindFirstFile - * - * RETURNS - * TRUE on success - * FALSE on failure - * - */ -BOOL WINAPI FTP_FindNextFileW(LPWININETFTPFINDNEXTW lpwh, LPVOID lpvFindData) -{ - BOOL bSuccess = TRUE; - LPWIN32_FIND_DATAW lpFindFileData; - - TRACE("index(%d) size(%d)\n", lpwh->index, lpwh->size); - - assert (lpwh->hdr.htype == WH_HFTPFINDNEXT); - - /* Clear any error information */ - INTERNET_SetLastError(0); - - lpFindFileData = (LPWIN32_FIND_DATAW) lpvFindData; - ZeroMemory(lpFindFileData, sizeof(WIN32_FIND_DATAA)); - - if (lpwh->index >= lpwh->size) - { - INTERNET_SetLastError(ERROR_NO_MORE_FILES); - bSuccess = FALSE; - goto lend; - } - - FTP_ConvertFileProp(&lpwh->lpafp[lpwh->index], lpFindFileData); - lpwh->index++; - - TRACE("\nName: %s\nSize: %d\n", debugstr_w(lpFindFileData->cFileName), lpFindFileData->nFileSizeLow); - -lend: - - if (lpwh->hdr.dwFlags & INTERNET_FLAG_ASYNC) - { - INTERNET_ASYNC_RESULT iar; - - iar.dwResult = (DWORD)bSuccess; - iar.dwError = iar.dwError = bSuccess ? ERROR_SUCCESS : - INTERNET_GetLastError(); - - INTERNET_SendCallback(&lpwh->hdr, lpwh->hdr.dwContext, - INTERNET_STATUS_REQUEST_COMPLETE, &iar, - sizeof(INTERNET_ASYNC_RESULT)); - } - - return bSuccess; -} - - -/*********************************************************************** - * FTP_CloseFindNextHandle (internal) - * - * Deallocate session handle - * - * RETURNS - * TRUE on success - * FALSE on failure - * - */ -static void FTP_CloseFindNextHandle(LPWININETHANDLEHEADER hdr) +static void FTPFINDNEXT_Destroy(WININETHANDLEHEADER *hdr) { LPWININETFTPFINDNEXTW lpwfn = (LPWININETFTPFINDNEXTW) hdr; DWORD i; @@ -3125,35 +3221,98 @@ static void FTP_CloseFindNextHandle(LPWININETHANDLEHEADER hdr) HeapFree(GetProcessHeap(), 0, lpwfn); } -/*********************************************************************** - * FTP_CloseFileTransferHandle (internal) - * - * Closes the file transfer handle. This also 'cleans' the data queue of - * the 'transfer complete' message (this is a bit of a hack though :-/ ) - * - */ -static void FTP_CloseFileTransferHandle(LPWININETHANDLEHEADER hdr) +static DWORD WINAPI FTPFINDNEXT_FindNextFileProc(WININETFTPFINDNEXTW *find, LPVOID data) { - LPWININETFTPFILE lpwh = (LPWININETFTPFILE) hdr; - LPWININETFTPSESSIONW lpwfs = lpwh->lpFtpSession; - INT nResCode; + WIN32_FIND_DATAW *find_data = data; + DWORD res = ERROR_SUCCESS; - TRACE("\n"); + TRACE("index(%d) size(%d)\n", find->index, find->size); - WININET_Release(&lpwh->lpFtpSession->hdr); + ZeroMemory(find_data, sizeof(WIN32_FIND_DATAW)); - if (!lpwh->session_deleted) - lpwfs->download_in_progress = NULL; + if (find->index < find->size) { + FTP_ConvertFileProp(&find->lpafp[find->index], find_data); + find->index++; - if (lpwh->nDataSocket != -1) - closesocket(lpwh->nDataSocket); + TRACE("Name: %s\nSize: %d\n", debugstr_w(find_data->cFileName), find_data->nFileSizeLow); + }else { + res = ERROR_NO_MORE_FILES; + } - nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext); - if (nResCode > 0 && nResCode != 226) WARN("server reports failed transfer\n"); + if (find->hdr.dwFlags & INTERNET_FLAG_ASYNC) + { + INTERNET_ASYNC_RESULT iar; - HeapFree(GetProcessHeap(), 0, lpwh); + iar.dwResult = (res == ERROR_SUCCESS); + iar.dwError = res; + + INTERNET_SendCallback(&find->hdr, find->hdr.dwContext, + INTERNET_STATUS_REQUEST_COMPLETE, &iar, + sizeof(INTERNET_ASYNC_RESULT)); + } + + return res; } +static void FTPFINDNEXT_AsyncFindNextFileProc(WORKREQUEST *workRequest) +{ + struct WORKREQ_FTPFINDNEXTW *req = &workRequest->u.FtpFindNextW; + + FTPFINDNEXT_FindNextFileProc((WININETFTPFINDNEXTW*)workRequest->hdr, req->lpFindFileData); +} + +static DWORD FTPFINDNEXT_QueryOption(WININETHANDLEHEADER *hdr, DWORD option, void *buffer, DWORD *size, BOOL unicode) +{ + switch(option) { + case INTERNET_OPTION_HANDLE_TYPE: + TRACE("INTERNET_OPTION_HANDLE_TYPE\n"); + + if (*size < sizeof(ULONG)) + return ERROR_INSUFFICIENT_BUFFER; + + *size = sizeof(DWORD); + *(DWORD*)buffer = INTERNET_HANDLE_TYPE_FTP_FIND; + return ERROR_SUCCESS; + } + + FIXME("Not implemented option %d\n", option); + return ERROR_INTERNET_INVALID_OPTION; +} + +static DWORD FTPFINDNEXT_FindNextFileW(WININETHANDLEHEADER *hdr, void *data) +{ + WININETFTPFINDNEXTW *find = (WININETFTPFINDNEXTW*)hdr; + + if (find->lpFtpSession->lpAppInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC) + { + WORKREQUEST workRequest; + struct WORKREQ_FTPFINDNEXTW *req; + + workRequest.asyncproc = FTPFINDNEXT_AsyncFindNextFileProc; + workRequest.hdr = WININET_AddRef( &find->hdr ); + req = &workRequest.u.FtpFindNextW; + req->lpFindFileData = data; + + INTERNET_AsyncCall(&workRequest); + + return ERROR_SUCCESS; + } + + return FTPFINDNEXT_FindNextFileProc(find, data); +} + +static const HANDLEHEADERVtbl FTPFINDNEXTVtbl = { + FTPFINDNEXT_Destroy, + NULL, + FTPFINDNEXT_QueryOption, + NULL, + NULL, + NULL, + NULL, + NULL, + FTPFINDNEXT_FindNextFileW +}; + /*********************************************************************** * FTP_ReceiveFileList (internal) * @@ -3183,10 +3342,9 @@ static HINTERNET FTP_ReceiveFileList(LPWININETFTPSESSIONW lpwfs, INT nSocket, LP if (lpwfn) { lpwfn->hdr.htype = WH_HFTPFINDNEXT; + lpwfn->hdr.vtbl = &FTPFINDNEXTVtbl; lpwfn->hdr.dwContext = dwContext; - lpwfn->hdr.dwRefCount = 1; - lpwfn->hdr.close_connection = NULL; - lpwfn->hdr.destroy = FTP_CloseFindNextHandle; + lpwfn->hdr.refs = 1; lpwfn->hdr.lpfnStatusCB = lpwfs->hdr.lpfnStatusCB; lpwfn->index = 1; /* Next index is 1 since we return index 0 */ lpwfn->size = dwSize; @@ -3218,7 +3376,7 @@ static HINTERNET FTP_ReceiveFileList(LPWININETFTPSESSIONW lpwfs, INT nSocket, LP * FALSE on failure * */ -BOOL FTP_ConvertFileProp(LPFILEPROPERTIESW lpafp, LPWIN32_FIND_DATAW lpFindFileData) +static BOOL FTP_ConvertFileProp(LPFILEPROPERTIESW lpafp, LPWIN32_FIND_DATAW lpFindFileData) { BOOL bSuccess = FALSE; diff --git a/reactos/dll/win32/wininet/http.c b/reactos/dll/win32/wininet/http.c index 5e73714fe1c..3ae7ac301b7 100644 --- a/reactos/dll/win32/wininet/http.c +++ b/reactos/dll/win32/wininet/http.c @@ -55,6 +55,7 @@ #define NO_SHLWAPI_GDI #include "shlwapi.h" #include "sspi.h" +#include "wincrypt.h" #include "internet.h" #include "wine/debug.h" @@ -64,8 +65,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(wininet); -static const WCHAR g_szHttp1_0[] = {' ','H','T','T','P','/','1','.','0',0 }; -static const WCHAR g_szHttp1_1[] = {' ','H','T','T','P','/','1','.','1',0 }; +static const WCHAR g_szHttp1_0[] = {'H','T','T','P','/','1','.','0',0}; +static const WCHAR g_szHttp1_1[] = {'H','T','T','P','/','1','.','1',0}; static const WCHAR g_szReferer[] = {'R','e','f','e','r','e','r',0}; static const WCHAR g_szAccept[] = {'A','c','c','e','p','t',0}; static const WCHAR g_szUserAgent[] = {'U','s','e','r','-','A','g','e','n','t',0}; @@ -74,6 +75,7 @@ static const WCHAR szAuthorization[] = { 'A','u','t','h','o','r','i','z','a','t' static const WCHAR szProxy_Authorization[] = { 'P','r','o','x','y','-','A','u','t','h','o','r','i','z','a','t','i','o','n',0 }; static const WCHAR szStatus[] = { 'S','t','a','t','u','s',0 }; static const WCHAR szKeepAlive[] = {'K','e','e','p','-','A','l','i','v','e',0}; +static const WCHAR szGET[] = { 'G','E','T', 0 }; #define MAXHOSTNAME 100 #define MAX_FIELD_VALUE_LEN 256 @@ -100,16 +102,14 @@ struct HttpAuthInfo CtxtHandle ctx; TimeStamp exp; ULONG attr; + ULONG max_token; void *auth_data; unsigned int auth_data_len; BOOL finished; /* finished authenticating */ }; -static void HTTP_CloseConnection(LPWININETHANDLEHEADER hdr); -static void HTTP_CloseHTTPRequestHandle(LPWININETHANDLEHEADER hdr); -static void HTTP_CloseHTTPSessionHandle(LPWININETHANDLEHEADER hdr); static BOOL HTTP_OpenConnection(LPWININETHTTPREQW lpwhr); -static BOOL HTTP_GetResponseHeaders(LPWININETHTTPREQW lpwhr); +static BOOL HTTP_GetResponseHeaders(LPWININETHTTPREQW lpwhr, BOOL clear); static BOOL HTTP_ProcessHeader(LPWININETHTTPREQW lpwhr, LPCWSTR field, LPCWSTR value, DWORD dwModifier); static LPWSTR * HTTP_InterpretHttpHeader(LPCWSTR buffer); static BOOL HTTP_InsertCustomHeader(LPWININETHTTPREQW lpwhr, LPHTTPHEADERW lpHdr); @@ -122,7 +122,7 @@ static BOOL WINAPI HTTP_HttpQueryInfoW( LPWININETHTTPREQW lpwhr, DWORD static BOOL HTTP_HandleRedirect(LPWININETHTTPREQW lpwhr, LPCWSTR lpszUrl); static UINT HTTP_DecodeBase64(LPCWSTR base64, LPSTR bin); static BOOL HTTP_VerifyValidHeader(LPWININETHTTPREQW lpwhr, LPCWSTR field); - +static void HTTP_DrainContent(WININETHTTPREQW *req); LPHTTPHEADERW HTTP_GetHeader(LPWININETHTTPREQW req, LPCWSTR head) { @@ -213,16 +213,6 @@ static void AsyncHttpSendRequestProc(WORKREQUEST *workRequest) HeapFree(GetProcessHeap(), 0, req->lpszHeader); } -static void HTTP_FixVerb( LPWININETHTTPREQW lpwhr ) -{ - /* if the verb is NULL default to GET */ - if (NULL == lpwhr->lpszVerb) - { - static const WCHAR szGET[] = { 'G','E','T', 0 }; - lpwhr->lpszVerb = WININET_strdupW(szGET); - } -} - static void HTTP_FixURL( LPWININETHTTPREQW lpwhr) { static const WCHAR szSlash[] = { '/',0 }; @@ -259,7 +249,7 @@ static void HTTP_FixURL( LPWININETHTTPREQW lpwhr) } } -static LPWSTR HTTP_BuildHeaderRequestString( LPWININETHTTPREQW lpwhr, LPCWSTR verb, LPCWSTR path, BOOL http1_1 ) +static LPWSTR HTTP_BuildHeaderRequestString( LPWININETHTTPREQW lpwhr, LPCWSTR verb, LPCWSTR path, LPCWSTR version ) { LPWSTR requestString; DWORD len, n; @@ -273,7 +263,7 @@ static LPWSTR HTTP_BuildHeaderRequestString( LPWININETHTTPREQW lpwhr, LPCWSTR ve static const WCHAR sztwocrlf[] = {'\r','\n','\r','\n', 0}; /* allocate space for an array of all the string pointers to be added */ - len = (lpwhr->nCustHeaders)*4 + 9; + len = (lpwhr->nCustHeaders)*4 + 10; req = HeapAlloc( GetProcessHeap(), 0, len*sizeof(LPCWSTR) ); /* add the verb, path and HTTP version string */ @@ -281,7 +271,8 @@ static LPWSTR HTTP_BuildHeaderRequestString( LPWININETHTTPREQW lpwhr, LPCWSTR ve req[n++] = verb; req[n++] = szSpace; req[n++] = path; - req[n++] = http1_1 ? g_szHttp1_1 : g_szHttp1_0; + req[n++] = szSpace; + req[n++] = version; /* Append custom request headers */ for (i = 0; i < lpwhr->nCustHeaders; i++) @@ -318,7 +309,7 @@ static LPWSTR HTTP_BuildHeaderRequestString( LPWININETHTTPREQW lpwhr, LPCWSTR ve return requestString; } -static void HTTP_ProcessHeaders( LPWININETHTTPREQW lpwhr ) +static void HTTP_ProcessCookies( LPWININETHTTPREQW lpwhr ) { static const WCHAR szSet_Cookie[] = { 'S','e','t','-','C','o','o','k','i','e',0 }; int HeaderIndex; @@ -405,7 +396,7 @@ static inline BOOL is_basic_auth_value( LPCWSTR pszAuthValue ) { static const WCHAR szBasic[] = {'B','a','s','i','c'}; /* Note: not nul-terminated */ return !strncmpiW(pszAuthValue, szBasic, ARRAYSIZE(szBasic)) && - ((pszAuthValue[ARRAYSIZE(szBasic)] != ' ') || !pszAuthValue[ARRAYSIZE(szBasic)]); + ((pszAuthValue[ARRAYSIZE(szBasic)] == ' ') || !pszAuthValue[ARRAYSIZE(szBasic)]); } static BOOL HTTP_DoAuthorization( LPWININETHTTPREQW lpwhr, LPCWSTR pszAuthValue, @@ -418,8 +409,6 @@ static BOOL HTTP_DoAuthorization( LPWININETHTTPREQW lpwhr, LPCWSTR pszAuthValue, TRACE("%s\n", debugstr_w(pszAuthValue)); - if (!domain_and_username) return FALSE; - if (!pAuthInfo) { TimeStamp exp; @@ -449,9 +438,8 @@ static BOOL HTTP_DoAuthorization( LPWININETHTTPREQW lpwhr, LPCWSTR pszAuthValue, } else { + PVOID pAuthData; SEC_WINNT_AUTH_IDENTITY_W nt_auth_identity; - WCHAR *user = strchrW(domain_and_username, '\\'); - WCHAR *domain = domain_and_username; pAuthInfo->scheme = WININET_strdupW(pszAuthValue); if (!pAuthInfo->scheme) @@ -460,27 +448,49 @@ static BOOL HTTP_DoAuthorization( LPWININETHTTPREQW lpwhr, LPCWSTR pszAuthValue, return FALSE; } - if (user) user++; - else + if (domain_and_username) { - user = domain_and_username; - domain = NULL; - } - nt_auth_identity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; - nt_auth_identity.User = user; - nt_auth_identity.UserLength = strlenW(nt_auth_identity.User); - nt_auth_identity.Domain = domain; - nt_auth_identity.DomainLength = domain ? user - domain - 1 : 0; - nt_auth_identity.Password = password; - nt_auth_identity.PasswordLength = strlenW(nt_auth_identity.Password); + WCHAR *user = strchrW(domain_and_username, '\\'); + WCHAR *domain = domain_and_username; - /* FIXME: make sure scheme accepts SEC_WINNT_AUTH_IDENTITY before calling AcquireCredentialsHandle */ + /* FIXME: make sure scheme accepts SEC_WINNT_AUTH_IDENTITY before calling AcquireCredentialsHandle */ + + pAuthData = &nt_auth_identity; + + if (user) user++; + else + { + user = domain_and_username; + domain = NULL; + } + + nt_auth_identity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; + nt_auth_identity.User = user; + nt_auth_identity.UserLength = strlenW(nt_auth_identity.User); + nt_auth_identity.Domain = domain; + nt_auth_identity.DomainLength = domain ? user - domain - 1 : 0; + nt_auth_identity.Password = password; + nt_auth_identity.PasswordLength = strlenW(nt_auth_identity.Password); + } + else + /* use default credentials */ + pAuthData = NULL; sec_status = AcquireCredentialsHandleW(NULL, pAuthInfo->scheme, SECPKG_CRED_OUTBOUND, NULL, - &nt_auth_identity, NULL, + pAuthData, NULL, NULL, &pAuthInfo->cred, &exp); + if (sec_status == SEC_E_OK) + { + PSecPkgInfoW sec_pkg_info; + sec_status = QuerySecurityPackageInfoW(pAuthInfo->scheme, &sec_pkg_info); + if (sec_status == SEC_E_OK) + { + pAuthInfo->max_token = sec_pkg_info->cbMaxToken; + FreeContextBuffer(sec_pkg_info); + } + } if (sec_status != SEC_E_OK) { WARN("AcquireCredentialsHandleW for scheme %s failed with error 0x%08x\n", @@ -505,12 +515,19 @@ static BOOL HTTP_DoAuthorization( LPWININETHTTPREQW lpwhr, LPCWSTR pszAuthValue, if (is_basic_auth_value(pszAuthValue)) { - int userlen = WideCharToMultiByte(CP_UTF8, 0, domain_and_username, lstrlenW(domain_and_username), NULL, 0, NULL, NULL); - int passlen = WideCharToMultiByte(CP_UTF8, 0, password, lstrlenW(password), NULL, 0, NULL, NULL); + int userlen; + int passlen; char *auth_data; TRACE("basic authentication\n"); + /* we don't cache credentials for basic authentication, so we can't + * retrieve them if the application didn't pass us any credentials */ + if (!domain_and_username) return FALSE; + + userlen = WideCharToMultiByte(CP_UTF8, 0, domain_and_username, lstrlenW(domain_and_username), NULL, 0, NULL, NULL); + passlen = WideCharToMultiByte(CP_UTF8, 0, password, lstrlenW(password), NULL, 0, NULL, NULL); + /* length includes a nul terminator, which will be re-used for the ':' */ auth_data = HeapAlloc(GetProcessHeap(), 0, userlen + 1 + passlen); if (!auth_data) @@ -552,10 +569,10 @@ static BOOL HTTP_DoAuthorization( LPWININETHTTPREQW lpwhr, LPCWSTR pszAuthValue, HTTP_DecodeBase64(pszAuthData, in.pvBuffer); } - buffer = HeapAlloc(GetProcessHeap(), 0, 0x100); + buffer = HeapAlloc(GetProcessHeap(), 0, pAuthInfo->max_token); out.BufferType = SECBUFFER_TOKEN; - out.cbBuffer = 0x100; + out.cbBuffer = pAuthInfo->max_token; out.pvBuffer = buffer; out_desc.ulVersion = 0; @@ -563,7 +580,8 @@ static BOOL HTTP_DoAuthorization( LPWININETHTTPREQW lpwhr, LPCWSTR pszAuthValue, out_desc.pBuffers = &out; sec_status = InitializeSecurityContextW(first ? &pAuthInfo->cred : NULL, - first ? NULL : &pAuthInfo->ctx, NULL, + first ? NULL : &pAuthInfo->ctx, + first ? lpwhr->lpHttpSession->lpszServerName : NULL, context_req, 0, SECURITY_NETWORK_DREP, in.pvBuffer ? &in_desc : NULL, 0, &pAuthInfo->ctx, &out_desc, @@ -584,6 +602,7 @@ static BOOL HTTP_DoAuthorization( LPWININETHTTPREQW lpwhr, LPCWSTR pszAuthValue, else { ERR("InitializeSecurityContextW returned error 0x%08x\n", sec_status); + pAuthInfo->finished = TRUE; HeapFree(GetProcessHeap(), 0, out.pvBuffer); return FALSE; } @@ -604,7 +623,7 @@ static BOOL WINAPI HTTP_HttpAddRequestHeadersW(LPWININETHTTPREQW lpwhr, BOOL bSuccess = FALSE; DWORD len; - TRACE("copying header: %s\n", debugstr_w(lpszHeader)); + TRACE("copying header: %s\n", debugstr_wn(lpszHeader, dwHeaderLength)); if( dwHeaderLength == ~0U ) len = strlenW(lpszHeader); @@ -660,6 +679,12 @@ static BOOL WINAPI HTTP_HttpAddRequestHeadersW(LPWININETHTTPREQW lpwhr, * * Adds one or more HTTP header to the request handler * + * NOTE + * On Windows if dwHeaderLength includes the trailing '\0', then + * HttpAddRequestHeadersW() adds it too. However this results in an + * invalid Http header which is rejected by some servers so we probably + * don't need to match Windows on that point. + * * RETURNS * TRUE on success * FALSE on failure @@ -671,8 +696,7 @@ BOOL WINAPI HttpAddRequestHeadersW(HINTERNET hHttpRequest, BOOL bSuccess = FALSE; LPWININETHTTPREQW lpwhr; - TRACE("%p, %s, %i, %i\n", hHttpRequest, debugstr_w(lpszHeader), dwHeaderLength, - dwModifier); + TRACE("%p, %s, %i, %i\n", hHttpRequest, debugstr_wn(lpszHeader, dwHeaderLength), dwHeaderLength, dwModifier); if (!lpszHeader) return TRUE; @@ -708,8 +732,7 @@ BOOL WINAPI HttpAddRequestHeadersA(HINTERNET hHttpRequest, LPWSTR hdr; BOOL r; - TRACE("%p, %s, %i, %i\n", hHttpRequest, debugstr_a(lpszHeader), dwHeaderLength, - dwModifier); + TRACE("%p, %s, %i, %i\n", hHttpRequest, debugstr_an(lpszHeader, dwHeaderLength), dwHeaderLength, dwModifier); len = MultiByteToWideChar( CP_ACP, 0, lpszHeader, dwHeaderLength, NULL, 0 ); hdr = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ); @@ -724,26 +747,6 @@ BOOL WINAPI HttpAddRequestHeadersA(HINTERNET hHttpRequest, return r; } -/* read any content returned by the server so that the connection can be - * reused */ -static void HTTP_DrainContent(LPWININETHTTPREQW lpwhr) -{ - DWORD bytes_read; - - if (!NETCON_connected(&lpwhr->netConnection)) return; - - if (lpwhr->dwContentLength == -1) - NETCON_close(&lpwhr->netConnection); - - do - { - char buffer[2048]; - if (!INTERNET_ReadFile(&lpwhr->hdr, buffer, sizeof(buffer), &bytes_read, - TRUE, FALSE)) - return; - } while (bytes_read); -} - /*********************************************************************** * HttpEndRequestA (WININET.@) * @@ -798,7 +801,7 @@ BOOL WINAPI HttpEndRequestA(HINTERNET hRequest, FIXME("Do we need to translate info out of these buffer?\n"); - HeapFree(GetProcessHeap(),0,(LPVOID)ptrW->lpvBuffer); + HeapFree(GetProcessHeap(),0,ptrW->lpvBuffer); ptrW2 = ptrW->Next; HeapFree(GetProcessHeap(),0,ptrW); ptrW = ptrW2; @@ -845,15 +848,15 @@ BOOL WINAPI HttpEndRequestW(HINTERNET hRequest, SendAsyncCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0); - responseLen = HTTP_GetResponseHeaders(lpwhr); + responseLen = HTTP_GetResponseHeaders(lpwhr, TRUE); if (responseLen) rc = TRUE; SendAsyncCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, INTERNET_STATUS_RESPONSE_RECEIVED, &responseLen, sizeof(DWORD)); - /* process headers here. Is this right? */ - HTTP_ProcessHeaders(lpwhr); + /* process cookies here. Is this right? */ + HTTP_ProcessCookies(lpwhr); dwBufferSize = sizeof(lpwhr->dwContentLength); if (!HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_CONTENT_LENGTH, @@ -869,15 +872,17 @@ BOOL WINAPI HttpEndRequestW(HINTERNET hRequest, if(HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_STATUS_CODE,&dwCode,&dwCodeLength,NULL) && (dwCode==302 || dwCode==301)) { - WCHAR szNewLocation[2048]; + WCHAR szNewLocation[INTERNET_MAX_URL_LENGTH]; dwBufferSize=sizeof(szNewLocation); if(HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_LOCATION,szNewLocation,&dwBufferSize,NULL)) { - static const WCHAR szGET[] = { 'G','E','T', 0 }; /* redirects are always GETs */ HeapFree(GetProcessHeap(),0,lpwhr->lpszVerb); - lpwhr->lpszVerb = WININET_strdupW(szGET); + lpwhr->lpszVerb = WININET_strdupW(szGET); HTTP_DrainContent(lpwhr); + INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, + INTERNET_STATUS_REDIRECT, szNewLocation, + dwBufferSize); rc = HTTP_HandleRedirect(lpwhr, szNewLocation); if (rc) rc = HTTP_HttpSendRequestW(lpwhr, NULL, 0, NULL, 0, 0, TRUE); @@ -961,9 +966,10 @@ HINTERNET WINAPI HttpOpenRequestA(HINTERNET hHttpSession, { LPWSTR szVerb = NULL, szObjectName = NULL; LPWSTR szVersion = NULL, szReferrer = NULL, *szAcceptTypes = NULL; - INT len; - INT acceptTypesCount; + INT len, acceptTypesCount; HINTERNET rc = FALSE; + LPCSTR *types; + TRACE("(%p, %s, %s, %s, %s, %p, %08x, %08lx)\n", hHttpSession, debugstr_a(lpszVerb), debugstr_a(lpszObjectName), debugstr_a(lpszVersion), debugstr_a(lpszReferrer), lpszAcceptTypes, @@ -1005,24 +1011,37 @@ HINTERNET WINAPI HttpOpenRequestA(HINTERNET hHttpSession, MultiByteToWideChar(CP_ACP, 0, lpszReferrer, -1, szReferrer, len ); } - acceptTypesCount = 0; if (lpszAcceptTypes) { - /* find out how many there are */ - while (lpszAcceptTypes[acceptTypesCount] && *lpszAcceptTypes[acceptTypesCount]) - acceptTypesCount++; - szAcceptTypes = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR *) * (acceptTypesCount+1)); acceptTypesCount = 0; - while (lpszAcceptTypes[acceptTypesCount] && *lpszAcceptTypes[acceptTypesCount]) + types = lpszAcceptTypes; + while (*types) { - len = MultiByteToWideChar(CP_ACP, 0, lpszAcceptTypes[acceptTypesCount], - -1, NULL, 0 ); - szAcceptTypes[acceptTypesCount] = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); - if (!szAcceptTypes[acceptTypesCount] ) - goto end; - MultiByteToWideChar(CP_ACP, 0, lpszAcceptTypes[acceptTypesCount], - -1, szAcceptTypes[acceptTypesCount], len ); - acceptTypesCount++; + /* find out how many there are */ + if (((ULONG_PTR)*types >> 16) && **types) + { + TRACE("accept type: %s\n", debugstr_a(*types)); + acceptTypesCount++; + } + types++; + } + szAcceptTypes = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR *) * (acceptTypesCount+1)); + if (!szAcceptTypes) goto end; + + acceptTypesCount = 0; + types = lpszAcceptTypes; + while (*types) + { + if (((ULONG_PTR)*types >> 16) && **types) + { + len = MultiByteToWideChar(CP_ACP, 0, *types, -1, NULL, 0 ); + szAcceptTypes[acceptTypesCount] = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + if (!szAcceptTypes[acceptTypesCount]) goto end; + + MultiByteToWideChar(CP_ACP, 0, *types, -1, szAcceptTypes[acceptTypesCount], len); + acceptTypesCount++; + } + types++; } szAcceptTypes[acceptTypesCount] = NULL; } @@ -1141,9 +1160,9 @@ static UINT HTTP_DecodeBase64( LPCWSTR base64, LPSTR bin ) { signed char in[4]; - if (base64[0] > ARRAYSIZE(HTTP_Base64Dec) || + if (base64[0] >= ARRAYSIZE(HTTP_Base64Dec) || ((in[0] = HTTP_Base64Dec[base64[0]]) == -1) || - base64[1] > ARRAYSIZE(HTTP_Base64Dec) || + base64[1] >= ARRAYSIZE(HTTP_Base64Dec) || ((in[1] = HTTP_Base64Dec[base64[1]]) == -1)) { WARN("invalid base64: %s\n", debugstr_w(base64)); @@ -1184,71 +1203,85 @@ static UINT HTTP_DecodeBase64( LPCWSTR base64, LPSTR bin ) } /*********************************************************************** - * HTTP_InsertAuthorizationForHeader + * HTTP_InsertAuthorization * * Insert or delete the authorization field in the request header. */ -static BOOL HTTP_InsertAuthorizationForHeader( LPWININETHTTPREQW lpwhr, struct HttpAuthInfo *pAuthInfo, LPCWSTR header ) +static BOOL HTTP_InsertAuthorization( LPWININETHTTPREQW lpwhr, struct HttpAuthInfo *pAuthInfo, LPCWSTR header ) { - WCHAR *authorization = NULL; - - if (pAuthInfo && pAuthInfo->auth_data_len) + if (pAuthInfo) { static const WCHAR wszSpace[] = {' ',0}; static const WCHAR wszBasic[] = {'B','a','s','i','c',0}; unsigned int len; + WCHAR *authorization = NULL; - /* scheme + space + base64 encoded data (3/2/1 bytes data -> 4 bytes of characters) */ - len = strlenW(pAuthInfo->scheme)+1+((pAuthInfo->auth_data_len+2)*4)/3; - authorization = HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR)); - if (!authorization) - return FALSE; - - strcpyW(authorization, pAuthInfo->scheme); - strcatW(authorization, wszSpace); - HTTP_EncodeBase64(pAuthInfo->auth_data, - pAuthInfo->auth_data_len, - authorization+strlenW(authorization)); - - /* clear the data as it isn't valid now that it has been sent to the - * server, unless it's Basic authentication which doesn't do - * connection tracking */ - if (strcmpiW(pAuthInfo->scheme, wszBasic)) + if (pAuthInfo->auth_data_len) { - HeapFree(GetProcessHeap(), 0, pAuthInfo->auth_data); - pAuthInfo->auth_data = NULL; - pAuthInfo->auth_data_len = 0; + /* scheme + space + base64 encoded data (3/2/1 bytes data -> 4 bytes of characters) */ + len = strlenW(pAuthInfo->scheme)+1+((pAuthInfo->auth_data_len+2)*4)/3; + authorization = HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR)); + if (!authorization) + return FALSE; + + strcpyW(authorization, pAuthInfo->scheme); + strcatW(authorization, wszSpace); + HTTP_EncodeBase64(pAuthInfo->auth_data, + pAuthInfo->auth_data_len, + authorization+strlenW(authorization)); + + /* clear the data as it isn't valid now that it has been sent to the + * server, unless it's Basic authentication which doesn't do + * connection tracking */ + if (strcmpiW(pAuthInfo->scheme, wszBasic)) + { + HeapFree(GetProcessHeap(), 0, pAuthInfo->auth_data); + pAuthInfo->auth_data = NULL; + pAuthInfo->auth_data_len = 0; + } } + + TRACE("Inserting authorization: %s\n", debugstr_w(authorization)); + + HTTP_ProcessHeader(lpwhr, header, authorization, HTTP_ADDHDR_FLAG_REQ | HTTP_ADDHDR_FLAG_REPLACE); + + HeapFree(GetProcessHeap(), 0, authorization); } - - TRACE("Inserting authorization: %s\n", debugstr_w(authorization)); - - HTTP_ProcessHeader(lpwhr, header, authorization, - HTTP_ADDHDR_FLAG_REPLACE | HTTP_ADDHDR_FLAG_REQ); - - HeapFree(GetProcessHeap(), 0, authorization); - return TRUE; } -/*********************************************************************** - * HTTP_InsertAuthorization - * - * Insert the authorization field in the request header - */ -static BOOL HTTP_InsertAuthorization( LPWININETHTTPREQW lpwhr ) +static WCHAR *HTTP_BuildProxyRequestUrl(WININETHTTPREQW *req) { - return HTTP_InsertAuthorizationForHeader(lpwhr, lpwhr->pAuthInfo, szAuthorization); -} + WCHAR new_location[INTERNET_MAX_URL_LENGTH], *url; + DWORD size; -/*********************************************************************** - * HTTP_InsertProxyAuthorization - * - * Insert the proxy authorization field in the request header - */ -static BOOL HTTP_InsertProxyAuthorization( LPWININETHTTPREQW lpwhr ) -{ - return HTTP_InsertAuthorizationForHeader(lpwhr, lpwhr->pProxyAuthInfo, szProxy_Authorization); + size = sizeof(new_location); + if (HTTP_HttpQueryInfoW(req, HTTP_QUERY_LOCATION, new_location, &size, NULL)) + { + if (!(url = HeapAlloc( GetProcessHeap(), 0, size + sizeof(WCHAR) ))) return NULL; + strcpyW( url, new_location ); + } + else + { + static const WCHAR slash[] = { '/',0 }; + static const WCHAR format[] = { 'h','t','t','p',':','/','/','%','s',':','%','d',0 }; + static const WCHAR formatSSL[] = { 'h','t','t','p','s',':','/','/','%','s',':','%','d',0 }; + WININETHTTPSESSIONW *session = req->lpHttpSession; + + size = 16; /* "https://" + sizeof(port#) + ":/\0" */ + size += strlenW( session->lpszHostName ) + strlenW( req->lpszPath ); + + if (!(url = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) ))) return NULL; + + if (req->hdr.dwFlags & INTERNET_FLAG_SECURE) + sprintfW( url, formatSSL, session->lpszHostName, session->nHostPort ); + else + sprintfW( url, format, session->lpszHostName, session->nHostPort ); + if (req->lpszPath[0] != '/') strcatW( url, slash ); + strcatW( url, req->lpszPath ); + } + TRACE("url=%s\n", debugstr_w(url)); + return url; } /*********************************************************************** @@ -1259,13 +1292,10 @@ static BOOL HTTP_DealWithProxy( LPWININETAPPINFOW hIC, { WCHAR buf[MAXHOSTNAME]; WCHAR proxy[MAXHOSTNAME + 15]; /* 15 == "http://" + sizeof(port#) + ":/\0" */ - WCHAR* url; static WCHAR szNul[] = { 0 }; URL_COMPONENTSW UrlComponents; - static const WCHAR szHttp[] = { 'h','t','t','p',':','/','/',0 }, szSlash[] = { '/',0 } ; - static const WCHAR szFormat1[] = { 'h','t','t','p',':','/','/','%','s',0 }; - static const WCHAR szFormat2[] = { 'h','t','t','p',':','/','/','%','s',':','%','d',0 }; - int len; + static const WCHAR szHttp[] = { 'h','t','t','p',':','/','/',0 }; + static const WCHAR szFormat[] = { 'h','t','t','p',':','/','/','%','s',0 }; memset( &UrlComponents, 0, sizeof UrlComponents ); UrlComponents.dwStructSize = sizeof UrlComponents; @@ -1274,7 +1304,7 @@ static BOOL HTTP_DealWithProxy( LPWININETAPPINFOW hIC, if( CSTR_EQUAL != CompareStringW(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, hIC->lpszProxy,strlenW(szHttp),szHttp,strlenW(szHttp)) ) - sprintfW(proxy, szFormat1, hIC->lpszProxy); + sprintfW(proxy, szFormat, hIC->lpszProxy); else strcpyW(proxy, hIC->lpszProxy); if( !InternetCrackUrlW(proxy, 0, 0, &UrlComponents) ) @@ -1284,28 +1314,15 @@ static BOOL HTTP_DealWithProxy( LPWININETAPPINFOW hIC, if( !lpwhr->lpszPath ) lpwhr->lpszPath = szNul; - TRACE("server=%s path=%s\n", - debugstr_w(lpwhs->lpszHostName), debugstr_w(lpwhr->lpszPath)); - /* for constant 15 see above */ - len = strlenW(lpwhs->lpszHostName) + strlenW(lpwhr->lpszPath) + 15; - url = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR)); if(UrlComponents.nPort == INTERNET_INVALID_PORT_NUMBER) UrlComponents.nPort = INTERNET_DEFAULT_HTTP_PORT; - sprintfW(url, szFormat2, lpwhs->lpszHostName, lpwhs->nHostPort); - - if( lpwhr->lpszPath[0] != '/' ) - strcatW( url, szSlash ); - strcatW(url, lpwhr->lpszPath); - if(lpwhr->lpszPath != szNul) - HeapFree(GetProcessHeap(), 0, lpwhr->lpszPath); - lpwhr->lpszPath = url; - HeapFree(GetProcessHeap(), 0, lpwhs->lpszServerName); lpwhs->lpszServerName = WININET_strdupW(UrlComponents.lpszHostName); lpwhs->nServerPort = UrlComponents.nPort; + TRACE("proxy server=%s port=%d\n", debugstr_w(lpwhs->lpszServerName), lpwhs->nServerPort); return TRUE; } @@ -1334,6 +1351,522 @@ static BOOL HTTP_ResolveName(LPWININETHTTPREQW lpwhr) return TRUE; } + +/*********************************************************************** + * HTTPREQ_Destroy (internal) + * + * Deallocate request handle + * + */ +static void HTTPREQ_Destroy(WININETHANDLEHEADER *hdr) +{ + LPWININETHTTPREQW lpwhr = (LPWININETHTTPREQW) hdr; + DWORD i; + + TRACE("\n"); + + if(lpwhr->hCacheFile) + CloseHandle(lpwhr->hCacheFile); + + if(lpwhr->lpszCacheFile) { + DeleteFileW(lpwhr->lpszCacheFile); /* FIXME */ + HeapFree(GetProcessHeap(), 0, lpwhr->lpszCacheFile); + } + + WININET_Release(&lpwhr->lpHttpSession->hdr); + + HeapFree(GetProcessHeap(), 0, lpwhr->lpszPath); + HeapFree(GetProcessHeap(), 0, lpwhr->lpszVerb); + HeapFree(GetProcessHeap(), 0, lpwhr->lpszRawHeaders); + HeapFree(GetProcessHeap(), 0, lpwhr->lpszVersion); + HeapFree(GetProcessHeap(), 0, lpwhr->lpszStatusText); + + for (i = 0; i < lpwhr->nCustHeaders; i++) + { + HeapFree(GetProcessHeap(), 0, lpwhr->pCustHeaders[i].lpszField); + HeapFree(GetProcessHeap(), 0, lpwhr->pCustHeaders[i].lpszValue); + } + + HeapFree(GetProcessHeap(), 0, lpwhr->pCustHeaders); + HeapFree(GetProcessHeap(), 0, lpwhr); +} + +static void HTTPREQ_CloseConnection(WININETHANDLEHEADER *hdr) +{ + LPWININETHTTPREQW lpwhr = (LPWININETHTTPREQW) hdr; + LPWININETHTTPSESSIONW lpwhs = NULL; + + TRACE("%p\n",lpwhr); + + if (!NETCON_connected(&lpwhr->netConnection)) + return; + + if (lpwhr->pAuthInfo) + { + if (SecIsValidHandle(&lpwhr->pAuthInfo->ctx)) + DeleteSecurityContext(&lpwhr->pAuthInfo->ctx); + if (SecIsValidHandle(&lpwhr->pAuthInfo->cred)) + FreeCredentialsHandle(&lpwhr->pAuthInfo->cred); + + HeapFree(GetProcessHeap(), 0, lpwhr->pAuthInfo->auth_data); + HeapFree(GetProcessHeap(), 0, lpwhr->pAuthInfo->scheme); + HeapFree(GetProcessHeap(), 0, lpwhr->pAuthInfo); + lpwhr->pAuthInfo = NULL; + } + if (lpwhr->pProxyAuthInfo) + { + if (SecIsValidHandle(&lpwhr->pProxyAuthInfo->ctx)) + DeleteSecurityContext(&lpwhr->pProxyAuthInfo->ctx); + if (SecIsValidHandle(&lpwhr->pProxyAuthInfo->cred)) + FreeCredentialsHandle(&lpwhr->pProxyAuthInfo->cred); + + HeapFree(GetProcessHeap(), 0, lpwhr->pProxyAuthInfo->auth_data); + HeapFree(GetProcessHeap(), 0, lpwhr->pProxyAuthInfo->scheme); + HeapFree(GetProcessHeap(), 0, lpwhr->pProxyAuthInfo); + lpwhr->pProxyAuthInfo = NULL; + } + + lpwhs = lpwhr->lpHttpSession; + + INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, + INTERNET_STATUS_CLOSING_CONNECTION, 0, 0); + + NETCON_close(&lpwhr->netConnection); + + INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, + INTERNET_STATUS_CONNECTION_CLOSED, 0, 0); +} + +static DWORD HTTPREQ_QueryOption(WININETHANDLEHEADER *hdr, DWORD option, void *buffer, DWORD *size, BOOL unicode) +{ + WININETHTTPREQW *req = (WININETHTTPREQW*)hdr; + + switch(option) { + case INTERNET_OPTION_HANDLE_TYPE: + TRACE("INTERNET_OPTION_HANDLE_TYPE\n"); + + if (*size < sizeof(ULONG)) + return ERROR_INSUFFICIENT_BUFFER; + + *size = sizeof(DWORD); + *(DWORD*)buffer = INTERNET_HANDLE_TYPE_HTTP_REQUEST; + return ERROR_SUCCESS; + + case INTERNET_OPTION_URL: { + WCHAR url[INTERNET_MAX_URL_LENGTH]; + HTTPHEADERW *host; + DWORD len; + + static const WCHAR formatW[] = {'h','t','t','p',':','/','/','%','s','%','s',0}; + static const WCHAR hostW[] = {'H','o','s','t',0}; + + TRACE("INTERNET_OPTION_URL\n"); + + host = HTTP_GetHeader(req, hostW); + sprintfW(url, formatW, host->lpszValue, req->lpszPath); + TRACE("INTERNET_OPTION_URL: %s\n",debugstr_w(url)); + + if(unicode) { + len = (strlenW(url)+1) * sizeof(WCHAR); + if(*size < len) + return ERROR_INSUFFICIENT_BUFFER; + + *size = len; + strcpyW(buffer, url); + return ERROR_SUCCESS; + }else { + len = WideCharToMultiByte(CP_ACP, 0, url, -1, buffer, *size, NULL, NULL); + if(len > *size) + return ERROR_INSUFFICIENT_BUFFER; + + *size = len; + return ERROR_SUCCESS; + } + } + + case INTERNET_OPTION_DATAFILE_NAME: { + DWORD req_size; + + TRACE("INTERNET_OPTION_DATAFILE_NAME\n"); + + if(!req->lpszCacheFile) { + *size = 0; + return ERROR_INTERNET_ITEM_NOT_FOUND; + } + + if(unicode) { + req_size = (lstrlenW(req->lpszCacheFile)+1) * sizeof(WCHAR); + if(*size < req_size) + return ERROR_INSUFFICIENT_BUFFER; + + *size = req_size; + memcpy(buffer, req->lpszCacheFile, *size); + return ERROR_SUCCESS; + }else { + req_size = WideCharToMultiByte(CP_ACP, 0, req->lpszCacheFile, -1, NULL, 0, NULL, NULL); + if (req_size > *size) + return ERROR_INSUFFICIENT_BUFFER; + + *size = WideCharToMultiByte(CP_ACP, 0, req->lpszCacheFile, + -1, buffer, *size, NULL, NULL); + return ERROR_SUCCESS; + } + } + + case INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT: { + PCCERT_CONTEXT context; + + if(*size < sizeof(INTERNET_CERTIFICATE_INFOW)) { + *size = sizeof(INTERNET_CERTIFICATE_INFOW); + return ERROR_INSUFFICIENT_BUFFER; + } + + context = (PCCERT_CONTEXT)NETCON_GetCert(&(req->netConnection)); + if(context) { + INTERNET_CERTIFICATE_INFOW *info = (INTERNET_CERTIFICATE_INFOW*)buffer; + DWORD len; + + memset(info, 0, sizeof(INTERNET_CERTIFICATE_INFOW)); + info->ftExpiry = context->pCertInfo->NotAfter; + info->ftStart = context->pCertInfo->NotBefore; + if(unicode) { + len = CertNameToStrW(context->dwCertEncodingType, + &context->pCertInfo->Subject, CERT_SIMPLE_NAME_STR, NULL, 0); + info->lpszSubjectInfo = LocalAlloc(0, len*sizeof(WCHAR)); + if(info->lpszSubjectInfo) + CertNameToStrW(context->dwCertEncodingType, + &context->pCertInfo->Subject, CERT_SIMPLE_NAME_STR, + info->lpszSubjectInfo, len); + len = CertNameToStrW(context->dwCertEncodingType, + &context->pCertInfo->Issuer, CERT_SIMPLE_NAME_STR, NULL, 0); + info->lpszIssuerInfo = LocalAlloc(0, len*sizeof(WCHAR)); + if (info->lpszIssuerInfo) + CertNameToStrW(context->dwCertEncodingType, + &context->pCertInfo->Issuer, CERT_SIMPLE_NAME_STR, + info->lpszIssuerInfo, len); + }else { + INTERNET_CERTIFICATE_INFOA *infoA = (INTERNET_CERTIFICATE_INFOA*)info; + + len = CertNameToStrA(context->dwCertEncodingType, + &context->pCertInfo->Subject, CERT_SIMPLE_NAME_STR, NULL, 0); + infoA->lpszSubjectInfo = LocalAlloc(0, len); + if(infoA->lpszSubjectInfo) + CertNameToStrA(context->dwCertEncodingType, + &context->pCertInfo->Subject, CERT_SIMPLE_NAME_STR, + infoA->lpszSubjectInfo, len); + len = CertNameToStrA(context->dwCertEncodingType, + &context->pCertInfo->Issuer, CERT_SIMPLE_NAME_STR, NULL, 0); + infoA->lpszIssuerInfo = LocalAlloc(0, len); + if(infoA->lpszIssuerInfo) + CertNameToStrA(context->dwCertEncodingType, + &context->pCertInfo->Issuer, CERT_SIMPLE_NAME_STR, + infoA->lpszIssuerInfo, len); + } + + /* + * Contrary to MSDN, these do not appear to be set. + * lpszProtocolName + * lpszSignatureAlgName + * lpszEncryptionAlgName + * dwKeySize + */ + CertFreeCertificateContext(context); + return ERROR_SUCCESS; + } + } + } + + FIXME("Not implemented option %d\n", option); + return ERROR_INTERNET_INVALID_OPTION; +} + +static DWORD HTTPREQ_SetOption(WININETHANDLEHEADER *hdr, DWORD option, void *buffer, DWORD size) +{ + WININETHTTPREQW *req = (WININETHTTPREQW*)hdr; + + switch(option) { + case INTERNET_OPTION_SEND_TIMEOUT: + case INTERNET_OPTION_RECEIVE_TIMEOUT: + TRACE("INTERNET_OPTION_SEND/RECEIVE_TIMEOUT\n"); + + if (size != sizeof(DWORD)) + return ERROR_INVALID_PARAMETER; + + return NETCON_set_timeout(&req->netConnection, option == INTERNET_OPTION_SEND_TIMEOUT, + *(DWORD*)buffer); + } + + return ERROR_INTERNET_INVALID_OPTION; +} + +static DWORD HTTP_Read(WININETHTTPREQW *req, void *buffer, DWORD size, DWORD *read, BOOL sync) +{ + int bytes_read; + + if(!NETCON_recv(&req->netConnection, buffer, min(size, req->dwContentLength - req->dwContentRead), + sync ? MSG_WAITALL : 0, &bytes_read)) { + if(req->dwContentLength != -1 && req->dwContentRead != req->dwContentLength) + ERR("not all data received %d/%d\n", req->dwContentRead, req->dwContentLength); + + /* always return success, even if the network layer returns an error */ + *read = 0; + HTTP_FinishedReading(req); + return ERROR_SUCCESS; + } + + req->dwContentRead += bytes_read; + *read = bytes_read; + + if(req->lpszCacheFile) { + BOOL res; + DWORD dwBytesWritten; + + res = WriteFile(req->hCacheFile, buffer, bytes_read, &dwBytesWritten, NULL); + if(!res) + WARN("WriteFile failed: %u\n", GetLastError()); + } + + if(!bytes_read && (req->dwContentRead == req->dwContentLength)) + HTTP_FinishedReading(req); + + return ERROR_SUCCESS; +} + +static DWORD get_chunk_size(const char *buffer) +{ + const char *p; + DWORD size = 0; + + for (p = buffer; *p; p++) + { + if (*p >= '0' && *p <= '9') size = size * 16 + *p - '0'; + else if (*p >= 'a' && *p <= 'f') size = size * 16 + *p - 'a' + 10; + else if (*p >= 'A' && *p <= 'F') size = size * 16 + *p - 'A' + 10; + else if (*p == ';') break; + } + return size; +} + +static DWORD HTTP_ReadChunked(WININETHTTPREQW *req, void *buffer, DWORD size, DWORD *read, BOOL sync) +{ + char reply[MAX_REPLY_LEN], *p = buffer; + DWORD buflen, to_read, to_write = size; + int bytes_read; + + *read = 0; + for (;;) + { + if (*read == size) break; + + if (req->dwContentLength == ~0UL) /* new chunk */ + { + buflen = sizeof(reply); + if (!NETCON_getNextLine(&req->netConnection, reply, &buflen)) break; + + if (!(req->dwContentLength = get_chunk_size(reply))) + { + /* zero sized chunk marks end of transfer; read any trailing headers and return */ + HTTP_GetResponseHeaders(req, FALSE); + break; + } + } + to_read = min(to_write, req->dwContentLength - req->dwContentRead); + + if (!NETCON_recv(&req->netConnection, p, to_read, sync ? MSG_WAITALL : 0, &bytes_read)) + { + if (bytes_read != to_read) + ERR("Not all data received %d/%d\n", bytes_read, to_read); + + /* always return success, even if the network layer returns an error */ + *read = 0; + break; + } + if (!bytes_read) break; + + req->dwContentRead += bytes_read; + to_write -= bytes_read; + *read += bytes_read; + + if (req->lpszCacheFile) + { + if (!WriteFile(req->hCacheFile, p, bytes_read, NULL, NULL)) + WARN("WriteFile failed: %u\n", GetLastError()); + } + p += bytes_read; + + if (req->dwContentRead == req->dwContentLength) /* chunk complete */ + { + req->dwContentRead = 0; + req->dwContentLength = ~0UL; + + buflen = sizeof(reply); + if (!NETCON_getNextLine(&req->netConnection, reply, &buflen)) + { + ERR("Malformed chunk\n"); + *read = 0; + break; + } + } + } + if (!*read) HTTP_FinishedReading(req); + return ERROR_SUCCESS; +} + +static DWORD HTTPREQ_Read(WININETHTTPREQW *req, void *buffer, DWORD size, DWORD *read, BOOL sync) +{ + WCHAR encoding[20]; + DWORD buflen = sizeof(encoding); + static const WCHAR szChunked[] = {'c','h','u','n','k','e','d',0}; + + if (HTTP_HttpQueryInfoW(req, HTTP_QUERY_TRANSFER_ENCODING, encoding, &buflen, NULL) && + !strcmpiW(encoding, szChunked)) + { + return HTTP_ReadChunked(req, buffer, size, read, sync); + } + else + return HTTP_Read(req, buffer, size, read, sync); +} + +static DWORD HTTPREQ_ReadFile(WININETHANDLEHEADER *hdr, void *buffer, DWORD size, DWORD *read) +{ + WININETHTTPREQW *req = (WININETHTTPREQW*)hdr; + return HTTPREQ_Read(req, buffer, size, read, TRUE); +} + +static void HTTPREQ_AsyncReadFileExProc(WORKREQUEST *workRequest) +{ + struct WORKREQ_INTERNETREADFILEEXA const *data = &workRequest->u.InternetReadFileExA; + WININETHTTPREQW *req = (WININETHTTPREQW*)workRequest->hdr; + INTERNET_ASYNC_RESULT iar; + DWORD res; + + TRACE("INTERNETREADFILEEXA %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_ReadFileExA(WININETHANDLEHEADER *hdr, INTERNET_BUFFERSA *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_AsyncReadFileExProc; + workRequest.hdr = WININET_AddRef(&req->hdr); + workRequest.u.InternetReadFileExA.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; + + return NETCON_send(&lpwhr->netConnection, buffer, size, 0, (LPINT)written); +} + +static void HTTPREQ_AsyncQueryDataAvailableProc(WORKREQUEST *workRequest) +{ + WININETHTTPREQW *req = (WININETHTTPREQW*)workRequest->hdr; + INTERNET_ASYNC_RESULT iar; + char buffer[4048]; + + TRACE("%p\n", workRequest->hdr); + + iar.dwResult = NETCON_recv(&req->netConnection, buffer, + min(sizeof(buffer), req->dwContentLength - req->dwContentRead), + MSG_PEEK, (int *)&iar.dwError); + + INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE, &iar, + sizeof(INTERNET_ASYNC_RESULT)); +} + +static DWORD HTTPREQ_QueryDataAvailable(WININETHANDLEHEADER *hdr, DWORD *available, DWORD flags, DWORD_PTR ctx) +{ + WININETHTTPREQW *req = (WININETHTTPREQW*)hdr; + BYTE buffer[4048]; + BOOL async; + + TRACE("(%p %p %x %lx)\n", req, available, flags, ctx); + + if(!NETCON_query_data_available(&req->netConnection, available) || *available) + return ERROR_SUCCESS; + + /* Even if we are in async mode, we need to determine whether + * there is actually more data available. We do this by trying + * to peek only a single byte in async mode. */ + async = (req->lpHttpSession->lpAppInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC) != 0; + + if (NETCON_recv(&req->netConnection, buffer, + min(async ? 1 : sizeof(buffer), req->dwContentLength - req->dwContentRead), + MSG_PEEK, (int *)available) && async && *available) + { + WORKREQUEST workRequest; + + *available = 0; + workRequest.asyncproc = HTTPREQ_AsyncQueryDataAvailableProc; + workRequest.hdr = WININET_AddRef( &req->hdr ); + + INTERNET_AsyncCall(&workRequest); + + return ERROR_IO_PENDING; + } + + return ERROR_SUCCESS; +} + +static const HANDLEHEADERVtbl HTTPREQVtbl = { + HTTPREQ_Destroy, + HTTPREQ_CloseConnection, + HTTPREQ_QueryOption, + HTTPREQ_SetOption, + HTTPREQ_ReadFile, + HTTPREQ_ReadFileExA, + HTTPREQ_WriteFile, + HTTPREQ_QueryDataAvailable, + NULL +}; + /*********************************************************************** * HTTP_HttpOpenRequestW (internal) * @@ -1371,11 +1904,10 @@ HINTERNET WINAPI HTTP_HttpOpenRequestW(LPWININETHTTPSESSIONW lpwhs, goto lend; } lpwhr->hdr.htype = WH_HHTTPREQ; + lpwhr->hdr.vtbl = &HTTPREQVtbl; lpwhr->hdr.dwFlags = dwFlags; lpwhr->hdr.dwContext = dwContext; - lpwhr->hdr.dwRefCount = 1; - lpwhr->hdr.close_connection = HTTP_CloseConnection; - lpwhr->hdr.destroy = HTTP_CloseHTTPRequestHandle; + lpwhr->hdr.refs = 1; lpwhr->hdr.lpfnStatusCB = lpwhs->hdr.lpfnStatusCB; lpwhr->hdr.dwInternalFlags = lpwhs->hdr.dwInternalFlags & INET_CALLBACKW; @@ -1397,7 +1929,7 @@ HINTERNET WINAPI HTTP_HttpOpenRequestW(LPWININETHTTPSESSIONW lpwhs, goto lend; } - if (NULL != lpszObjectName && strlenW(lpszObjectName)) { + if (lpszObjectName && *lpszObjectName) { HRESULT rc; len = 0; @@ -1414,7 +1946,7 @@ HINTERNET WINAPI HTTP_HttpOpenRequestW(LPWININETHTTPSESSIONW lpwhs, } } - if (NULL != lpszReferrer && strlenW(lpszReferrer)) + if (lpszReferrer && *lpszReferrer) HTTP_ProcessHeader(lpwhr, HTTP_REFERER, lpszReferrer, HTTP_ADDREQ_FLAG_ADD | HTTP_ADDHDR_FLAG_REQ); if (lpszAcceptTypes) @@ -1430,13 +1962,12 @@ HINTERNET WINAPI HTTP_HttpOpenRequestW(LPWININETHTTPSESSIONW lpwhs, } } - if (NULL == lpszVerb) - { - static const WCHAR szGet[] = {'G','E','T',0}; - lpwhr->lpszVerb = WININET_strdupW(szGet); - } - else if (strlenW(lpszVerb)) - lpwhr->lpszVerb = WININET_strdupW(lpszVerb); + lpwhr->lpszVerb = WININET_strdupW(lpszVerb && *lpszVerb ? lpszVerb : szGET); + + if (lpszVersion) + lpwhr->lpszVersion = WININET_strdupW(lpszVersion); + else + lpwhr->lpszVersion = WININET_strdupW(g_szHttp1_1); HTTP_ProcessHeader(lpwhr, szHost, lpwhs->lpszHostName, HTTP_ADDREQ_FLAG_ADD | HTTP_ADDHDR_FLAG_REQ); @@ -1444,25 +1975,15 @@ HINTERNET WINAPI HTTP_HttpOpenRequestW(LPWININETHTTPSESSIONW lpwhs, lpwhs->nServerPort = (dwFlags & INTERNET_FLAG_SECURE ? INTERNET_DEFAULT_HTTPS_PORT : INTERNET_DEFAULT_HTTP_PORT); - lpwhs->nHostPort = lpwhs->nServerPort; + + if (lpwhs->nHostPort == INTERNET_INVALID_PORT_NUMBER) + lpwhs->nHostPort = (dwFlags & INTERNET_FLAG_SECURE ? + INTERNET_DEFAULT_HTTPS_PORT : + INTERNET_DEFAULT_HTTP_PORT); if (NULL != hIC->lpszProxy && hIC->lpszProxy[0] != 0) HTTP_DealWithProxy( hIC, lpwhs, lpwhr ); - if (hIC->lpszAgent) - { - WCHAR *agent_header; - static const WCHAR user_agent[] = {'U','s','e','r','-','A','g','e','n','t',':',' ','%','s','\r','\n',0 }; - - len = strlenW(hIC->lpszAgent) + strlenW(user_agent); - agent_header = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ); - sprintfW(agent_header, user_agent, hIC->lpszAgent ); - - HTTP_HttpAddRequestHeadersW(lpwhr, agent_header, strlenW(agent_header), - HTTP_ADDREQ_FLAG_ADD); - HeapFree(GetProcessHeap(), 0, agent_header); - } - Host = HTTP_GetHeader(lpwhr,szHost); len = lstrlenW(Host->lpszValue) + strlenW(szUrlForm); @@ -1511,6 +2032,25 @@ lend: return handle; } +/* read any content returned by the server so that the connection can be + * reused */ +static void HTTP_DrainContent(WININETHTTPREQW *req) +{ + DWORD bytes_read; + + if (!NETCON_connected(&req->netConnection)) return; + + if (req->dwContentLength == -1) + NETCON_close(&req->netConnection); + + do + { + char buffer[2048]; + if (HTTP_Read(req, buffer, sizeof(buffer), &bytes_read, TRUE) != ERROR_SUCCESS) + return; + } while (bytes_read); +} + static const WCHAR szAccept[] = { 'A','c','c','e','p','t',0 }; static const WCHAR szAccept_Charset[] = { 'A','c','c','e','p','t','-','C','h','a','r','s','e','t', 0 }; static const WCHAR szAccept_Encoding[] = { 'A','c','c','e','p','t','-','E','n','c','o','d','i','n','g',0 }; @@ -1664,27 +2204,26 @@ static BOOL WINAPI HTTP_HttpQueryInfoW( LPWININETHTTPREQW lpwhr, DWORD dwInfoLev { LPWSTR headers; DWORD len; - BOOL ret; + BOOL ret = FALSE; if (request_only) - headers = HTTP_BuildHeaderRequestString(lpwhr, lpwhr->lpszVerb, lpwhr->lpszPath, FALSE); + headers = HTTP_BuildHeaderRequestString(lpwhr, lpwhr->lpszVerb, lpwhr->lpszPath, lpwhr->lpszVersion); else headers = lpwhr->lpszRawHeaders; - len = strlenW(headers); - if (len + 1 > *lpdwBufferLength/sizeof(WCHAR)) + len = (strlenW(headers) + 1) * sizeof(WCHAR); + if (len > *lpdwBufferLength) { - *lpdwBufferLength = (len + 1) * sizeof(WCHAR); INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER); ret = FALSE; - } else + } + else if (lpBuffer) { - memcpy(lpBuffer, headers, (len+1)*sizeof(WCHAR)); - *lpdwBufferLength = len * sizeof(WCHAR); - - TRACE("returning data: %s\n", debugstr_wn((WCHAR*)lpBuffer, len)); + memcpy(lpBuffer, headers, len); + TRACE("returning data: %s\n", debugstr_wn(lpBuffer, len / sizeof(WCHAR))); ret = TRUE; } + *lpdwBufferLength = len; if (request_only) HeapFree(GetProcessHeap(), 0, headers); @@ -2010,11 +2549,20 @@ BOOL WINAPI HttpQueryInfoA(HINTERNET hHttpRequest, DWORD dwInfoLevel, if (lpBuffer) { + DWORD alloclen; len = (*lpdwBufferLength)*sizeof(WCHAR); - bufferW = HeapAlloc( GetProcessHeap(), 0, len ); + if ((dwInfoLevel & HTTP_QUERY_HEADER_MASK) == HTTP_QUERY_CUSTOM) + { + alloclen = MultiByteToWideChar( CP_ACP, 0, lpBuffer, -1, NULL, 0 ) * sizeof(WCHAR); + if (alloclen < len) + alloclen = len; + } + else + alloclen = len; + bufferW = HeapAlloc( GetProcessHeap(), 0, alloclen ); /* buffer is in/out because of HTTP_QUERY_CUSTOM */ if ((dwInfoLevel & HTTP_QUERY_HEADER_MASK) == HTTP_QUERY_CUSTOM) - MultiByteToWideChar(CP_ACP,0,lpBuffer,-1,bufferW,len); + MultiByteToWideChar( CP_ACP, 0, lpBuffer, -1, bufferW, alloclen / sizeof(WCHAR) ); } else { bufferW = NULL; @@ -2062,7 +2610,7 @@ BOOL WINAPI HttpSendRequestExA(HINTERNET hRequest, DWORD headerlen; LPWSTR header = NULL; - TRACE("(%p, %p, %p, %08x, %08lx): stub\n", hRequest, lpBuffersIn, + TRACE("(%p, %p, %p, %08x, %08lx)\n", hRequest, lpBuffersIn, lpBuffersOut, dwFlags, dwContext); if (lpBuffersIn) @@ -2301,24 +2849,37 @@ BOOL WINAPI HttpSendRequestA(HINTERNET hHttpRequest, LPCSTR lpszHeaders, return result; } +static BOOL HTTP_GetRequestURL(WININETHTTPREQW *req, LPWSTR buf) +{ + LPHTTPHEADERW host_header; + + static const WCHAR formatW[] = {'h','t','t','p',':','/','/','%','s','%','s',0}; + + host_header = HTTP_GetHeader(req, szHost); + if(!host_header) + return FALSE; + + sprintfW(buf, formatW, host_header->lpszValue, req->lpszPath); /* FIXME */ + return TRUE; +} + /*********************************************************************** * HTTP_HandleRedirect (internal) */ static BOOL HTTP_HandleRedirect(LPWININETHTTPREQW lpwhr, LPCWSTR lpszUrl) { + static const WCHAR szContentType[] = {'C','o','n','t','e','n','t','-','T','y','p','e',0}; + static const WCHAR szContentLength[] = {'C','o','n','t','e','n','t','-','L','e','n','g','t','h',0}; LPWININETHTTPSESSIONW lpwhs = lpwhr->lpHttpSession; LPWININETAPPINFOW hIC = lpwhs->lpAppInfo; - WCHAR path[2048]; + BOOL using_proxy = hIC->lpszProxy && hIC->lpszProxy[0]; + WCHAR path[INTERNET_MAX_URL_LENGTH]; + int index; if(lpszUrl[0]=='/') { /* if it's an absolute path, keep the same session info */ - lstrcpynW(path, lpszUrl, 2048); - } - else if (NULL != hIC->lpszProxy && hIC->lpszProxy[0] != 0) - { - TRACE("Redirect through proxy\n"); - lstrcpynW(path, lpszUrl, 2048); + lstrcpynW(path, lpszUrl, INTERNET_MAX_URL_LENGTH); } else { @@ -2398,6 +2959,7 @@ static BOOL HTTP_HandleRedirect(LPWININETHTTPREQW lpwhr, LPCWSTR lpszUrl) HeapFree(GetProcessHeap(), 0, combined_url); return FALSE; } + HeapFree(GetProcessHeap(), 0, combined_url); if (!strncmpW(szHttp, urlComponents.lpszScheme, strlenW(szHttp)) && @@ -2434,17 +2996,15 @@ static BOOL HTTP_HandleRedirect(LPWININETHTTPREQW lpwhr, LPCWSTR lpszUrl) */ /* consider the current host as the referrer */ - if (NULL != lpwhs->lpszServerName && strlenW(lpwhs->lpszServerName)) + if (lpwhs->lpszServerName && *lpwhs->lpszServerName) HTTP_ProcessHeader(lpwhr, HTTP_REFERER, lpwhs->lpszServerName, HTTP_ADDHDR_FLAG_REQ|HTTP_ADDREQ_FLAG_REPLACE| HTTP_ADDHDR_FLAG_ADD_IF_NEW); #endif - HeapFree(GetProcessHeap(), 0, lpwhs->lpszServerName); - lpwhs->lpszServerName = WININET_strdupW(hostName); HeapFree(GetProcessHeap(), 0, lpwhs->lpszHostName); if (urlComponents.nPort != INTERNET_DEFAULT_HTTP_PORT && - urlComponents.nPort != INTERNET_DEFAULT_HTTPS_PORT) + urlComponents.nPort != INTERNET_DEFAULT_HTTPS_PORT) { int len; static const WCHAR fmt[] = {'%','s',':','%','i',0}; @@ -2458,25 +3018,32 @@ static BOOL HTTP_HandleRedirect(LPWININETHTTPREQW lpwhr, LPCWSTR lpszUrl) HTTP_ProcessHeader(lpwhr, szHost, lpwhs->lpszHostName, HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE | HTTP_ADDHDR_FLAG_REQ); - HeapFree(GetProcessHeap(), 0, lpwhs->lpszUserName); lpwhs->lpszUserName = NULL; if (userName[0]) lpwhs->lpszUserName = WININET_strdupW(userName); - lpwhs->nServerPort = urlComponents.nPort; - if (!HTTP_ResolveName(lpwhr)) - return FALSE; + if (!using_proxy) + { + HeapFree(GetProcessHeap(), 0, lpwhs->lpszServerName); + lpwhs->lpszServerName = WININET_strdupW(hostName); + lpwhs->nServerPort = urlComponents.nPort; - NETCON_close(&lpwhr->netConnection); + if (!HTTP_ResolveName(lpwhr)) + return FALSE; - if (!NETCON_init(&lpwhr->netConnection,lpwhr->hdr.dwFlags & INTERNET_FLAG_SECURE)) - return FALSE; + NETCON_close(&lpwhr->netConnection); + + if (!NETCON_init(&lpwhr->netConnection,lpwhr->hdr.dwFlags & INTERNET_FLAG_SECURE)) + return FALSE; + } + else + TRACE("Redirect through proxy\n"); } HeapFree(GetProcessHeap(), 0, lpwhr->lpszPath); lpwhr->lpszPath=NULL; - if (strlenW(path)) + if (*path) { DWORD needed = 0; HRESULT rc; @@ -2494,6 +3061,14 @@ static BOOL HTTP_HandleRedirect(LPWININETHTTPREQW lpwhr, LPCWSTR lpszUrl) } } + /* Remove custom content-type/length headers on redirects. */ + index = HTTP_GetCustomHeaderIndex(lpwhr, szContentType, 0, TRUE); + if (0 <= index) + HTTP_DeleteCustomHeader(lpwhr, index); + index = HTTP_GetCustomHeaderIndex(lpwhr, szContentLength, 0, TRUE); + if (0 <= index) + HTTP_DeleteCustomHeader(lpwhr, index); + return TRUE; } @@ -2537,7 +3112,7 @@ static BOOL HTTP_SecureProxyConnect(LPWININETHTTPREQW lpwhr) lpszPath = HeapAlloc( GetProcessHeap(), 0, (lstrlenW( lpwhs->lpszHostName ) + 13)*sizeof(WCHAR) ); sprintfW( lpszPath, szFormat, lpwhs->lpszHostName, lpwhs->nHostPort ); - requestString = HTTP_BuildHeaderRequestString( lpwhr, szConnect, lpszPath, FALSE ); + requestString = HTTP_BuildHeaderRequestString( lpwhr, szConnect, lpszPath, g_szHttp1_1 ); HeapFree( GetProcessHeap(), 0, lpszPath ); len = WideCharToMultiByte( CP_ACP, 0, requestString, -1, @@ -2555,7 +3130,7 @@ static BOOL HTTP_SecureProxyConnect(LPWININETHTTPREQW lpwhr) if (!ret || cnt < 0) return FALSE; - responseLen = HTTP_GetResponseHeaders( lpwhr ); + responseLen = HTTP_GetResponseHeaders( lpwhr, TRUE ); if (!responseLen) return FALSE; @@ -2583,6 +3158,7 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders, BOOL loop_next; INTERNET_ASYNC_RESULT iar; static const WCHAR szClose[] = { 'C','l','o','s','e',0 }; + static const WCHAR szPost[] = { 'P','O','S','T',0 }; static const WCHAR szContentLength[] = { 'C','o','n','t','e','n','t','-','L','e','n','g','t','h',':',' ','%','l','i','\r','\n',0 }; WCHAR contentLengthStr[sizeof szContentLength/2 /* includes \r\n */ + 20 /* int */ ]; @@ -2594,10 +3170,28 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders, /* Clear any error information */ INTERNET_SetLastError(0); - HTTP_FixVerb(lpwhr); - - sprintfW(contentLengthStr, szContentLength, dwContentLength); - HTTP_HttpAddRequestHeadersW(lpwhr, contentLengthStr, -1L, HTTP_ADDREQ_FLAG_ADD | HTTP_ADDHDR_FLAG_REPLACE); + /* if the verb is NULL default to GET */ + if (!lpwhr->lpszVerb) + lpwhr->lpszVerb = WININET_strdupW(szGET); + + if (dwContentLength || !strcmpW(lpwhr->lpszVerb, szPost)) + { + sprintfW(contentLengthStr, szContentLength, dwContentLength); + HTTP_HttpAddRequestHeadersW(lpwhr, contentLengthStr, -1L, HTTP_ADDREQ_FLAG_ADD_IF_NEW); + } + if (lpwhr->lpHttpSession->lpAppInfo->lpszAgent) + { + WCHAR *agent_header; + static const WCHAR user_agent[] = {'U','s','e','r','-','A','g','e','n','t',':',' ','%','s','\r','\n',0}; + int len; + + len = strlenW(lpwhr->lpHttpSession->lpAppInfo->lpszAgent) + strlenW(user_agent); + agent_header = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + sprintfW(agent_header, user_agent, lpwhr->lpHttpSession->lpAppInfo->lpszAgent); + + HTTP_HttpAddRequestHeadersW(lpwhr, agent_header, strlenW(agent_header), HTTP_ADDREQ_FLAG_ADD_IF_NEW); + HeapFree(GetProcessHeap(), 0, agent_header); + } do { @@ -2622,8 +3216,8 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders, lpwhr->hdr.dwFlags & INTERNET_FLAG_KEEP_CONNECTION ? szKeepAlive : szClose, HTTP_ADDHDR_FLAG_REQ | HTTP_ADDHDR_FLAG_REPLACE); - HTTP_InsertAuthorization(lpwhr); - HTTP_InsertProxyAuthorization(lpwhr); + HTTP_InsertAuthorization(lpwhr, lpwhr->pAuthInfo, szAuthorization); + HTTP_InsertAuthorization(lpwhr, lpwhr->pProxyAuthInfo, szProxy_Authorization); /* add the headers the caller supplied */ if( lpszHeaders && dwHeaderLength ) @@ -2632,7 +3226,15 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders, HTTP_ADDREQ_FLAG_ADD | HTTP_ADDHDR_FLAG_REPLACE); } - requestString = HTTP_BuildHeaderRequestString(lpwhr, lpwhr->lpszVerb, lpwhr->lpszPath, FALSE); + if (lpwhr->lpHttpSession->lpAppInfo->lpszProxy && lpwhr->lpHttpSession->lpAppInfo->lpszProxy[0]) + { + WCHAR *url = HTTP_BuildProxyRequestUrl(lpwhr); + requestString = HTTP_BuildHeaderRequestString(lpwhr, lpwhr->lpszVerb, url, lpwhr->lpszVersion); + HeapFree(GetProcessHeap(), 0, url); + } + else + requestString = HTTP_BuildHeaderRequestString(lpwhr, lpwhr->lpszVerb, lpwhr->lpszPath, lpwhr->lpszVersion); + TRACE("Request header -> %s\n", debugstr_w(requestString) ); @@ -2668,6 +3270,8 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders, { DWORD dwBufferSize; DWORD dwStatusCode; + WCHAR encoding[20]; + static const WCHAR szChunked[] = {'c','h','u','n','k','e','d',0}; INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0); @@ -2675,7 +3279,7 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders, if (cnt < 0) goto lend; - responseLen = HTTP_GetResponseHeaders(lpwhr); + responseLen = HTTP_GetResponseHeaders(lpwhr, TRUE); if (responseLen) bSuccess = TRUE; @@ -2683,7 +3287,7 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders, INTERNET_STATUS_RESPONSE_RECEIVED, &responseLen, sizeof(DWORD)); - HTTP_ProcessHeaders(lpwhr); + HTTP_ProcessCookies(lpwhr); dwBufferSize = sizeof(lpwhr->dwContentLength); if (!HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_CONTENT_LENGTH, @@ -2693,6 +3297,15 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders, if (lpwhr->dwContentLength == 0) HTTP_FinishedReading(lpwhr); + /* Correct the case where both a Content-Length and Transfer-encoding = chunked are set */ + + dwBufferSize = sizeof(encoding); + if (HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_TRANSFER_ENCODING, encoding, &dwBufferSize, NULL) && + !strcmpiW(encoding, szChunked)) + { + lpwhr->dwContentLength = -1; + } + dwBufferSize = sizeof(dwStatusCode); if (!HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_STATUS_CODE, &dwStatusCode,&dwBufferSize,NULL)) @@ -2700,7 +3313,7 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders, if (!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_AUTO_REDIRECT) && bSuccess) { - WCHAR szNewLocation[2048]; + WCHAR szNewLocation[INTERNET_MAX_URL_LENGTH]; dwBufferSize=sizeof(szNewLocation); if ((dwStatusCode==HTTP_STATUS_REDIRECT || dwStatusCode==HTTP_STATUS_MOVED) && HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_LOCATION,szNewLocation,&dwBufferSize,NULL)) @@ -2758,13 +3371,39 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders, } while (loop_next); + /* FIXME: Better check, when we have to create the cache file */ + if(bSuccess && (lpwhr->hdr.dwFlags & INTERNET_FLAG_NEED_FILE)) { + WCHAR url[INTERNET_MAX_URL_LENGTH]; + WCHAR cacheFileName[MAX_PATH+1]; + BOOL b; + + b = HTTP_GetRequestURL(lpwhr, url); + if(!b) { + WARN("Could not get URL\n"); + goto lend; + } + + b = CreateUrlCacheEntryW(url, lpwhr->dwContentLength > 0 ? lpwhr->dwContentLength : 0, NULL, cacheFileName, 0); + if(b) { + lpwhr->lpszCacheFile = WININET_strdupW(cacheFileName); + lpwhr->hCacheFile = CreateFileW(lpwhr->lpszCacheFile, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, + NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if(lpwhr->hCacheFile == INVALID_HANDLE_VALUE) { + WARN("Could not create file: %u\n", GetLastError()); + lpwhr->hCacheFile = NULL; + } + }else { + WARN("Could not create cache entry: %08x\n", GetLastError()); + } + } + lend: HeapFree(GetProcessHeap(), 0, requestString); /* TODO: send notification for P3P header */ - iar.dwResult = (DWORD)bSuccess; + iar.dwResult = (DWORD_PTR)lpwhr->hdr.hInternet; iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError(); INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, @@ -2775,6 +3414,58 @@ lend: return bSuccess; } +/*********************************************************************** + * HTTPSESSION_Destroy (internal) + * + * Deallocate session handle + * + */ +static void HTTPSESSION_Destroy(WININETHANDLEHEADER *hdr) +{ + LPWININETHTTPSESSIONW lpwhs = (LPWININETHTTPSESSIONW) hdr; + + TRACE("%p\n", lpwhs); + + WININET_Release(&lpwhs->lpAppInfo->hdr); + + HeapFree(GetProcessHeap(), 0, lpwhs->lpszHostName); + HeapFree(GetProcessHeap(), 0, lpwhs->lpszServerName); + HeapFree(GetProcessHeap(), 0, lpwhs->lpszPassword); + HeapFree(GetProcessHeap(), 0, lpwhs->lpszUserName); + HeapFree(GetProcessHeap(), 0, lpwhs); +} + +static DWORD HTTPSESSION_QueryOption(WININETHANDLEHEADER *hdr, DWORD option, void *buffer, DWORD *size, BOOL unicode) +{ + switch(option) { + case INTERNET_OPTION_HANDLE_TYPE: + TRACE("INTERNET_OPTION_HANDLE_TYPE\n"); + + if (*size < sizeof(ULONG)) + return ERROR_INSUFFICIENT_BUFFER; + + *size = sizeof(DWORD); + *(DWORD*)buffer = INTERNET_HANDLE_TYPE_CONNECT_HTTP; + return ERROR_SUCCESS; + } + + FIXME("Not implemented option %d\n", option); + return ERROR_INTERNET_INVALID_OPTION; +} + +static const HANDLEHEADERVtbl HTTPSESSIONVtbl = { + HTTPSESSION_Destroy, + NULL, + HTTPSESSION_QueryOption, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL +}; + + /*********************************************************************** * HTTP_Connect (internal) * @@ -2790,12 +3481,17 @@ HINTERNET HTTP_Connect(LPWININETAPPINFOW hIC, LPCWSTR lpszServerName, LPCWSTR lpszPassword, DWORD dwFlags, DWORD_PTR dwContext, DWORD dwInternalFlags) { - BOOL bSuccess = FALSE; LPWININETHTTPSESSIONW lpwhs = NULL; HINTERNET handle = NULL; TRACE("-->\n"); + if (!lpszServerName || !lpszServerName[0]) + { + INTERNET_SetLastError(ERROR_INVALID_PARAMETER); + goto lerror; + } + assert( hIC->hdr.htype == WH_HINIT ); lpwhs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WININETHTTPSESSIONW)); @@ -2810,12 +3506,11 @@ HINTERNET HTTP_Connect(LPWININETAPPINFOW hIC, LPCWSTR lpszServerName, */ lpwhs->hdr.htype = WH_HHTTPSESSION; + lpwhs->hdr.vtbl = &HTTPSESSIONVtbl; lpwhs->hdr.dwFlags = dwFlags; lpwhs->hdr.dwContext = dwContext; lpwhs->hdr.dwInternalFlags = dwInternalFlags | (hIC->hdr.dwInternalFlags & INET_CALLBACKW); - lpwhs->hdr.dwRefCount = 1; - lpwhs->hdr.close_connection = NULL; - lpwhs->hdr.destroy = HTTP_CloseHTTPSessionHandle; + lpwhs->hdr.refs = 1; lpwhs->hdr.lpfnStatusCB = hIC->hdr.lpfnStatusCB; WININET_AddRef( &hIC->hdr ); @@ -2856,8 +3551,6 @@ HINTERNET HTTP_Connect(LPWININETAPPINFOW hIC, LPCWSTR lpszServerName, sizeof(handle)); } - bSuccess = TRUE; - lerror: if( lpwhs ) WININET_Release( &lpwhs->hdr ); @@ -2987,7 +3680,7 @@ static void HTTP_clear_response_headers( LPWININETHTTPREQW lpwhr ) * TRUE on success * FALSE on error */ -static INT HTTP_GetResponseHeaders(LPWININETHTTPREQW lpwhr) +static INT HTTP_GetResponseHeaders(LPWININETHTTPREQW lpwhr, BOOL clear) { INT cbreaks = 0; WCHAR buffer[MAX_REPLY_LEN]; @@ -2995,6 +3688,7 @@ static INT HTTP_GetResponseHeaders(LPWININETHTTPREQW lpwhr) BOOL bSuccess = FALSE; INT rc = 0; static const WCHAR szCrLf[] = {'\r','\n',0}; + static const WCHAR szHundred[] = {'1','0','0',0}; char bufferA[MAX_REPLY_LEN]; LPWSTR status_code, status_text; DWORD cchMaxRawHeaders = 1024; @@ -3004,31 +3698,56 @@ static INT HTTP_GetResponseHeaders(LPWININETHTTPREQW lpwhr) TRACE("-->\n"); /* clear old response headers (eg. from a redirect response) */ - HTTP_clear_response_headers( lpwhr ); + if (clear) HTTP_clear_response_headers( lpwhr ); if (!NETCON_connected(&lpwhr->netConnection)) goto lend; - /* - * HACK peek at the buffer - */ -#if 0 - /* This is Wine code, we don't support MSG_PEEK yet so we have to do it - a bit different */ - NETCON_recv(&lpwhr->netConnection, buffer, buflen, MSG_PEEK, &rc); -#endif + do { + /* + * HACK peek at the buffer + */ + buflen = MAX_REPLY_LEN; + NETCON_recv(&lpwhr->netConnection, buffer, buflen, MSG_PEEK, &rc); - /* - * We should first receive 'HTTP/1.x nnn OK' where nnn is the status code. - */ - buflen = MAX_REPLY_LEN; - memset(buffer, 0, MAX_REPLY_LEN); - if (!NETCON_getNextLine(&lpwhr->netConnection, bufferA, &buflen)) - goto lend; -#if 1 - rc = buflen; -#endif - MultiByteToWideChar( CP_ACP, 0, bufferA, buflen, buffer, MAX_REPLY_LEN ); + /* + * We should first receive 'HTTP/1.x nnn OK' where nnn is the status code. + */ + memset(buffer, 0, MAX_REPLY_LEN); + if (!NETCON_getNextLine(&lpwhr->netConnection, bufferA, &buflen)) + goto lend; + MultiByteToWideChar( CP_ACP, 0, bufferA, buflen, buffer, MAX_REPLY_LEN ); + + /* split the version from the status code */ + status_code = strchrW( buffer, ' ' ); + if( !status_code ) + goto lend; + *status_code++=0; + + /* split the status code from the status text */ + status_text = strchrW( status_code, ' ' ); + if( !status_text ) + goto lend; + *status_text++=0; + + TRACE("version [%s] status code [%s] status text [%s]\n", + debugstr_w(buffer), debugstr_w(status_code), debugstr_w(status_text) ); + + } while (!strcmpW(status_code, szHundred)); /* ignore "100 Continue" responses */ + + /* Add status code */ + HTTP_ProcessHeader(lpwhr, szStatus, status_code, + HTTP_ADDHDR_FLAG_REPLACE); + + HeapFree(GetProcessHeap(),0,lpwhr->lpszVersion); + HeapFree(GetProcessHeap(),0,lpwhr->lpszStatusText); + + lpwhr->lpszVersion= WININET_strdupW(buffer); + lpwhr->lpszStatusText = WININET_strdupW(status_text); + + /* Restore the spaces */ + *(status_code-1) = ' '; + *(status_text-1) = ' '; /* regenerate raw headers */ while (cchRawHeaders + buflen + strlenW(szCrLf) > cchMaxRawHeaders) @@ -3042,30 +3761,6 @@ static INT HTTP_GetResponseHeaders(LPWININETHTTPREQW lpwhr) cchRawHeaders += sizeof(szCrLf)/sizeof(szCrLf[0])-1; lpszRawHeaders[cchRawHeaders] = '\0'; - /* split the version from the status code */ - status_code = strchrW( buffer, ' ' ); - if( !status_code ) - goto lend; - *status_code++=0; - - /* split the status code from the status text */ - status_text = strchrW( status_code, ' ' ); - if( !status_text ) - goto lend; - *status_text++=0; - - TRACE("version [%s] status code [%s] status text [%s]\n", - debugstr_w(buffer), debugstr_w(status_code), debugstr_w(status_text) ); - - HTTP_ProcessHeader(lpwhr, szStatus, status_code, - HTTP_ADDHDR_FLAG_REPLACE); - - HeapFree(GetProcessHeap(),0,lpwhr->lpszVersion); - HeapFree(GetProcessHeap(),0,lpwhr->lpszStatusText); - - lpwhr->lpszVersion= WININET_strdupW(buffer); - lpwhr->lpszStatusText = WININET_strdupW(status_text); - /* Parse each response line */ do { @@ -3320,57 +4015,6 @@ static BOOL HTTP_ProcessHeader(LPWININETHTTPREQW lpwhr, LPCWSTR field, LPCWSTR v } -/*********************************************************************** - * HTTP_CloseConnection (internal) - * - * Close socket connection - * - */ -static void HTTP_CloseConnection(LPWININETHANDLEHEADER hdr) -{ - LPWININETHTTPREQW lpwhr = (LPWININETHTTPREQW) hdr; - LPWININETHTTPSESSIONW lpwhs = NULL; - LPWININETAPPINFOW hIC = NULL; - - TRACE("%p\n",lpwhr); - - if (!NETCON_connected(&lpwhr->netConnection)) - return; - - if (lpwhr->pAuthInfo) - { - DeleteSecurityContext(&lpwhr->pAuthInfo->ctx); - FreeCredentialsHandle(&lpwhr->pAuthInfo->cred); - - HeapFree(GetProcessHeap(), 0, lpwhr->pAuthInfo->auth_data); - HeapFree(GetProcessHeap(), 0, lpwhr->pAuthInfo->scheme); - HeapFree(GetProcessHeap(), 0, lpwhr->pAuthInfo); - lpwhr->pAuthInfo = NULL; - } - if (lpwhr->pProxyAuthInfo) - { - DeleteSecurityContext(&lpwhr->pProxyAuthInfo->ctx); - FreeCredentialsHandle(&lpwhr->pProxyAuthInfo->cred); - - HeapFree(GetProcessHeap(), 0, lpwhr->pProxyAuthInfo->auth_data); - HeapFree(GetProcessHeap(), 0, lpwhr->pProxyAuthInfo->scheme); - HeapFree(GetProcessHeap(), 0, lpwhr->pProxyAuthInfo); - lpwhr->pProxyAuthInfo = NULL; - } - - lpwhs = lpwhr->lpHttpSession; - hIC = lpwhs->lpAppInfo; - - INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, - INTERNET_STATUS_CLOSING_CONNECTION, 0, 0); - - NETCON_close(&lpwhr->netConnection); - - INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, - INTERNET_STATUS_CONNECTION_CLOSED, 0, 0); -} - - /*********************************************************************** * HTTP_FinishedReading (internal) * @@ -3379,16 +4023,26 @@ static void HTTP_CloseConnection(LPWININETHANDLEHEADER hdr) */ BOOL HTTP_FinishedReading(LPWININETHTTPREQW lpwhr) { - WCHAR szConnectionResponse[20]; - DWORD dwBufferSize = sizeof(szConnectionResponse); + WCHAR szVersion[10]; + DWORD dwBufferSize = sizeof(szVersion); TRACE("\n"); - if (!HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_CONNECTION, szConnectionResponse, + /* as per RFC 2068, S8.1.2.1, if the client is HTTP/1.1 then assume that + * the connection is keep-alive by default */ + if (!HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_VERSION, szVersion, &dwBufferSize, NULL) || - strcmpiW(szConnectionResponse, szKeepAlive)) + strcmpiW(szVersion, g_szHttp1_1)) { - HTTP_CloseConnection(&lpwhr->hdr); + WCHAR szConnectionResponse[20]; + dwBufferSize = sizeof(szConnectionResponse); + if ((!HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_CONNECTION, szConnectionResponse, &dwBufferSize, NULL) || + strcmpiW(szConnectionResponse, szKeepAlive)) && + (!HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_PROXY_CONNECTION, szConnectionResponse, &dwBufferSize, NULL) || + strcmpiW(szConnectionResponse, szKeepAlive))) + { + HTTPREQ_CloseConnection(&lpwhr->hdr); + } } /* FIXME: store data in the URL cache here */ @@ -3396,59 +4050,6 @@ BOOL HTTP_FinishedReading(LPWININETHTTPREQW lpwhr) return TRUE; } -/*********************************************************************** - * HTTP_CloseHTTPRequestHandle (internal) - * - * Deallocate request handle - * - */ -static void HTTP_CloseHTTPRequestHandle(LPWININETHANDLEHEADER hdr) -{ - DWORD i; - LPWININETHTTPREQW lpwhr = (LPWININETHTTPREQW) hdr; - - TRACE("\n"); - - WININET_Release(&lpwhr->lpHttpSession->hdr); - - HeapFree(GetProcessHeap(), 0, lpwhr->lpszPath); - HeapFree(GetProcessHeap(), 0, lpwhr->lpszVerb); - HeapFree(GetProcessHeap(), 0, lpwhr->lpszRawHeaders); - HeapFree(GetProcessHeap(), 0, lpwhr->lpszVersion); - HeapFree(GetProcessHeap(), 0, lpwhr->lpszStatusText); - - for (i = 0; i < lpwhr->nCustHeaders; i++) - { - HeapFree(GetProcessHeap(), 0, lpwhr->pCustHeaders[i].lpszField); - HeapFree(GetProcessHeap(), 0, lpwhr->pCustHeaders[i].lpszValue); - } - - HeapFree(GetProcessHeap(), 0, lpwhr->pCustHeaders); - HeapFree(GetProcessHeap(), 0, lpwhr); -} - - -/*********************************************************************** - * HTTP_CloseHTTPSessionHandle (internal) - * - * Deallocate session handle - * - */ -static void HTTP_CloseHTTPSessionHandle(LPWININETHANDLEHEADER hdr) -{ - LPWININETHTTPSESSIONW lpwhs = (LPWININETHTTPSESSIONW) hdr; - - TRACE("%p\n", lpwhs); - - WININET_Release(&lpwhs->lpAppInfo->hdr); - - HeapFree(GetProcessHeap(), 0, lpwhs->lpszHostName); - HeapFree(GetProcessHeap(), 0, lpwhs->lpszServerName); - HeapFree(GetProcessHeap(), 0, lpwhs->lpszPassword); - HeapFree(GetProcessHeap(), 0, lpwhs->lpszUserName); - HeapFree(GetProcessHeap(), 0, lpwhs); -} - /*********************************************************************** * HTTP_GetCustomHeaderIndex (internal) @@ -3555,13 +4156,11 @@ static BOOL HTTP_DeleteCustomHeader(LPWININETHTTPREQW lpwhr, DWORD index) */ static BOOL HTTP_VerifyValidHeader(LPWININETHTTPREQW lpwhr, LPCWSTR field) { - BOOL rc = TRUE; - /* Accept-Encoding is stripped from HTTP/1.0 requests. It is invalid */ - if (strcmpiW(field,szAccept_Encoding)==0) + if (!strcmpW(lpwhr->lpszVersion, g_szHttp1_0) && !strcmpiW(field, szAccept_Encoding)) return FALSE; - return rc; + return TRUE; } /*********************************************************************** diff --git a/reactos/dll/win32/wininet/internet.c b/reactos/dll/win32/wininet/internet.c index b0357a2b55c..2301d9c8628 100644 --- a/reactos/dll/win32/wininet/internet.c +++ b/reactos/dll/win32/wininet/internet.c @@ -38,6 +38,12 @@ #ifdef HAVE_SYS_SOCKET_H # include #endif +#ifdef HAVE_POLL_H +#include +#endif +#ifdef HAVE_SYS_POLL_H +# include +#endif #ifdef HAVE_SYS_TIME_H # include #endif @@ -59,7 +65,6 @@ #include "winerror.h" #define NO_SHLWAPI_STREAM #include "shlwapi.h" -#include "wincrypt.h" #include "wine/exception.h" @@ -67,7 +72,6 @@ #include "resource.h" #include "wine/unicode.h" -#define CP_UNIXCP CP_THREAD_ACP WINE_DEFAULT_DEBUG_CHANNEL(wininet); @@ -79,10 +83,6 @@ typedef struct CHAR response[MAX_REPLY_LEN]; } WITHREADERROR, *LPWITHREADERROR; -static VOID INTERNET_CloseHandle(LPWININETHANDLEHEADER hdr); -HINTERNET WINAPI INTERNET_InternetOpenUrlW(LPWININETAPPINFOW hIC, LPCWSTR lpszUrl, - LPCWSTR lpszHeaders, DWORD dwHeadersLength, DWORD dwFlags, DWORD_PTR dwContext); - static DWORD g_dwTlsErrIndex = TLS_OUT_OF_INDEXES; static HMODULE WININET_hModule; @@ -147,8 +147,8 @@ end: LPWININETHANDLEHEADER WININET_AddRef( LPWININETHANDLEHEADER info ) { - info->dwRefCount++; - TRACE("%p -> refcount = %d\n", info, info->dwRefCount ); + ULONG refs = InterlockedIncrement(&info->refs); + TRACE("%p -> refcount = %d\n", info, refs ); return info; } @@ -172,14 +172,14 @@ LPWININETHANDLEHEADER WININET_GetObject( HINTERNET hinternet ) BOOL WININET_Release( LPWININETHANDLEHEADER info ) { - info->dwRefCount--; - TRACE( "object %p refcount = %d\n", info, info->dwRefCount ); - if( !info->dwRefCount ) + ULONG refs = InterlockedDecrement(&info->refs); + TRACE( "object %p refcount = %d\n", info, refs ); + if( !refs ) { - if ( info->close_connection ) + if ( info->vtbl->CloseConnection ) { TRACE( "closing connection %p\n", info); - info->close_connection( info ); + info->vtbl->CloseConnection( info ); } INTERNET_SendCallback(info, info->dwContext, INTERNET_STATUS_HANDLE_CLOSING, &info->hInternet, @@ -187,7 +187,7 @@ BOOL WININET_Release( LPWININETHANDLEHEADER info ) TRACE( "destroying object %p\n", info); if ( info->htype != WH_HINIT ) list_remove( &info->entry ); - info->destroy( info ); + info->vtbl->Destroy( info ); } return TRUE; } @@ -266,7 +266,7 @@ BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) URLCacheContainers_CreateDefaults(); - WININET_hModule = (HMODULE)hinstDLL; + WININET_hModule = hinstDLL; case DLL_THREAD_ATTACH: break; @@ -333,53 +333,56 @@ BOOL WINAPI DetectAutoProxyUrl(LPSTR lpszAutoProxyUrl, /*********************************************************************** - * INTERNET_ConfigureProxyFromReg + * INTERNET_ConfigureProxy * * FIXME: * The proxy may be specified in the form 'http=proxy.my.org' * Presumably that means there can be ftp=ftpproxy.my.org too. */ -static BOOL INTERNET_ConfigureProxyFromReg( LPWININETAPPINFOW lpwai ) +static BOOL INTERNET_ConfigureProxy( LPWININETAPPINFOW lpwai ) { HKEY key; - DWORD r, keytype, len, enabled; - LPCSTR lpszInternetSettings = - "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"; + DWORD type, len, enabled = 0; + LPCSTR envproxy; + static const WCHAR szInternetSettings[] = + { 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\', + 'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', + 'I','n','t','e','r','n','e','t',' ','S','e','t','t','i','n','g','s',0 }; static const WCHAR szProxyServer[] = { 'P','r','o','x','y','S','e','r','v','e','r', 0 }; + static const WCHAR szProxyEnable[] = { 'P','r','o','x','y','E','n','a','b','l','e', 0 }; - r = RegOpenKeyA(HKEY_CURRENT_USER, lpszInternetSettings, &key); - if ( r != ERROR_SUCCESS ) - return FALSE; + if (RegOpenKeyW( HKEY_CURRENT_USER, szInternetSettings, &key )) return FALSE; len = sizeof enabled; - r = RegQueryValueExA( key, "ProxyEnable", NULL, &keytype, - (BYTE*)&enabled, &len); - if( (r == ERROR_SUCCESS) && enabled ) + if (RegQueryValueExW( key, szProxyEnable, NULL, &type, (BYTE *)&enabled, &len ) || type != REG_DWORD) + RegSetValueExW( key, szProxyEnable, 0, REG_DWORD, (BYTE *)&enabled, sizeof(REG_DWORD) ); + + if (enabled) { TRACE("Proxy is enabled.\n"); /* figure out how much memory the proxy setting takes */ - r = RegQueryValueExW( key, szProxyServer, NULL, &keytype, - NULL, &len); - if( (r == ERROR_SUCCESS) && len && (keytype == REG_SZ) ) + if (!RegQueryValueExW( key, szProxyServer, NULL, &type, NULL, &len ) && len && (type == REG_SZ)) { LPWSTR szProxy, p; static const WCHAR szHttp[] = {'h','t','t','p','=',0}; - szProxy=HeapAlloc( GetProcessHeap(), 0, len ); - RegQueryValueExW( key, szProxyServer, NULL, &keytype, - (BYTE*)szProxy, &len); + if (!(szProxy = HeapAlloc( GetProcessHeap(), 0, len ))) + { + RegCloseKey( key ); + return FALSE; + } + RegQueryValueExW( key, szProxyServer, NULL, &type, (BYTE*)szProxy, &len ); /* find the http proxy, and strip away everything else */ p = strstrW( szProxy, szHttp ); - if( p ) + if (p) { - p += lstrlenW(szHttp); - lstrcpyW( szProxy, p ); + p += lstrlenW( szHttp ); + lstrcpyW( szProxy, p ); } p = strchrW( szProxy, ' ' ); - if( p ) - *p = 0; + if (p) *p = 0; lpwai->dwAccessType = INTERNET_OPEN_TYPE_PROXY; lpwai->lpszProxy = szProxy; @@ -387,13 +390,26 @@ static BOOL INTERNET_ConfigureProxyFromReg( LPWININETAPPINFOW lpwai ) TRACE("http proxy = %s\n", debugstr_w(lpwai->lpszProxy)); } else - ERR("Couldn't read proxy server settings.\n"); + ERR("Couldn't read proxy server settings from registry.\n"); } - else - TRACE("Proxy is not enabled.\n"); - RegCloseKey(key); + else if ((envproxy = getenv( "http_proxy" ))) + { + WCHAR *envproxyW; - return enabled; + len = MultiByteToWideChar( CP_UNIXCP, 0, envproxy, -1, NULL, 0 ); + if (!(envproxyW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR)))) return FALSE; + MultiByteToWideChar( CP_UNIXCP, 0, envproxy, -1, envproxyW, len ); + + lpwai->dwAccessType = INTERNET_OPEN_TYPE_PROXY; + lpwai->lpszProxy = envproxyW; + + TRACE("http proxy (from environment) = %s\n", debugstr_w(lpwai->lpszProxy)); + enabled = 1; + } + if (!enabled) TRACE("Proxy is not enabled.\n"); + + RegCloseKey( key ); + return (enabled > 0); } /*********************************************************************** @@ -453,6 +469,57 @@ static void dump_INTERNET_FLAGS(DWORD dwFlags) TRACE("\n"); } +/*********************************************************************** + * INTERNET_CloseHandle (internal) + * + * Close internet handle + * + */ +static VOID APPINFO_Destroy(WININETHANDLEHEADER *hdr) +{ + LPWININETAPPINFOW lpwai = (LPWININETAPPINFOW) hdr; + + TRACE("%p\n",lpwai); + + HeapFree(GetProcessHeap(), 0, lpwai->lpszAgent); + HeapFree(GetProcessHeap(), 0, lpwai->lpszProxy); + HeapFree(GetProcessHeap(), 0, lpwai->lpszProxyBypass); + HeapFree(GetProcessHeap(), 0, lpwai->lpszProxyUsername); + HeapFree(GetProcessHeap(), 0, lpwai->lpszProxyPassword); + HeapFree(GetProcessHeap(), 0, lpwai); +} + +static DWORD APPINFO_QueryOption(WININETHANDLEHEADER *hdr, DWORD option, void *buffer, DWORD *size, BOOL unicode) +{ + switch(option) { + case INTERNET_OPTION_HANDLE_TYPE: + TRACE("INTERNET_OPTION_HANDLE_TYPE\n"); + + if (*size < sizeof(ULONG)) + return ERROR_INSUFFICIENT_BUFFER; + + *size = sizeof(DWORD); + *(DWORD*)buffer = INTERNET_HANDLE_TYPE_INTERNET; + return ERROR_SUCCESS; + } + + FIXME("Not implemented option %d\n", option); + return ERROR_INTERNET_INVALID_OPTION; +} + +static const HANDLEHEADERVtbl APPINFOVtbl = { + APPINFO_Destroy, + NULL, + APPINFO_QueryOption, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL +}; + + /*********************************************************************** * InternetOpenW (WININET.@) * @@ -505,10 +572,9 @@ HINTERNET WINAPI InternetOpenW(LPCWSTR lpszAgent, DWORD dwAccessType, } lpwai->hdr.htype = WH_HINIT; + lpwai->hdr.vtbl = &APPINFOVtbl; lpwai->hdr.dwFlags = dwFlags; - lpwai->hdr.dwRefCount = 1; - lpwai->hdr.close_connection = NULL; - lpwai->hdr.destroy = INTERNET_CloseHandle; + lpwai->hdr.refs = 1; lpwai->dwAccessType = dwAccessType; lpwai->lpszProxyUsername = NULL; lpwai->lpszProxyPassword = NULL; @@ -529,7 +595,7 @@ HINTERNET WINAPI InternetOpenW(LPCWSTR lpszAgent, DWORD dwAccessType, lstrcpyW( lpwai->lpszAgent, lpszAgent ); } if(dwAccessType == INTERNET_OPEN_TYPE_PRECONFIG) - INTERNET_ConfigureProxyFromReg( lpwai ); + INTERNET_ConfigureProxy( lpwai ); else if (NULL != lpszProxy) { lpwai->lpszProxy = HeapAlloc( GetProcessHeap(), 0, @@ -569,7 +635,7 @@ lend: HINTERNET WINAPI InternetOpenA(LPCSTR lpszAgent, DWORD dwAccessType, LPCSTR lpszProxy, LPCSTR lpszProxyBypass, DWORD dwFlags) { - HINTERNET rc = (HINTERNET)NULL; + HINTERNET rc = NULL; INT len; WCHAR *szAgent = NULL, *szProxy = NULL, *szBypass = NULL; @@ -852,7 +918,7 @@ HINTERNET WINAPI InternetConnectA(HINTERNET hInternet, LPCSTR lpszUserName, LPCSTR lpszPassword, DWORD dwService, DWORD dwFlags, DWORD_PTR dwContext) { - HINTERNET rc = (HINTERNET)NULL; + HINTERNET rc = NULL; INT len = 0; LPWSTR szServerName = NULL; LPWSTR szUserName = NULL; @@ -919,79 +985,34 @@ BOOL WINAPI InternetFindNextFileA(HINTERNET hFind, LPVOID lpvFindData) * FALSE on failure * */ -static void AsyncFtpFindNextFileProc(WORKREQUEST *workRequest) -{ - struct WORKREQ_FTPFINDNEXTW *req = &workRequest->u.FtpFindNextW; - LPWININETFTPFINDNEXTW lpwh = (LPWININETFTPFINDNEXTW) workRequest->hdr; - - TRACE("%p\n", lpwh); - - FTP_FindNextFileW(lpwh, req->lpFindFileData); -} - BOOL WINAPI InternetFindNextFileW(HINTERNET hFind, LPVOID lpvFindData) { - LPWININETAPPINFOW hIC = NULL; - LPWININETFTPFINDNEXTW lpwh; - BOOL bSuccess = FALSE; + WININETHANDLEHEADER *hdr; + DWORD res; TRACE("\n"); - lpwh = (LPWININETFTPFINDNEXTW) WININET_GetObject( hFind ); - if (NULL == lpwh || lpwh->hdr.htype != WH_HFTPFINDNEXT) - { - FIXME("Only FTP supported\n"); - INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE); - goto lend; + hdr = WININET_GetObject(hFind); + if(!hdr) { + WARN("Invalid handle\n"); + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; } - hIC = lpwh->lpFtpSession->lpAppInfo; - if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC) - { - WORKREQUEST workRequest; - struct WORKREQ_FTPFINDNEXTW *req; - - workRequest.asyncproc = AsyncFtpFindNextFileProc; - workRequest.hdr = WININET_AddRef( &lpwh->hdr ); - req = &workRequest.u.FtpFindNextW; - req->lpFindFileData = lpvFindData; - - bSuccess = INTERNET_AsyncCall(&workRequest); + if(hdr->vtbl->FindNextFileW) { + res = hdr->vtbl->FindNextFileW(hdr, lpvFindData); + }else { + WARN("Handle doesn't support NextFile\n"); + res = ERROR_INTERNET_INCORRECT_HANDLE_TYPE; } - else - { - bSuccess = FTP_FindNextFileW(lpwh, lpvFindData); - } -lend: - if( lpwh ) - WININET_Release( &lpwh->hdr ); - return bSuccess; + + WININET_Release(hdr); + + if(res != ERROR_SUCCESS) + SetLastError(res); + return res == ERROR_SUCCESS; } -/*********************************************************************** - * INTERNET_CloseHandle (internal) - * - * Close internet handle - * - * RETURNS - * Void - * - */ -static VOID INTERNET_CloseHandle(LPWININETHANDLEHEADER hdr) -{ - LPWININETAPPINFOW lpwai = (LPWININETAPPINFOW) hdr; - - TRACE("%p\n",lpwai); - - HeapFree(GetProcessHeap(), 0, lpwai->lpszAgent); - HeapFree(GetProcessHeap(), 0, lpwai->lpszProxy); - HeapFree(GetProcessHeap(), 0, lpwai->lpszProxyBypass); - HeapFree(GetProcessHeap(), 0, lpwai->lpszProxyUsername); - HeapFree(GetProcessHeap(), 0, lpwai->lpszProxyPassword); - HeapFree(GetProcessHeap(), 0, lpwai); -} - - /*********************************************************************** * InternetCloseHandle (WININET.@) * @@ -1693,126 +1714,35 @@ DWORD WINAPI InternetSetFilePointer(HINTERNET hFile, LONG lDistanceToMove, * FALSE on failure * */ -BOOL WINAPI InternetWriteFile(HINTERNET hFile, LPCVOID lpBuffer , +BOOL WINAPI InternetWriteFile(HINTERNET hFile, LPCVOID lpBuffer, DWORD dwNumOfBytesToWrite, LPDWORD lpdwNumOfBytesWritten) { - BOOL retval = FALSE; - int nSocket = -1; LPWININETHANDLEHEADER lpwh; + BOOL retval = FALSE; - TRACE("\n"); - lpwh = (LPWININETHANDLEHEADER) WININET_GetObject( hFile ); - if (NULL == lpwh) + TRACE("(%p %p %d %p)\n", hFile, lpBuffer, dwNumOfBytesToWrite, lpdwNumOfBytesWritten); + + lpwh = WININET_GetObject( hFile ); + if (!lpwh) { + WARN("Invalid handle\n"); + SetLastError(ERROR_INVALID_HANDLE); return FALSE; - - switch (lpwh->htype) - { - case WH_HHTTPREQ: - { - LPWININETHTTPREQW lpwhr; - lpwhr = (LPWININETHTTPREQW)lpwh; - - TRACE("HTTPREQ %i\n",dwNumOfBytesToWrite); - retval = NETCON_send(&lpwhr->netConnection, lpBuffer, - dwNumOfBytesToWrite, 0, (LPINT)lpdwNumOfBytesWritten); - - WININET_Release( lpwh ); - return retval; - } - break; - - case WH_HFILE: - nSocket = ((LPWININETFTPFILE)lpwh)->nDataSocket; - break; - - default: - break; } - if (nSocket != -1) - { - int res = send(nSocket, lpBuffer, dwNumOfBytesToWrite, 0); - retval = (res >= 0); - *lpdwNumOfBytesWritten = retval ? res : 0; + if(lpwh->vtbl->WriteFile) { + retval = lpwh->vtbl->WriteFile(lpwh, lpBuffer, dwNumOfBytesToWrite, lpdwNumOfBytesWritten); + }else { + WARN("No Writefile method.\n"); + SetLastError(ERROR_INVALID_HANDLE); + retval = FALSE; } + WININET_Release( lpwh ); return retval; } -BOOL INTERNET_ReadFile(LPWININETHANDLEHEADER lpwh, LPVOID lpBuffer, - DWORD dwNumOfBytesToRead, LPDWORD pdwNumOfBytesRead, - BOOL bWait, BOOL bSendCompletionStatus) -{ - BOOL retval = FALSE; - int nSocket = -1; - int bytes_read; - LPWININETHTTPREQW lpwhr; - - /* FIXME: this should use NETCON functions! */ - switch (lpwh->htype) - { - case WH_HHTTPREQ: - lpwhr = (LPWININETHTTPREQW)lpwh; - - if (!NETCON_recv(&lpwhr->netConnection, lpBuffer, - min(dwNumOfBytesToRead, lpwhr->dwContentLength - lpwhr->dwContentRead), - bWait ? MSG_WAITALL : 0, &bytes_read)) - { - - if (((lpwhr->dwContentLength != -1) && - (lpwhr->dwContentRead != lpwhr->dwContentLength))) - ERR("not all data received %d/%d\n", lpwhr->dwContentRead, - lpwhr->dwContentLength); - - /* always returns TRUE, even if the network layer returns an - * error */ - *pdwNumOfBytesRead = 0; - HTTP_FinishedReading(lpwhr); - retval = TRUE; - } - else - { - lpwhr->dwContentRead += bytes_read; - *pdwNumOfBytesRead = bytes_read; - if (!bytes_read && (lpwhr->dwContentRead == lpwhr->dwContentLength)) - retval = HTTP_FinishedReading(lpwhr); - else - retval = TRUE; - } - break; - - case WH_HFILE: - /* FIXME: FTP should use NETCON_ stuff */ - nSocket = ((LPWININETFTPFILE)lpwh)->nDataSocket; - if (nSocket != -1) - { - int res = recv(nSocket, lpBuffer, dwNumOfBytesToRead, bWait ? MSG_WAITALL : 0); - retval = (res >= 0); - *pdwNumOfBytesRead = retval ? res : 0; - } - break; - - default: - break; - } - - if (bSendCompletionStatus) - { - INTERNET_ASYNC_RESULT iar; - - iar.dwResult = retval; - iar.dwError = iar.dwError = retval ? ERROR_SUCCESS : - INTERNET_GetLastError(); - - INTERNET_SendCallback(lpwh, lpwh->dwContext, - INTERNET_STATUS_REQUEST_COMPLETE, &iar, - sizeof(INTERNET_ASYNC_RESULT)); - } - return retval; -} - /*********************************************************************** * InternetReadFile (WININET.@) * @@ -1824,25 +1754,30 @@ BOOL INTERNET_ReadFile(LPWININETHANDLEHEADER lpwh, LPVOID lpBuffer, * */ BOOL WINAPI InternetReadFile(HINTERNET hFile, LPVOID lpBuffer, - DWORD dwNumOfBytesToRead, LPDWORD pdwNumOfBytesRead) + DWORD dwNumOfBytesToRead, LPDWORD pdwNumOfBytesRead) { - LPWININETHANDLEHEADER lpwh; - BOOL retval; + LPWININETHANDLEHEADER hdr; + DWORD res = ERROR_INTERNET_INCORRECT_HANDLE_TYPE; TRACE("%p %p %d %p\n", hFile, lpBuffer, dwNumOfBytesToRead, pdwNumOfBytesRead); - lpwh = WININET_GetObject( hFile ); - if (!lpwh) - { + hdr = WININET_GetObject(hFile); + if (!hdr) { INTERNET_SetLastError(ERROR_INVALID_HANDLE); return FALSE; } - retval = INTERNET_ReadFile(lpwh, lpBuffer, dwNumOfBytesToRead, pdwNumOfBytesRead, TRUE, FALSE); - WININET_Release( lpwh ); + if(hdr->vtbl->ReadFile) + res = hdr->vtbl->ReadFile(hdr, lpBuffer, dwNumOfBytesToRead, pdwNumOfBytesRead); - TRACE("-- %s (bytes read: %d)\n", retval ? "TRUE": "FALSE", pdwNumOfBytesRead ? *pdwNumOfBytesRead : -1); - return retval; + WININET_Release(hdr); + + TRACE("-- %s (%u) (bytes read: %d)\n", res == ERROR_SUCCESS ? "TRUE": "FALSE", res, + pdwNumOfBytesRead ? *pdwNumOfBytesRead : -1); + + if(res != ERROR_SUCCESS) + SetLastError(res); + return res == ERROR_SUCCESS; } /*********************************************************************** @@ -1872,89 +1807,31 @@ BOOL WINAPI InternetReadFile(HINTERNET hFile, LPVOID lpBuffer, * SEE * InternetOpenUrlA(), HttpOpenRequestA() */ -void AsyncInternetReadFileExProc(WORKREQUEST *workRequest) -{ - struct WORKREQ_INTERNETREADFILEEXA const *req = &workRequest->u.InternetReadFileExA; - - TRACE("INTERNETREADFILEEXA %p\n", workRequest->hdr); - - INTERNET_ReadFile(workRequest->hdr, req->lpBuffersOut->lpvBuffer, - req->lpBuffersOut->dwBufferLength, - &req->lpBuffersOut->dwBufferLength, TRUE, TRUE); -} - BOOL WINAPI InternetReadFileExA(HINTERNET hFile, LPINTERNET_BUFFERSA lpBuffersOut, DWORD dwFlags, DWORD_PTR dwContext) { - BOOL retval = FALSE; - LPWININETHANDLEHEADER lpwh; + LPWININETHANDLEHEADER hdr; + DWORD res = ERROR_INTERNET_INCORRECT_HANDLE_TYPE; TRACE("(%p %p 0x%x 0x%lx)\n", hFile, lpBuffersOut, dwFlags, dwContext); - if (dwFlags & ~(IRF_ASYNC|IRF_NO_WAIT)) - FIXME("these dwFlags aren't implemented: 0x%x\n", dwFlags & ~(IRF_ASYNC|IRF_NO_WAIT)); - - if (lpBuffersOut->dwStructSize != sizeof(*lpBuffersOut)) - { - INTERNET_SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - lpwh = (LPWININETHANDLEHEADER) WININET_GetObject( hFile ); - if (!lpwh) - { + hdr = WININET_GetObject(hFile); + if (!hdr) { INTERNET_SetLastError(ERROR_INVALID_HANDLE); return FALSE; } - INTERNET_SendCallback(lpwh, lpwh->dwContext, - INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0); + if(hdr->vtbl->ReadFileExA) + res = hdr->vtbl->ReadFileExA(hdr, lpBuffersOut, dwFlags, dwContext); - /* FIXME: IRF_ASYNC may not be the right thing to test here; - * hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC is probably better */ - if (dwFlags & IRF_ASYNC) - { - DWORD dwDataAvailable = 0; + WININET_Release(hdr); - if (lpwh->htype == WH_HHTTPREQ) - NETCON_query_data_available(&((LPWININETHTTPREQW)lpwh)->netConnection, - &dwDataAvailable); + TRACE("-- %s (%u, bytes read: %d)\n", res == ERROR_SUCCESS ? "TRUE": "FALSE", + res, lpBuffersOut->dwBufferLength); - if (!dwDataAvailable) - { - WORKREQUEST workRequest; - struct WORKREQ_INTERNETREADFILEEXA *req; - - workRequest.asyncproc = AsyncInternetReadFileExProc; - workRequest.hdr = WININET_AddRef( lpwh ); - req = &workRequest.u.InternetReadFileExA; - req->lpBuffersOut = lpBuffersOut; - - if (!INTERNET_AsyncCall(&workRequest)) - WININET_Release( lpwh ); - else - INTERNET_SetLastError(ERROR_IO_PENDING); - goto end; - } - } - - retval = INTERNET_ReadFile(lpwh, lpBuffersOut->lpvBuffer, - lpBuffersOut->dwBufferLength, &lpBuffersOut->dwBufferLength, - !(dwFlags & IRF_NO_WAIT), FALSE); - - if (retval) - { - DWORD dwBytesReceived = lpBuffersOut->dwBufferLength; - INTERNET_SendCallback(lpwh, lpwh->dwContext, - INTERNET_STATUS_RESPONSE_RECEIVED, &dwBytesReceived, - sizeof(dwBytesReceived)); - } - -end: - WININET_Release( lpwh ); - - TRACE("-- %s (bytes read: %d)\n", retval ? "TRUE": "FALSE", lpBuffersOut->dwBufferLength); - return retval; + if(res != ERROR_SUCCESS) + SetLastError(res); + return res == ERROR_SUCCESS; } /*********************************************************************** @@ -1995,36 +1872,10 @@ static BOOL INET_QueryOptionHelper(BOOL bIsUnicode, HINTERNET hInternet, DWORD d TRACE("(%p, 0x%08x, %p, %p)\n", hInternet, dwOption, lpBuffer, lpdwBufferLength); - lpwhh = (LPWININETHANDLEHEADER) WININET_GetObject( hInternet ); + lpwhh = WININET_GetObject( hInternet ); switch (dwOption) { - case INTERNET_OPTION_HANDLE_TYPE: - { - ULONG type; - - if (!lpwhh) - { - WARN("Invalid hInternet handle\n"); - INTERNET_SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - - type = lpwhh->htype; - - TRACE("INTERNET_OPTION_HANDLE_TYPE: %d\n", type); - - if (*lpdwBufferLength < sizeof(ULONG)) - INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER); - else - { - memcpy(lpBuffer, &type, sizeof(ULONG)); - bSuccess = TRUE; - } - *lpdwBufferLength = sizeof(ULONG); - break; - } - case INTERNET_OPTION_REQUEST_FLAGS: { ULONG flags = 4; @@ -2040,50 +1891,41 @@ static BOOL INET_QueryOptionHelper(BOOL bIsUnicode, HINTERNET hInternet, DWORD d break; } - case INTERNET_OPTION_URL: - case INTERNET_OPTION_DATAFILE_NAME: + case INTERNET_OPTION_USER_AGENT: { - if (!lpwhh) + DWORD required; + LPWININETAPPINFOW ai = (LPWININETAPPINFOW)lpwhh; + + TRACE("INTERNET_OPTION_USER_AGENT\n"); + + if (lpwhh->htype != INTERNET_HANDLE_TYPE_INTERNET) { - WARN("Invalid hInternet handle\n"); - INTERNET_SetLastError(ERROR_INVALID_HANDLE); + INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE); return FALSE; } - if (lpwhh->htype == WH_HHTTPREQ) + if (bIsUnicode) { - LPWININETHTTPREQW lpreq = (LPWININETHTTPREQW) lpwhh; - WCHAR url[1023]; - static const WCHAR szFmt[] = {'h','t','t','p',':','/','/','%','s','%','s',0}; - static const WCHAR szHost[] = {'H','o','s','t',0}; - DWORD sizeRequired; - LPHTTPHEADERW Host; - - Host = HTTP_GetHeader(lpreq,szHost); - sprintfW(url,szFmt,Host->lpszValue,lpreq->lpszPath); - TRACE("INTERNET_OPTION_URL: %s\n",debugstr_w(url)); - if(!bIsUnicode) + required = (strlenW(ai->lpszAgent) + 1) * sizeof(WCHAR); + if (*lpdwBufferLength < required) + INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER); + else if (lpBuffer) { - sizeRequired = WideCharToMultiByte(CP_ACP,0,url,-1, - lpBuffer,*lpdwBufferLength,NULL,NULL); - if (sizeRequired > *lpdwBufferLength) - INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER); - else - bSuccess = TRUE; - *lpdwBufferLength = sizeRequired; - } - else - { - sizeRequired = (lstrlenW(url)+1) * sizeof(WCHAR); - if (*lpdwBufferLength < sizeRequired) - INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER); - else - { - strcpyW(lpBuffer, url); - bSuccess = TRUE; - } - *lpdwBufferLength = sizeRequired; + strcpyW(lpBuffer, ai->lpszAgent); + bSuccess = TRUE; } } + else + { + required = WideCharToMultiByte(CP_ACP, 0, ai->lpszAgent, -1, NULL, 0, NULL, NULL); + if (*lpdwBufferLength < required) + INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER); + else if (lpBuffer) + { + WideCharToMultiByte(CP_ACP, 0, ai->lpszAgent, -1, lpBuffer, required, NULL, NULL); + bSuccess = TRUE; + } + } + *lpdwBufferLength = required; break; } case INTERNET_OPTION_HTTP_VERSION: @@ -2126,7 +1968,7 @@ static BOOL INET_QueryOptionHelper(BOOL bIsUnicode, HINTERNET hInternet, DWORD d { TRACE("Getting global proxy info\n"); memset(&wai, 0, sizeof(WININETAPPINFOW)); - INTERNET_ConfigureProxyFromReg( &wai ); + INTERNET_ConfigureProxy( &wai ); lpwai = &wai; } @@ -2250,87 +2092,6 @@ static BOOL INET_QueryOptionHelper(BOOL bIsUnicode, HINTERNET hInternet, DWORD d bSuccess = TRUE; break; - case INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT: - if (!lpwhh) - { - INTERNET_SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - if (*lpdwBufferLength < sizeof(INTERNET_CERTIFICATE_INFOW)) - { - *lpdwBufferLength = sizeof(INTERNET_CERTIFICATE_INFOW); - INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER); - } - else if (lpwhh->htype == WH_HHTTPREQ) - { - LPWININETHTTPREQW lpwhr; - PCCERT_CONTEXT context; - - lpwhr = (LPWININETHTTPREQW)lpwhh; - context = (PCCERT_CONTEXT)NETCON_GetCert(&(lpwhr->netConnection)); - if (context) - { - LPINTERNET_CERTIFICATE_INFOW info = (LPINTERNET_CERTIFICATE_INFOW)lpBuffer; - DWORD strLen; - - memset(info,0,sizeof(INTERNET_CERTIFICATE_INFOW)); - info->ftExpiry = context->pCertInfo->NotAfter; - info->ftStart = context->pCertInfo->NotBefore; - if (bIsUnicode) - { - strLen = CertNameToStrW(context->dwCertEncodingType, - &context->pCertInfo->Subject, CERT_SIMPLE_NAME_STR, - NULL, 0); - info->lpszSubjectInfo = LocalAlloc(0, - strLen * sizeof(WCHAR)); - if (info->lpszSubjectInfo) - CertNameToStrW(context->dwCertEncodingType, - &context->pCertInfo->Subject, CERT_SIMPLE_NAME_STR, - info->lpszSubjectInfo, strLen); - strLen = CertNameToStrW(context->dwCertEncodingType, - &context->pCertInfo->Issuer, CERT_SIMPLE_NAME_STR, - NULL, 0); - info->lpszIssuerInfo = LocalAlloc(0, - strLen * sizeof(WCHAR)); - if (info->lpszIssuerInfo) - CertNameToStrW(context->dwCertEncodingType, - &context->pCertInfo->Issuer, CERT_SIMPLE_NAME_STR, - info->lpszIssuerInfo, strLen); - } - else - { - LPINTERNET_CERTIFICATE_INFOA infoA = - (LPINTERNET_CERTIFICATE_INFOA)info; - - strLen = CertNameToStrA(context->dwCertEncodingType, - &context->pCertInfo->Subject, CERT_SIMPLE_NAME_STR, - NULL, 0); - infoA->lpszSubjectInfo = LocalAlloc(0, strLen); - if (infoA->lpszSubjectInfo) - CertNameToStrA(context->dwCertEncodingType, - &context->pCertInfo->Subject, CERT_SIMPLE_NAME_STR, - infoA->lpszSubjectInfo, strLen); - strLen = CertNameToStrA(context->dwCertEncodingType, - &context->pCertInfo->Issuer, CERT_SIMPLE_NAME_STR, - NULL, 0); - infoA->lpszIssuerInfo = LocalAlloc(0, strLen); - if (infoA->lpszIssuerInfo) - CertNameToStrA(context->dwCertEncodingType, - &context->pCertInfo->Issuer, CERT_SIMPLE_NAME_STR, - infoA->lpszIssuerInfo, strLen); - } - /* - * Contrary to MSDN, these do not appear to be set. - * lpszProtocolName - * lpszSignatureAlgName - * lpszEncryptionAlgName - * dwKeySize - */ - CertFreeCertificateContext(context); - bSuccess = TRUE; - } - } - break; case INTERNET_OPTION_VERSION: { TRACE("INTERNET_OPTION_VERSION\n"); @@ -2338,16 +2099,72 @@ static BOOL INET_QueryOptionHelper(BOOL bIsUnicode, HINTERNET hInternet, DWORD d INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER); else { - static const INTERNET_VERSION_INFO info = { 6, 0 }; + static const INTERNET_VERSION_INFO info = { 1, 2 }; memcpy(lpBuffer, &info, sizeof(info)); *lpdwBufferLength = sizeof(info); bSuccess = TRUE; } break; } - default: - FIXME("Stub! %d\n", dwOption); + case INTERNET_OPTION_PER_CONNECTION_OPTION: + FIXME("INTERNET_OPTION_PER_CONNECTION_OPTION stub\n"); + if (*lpdwBufferLength < sizeof(INTERNET_PER_CONN_OPTION_LISTW)) + INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER); + else + { + INTERNET_PER_CONN_OPTION_LISTW *con = lpBuffer; + int x; + bSuccess = TRUE; + for (x = 0; x < con->dwOptionCount; ++x) + { + INTERNET_PER_CONN_OPTIONW *option = con->pOptions + x; + switch (option->dwOption) + { + case INTERNET_PER_CONN_FLAGS: + option->Value.dwValue = PROXY_TYPE_DIRECT; + break; + + case INTERNET_PER_CONN_PROXY_SERVER: + case INTERNET_PER_CONN_PROXY_BYPASS: + case INTERNET_PER_CONN_AUTOCONFIG_URL: + case INTERNET_PER_CONN_AUTODISCOVERY_FLAGS: + case INTERNET_PER_CONN_AUTOCONFIG_SECONDARY_URL: + case INTERNET_PER_CONN_AUTOCONFIG_RELOAD_DELAY_MINS: + case INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_TIME: + case INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_URL: + FIXME("Unhandled dwOption %d\n", option->dwOption); + option->Value.dwValue = 0; + bSuccess = FALSE; + break; + + default: + FIXME("Unknown dwOption %d\n", option->dwOption); + bSuccess = FALSE; + break; + } + } + if (!bSuccess) + INTERNET_SetLastError(ERROR_INVALID_PARAMETER); + } break; + case 66: + FIXME("66\n"); + bSuccess = TRUE; + break; + default: { + if(lpwhh) { + DWORD res; + + res = lpwhh->vtbl->QueryOption(lpwhh, dwOption, lpBuffer, lpdwBufferLength, bIsUnicode); + if(res == ERROR_SUCCESS) + bSuccess = TRUE; + else + SetLastError(res); + }else { + FIXME("Stub! %d\n", dwOption); + break; + } + } } if (lpwhh) WININET_Release( lpwhh ); @@ -2404,11 +2221,22 @@ BOOL WINAPI InternetSetOptionW(HINTERNET hInternet, DWORD dwOption, LPWININETHANDLEHEADER lpwhh; BOOL ret = TRUE; - TRACE("0x%08x\n", dwOption); + TRACE("(%p %d %p %d)\n", hInternet, dwOption, lpBuffer, dwBufferLength); lpwhh = (LPWININETHANDLEHEADER) WININET_GetObject( hInternet ); - if( !lpwhh ) - return FALSE; + if(lpwhh && lpwhh->vtbl->SetOption) { + DWORD res; + + res = lpwhh->vtbl->SetOption(lpwhh, dwOption, lpBuffer, dwBufferLength); + if(res != ERROR_INTERNET_INVALID_OPTION) { + WININET_Release( lpwhh ); + + if(res != ERROR_SUCCESS) + SetLastError(res); + + return res == ERROR_SUCCESS; + } + } switch (dwOption) { @@ -2480,25 +2308,7 @@ BOOL WINAPI InternetSetOptionW(HINTERNET hInternet, DWORD dwOption, break; case INTERNET_OPTION_SEND_TIMEOUT: case INTERNET_OPTION_RECEIVE_TIMEOUT: - TRACE("INTERNET_OPTION_SEND/RECEIVE_TIMEOUT\n"); - if (dwBufferLength == sizeof(DWORD)) - { - if (lpwhh->htype == WH_HHTTPREQ) - ret = NETCON_set_timeout( - &((LPWININETHTTPREQW)lpwhh)->netConnection, - dwOption == INTERNET_OPTION_SEND_TIMEOUT, - *(DWORD *)lpBuffer); - else - { - FIXME("INTERNET_OPTION_SEND/RECEIVE_TIMEOUT not supported on protocol %d\n", - lpwhh->htype); - } - } - else - { - INTERNET_SetLastError(ERROR_INVALID_PARAMETER); - ret = FALSE; - } + FIXME("INTERNET_OPTION_SEND/RECEIVE_TIMEOUT\n"); break; case INTERNET_OPTION_CONNECT_RETRIES: FIXME("Option INTERNET_OPTION_CONNECT_RETRIES: STUB\n"); @@ -2509,13 +2319,18 @@ BOOL WINAPI InternetSetOptionW(HINTERNET hInternet, DWORD dwOption, case INTERNET_OPTION_SECURITY_FLAGS: FIXME("Option INTERNET_OPTION_SECURITY_FLAGS; STUB\n"); break; + case 86: + FIXME("86\n"); + break; default: FIXME("Option %d STUB\n",dwOption); - INTERNET_SetLastError(ERROR_INVALID_PARAMETER); + INTERNET_SetLastError(ERROR_INTERNET_INVALID_OPTION); ret = FALSE; break; } - WININET_Release( lpwhh ); + + if(lpwhh) + WININET_Release( lpwhh ); return ret; } @@ -2545,7 +2360,7 @@ BOOL WINAPI InternetSetOptionA(HINTERNET hInternet, DWORD dwOption, LPWININETHANDLEHEADER lpwh; INTERNET_STATUS_CALLBACK callback = *(INTERNET_STATUS_CALLBACK *)lpBuffer; - if (!(lpwh = (LPWININETHANDLEHEADER)WININET_GetObject(hInternet))) return FALSE; + if (!(lpwh = WININET_GetObject(hInternet))) return FALSE; r = (set_status_callback(lpwh, callback, FALSE) != INTERNET_INVALID_STATUS_CALLBACK); WININET_Release(lpwh); return r; @@ -2916,7 +2731,7 @@ BOOL WINAPI InternetCheckConnectionA(LPCSTR lpszUrl, DWORD dwFlags, DWORD dwRese * RETURNS * handle of connection or NULL on failure */ -HINTERNET WINAPI INTERNET_InternetOpenUrlW(LPWININETAPPINFOW hIC, LPCWSTR lpszUrl, +static HINTERNET INTERNET_InternetOpenUrlW(LPWININETAPPINFOW hIC, LPCWSTR lpszUrl, LPCWSTR lpszHeaders, DWORD dwHeadersLength, DWORD dwFlags, DWORD_PTR dwContext) { URL_COMPONENTSW urlComponents; @@ -3105,7 +2920,7 @@ HINTERNET WINAPI InternetOpenUrlW(HINTERNET hInternet, LPCWSTR lpszUrl, HINTERNET WINAPI InternetOpenUrlA(HINTERNET hInternet, LPCSTR lpszUrl, LPCSTR lpszHeaders, DWORD dwHeadersLength, DWORD dwFlags, DWORD_PTR dwContext) { - HINTERNET rc = (HINTERNET)NULL; + HINTERNET rc = NULL; INT lenUrl; INT lenHeaders = 0; @@ -3118,16 +2933,16 @@ HINTERNET WINAPI InternetOpenUrlA(HINTERNET hInternet, LPCSTR lpszUrl, lenUrl = MultiByteToWideChar(CP_ACP, 0, lpszUrl, -1, NULL, 0 ); szUrl = HeapAlloc(GetProcessHeap(), 0, lenUrl*sizeof(WCHAR)); if(!szUrl) - return (HINTERNET)NULL; + return NULL; MultiByteToWideChar(CP_ACP, 0, lpszUrl, -1, szUrl, lenUrl); } - + if(lpszHeaders) { lenHeaders = MultiByteToWideChar(CP_ACP, 0, lpszHeaders, dwHeadersLength, NULL, 0 ); szHeaders = HeapAlloc(GetProcessHeap(), 0, lenHeaders*sizeof(WCHAR)); if(!szHeaders) { HeapFree(GetProcessHeap(), 0, szUrl); - return (HINTERNET)NULL; + return NULL; } MultiByteToWideChar(CP_ACP, 0, lpszHeaders, dwHeadersLength, szHeaders, lenHeaders); } @@ -3216,7 +3031,7 @@ static DWORD CALLBACK INTERNET_WorkerThreadFunc(LPVOID lpvParam) TRACE("\n"); - memcpy(&workRequest, lpRequest, sizeof(WORKREQUEST)); + workRequest = *lpRequest; HeapFree(GetProcessHeap(), 0, lpRequest); workRequest.asyncproc(&workRequest); @@ -3245,7 +3060,7 @@ BOOL INTERNET_AsyncCall(LPWORKREQUEST lpWorkRequest) if (!lpNewRequest) return FALSE; - memcpy(lpNewRequest, lpWorkRequest, sizeof(WORKREQUEST)); + *lpNewRequest = *lpWorkRequest; bSuccess = QueueUserWorkItem(INTERNET_WorkerThreadFunc, lpNewRequest, WT_EXECUTELONGFUNCTION); if (!bSuccess) @@ -3351,96 +3166,33 @@ lend: * INTERNET_STATUS_REQUEST_COMPLETE will be sent when more * data is available. */ -void AsyncInternetQueryDataAvailableProc(WORKREQUEST *workRequest) -{ - LPWININETHTTPREQW lpwhr; - INTERNET_ASYNC_RESULT iar; - char buffer[4048]; - - TRACE("INTERNETQUERYDATAAVAILABLE %p\n", workRequest->hdr); - - switch (workRequest->hdr->htype) - { - case WH_HHTTPREQ: - lpwhr = (LPWININETHTTPREQW)workRequest->hdr; - iar.dwResult = NETCON_recv(&lpwhr->netConnection, buffer, - min(sizeof(buffer), - lpwhr->dwContentLength - lpwhr->dwContentRead), - MSG_PEEK, (int *)&iar.dwError); - INTERNET_SendCallback(workRequest->hdr, workRequest->hdr->dwContext, - INTERNET_STATUS_REQUEST_COMPLETE, &iar, - sizeof(INTERNET_ASYNC_RESULT)); - break; - - default: - FIXME("unsupported file type\n"); - break; - } -} - BOOL WINAPI InternetQueryDataAvailable( HINTERNET hFile, LPDWORD lpdwNumberOfBytesAvailble, DWORD dwFlags, DWORD_PTR dwContext) { - LPWININETHTTPREQW lpwhr; - BOOL retval = FALSE; - char buffer[4048]; + WININETHANDLEHEADER *hdr; + DWORD res; - lpwhr = (LPWININETHTTPREQW) WININET_GetObject( hFile ); - if (NULL == lpwhr) - { - INTERNET_SetLastError(ERROR_NO_MORE_FILES); + TRACE("(%p %p %x %lx)\n", hFile, lpdwNumberOfBytesAvailble, dwFlags, dwContext); + + hdr = WININET_GetObject( hFile ); + if (!hdr) { + INTERNET_SetLastError(ERROR_INVALID_HANDLE); return FALSE; } - TRACE("--> %p %i\n",lpwhr,lpwhr->hdr.htype); - - switch (lpwhr->hdr.htype) - { - case WH_HHTTPREQ: - retval = TRUE; - if (NETCON_query_data_available(&lpwhr->netConnection, - lpdwNumberOfBytesAvailble) && - !*lpdwNumberOfBytesAvailble) - { - /* Even if we are in async mode, we need to determine whether - * there is actually more data available. We do this by trying - * to peek only a single byte in async mode. */ - BOOL async = (lpwhr->lpHttpSession->lpAppInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC); - if (NETCON_recv(&lpwhr->netConnection, buffer, - min(async ? 1 : sizeof(buffer), - lpwhr->dwContentLength - lpwhr->dwContentRead), - MSG_PEEK, (int *)lpdwNumberOfBytesAvailble) && - async && *lpdwNumberOfBytesAvailble) - { - WORKREQUEST workRequest; - - *lpdwNumberOfBytesAvailble = 0; - workRequest.asyncproc = AsyncInternetQueryDataAvailableProc; - workRequest.hdr = WININET_AddRef( &lpwhr->hdr ); - - retval = INTERNET_AsyncCall(&workRequest); - if (!retval) - { - WININET_Release( &lpwhr->hdr ); - } - else - { - INTERNET_SetLastError(ERROR_IO_PENDING); - retval = FALSE; - } - } - } - break; - - default: - FIXME("unsupported file type\n"); - break; + if(hdr->vtbl->QueryDataAvailable) { + res = hdr->vtbl->QueryDataAvailable(hdr, lpdwNumberOfBytesAvailble, dwFlags, dwContext); + }else { + WARN("wrong handle\n"); + res = ERROR_INTERNET_INCORRECT_HANDLE_TYPE; } - WININET_Release( &lpwhr->hdr ); - TRACE("<-- %i\n",retval); - return retval; + WININET_Release(hdr); + + if(res != ERROR_SUCCESS) + SetLastError(res); + return res == ERROR_SUCCESS; } diff --git a/reactos/dll/win32/wininet/internet.h b/reactos/dll/win32/wininet/internet.h index 0f283e13414..5d4d7e89b6b 100644 --- a/reactos/dll/win32/wininet/internet.h +++ b/reactos/dll/win32/wininet/internet.h @@ -23,6 +23,9 @@ #ifndef _WINE_INTERNET_H_ #define _WINE_INTERNET_H_ +/* ReactOS-specific definitions */ +#define CP_UNIXCP CP_THREAD_ACP + #ifndef __WINE_CONFIG_H # error You must include config.h to use this header #endif @@ -55,12 +58,13 @@ #endif #if defined(__MINGW32__) || defined (_MSC_VER) -#include "winsock2.h" +#include "ws2tcpip.h" #ifndef MSG_WAITALL #define MSG_WAITALL 0 #endif #else #define closesocket close +#define ioctlsocket ioctl #endif /* __MINGW32__ */ /* used for netconnection.c stuff */ @@ -133,22 +137,30 @@ typedef enum #define INET_OPENURL 0x0001 #define INET_CALLBACKW 0x0002 -struct _WININETHANDLEHEADER; typedef struct _WININETHANDLEHEADER WININETHANDLEHEADER, *LPWININETHANDLEHEADER; -typedef void (*WININET_object_function)( LPWININETHANDLEHEADER ); +typedef struct { + void (*Destroy)(WININETHANDLEHEADER*); + void (*CloseConnection)(WININETHANDLEHEADER*); + DWORD (*QueryOption)(WININETHANDLEHEADER*,DWORD,void*,DWORD*,BOOL); + DWORD (*SetOption)(WININETHANDLEHEADER*,DWORD,void*,DWORD); + DWORD (*ReadFile)(WININETHANDLEHEADER*,void*,DWORD,DWORD*); + DWORD (*ReadFileExA)(WININETHANDLEHEADER*,INTERNET_BUFFERSA*,DWORD,DWORD_PTR); + BOOL (*WriteFile)(WININETHANDLEHEADER*,const void*,DWORD,DWORD*); + DWORD (*QueryDataAvailable)(WININETHANDLEHEADER*,DWORD*,DWORD,DWORD_PTR); + DWORD (*FindNextFileW)(WININETHANDLEHEADER*,void*); +} HANDLEHEADERVtbl; struct _WININETHANDLEHEADER { WH_TYPE htype; + const HANDLEHEADERVtbl *vtbl; HINTERNET hInternet; DWORD dwFlags; DWORD_PTR dwContext; DWORD dwError; DWORD dwInternalFlags; - DWORD dwRefCount; - WININET_object_function close_connection; - WININET_object_function destroy; + LONG refs; INTERNET_STATUS_CALLBACK lpfnStatusCB; struct list entry; struct list children; @@ -209,55 +221,13 @@ typedef struct DWORD dwContentRead; /* bytes of the content read so far */ HTTPHEADERW *pCustHeaders; DWORD nCustHeaders; + HANDLE hCacheFile; + LPWSTR lpszCacheFile; struct HttpAuthInfo *pAuthInfo; struct HttpAuthInfo *pProxyAuthInfo; } WININETHTTPREQW, *LPWININETHTTPREQW; -struct _WININETFTPSESSIONW; - -typedef struct -{ - WININETHANDLEHEADER hdr; - struct _WININETFTPSESSIONW *lpFtpSession; - BOOL session_deleted; - int nDataSocket; -} WININETFTPFILE, *LPWININETFTPFILE; - - -typedef struct _WININETFTPSESSIONW -{ - WININETHANDLEHEADER hdr; - WININETAPPINFOW *lpAppInfo; - int sndSocket; - int lstnSocket; - int pasvSocket; /* data socket connected by us in case of passive FTP */ - LPWININETFTPFILE download_in_progress; - struct sockaddr_in socketAddress; - struct sockaddr_in lstnSocketAddress; - LPWSTR lpszPassword; - LPWSTR lpszUserName; -} WININETFTPSESSIONW, *LPWININETFTPSESSIONW; - - -typedef struct -{ - BOOL bIsDirectory; - LPWSTR lpszName; - DWORD nSize; - struct tm tmLastModified; - unsigned short permissions; -} FILEPROPERTIESW, *LPFILEPROPERTIESW; - - -typedef struct -{ - WININETHANDLEHEADER hdr; - WININETFTPSESSIONW *lpFtpSession; - DWORD index; - DWORD size; - LPFILEPROPERTIESW lpafp; -} WININETFTPFINDNEXTW, *LPWININETFTPFINDNEXTW; struct WORKREQ_FTPPUTFILEW { @@ -414,28 +384,6 @@ DWORD INTERNET_GetLastError(void); BOOL INTERNET_AsyncCall(LPWORKREQUEST lpWorkRequest); LPSTR INTERNET_GetResponseBuffer(void); LPSTR INTERNET_GetNextLine(INT nSocket, LPDWORD dwLen); -BOOL INTERNET_ReadFile(LPWININETHANDLEHEADER lpwh, LPVOID lpBuffer, - DWORD dwNumOfBytesToRead, LPDWORD pdwNumOfBytesRead, - BOOL bWait, BOOL bSendCompletionStatus); - -BOOLAPI FTP_FtpPutFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszLocalFile, - LPCWSTR lpszNewRemoteFile, DWORD dwFlags, DWORD_PTR dwContext); -BOOLAPI FTP_FtpSetCurrentDirectoryW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszDirectory); -BOOLAPI FTP_FtpCreateDirectoryW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszDirectory); -INTERNETAPI HINTERNET WINAPI FTP_FtpFindFirstFileW(LPWININETFTPSESSIONW lpwfs, - LPCWSTR lpszSearchFile, LPWIN32_FIND_DATAW lpFindFileData, DWORD dwFlags, DWORD_PTR dwContext); -BOOL WINAPI FTP_FindNextFileW(LPWININETFTPFINDNEXTW lpwh, LPVOID lpvFindData); -BOOLAPI FTP_FtpGetCurrentDirectoryW(LPWININETFTPSESSIONW lpwfs, LPWSTR lpszCurrentDirectory, - LPDWORD lpdwCurrentDirectory); -BOOL FTP_ConvertFileProp(LPFILEPROPERTIESW lpafp, LPWIN32_FIND_DATAW lpFindFileData); -BOOL FTP_FtpRenameFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszSrc, LPCWSTR lpszDest); -BOOL FTP_FtpRemoveDirectoryW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszDirectory); -BOOL FTP_FtpDeleteFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszFileName); -HINTERNET FTP_FtpOpenFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszFileName, - DWORD fdwAccess, DWORD dwFlags, DWORD_PTR dwContext); -BOOLAPI FTP_FtpGetFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszRemoteFile, LPCWSTR lpszNewFile, - BOOL fFailIfExists, DWORD dwLocalFlagsAttribute, DWORD dwInternetFlags, - DWORD_PTR dwContext); BOOLAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders, DWORD dwHeaderLength, LPVOID lpOptional, DWORD dwOptionalLength, @@ -471,7 +419,7 @@ BOOL NETCON_recv(WININET_NETCONNECTION *connection, void *buf, size_t len, int f 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); +DWORD NETCON_set_timeout(WININET_NETCONNECTION *connection, BOOL send, int value); extern void URLCacheContainers_CreateDefaults(void); extern void URLCacheContainers_DeleteAll(void); diff --git a/reactos/dll/win32/wininet/netconnection.c b/reactos/dll/win32/wininet/netconnection.c index 8d9d026210d..45dc40d025d 100644 --- a/reactos/dll/win32/wininet/netconnection.c +++ b/reactos/dll/win32/wininet/netconnection.c @@ -23,6 +23,12 @@ #include "config.h" #include "wine/port.h" +#ifdef HAVE_POLL_H +#include +#endif +#ifdef HAVE_SYS_POLL_H +# include +#endif #ifdef HAVE_SYS_TIME_H # include #endif @@ -49,18 +55,16 @@ #include "winerror.h" #include "wincrypt.h" +#include "wine/debug.h" +#include "internet.h" + /* To avoid conflicts with the Unix socket headers. we only need it for * the error codes anyway. */ #define USE_WS_PREFIX #include "winsock2.h" -#include "wine/debug.h" -#include "internet.h" - #define RESPONSE_TIMEOUT 30 /* FROM internet.c */ #define sock_get_error(x) WSAGetLastError() -#undef FIONREAD - WINE_DEFAULT_DEBUG_CHANNEL(wininet); @@ -115,7 +119,7 @@ BOOL NETCON_init(WININET_NETCONNECTION *connection, BOOL useSSL) connection->socketFD = -1; if (useSSL) { -#ifdef SONAME_LIBSSL +#if defined(SONAME_LIBSSL) && defined(SONAME_LIBCRYPTO) TRACE("using SSL connection\n"); if (OpenSSL_ssl_handle) /* already initialized everything */ return TRUE; @@ -202,10 +206,11 @@ BOOL NETCON_connected(WININET_NETCONNECTION *connection) return TRUE; } -#ifndef __REACTOS__ +#if 0 /* translate a unix error code into a winsock one */ static int sock_get_error( int err ) { +#if !defined(__MINGW32__) && !defined (_MSC_VER) switch (err) { case EINTR: return WSAEINTR; @@ -265,6 +270,8 @@ static int sock_get_error( int err ) #endif default: errno=err; perror("sock_set_error"); return WSAEFAULT; } +#endif + return err; } #endif @@ -588,7 +595,7 @@ BOOL NETCON_query_data_available(WININET_NETCONNECTION *connection, DWORD *avail if (!connection->useSSL) { int unread; - int retval = ioctl(connection->socketFD, FIONREAD, &unread); + int retval = ioctlsocket(connection->socketFD, FIONREAD, &unread); if (!retval) { TRACE("%d bytes of queued, but unread data\n", unread); @@ -749,7 +756,7 @@ LPCVOID NETCON_GetCert(WININET_NETCONNECTION *connection) #endif } -BOOL NETCON_set_timeout(WININET_NETCONNECTION *connection, BOOL send, int value) +DWORD NETCON_set_timeout(WININET_NETCONNECTION *connection, BOOL send, int value) { int result; struct timeval tv; @@ -757,7 +764,7 @@ BOOL NETCON_set_timeout(WININET_NETCONNECTION *connection, BOOL send, int value) /* FIXME: we should probably store the timeout in the connection to set * when we do connect */ if (!NETCON_connected(connection)) - return TRUE; + return ERROR_SUCCESS; /* value is in milliseconds, convert to struct timeval */ tv.tv_sec = value / 1000; @@ -770,9 +777,8 @@ BOOL NETCON_set_timeout(WININET_NETCONNECTION *connection, BOOL send, int value) if (result == -1) { WARN("setsockopt failed (%s)\n", strerror(errno)); - INTERNET_SetLastError(sock_get_error(errno)); - return FALSE; + return sock_get_error(errno); } - return TRUE; + return ERROR_SUCCESS; } diff --git a/reactos/dll/win32/wininet/rsrc.rc b/reactos/dll/win32/wininet/rsrc.rc index d284d72535f..c160c476447 100644 --- a/reactos/dll/win32/wininet/rsrc.rc +++ b/reactos/dll/win32/wininet/rsrc.rc @@ -42,6 +42,7 @@ */ #include "wininet_Bg.rc" #include "wininet_Cs.rc" +#include "wininet_Da.rc" #include "wininet_De.rc" #include "wininet_En.rc" #include "wininet_Eo.rc" @@ -59,5 +60,5 @@ #include "wininet_Ru.rc" #include "wininet_Si.rc" #include "wininet_Sv.rc" -#include "wininet_Tr.rc" #include "wininet_Uk.rc" +#include "wininet_Tr.rc" diff --git a/reactos/dll/win32/wininet/urlcache.c b/reactos/dll/win32/wininet/urlcache.c index 7dfb20aec10..6e768933a07 100644 --- a/reactos/dll/win32/wininet/urlcache.c +++ b/reactos/dll/win32/wininet/urlcache.c @@ -101,7 +101,7 @@ typedef struct _URL_CACHEFILE_ENTRY DWORD CacheEntryType; /* see INTERNET_CACHE_ENTRY_INFO::CacheEntryType */ DWORD dwOffsetHeaderInfo; /* offset of start of header info from start of entry */ DWORD dwHeaderInfoSize; - DWORD dwUnknown6; /* usually zero */ + DWORD dwOffsetFileExtension; /* offset of start of file extension from start of entry */ WORD wLastSyncDate; /* last sync date in dos format */ WORD wLastSyncTime; /* last sync time in dos format */ DWORD dwHitRate; /* see INTERNET_CACHE_ENTRY_INFO::dwHitRate */ @@ -375,8 +375,6 @@ static BOOL URLCacheContainer_OpenIndex(URLCACHECONTAINER * pContainer) if (CreateDirectoryW(wszDirPath, 0)) { - int k; - /* The following is OK because we generated an * 8 character directory name made from characters * [A-Z0-9], which are equivalent for all code @@ -543,7 +541,7 @@ void URLCacheContainers_CreateDefaults(void) WCHAR wszMutexName[MAX_PATH]; int path_len, suffix_len; - if (FAILED(SHGetSpecialFolderPathW(NULL, wszCachePath, DefaultContainerData[i].nFolder, TRUE))) + if (!SHGetSpecialFolderPathW(NULL, wszCachePath, DefaultContainerData[i].nFolder, TRUE)) { ERR("Couldn't get path for default container %u\n", i); continue; @@ -583,13 +581,12 @@ void URLCacheContainers_DeleteAll(void) static BOOL URLCacheContainers_FindContainerW(LPCWSTR lpwszUrl, URLCACHECONTAINER ** ppContainer) { - struct list * cursor; + URLCACHECONTAINER * pContainer; TRACE("searching for prefix for URL: %s\n", debugstr_w(lpwszUrl)); - LIST_FOR_EACH(cursor, &UrlContainers) + LIST_FOR_EACH_ENTRY(pContainer, &UrlContainers, URLCACHECONTAINER, entry) { - URLCACHECONTAINER * pContainer = LIST_ENTRY(cursor, URLCACHECONTAINER, entry); int prefix_len = strlenW(pContainer->cache_prefix); if (!strncmpW(pContainer->cache_prefix, lpwszUrl, prefix_len)) { @@ -618,6 +615,42 @@ static BOOL URLCacheContainers_FindContainerA(LPCSTR lpszUrl, URLCACHECONTAINER return FALSE; } +static BOOL URLCacheContainers_Enum(LPCWSTR lpwszSearchPattern, DWORD dwIndex, URLCACHECONTAINER ** ppContainer) +{ + DWORD i = 0; + URLCACHECONTAINER * pContainer; + + TRACE("searching for prefix: %s\n", debugstr_w(lpwszSearchPattern)); + + /* non-NULL search pattern only returns one container ever */ + if (lpwszSearchPattern && dwIndex > 0) + return FALSE; + + LIST_FOR_EACH_ENTRY(pContainer, &UrlContainers, URLCACHECONTAINER, entry) + { + if (lpwszSearchPattern) + { + if (!strcmpW(pContainer->cache_prefix, lpwszSearchPattern)) + { + TRACE("found container with prefix %s\n", debugstr_w(pContainer->cache_prefix)); + *ppContainer = pContainer; + return TRUE; + } + } + else + { + if (i == dwIndex) + { + TRACE("found container with prefix %s\n", debugstr_w(pContainer->cache_prefix)); + *ppContainer = pContainer; + return TRUE; + } + } + i++; + } + return FALSE; +} + /*********************************************************************** * URLCacheContainer_LockIndex (Internal) * @@ -874,14 +907,14 @@ static BOOL URLCache_LocalFileNameToPathA( return FALSE; } - path_len = WideCharToMultiByte(CP_ACP, 0, pContainer->path, -1, NULL, 0, NULL, NULL); - file_name_len = strlen(szLocalFileName); + path_len = WideCharToMultiByte(CP_ACP, 0, pContainer->path, -1, NULL, 0, NULL, NULL) - 1; + file_name_len = strlen(szLocalFileName) + 1 /* for nul-terminator */; dir_len = DIR_LENGTH; - nRequired = (path_len + dir_len + 1 + file_name_len) * sizeof(WCHAR); + nRequired = (path_len + dir_len + 1 + file_name_len) * sizeof(char); if (nRequired < *lpBufferSize) { - WideCharToMultiByte(CP_ACP, 0, pContainer->path, -1, szPath, -1, NULL, NULL); + WideCharToMultiByte(CP_ACP, 0, pContainer->path, -1, szPath, path_len, NULL, NULL); memcpy(szPath+path_len, pHeader->directory_data[Directory].filename, dir_len); szPath[path_len + dir_len] = '\\'; memcpy(szPath + path_len + dir_len + 1, szLocalFileName, file_name_len); @@ -907,7 +940,7 @@ static BOOL URLCache_CopyEntry( LPCURLCACHE_HEADER pHeader, LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo, LPDWORD lpdwBufferSize, - URL_CACHEFILE_ENTRY * pUrlEntry, + const URL_CACHEFILE_ENTRY * pUrlEntry, BOOL bUnicode) { int lenUrl; @@ -987,6 +1020,30 @@ static BOOL URLCache_CopyEntry( ZeroMemory((LPBYTE)lpCacheEntryInfo + dwRequiredSize, 4 - (dwRequiredSize % 4)); dwRequiredSize = DWORD_ALIGN(dwRequiredSize); + if (pUrlEntry->dwOffsetFileExtension) + { + int lenExtension; + + if (bUnicode) + lenExtension = MultiByteToWideChar(CP_ACP, 0, (LPSTR)pUrlEntry + pUrlEntry->dwOffsetFileExtension, -1, NULL, 0); + else + lenExtension = strlen((LPSTR)pUrlEntry + pUrlEntry->dwOffsetFileExtension) + 1; + dwRequiredSize += lenExtension * (bUnicode ? sizeof(WCHAR) : sizeof(CHAR)); + + if (*lpdwBufferSize >= dwRequiredSize) + { + lpCacheEntryInfo->lpszFileExtension = (LPSTR)lpCacheEntryInfo + dwRequiredSize - lenExtension; + if (bUnicode) + MultiByteToWideChar(CP_ACP, 0, (LPSTR)pUrlEntry + pUrlEntry->dwOffsetFileExtension, -1, (LPWSTR)lpCacheEntryInfo->lpszSourceUrlName, lenExtension); + else + memcpy(lpCacheEntryInfo->lpszFileExtension, (LPSTR)pUrlEntry + pUrlEntry->dwOffsetFileExtension, lenExtension * sizeof(CHAR)); + } + + if ((dwRequiredSize % 4) && (dwRequiredSize < *lpdwBufferSize)) + ZeroMemory((LPBYTE)lpCacheEntryInfo + dwRequiredSize, 4 - (dwRequiredSize % 4)); + dwRequiredSize = DWORD_ALIGN(dwRequiredSize); + } + if (dwRequiredSize > *lpdwBufferSize) { *lpdwBufferSize = dwRequiredSize; @@ -1082,12 +1139,6 @@ static DWORD URLCache_HashKey(LPCSTR lpszKey) }; BYTE key[4]; DWORD i; - int subscript[sizeof(key) / sizeof(key[0])]; - - subscript[0] = *lpszKey; - subscript[1] = (char)(*lpszKey + 1); - subscript[2] = (char)(*lpszKey + 2); - subscript[3] = (char)(*lpszKey + 3); for (i = 0; i < sizeof(key) / sizeof(key[0]); i++) key[i] = lookupTable[i]; @@ -1106,6 +1157,13 @@ static inline HASH_CACHEFILE_ENTRY * URLCache_HashEntryFromOffset(LPCURLCACHE_HE return (HASH_CACHEFILE_ENTRY *)((LPBYTE)pHeader + dwOffset); } +static inline BOOL URLCache_IsHashEntryValid(LPCURLCACHE_HEADER pHeader, const HASH_CACHEFILE_ENTRY *pHashEntry) +{ + /* check pHashEntry located within acceptable bounds in the URL cache mapping */ + return ((DWORD)((LPBYTE)pHashEntry - (LPBYTE)pHeader) >= ENTRY_START_OFFSET) && + ((DWORD)((LPBYTE)pHashEntry - (LPBYTE)pHeader) < pHeader->dwFileSize); +} + static BOOL URLCache_FindHash(LPCURLCACHE_HEADER pHeader, LPCSTR lpszUrl, struct _HASH_ENTRY ** ppHashEntry) { /* structure of hash table: @@ -1125,10 +1183,10 @@ static BOOL URLCache_FindHash(LPCURLCACHE_HEADER pHeader, LPCSTR lpszUrl, struct HASH_CACHEFILE_ENTRY * pHashEntry; DWORD dwHashTableNumber = 0; - key = (DWORD)(key / HASHTABLE_NUM_ENTRIES) * HASHTABLE_NUM_ENTRIES; + key = (key / HASHTABLE_NUM_ENTRIES) * HASHTABLE_NUM_ENTRIES; for (pHashEntry = URLCache_HashEntryFromOffset(pHeader, pHeader->dwOffsetFirstHashTable); - ((DWORD)((LPBYTE)pHashEntry - (LPBYTE)pHeader) >= ENTRY_START_OFFSET) && ((DWORD)((LPBYTE)pHashEntry - (LPBYTE)pHeader) < pHeader->dwFileSize); + URLCache_IsHashEntryValid(pHeader, pHashEntry); pHashEntry = URLCache_HashEntryFromOffset(pHeader, pHashEntry->dwAddressNext)) { int i; @@ -1147,7 +1205,7 @@ static BOOL URLCache_FindHash(LPCURLCACHE_HEADER pHeader, LPCSTR lpszUrl, struct for (i = 0; i < HASHTABLE_BLOCKSIZE; i++) { struct _HASH_ENTRY * pHashElement = &pHashEntry->HashTable[offset + i]; - if (key == (DWORD)(pHashElement->dwHashKey / HASHTABLE_NUM_ENTRIES) * HASHTABLE_NUM_ENTRIES) + if (key == (pHashElement->dwHashKey / HASHTABLE_NUM_ENTRIES) * HASHTABLE_NUM_ENTRIES) { /* FIXME: we should make sure that this is the right element * before returning and claiming that it is. We can do this @@ -1195,7 +1253,7 @@ static BOOL URLCache_FindHashW(LPCURLCACHE_HEADER pHeader, LPCWSTR lpszUrl, stru */ static BOOL URLCache_HashEntrySetUse(struct _HASH_ENTRY * pHashEntry, DWORD dwUseCount) { - pHashEntry->dwHashKey = dwUseCount | (DWORD)(pHashEntry->dwHashKey / HASHTABLE_NUM_ENTRIES) * HASHTABLE_NUM_ENTRIES; + pHashEntry->dwHashKey = dwUseCount | (pHashEntry->dwHashKey / HASHTABLE_NUM_ENTRIES) * HASHTABLE_NUM_ENTRIES; return TRUE; } @@ -1238,10 +1296,10 @@ static BOOL URLCache_AddEntryToHash(LPURLCACHE_HEADER pHeader, LPCSTR lpszUrl, D HASH_CACHEFILE_ENTRY * pHashEntry; DWORD dwHashTableNumber = 0; - key = (DWORD)(key / HASHTABLE_NUM_ENTRIES) * HASHTABLE_NUM_ENTRIES; + key = (key / HASHTABLE_NUM_ENTRIES) * HASHTABLE_NUM_ENTRIES; for (pHashEntry = URLCache_HashEntryFromOffset(pHeader, pHeader->dwOffsetFirstHashTable); - ((DWORD)((LPBYTE)pHashEntry - (LPBYTE)pHeader) >= ENTRY_START_OFFSET) && ((DWORD)((LPBYTE)pHashEntry - (LPBYTE)pHeader) < pHeader->dwFileSize); + URLCache_IsHashEntryValid(pHeader, pHashEntry); pHashEntry = URLCache_HashEntryFromOffset(pHeader, pHashEntry->dwAddressNext)) { int i; @@ -1277,6 +1335,17 @@ static BOOL URLCache_AddEntryToHash(LPURLCACHE_HEADER pHeader, LPCSTR lpszUrl, D return TRUE; } +/*********************************************************************** + * URLCache_CreateHashTable (Internal) + * + * Creates a new hash table in free space and adds it to the chain of existing + * hash tables. + * + * RETURNS + * TRUE if the hash table was created + * FALSE if the hash table could not be created + * + */ static HASH_CACHEFILE_ENTRY *URLCache_CreateHashTable(LPURLCACHE_HEADER pHeader, HASH_CACHEFILE_ENTRY *pPrevHash) { HASH_CACHEFILE_ENTRY *pHash; @@ -1307,6 +1376,66 @@ static HASH_CACHEFILE_ENTRY *URLCache_CreateHashTable(LPURLCACHE_HEADER pHeader, return pHash; } +/*********************************************************************** + * URLCache_EnumHashTables (Internal) + * + * Enumerates the hash tables in a container. + * + * RETURNS + * TRUE if an entry was found + * FALSE if there are no more tables to enumerate. + * + */ +static BOOL URLCache_EnumHashTables(LPCURLCACHE_HEADER pHeader, DWORD *pdwHashTableNumber, HASH_CACHEFILE_ENTRY ** ppHashEntry) +{ + for (*ppHashEntry = URLCache_HashEntryFromOffset(pHeader, pHeader->dwOffsetFirstHashTable); + URLCache_IsHashEntryValid(pHeader, *ppHashEntry); + *ppHashEntry = URLCache_HashEntryFromOffset(pHeader, (*ppHashEntry)->dwAddressNext)) + { + TRACE("looking at hash table number %d\n", (*ppHashEntry)->dwHashTableNumber); + if ((*ppHashEntry)->dwHashTableNumber != *pdwHashTableNumber) + continue; + /* make sure that it is in fact a hash entry */ + if ((*ppHashEntry)->CacheFileEntry.dwSignature != HASH_SIGNATURE) + { + ERR("Error: not right signature (\"%.4s\") - expected \"HASH\"\n", (LPCSTR)&(*ppHashEntry)->CacheFileEntry.dwSignature); + (*pdwHashTableNumber)++; + continue; + } + + TRACE("hash table number %d found\n", *pdwHashTableNumber); + return TRUE; + } + return FALSE; +} + +/*********************************************************************** + * URLCache_EnumHashTableEntries (Internal) + * + * Enumerates entries in a hash table and returns the next non-free entry. + * + * RETURNS + * TRUE if an entry was found + * FALSE if the hash table is empty or there are no more entries to + * enumerate. + * + */ +static BOOL URLCache_EnumHashTableEntries(LPCURLCACHE_HEADER pHeader, const HASH_CACHEFILE_ENTRY * pHashEntry, + DWORD * index, const struct _HASH_ENTRY ** ppHashEntry) +{ + for (; *index < HASHTABLE_SIZE ; (*index)++) + { + if (pHashEntry->HashTable[*index].dwHashKey == HASHTABLE_FREE) + continue; + + *ppHashEntry = &pHashEntry->HashTable[*index]; + TRACE("entry found %d\n", *index); + return TRUE; + } + TRACE("no more entries (%d)\n", *index); + return FALSE; +} + /*********************************************************************** * GetUrlCacheEntryInfoExA (WININET.@) * @@ -1354,8 +1483,8 @@ BOOL WINAPI GetUrlCacheEntryInfoA( { LPURLCACHE_HEADER pHeader; struct _HASH_ENTRY * pHashEntry; - CACHEFILE_ENTRY * pEntry; - URL_CACHEFILE_ENTRY * pUrlEntry; + const CACHEFILE_ENTRY * pEntry; + const URL_CACHEFILE_ENTRY * pUrlEntry; URLCACHECONTAINER * pContainer; TRACE("(%s, %p, %p)\n", debugstr_a(lpszUrlName), lpCacheEntryInfo, lpdwCacheEntryInfoBufferSize); @@ -1377,7 +1506,7 @@ BOOL WINAPI GetUrlCacheEntryInfoA( return FALSE; } - pEntry = (CACHEFILE_ENTRY *)((LPBYTE)pHeader + pHashEntry->dwOffsetEntry); + pEntry = (const CACHEFILE_ENTRY *)((LPBYTE)pHeader + pHashEntry->dwOffsetEntry); if (pEntry->dwSignature != URL_SIGNATURE) { URLCacheContainer_UnlockIndex(pContainer, pHeader); @@ -1386,23 +1515,26 @@ BOOL WINAPI GetUrlCacheEntryInfoA( return FALSE; } - pUrlEntry = (URL_CACHEFILE_ENTRY *)pEntry; + pUrlEntry = (const URL_CACHEFILE_ENTRY *)pEntry; TRACE("Found URL: %s\n", debugstr_a((LPSTR)pUrlEntry + pUrlEntry->dwOffsetUrl)); if (pUrlEntry->dwOffsetHeaderInfo) TRACE("Header info: %s\n", debugstr_a((LPSTR)pUrlEntry + pUrlEntry->dwOffsetHeaderInfo)); - if (!URLCache_CopyEntry( - pContainer, - pHeader, - lpCacheEntryInfo, - lpdwCacheEntryInfoBufferSize, - pUrlEntry, - FALSE /* ANSI */)) + if (lpdwCacheEntryInfoBufferSize) { - URLCacheContainer_UnlockIndex(pContainer, pHeader); - return FALSE; + if (!URLCache_CopyEntry( + pContainer, + pHeader, + lpCacheEntryInfo, + lpdwCacheEntryInfoBufferSize, + pUrlEntry, + FALSE /* ANSI */)) + { + URLCacheContainer_UnlockIndex(pContainer, pHeader); + return FALSE; + } + TRACE("Local File Name: %s\n", debugstr_a(lpCacheEntryInfo->lpszLocalFileName)); } - TRACE("Local File Name: %s\n", debugstr_a(lpCacheEntryInfo->lpszLocalFileName)); URLCacheContainer_UnlockIndex(pContainer, pHeader); @@ -1419,8 +1551,8 @@ BOOL WINAPI GetUrlCacheEntryInfoW(LPCWSTR lpszUrl, { LPURLCACHE_HEADER pHeader; struct _HASH_ENTRY * pHashEntry; - CACHEFILE_ENTRY * pEntry; - URL_CACHEFILE_ENTRY * pUrlEntry; + const CACHEFILE_ENTRY * pEntry; + const URL_CACHEFILE_ENTRY * pUrlEntry; URLCACHECONTAINER * pContainer; TRACE("(%s, %p, %p)\n", debugstr_w(lpszUrl), lpCacheEntryInfo, lpdwCacheEntryInfoBufferSize); @@ -1442,7 +1574,7 @@ BOOL WINAPI GetUrlCacheEntryInfoW(LPCWSTR lpszUrl, return FALSE; } - pEntry = (CACHEFILE_ENTRY *)((LPBYTE)pHeader + pHashEntry->dwOffsetEntry); + pEntry = (const CACHEFILE_ENTRY *)((LPBYTE)pHeader + pHashEntry->dwOffsetEntry); if (pEntry->dwSignature != URL_SIGNATURE) { URLCacheContainer_UnlockIndex(pContainer, pHeader); @@ -1451,22 +1583,25 @@ BOOL WINAPI GetUrlCacheEntryInfoW(LPCWSTR lpszUrl, return FALSE; } - pUrlEntry = (URL_CACHEFILE_ENTRY *)pEntry; + pUrlEntry = (const URL_CACHEFILE_ENTRY *)pEntry; TRACE("Found URL: %s\n", debugstr_a((LPSTR)pUrlEntry + pUrlEntry->dwOffsetUrl)); TRACE("Header info: %s\n", debugstr_a((LPSTR)pUrlEntry + pUrlEntry->dwOffsetHeaderInfo)); - if (!URLCache_CopyEntry( - pContainer, - pHeader, - (LPINTERNET_CACHE_ENTRY_INFOA)lpCacheEntryInfo, - lpdwCacheEntryInfoBufferSize, - pUrlEntry, - TRUE /* UNICODE */)) + if (lpdwCacheEntryInfoBufferSize) { - URLCacheContainer_UnlockIndex(pContainer, pHeader); - return FALSE; + if (!URLCache_CopyEntry( + pContainer, + pHeader, + (LPINTERNET_CACHE_ENTRY_INFOA)lpCacheEntryInfo, + lpdwCacheEntryInfoBufferSize, + pUrlEntry, + TRUE /* UNICODE */)) + { + URLCacheContainer_UnlockIndex(pContainer, pHeader); + return FALSE; + } + TRACE("Local File Name: %s\n", debugstr_w(lpCacheEntryInfo->lpszLocalFileName)); } - TRACE("Local File Name: %s\n", debugstr_w(lpCacheEntryInfo->lpszLocalFileName)); URLCacheContainer_UnlockIndex(pContainer, pHeader); @@ -1974,8 +2109,7 @@ BOOL WINAPI CreateUrlCacheEntryW( return FALSE; } - for (lpszUrlEnd = lpszUrlName; *lpszUrlEnd; lpszUrlEnd++) - ; + lpszUrlEnd = lpszUrlName + strlenW(lpszUrlName); if (((lpszUrlEnd - lpszUrlName) > 1) && (*(lpszUrlEnd - 1) == '/' || *(lpszUrlEnd - 1) == '\\')) lpszUrlEnd--; @@ -1990,6 +2124,10 @@ BOOL WINAPI CreateUrlCacheEntryW( lpszUrlPart++; break; } + else if(*lpszUrlPart == '?' || *lpszUrlPart == '#') + { + lpszUrlEnd = lpszUrlPart; + } } if (!lstrcmpW(lpszUrlPart, szWWW)) { @@ -2101,12 +2239,16 @@ static BOOL WINAPI CommitUrlCacheEntryInternal( DWORD dwBytesNeeded = DWORD_ALIGN(sizeof(*pUrlEntry)); DWORD dwOffsetLocalFileName = 0; DWORD dwOffsetHeader = 0; + DWORD dwOffsetFileExtension = 0; DWORD dwFileSizeLow = 0; DWORD dwFileSizeHigh = 0; BYTE cDirectory = 0; + int len; char achFile[MAX_PATH]; - char achUrl[MAX_PATH]; + LPSTR lpszUrlNameA = NULL; + LPSTR lpszFileExtensionA = NULL; char *pchLocalFileName = 0; + DWORD error = ERROR_SUCCESS; TRACE("(%s, %s, ..., ..., %x, %p, %d, %s, %s)\n", debugstr_w(lpszUrlName), @@ -2152,17 +2294,35 @@ static BOOL WINAPI CommitUrlCacheEntryInternal( if (!(pHeader = URLCacheContainer_LockIndex(pContainer))) return FALSE; - WideCharToMultiByte(CP_ACP, 0, lpszUrlName, -1, achUrl, -1, NULL, NULL); - - if (URLCache_FindHash(pHeader, achUrl, &pHashEntry)) + len = WideCharToMultiByte(CP_ACP, 0, lpszUrlName, -1, NULL, 0, NULL, NULL); + lpszUrlNameA = HeapAlloc(GetProcessHeap(), 0, len * sizeof(char)); + if (!lpszUrlNameA) + { + error = GetLastError(); + goto cleanup; + } + WideCharToMultiByte(CP_ACP, 0, lpszUrlName, -1, lpszUrlNameA, len, NULL, NULL); + + if (lpszFileExtension) + { + len = WideCharToMultiByte(CP_ACP, 0, lpszFileExtension, -1, NULL, 0, NULL, NULL); + lpszFileExtensionA = HeapAlloc(GetProcessHeap(), 0, len * sizeof(char)); + if (!lpszFileExtensionA) + { + error = GetLastError(); + goto cleanup; + } + WideCharToMultiByte(CP_ACP, 0, lpszFileExtension, -1, lpszFileExtensionA, len, NULL, NULL); + } + + if (URLCache_FindHash(pHeader, lpszUrlNameA, &pHashEntry)) { - URLCacheContainer_UnlockIndex(pContainer, pHeader); FIXME("entry already in cache - don't know what to do!\n"); /* * SetLastError(ERROR_FILE_NOT_FOUND); * return FALSE; */ - return TRUE; + goto cleanup; } if (lpszLocalFileName) @@ -2171,10 +2331,9 @@ static BOOL WINAPI CommitUrlCacheEntryInternal( if (strncmpW(lpszLocalFileName, pContainer->path, lstrlenW(pContainer->path))) { - URLCacheContainer_UnlockIndex(pContainer, pHeader); ERR("path %s must begin with cache content path %s\n", debugstr_w(lpszLocalFileName), debugstr_w(pContainer->path)); - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; + error = ERROR_INVALID_PARAMETER; + goto cleanup; } /* skip container path prefix */ @@ -2194,18 +2353,18 @@ static BOOL WINAPI CommitUrlCacheEntryInternal( if (!bFound) { - URLCacheContainer_UnlockIndex(pContainer, pHeader); ERR("cache directory not found in path %s\n", debugstr_w(lpszLocalFileName)); - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; + error = ERROR_INVALID_PARAMETER; + goto cleanup; } lpszLocalFileName += (DIR_LENGTH + 1); /* "1234WXYZ\" */ } - dwBytesNeeded = DWORD_ALIGN(dwBytesNeeded + strlen(achUrl) + 1); + dwBytesNeeded = DWORD_ALIGN(dwBytesNeeded + strlen(lpszUrlNameA) + 1); if (lpszLocalFileName) { + len = WideCharToMultiByte(CP_ACP, 0, lpszUrlName, -1, NULL, 0, NULL, NULL); dwOffsetLocalFileName = dwBytesNeeded; dwBytesNeeded = DWORD_ALIGN(dwBytesNeeded + strlen(pchLocalFileName) + 1); } @@ -2214,6 +2373,11 @@ static BOOL WINAPI CommitUrlCacheEntryInternal( dwOffsetHeader = dwBytesNeeded; dwBytesNeeded = DWORD_ALIGN(dwBytesNeeded + dwHeaderSize); } + if (lpszFileExtensionA) + { + dwOffsetFileExtension = dwBytesNeeded; + dwBytesNeeded = DWORD_ALIGN(dwBytesNeeded + strlen(lpszFileExtensionA) + 1); + } /* round up to next block */ if (dwBytesNeeded % BLOCKSIZE) @@ -2224,10 +2388,9 @@ static BOOL WINAPI CommitUrlCacheEntryInternal( if (!URLCache_FindFirstFreeEntry(pHeader, dwBytesNeeded / BLOCKSIZE, &pEntry)) { - URLCacheContainer_UnlockIndex(pContainer, pHeader); ERR("no free entries\n"); - SetLastError(ERROR_DISK_FULL); - return FALSE; + error = ERROR_DISK_FULL; + goto cleanup; } /* FindFirstFreeEntry fills in blocks used */ @@ -2238,6 +2401,7 @@ static BOOL WINAPI CommitUrlCacheEntryInternal( pUrlEntry->dwHeaderInfoSize = dwHeaderSize; pUrlEntry->dwExemptDelta = 0; pUrlEntry->dwHitRate = 0; + pUrlEntry->dwOffsetFileExtension = dwOffsetFileExtension; pUrlEntry->dwOffsetHeaderInfo = dwOffsetHeader; pUrlEntry->dwOffsetLocalName = dwOffsetLocalFileName; pUrlEntry->dwOffsetUrl = DWORD_ALIGN(sizeof(*pUrlEntry)); @@ -2258,27 +2422,38 @@ static BOOL WINAPI CommitUrlCacheEntryInternal( pUrlEntry->dwUnknown3 = 0x60; pUrlEntry->Unknown4 = 0; pUrlEntry->wUnknown5 = 0x1010; - pUrlEntry->dwUnknown6 = 0; pUrlEntry->dwUnknown7 = 0; pUrlEntry->dwUnknown8 = 0; - strcpy((LPSTR)pUrlEntry + pUrlEntry->dwOffsetUrl, achUrl); + strcpy((LPSTR)pUrlEntry + pUrlEntry->dwOffsetUrl, lpszUrlNameA); if (dwOffsetLocalFileName) strcpy((LPSTR)((LPBYTE)pUrlEntry + dwOffsetLocalFileName), pchLocalFileName + DIR_LENGTH + 1); if (dwOffsetHeader) - memcpy((LPBYTE)pUrlEntry + dwOffsetHeader, lpHeaderInfo, dwHeaderSize); + memcpy((LPBYTE)pUrlEntry + dwOffsetHeader, lpHeaderInfo, dwHeaderSize); + if (dwOffsetFileExtension) + strcpy((LPSTR)((LPBYTE)pUrlEntry + dwOffsetFileExtension), lpszFileExtensionA); - if (!URLCache_AddEntryToHash(pHeader, achUrl, (DWORD)((LPBYTE)pUrlEntry - (LPBYTE)pHeader))) + if (!URLCache_AddEntryToHash(pHeader, lpszUrlNameA, (DWORD)((LPBYTE)pUrlEntry - (LPBYTE)pHeader))) { URLCache_DeleteEntry(pHeader, &pUrlEntry->CacheFileEntry); URLCacheContainer_UnlockIndex(pContainer, pHeader); + HeapFree(GetProcessHeap(), 0, lpszUrlNameA); return FALSE; } +cleanup: URLCacheContainer_UnlockIndex(pContainer, pHeader); + HeapFree(GetProcessHeap(), 0, lpszUrlNameA); + HeapFree(GetProcessHeap(), 0, lpszFileExtensionA); - return TRUE; + if (error == ERROR_SUCCESS) + return TRUE; + else + { + SetLastError(error); + return FALSE; + } } /*********************************************************************** @@ -2298,11 +2473,11 @@ BOOL WINAPI CommitUrlCacheEntryA( ) { DWORD len; - WCHAR *url_name; - WCHAR *local_file_name; + WCHAR *url_name = NULL; + WCHAR *local_file_name = NULL; WCHAR *original_url = NULL; + WCHAR *file_extension = NULL; BOOL bSuccess = FALSE; - DWORD dwError = 0; TRACE("(%s, %s, ..., ..., %x, %p, %d, %s, %s)\n", debugstr_a(lpszUrlName), @@ -2313,51 +2488,47 @@ BOOL WINAPI CommitUrlCacheEntryA( debugstr_a(lpszFileExtension), debugstr_a(lpszOriginalUrl)); - if (lpszFileExtension != 0) + len = MultiByteToWideChar(CP_ACP, 0, lpszUrlName, -1, NULL, 0); + url_name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + if (!url_name) + goto cleanup; + MultiByteToWideChar(CP_ACP, 0, lpszUrlName, -1, url_name, len); + + if (lpszLocalFileName) { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; + len = MultiByteToWideChar(CP_ACP, 0, lpszLocalFileName, -1, NULL, 0); + local_file_name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + if (!local_file_name) + goto cleanup; + MultiByteToWideChar(CP_ACP, 0, lpszLocalFileName, -1, local_file_name, len); } - if ((len = MultiByteToWideChar(CP_ACP, 0, lpszUrlName, -1, NULL, 0)) != 0 && - (url_name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR))) != 0) + if (lpszFileExtension) { - MultiByteToWideChar(CP_ACP, 0, lpszUrlName, -1, url_name, len); - if ((len = MultiByteToWideChar(CP_ACP, 0, lpszLocalFileName, -1, NULL, 0)) != 0 && - (local_file_name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR))) != 0) - { - MultiByteToWideChar(CP_ACP, 0, lpszLocalFileName, -1, local_file_name, len); - if (!lpszOriginalUrl || - ((len = MultiByteToWideChar(CP_ACP, 0, lpszOriginalUrl, -1, NULL, 0)) != 0 && - (original_url = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR))) != 0)) - { - if (original_url) - MultiByteToWideChar(CP_ACP, 0, lpszOriginalUrl, -1, original_url, len); - if (CommitUrlCacheEntryInternal(url_name, local_file_name, ExpireTime, LastModifiedTime, - CacheEntryType, lpHeaderInfo, dwHeaderSize, - NULL, original_url)) - { - bSuccess = TRUE; - } - else - { - dwError = GetLastError(); - } - HeapFree(GetProcessHeap(), 0, original_url); - } - else - { - dwError = GetLastError(); - } - HeapFree(GetProcessHeap(), 0, local_file_name); - } - else - { - dwError = GetLastError(); - } - HeapFree(GetProcessHeap(), 0, url_name); - if (!bSuccess) - SetLastError(dwError); + len = MultiByteToWideChar(CP_ACP, 0, lpszFileExtension, -1, NULL, 0); + file_extension = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + if (!file_extension) + goto cleanup; + MultiByteToWideChar(CP_ACP, 0, lpszFileExtension, -1, file_extension, len); } + if (lpszOriginalUrl) + { + len = MultiByteToWideChar(CP_ACP, 0, lpszOriginalUrl, -1, NULL, 0); + original_url = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + if (!original_url) + goto cleanup; + MultiByteToWideChar(CP_ACP, 0, lpszOriginalUrl, -1, original_url, len); + } + + bSuccess = CommitUrlCacheEntryInternal(url_name, local_file_name, ExpireTime, LastModifiedTime, + CacheEntryType, lpHeaderInfo, dwHeaderSize, + file_extension, original_url); + +cleanup: + HeapFree(GetProcessHeap(), 0, original_url); + HeapFree(GetProcessHeap(), 0, file_extension); + HeapFree(GetProcessHeap(), 0, local_file_name); + HeapFree(GetProcessHeap(), 0, url_name); + return bSuccess; } @@ -2693,15 +2864,6 @@ BOOL WINAPI CreateUrlCacheContainerW(DWORD d1, DWORD d2, DWORD d3, DWORD d4, return TRUE; } -/*********************************************************************** - * FindCloseUrlCache (WININET.@) - */ -BOOL WINAPI FindCloseUrlCache(HANDLE hEnumHandle) -{ - FIXME("(%p) stub\n", hEnumHandle); - return TRUE; -} - /*********************************************************************** * FindFirstUrlCacheContainerA (WININET.@) */ @@ -2776,6 +2938,17 @@ HANDLE WINAPI FindFirstUrlCacheEntryExW( return NULL; } +#define URLCACHE_FIND_ENTRY_HANDLE_MAGIC 0xF389ABCD + +typedef struct URLCacheFindEntryHandle +{ + DWORD dwMagic; + LPWSTR lpszUrlSearchPattern; + DWORD dwContainerIndex; + DWORD dwHashTableIndex; + DWORD dwHashEntryIndex; +} URLCacheFindEntryHandle; + /*********************************************************************** * FindFirstUrlCacheEntryA (WININET.@) * @@ -2783,9 +2956,38 @@ HANDLE WINAPI FindFirstUrlCacheEntryExW( INTERNETAPI HANDLE WINAPI FindFirstUrlCacheEntryA(LPCSTR lpszUrlSearchPattern, LPINTERNET_CACHE_ENTRY_INFOA lpFirstCacheEntryInfo, LPDWORD lpdwFirstCacheEntryInfoBufferSize) { - FIXME("(%s, %p, %p): stub\n", debugstr_a(lpszUrlSearchPattern), lpFirstCacheEntryInfo, lpdwFirstCacheEntryInfoBufferSize); - SetLastError(ERROR_FILE_NOT_FOUND); - return 0; + URLCacheFindEntryHandle *pEntryHandle; + + TRACE("(%s, %p, %p)\n", debugstr_a(lpszUrlSearchPattern), lpFirstCacheEntryInfo, lpdwFirstCacheEntryInfoBufferSize); + + pEntryHandle = HeapAlloc(GetProcessHeap(), 0, sizeof(*pEntryHandle)); + if (!pEntryHandle) + return NULL; + + pEntryHandle->dwMagic = URLCACHE_FIND_ENTRY_HANDLE_MAGIC; + if (lpszUrlSearchPattern) + { + int len = MultiByteToWideChar(CP_ACP, 0, lpszUrlSearchPattern, -1, NULL, 0); + pEntryHandle->lpszUrlSearchPattern = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + if (!pEntryHandle->lpszUrlSearchPattern) + { + HeapFree(GetProcessHeap(), 0, pEntryHandle); + return NULL; + } + MultiByteToWideChar(CP_ACP, 0, lpszUrlSearchPattern, -1, pEntryHandle->lpszUrlSearchPattern, len); + } + else + pEntryHandle->lpszUrlSearchPattern = NULL; + pEntryHandle->dwContainerIndex = 0; + pEntryHandle->dwHashTableIndex = 0; + pEntryHandle->dwHashEntryIndex = 0; + + if (!FindNextUrlCacheEntryA(pEntryHandle, lpFirstCacheEntryInfo, lpdwFirstCacheEntryInfoBufferSize)) + { + HeapFree(GetProcessHeap(), 0, pEntryHandle); + return NULL; + } + return pEntryHandle; } /*********************************************************************** @@ -2795,26 +2997,113 @@ INTERNETAPI HANDLE WINAPI FindFirstUrlCacheEntryA(LPCSTR lpszUrlSearchPattern, INTERNETAPI HANDLE WINAPI FindFirstUrlCacheEntryW(LPCWSTR lpszUrlSearchPattern, LPINTERNET_CACHE_ENTRY_INFOW lpFirstCacheEntryInfo, LPDWORD lpdwFirstCacheEntryInfoBufferSize) { - FIXME("(%s, %p, %p): stub\n", debugstr_w(lpszUrlSearchPattern), lpFirstCacheEntryInfo, lpdwFirstCacheEntryInfoBufferSize); - SetLastError(ERROR_FILE_NOT_FOUND); - return 0; -} - -HANDLE WINAPI FindFirstUrlCacheGroup( DWORD dwFlags, DWORD dwFilter, LPVOID lpSearchCondition, - DWORD dwSearchCondition, GROUPID* lpGroupId, LPVOID lpReserved ) -{ - FIXME("(0x%08x, 0x%08x, %p, 0x%08x, %p, %p) stub\n", dwFlags, dwFilter, lpSearchCondition, - dwSearchCondition, lpGroupId, lpReserved); - return NULL; + URLCacheFindEntryHandle *pEntryHandle; + + TRACE("(%s, %p, %p)\n", debugstr_w(lpszUrlSearchPattern), lpFirstCacheEntryInfo, lpdwFirstCacheEntryInfoBufferSize); + + pEntryHandle = HeapAlloc(GetProcessHeap(), 0, sizeof(*pEntryHandle)); + if (!pEntryHandle) + return NULL; + + pEntryHandle->dwMagic = URLCACHE_FIND_ENTRY_HANDLE_MAGIC; + if (lpszUrlSearchPattern) + { + int len = strlenW(lpszUrlSearchPattern); + pEntryHandle->lpszUrlSearchPattern = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR)); + if (!pEntryHandle->lpszUrlSearchPattern) + { + HeapFree(GetProcessHeap(), 0, pEntryHandle); + return NULL; + } + memcpy(pEntryHandle->lpszUrlSearchPattern, lpszUrlSearchPattern, (len + 1) * sizeof(WCHAR)); + } + else + pEntryHandle->lpszUrlSearchPattern = NULL; + pEntryHandle->dwContainerIndex = 0; + pEntryHandle->dwHashTableIndex = 0; + pEntryHandle->dwHashEntryIndex = 0; + + if (!FindNextUrlCacheEntryW(pEntryHandle, lpFirstCacheEntryInfo, lpdwFirstCacheEntryInfoBufferSize)) + { + HeapFree(GetProcessHeap(), 0, pEntryHandle); + return NULL; + } + return pEntryHandle; } +/*********************************************************************** + * FindNextUrlCacheEntryA (WININET.@) + */ BOOL WINAPI FindNextUrlCacheEntryA( HANDLE hEnumHandle, LPINTERNET_CACHE_ENTRY_INFOA lpNextCacheEntryInfo, - LPDWORD lpdwNextCacheEntryInfoBufferSize -) + LPDWORD lpdwNextCacheEntryInfoBufferSize) { - FIXME("(%p, %p, %p) stub\n", hEnumHandle, lpNextCacheEntryInfo, lpdwNextCacheEntryInfoBufferSize); + URLCacheFindEntryHandle *pEntryHandle = (URLCacheFindEntryHandle *)hEnumHandle; + URLCACHECONTAINER * pContainer; + + TRACE("(%p, %p, %p)\n", hEnumHandle, lpNextCacheEntryInfo, lpdwNextCacheEntryInfoBufferSize); + + if (pEntryHandle->dwMagic != URLCACHE_FIND_ENTRY_HANDLE_MAGIC) + { + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + for (; URLCacheContainers_Enum(pEntryHandle->lpszUrlSearchPattern, pEntryHandle->dwContainerIndex, &pContainer); + pEntryHandle->dwContainerIndex++, pEntryHandle->dwHashTableIndex = 0) + { + LPURLCACHE_HEADER pHeader; + HASH_CACHEFILE_ENTRY *pHashTableEntry; + + if (!URLCacheContainer_OpenIndex(pContainer)) + return FALSE; + + if (!(pHeader = URLCacheContainer_LockIndex(pContainer))) + return FALSE; + + for (; URLCache_EnumHashTables(pHeader, &pEntryHandle->dwHashTableIndex, &pHashTableEntry); + pEntryHandle->dwHashTableIndex++, pEntryHandle->dwHashEntryIndex = 0) + { + const struct _HASH_ENTRY *pHashEntry = NULL; + for (; URLCache_EnumHashTableEntries(pHeader, pHashTableEntry, &pEntryHandle->dwHashEntryIndex, &pHashEntry); + pEntryHandle->dwHashEntryIndex++) + { + const URL_CACHEFILE_ENTRY *pUrlEntry; + const CACHEFILE_ENTRY *pEntry = (const CACHEFILE_ENTRY *)((LPBYTE)pHeader + pHashEntry->dwOffsetEntry); + + if (pEntry->dwSignature != URL_SIGNATURE) + continue; + + pUrlEntry = (URL_CACHEFILE_ENTRY *)pEntry; + TRACE("Found URL: %s\n", (LPSTR)pUrlEntry + pUrlEntry->dwOffsetUrl); + TRACE("Header info: %s\n", (LPBYTE)pUrlEntry + pUrlEntry->dwOffsetHeaderInfo); + + if (!URLCache_CopyEntry( + pContainer, + pHeader, + lpNextCacheEntryInfo, + lpdwNextCacheEntryInfoBufferSize, + pUrlEntry, + FALSE /* not UNICODE */)) + { + URLCacheContainer_UnlockIndex(pContainer, pHeader); + return FALSE; + } + TRACE("Local File Name: %s\n", debugstr_a(lpNextCacheEntryInfo->lpszLocalFileName)); + + /* increment the current index so that next time the function + * is called the next entry is returned */ + pEntryHandle->dwHashEntryIndex++; + URLCacheContainer_UnlockIndex(pContainer, pHeader); + return TRUE; + } + } + + URLCacheContainer_UnlockIndex(pContainer, pHeader); + } + + SetLastError(ERROR_NO_MORE_ITEMS); return FALSE; } @@ -2825,9 +3114,40 @@ BOOL WINAPI FindNextUrlCacheEntryW( ) { FIXME("(%p, %p, %p) stub\n", hEnumHandle, lpNextCacheEntryInfo, lpdwNextCacheEntryInfoBufferSize); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } +/*********************************************************************** + * FindCloseUrlCache (WININET.@) + */ +BOOL WINAPI FindCloseUrlCache(HANDLE hEnumHandle) +{ + URLCacheFindEntryHandle *pEntryHandle = (URLCacheFindEntryHandle *)hEnumHandle; + + TRACE("(%p)\n", hEnumHandle); + + if (!pEntryHandle || pEntryHandle->dwMagic != URLCACHE_FIND_ENTRY_HANDLE_MAGIC) + { + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + pEntryHandle->dwMagic = 0; + HeapFree(GetProcessHeap(), 0, pEntryHandle->lpszUrlSearchPattern); + HeapFree(GetProcessHeap(), 0, pEntryHandle); + + return TRUE; +} + +HANDLE WINAPI FindFirstUrlCacheGroup( DWORD dwFlags, DWORD dwFilter, LPVOID lpSearchCondition, + DWORD dwSearchCondition, GROUPID* lpGroupId, LPVOID lpReserved ) +{ + FIXME("(0x%08x, 0x%08x, %p, 0x%08x, %p, %p) stub\n", dwFlags, dwFilter, lpSearchCondition, + dwSearchCondition, lpGroupId, lpReserved); + return NULL; +} + BOOL WINAPI FindNextUrlCacheEntryExA( HANDLE hEnumHandle, LPINTERNET_CACHE_ENTRY_INFOA lpFirstCacheEntryInfo, @@ -3012,8 +3332,8 @@ BOOL WINAPI IsUrlCacheEntryExpiredA( LPCSTR url, DWORD dwFlags, FILETIME* pftLas { LPURLCACHE_HEADER pHeader; struct _HASH_ENTRY * pHashEntry; - CACHEFILE_ENTRY * pEntry; - URL_CACHEFILE_ENTRY * pUrlEntry; + const CACHEFILE_ENTRY * pEntry; + const URL_CACHEFILE_ENTRY * pUrlEntry; URLCACHECONTAINER * pContainer; TRACE("(%s, %08x, %p)\n", debugstr_a(url), dwFlags, pftLastModified); @@ -3035,7 +3355,7 @@ BOOL WINAPI IsUrlCacheEntryExpiredA( LPCSTR url, DWORD dwFlags, FILETIME* pftLas return FALSE; } - pEntry = (CACHEFILE_ENTRY *)((LPBYTE)pHeader + pHashEntry->dwOffsetEntry); + pEntry = (const CACHEFILE_ENTRY *)((LPBYTE)pHeader + pHashEntry->dwOffsetEntry); if (pEntry->dwSignature != URL_SIGNATURE) { URLCacheContainer_UnlockIndex(pContainer, pHeader); @@ -3044,7 +3364,7 @@ BOOL WINAPI IsUrlCacheEntryExpiredA( LPCSTR url, DWORD dwFlags, FILETIME* pftLas return FALSE; } - pUrlEntry = (URL_CACHEFILE_ENTRY *)pEntry; + pUrlEntry = (const URL_CACHEFILE_ENTRY *)pEntry; DosDateTimeToFileTime(pUrlEntry->wExpiredDate, pUrlEntry->wExpiredTime, pftLastModified); @@ -3065,8 +3385,8 @@ BOOL WINAPI IsUrlCacheEntryExpiredW( LPCWSTR url, DWORD dwFlags, FILETIME* pftLa { LPURLCACHE_HEADER pHeader; struct _HASH_ENTRY * pHashEntry; - CACHEFILE_ENTRY * pEntry; - URL_CACHEFILE_ENTRY * pUrlEntry; + const CACHEFILE_ENTRY * pEntry; + const URL_CACHEFILE_ENTRY * pUrlEntry; URLCACHECONTAINER * pContainer; TRACE("(%s, %08x, %p)\n", debugstr_w(url), dwFlags, pftLastModified); @@ -3088,7 +3408,7 @@ BOOL WINAPI IsUrlCacheEntryExpiredW( LPCWSTR url, DWORD dwFlags, FILETIME* pftLa return FALSE; } - pEntry = (CACHEFILE_ENTRY *)((LPBYTE)pHeader + pHashEntry->dwOffsetEntry); + pEntry = (const CACHEFILE_ENTRY *)((LPBYTE)pHeader + pHashEntry->dwOffsetEntry); if (pEntry->dwSignature != URL_SIGNATURE) { URLCacheContainer_UnlockIndex(pContainer, pHeader); @@ -3097,7 +3417,7 @@ BOOL WINAPI IsUrlCacheEntryExpiredW( LPCWSTR url, DWORD dwFlags, FILETIME* pftLa return FALSE; } - pUrlEntry = (URL_CACHEFILE_ENTRY *)pEntry; + pUrlEntry = (const URL_CACHEFILE_ENTRY *)pEntry; DosDateTimeToFileTime(pUrlEntry->wExpiredDate, pUrlEntry->wExpiredTime, pftLastModified); diff --git a/reactos/dll/win32/wininet/utility.c b/reactos/dll/win32/wininet/utility.c index 70336d4136e..25972688a1e 100644 --- a/reactos/dll/win32/wininet/utility.c +++ b/reactos/dll/win32/wininet/utility.c @@ -37,7 +37,6 @@ #include "wine/debug.h" #include "internet.h" -#define CP_UNIXCP CP_THREAD_ACP WINE_DEFAULT_DEBUG_CHANNEL(wininet); @@ -72,6 +71,7 @@ time_t ConvertTimeString(LPCWSTR asctime) tmpChar[22]='\0'; tmpChar[25]='\0'; + memset( &t, 0, sizeof(t) ); t.tm_year = atoiW(tmpChar+12) - 1900; t.tm_mday = atoiW(tmpChar+5); t.tm_hour = atoiW(tmpChar+17); @@ -163,7 +163,7 @@ BOOL GetAddress(LPCWSTR lpszServerName, INTERNET_PORT nServerPort, memset(psa,0,sizeof(struct sockaddr_in)); memcpy((char *)&psa->sin_addr, phe->h_addr, phe->h_length); psa->sin_family = phe->h_addrtype; - psa->sin_port = htons((u_short)nServerPort); + psa->sin_port = htons(nServerPort); return TRUE; } diff --git a/reactos/dll/win32/wininet/wininet.spec b/reactos/dll/win32/wininet/wininet.spec index 19e65512be3..dfbc38c02fc 100644 --- a/reactos/dll/win32/wininet/wininet.spec +++ b/reactos/dll/win32/wininet/wininet.spec @@ -116,8 +116,8 @@ @ stdcall InternetAutodial(long ptr) @ stub InternetAutodialCallback @ stdcall InternetAutodialHangup(long) -@ stdcall InternetCanonicalizeUrlA(str str ptr long) -@ stdcall InternetCanonicalizeUrlW(wstr wstr ptr long) +@ stdcall InternetCanonicalizeUrlA(str ptr ptr long) +@ stdcall InternetCanonicalizeUrlW(wstr ptr ptr long) @ stdcall InternetCheckConnectionA(ptr long long) @ stdcall InternetCheckConnectionW(ptr long long) @ stdcall InternetClearAllPerSiteCookieDecisions() diff --git a/reactos/dll/win32/wininet/wininet_Da.rc b/reactos/dll/win32/wininet/wininet_Da.rc new file mode 100644 index 00000000000..515dcabd8b3 --- /dev/null +++ b/reactos/dll/win32/wininet/wininet_Da.rc @@ -0,0 +1,44 @@ +/* + * Copyright 2008 Jens Albretsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +LANGUAGE LANG_DANISH, SUBLANG_DEFAULT + +IDD_PROXYDLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 250, 154 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Skriv netvжrkskodeord" +FONT 8, "MS Shell Dlg" +{ + LTEXT "Skriv dit brugernavn og kodeord:", -1, 40, 6, 150, 15 + LTEXT "Proxy", -1, 40, 26, 50, 10 + LTEXT "Realm", -1, 40, 46, 50, 10 + LTEXT "Brugernavn", -1, 40, 66, 50, 10 + LTEXT "Kodeord", -1, 40, 86, 50, 10 + LTEXT "" IDC_PROXY, 80, 26, 150, 14, 0 + LTEXT "" IDC_REALM, 80, 46, 150, 14, 0 + EDITTEXT IDC_USERNAME, 80, 66, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP + EDITTEXT IDC_PASSWORD, 80, 86, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP | ES_PASSWORD + CHECKBOX "&Gem dette kodeord (usikkert)", IDC_SAVEPASSWORD, + 80, 106, 150, 12, BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP + PUSHBUTTON "OK", IDOK, 98, 126, 56, 14, WS_GROUP | WS_TABSTOP | BS_DEFPUSHBUTTON + PUSHBUTTON "Annuller", IDCANCEL, 158, 126, 56, 14, WS_GROUP | WS_TABSTOP +} + +STRINGTABLE DISCARDABLE +{ + IDS_LANCONNECTION "Lokal netvжrksforbindelse" +} diff --git a/reactos/dll/win32/wininet/wininet_Ru.rc b/reactos/dll/win32/wininet/wininet_Ru.rc index 05d706ba12d..d75985ba1b7 100644 --- a/reactos/dll/win32/wininet/wininet_Ru.rc +++ b/reactos/dll/win32/wininet/wininet_Ru.rc @@ -27,7 +27,7 @@ FONT 8, "MS Shell Dlg" { LTEXT "Введите имя пользователя и пароль:", -1, 40, 6, 150, 15 LTEXT "Прокси", -1, 40, 26, 50, 10 - LTEXT "Realm", -1, 40, 46, 50, 10 + LTEXT "Домен", -1, 40, 46, 50, 10 LTEXT "Пользователь", -1, 40, 66, 50, 10 LTEXT "Пароль", -1, 40, 86, 50, 10 LTEXT "" IDC_PROXY, 80, 26, 150, 14, 0 @@ -39,3 +39,8 @@ FONT 8, "MS Shell Dlg" PUSHBUTTON "OK", IDOK, 98, 126, 56, 14, WS_GROUP | WS_TABSTOP | BS_DEFPUSHBUTTON PUSHBUTTON "Отмена", IDCANCEL, 158, 126, 56, 14, WS_GROUP | WS_TABSTOP } + +STRINGTABLE DISCARDABLE +{ + IDS_LANCONNECTION "Сетевое подключение" +} diff --git a/reactos/dll/win32/wininet/wininet_Si.rc b/reactos/dll/win32/wininet/wininet_Si.rc index af33339295c..93ac9e1f33b 100644 --- a/reactos/dll/win32/wininet/wininet_Si.rc +++ b/reactos/dll/win32/wininet/wininet_Si.rc @@ -1,5 +1,5 @@ /* - * Copyright 2003 Rok Mandeljc + * Copyright 2003, 2008 Rok Mandeljc * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -16,24 +16,33 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#pragma code_page(65001) + LANGUAGE LANG_SLOVENIAN, SUBLANG_DEFAULT IDD_PROXYDLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 250, 154 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Vnos omreћnega gesla" +CAPTION "Vnos omreЕѕnega gesla" FONT 8, "MS Shell Dlg" { - LTEXT "Vnesite uporabniљko ime in geslo:", -1, 40, 6, 150, 15 - LTEXT "Proxy", -1, 40, 26, 50, 10 - LTEXT "Realm", -1, 40, 46, 50, 10 - LTEXT "Uporabniљko ime", -1, 40, 66, 50, 10 + LTEXT "Vnesite uporabniЕЎko ime in geslo:", -1, 40, 6, 150, 15 + LTEXT "Proksi", -1, 40, 26, 50, 10 + LTEXT "Kraljestvo", -1, 40, 46, 50, 10 + LTEXT "UporabniЕЎko ime", -1, 40, 66, 50, 10 LTEXT "Geslo", -1, 40, 86, 50, 10 LTEXT "" IDC_PROXY, 80, 26, 150, 14, 0 LTEXT "" IDC_REALM, 80, 46, 150, 14, 0 EDITTEXT IDC_USERNAME, 80, 66, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP EDITTEXT IDC_PASSWORD, 80, 86, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP | ES_PASSWORD - CHECKBOX "&Shrani geslo (nezaљиiteno)", IDC_SAVEPASSWORD, + CHECKBOX "&Shrani geslo (nezaЕЎДЌiteno)", IDC_SAVEPASSWORD, 80, 106, 150, 12, BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP PUSHBUTTON "V redu", IDOK, 98, 126, 56, 14, WS_GROUP | WS_TABSTOP | BS_DEFPUSHBUTTON - PUSHBUTTON "Prekliиi", IDCANCEL, 158, 126, 56, 14, WS_GROUP | WS_TABSTOP + PUSHBUTTON "PrekliДЌi", IDCANCEL, 158, 126, 56, 14, WS_GROUP | WS_TABSTOP } + +STRINGTABLE DISCARDABLE +{ + IDS_LANCONNECTION "LAN povezava" +} + +#pragma code_page(default) diff --git a/reactos/dll/win32/wininet/wininet_Sv.rc b/reactos/dll/win32/wininet/wininet_Sv.rc index 422b2c85799..6d71f2ef842 100644 --- a/reactos/dll/win32/wininet/wininet_Sv.rc +++ b/reactos/dll/win32/wininet/wininet_Sv.rc @@ -16,7 +16,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -LANGUAGE LANG_SWEDISH, SUBLANG_DEFAULT +LANGUAGE LANG_SWEDISH, SUBLANG_NEUTRAL IDD_PROXYDLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 250, 154 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU diff --git a/reactos/dll/win32/wininet/wininet_ros.diff b/reactos/dll/win32/wininet/wininet_ros.diff index 1a26b9f5a41..b326c853b98 100644 --- a/reactos/dll/win32/wininet/wininet_ros.diff +++ b/reactos/dll/win32/wininet/wininet_ros.diff @@ -1,20 +1,6 @@ -Index: ftp.c -=================================================================== ---- ftp.c (revision 30893) -+++ ftp.c (working copy) -@@ -58,6 +58,7 @@ - - #include "wine/debug.h" - #include "internet.h" -+typedef size_t socklen_t; - - WINE_DEFAULT_DEBUG_CHANNEL(wininet); - -Index: http.c -=================================================================== ---- http.c (revision 30893) -+++ http.c (working copy) -@@ -60,6 +60,8 @@ +--- D:/Wine-CVS/wine/dlls/wininet/http.c Wed May 28 14:33:28 2008 ++++ D:/ReactOS-Trunk/reactos/dll/win32/wininet/http.c Sat May 31 11:59:23 2008 +@@ -61,6 +61,8 @@ #include "wine/debug.h" #include "wine/unicode.h" @@ -22,345 +8,115 @@ Index: http.c + WINE_DEFAULT_DEBUG_CHANNEL(wininet); - static const WCHAR g_szHttp1_0[] = {' ','H','T','T','P','/','1','.','0',0 }; -@@ -3010,7 +3011,11 @@ - /* - * HACK peek at the buffer - */ -+#if 0 -+ /* This is Wine code, we don't support MSG_PEEK yet so we have to do it -+ a bit different */ - NETCON_recv(&lpwhr->netConnection, buffer, buflen, MSG_PEEK, &rc); -+#endif + static const WCHAR g_szHttp1_0[] = {'H','T','T','P','/','1','.','0',0}; +@@ -1617,8 +1619,9 @@ - /* - * We should first receive 'HTTP/1.x nnn OK' where nnn is the status code. -@@ -3019,6 +3024,9 @@ - memset(buffer, 0, MAX_REPLY_LEN); - if (!NETCON_getNextLine(&lpwhr->netConnection, bufferA, &buflen)) - goto lend; -+#if 1 -+ rc = buflen; -+#endif - MultiByteToWideChar( CP_ACP, 0, bufferA, buflen, buffer, MAX_REPLY_LEN ); + if(req->lpszCacheFile) { + BOOL res; ++ DWORD dwBytesWritten; - /* regenerate raw headers */ -Index: inet_ntop.c -=================================================================== ---- inet_ntop.c (revision 30893) -+++ inet_ntop.c (working copy) -@@ -0,0 +1,189 @@ -+/* from NetBSD: inet_ntop.c,v 1.9 2000/01/22 22:19:16 mycroft Exp */ -+ -+/* Copyright (c) 1996 by Internet Software Consortium. -+ * -+ * Permission to use, copy, modify, and distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS -+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES -+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE -+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL -+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR -+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS -+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -+ * SOFTWARE. -+ */ -+ -+#define ENOSPC 28 -+#define EAFNOSUPPORT 52 -+ -+#ifndef IN6ADDRSZ -+#define IN6ADDRSZ 16 -+#endif -+ -+#ifndef INT16SZ -+#define INT16SZ 2 -+#endif -+ -+#ifdef SPRINTF_CHAR -+# define SPRINTF(x) strlen(sprintf/**/x) -+#else -+# define SPRINTF(x) ((size_t)sprintf x) -+#endif -+ -+/* -+ * WARNING: Don't even consider trying to compile this on a system where -+ * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. -+ */ -+ -+static const char *inet_ntop4(const u_char *src, char *dst, size_t size); -+static const char *inet_ntop6(const u_char *src, char *dst, size_t size); -+ -+/* char * -+ * inet_ntop(af, src, dst, size) -+ * convert a network format address to presentation format. -+ * return: -+ * pointer to presentation format address (`dst'), or NULL (see errno). -+ * author: -+ * Paul Vixie, 1996. -+ */ -+const char * -+inet_ntop(int af, const void *src, char *dst, size_t size) -+{ -+ -+ switch (af) { -+ case AF_INET: -+ return (inet_ntop4(src, dst, size)); -+#ifdef INET6 -+ case AF_INET6: -+ return (inet_ntop6(src, dst, size)); -+#endif -+ default: -+ errno = EAFNOSUPPORT; -+ return (NULL); -+ } -+ /* NOTREACHED */ -+} -+ -+/* const char * -+ * inet_ntop4(src, dst, size) -+ * format an IPv4 address, more or less like inet_ntoa() -+ * return: -+ * `dst' (as a const) -+ * notes: -+ * (1) uses no statics -+ * (2) takes a u_char* not an in_addr as input -+ * author: -+ * Paul Vixie, 1996. -+ */ -+static const char * -+inet_ntop4(const u_char *src, char *dst, size_t size) -+{ -+ static const char fmt[] = "%u.%u.%u.%u"; -+ char tmp[sizeof "255.255.255.255"]; -+ -+ if (SPRINTF((tmp, fmt, src[0], src[1], src[2], src[3])) > size) { -+ errno = ENOSPC; -+ return (NULL); -+ } -+ strcpy(dst, tmp); -+ return (dst); -+} -+ -+#ifdef INET6 -+/* const char * -+ * inet_ntop6(src, dst, size) -+ * convert IPv6 binary address into presentation (printable) format -+ * author: -+ * Paul Vixie, 1996. -+ */ -+static const char * -+inet_ntop6(const u_char *src, char *dst, size_t size) -+{ -+ /* -+ * Note that int32_t and int16_t need only be "at least" large enough -+ * to contain a value of the specified size. On some systems, like -+ * Crays, there is no such thing as an integer variable with 16 bits. -+ * Keep this in mind if you think this function should have been coded -+ * to use pointer overlays. All the world's not a VAX. -+ */ -+ char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp; -+ struct { int base, len; } best, cur; -+ u_int words[IN6ADDRSZ / INT16SZ]; -+ int i; -+ -+ /* -+ * Preprocess: -+ * Copy the input (bytewise) array into a wordwise array. -+ * Find the longest run of 0x00's in src[] for :: shorthanding. -+ */ -+ memset(words, '\0', sizeof words); -+ for (i = 0; i < IN6ADDRSZ; i++) -+ words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); -+ best.base = -1; -+ cur.base = -1; -+ for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { -+ if (words[i] == 0) { -+ if (cur.base == -1) -+ cur.base = i, cur.len = 1; -+ else -+ cur.len++; -+ } else { -+ if (cur.base != -1) { -+ if (best.base == -1 || cur.len > best.len) -+ best = cur; -+ cur.base = -1; -+ } -+ } -+ } -+ if (cur.base != -1) { -+ if (best.base == -1 || cur.len > best.len) -+ best = cur; -+ } -+ if (best.base != -1 && best.len < 2) -+ best.base = -1; -+ -+ /* -+ * Format the result. -+ */ -+ tp = tmp; -+ for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { -+ /* Are we inside the best run of 0x00's? */ -+ if (best.base != -1 && i >= best.base && -+ i < (best.base + best.len)) { -+ if (i == best.base) -+ *tp++ = ':'; -+ continue; -+ } -+ /* Are we following an initial run of 0x00s or any real hex? */ -+ if (i != 0) -+ *tp++ = ':'; -+ /* Is this address an encapsulated IPv4? */ -+ if (i == 6 && best.base == 0 && -+ (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { -+ if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp))) -+ return (NULL); -+ tp += strlen(tp); -+ break; -+ } -+ tp += SPRINTF((tp, "%x", words[i])); -+ } -+ /* Was it a trailing run of 0x00's? */ -+ if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) -+ *tp++ = ':'; -+ *tp++ = '\0'; -+ -+ /* -+ * Check for overflow, copy, and we're done. -+ */ -+ if ((size_t)(tp - tmp) > size) { -+ errno = ENOSPC; -+ return (NULL); -+ } -+ strcpy(dst, tmp); -+ return (dst); -+} -+#endif -+ -Index: internet.c -=================================================================== ---- internet.c (revision 30893) -+++ internet.c (working copy) -@@ -67,6 +67,7 @@ - #include "resource.h" +- res = WriteFile(req->hCacheFile, buffer, bytes_read, NULL, NULL); ++ res = WriteFile(req->hCacheFile, buffer, bytes_read, &dwBytesWritten, NULL); + if(!res) + WARN("WriteFile failed: %u\n", GetLastError()); + } +--- D:/Wine-CVS/wine/dlls/wininet/internet.c Wed May 28 14:33:28 2008 ++++ D:/ReactOS-Trunk/reactos/dll/win32/wininet/internet.c Fri May 30 18:04:29 2008 +@@ -3101,19 +3101,22 @@ - #include "wine/unicode.h" -+#define CP_UNIXCP CP_THREAD_ACP + LPSTR INTERNET_GetNextLine(INT nSocket, LPDWORD dwLen) + { +- struct pollfd pfd; ++ struct timeval tv; ++ fd_set infd; + BOOL bSuccess = FALSE; + INT nRecv = 0; + LPSTR lpszBuffer = INTERNET_GetResponseBuffer(); - WINE_DEFAULT_DEBUG_CHANNEL(wininet); + TRACE("\n"); -Index: netconnection.c -=================================================================== ---- netconnection.c (revision 30893) -+++ netconnection.c (working copy) -@@ -58,6 +58,8 @@ - #include "internet.h" +- pfd.fd = nSocket; +- pfd.events = POLLIN; ++ FD_ZERO(&infd); ++ FD_SET(nSocket, &infd); ++ tv.tv_sec=RESPONSE_TIMEOUT; ++ tv.tv_usec=0; + + while (nRecv < MAX_REPLY_LEN) + { +- if (poll(&pfd,1, RESPONSE_TIMEOUT * 1000) > 0) ++ if (select(nSocket+1,&infd,NULL,NULL,&tv) > 0) + { + if (recv(nSocket, &lpszBuffer[nRecv], 1, 0) <= 0) + { +--- D:/Wine-CVS/wine/dlls/wininet/internet.h Fri Mar 28 20:13:36 2008 ++++ D:/ReactOS-Trunk/reactos/dll/win32/wininet/internet.h Thu May 29 19:01:31 2008 +@@ -23,6 +23,9 @@ + #ifndef _WINE_INTERNET_H_ + #define _WINE_INTERNET_H_ + ++/* ReactOS-specific definitions */ ++#define CP_UNIXCP CP_THREAD_ACP ++ + #ifndef __WINE_CONFIG_H + # error You must include config.h to use this header + #endif +--- D:/Wine-CVS/wine/dlls/wininet/netconnection.c Sat May 17 12:09:49 2008 ++++ D:/ReactOS-Trunk/reactos/dll/win32/wininet/netconnection.c Sat May 31 12:01:55 2008 +@@ -64,7 +64,7 @@ + #include "winsock2.h" #define RESPONSE_TIMEOUT 30 /* FROM internet.c */ +- +#define sock_get_error(x) WSAGetLastError() -+#undef FIONREAD - WINE_DEFAULT_DEBUG_CHANNEL(wininet); -@@ -200,6 +202,7 @@ + +@@ -206,6 +206,7 @@ return TRUE; } -+#ifndef __REACTOS__ ++#if 0 /* translate a unix error code into a winsock one */ static int sock_get_error( int err ) { -@@ -263,6 +266,7 @@ - default: errno=err; perror("sock_set_error"); return WSAEFAULT; - } +@@ -272,6 +273,7 @@ + #endif + return err; } +#endif /****************************************************************************** * NETCON_create -Index: rsrc.rc -=================================================================== ---- rsrc.rc (revision 30893) -+++ rsrc.rc (working copy) -@@ -60,3 +60,4 @@ +@@ -616,16 +618,19 @@ + + if (!connection->useSSL) + { +- struct pollfd pfd; ++ struct timeval tv; ++ fd_set infd; + BOOL bSuccess = FALSE; + DWORD nRecv = 0; + +- pfd.fd = connection->socketFD; +- pfd.events = POLLIN; ++ FD_ZERO(&infd); ++ FD_SET(connection->socketFD, &infd); ++ tv.tv_sec=RESPONSE_TIMEOUT; ++ tv.tv_usec=0; + + while (nRecv < *dwBuffer) + { +- if (poll(&pfd,1, RESPONSE_TIMEOUT * 1000) > 0) ++ if (select(connection->socketFD+1,&infd,NULL,NULL,&tv) > 0) + { + if (recv(connection->socketFD, &lpszBuffer[nRecv], 1, 0) <= 0) + { +--- D:/Wine-CVS/wine/dlls/wininet/rsrc.rc Thu May 08 21:26:20 2008 ++++ D:/ReactOS-Trunk/reactos/dll/win32/wininet/rsrc.rc Thu May 29 18:57:29 2008 +@@ -60,4 +60,5 @@ + #include "wininet_Ru.rc" #include "wininet_Si.rc" #include "wininet_Sv.rc" - #include "wininet_Tr.rc" +#include "wininet_Uk.rc" -Index: utility.c -=================================================================== ---- utility.c (revision 30893) -+++ utility.c (working copy) -@@ -37,6 +37,7 @@ - - #include "wine/debug.h" - #include "internet.h" -+#define CP_UNIXCP CP_THREAD_ACP - - WINE_DEFAULT_DEBUG_CHANNEL(wininet); - -Index: wininet.rbuild -=================================================================== ---- wininet.rbuild (revision 30893) -+++ wininet.rbuild (working copy) -@@ -19,6 +19,7 @@ - ntdll - secur32 - crypt32 -+ ws2_32 - cookie.c - dialogs.c - ftp.c -Index: wininet_Uk.rc -=================================================================== ---- wininet_Uk.rc (revision 30893) -+++ wininet_Uk.rc (working copy) -@@ -0,0 +1,46 @@ -+/* -+ * wininet.dll (Ukrainian resources) -+ * -+ * Copyright 2006 Artem Reznikov -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+LANGUAGE LANG_UKRAINIAN, SUBLANG_DEFAULT -+ -+IDD_PROXYDLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 250, 154 -+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -+CAPTION "Введіть Мережний Пароль" -+FONT 8, "MS Shell Dlg" -+{ -+ LTEXT "Будь ласка, введіть Ваші ім'я та пароль:", -1, 40, 6, 150, 15 -+ LTEXT "Проксі", -1, 40, 26, 50, 10 -+ LTEXT "Область", -1, 40, 46, 50, 10 -+ LTEXT "Користувач", -1, 40, 66, 50, 10 -+ LTEXT "Пароль", -1, 40, 86, 50, 10 -+ LTEXT "" IDC_PROXY, 80, 26, 150, 14, 0 -+ LTEXT "" IDC_REALM, 80, 46, 150, 14, 0 -+ EDITTEXT IDC_USERNAME, 80, 66, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP -+ EDITTEXT IDC_PASSWORD, 80, 86, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP | ES_PASSWORD -+ CHECKBOX "&Зберегти цей пароль (небезпечно)", IDC_SAVEPASSWORD, -+ 80, 106, 150, 12, BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP -+ PUSHBUTTON "OK", IDOK, 98, 126, 56, 14, WS_GROUP | WS_TABSTOP | BS_DEFPUSHBUTTON -+ PUSHBUTTON "Скасувати", IDCANCEL, 158, 126, 56, 14, WS_GROUP | WS_TABSTOP -+} -+ -+STRINGTABLE DISCARDABLE -+{ -+ IDS_LANCONNECTION "Підключення по локальній мережі" -+} + #include "wininet_Tr.rc" diff --git a/reactos/include/psdk/wininet.h b/reactos/include/psdk/wininet.h index 4aae40ad677..de1aae3fdfd 100644 --- a/reactos/include/psdk/wininet.h +++ b/reactos/include/psdk/wininet.h @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef _WINE_WININET_H_ @@ -149,7 +149,7 @@ typedef enum { } INTERNET_SCHEME,* LPINTERNET_SCHEME; typedef struct { - DWORD dwResult; + DWORD_PTR dwResult; DWORD dwError; } INTERNET_ASYNC_RESULT,* LPINTERNET_ASYNC_RESULT; @@ -307,6 +307,70 @@ typedef struct _INTERNET_CACHE_GROUP_INFOW { DECL_WINELIB_TYPE_AW(INTERNET_CACHE_GROUP_INFO) DECL_WINELIB_TYPE_AW(LPINTERNET_CACHE_GROUP_INFO) +typedef struct _INTERNET_PER_CONN_OPTIONA { + DWORD dwOption; + union { + DWORD dwValue; + LPSTR pszValue; + FILETIME ftValue; + } Value; +} INTERNET_PER_CONN_OPTIONA, *LPINTERNET_PER_CONN_OPTIONA; + +typedef struct _INTERNET_PER_CONN_OPTIONW { + DWORD dwOption; + union { + DWORD dwValue; + LPWSTR pszValue; + FILETIME ftValue; + } Value; +} INTERNET_PER_CONN_OPTIONW, *LPINTERNET_PER_CONN_OPTIONW; + +DECL_WINELIB_TYPE_AW(INTERNET_PER_CONN_OPTION) +DECL_WINELIB_TYPE_AW(LPINTERNET_PER_CONN_OPTION) + +#define INTERNET_PER_CONN_FLAGS 1 +#define INTERNET_PER_CONN_PROXY_SERVER 2 +#define INTERNET_PER_CONN_PROXY_BYPASS 3 +#define INTERNET_PER_CONN_AUTOCONFIG_URL 4 +#define INTERNET_PER_CONN_AUTODISCOVERY_FLAGS 5 +#define INTERNET_PER_CONN_AUTOCONFIG_SECONDARY_URL 6 +#define INTERNET_PER_CONN_AUTOCONFIG_RELOAD_DELAY_MINS 7 +#define INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_TIME 8 +#define INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_URL 9 + +/* Values for INTERNET_PER_CONN_FLAGS */ +#define PROXY_TYPE_DIRECT 0x00000001 +#define PROXY_TYPE_PROXY 0x00000002 +#define PROXY_TYPE_AUTO_PROXY_URL 0x00000004 +#define PROXY_TYPE_AUTO_DETECT 0x00000008 +/* Values for INTERNET_PER_CONN_AUTODISCOVERY_FLAGS */ +#define AUTO_PROXY_FLAG_USER_SET 0x00000001 +#define AUTO_PROXY_FLAG_ALWAYS_DETECT 0x00000002 +#define AUTO_PROXY_FLAG_DETECTION_RUN 0x00000004 +#define AUTO_PROXY_FLAG_MIGRATED 0x00000008 +#define AUTO_PROXY_FLAG_DONT_CACHE_PROXY_RESULT 0x00000010 +#define AUTO_PROXY_FLAG_CACHE_INIT_RUN 0x00000020 +#define AUTO_PROXY_FLAG_DETECTION_SUSPECT 0x00000040 + +typedef struct _INTERNET_PER_CONN_OPTION_LISTA { + DWORD dwSize; + LPSTR pszConnection; + DWORD dwOptionCount; + DWORD dwOptionError; + LPINTERNET_PER_CONN_OPTIONA pOptions; +} INTERNET_PER_CONN_OPTION_LISTA, *LPINTERNET_PER_CONN_OPTION_LISTA; + +typedef struct _INTERNET_PER_CONN_OPTION_LISTW { + DWORD dwSize; + LPWSTR pszConnection; + DWORD dwOptionCount; + DWORD dwOptionError; + LPINTERNET_PER_CONN_OPTIONW pOptions; +} INTERNET_PER_CONN_OPTION_LISTW, *LPINTERNET_PER_CONN_OPTION_LISTW; + +DECL_WINELIB_TYPE_AW(INTERNET_PER_CONN_OPTION_LIST) +DECL_WINELIB_TYPE_AW(LPINTERNET_PER_CONN_OPTION_LIST) + BOOLAPI InternetTimeFromSystemTimeA(CONST SYSTEMTIME *,DWORD ,LPSTR ,DWORD); BOOLAPI InternetTimeFromSystemTimeW(CONST SYSTEMTIME *,DWORD ,LPWSTR ,DWORD); #define InternetTimeFromSystemTime WINELIB_NAME_AW(InternetTimeFromSystemTime) @@ -342,8 +406,8 @@ BOOLAPI InternetCombineUrlW(LPCWSTR ,LPCWSTR ,LPWSTR ,LPDWORD ,DWORD); #define ICU_ENCODE_SPACES_ONLY 0x04000000 #define ICU_BROWSER_MODE 0x02000000 -INTERNETAPI HINTERNET WINAPI InternetOpenA(LPCSTR ,DWORD ,LPCSTR lpszProxy ,LPCSTR lpszProxyBypass ,DWORD); -INTERNETAPI HINTERNET WINAPI InternetOpenW(LPCWSTR ,DWORD ,LPCWSTR lpszProxy ,LPCWSTR lpszProxyBypass ,DWORD); +INTERNETAPI HINTERNET WINAPI InternetOpenA(LPCSTR ,DWORD ,LPCSTR ,LPCSTR ,DWORD); +INTERNETAPI HINTERNET WINAPI InternetOpenW(LPCWSTR ,DWORD ,LPCWSTR ,LPCWSTR ,DWORD); #define InternetOpen WINELIB_NAME_AW(InternetOpen) #define INTERNET_OPEN_TYPE_PRECONFIG 0 @@ -357,9 +421,9 @@ INTERNETAPI HINTERNET WINAPI InternetOpenW(LPCWSTR ,DWORD ,LPCWSTR lpszProxy ,LP BOOLAPI InternetCloseHandle(HINTERNET); INTERNETAPI HINTERNET WINAPI InternetConnectA(HINTERNET ,LPCSTR ,INTERNET_PORT , - LPCSTR lpszUserName ,LPCSTR lpszPassword ,DWORD ,DWORD ,DWORD ); + LPCSTR ,LPCSTR ,DWORD ,DWORD ,DWORD_PTR ); INTERNETAPI HINTERNET WINAPI InternetConnectW(HINTERNET ,LPCWSTR ,INTERNET_PORT , - LPCWSTR lpszUserName ,LPCWSTR lpszPassword ,DWORD ,DWORD ,DWORD ); + LPCWSTR ,LPCWSTR ,DWORD ,DWORD ,DWORD_PTR ); #define InternetConnect WINELIB_NAME_AW(InternetConnect) #define INTERNET_SERVICE_URL 0 @@ -378,13 +442,13 @@ INTERNETAPI HINTERNET WINAPI InternetConnectW(HINTERNET ,LPCWSTR ,INTERNET_PORT dwContext \ ) -INTERNETAPI HINTERNET WINAPI InternetOpenUrlA(HINTERNET ,LPCSTR ,LPCSTR lpszHeaders ,DWORD ,DWORD ,DWORD); -INTERNETAPI HINTERNET WINAPI InternetOpenUrlW(HINTERNET ,LPCWSTR ,LPCWSTR lpszHeaders ,DWORD ,DWORD ,DWORD); +INTERNETAPI HINTERNET WINAPI InternetOpenUrlA(HINTERNET ,LPCSTR ,LPCSTR ,DWORD ,DWORD ,DWORD_PTR); +INTERNETAPI HINTERNET WINAPI InternetOpenUrlW(HINTERNET ,LPCWSTR ,LPCWSTR ,DWORD ,DWORD ,DWORD_PTR); #define InternetOpenUrl WINELIB_NAME_AW(InternetOpenUrl) BOOLAPI InternetReadFile( HINTERNET ,LPVOID ,DWORD ,LPDWORD ); -INTERNETAPI BOOL WINAPI InternetReadFileExA( HINTERNET ,LPINTERNET_BUFFERSA ,DWORD ,DWORD ); -INTERNETAPI BOOL WINAPI InternetReadFileExW( HINTERNET ,LPINTERNET_BUFFERSW ,DWORD ,DWORD ); +INTERNETAPI BOOL WINAPI InternetReadFileExA( HINTERNET ,LPINTERNET_BUFFERSA ,DWORD ,DWORD_PTR ); +INTERNETAPI BOOL WINAPI InternetReadFileExW( HINTERNET ,LPINTERNET_BUFFERSW ,DWORD ,DWORD_PTR ); #define InternetReadFileEx WINELIB_NAME_AW(InternetReadFileEx) #define IRF_ASYNC WININET_API_FLAG_ASYNC @@ -392,23 +456,23 @@ INTERNETAPI BOOL WINAPI InternetReadFileExW( HINTERNET ,LPINTERNET_BUFFERSW ,DWO #define IRF_USE_CONTEXT WININET_API_FLAG_USE_CONTEXT #define IRF_NO_WAIT 0x00000008 -INTERNETAPI DWORD WINAPI InternetSetFilePointer(HINTERNET ,LONG ,PVOID ,DWORD ,DWORD); +INTERNETAPI DWORD WINAPI InternetSetFilePointer(HINTERNET ,LONG ,PVOID ,DWORD ,DWORD_PTR); BOOLAPI InternetWriteFile(HINTERNET ,LPCVOID ,DWORD ,LPDWORD); -BOOLAPI InternetQueryDataAvailable(HINTERNET ,LPDWORD lpdwNumberOfBytesAvailable ,DWORD ,DWORD); +BOOLAPI InternetQueryDataAvailable(HINTERNET ,LPDWORD ,DWORD ,DWORD_PTR); BOOLAPI InternetFindNextFileA(HINTERNET ,LPVOID); BOOLAPI InternetFindNextFileW(HINTERNET ,LPVOID); #define InternetFindNextFile WINELIB_NAME_AW(InternetFindNextFile) -BOOLAPI InternetQueryOptionA(HINTERNET hInternet ,DWORD ,LPVOID lpBuffer ,LPDWORD); -BOOLAPI InternetQueryOptionW(HINTERNET hInternet ,DWORD ,LPVOID lpBuffer ,LPDWORD); +BOOLAPI InternetQueryOptionA(HINTERNET ,DWORD ,LPVOID ,LPDWORD); +BOOLAPI InternetQueryOptionW(HINTERNET ,DWORD ,LPVOID ,LPDWORD); #define InternetQueryOption WINELIB_NAME_AW(InternetQueryOption) -BOOLAPI InternetSetOptionA(HINTERNET hInternet ,DWORD ,LPVOID ,DWORD); -BOOLAPI InternetSetOptionW(HINTERNET hInternet ,DWORD ,LPVOID ,DWORD); +BOOLAPI InternetSetOptionA(HINTERNET ,DWORD ,LPVOID ,DWORD); +BOOLAPI InternetSetOptionW(HINTERNET ,DWORD ,LPVOID ,DWORD); #define InternetSetOption WINELIB_NAME_AW(InternetSetOption) -BOOLAPI InternetSetOptionExA(HINTERNET hInternet ,DWORD ,LPVOID ,DWORD ,DWORD); -BOOLAPI InternetSetOptionExW(HINTERNET hInternet ,DWORD ,LPVOID ,DWORD ,DWORD); +BOOLAPI InternetSetOptionExA(HINTERNET ,DWORD ,LPVOID ,DWORD ,DWORD); +BOOLAPI InternetSetOptionExW(HINTERNET ,DWORD ,LPVOID ,DWORD ,DWORD); #define InternetSetOptionEx WINELIB_NAME_AW(InternetSetOptionEx) BOOLAPI InternetLockRequestFile(HINTERNET ,HANDLE *); @@ -494,7 +558,6 @@ BOOLAPI InternetUnlockRequestFile(HANDLE); #define INTERNET_OPTION_CLIENT_CERT_CONTEXT 84 #define INTERNET_OPTION_AUTH_FLAGS 85 #define INTERNET_OPTION_COOKIES_3RD_PARTY 86 -#define INTERNET_OPTION_COOKIES_3RD_PARTY 86 #define INTERNET_OPTION_DISABLE_PASSPORT_AUTH 87 #define INTERNET_OPTION_SEND_UTF8_SERVERNAME_TO_PROXY 88 #define INTERNET_OPTION_EXEMPT_CONNECTION_LIMIT 89 @@ -554,12 +617,12 @@ BOOLAPI InternetUnlockRequestFile(HANDLE); -BOOLAPI InternetGetLastResponseInfoA(LPDWORD ,LPSTR lpszBuffer ,LPDWORD); -BOOLAPI InternetGetLastResponseInfoW(LPDWORD ,LPWSTR lpszBuffer ,LPDWORD); +BOOLAPI InternetGetLastResponseInfoA(LPDWORD ,LPSTR ,LPDWORD); +BOOLAPI InternetGetLastResponseInfoW(LPDWORD ,LPWSTR ,LPDWORD); #define InternetGetLastResponseInfo WINELIB_NAME_AW(InternetGetLastResponseInfo) -typedef VOID (CALLBACK *INTERNET_STATUS_CALLBACK)(HINTERNET ,DWORD ,DWORD , - LPVOID lpvStatusInformation ,DWORD); +typedef VOID (CALLBACK *INTERNET_STATUS_CALLBACK)(HINTERNET ,DWORD_PTR ,DWORD , + LPVOID ,DWORD); typedef INTERNET_STATUS_CALLBACK * LPINTERNET_STATUS_CALLBACK; @@ -610,18 +673,20 @@ BOOLAPI FtpCommandA(HINTERNET, BOOL, DWORD, LPCSTR, DWORD_PTR, HINTERNET *); BOOLAPI FtpCommandW(HINTERNET, BOOL, DWORD, LPCWSTR, DWORD_PTR, HINTERNET *); #define FtpCommand WINELIB_NAME_AW(FtpCommand) -INTERNETAPI HINTERNET WINAPI FtpFindFirstFileA(HINTERNET ,LPCSTR lpszSearchFile , - LPWIN32_FIND_DATAA lpFindFileData ,DWORD ,DWORD); -INTERNETAPI HINTERNET WINAPI FtpFindFirstFileW(HINTERNET ,LPCWSTR lpszSearchFile , - LPWIN32_FIND_DATAW lpFindFileData ,DWORD ,DWORD); +INTERNETAPI HINTERNET WINAPI FtpFindFirstFileA(HINTERNET ,LPCSTR , + LPWIN32_FIND_DATAA ,DWORD ,DWORD_PTR); +INTERNETAPI HINTERNET WINAPI FtpFindFirstFileW(HINTERNET ,LPCWSTR , + LPWIN32_FIND_DATAW ,DWORD ,DWORD_PTR); #define FtpFindFirstFile WINELIB_NAME_AW(FtpFindFirstFile) -BOOLAPI FtpGetFileA(HINTERNET ,LPCSTR ,LPCSTR ,BOOL ,DWORD ,DWORD ,DWORD); -BOOLAPI FtpGetFileW(HINTERNET ,LPCWSTR ,LPCWSTR ,BOOL ,DWORD ,DWORD ,DWORD); +BOOLAPI FtpGetFileA(HINTERNET ,LPCSTR ,LPCSTR ,BOOL ,DWORD ,DWORD ,DWORD_PTR); +BOOLAPI FtpGetFileW(HINTERNET ,LPCWSTR ,LPCWSTR ,BOOL ,DWORD ,DWORD ,DWORD_PTR); #define FtpGetFile WINELIB_NAME_AW(FtpGetFile) -BOOLAPI FtpPutFileA(HINTERNET ,LPCSTR ,LPCSTR ,DWORD ,DWORD); -BOOLAPI FtpPutFileW(HINTERNET ,LPCWSTR ,LPCWSTR ,DWORD ,DWORD); +DWORD WINAPI FtpGetFileSize(HINTERNET, LPDWORD); + +BOOLAPI FtpPutFileA(HINTERNET ,LPCSTR ,LPCSTR ,DWORD ,DWORD_PTR); +BOOLAPI FtpPutFileW(HINTERNET ,LPCWSTR ,LPCWSTR ,DWORD ,DWORD_PTR); #define FtpPutFile WINELIB_NAME_AW(FtpPutFile) BOOLAPI FtpDeleteFileA(HINTERNET ,LPCSTR); @@ -632,8 +697,8 @@ BOOLAPI FtpRenameFileA(HINTERNET ,LPCSTR ,LPCSTR); BOOLAPI FtpRenameFileW(HINTERNET ,LPCWSTR ,LPCWSTR); #define FtpRenameFile WINELIB_NAME_AW(FtpRenameFile) -INTERNETAPI HINTERNET WINAPI FtpOpenFileA(HINTERNET ,LPCSTR ,DWORD ,DWORD ,DWORD); -INTERNETAPI HINTERNET WINAPI FtpOpenFileW(HINTERNET ,LPCWSTR ,DWORD ,DWORD ,DWORD); +INTERNETAPI HINTERNET WINAPI FtpOpenFileA(HINTERNET ,LPCSTR ,DWORD ,DWORD ,DWORD_PTR); +INTERNETAPI HINTERNET WINAPI FtpOpenFileW(HINTERNET ,LPCWSTR ,DWORD ,DWORD ,DWORD_PTR); #define FtpOpenFile WINELIB_NAME_AW(FtpOpenFile) BOOLAPI FtpCreateDirectoryA(HINTERNET ,LPCSTR); @@ -1002,24 +1067,24 @@ DECL_WINELIB_TYPE_AW(LPGOPHER_ATTRIBUTE_TYPE) #define GOPHER_ATTRIBUTE_ID_TREEWALK (GOPHER_ATTRIBUTE_ID_BASE + 24) #define GOPHER_ATTRIBUTE_ID_UNKNOWN (GOPHER_ATTRIBUTE_ID_BASE + 25) -BOOLAPI GopherCreateLocatorA(LPCSTR ,INTERNET_PORT ,LPCSTR lpszDisplayString , - LPCSTR lpszSelectorString ,DWORD ,LPSTR lpszLocator ,LPDWORD); -BOOLAPI GopherCreateLocatorW(LPCWSTR ,INTERNET_PORT ,LPCWSTR lpszDisplayString , - LPCWSTR lpszSelectorString ,DWORD ,LPWSTR lpszLocator ,LPDWORD); +BOOLAPI GopherCreateLocatorA(LPCSTR ,INTERNET_PORT ,LPCSTR , + LPCSTR ,DWORD ,LPSTR ,LPDWORD); +BOOLAPI GopherCreateLocatorW(LPCWSTR ,INTERNET_PORT ,LPCWSTR , + LPCWSTR ,DWORD ,LPWSTR ,LPDWORD); #define GopherCreateLocator WINELIB_NAME_AW(GopherCreateLocator) BOOLAPI GopherGetLocatorTypeA(LPCSTR ,LPDWORD); BOOLAPI GopherGetLocatorTypeW(LPCWSTR ,LPDWORD); #define GopherGetLocatorType WINELIB_NAME_AW(GopherGetLocatorType) -INTERNETAPI HINTERNET WINAPI GopherFindFirstFileA(HINTERNET ,LPCSTR lpszLocator , - LPCSTR lpszSearchString ,LPGOPHER_FIND_DATAA lpFindData ,DWORD ,DWORD); -INTERNETAPI HINTERNET WINAPI GopherFindFirstFileW(HINTERNET ,LPCWSTR lpszLocator , - LPCWSTR lpszSearchString ,LPGOPHER_FIND_DATAW lpFindData ,DWORD ,DWORD); +INTERNETAPI HINTERNET WINAPI GopherFindFirstFileA(HINTERNET ,LPCSTR , + LPCSTR ,LPGOPHER_FIND_DATAA ,DWORD ,DWORD_PTR); +INTERNETAPI HINTERNET WINAPI GopherFindFirstFileW(HINTERNET ,LPCWSTR , + LPCWSTR ,LPGOPHER_FIND_DATAW ,DWORD ,DWORD_PTR); #define GopherFindFirstFile WINELIB_NAME_AW(GopherFindFirstFile) -INTERNETAPI HINTERNET WINAPI GopherOpenFileA(HINTERNET ,LPCSTR ,LPCSTR lpszView ,DWORD ,DWORD); -INTERNETAPI HINTERNET WINAPI GopherOpenFileW(HINTERNET ,LPCWSTR ,LPCWSTR lpszView ,DWORD ,DWORD); +INTERNETAPI HINTERNET WINAPI GopherOpenFileA(HINTERNET ,LPCSTR ,LPCSTR ,DWORD ,DWORD_PTR); +INTERNETAPI HINTERNET WINAPI GopherOpenFileW(HINTERNET ,LPCWSTR ,LPCWSTR ,DWORD ,DWORD_PTR); #define GopherOpenFile WINELIB_NAME_AW(GopherOpenFile) typedef BOOL (CALLBACK *GOPHER_ATTRIBUTE_ENUMERATORA)(LPGOPHER_ATTRIBUTE_TYPEA ,DWORD); @@ -1027,10 +1092,10 @@ typedef BOOL (CALLBACK *GOPHER_ATTRIBUTE_ENUMERATORW)(LPGOPHER_ATTRIBUTE_TYPEW , DECL_WINELIB_TYPE_AW(GOPHER_ATTRIBUTE_ENUMERATOR) -BOOLAPI GopherGetAttributeA(HINTERNET ,LPCSTR ,LPCSTR lpszAttributeName ,LPBYTE , - DWORD ,LPDWORD ,GOPHER_ATTRIBUTE_ENUMERATORA lpfnEnumerator ,DWORD); -BOOLAPI GopherGetAttributeW(HINTERNET ,LPCWSTR ,LPCWSTR lpszAttributeName ,LPBYTE , - DWORD ,LPDWORD ,GOPHER_ATTRIBUTE_ENUMERATORW lpfnEnumerator ,DWORD); +BOOLAPI GopherGetAttributeA(HINTERNET ,LPCSTR ,LPCSTR ,LPBYTE , + DWORD ,LPDWORD ,GOPHER_ATTRIBUTE_ENUMERATORA ,DWORD_PTR); +BOOLAPI GopherGetAttributeW(HINTERNET ,LPCWSTR ,LPCWSTR ,LPBYTE , + DWORD ,LPDWORD ,GOPHER_ATTRIBUTE_ENUMERATORW ,DWORD_PTR); #define GopherGetAttribute WINELIB_NAME_AW(GopherGetAttribute) #define HTTP_MAJOR_VERSION 1 @@ -1171,9 +1236,9 @@ BOOLAPI GopherGetAttributeW(HINTERNET ,LPCWSTR ,LPCWSTR lpszAttributeName ,LPBYT INTERNETAPI HINTERNET WINAPI HttpOpenRequestA(HINTERNET ,LPCSTR ,LPCSTR ,LPCSTR , - LPCSTR lpszReferrer ,LPCSTR * ,DWORD ,DWORD); + LPCSTR ,LPCSTR * ,DWORD ,DWORD_PTR); INTERNETAPI HINTERNET WINAPI HttpOpenRequestW(HINTERNET ,LPCWSTR ,LPCWSTR ,LPCWSTR , - LPCWSTR lpszReferrer ,LPCWSTR * ,DWORD ,DWORD); + LPCWSTR ,LPCWSTR * ,DWORD ,DWORD_PTR); #define HttpOpenRequest WINELIB_NAME_AW(HttpOpenRequest) BOOLAPI HttpAddRequestHeadersA(HINTERNET ,LPCSTR ,DWORD ,DWORD); @@ -1189,14 +1254,14 @@ BOOLAPI HttpAddRequestHeadersW(HINTERNET ,LPCWSTR ,DWORD ,DWORD); #define HTTP_ADDREQ_FLAG_COALESCE HTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA #define HTTP_ADDREQ_FLAG_REPLACE 0x80000000 -BOOLAPI HttpSendRequestA(HINTERNET ,LPCSTR lpszHeaders ,DWORD ,LPVOID lpOptional ,DWORD); -BOOLAPI HttpSendRequestW(HINTERNET ,LPCWSTR lpszHeaders ,DWORD ,LPVOID lpOptional ,DWORD); +BOOLAPI HttpSendRequestA(HINTERNET ,LPCSTR ,DWORD ,LPVOID ,DWORD); +BOOLAPI HttpSendRequestW(HINTERNET ,LPCWSTR ,DWORD ,LPVOID ,DWORD); #define HttpSendRequest WINELIB_NAME_AW(HttpSendRequest) -INTERNETAPI BOOL WINAPI HttpSendRequestExA(HINTERNET ,LPINTERNET_BUFFERSA lpBuffersIn , - LPINTERNET_BUFFERSA lpBuffersOut ,DWORD ,DWORD); -INTERNETAPI BOOL WINAPI HttpSendRequestExW(HINTERNET ,LPINTERNET_BUFFERSW lpBuffersIn , - LPINTERNET_BUFFERSW lpBuffersOut ,DWORD ,DWORD); +INTERNETAPI BOOL WINAPI HttpSendRequestExA(HINTERNET ,LPINTERNET_BUFFERSA , + LPINTERNET_BUFFERSA ,DWORD ,DWORD_PTR); +INTERNETAPI BOOL WINAPI HttpSendRequestExW(HINTERNET ,LPINTERNET_BUFFERSW , + LPINTERNET_BUFFERSW ,DWORD ,DWORD_PTR); #define HttpSendRequestEx WINELIB_NAME_AW(HttpSendRequestEx) #define HSR_ASYNC WININET_API_FLAG_ASYNC @@ -1206,12 +1271,12 @@ INTERNETAPI BOOL WINAPI HttpSendRequestExW(HINTERNET ,LPINTERNET_BUFFERSW lpBuff #define HSR_DOWNLOAD 0x00000010 #define HSR_CHUNKED 0x00000020 -INTERNETAPI BOOL WINAPI HttpEndRequestA(HINTERNET ,LPINTERNET_BUFFERSA lpBuffersOut ,DWORD ,DWORD); -INTERNETAPI BOOL WINAPI HttpEndRequestW(HINTERNET ,LPINTERNET_BUFFERSW lpBuffersOut ,DWORD ,DWORD); +INTERNETAPI BOOL WINAPI HttpEndRequestA(HINTERNET ,LPINTERNET_BUFFERSA ,DWORD ,DWORD_PTR); +INTERNETAPI BOOL WINAPI HttpEndRequestW(HINTERNET ,LPINTERNET_BUFFERSW ,DWORD ,DWORD_PTR); #define HttpEndRequest WINELIB_NAME_AW(HttpEndRequest) -BOOLAPI HttpQueryInfoA(HINTERNET ,DWORD ,LPVOID lpBuffer ,LPDWORD ,LPDWORD lpdwIndex); -BOOLAPI HttpQueryInfoW(HINTERNET ,DWORD ,LPVOID lpBuffer ,LPDWORD ,LPDWORD lpdwIndex); +BOOLAPI HttpQueryInfoA(HINTERNET ,DWORD ,LPVOID ,LPDWORD ,LPDWORD); +BOOLAPI HttpQueryInfoW(HINTERNET ,DWORD ,LPVOID ,LPDWORD ,LPDWORD); #define HttpQueryInfo WINELIB_NAME_AW(HttpQueryInfo) BOOLAPI InternetClearAllPerSiteCookieDecisions(VOID); @@ -1220,6 +1285,17 @@ BOOLAPI InternetEnumPerSiteCookieDecisionA(LPSTR,unsigned long *,unsigned long * BOOLAPI InternetEnumPerSiteCookieDecisionW(LPWSTR,unsigned long *,unsigned long *,unsigned long); #define InternetEnumPerSiteCookieDecision WINELIB_NAME_AW(InternetEnumPerSiteCookieDecision) +#define INTERNET_COOKIE_IS_SECURE 0x00000001 +#define INTERNET_COOKIE_IS_SESSION 0x00000002 +#define INTERNET_COOKIE_THIRD_PARTY 0x00000010 +#define INTERNET_COOKIE_PROMPT_REQUIRED 0x00000020 +#define INTERNET_COOKIE_EVALUATE_P3P 0x00000040 +#define INTERNET_COOKIE_APPLY_P3P 0x00000080 +#define INTERNET_COOKIE_P3P_ENABLED 0x00000100 +#define INTERNET_COOKIE_IS_RESTRICTED 0x00000200 +#define INTERNET_COOKIE_IE6 0x00000400 +#define INTERNET_COOKIE_IS_LEGACY 0x00000800 + BOOLAPI InternetGetCookieExA(LPCSTR,LPCSTR,LPSTR,LPDWORD,DWORD,LPVOID); BOOLAPI InternetGetCookieExW(LPCWSTR,LPCWSTR,LPWSTR,LPDWORD,DWORD,LPVOID); #define InternetGetCookieEx WINELIB_NAME_AW(InternetGetCookieEx) @@ -1257,15 +1333,15 @@ BOOLAPI InternetCheckConnectionW(LPCWSTR ,DWORD ,DWORD); #define FLAGS_ERROR_UI_FLAGS_NO_UI 0x08 #define FLAGS_ERROR_UI_SERIALIZE_DIALOGS 0x10 -DWORD InternetAuthNotifyCallback ( DWORD ,DWORD ,LPVOID ); -typedef DWORD (CALLBACK *PFN_AUTH_NOTIFY) (DWORD,DWORD,LPVOID); +DWORD InternetAuthNotifyCallback ( DWORD_PTR ,DWORD ,LPVOID ); +typedef DWORD (CALLBACK *PFN_AUTH_NOTIFY) (DWORD_PTR,DWORD,LPVOID); typedef struct { DWORD cbStruct; DWORD dwOptions; PFN_AUTH_NOTIFY pfnNotify; - DWORD dwContext; + DWORD_PTR dwContext; } INTERNET_AUTH_NOTIFY_DATA; @@ -1328,6 +1404,9 @@ INTERNETAPI DWORD WINAPI InternetConfirmZoneCrossingW(HWND ,LPWSTR ,LPWSTR ,BOOL #define ERROR_INTERNET_RETRY_DIALOG (INTERNET_ERROR_BASE + 50) #define ERROR_INTERNET_HTTPS_HTTP_SUBMIT_REDIR (INTERNET_ERROR_BASE + 52) #define ERROR_INTERNET_INSERT_CDROM (INTERNET_ERROR_BASE + 53) +#define ERROR_INTERNET_SEC_CERT_ERRORS (INTERNET_ERROR_BASE + 55) +#define ERROR_INTERNET_SEC_CERT_NO_REV (INTERNET_ERROR_BASE + 56) +#define ERROR_INTERNET_SEC_CERT_REV_FAILED (INTERNET_ERROR_BASE + 57) #define ERROR_FTP_TRANSFER_IN_PROGRESS (INTERNET_ERROR_BASE + 110) #define ERROR_FTP_DROPPED (INTERNET_ERROR_BASE + 111) #define ERROR_FTP_NO_PASSIVE_MODE (INTERNET_ERROR_BASE + 112) @@ -1362,16 +1441,17 @@ INTERNETAPI DWORD WINAPI InternetConfirmZoneCrossingW(HWND ,LPWSTR ,LPWSTR ,BOOL #define ERROR_INTERNET_SEC_INVALID_CERT (INTERNET_ERROR_BASE + 169) #define ERROR_INTERNET_SEC_CERT_REVOKED (INTERNET_ERROR_BASE + 170) #define ERROR_INTERNET_FAILED_DUETOSECURITYCHECK (INTERNET_ERROR_BASE + 171) -#define ERROR_INTERNET_NOT_INITIALIZED (INTERNET_ERROR_BASE + 172) +#define ERROR_INTERNET_NOT_INITIALIZED (INTERNET_ERROR_BASE + 172) #define INTERNET_ERROR_LAST ERROR_INTERNET_NOT_INITIALIZED #define NORMAL_CACHE_ENTRY 0x00000001 +#define STICKY_CACHE_ENTRY 0x00000004 +#define EDITED_CACHE_ENTRY 0x00000008 #define COOKIE_CACHE_ENTRY 0x00100000 #define URLHISTORY_CACHE_ENTRY 0x00200000 #define TRACK_OFFLINE_CACHE_ENTRY 0x00000010 #define TRACK_ONLINE_CACHE_ENTRY 0x00000020 -#define STICKY_CACHE_ENTRY 0x00000004 #define SPARSE_CACHE_ENTRY 0x00010000 #define URLCACHE_FIND_DEFAULT_FILTER NORMAL_CACHE_ENTRY \ @@ -1528,14 +1608,14 @@ BOOLAPI DeleteUrlCacheEntryA(LPCSTR); BOOLAPI DeleteUrlCacheEntryW(LPCWSTR); #define DeleteUrlCacheEntry WINELIB_NAME_AW(DeleteUrlCacheEntry) -INTERNETAPI DWORD WINAPI InternetDialA(HWND ,LPSTR ,DWORD ,LPDWORD ,DWORD); -INTERNETAPI DWORD WINAPI InternetDialW(HWND ,LPWSTR ,DWORD ,LPDWORD ,DWORD); +INTERNETAPI DWORD WINAPI InternetDialA(HWND ,LPSTR ,DWORD ,DWORD_PTR* ,DWORD); +INTERNETAPI DWORD WINAPI InternetDialW(HWND ,LPWSTR ,DWORD ,DWORD_PTR* ,DWORD); #define InternetDial WINELIB_NAME_AW(InternetDial) #define INTERNET_DIAL_UNATTENDED 0x8000 -INTERNETAPI DWORD WINAPI InternetHangUp(DWORD ,DWORD); +INTERNETAPI DWORD WINAPI InternetHangUp(DWORD_PTR ,DWORD); BOOLAPI CreateMD5SSOHash(PWSTR,PWSTR,PWSTR,PBYTE); #define INTERENT_GOONLINE_REFRESH 0x00000001 @@ -1573,9 +1653,12 @@ INTERNETAPI BOOL WINAPI InternetSetDialStateW(LPCWSTR ,DWORD ,DWORD); #define InternetSetDialState WINELIB_NAME_AW(InternetSetDialState) #define INTERNET_DIALSTATE_DISCONNECTED 1 -BOOLAPI InternetCheckConnectionA(LPCSTR lpszUrl,DWORD dwFlags,DWORD dwReserved); -BOOLAPI InternetCheckConnectionW(LPCWSTR lpszUrl,DWORD dwFlags,DWORD dwReserved); -#define InternetCheckConnection WINELIB_NAME_AW(InternetCheckConnection) +BOOL WINAPI InternetGetConnectedStateExA(LPDWORD, LPSTR, DWORD, DWORD); +BOOL WINAPI InternetGetConnectedStateExW(LPDWORD, LPWSTR, DWORD, DWORD); +#define InternetGetConnectedStateEx WINELIB_NAME_AW(InternetGetConnectedStateEx) + +BOOL WINAPI InternetInitializeAutoProxyDll(DWORD); +BOOL WINAPI DetectAutoProxyUrl(LPSTR, DWORD, DWORD); #ifdef __cplusplus }